diff --git a/src/common/backend/parser/LIST.TXT b/src/common/backend/parser/LIST.TXT new file mode 100644 index 000000000..351695bb8 --- /dev/null +++ b/src/common/backend/parser/LIST.TXT @@ -0,0 +1,33 @@ +analyze.cpp +CMakeLists.txt +gram.xml +gram.y +hint_gram.y +hint_scan.l +keywords.cpp +kwlookup.cpp +LIST.TXT +Makefile +parser.cpp +parse_agg.cpp +parse_clause.cpp +parse_coerce.cpp +parse_collate.cpp +parse_compatibility.cpp +parse_cte.cpp +parse_expr.cpp +parse_func.cpp +parse_hint.cpp +parse_merge.cpp +parse_node.cpp +parse_oper.cpp +parse_param.cpp +parse_relation.cpp +parse_startwith.cpp +parse_target.cpp +parse_type.cpp +parse_utilcmd.cpp +README +scan.l +scansup.cpp +新建文本文档.bat diff --git a/src/common/backend/parser/鏂板缓鏂囨湰鏂囨。.bat b/src/common/backend/parser/鏂板缓鏂囨湰鏂囨。.bat new file mode 100644 index 000000000..d055abd11 --- /dev/null +++ b/src/common/backend/parser/鏂板缓鏂囨湰鏂囨。.bat @@ -0,0 +1 @@ +DIR *.* /B >LIST.TXT \ No newline at end of file diff --git a/src/common/backend/utils/init/miscinit.cpp b/src/common/backend/utils/init/miscinit.cpp index 8664009a8..843a952fd 100644 --- a/src/common/backend/utils/init/miscinit.cpp +++ b/src/common/backend/utils/init/miscinit.cpp @@ -65,7 +65,7 @@ #ifdef ENABLE_MULTIPLE_NODES #include "tsdb/compaction/compaction_entry.h" -#endif /* ENABLE_MULTIPLE_NODES */ +#endif /* ENABLE_MULTIPLE_NODES */ #include "access/ustore/knl_undoworker.h" #define DIRECTORY_LOCK_FILE "postmaster.pid" @@ -84,47 +84,31 @@ Alarm alarmItemTooManyDbUserConn[1] = {ALM_AI_Unknown, ALM_AS_Normal, 0, 0, 0, 0 * ---------------------------------------------------------------- */ -void ReportAlarmTooManyDbUserConn(const char* roleName) +void ReportAlarmTooManyDbUserConn(const char *roleName) { AlarmAdditionalParam tempAdditionalParam; // Initialize the alarm item - AlarmItemInitialize(alarmItemTooManyDbUserConn, - ALM_AI_TooManyDbUserConn, - alarmItemTooManyDbUserConn->stat, - NULL, - alarmItemTooManyDbUserConn->lastReportTime, - alarmItemTooManyDbUserConn->reportCount); + AlarmItemInitialize(alarmItemTooManyDbUserConn, ALM_AI_TooManyDbUserConn, alarmItemTooManyDbUserConn->stat, NULL, + alarmItemTooManyDbUserConn->lastReportTime, alarmItemTooManyDbUserConn->reportCount); // fill the alarm message - WriteAlarmAdditionalInfo(&tempAdditionalParam, - g_instance.attr.attr_common.PGXCNodeName, - "AllDatabases", - const_cast(roleName), - alarmItemTooManyDbUserConn, - ALM_AT_Fault, - const_cast(roleName)); + WriteAlarmAdditionalInfo(&tempAdditionalParam, g_instance.attr.attr_common.PGXCNodeName, "AllDatabases", + const_cast(roleName), alarmItemTooManyDbUserConn, ALM_AT_Fault, + const_cast(roleName)); // report the alarm AlarmReporter(alarmItemTooManyDbUserConn, ALM_AT_Fault, &tempAdditionalParam); } -void ReportResumeTooManyDbUserConn(const char* roleName) +void ReportResumeTooManyDbUserConn(const char *roleName) { AlarmAdditionalParam tempAdditionalParam; // Initialize the alarm item - AlarmItemInitialize(alarmItemTooManyDbUserConn, - ALM_AI_TooManyDbUserConn, - alarmItemTooManyDbUserConn->stat, - NULL, - alarmItemTooManyDbUserConn->lastReportTime, - alarmItemTooManyDbUserConn->reportCount); + AlarmItemInitialize(alarmItemTooManyDbUserConn, ALM_AI_TooManyDbUserConn, alarmItemTooManyDbUserConn->stat, NULL, + alarmItemTooManyDbUserConn->lastReportTime, alarmItemTooManyDbUserConn->reportCount); // fill the resume message - WriteAlarmAdditionalInfo(&tempAdditionalParam, - g_instance.attr.attr_common.PGXCNodeName, - "AllDatabases", - const_cast(roleName), - alarmItemTooManyDbUserConn, - ALM_AT_Resume); + WriteAlarmAdditionalInfo(&tempAdditionalParam, g_instance.attr.attr_common.PGXCNodeName, "AllDatabases", + const_cast(roleName), alarmItemTooManyDbUserConn, ALM_AT_Resume); // report the alarm AlarmReporter(alarmItemTooManyDbUserConn, ALM_AT_Resume, &tempAdditionalParam); } @@ -137,13 +121,8 @@ void ReportAlarmDataInstLockFileExist() // Initialize the alarm item AlarmItemInitialize(alarmItem, ALM_AI_DataInstLockFileExist, ALM_AS_Reported, NULL); // fill the alarm message - WriteAlarmAdditionalInfo(&tempAdditionalParam, - g_instance.attr.attr_common.PGXCNodeName, - "", - "", - alarmItem, - ALM_AT_Fault, - g_instance.attr.attr_common.PGXCNodeName); + WriteAlarmAdditionalInfo(&tempAdditionalParam, g_instance.attr.attr_common.PGXCNodeName, "", "", alarmItem, + ALM_AT_Fault, g_instance.attr.attr_common.PGXCNodeName); // report the alarm AlarmReporter(alarmItem, ALM_AT_Fault, &tempAdditionalParam); } @@ -156,8 +135,8 @@ void ReportResumeDataInstLockFileExist() // Initialize the alarm item AlarmItemInitialize(alarmItem, ALM_AI_DataInstLockFileExist, ALM_AS_Normal, NULL); // fill the alarm message - WriteAlarmAdditionalInfo( - &tempAdditionalParam, g_instance.attr.attr_common.PGXCNodeName, "", "", alarmItem, ALM_AT_Resume); + WriteAlarmAdditionalInfo(&tempAdditionalParam, g_instance.attr.attr_common.PGXCNodeName, "", "", alarmItem, + ALM_AT_Resume); // report the alarm AlarmReporter(alarmItem, ALM_AT_Resume, &tempAdditionalParam); } @@ -167,29 +146,28 @@ void ReportResumeDataInstLockFileExist() * ---------------------------------------------------------------- */ -void SetDatabasePath(const char* path) +void SetDatabasePath(const char *path) { /* This should happen only once per process */ Assert(!u_sess->proc_cxt.DatabasePath); - u_sess->proc_cxt.DatabasePath = - MemoryContextStrdup(SESS_GET_MEM_CXT_GROUP(MEMORY_CONTEXT_EXECUTOR), path); + u_sess->proc_cxt.DatabasePath = MemoryContextStrdup(SESS_GET_MEM_CXT_GROUP(MEMORY_CONTEXT_EXECUTOR), path); } /* * Set data directory, but make sure it's an absolute path. Use this, * never set t_thrd.proc_cxt.DataDir directly. */ -void SetDataDir(const char* dir) +void SetDataDir(const char *dir) { AssertArg(dir); /* If presented path is relative, convert to absolute */ - char* newm = make_absolute_path(dir); + char *newm = make_absolute_path(dir); char real_newm[PATH_MAX + 1] = {'\0'}; - char* DataDir = (char*)MemoryContextAlloc(SESS_GET_MEM_CXT_GROUP(MEMORY_CONTEXT_EXECUTOR), MAXPGPATH); + char *DataDir = (char *)MemoryContextAlloc(SESS_GET_MEM_CXT_GROUP(MEMORY_CONTEXT_EXECUTOR), MAXPGPATH); if (realpath(newm, real_newm) == NULL) { - ereport(ERROR, (errcode(ERRCODE_FILE_READ_FAILED),errmsg("invalid path:%s", dir))); + ereport(ERROR, (errcode(ERRCODE_FILE_READ_FAILED), errmsg("invalid path:%s", dir))); } errno_t rc = strncpy_s(DataDir, MAXPGPATH, real_newm, MAXPGPATH - 1); securec_check(rc, "\0", "\0"); @@ -217,8 +195,8 @@ void ChangeToDataDir(void) AssertState(t_thrd.proc_cxt.DataDir); if (chdir(t_thrd.proc_cxt.DataDir) < 0) - ereport(FATAL, - (errcode_for_file_access(), errmsg("could not change directory to \"%s\": %m", t_thrd.proc_cxt.DataDir))); + ereport(FATAL, (errcode_for_file_access(), + errmsg("could not change directory to \"%s\": %m", t_thrd.proc_cxt.DataDir))); } /* @@ -231,9 +209,9 @@ void ChangeToDataDir(void) * should happen before doing ChangeToDataDir(), else the user will probably * not like the results. */ -char* make_absolute_path(const char* path) +char *make_absolute_path(const char *path) { - char* newm = NULL; + char *newm = NULL; size_t tmplen; /* Returning null for null input is convenient for some callers */ @@ -242,16 +220,16 @@ char* make_absolute_path(const char* path) } if (!is_absolute_path(path)) { - char* buf = NULL; + char *buf = NULL; size_t buflen; buflen = MAXPGPATH; for (;;) { #ifdef FRONTEND - buf = (char*)malloc(buflen); + buf = (char *)malloc(buflen); #else - buf = (char*)MemoryContextAlloc(SESS_GET_MEM_CXT_GROUP(MEMORY_CONTEXT_EXECUTOR), buflen); + buf = (char *)MemoryContextAlloc(SESS_GET_MEM_CXT_GROUP(MEMORY_CONTEXT_EXECUTOR), buflen); #endif if (buf == NULL) @@ -259,8 +237,7 @@ char* make_absolute_path(const char* path) if (getcwd(buf, buflen) != NULL) { break; - } - else if (errno == ERANGE) { + } else if (errno == ERANGE) { #ifdef FRONTEND free(buf); #else @@ -280,9 +257,9 @@ char* make_absolute_path(const char* path) tmplen = strlen(buf) + strlen(path) + 2; #ifdef FRONTEND - newm = (char*)malloc(tmplen); + newm = (char *)malloc(tmplen); #else - newm = (char*)MemoryContextAlloc(SESS_GET_MEM_CXT_GROUP(MEMORY_CONTEXT_EXECUTOR), tmplen); + newm = (char *)MemoryContextAlloc(SESS_GET_MEM_CXT_GROUP(MEMORY_CONTEXT_EXECUTOR), tmplen); #endif if (newm == NULL) @@ -321,12 +298,16 @@ Oid GetAuthenticatedUserId(void) * * Note: there's no SetUserId() anymore; use SetUserIdAndSecContext(). */ +/* + *鍔熻兘锛 杩欎釜鍑芥暟鐢ㄤ簬鑾峰彇褰撳墠浼氳瘽鐨勭敤鎴锋爣璇嗙锛圤id锛夛紝浠ヤ究鍦ㄦ暟鎹簱鎿嶄綔涓爣璇嗗綋鍓嶇敤鎴风殑韬唤銆 + */ Oid GetUserId(void) { + // 妫鏌ュ綋鍓嶇敤鎴锋爣璇嗙鏄惁鏈夋晥 if (!OidIsValid(u_sess->misc_cxt.CurrentUserId)) { - ereport(ERROR, (errcode(ERRCODE_INTERNAL_ERROR), - errmsg("Current user id is invalid. Please try later."))); + ereport(ERROR, (errcode(ERRCODE_INTERNAL_ERROR), errmsg("Current user id is invalid. Please try later."))); } + // 杩斿洖褰撳墠鐢ㄦ埛鏍囪瘑绗 return u_sess->misc_cxt.CurrentUserId; } @@ -438,7 +419,7 @@ bool exist_logic_cluster() * show_nodegroup_mode - return node group mode as sting. * The function is only used in guc.cpp. */ -const char* show_nodegroup_mode(void) +const char *show_nodegroup_mode(void) { modify_nodegroup_mode(); @@ -484,7 +465,7 @@ const int GetCustomParserId() * get_current_lcgroup_name - get current logic group name. * The function return NULL in datanode because datanode don't see pgxc_group. */ -const char* get_current_lcgroup_name() +const char *get_current_lcgroup_name() { if (IS_PGXC_COORDINATOR && u_sess->attr.attr_common.current_logic_cluster_name == NULL && OidIsValid(u_sess->misc_cxt.current_logic_cluster) && t_thrd.proc_cxt.postgres_initialized) { @@ -493,8 +474,8 @@ const char* get_current_lcgroup_name() if (HeapTupleIsValid(groupTup)) { rform = (Form_pgxc_group)GETSTRUCT(groupTup); - u_sess->attr.attr_common.current_logic_cluster_name = MemoryContextStrdup( - SESS_GET_MEM_CXT_GROUP(MEMORY_CONTEXT_EXECUTOR), NameStr(rform->group_name)); + u_sess->attr.attr_common.current_logic_cluster_name = + MemoryContextStrdup(SESS_GET_MEM_CXT_GROUP(MEMORY_CONTEXT_EXECUTOR), NameStr(rform->group_name)); ReleaseSysCache(groupTup); } } @@ -521,9 +502,9 @@ static void set_current_lcgroup_oid(Oid group_oid) * show_show_lcgroup_name - show current logic group name. * The function is only used in guc.cpp. */ -const char* show_lcgroup_name() +const char *show_lcgroup_name() { - const char* name = get_current_lcgroup_name(); + const char *name = get_current_lcgroup_name(); return (name == NULL) ? "" : name; } @@ -614,7 +595,7 @@ Oid get_pgxc_logic_groupoid(Oid roleid) * Obtain PGXC Logic Group Oid for rolename * Return Invalid Oid if group does not exist */ -Oid get_pgxc_logic_groupoid(const char* rolename) +Oid get_pgxc_logic_groupoid(const char *rolename) { bool isNull = false; Datum aclDatum; @@ -693,7 +674,7 @@ static void RegisterNodeGroupCacheCallback() * and perhaps restored is indeed invalid. We have to be able to get * through AbortTransaction without asserting in case InitPostgres fails. */ -void GetUserIdAndSecContext(Oid* userid, int* sec_context) +void GetUserIdAndSecContext(Oid *userid, int *sec_context) { *userid = u_sess->misc_cxt.CurrentUserId; *sec_context = u_sess->misc_cxt.SecurityRestrictionContext; @@ -727,7 +708,7 @@ bool InSecurityRestrictedOperation(void) * pljava. We allow the userid to be set, but only when not inside a * security restriction context. */ -void GetUserIdAndContext(Oid* userid, bool* sec_def_context) +void GetUserIdAndContext(Oid *userid, bool *sec_def_context) { *userid = u_sess->misc_cxt.CurrentUserId; *sec_def_context = InLocalUserIdChange(); @@ -737,9 +718,8 @@ void SetUserIdAndContext(Oid userid, bool sec_def_context) { /* We throw the same error SET ROLE would. */ if (InSecurityRestrictedOperation()) - ereport(ERROR, - (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), - errmsg("cannot set parameter \"%s\" within security-restricted operation", "role"))); + ereport(ERROR, (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), + errmsg("cannot set parameter \"%s\" within security-restricted operation", "role"))); u_sess->misc_cxt.CurrentUserId = userid; @@ -800,7 +780,7 @@ static void DecreaseUserCountReuse(Oid roleid, bool ispoolerreuse) /* * Initialize user identity during normal backend startup */ -void InitializeSessionUserId(const char* rolename, bool ispoolerreuse, Oid useroid) +void InitializeSessionUserId(const char *rolename, bool ispoolerreuse, Oid useroid) { HeapTuple roleTup; Form_pg_authid rform; @@ -813,8 +793,7 @@ void InitializeSessionUserId(const char* rolename, bool ispoolerreuse, Oid usero * exist yet, and they should be owned by openGauss anyway. */ if (IsBootstrapProcessingMode()) { - ereport( - ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("IsBootstrapProcessingMode"))); + ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("IsBootstrapProcessingMode"))); } /* In pooler stateless reuse mode, to reset session userid */ @@ -824,10 +803,10 @@ void InitializeSessionUserId(const char* rolename, bool ispoolerreuse, Oid usero if (!isUserOidInvalid) { AssertState(false); ereport(FATAL, - (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("Abnormal process. UserOid has been reseted. Current userOid[%u], reset username is %s," - "useroid is %u", - u_sess->misc_cxt.AuthenticatedUserId, rolename, useroid))); + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("Abnormal process. UserOid has been reseted. Current userOid[%u], reset username is %s," + "useroid is %u", + u_sess->misc_cxt.AuthenticatedUserId, rolename, useroid))); } } @@ -850,7 +829,7 @@ void InitializeSessionUserId(const char* rolename, bool ispoolerreuse, Oid usero oldcontext = MemoryContextSwitchTo(SESS_GET_MEM_CXT_GROUP(MEMORY_CONTEXT_EXECUTOR)); if (u_sess->proc_cxt.MyProcPort->user_name) pfree_ext(u_sess->proc_cxt.MyProcPort->user_name); - u_sess->proc_cxt.MyProcPort->user_name = pstrdup((char*)GetSuperUserName((char*)userName)); + u_sess->proc_cxt.MyProcPort->user_name = pstrdup((char *)GetSuperUserName((char *)userName)); (void)MemoryContextSwitchTo(oldcontext); rolename = u_sess->proc_cxt.MyProcPort->user_name; } @@ -863,23 +842,20 @@ void InitializeSessionUserId(const char* rolename, bool ispoolerreuse, Oid usero securec_check_ss(rc, "", ""); rolename = roleIdStr; } - /* - * Audit user login - * it's unsafe to deal with plugins hooks as dynamic lib may be released + /* + * Audit user login + * it's unsafe to deal with plugins hooks as dynamic lib may be released */ if (!(g_instance.status > NoShutdown) && user_login_hook) { user_login_hook(u_sess->proc_cxt.MyProcPort->database_name, rolename, false, true); } - int rcs = snprintf_truncated_s(details, - sizeof(details), - "login db(%s) failed-the role(%s)does not exist", - u_sess->proc_cxt.MyProcPort->database_name, - rolename); + int rcs = snprintf_truncated_s(details, sizeof(details), "login db(%s) failed-the role(%s)does not exist", + u_sess->proc_cxt.MyProcPort->database_name, rolename); securec_check_ss(rcs, "\0", "\0"); pgaudit_user_login(FALSE, u_sess->proc_cxt.MyProcPort->database_name, details); - ereport(FATAL, - (errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION), errmsg("Invalid username/password,login denied."))); + ereport(FATAL, (errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION), + errmsg("Invalid username/password,login denied."))); } rform = (Form_pg_authid)GETSTRUCT(roleTup); @@ -925,9 +901,8 @@ void InitializeSessionUserId(const char* rolename, bool ispoolerreuse, Oid usero } if (!rform->rolcanlogin) - ereport(FATAL, - (errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION), - errmsg("role \"%s\" is not permitted to login", rolename))); + ereport(FATAL, (errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION), + errmsg("role \"%s\" is not permitted to login", rolename))); /* * Check connection limit for this role. @@ -943,7 +918,7 @@ void InitializeSessionUserId(const char* rolename, bool ispoolerreuse, Oid usero CountUserBackends(roleid) > rform->rolconnlimit) { ReportAlarmTooManyDbUserConn(rolename); ereport(FATAL, - (errcode(ERRCODE_TOO_MANY_CONNECTIONS), errmsg("too many connections for role \"%s\"", rolename))); + (errcode(ERRCODE_TOO_MANY_CONNECTIONS), errmsg("too many connections for role \"%s\"", rolename))); } else if (!u_sess->misc_cxt.AuthenticatedUserIsSuperuser) { ReportResumeTooManyDbUserConn(rolename); } @@ -951,8 +926,8 @@ void InitializeSessionUserId(const char* rolename, bool ispoolerreuse, Oid usero /* Record username and superuser status as GUC settings too */ SetConfigOption("session_authorization", rolename, PGC_BACKEND, PGC_S_OVERRIDE); - SetConfigOption( - "is_sysadmin", u_sess->misc_cxt.AuthenticatedUserIsSuperuser ? "on" : "off", PGC_INTERNAL, PGC_S_OVERRIDE); + SetConfigOption("is_sysadmin", u_sess->misc_cxt.AuthenticatedUserIsSuperuser ? "on" : "off", PGC_INTERNAL, + PGC_S_OVERRIDE); ReleaseSysCache(roleTup); } @@ -968,14 +943,15 @@ void InitializeSessionUserIdStandalone(void) */ #ifdef ENABLE_MULTIPLE_NODES AssertState(!IsUnderPostmaster || IsAutoVacuumWorkerProcess() || IsJobSchedulerProcess() || IsJobWorkerProcess() || - AM_WAL_SENDER || IsTxnSnapCapturerProcess() || IsTxnSnapWorkerProcess() || IsUndoWorkerProcess() || - CompactionProcess::IsTsCompactionProcess() || IsRbCleanerProcess() || IsRbWorkerProcess() || - t_thrd.role == PARALLEL_DECODE || t_thrd.role == LOGICAL_READ_RECORD); -#else /* ENABLE_MULTIPLE_NODES */ + AM_WAL_SENDER || IsTxnSnapCapturerProcess() || IsTxnSnapWorkerProcess() || IsUndoWorkerProcess() || + CompactionProcess::IsTsCompactionProcess() || IsRbCleanerProcess() || IsRbWorkerProcess() || + t_thrd.role == PARALLEL_DECODE || t_thrd.role == LOGICAL_READ_RECORD); +#else /* ENABLE_MULTIPLE_NODES */ AssertState(!IsUnderPostmaster || IsAutoVacuumWorkerProcess() || IsJobSchedulerProcess() || IsJobWorkerProcess() || - AM_WAL_SENDER || IsTxnSnapCapturerProcess() || IsTxnSnapWorkerProcess() || IsUndoWorkerProcess() || IsRbCleanerProcess() || - IsRbWorkerProcess() || t_thrd.role == PARALLEL_DECODE || t_thrd.role == LOGICAL_READ_RECORD); -#endif /* ENABLE_MULTIPLE_NODES */ + AM_WAL_SENDER || IsTxnSnapCapturerProcess() || IsTxnSnapWorkerProcess() || IsUndoWorkerProcess() || + IsRbCleanerProcess() || IsRbWorkerProcess() || t_thrd.role == PARALLEL_DECODE || + t_thrd.role == LOGICAL_READ_RECORD); +#endif /* ENABLE_MULTIPLE_NODES */ /* In pooler stateless reuse mode, to reset session userid */ if (!ENABLE_STATELESS_REUSE) { @@ -1011,8 +987,8 @@ void SetSessionAuthorization(Oid userid, bool is_superuser) if (!t_thrd.xact_cxt.bInAbortTransaction && userid != u_sess->misc_cxt.AuthenticatedUserId && !u_sess->misc_cxt.AuthenticatedUserIsSuperuser && !superuser()) - ereport( - ERROR, (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), errmsg("permission denied to set session authorization"))); + ereport(ERROR, + (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), errmsg("permission denied to set session authorization"))); SetSessionUserId(userid, is_superuser); @@ -1077,10 +1053,10 @@ void SetCurrentRoleId(Oid roleid, bool is_superuser) /* * Get user name from user oid */ -char* GetUserNameFromId(Oid roleid) +char *GetUserNameFromId(Oid roleid) { HeapTuple tuple; - char* result = NULL; + char *result = NULL; tuple = SearchSysCache1(AUTHOID, ObjectIdGetDatum(roleid)); @@ -1093,10 +1069,10 @@ char* GetUserNameFromId(Oid roleid) return result; } -char* GetUserNameById(Oid roleid) +char *GetUserNameById(Oid roleid) { HeapTuple tuple; - char* result = NULL; + char *result = NULL; tuple = SearchSysCache1(AUTHOID, ObjectIdGetDatum(roleid)); @@ -1109,7 +1085,6 @@ char* GetUserNameById(Oid roleid) return result; } - /* ------------------------------------------------------------------------- * Interlock-file support * @@ -1130,7 +1105,7 @@ char* GetUserNameById(Oid roleid) */ static void UnlinkLockFile(int status, Datum filename) { - char* fname = (char*)DatumGetPointer(filename); + char *fname = (char *)DatumGetPointer(filename); if (fname != NULL) { if (unlink(fname) != 0) { @@ -1154,7 +1129,7 @@ static void UnLockPidLockFile(int status, Datum fileDes) } } -static void CreatePidLockFile(const char* filename) +static void CreatePidLockFile(const char *filename) { int fd = -1; char pid_lock_file[MAXPGPATH] = {0}; @@ -1162,7 +1137,8 @@ static void CreatePidLockFile(const char* filename) securec_check_ss(rc, "", ""); if ((fd = open(pid_lock_file, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR)) == -1) { - ereport(FATAL, (errcode_for_file_access(), errmsg("could not create or open lock file \"%s\": %m", pid_lock_file))); + ereport(FATAL, + (errcode_for_file_access(), errmsg("could not create or open lock file \"%s\": %m", pid_lock_file))); } if (flock(fd, LOCK_EX | LOCK_NB) == -1) { @@ -1180,7 +1156,7 @@ static void CreatePidLockFile(const char* filename) * amPostmaster is used to determine how to encode the output PID. * isDDLock and refName are used to determine what error message to produce. */ -static void CreateLockFile(const char* filename, bool amPostmaster, bool isDDLock, const char* refName) +static void CreateLockFile(const char *filename, bool amPostmaster, bool isDDLock, const char *refName) { int fd = -1; char buffer[MAXPGPATH * 2 + 256]; @@ -1189,7 +1165,7 @@ static void CreateLockFile(const char* filename, bool amPostmaster, bool isDDLoc int encoded_pid; pid_t other_pid; pid_t my_pid, my_p_pid, my_gp_pid; - const char* envvar = NULL; + const char *envvar = NULL; /* Grab a file lock to establish our priority to process postmaster.pid */ if (isDDLock) { @@ -1290,18 +1266,15 @@ static void CreateLockFile(const char* filename, bool amPostmaster, bool isDDLoc if (lstat(filename, &filenameStat) >= 0) { if (0 == filenameStat.st_size) { if (remove(filename) < 0) - ereport(FATAL, - (errcode_for_file_access(), - errmsg("bogus lock file \"%s\",could not unlink it : %m", filename))); + ereport(FATAL, (errcode_for_file_access(), + errmsg("bogus lock file \"%s\",could not unlink it : %m", filename))); continue; } } - ereport(FATAL, - (errmsg("bogus data in lock file \"%s\": \"%s\", please kill the " - "instance process, than remove the damaged lock file", - filename, - buffer))); + ereport(FATAL, (errmsg("bogus data in lock file \"%s\": \"%s\", please kill the " + "instance process, than remove the damaged lock file", + filename, buffer))); } /* @@ -1338,24 +1311,20 @@ static void CreateLockFile(const char* filename, bool amPostmaster, bool isDDLoc { ReportAlarmDataInstLockFileExist(); - ereport(FATAL, - (errcode(ERRCODE_LOCK_FILE_EXISTS), - errmsg("lock file \"%s\" already exists", filename), - isDDLock - ? ((encoded_pid < 0) - ? errhint("Is another openGauss (PID %d) running in data directory \"%s\"?", - (int)other_pid, - refName) - : errhint("Is another postmaster (PID %d) running in data directory \"%s\"?", - (int)other_pid, - refName)) - : ((encoded_pid < 0) ? errhint("Is another openGauss (PID %d) \ + ereport( + FATAL, + (errcode(ERRCODE_LOCK_FILE_EXISTS), errmsg("lock file \"%s\" already exists", filename), + isDDLock + ? ((encoded_pid < 0) + ? errhint("Is another openGauss (PID %d) running in data directory \"%s\"?", + (int)other_pid, refName) + : errhint("Is another postmaster (PID %d) running in data directory \"%s\"?", + (int)other_pid, refName)) + : ((encoded_pid < 0) ? errhint("Is another openGauss (PID %d) \ using socket file \"%s\"?", - (int)other_pid, - refName) - : errhint("Is another postmaster (PID %d) using socket file \"%s\"?", - (int)other_pid, - refName)))); + (int)other_pid, refName) + : errhint("Is another postmaster (PID %d) using socket file \"%s\"?", + (int)other_pid, refName)))); } } } @@ -1372,7 +1341,7 @@ static void CreateLockFile(const char* filename, bool amPostmaster, bool isDDLoc * error. */ if (isDDLock != false) { - char* ptr = buffer; + char *ptr = buffer; unsigned long id1, id2; int lineno; @@ -1385,17 +1354,15 @@ static void CreateLockFile(const char* filename, bool amPostmaster, bool isDDLoc if (ptr != NULL && sscanf_s(ptr, "%lu %lu", &id1, &id2) == 2) { if (PGSharedMemoryIsInUse(id1, id2)) { - ereport(FATAL, - (errcode(ERRCODE_LOCK_FILE_EXISTS), - errmsg("pre-existing shared memory block " - "(key %lu, ID %lu) is still in use", - id1, - id2), - errhint("If you're sure there are no old " - "server processes still running, remove " - "the shared memory block " - "or just delete the file \"%s\".", - filename))); + ereport(FATAL, (errcode(ERRCODE_LOCK_FILE_EXISTS), + errmsg("pre-existing shared memory block " + "(key %lu, ID %lu) is still in use", + id1, id2), + errhint("If you're sure there are no old " + "server processes still running, remove " + "the shared memory block " + "or just delete the file \"%s\".", + filename))); } } } @@ -1406,12 +1373,10 @@ static void CreateLockFile(const char* filename, bool amPostmaster, bool isDDLoc * would-be creators. */ if (unlink(filename) < 0) - ereport(FATAL, - (errcode_for_file_access(), - errmsg("could not remove old lock file \"%s\": %m", filename), - errhint("The file seems accidentally left over, but " - "it could not be removed. Please remove the file " - "by hand and try again."))); + ereport(FATAL, (errcode_for_file_access(), errmsg("could not remove old lock file \"%s\": %m", filename), + errhint("The file seems accidentally left over, but " + "it could not be removed. Please remove the file " + "by hand and try again."))); } ReportResumeDataInstLockFileExist(); @@ -1422,8 +1387,8 @@ static void CreateLockFile(const char* filename, bool amPostmaster, bool isDDLoc * both datadir and socket lockfiles; although more stuff may get added to * the datadir lockfile later. */ - char* unixSocketDir = NULL; - char* pghost = gs_getenv_r("PGHOST"); + char *unixSocketDir = NULL; + char *pghost = gs_getenv_r("PGHOST"); if (pghost != NULL) { check_backend_env(pghost); } @@ -1438,18 +1403,13 @@ static void CreateLockFile(const char* filename, bool amPostmaster, bool isDDLoc } } - int rc = snprintf_s(buffer, - sizeof(buffer), - sizeof(buffer) - 1, - "%d\n%s\n%ld\n%d\n%s\n", - amPostmaster ? (int)my_pid : -((int)my_pid), - t_thrd.proc_cxt.DataDir, - (long)t_thrd.proc_cxt.MyStartTime, - g_instance.attr.attr_network.PostPortNumber, + int rc = snprintf_s(buffer, sizeof(buffer), sizeof(buffer) - 1, "%d\n%s\n%ld\n%d\n%s\n", + amPostmaster ? (int)my_pid : -((int)my_pid), t_thrd.proc_cxt.DataDir, + (long)t_thrd.proc_cxt.MyStartTime, g_instance.attr.attr_network.PostPortNumber, #ifdef HAVE_UNIX_SOCKETS - unixSocketDir + unixSocketDir #else - "" + "" #endif ); @@ -1467,13 +1427,13 @@ static void CreateLockFile(const char* filename, bool amPostmaster, bool isDDLoc pgstat_report_waitevent(WAIT_EVENT_LOCK_FILE_CREATE_WRITE); if (strlen(buffer) > 0) { if ((unsigned int)(write(fd, buffer, strlen(buffer))) != strlen(buffer)) { - int save_errno = errno; + int save_errno = errno; - close(fd); - (void)unlink(filename); - /* if write didn't set errno, assume problem is no disk space */ - errno = save_errno ? save_errno : ENOSPC; - ereport(FATAL, (errcode_for_file_access(), errmsg("could not write lock file \"%s\": %m", filename))); + close(fd); + (void)unlink(filename); + /* if write didn't set errno, assume problem is no disk space */ + errno = save_errno ? save_errno : ENOSPC; + ereport(FATAL, (errcode_for_file_access(), errmsg("could not write lock file \"%s\": %m", filename))); } } pgstat_report_waitevent(WAIT_EVENT_END); @@ -1501,7 +1461,7 @@ static void CreateLockFile(const char* filename, bool amPostmaster, bool isDDLoc * Arrange for automatic removal of lockfile at proc_exit. */ { - char* ptr = NULL; + char *ptr = NULL; ptr = MemoryContextStrdup(SESS_GET_MEM_CXT_GROUP(MEMORY_CONTEXT_EXECUTOR), filename); on_proc_exit(UnlinkLockFile, PointerGetDatum(ptr)); } @@ -1522,7 +1482,7 @@ void CreateDataDirLockFile(bool amPostmaster) /* * Create a lockfile for the specified Unix socket file. */ -void CreateSocketLockFile(const char* socketfile, bool amPostmaster, bool is_create_psql_sock) +void CreateSocketLockFile(const char *socketfile, bool amPostmaster, bool is_create_psql_sock) { char lockfile[MAXPGPATH]; @@ -1532,8 +1492,7 @@ void CreateSocketLockFile(const char* socketfile, bool amPostmaster, bool is_cre CreateLockFile(lockfile, amPostmaster, false, socketfile); /* Save name of lockfile for TouchSocketLockFile */ errno_t rcs = strcpy_s((is_create_psql_sock ? u_sess->misc_cxt.socketLockFile : u_sess->misc_cxt.hasocketLockFile), - MAXPGPATH, - lockfile); + MAXPGPATH, lockfile); securec_check_c(rcs, "\0", "\0"); } @@ -1545,7 +1504,7 @@ void CreateSocketLockFile(const char* socketfile, bool amPostmaster, bool is_cre * from being removed by overenthusiastic /tmp-directory-cleaner daemons. * (Another reason we should never have put the socket file in /tmp...) */ -void TouchSocketLockFileInternel(const char* socketLockFile) +void TouchSocketLockFileInternel(const char *socketLockFile) { /* Do nothing if we did not create a socket... */ if (socketLockFile[0] != '\0') { @@ -1589,12 +1548,12 @@ void TouchSocketLockFile(void) * Caution: this erases all following lines. In current usage that is OK * because lines are added in order. We could improve it if needed. */ -void AddToDataDirLockFile(int target_line, const char* str) +void AddToDataDirLockFile(int target_line, const char *str) { int fd = -1; int len; int lineno; - char* ptr = NULL; + char *ptr = NULL; char buffer[BLCKSZ]; fd = open(DIRECTORY_LOCK_FILE, O_RDWR | PG_BINARY, 0); @@ -1623,11 +1582,8 @@ void AddToDataDirLockFile(int target_line, const char* str) for (lineno = 1; lineno < target_line; lineno++) { if ((ptr = strchr(ptr, '\n')) == NULL) { - ereport(LOG, - (errmsg("incomplete data in \"%s\": found only %d newlines while trying to add line %d", - DIRECTORY_LOCK_FILE, - lineno - 1, - target_line))); + ereport(LOG, (errmsg("incomplete data in \"%s\": found only %d newlines while trying to add line %d", + DIRECTORY_LOCK_FILE, lineno - 1, target_line))); close(fd); return; } @@ -1683,15 +1639,15 @@ void AddToDataDirLockFile(int target_line, const char* str) * * If compatible, return. Otherwise, ereport(FATAL). */ -void ValidatePgVersion(const char* path) +void ValidatePgVersion(const char *path) { char full_path[MAXPGPATH]; - FILE* file = NULL; + FILE *file = NULL; int ret; long file_major, file_minor; long my_major = 0, my_minor = 0; - char* endptr = NULL; - const char* version_string = PG_VERSION; + char *endptr = NULL; + const char *version_string = PG_VERSION; errno_t rc; my_major = strtol(version_string, &endptr, 10); @@ -1707,9 +1663,8 @@ void ValidatePgVersion(const char* path) if (file == NULL) { if (errno == ENOENT) ereport(FATAL, - (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("\"%s\" is not a valid data directory", path), - errdetail("File \"%s\" is missing.", full_path))); + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("\"%s\" is not a valid data directory", path), + errdetail("File \"%s\" is missing.", full_path))); else ereport(FATAL, (errcode_for_file_access(), errmsg("could not open file \"%s\": %m", full_path))); } @@ -1717,23 +1672,17 @@ void ValidatePgVersion(const char* path) ret = fscanf_s(file, "%ld.%ld", &file_major, &file_minor); if (ret != 2) - ereport(FATAL, - (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("\"%s\" is not a valid data directory", path), - errdetail("File \"%s\" does not contain valid data.", full_path), - errhint("You might need to initdb."))); + ereport(FATAL, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("\"%s\" is not a valid data directory", path), + errdetail("File \"%s\" does not contain valid data.", full_path), + errhint("You might need to initdb."))); FreeFile(file); if (my_major != file_major || my_minor != file_minor) - ereport(FATAL, - (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("database files are incompatible with server"), - errdetail("The data directory was initialized by PostgreSQL version %ld.%ld, " - "which is not compatible with this version %s.", - file_major, - file_minor, - version_string))); + ereport(FATAL, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("database files are incompatible with server"), + errdetail("The data directory was initialized by PostgreSQL version %ld.%ld, " + "which is not compatible with this version %s.", + file_major, file_minor, version_string))); } /* ------------------------------------------------------------------------- @@ -1746,12 +1695,12 @@ void ValidatePgVersion(const char* path) * 'gucname': name of GUC variable, for error reports * 'restricted': if true, force libraries to be in $libdir/plugins/ */ -static void load_libraries(const char* libraries, const char* gucname, bool restricted) +static void load_libraries(const char *libraries, const char *gucname, bool restricted) { - char* rawstring = NULL; - List* elemlist = NULL; + char *rawstring = NULL; + List *elemlist = NULL; int elevel; - ListCell* l = NULL; + ListCell *l = NULL; if (libraries == NULL || libraries[0] == '\0') { return; /* nothing to do */ @@ -1783,21 +1732,21 @@ static void load_libraries(const char* libraries, const char* gucname, bool rest elevel = LOG; foreach (l, elemlist) { - char* tok = (char*)lfirst(l); - char* filename = NULL; + char *tok = (char *)lfirst(l); + char *filename = NULL; errno_t rc; filename = pstrdup(tok); - if (strcmp(filename, "security_plugin") == 0 && WorkingGrandVersionNum < 92076) { + if (strcmp(filename, "security_plugin") == 0 && WorkingGrandVersionNum < 92076) { continue; - } + } canonicalize_path(filename); /* If restricting, insert $libdir/plugins if not mentioned already */ if (restricted && first_dir_separator(filename) == NULL) { - char* expanded = NULL; + char *expanded = NULL; - expanded = (char*)palloc(strlen("$libdir/plugins/") + strlen(filename) + 1); + expanded = (char *)palloc(strlen("$libdir/plugins/") + strlen(filename) + 1); rc = strcpy_s(expanded, strlen("$libdir/plugins/") + strlen(filename) + 1, "$libdir/plugins/"); securec_check_c(rc, "\0", "\0"); rc = strcat_s(expanded, strlen("$libdir/plugins/") + strlen(filename) + 1, filename); @@ -1818,12 +1767,11 @@ static void load_libraries(const char* libraries, const char* gucname, bool rest /* * process shared preloaded libraries internal */ -void -process_shared_preload_libraries_internal(void) +void process_shared_preload_libraries_internal(void) { #ifdef ENABLE_MULTIPLE_NODES if (is_streaming_engine_available()) { - load_libraries("streaming", "shared_preload_libraries", false); + load_libraries("streaming", "shared_preload_libraries", false); } #endif return; @@ -1848,7 +1796,7 @@ void process_local_preload_libraries(void) load_libraries(u_sess->attr.attr_common.local_preload_libraries_string, "local_preload_libraries", true); } -void pg_bindtextdomain(const char* domain) +void pg_bindtextdomain(const char *domain) { #ifdef ENABLE_NLS @@ -1875,7 +1823,8 @@ void Reset_Pseudo_CurrentUserId(void) * During connection obtaining, the agent_send_connection_params_parallel function * is used to synchronize the version number. */ -void register_backend_version(uint32 backend_version){ +void register_backend_version(uint32 backend_version) +{ if (IsBootstrapProcessingMode() || IsInitProcessingMode() || !IS_PGXC_COORDINATOR) { return; } @@ -1890,7 +1839,7 @@ void register_backend_version(uint32 backend_version){ ereport(ERROR, (errcode(ERRCODE_SET_QUERY), errmsg("backend_version is a error value: %d", backend_version))); } securec_check_ss_c(ret, "\0", "\0"); - if (PoolManagerSetCommand(POOL_CMD_GLOBAL_SET, sql_tmp, "backend_version") < 0){ + if (PoolManagerSetCommand(POOL_CMD_GLOBAL_SET, sql_tmp, "backend_version") < 0) { ereport(ERROR, (errmodule(MOD_TRANS_HANDLE), errcode(ERRCODE_SET_QUERY), errmsg("ERROR SET backend_version"))); } } @@ -1898,8 +1847,8 @@ void register_backend_version(uint32 backend_version){ /* * Check whether the version contains the backend_version parameter. */ -bool contain_backend_version(uint32 version_number) { - return ((version_number >= V5R1C20_BACKEND_VERSION_NUM && - version_number < V5R2C00_START_VERSION_NUM) || +bool contain_backend_version(uint32 version_number) +{ + return ((version_number >= V5R1C20_BACKEND_VERSION_NUM && version_number < V5R2C00_START_VERSION_NUM) || (version_number >= V5R2C00_BACKEND_VERSION_NUM)); } diff --git a/src/gausskernel/optimizer/commands/aggregatecmds.cpp b/src/gausskernel/optimizer/commands/aggregatecmds.cpp index 68db543f5..3d59f9c9d 100644 --- a/src/gausskernel/optimizer/commands/aggregatecmds.cpp +++ b/src/gausskernel/optimizer/commands/aggregatecmds.cpp @@ -43,47 +43,47 @@ #include "catalog/pg_proc_fn.h" /* - * DefineAggregate - * - * "oldstyle" signals the old (pre-8.2) style where the aggregate input type - * is specified by a BASETYPE element in the parameters. Otherwise, - * "args" defines the input type(s). + DefineAggregate + "oldstyle" 琛ㄧず鏃у紡鑱氬悎鍑芥暟瀹氫箟椋庢牸锛 + 鍏朵腑鑱氬悎鍑芥暟鐨勮緭鍏ョ被鍨嬬敱鍙傛暟涓殑 BASETYPE 鍏冪礌鎸囧畾銆 + 鍚﹀垯锛"args" 瀹氫箟浜嗚緭鍏ョ被鍨 */ void DefineAggregate(List* name, List* args, bool oldstyle, List* parameters) { - char* aggName = NULL; - Oid aggNamespace; - AclResult aclresult; - List* transfuncName = NIL; - List* finalfuncName = NIL; - List* sortoperatorName = NIL; - TypeName* baseType = NULL; - TypeName* transType = NULL; - char* initval = NULL; + char* aggName = NULL;//瀛楃鍨嬫寚閽堬紝鐢ㄤ簬瀛樺偍鑱氬悎鍑芥暟鐨勫悕绉 + Oid aggNamespace;//瀵硅薄鏍囪瘑绗︾被鍨嬶紝琛ㄧず鑱氬悎鍑芥暟鎵灞炵殑鍛藉悕绌洪棿 + AclResult aclresult;//aclresult 鏄竴涓灇涓惧硷紝琛ㄧず璁块棶鎺у埗鐨勭粨鏋 + List* transfuncName = NIL;//閾捐〃绫诲瀷锛岀敤浜庡瓨鍌ㄨ仛鍚堝嚱鏁扮殑杩囨浮鍑芥暟鐨勫悕绉 + List* finalfuncName = NIL;//鐢ㄤ簬瀛樺偍鑱氬悎鍑芥暟鐨勬渶缁堝嚱鏁扮殑鍚嶇О + List* sortoperatorName = NIL;//鐢ㄤ簬瀛樺偍鎺掑簭鎿嶄綔绗︾殑鍚嶇О + TypeName* baseType = NULL;//涓涓寚鍚 TypeName 缁撴瀯鐨勬寚閽堬紝琛ㄧず鑱氬悎鍑芥暟鐨勫熀纭绫诲瀷 + TypeName* transType = NULL;//涔熸槸TypeName缁撴瀯鐨勬寚閽堬紝琛ㄧず鑱氬悎鍑芥暟鐨勮繃娓$被鍨 + char* initval = NULL;//鐢ㄤ簬瀛樺偍鑱氬悎鍑芥暟鐨勫垵濮嬪 #ifdef PGXC List* collectfuncName = NIL; char* initcollect = NULL; #endif - Oid* aggArgTypes = NULL; - int numArgs; - Oid transTypeId; - ListCell* pl = NULL; +//瀹氫箟浜嗙敤浜庢敹闆嗘暟鎹殑鍑芥暟鍚嶇О鍜屽垵濮嬪 + Oid* aggArgTypes = NULL;//琛ㄧず鑱氬悎鍑芥暟鐨勫弬鏁扮被鍨 + int numArgs;//琛ㄧず鑱氬悎鍑芥暟鐨勫弬鏁版暟閲 + Oid transTypeId;//琛ㄧず鑱氬悎鍑芥暟鐨勮繃娓$被鍨嬬殑鏍囪瘑绗 + ListCell* pl = NULL;//寰幆涓棿鍙橀噺 - /* attribute for ordered set aggregate */ + //鏈夊簭闆嗗悎鑱氬悎鍑芥暟鐨勫睘鎬ф垨鐗瑰緛 char aggKind = AGGKIND_NORMAL; - /* Convert list of names to a name and namespace */ + //灏嗕竴缁勫悕绉板垪琛ㄨ浆鎹负鍚嶇О鍜屽懡鍚嶇┖闂 aggNamespace = QualifiedNameGetCreationNamespace(name, &aggName); - /* Check we have creation rights in target namespace */ + //妫鏌ユ槸鍚﹀叿鏈夊湪鐩爣鍛藉悕绌洪棿涓垱寤虹殑鏉冮檺 aclresult = pg_namespace_aclcheck(aggNamespace, GetUserId(), ACL_CREATE); if (aclresult != ACLCHECK_OK) aclcheck_error(aclresult, ACL_KIND_NAMESPACE, get_namespace_name(aggNamespace)); if (u_sess->attr.attr_sql.enforce_a_behavior) { Oid proowner = InvalidOid; /* - * isalter is true, change the owner of the objects as the owner of the - * namespace, if the owner of the namespce has the same name as the namescpe + 濡傛灉 isalter 涓虹湡锛屽垯灏嗗璞$殑鎵鏈夎呮洿鏀逛负鍛藉悕绌洪棿鐨勬墍鏈夎咃紝 + 浣嗗墠鎻愭槸鍛藉悕绌洪棿鐨勬墍鏈夎呬笌鍛藉悕绌洪棿鏈韩鍏锋湁鐩稿悓鐨勫悕绉 */ bool isalter = false; proowner = GetUserIdFromNspId(aggNamespace); @@ -102,10 +102,8 @@ void DefineAggregate(List* name, List* args, bool oldstyle, List* parameters) foreach (pl, parameters) { DefElem* defel = (DefElem*)lfirst(pl); - /* - * sfunc1, stype1, and initcond1 are accepted as obsolete spellings - * for sfunc, stype, initcond. - */ + //sfunc1銆乻type1 鍜 initcond1 琚涓 鏄痵func銆乻type 鍜 initcond 鐨勮繃鏃舵嫾鍐欐柟寮 + if (pg_strcasecmp(defel->defname, "sfunc") == 0) transfuncName = defGetQualifiedName(defel); else if (pg_strcasecmp(defel->defname, "sfunc1") == 0) @@ -124,6 +122,10 @@ void DefineAggregate(List* name, List* args, bool oldstyle, List* parameters) initval = defGetString(defel); else if (pg_strcasecmp(defel->defname, "initcond1") == 0) initval = defGetString(defel); + /* + 涓婅堪浣跨敤涓涓惊鐜亶鍘 parameters 鍒楄〃涓殑姣忎釜鍏冪礌锛圖efElem 缁撴瀯锛夛紝 + 鐒跺悗鏍规嵁鍏冪礌鐨 defname 瀛楁锛堝弬鏁板悕绉帮級鐨勫兼墽琛屼笉鍚岀殑鎿嶄綔 + */ #ifdef PGXC else if (pg_strcasecmp(defel->defname, "cfunc") == 0) collectfuncName = defGetQualifiedName(defel); @@ -135,29 +137,23 @@ void DefineAggregate(List* name, List* args, bool oldstyle, List* parameters) (errcode(ERRCODE_SYNTAX_ERROR), errmsg("aggregate attribute \"%s\" not recognized", defel->defname))); } - /* - * make sure we have our required definitions - */ + + //纭繚鎴戜滑鏈夋墍闇鐨勫畾涔夊彉閲 + if (transType == NULL) ereport(ERROR, (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION), errmsg("aggregate stype must be specified"))); if (transfuncName == NIL) ereport(ERROR, (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION), errmsg("aggregate sfunc must be specified"))); - /* - * look up the aggregate's input datatype(s). - */ if (oldstyle) { /* - * Old style: use basetype parameter. This supports aggregates of - * zero or one input, with input type ANY meaning zero inputs. - * - * Historically we allowed the command to look like basetype = 'ANY' - * so we must do a case-insensitive comparison for the name ANY. Ugh. + Old style鏀寔闆朵釜鎴栦竴涓緭鍏ョ殑鑱氬悎鍑芥暟锛屽叾涓緭鍏ョ被鍨 ANY 琛ㄧず闆朵釜杈撳叆 + 浠ュ線鎴戜滑鍏佽鍛戒护鐪嬭捣鏉ュ儚 basetype = 'ANY'锛屽洜姝ゆ垜浠繀椤诲鍚嶇О ANY 杩涜涓嶅尯鍒嗗ぇ灏忓啓鐨勬瘮杈 */ if (baseType == NULL) ereport(ERROR, (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION), errmsg("aggregate input type must be specified"))); - + //baseType鍙傛暟鐨勫间笉鑳戒负绌猴紝鑱氬悎鍑芥暟鐨勮緭鍏ョ被鍨嬪繀椤绘寚瀹 if (pg_strcasecmp(TypeNameToString(baseType), "ANY") == 0) { numArgs = 0; aggArgTypes = NULL; @@ -167,9 +163,6 @@ void DefineAggregate(List* name, List* args, bool oldstyle, List* parameters) aggArgTypes[0] = typenameTypeId(NULL, baseType); } } else { - /* - * New style: args is a list of TypeNames (possibly zero of 'em). - */ ListCell* lc = NULL; int i = 0; @@ -178,32 +171,31 @@ void DefineAggregate(List* name, List* args, bool oldstyle, List* parameters) (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION), errmsg("basetype is redundant with aggregate input type specification"))); - /* Given ordered set aggregate with no direct args, aggr_args variable is modified in gram.y. - So the parse of aggr_args should be changed. See gram.y for detail. */ + /* 鍦ㄤ娇鐢ㄦ病鏈夌洿鎺ュ弬鏁扮殑鏈夊簭闆嗗悎鑱氬悎鍑芥暟鏃讹紝aggr_args 鍙橀噺浼氬湪 gram.y 鏂囦欢涓繘琛屼慨鏀广 + 鍥犳锛岃В鏋 aggr_args 鐨勮繃绋嬪簲璇ヨ繘琛岀浉搴旂殑鏇存敼銆 + */ numArgs = list_length((List*)linitial(args)); + // 鑾峰彇浼犻掔粰鑱氬悎鍑芥暟鐨勫弬鏁版暟閲 aggArgTypes = (Oid*)palloc(sizeof(Oid) * numArgs); - foreach (lc, (List*)linitial(args)) { + // 涓鸿仛鍚堝嚱鏁扮殑鍙傛暟绫诲瀷鏍囪瘑绗﹀垎閰嶅唴瀛 + foreach (lc, (List*)linitial(args)) + {//// 閬嶅巻浼犻掔粰鑱氬悎鍑芥暟鐨勫弬鏁板垪琛 TypeName* curTypeName = (TypeName*)lfirst(lc); aggArgTypes[i++] = typenameTypeId(NULL, curTypeName); + // 鑾峰彇褰撳墠鍙傛暟鐨勭被鍨嬫爣璇嗙骞跺瓨鍌ㄥ埌鏁扮粍涓 } - /* Set aggKind to AGGKIND_ORDERED_SET if second arg of aggr_args is 0. */ if (intVal(lsecond(args)) == 0) { aggKind = AGGKIND_ORDERED_SET; } } /* - * look up the aggregate's transtype. - * - * transtype can't be a pseudo-type, since we need to be able to store - * values of the transtype. However, we can allow polymorphic transtype - * in some cases (AggregateCreate will check). Also, we allow "internal" - * for functions that want to pass pointers to private data structures; - * but allow that only to superusers, since you could crash the system (or - * worse) by connecting up incompatible internal-using functions in an - * aggregate. + 涓嬮潰鏌ユ壘鑱氬悎鍑芥暟鐨 transtype + transtype 涓嶈兘鏄吉绫诲瀷锛屽洜涓烘垜浠渶瑕佽兘澶熷瓨鍌 transtype 鐨勫笺 + 鐒惰岋紝鍦ㄦ煇浜涙儏鍐典笅锛屾垜浠彲浠ュ厑璁稿鎬佺殑 transtype锛圓ggregateCreate 鍑芥暟灏嗕細妫鏌ヨ繖涓鐐癸級銆 + 姝ゅ锛屾垜浠厑璁镐娇鐢 "internal"锛岀敤浜庨偅浜涘笇鏈涗紶閫掓寚鍚戠鏈夋暟鎹粨鏋勭殑鎸囬拡鐨勫嚱鏁 */ transTypeId = typenameTypeId(NULL, transType); if (get_typtype(transTypeId) == TYPTYPE_PSEUDO && !IsPolymorphicType(transTypeId) @@ -212,45 +204,44 @@ void DefineAggregate(List* name, List* args, bool oldstyle, List* parameters) (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION), errmsg("aggregate transition data type cannot be %s", format_type_be(transTypeId)))); } - /* - * Most of the argument-checking is done inside of AggregateCreate - */ - AggregateCreate(aggName, /* aggregate name */ - aggNamespace, /* namespace */ - aggKind, /* agg kind */ - aggArgTypes, /* input data type(s) */ - numArgs, - transfuncName, /* step function name */ + + //澶ч儴鍒嗙殑鍙傛暟妫鏌ラ兘鍦 AggregateCreate 鍑芥暟鍐呴儴瀹屾垚 + AggregateCreate(aggName, /* 鑱氬悎鍑芥暟鐨勫悕绉 */ + aggNamespace, /* 鍛藉悕绌洪棿 */ + aggKind, /* 鑱氬悎绉嶇被 */ + aggArgTypes, /* 杈撳叆绫诲瀷绉嶇被 */ + numArgs, /* 杈撳叆鍙傛暟鏁伴噺 */ + transfuncName, /* 杩囨浮鍑芥暟鍚嶇О */ #ifdef PGXC - collectfuncName, /* collect function name */ + collectfuncName, /* 鏀堕泦鍑芥暟鍚嶇О */ #endif - finalfuncName, /* final function name */ - sortoperatorName, /* sort operator name */ - transTypeId, /* transition data type */ + finalfuncName, /* 鏈缁堝嚱鏁板悕绉 */ + sortoperatorName, /* 鎺掑簭鎿嶄綔绗﹀悕绉 */ + transTypeId, /* 杩囨浮鏁版嵁绫诲瀷 */ #ifdef PGXC - initval, /* initial condition */ - initcollect); /* initial condition for collection function */ + initval, /* 鍒濆鏉′欢 */ + initcollect); /* 鏀堕泦鍑芥暟鐨勫垵濮嬫潯浠 */ #else - initval); /* initial condition */ + initval); /* 鍒濆鏉′欢 */ #endif } void RenameAggregate(List* name, List* args, const char* newname) { - Oid procOid; - Oid namespaceOid; - HeapTuple tup; - Form_pg_proc procForm; - Relation rel; - AclResult aclresult; - bool isNull = false; - rel = heap_open(ProcedureRelationId, RowExclusiveLock); + Oid procOid; /* 鑱氬悎鍑芥暟鐨 Oid */ + Oid namespaceOid; /* 鍛藉悕绌洪棿鐨 Oid */ + HeapTuple tup; /* HeapTuple 缁撴瀯锛岀敤浜庡瓨鍌ㄥ厓缁 */ + Form_pg_proc procForm; /* pg_proc 琛ㄤ腑鐨勫厓缁勭粨鏋 */ + Relation rel; /* pg_proc 琛ㄧ殑 Relation 瀵硅薄 */ + AclResult aclresult; /* AclResult 鏋氫妇锛岀敤浜庡瓨鍌ㄨ闂帶鍒剁殑缁撴灉 */ + bool isNull = false; /* 甯冨皵鍙橀噺锛岃〃绀烘槸鍚︿负 NULL */ + rel = heap_open(ProcedureRelationId, RowExclusiveLock); /* 鎵撳紑 pg_proc 琛 */ - /* Look up function and make sure it's an aggregate */ + /* 鏌ヨ鍑芥暟骞剁‘淇濅粬鏄仛鍚堢殑*/ procOid = LookupAggNameTypeNames(name, args, false); tup = SearchSysCacheCopy1(PROCOID, ObjectIdGetDatum(procOid)); - if (!HeapTupleIsValid(tup)) /* should not happen */ + if (!HeapTupleIsValid(tup)) /* 濡傛灉杩愯姝e父杩欐槸涓嶄細鍑虹幇鐨 */ ereport(ERROR, (errcode(ERRCODE_CACHE_LOOKUP_FAILED), errmsg("cache lookup failed for function %u", procOid))); procForm = (Form_pg_proc)GETSTRUCT(tup); @@ -265,13 +256,14 @@ void RenameAggregate(List* name, List* args, const char* newname) #ifndef ENABLE_MULTIPLE_NODES Datum allargtypes = ProcedureGetAllArgTypes(tup, &isNull); Datum argmodes = SysCacheGetAttr(PROCOID, tup, Anum_pg_proc_proargmodes, &isNull); - /* make sure the new name doesn't exist */ + // 鍦ㄧ郴缁熺紦瀛樹腑鎼滅储鍏锋湁鐩稿悓鍙傛暟鐨勫嚱鏁 if (SearchSysCacheForProcAllArgs( CStringGetDatum(newname), allargtypes, ObjectIdGetDatum(namespaceOid), ObjectIdGetDatum(packageoid), argmodes)) + // 濡傛灉鎵惧埌鐩稿悓鍙傛暟鐨勫嚱鏁帮紝鎶ュ憡閿欒 ereport(ERROR, (errcode(ERRCODE_DUPLICATE_FUNCTION), errmsg("function %s already exists in schema \"%s\"", @@ -288,16 +280,16 @@ void RenameAggregate(List* name, List* args, const char* newname) funcname_signature_string(newname, procForm->pronargs, NIL, proargs->values), get_namespace_name(namespaceOid)))); #endif - /* must be owner */ + // 妫鏌ュ綋鍓嶇敤鎴锋槸鍚︽槸鑱氬悎鍑芥暟鐨勬墍鏈夎咃紝濡傛灉涓嶆槸锛屽垯鎶ュ憡閿欒 if (!pg_proc_ownercheck(procOid, GetUserId())) aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_PROC, NameListToString(name)); - /* must have CREATE privilege on namespace */ + // 妫鏌ュ綋鍓嶇敤鎴锋槸鍚︽湁鍦ㄥ懡鍚嶇┖闂翠腑鍒涘缓瀵硅薄鐨勬潈闄 aclresult = pg_namespace_aclcheck(namespaceOid, GetUserId(), ACL_CREATE); if (aclresult != ACLCHECK_OK) aclcheck_error(aclresult, ACL_KIND_NAMESPACE, get_namespace_name(namespaceOid)); - /* rename */ + //閲嶅懡鍚 (void)namestrcpy(&(((Form_pg_proc)GETSTRUCT(tup))->proname), newname); simple_heap_update(rel, &tup->t_self, tup); CatalogUpdateIndexes(rel, tup); @@ -307,15 +299,15 @@ void RenameAggregate(List* name, List* args, const char* newname) } /* - * Change aggregate owner + 涓嬮潰鍑芥暟鐢ㄦ潵鏇存敼鑱氬悎鍑芥暟鐨勬墍鏈夎 */ void AlterAggregateOwner(List* name, List* args, Oid newOwnerId) { Oid procOid; - /* Look up function and make sure it's an aggregate */ + /* 鏌ユ壘鍑芥暟骞剁‘淇濆畠鏄竴涓仛鍚堝嚱鏁般 */ procOid = LookupAggNameTypeNames(name, args, false); - /* The rest is just like a function */ + /* 鍏朵綑閮ㄥ垎涓庢櫘閫氬嚱鏁扮被浼 */ AlterFunctionOwner_oid(procOid, newOwnerId); -} +} \ No newline at end of file diff --git a/src/gausskernel/process/globalplancache/globalplancache.cpp b/src/gausskernel/process/globalplancache/globalplancache.cpp index 96f6ecf75..0f39685ef 100644 --- a/src/gausskernel/process/globalplancache/globalplancache.cpp +++ b/src/gausskernel/process/globalplancache/globalplancache.cpp @@ -22,7 +22,6 @@ * ------------------------------------------------------------------------- */ - #include "postgres.h" #include "knl/knl_variable.h" @@ -45,12 +44,20 @@ #include "nodes/pg_list.h" #include "commands/sqladvisor.h" -template void GlobalPlanCache::RemovePlanSource(CachedPlanSource* plansource, const char* stmt_name); +template void GlobalPlanCache::RemovePlanSource(CachedPlanSource *plansource, const char *stmt_name); -template void GlobalPlanCache::RemovePlanSource(CachedPlanSource* plansource, const char* stmt_name); - -template void GlobalPlanCache::RemovePlanSource(CachedPlanSource* plansource, const char* stmt_name); +template void GlobalPlanCache::RemovePlanSource(CachedPlanSource *plansource, const char *stmt_name); +template void GlobalPlanCache::RemovePlanSource(CachedPlanSource *plansource, const char *stmt_name); +/* + * 鍔熻兘锛氭鏌ヤ袱涓垪琛ㄦ槸鍚﹀叿鏈変笉鍚岀殑妯″紡 + * + * 鍙傛暟鍒楄〃锛 + * list1锛氱涓涓垪琛 + * list2锛氱浜屼釜鍒楄〃 + * + * 杩斿洖鍊硷細濡傛灉涓や釜鍒楄〃鍏锋湁涓嶅悓鐨勬ā寮忥紝杩斿洖 true锛屽惁鍒欒繑鍥 false + */ static bool has_diff_schema(const List *list1, const List *list2) { const ListCell *cell = NULL; @@ -65,42 +72,68 @@ static bool has_diff_schema(const List *list1, const List *list2) } return false; } - -static bool -CompareSearchPath(struct OverrideSearchPath* path1, struct OverrideSearchPath* path2) +/* + * 鍔熻兘锛氭瘮杈冧袱涓悳绱㈣矾寰凮verrideSearchPath鏄惁鐩稿悓 + * + * 鍙傛暟鍒楄〃锛 + * path1锛氱涓涓悳绱㈣矾寰凮verrideSearchPath + * path2锛氱浜屼釜鎼滅储璺緞OverrideSearchPath + * + * 杩斿洖鍊硷細濡傛灉涓や釜鎼滅储璺緞鐩稿悓锛岃繑鍥 true锛屽惁鍒欒繑鍥 false + */ +static bool CompareSearchPath(struct OverrideSearchPath *path1, struct OverrideSearchPath *path2) { + // 妫鏌ョ涓涓悳绱㈣矾寰勬槸鍚︿负NULL Assert(path1 != NULL); + // 濡傛灉绗簩涓悳绱㈣矾寰勪负NULL锛屼笌褰撳墠鎼滅储璺緞杩涜姣旇緝 if (path2 == NULL) { return OverrideSearchPathMatchesCurrent(path1); } + // 濡傛灉涓や釜鎼滅储璺緞鎸囧悜鐩稿悓鐨勫唴瀛樹綅缃紝瀹冧滑涓瀹氱浉鍚 if (path1 == path2) { return true; } + // 妫鏌ユ槸鍚︽坊鍔犱簡涓存椂妯″紡 if (path1->addTemp != path2->addTemp) { return false; } + // 妫鏌ユ槸鍚︽坊鍔犱簡绯荤粺妯″紡 if (path1->addCatalog != path2->addCatalog) { return false; } + // 妫鏌ユā寮忓垪琛ㄦ槸鍚﹀叿鏈変笉鍚岀殑妯″紡 if (has_diff_schema(path1->schemas, path2->schemas)) { return false; } + // 妫鏌ユā寮忓垪琛ㄦ槸鍚﹀叿鏈変笉鍚岀殑妯″紡 if (has_diff_schema(path2->schemas, path1->schemas)) { return false; } + // 濡傛灉涓婅堪鏉′欢閮戒笉婊¤冻锛岃鏄庝袱涓悳绱㈣矾寰勭浉鍚 return true; } - -static bool GPCCompareParam(Oid* params1, Oid* params2, int paramNum) +/* + * 鍔熻兘锛氭瘮杈冧袱涓弬鏁板垪琛ㄦ槸鍚︾浉鍚 + * + * 鍙傛暟鍒楄〃锛 + * params1锛氱涓涓弬鏁板垪琛ㄧ殑Oid鏁扮粍 + * params2锛氱浜屼釜鍙傛暟鍒楄〃鐨凮id鏁扮粍 + * paramNum锛氬弬鏁扮殑鏁伴噺 + * + * 杩斿洖鍊硷細濡傛灉涓や釜鍙傛暟鍒楄〃鐩稿悓锛岃繑鍥 true锛屽惁鍒欒繑鍥 false + */ +static bool GPCCompareParam(Oid *params1, Oid *params2, int paramNum) { for (int i = 0; i < paramNum; i++) { + // 濡傛灉涓や釜鍙傛暟鍒楄〃鐨勭浉搴斿弬鏁颁笉鐩哥瓑锛岃鏄庡弬鏁板垪琛ㄤ笉鍚 if (params1[i] != params2[i]) { return false; } } + // 濡傛灉寰幆瀹屾垚鍚庨兘娌℃湁鍙戠幇涓嶅悓鐨勫弬鏁帮紝璇存槑鍙傛暟鍒楄〃鐩稿悓 return true; } @@ -108,16 +141,14 @@ static bool GPCCompareParam(Oid* params1, Oid* params2, int paramNum) * Return false when the given compilation environment matches the current * session compilation environment, mainly compares GUC parameter settings. */ -static bool -GPCCompareEnv(GPCEnv *env1, GPCEnv *env2) +static bool GPCCompareEnv(GPCEnv *env1, GPCEnv *env2) { - Assert (env1 != NULL); - Assert (env2 != NULL); - if (memcmp(&env1->plainenv, &env2->plainenv, sizeof(GPCPlainEnv)) == 0 - && strncmp(env1->default_storage_nodegroup, env2->default_storage_nodegroup, NAMEDATALEN) == 0 - && strncmp(env1->expected_computing_nodegroup, env2->expected_computing_nodegroup, NAMEDATALEN) == 0 - && env1->num_params == env2->num_params) - { + Assert(env1 != NULL); + Assert(env2 != NULL); + if (memcmp(&env1->plainenv, &env2->plainenv, sizeof(GPCPlainEnv)) == 0 && + strncmp(env1->default_storage_nodegroup, env2->default_storage_nodegroup, NAMEDATALEN) == 0 && + strncmp(env1->expected_computing_nodegroup, env2->expected_computing_nodegroup, NAMEDATALEN) == 0 && + env1->num_params == env2->num_params) { if (!GPCCompareParam(env1->param_types, env2->param_types, env1->num_params)) { return false; } @@ -134,23 +165,43 @@ GPCCompareEnv(GPCEnv *env1, GPCEnv *env2) return false; } - +/* + * 鍔熻兘锛氳绠椾竴涓狦PCKey瀵硅薄鐨勫搱甯屽 + * + * 鍙傛暟鍒楄〃锛 + * key锛氭寚鍚慓PCKey缁撴瀯鐨勬寚閽 + * keysize锛歬ey鍙傛暟鐨勫ぇ灏 + * + * 杩斿洖鍊硷細璁$畻寰楀埌鐨勫搱甯屽 + */ uint32 GPCHashFunc(const void *key, Size keysize) { - const GPCKey *item = (const GPCKey *) key; + // 灏唊ey寮哄埗杞崲涓篏PCKey绫诲瀷鐨勬寚閽 + const GPCKey *item = (const GPCKey *)key; + // 鍒嗗埆璁$畻涓変釜涓嶅悓閮ㄥ垎鐨勫搱甯屽 uint32 val1 = DatumGetUInt32(hash_any((const unsigned char *)item->query_string, item->query_length)); uint32 val2 = DatumGetUInt32(hash_any((const unsigned char *)(&item->env.plainenv), sizeof(GPCPlainEnv))); uint32 val3 = DatumGetUInt32(hash_any((const unsigned char *)(&item->spi_signature), sizeof(SPISign))); + // 瀵硅繖涓変釜鍝堝笇鍊艰繘琛屽紓鎴栨搷浣滐紝寰楀埌鏈缁堢殑鍝堝笇鍊 val1 ^= val2; val1 ^= val3; return val1; } - +/* + * 鍔熻兘锛氭瘮杈冧袱涓狦PCKey瀵硅薄鏄惁鐩哥瓑 + * + * 鍙傛暟鍒楄〃锛 + * left锛氭寚鍚戠涓涓狦PCKey缁撴瀯鐨勬寚閽 + * right锛氭寚鍚戠浜屼釜GPCKey缁撴瀯鐨勬寚閽 + * keysize锛歬ey鍙傛暟鐨勫ぇ灏 + * + * 杩斿洖鍊硷細濡傛灉涓や釜GPCKey瀵硅薄鐩哥瓑锛岃繑鍥0锛涘惁鍒欒繑鍥為潪0鍊 + */ int GPCKeyMatch(const void *left, const void *right, Size keysize) { - GPCKey *leftItem = (GPCKey*)left; - GPCKey *rightItem = (GPCKey*)right; + GPCKey *leftItem = (GPCKey *)left; + GPCKey *rightItem = (GPCKey *)right; Assert(NULL != leftItem); Assert(NULL != rightItem); @@ -159,17 +210,23 @@ int GPCKeyMatch(const void *left, const void *right, Size keysize) return 1; } - if(strncmp(leftItem->query_string, rightItem->query_string, leftItem->query_length)) { + if (strncmp(leftItem->query_string, rightItem->query_string, leftItem->query_length)) { return 1; } - if(GPCCompareEnv(&(leftItem->env), &(rightItem->env)) == false) { + if (GPCCompareEnv(&(leftItem->env), &(rightItem->env)) == false) { return 1; } return 0; } - +/* + * 鍔熻兘锛氭繁搴﹀鍒朵竴涓狦PCKey瀵硅薄鍒板彟涓涓璞 + * + * 鍙傛暟鍒楄〃锛 + * srcGpckey锛氭簮GPCKey瀵硅薄鐨勬寚閽 + * destGpckey锛氱洰鏍嘒PCKey瀵硅薄鐨勬寚閽 + */ void GPCKeyDeepCopy(const GPCKey *srcGpckey, GPCKey *destGpckey) { *destGpckey = *srcGpckey; @@ -177,10 +234,10 @@ void GPCKeyDeepCopy(const GPCKey *srcGpckey, GPCKey *destGpckey) destGpckey->query_string = pstrdup(srcGpckey->query_string); if (destGpckey->env.num_params > 0) { - destGpckey->env.param_types = (Oid*)palloc(sizeof(Oid) * destGpckey->env.num_params); + destGpckey->env.param_types = (Oid *)palloc(sizeof(Oid) * destGpckey->env.num_params); errno_t rc = 0; - rc = memcpy_s(destGpckey->env.param_types, sizeof(Oid) * destGpckey->env.num_params, - srcGpckey->env.param_types, sizeof(Oid) * destGpckey->env.num_params); + rc = memcpy_s(destGpckey->env.param_types, sizeof(Oid) * destGpckey->env.num_params, srcGpckey->env.param_types, + sizeof(Oid) * destGpckey->env.num_params); securec_check(rc, "", ""); } @@ -201,13 +258,17 @@ GlobalPlanCache::GlobalPlanCache() } GlobalPlanCache::~GlobalPlanCache() -{ -} - +{} +/* + * 鍔熻兘锛氬垵濮嬪寲鍏ㄥ眬璁″垝缂撳瓨 + * + * 鍙傛暟鍒楄〃锛氭棤 + */ void GlobalPlanCache::Init() { HASHCTL ctl; errno_t rc = 0; + // 鍒濆鍖朿tl缁撴瀯浣擄紝鐢ㄤ簬閰嶇疆鍝堝笇琛ㄧ殑灞炴 rc = memset_s(&ctl, sizeof(ctl), 0, sizeof(ctl)); securec_check(rc, "\0", "\0"); ctl.keysize = sizeof(GPCKey); @@ -215,68 +276,79 @@ void GlobalPlanCache::Init() ctl.hash = (HashValueFunc)GPCHashFunc; ctl.match = (HashCompareFunc)GPCKeyMatch; + // 璁剧疆鍝堝笇琛ㄧ殑鏍囧織 int flags = HASH_ELEM | HASH_FUNCTION | HASH_CONTEXT | HASH_COMPARE | HASH_EXTERN_CONTEXT | HASH_NOEXCEPT; - m_array = (GPCHashCtl *) MemoryContextAllocZero(GLOBAL_PLANCACHE_MEMCONTEXT, - sizeof(GPCHashCtl) * GPC_NUM_OF_BUCKETS); + // 鍒嗛厤鍐呭瓨鐢ㄤ簬瀛樺偍鍝堝笇琛ㄦ暟缁 + m_array = + (GPCHashCtl *)MemoryContextAllocZero(GLOBAL_PLANCACHE_MEMCONTEXT, sizeof(GPCHashCtl) * GPC_NUM_OF_BUCKETS); + // 鍒濆鍖栨瘡涓搱甯岃〃妗 for (uint32 i = 0; i < GPC_NUM_OF_BUCKETS; i++) { m_array[i].count = 0; m_array[i].lockId = FirstGPCMappingLock + i; - + /* - * Create a MemoryContext per hash bucket so that all entries, plans etc under the bucket will live - * under this Memory context. This is for performance purposes. We do not want everything to be under - * the shared GlobalPlanCacheContext because more threads would need to synchronize everytime it needs a chunk - * of memory and that would become a bottleneck. - */ - m_array[i].context = AllocSetContextCreate(GLOBAL_PLANCACHE_MEMCONTEXT, - "GPC_Plan_Bucket_Context", - ALLOCSET_DEFAULT_MINSIZE, - ALLOCSET_DEFAULT_INITSIZE, - ALLOCSET_DEFAULT_MAXSIZE, - SHARED_CONTEXT); - + * Create a MemoryContext per hash bucket so that all entries, plans etc under the bucket will live + * under this Memory context. This is for performance purposes. We do not want everything to be under + * the shared GlobalPlanCacheContext because more threads would need to synchronize everytime it needs a chunk + * of memory and that would become a bottleneck. + */ + m_array[i].context = + AllocSetContextCreate(GLOBAL_PLANCACHE_MEMCONTEXT, "GPC_Plan_Bucket_Context", ALLOCSET_DEFAULT_MINSIZE, + ALLOCSET_DEFAULT_INITSIZE, ALLOCSET_DEFAULT_MAXSIZE, SHARED_CONTEXT); + // 閰嶇疆鍝堝笇琛ㄧ殑涓婁笅鏂 ctl.hcxt = m_array[i].context; - m_array[i].hash_tbl = hash_create("Global_Plan_Cache", - GPC_HTAB_SIZE, - &ctl, - flags); - + // 鍒涘缓鍝堝笇琛 + m_array[i].hash_tbl = hash_create("Global_Plan_Cache", GPC_HTAB_SIZE, &ctl, flags); } + // 鍒濆鍖栨棤鏁堣鍒掔殑鍒楄〃 m_invalid_list = NULL; } - -bool GlobalPlanCache::TryStore(CachedPlanSource *plansource, PreparedStatement *ps) +/* + * 鍔熻兘锛氬皾璇曞瓨鍌ㄥ叏灞璁″垝缂撳瓨 + * + * 鍙傛暟鍒楄〃锛 + * plansource锛氳鍒掓簮瀵硅薄 + * ps锛氶澶勭悊璇彞瀵硅薄 + * + * 杩斿洖鍊硷細瀛樺偍鏄惁鎴愬姛 + */ +bool GlobalPlanCache::TryStore(CachedPlanSource *plansource, PreparedStatement *ps) { - Assert (plansource != NULL); - Assert (plansource->magic == CACHEDPLANSOURCE_MAGIC); - Assert (!plansource->gpc.status.InShareTable()); - Assert (plansource->gpc.status.IsSharePlan()); - Assert (plansource->is_support_gplan || (plansource->gplan == NULL && plansource->cplan == NULL)); + // 鏂█鍙傛暟鏈夋晥鎬 + Assert(plansource != NULL); + Assert(plansource->magic == CACHEDPLANSOURCE_MAGIC); + Assert(!plansource->gpc.status.InShareTable()); + Assert(plansource->gpc.status.IsSharePlan()); + Assert(plansource->is_support_gplan || (plansource->gplan == NULL && plansource->cplan == NULL)); - GPCKey* key = plansource->gpc.key; + // 鑾峰彇璁″垝鐨勫叧閿瓧 + GPCKey *key = plansource->gpc.key; - uint32 hashCode = GPCHashFunc((const void *) key, sizeof(*key)); + // 璁$畻鍏抽敭瀛楃殑鍝堝笇鍊 + int32 hashCode = GPCHashFunc((const void *)key, sizeof(*key)); + // 鏍规嵁鍝堝笇鍊艰幏鍙栧搱甯屾《鐨勭紪鍙 uint32 bucket_id = GetBucket(hashCode); - Assert (bucket_id >= 0 && bucket_id < GPC_NUM_OF_BUCKETS); + Assert(bucket_id >= 0 && bucket_id < GPC_NUM_OF_BUCKETS); int lock_id = m_array[bucket_id].lockId; + // 鑾峰彇鍝堝笇妗剁殑閿 (void)LWLockAcquire(GetMainLWLockByIndex(lock_id), LW_EXCLUSIVE); MemoryContext oldcontext = MemoryContextSwitchTo(m_array[bucket_id].context); bool found = false; - GPCEntry *entry = (GPCEntry *)hash_search_with_hash_value(m_array[bucket_id].hash_tbl, - (const void*)key, hashCode, HASH_ENTER, &found); + GPCEntry *entry = (GPCEntry *)hash_search_with_hash_value(m_array[bucket_id].hash_tbl, (const void *)key, hashCode, + HASH_ENTER, &found); + // 濡傛灉鏃犳硶鍒涘缓鍝堝笇琛ㄦ潯鐩紝鎶ラ敊骞惰繑鍥炲け璐 if (entry == NULL) { MemoryContextSwitchTo(oldcontext); LWLockRelease(GetMainLWLockByIndex(lock_id)); - ereport(ERROR, - (errcode(ERRCODE_UNDEFINED_PSTATEMENT), - errmsg("store global plan source failed due to memory allocation failed"))); + ereport(ERROR, (errcode(ERRCODE_UNDEFINED_PSTATEMENT), + errmsg("store global plan source failed due to memory allocation failed"))); return false; } @@ -293,7 +365,7 @@ bool GlobalPlanCache::TryStore(CachedPlanSource *plansource, PreparedStatement plansource->next_saved = NULL; plansource->is_checked_opfusion = true; if (plansource->opFusionObj != NULL) { - OpFusion::SaveInGPC((OpFusion*)(plansource->opFusionObj)); + OpFusion::SaveInGPC((OpFusion *)(plansource->opFusionObj)); } /* initialize the ref count .*/ #ifdef ENABLE_MULTIPLE_NODES @@ -310,15 +382,15 @@ bool GlobalPlanCache::TryStore(CachedPlanSource *plansource, PreparedStatement Assert(plansource->query_context->is_shared); MemoryContextSeal(plansource->query_context); if (plansource->gplan) { - pg_atomic_fetch_add_u32((volatile uint32*)&plansource->gplan->global_refcount, 1); + pg_atomic_fetch_add_u32((volatile uint32 *)&plansource->gplan->global_refcount, 1); plansource->gplan->is_share = true; Assert(plansource->gplan->context->is_shared); MemoryContextSeal(plansource->gplan->context); } #ifdef USE_ASSERT_CHECKING else { - Assert(IS_PGXC_COORDINATOR && plansource->single_exec_node && - plansource->gplan == NULL && plansource->cplan == NULL); + Assert(IS_PGXC_COORDINATOR && plansource->single_exec_node && plansource->gplan == NULL && + plansource->cplan == NULL); } #endif plansource->gpc.status.SetLoc(GPC_SHARE_IN_SHARE_TABLE); @@ -328,11 +400,11 @@ bool GlobalPlanCache::TryStore(CachedPlanSource *plansource, PreparedStatement } else { /* some guys win. */ if (ps == NULL) { - Assert (IS_PGXC_DATANODE); + Assert(IS_PGXC_DATANODE); GPC_LOG("drop cache plan in try store", plansource, 0); DropCachedPlan(plansource); } else { - CachedPlanSource* newsource = entry->val.plansource; + CachedPlanSource *newsource = entry->val.plansource; ps->plansource = newsource; newsource->gpc.status.AddRefcount(); INSTR_TIME_SET_CURRENT(entry->val.last_use_time); @@ -354,9 +426,20 @@ bool GlobalPlanCache::TryStore(CachedPlanSource *plansource, PreparedStatement LWLockRelease(GetMainLWLockByIndex(lock_id)); return true; } - -CachedPlanSource* GlobalPlanCache::Fetch(const char *query_string, uint32 query_len, - int num_params, Oid* paramTypes, SPISign* spi_sign_ptr) +/* + * 鍔熻兘锛氫粠鍏ㄥ眬璁″垝缂撳瓨涓幏鍙栫紦瀛樿鍒掓簮瀵硅薄 + * + * 鍙傛暟鍒楄〃锛 + * query_string锛氭煡璇㈠瓧绗︿覆 + * query_len锛氭煡璇㈠瓧绗︿覆闀垮害 + * num_params锛氬弬鏁版暟閲 + * paramTypes锛氬弬鏁扮被鍨嬫暟缁 + * spi_sign_ptr锛歋PI绛惧悕鎸囬拡 + * + * 杩斿洖鍊硷細鑾峰彇鍒扮殑缂撳瓨璁″垝婧愬璞★紝鎴栬匩ULL琛ㄧず鏈壘鍒 + */ +CachedPlanSource *GlobalPlanCache::Fetch(const char *query_string, uint32 query_len, int num_params, Oid *paramTypes, + SPISign *spi_sign_ptr) { GPCKey key; key.env.filled = false; @@ -371,30 +454,33 @@ CachedPlanSource* GlobalPlanCache::Fetch(const char *query_string, uint32 query_ else key.spi_signature = {(uint32)-1, 0, (uint32)-1, -1}; - uint32 hashCode = GPCHashFunc((const void *) &key, sizeof(key)); + // 璁$畻鍏抽敭瀛楃殑鍝堝笇鍊 + uint32 hashCode = GPCHashFunc((const void *)&key, sizeof(key)); + // 鏍规嵁鍝堝笇鍊艰幏鍙栧搱甯屾《鐨勭紪鍙 uint32 bucket_id = GetBucket(hashCode); - Assert (bucket_id >= 0 && bucket_id < GPC_NUM_OF_BUCKETS); + Assert(bucket_id >= 0 && bucket_id < GPC_NUM_OF_BUCKETS); int lock_id = m_array[bucket_id].lockId; + // 鑾峰彇鍝堝笇妗剁殑閿 (void)LWLockAcquire(GetMainLWLockByIndex(lock_id), LW_SHARED); MemoryContext oldcontext = MemoryContextSwitchTo(m_array[bucket_id].context); bool foundCachedEntry = false; - GPCEntry *entry = (GPCEntry *) hash_search_with_hash_value(m_array[bucket_id].hash_tbl, - (const void*)(&key), - hashCode, - HASH_FIND, - &foundCachedEntry); + GPCEntry *entry = (GPCEntry *)hash_search_with_hash_value(m_array[bucket_id].hash_tbl, (const void *)(&key), + hashCode, HASH_FIND, &foundCachedEntry); + // 濡傛灉鏈壘鍒扮紦瀛樻潯鐩紝閲婃斁閿佸苟杩斿洖NULL if (!foundCachedEntry) { MemoryContextSwitchTo(oldcontext); LWLockRelease(GetMainLWLockByIndex(lock_id)); return NULL; } else { - CachedPlanSource* psrc = entry->val.plansource; + // 鎵惧埌缂撳瓨璁″垝婧愬璞″苟澧炲姞寮曠敤璁℃暟 + CachedPlanSource *psrc = entry->val.plansource; psrc->gpc.status.AddRefcount(); if (!psrc->gpc.status.IsValid()) { + // 濡傛灉璁″垝婧愬璞℃棤鏁堬紝閲婃斁閿侊紝灏嗗叾绉诲埌鏃犳晥璁″垝鍒楄〃锛屽噺灏戝紩鐢ㄨ鏁帮紝骞惰繑鍥濶ULL MemoryContextSwitchTo(oldcontext); LWLockRelease(GetMainLWLockByIndex(lock_id)); MoveIntoInvalidPlanList(psrc); @@ -403,6 +489,7 @@ CachedPlanSource* GlobalPlanCache::Fetch(const char *query_string, uint32 query_ } if (ENABLE_DN_GPC) u_sess->pcache_cxt.private_refcount++; + // 澧炲姞璁″垝婧愬璞$殑浣跨敤璁℃暟 pg_atomic_fetch_add_u32(&entry->val.used_count, 1); MemoryContextSwitchTo(oldcontext); LWLockRelease(GetMainLWLockByIndex(lock_id)); @@ -411,39 +498,57 @@ CachedPlanSource* GlobalPlanCache::Fetch(const char *query_string, uint32 query_ return NULL; } - -void GlobalPlanCache::AddInvalidList(CachedPlanSource* plansource) +/* + * 鍔熻兘锛氬皢璁″垝婧愬璞℃坊鍔犲埌鏃犳晥璁″垝鍒楄〃涓 + * + * 鍙傛暟鍒楄〃锛 + * plansource锛氳娣诲姞鐨勮鍒掓簮瀵硅薄 + */ +void GlobalPlanCache::AddInvalidList(CachedPlanSource *plansource) { + // 鑾峰彇娓呴櫎閿佷互鐙崰鏂瑰紡 (void)LWLockAcquire(GPCClearLock, LW_EXCLUSIVE); MemoryContext oldcontext = MemoryContextSwitchTo(GLOBAL_PLANCACHE_MEMCONTEXT); START_CRIT_SECTION(); + // 璁剧疆璁″垝婧愬璞$殑浣嶇疆涓篏PC_SHARE_IN_SHARE_TABLE_INVALID_LIST plansource->gpc.status.SetLoc(GPC_SHARE_IN_SHARE_TABLE_INVALID_LIST); + // 灏嗚鍒掓簮瀵硅薄娣诲姞鍒版棤鏁堣鍒掑垪琛ㄤ腑 m_invalid_list = dlappend(m_invalid_list, plansource); + // 璁剧疆璁″垝婧愬璞$殑鐘舵佷负GPC_INVALID plansource->gpc.status.SetStatus(GPC_INVALID); END_CRIT_SECTION(); MemoryContextSwitchTo(oldcontext); + // 閲婃斁娓呴櫎閿 LWLockRelease(GPCClearLock); } - +/* + * 鍔熻兘锛氭竻闄ゆ棤鏁堢殑鍏ㄥ眬璁″垝缂撳瓨椤 + */ void GlobalPlanCache::DropInvalid() { + // 鑾峰彇娓呴櫎閿佷互鐙崰鏂瑰紡 (void)LWLockAcquire(GPCClearLock, LW_EXCLUSIVE); if (m_invalid_list != NULL) { DListCell *cell = m_invalid_list->head; while (cell != NULL) { CachedPlanSource *curr = (CachedPlanSource *)cell->data.ptr_value; + // 妫鏌ヨ鍒掓簮瀵硅薄鐨勫紩鐢ㄨ鏁版槸鍚︿负闆 if (curr->gpc.status.RefCountZero()) { Assert(curr->next_saved == NULL); DListCell *next = cell->next; GPC_LOG("drop invalid shared plancache", curr, curr->stmt_name); + // 浠庢棤鏁堣鍒掑垪琛ㄤ腑绉婚櫎璇ヨ鍒掓簮瀵硅薄 m_invalid_list = dlist_delete_cell(m_invalid_list, cell, false); + // 鍒犻櫎璇ヨ鍒掓簮瀵硅薄 DropCachedPlanInternal(curr); curr->magic = 0; + // 瑙i櫎鍐呭瓨涓婁笅鏂囩殑灏佸嵃 MemoryContextUnSeal(curr->context); MemoryContextUnSeal(curr->query_context); if (curr->opFusionObj) { - OpFusion::DropGlobalOpfusion((OpFusion*)(curr->opFusionObj)); + OpFusion::DropGlobalOpfusion((OpFusion *)(curr->opFusionObj)); } + // 鍒犻櫎鍐呭瓨涓婁笅鏂 MemoryContextDelete(curr->context); cell = next; @@ -452,40 +557,60 @@ void GlobalPlanCache::DropInvalid() } } } + // 閲婃斁娓呴櫎閿 LWLockRelease(GPCClearLock); } - -template -void GlobalPlanCache::RemovePlanSource(CachedPlanSource* plansource, const char* stmt_name) +/* + * 鍔熻兘锛氭牴鎹粰瀹氱殑鍔ㄤ綔绫诲瀷绉婚櫎璁″垝婧愬璞 + * + * 鍙傛暟锛 + * action_type锛氬姩浣滅被鍨嬶紝鍙互鏄 ACTION_RECREATE銆丄CTION_RELOAD 绛 + * plansource锛氳绉婚櫎鐨勮鍒掓簮瀵硅薄 + * stmt_name锛氳鍙ュ悕 + */ +template +void GlobalPlanCache::RemovePlanSource(CachedPlanSource *plansource, const char *stmt_name) { Assert(plansource->magic == CACHEDPLANSOURCE_MAGIC); - if(plansource->gpc.status.InShareTable()) { - GPCKey* key = plansource->gpc.key; - uint32 hashCode = GPCHashFunc((const void *) key, sizeof(*key)); + // 濡傛灉璁″垝婧愬璞″湪鍏ㄥ眬璁″垝缂撳瓨涓 + if (plansource->gpc.status.InShareTable()) { + GPCKey *key = plansource->gpc.key; + uint32 hashCode = GPCHashFunc((const void *)key, sizeof(*key)); uint32 bucket_id = GetBucket(hashCode); int lock_id = m_array[bucket_id].lockId; + // 鑾峰彇閿佷互鐙崰鏂瑰紡 (void)LWLockAcquire(GetMainLWLockByIndex(lock_id), LW_EXCLUSIVE); + // 濡傛灉璁″垝婧愬璞′笉鍦ㄦ棤鏁堣鍒掑垪琛ㄤ腑 if (plansource->gpc.status.InShareTableInvalidList() == false) { bool found = false; + // 浠庡搱甯岃〃涓Щ闄よ鍒掓簮瀵硅薄 hash_search(m_array[bucket_id].hash_tbl, (void *)key, HASH_REMOVE, &found); + // 濡傛灉鏈壘鍒拌鍒掓簮瀵硅薄锛屽彂鍑 PANIC 绾у埆閿欒 if (unlikely(found == false)) elog(PANIC, "should found plan in gpc when RemovePlanSource"); + // 鍑忓皯璁″垝缂撳瓨鐨勮鏁 m_array[bucket_id].count--; + // 灏嗚鍒掓簮瀵硅薄娣诲姞鍒版棤鏁堣鍒掑垪琛ㄤ腑 AddInvalidList(plansource); } /* Has hold refcount for ACTION_RECREATE */ if (action_type == ACTION_RECREATE) plansource->gpc.status.SubRefCount(); + // 娓呴櫎鏃犳晥璁″垝 DropInvalid(); + // 閲婃斁閿 LWLockRelease(GetMainLWLockByIndex(lock_id)); + // 濡傛灉鍚敤浜嗗垎甯冨紡璁$畻锛屾洿鏂扮鏈夊紩鐢ㄨ鏁 if (ENABLE_DN_GPC) { u_sess->pcache_cxt.private_refcount--; + // 妫鏌ョ鏈夊紩鐢ㄨ鏁版槸鍚︽纭 if (u_sess->pcache_cxt.private_refcount != 0) elog(PANIC, "wrong refcount in subrefcount"); } + // 濡傛灉鍔ㄤ綔绫诲瀷鏄 ACTION_RELOAD if (action_type == ACTION_RELOAD) { /* clear Datanode statements */ #ifdef ENABLE_MULTIPLE_NODES @@ -495,12 +620,14 @@ void GlobalPlanCache::RemovePlanSource(CachedPlanSource* plansource, const char* GPCDropLPIfNecessary(stmt_name, true, true, NULL); #endif } - - } else { + + } else { // 濡傛灉璁″垝婧愬璞′笉鍦ㄥ叏灞璁″垝缂撳瓨涓 if (action_type == ACTION_RECREATE) { + // 浠庣鏈夎鍒掔紦瀛樹腑绉婚櫎璁″垝婧愬璞 GPC_LOG("remove private plansource", plansource, plansource->stmt_name); DropCachedPlan(plansource); } else { + // 鏍囪璁″垝婧愬璞′负鏃犳晥 CN_GPC_LOG("invalid plan", plansource, stmt_name); plansource->gpc.status.SetStatus(GPC_INVALID); plansource->is_valid = false; @@ -508,29 +635,52 @@ void GlobalPlanCache::RemovePlanSource(CachedPlanSource* plansource, const char* plansource->gplan->is_valid = false; Assert(!plansource->gplan->isShared()); } + // 濡傛灉鍔ㄤ綔绫诲瀷鏄 ACTION_RELOAD if (action_type == ACTION_RELOAD) { + // 鍒犻櫎璁″垝婧愬璞 DropCachedPlanInternal(plansource); + // 濡傛灉璁″垝婧愬璞℃病鏈夊叏灞璁″垝 if (plansource->gplan == NULL) GPCDropLPIfNecessary(stmt_name, true, true, NULL); } } } } - +/* + * 鍔熻兘锛氱Щ闄ゅ叏灞璁″垝缂撳瓨涓殑鏉$洰 + * + * 鍙傛暟锛 + * htblIdx锛氬搱甯岃〃绱㈠紩 + * entry锛氳绉婚櫎鐨勬潯鐩 + */ void GlobalPlanCache::RemoveEntry(uint32 htblIdx, GPCEntry *entry) { CachedPlanSource *plansource = entry->val.plansource; + // 浠庡搱甯岃〃涓Щ闄ゆ潯鐩 bool found = false; - hash_search(m_array[htblIdx].hash_tbl, (void *) &(entry->key), HASH_REMOVE, &found); + hash_search(m_array[htblIdx].hash_tbl, (void *)&(entry->key), HASH_REMOVE, &found); + // 鏂█绉婚櫎鎿嶄綔鎴愬姛 Assert(found == true); + // 鍑忓皯璁″垝缂撳瓨鐨勮鏁 m_array[htblIdx].count--; + // 灏嗚鍒掓簮瀵硅薄娣诲姞鍒版棤鏁堣鍒掑垪琛ㄤ腑 AddInvalidList(plansource); + // 娓呴櫎鏃犳晥璁″垝 DropInvalid(); } - -bool GlobalPlanCache::CheckRecreateCachePlan(CachedPlanSource* psrc, bool* hasGetLock) +/* + * 鍔熻兘锛氭鏌ユ槸鍚﹂渶瑕侀噸鏂板垱寤虹紦瀛樿鍒 + * + * 鍙傛暟锛 + * psrc锛氱紦瀛樿鍒掓簮 + * hasGetLock锛氭寚绀烘槸鍚﹀凡鑾峰彇閿佺殑鏍囧織 + * + * 杩斿洖鍊硷細 + * 濡傛灉闇瑕侀噸鏂板垱寤虹紦瀛樿鍒掞紝杩斿洖true锛涘惁鍒欒繑鍥瀎alse銆 + */ +bool GlobalPlanCache::CheckRecreateCachePlan(CachedPlanSource *psrc, bool *hasGetLock) { /* * Start up a transaction command so we can run parse analysis etc. (Note @@ -577,13 +727,21 @@ bool GlobalPlanCache::CheckRecreateCachePlan(CachedPlanSource* psrc, bool* hasGe return false; } - +/* + * 鍔熻兘锛氭鏌ユ槸鍚﹂渶瑕侀噸鏂板垱寤篠PI缂撳瓨璁″垝 + * + * 鍙傛暟锛 + * spi_plan锛歋PI璁″垝鎸囬拡 + * + * 杩斿洖鍊硷細 + * 濡傛灉闇瑕侀噸鏂板垱寤篠PI缂撳瓨璁″垝锛岃繑鍥瀟rue锛涘惁鍒欒繑鍥瀎alse銆 + */ bool GlobalPlanCache::CheckRecreateSPICachePlan(SPIPlanPtr spi_plan) { - ListCell* cell = NULL; + ListCell *cell = NULL; Assert(spi_plan->magic == _SPI_PLAN_MAGIC); - foreach(cell, spi_plan->plancache_list) { - CachedPlanSource* plansource = (CachedPlanSource*)lfirst(cell); + foreach (cell, spi_plan->plancache_list) { + CachedPlanSource *plansource = (CachedPlanSource *)lfirst(cell); bool hasGetLock = false; if (CheckRecreateCachePlan(plansource, &hasGetLock)) { if (hasGetLock) { @@ -597,10 +755,18 @@ bool GlobalPlanCache::CheckRecreateSPICachePlan(SPIPlanPtr spi_plan) } return false; } - +/* + * 鍔熻兘锛氶噸鏂板垱寤篠PI缂撳瓨璁″垝 + * + * 鍙傛暟锛 + * spiplan锛歋PI璁″垝鎸囬拡 + * + * 璇存槑锛 + * 杩欎釜鍑芥暟鐢ㄤ簬閲嶆柊鍒涘缓SPI缂撳瓨璁″垝銆傚畠閬嶅巻SPI璁″垝涓殑姣忎釜缂撳瓨璁″垝婧愶紝瀵逛簬姣忎釜璁″垝婧愶紝濡傛灉瀹冧笉鍦ㄥ叡浜〃涓紙涓嶉渶瑕侀噸鏂板垱寤猴級锛屽垯缁х画涓嬩竴涓鍒掓簮锛涘惁鍒欙紝璋冪敤RecreateCachePlan鍑芥暟閲嶆柊鍒涘缓缂撳瓨璁″垝銆 + */ void GlobalPlanCache::RecreateSPICachePlan(SPIPlanPtr spiplan) { - ListCell* cell = NULL; + ListCell *cell = NULL; Assert(spiplan->magic == _SPI_PLAN_MAGIC); /* push error context stack */ ErrorContextCallback spi_err_context; @@ -608,8 +774,8 @@ void GlobalPlanCache::RecreateSPICachePlan(SPIPlanPtr spiplan) spi_err_context.arg = NULL; /* we'll fill this below */ spi_err_context.previous = t_thrd.log_cxt.error_context_stack; t_thrd.log_cxt.error_context_stack = &spi_err_context; - foreach(cell, spiplan->plancache_list) { - CachedPlanSource* oldsource = (CachedPlanSource*)lfirst(cell); + foreach (cell, spiplan->plancache_list) { + CachedPlanSource *oldsource = (CachedPlanSource *)lfirst(cell); if (!oldsource->gpc.status.InShareTable()) continue; GPC_LOG("recreate spi cachedplan", oldsource, 0); @@ -619,12 +785,24 @@ void GlobalPlanCache::RecreateSPICachePlan(SPIPlanPtr spiplan) t_thrd.log_cxt.error_context_stack = spi_err_context.previous; Assert(SPIPlanCacheTableLookup(u_sess->SPI_cxt._current->spi_hash_key)); } - -void GlobalPlanCache::MoveIntoInvalidPlanList(CachedPlanSource* psrc) +/* + * 鍔熻兘锛氬皢璁″垝婧愮Щ鍒版棤鏁堣鍒掑垪琛 + * + * 鍙傛暟锛 + * psrc锛氬緟绉诲姩鐨勮鍒掓簮鎸囬拡 + * + * 璇存槑锛 + * 杩欎釜鍑芥暟鐢ㄤ簬灏嗚鍒掓簮绉诲埌鏃犳晥璁″垝鍒楄〃銆傞鍏堟鏌ヨ鍒掓簮鏄惁鍦ㄥ叡浜〃涓苟涓斾笉鏄湁鏁堢殑锛屽鏋滄槸锛屽垯缁х画鎵ц涓嬮潰鐨勬搷浣滐細 + * 1. 鑾峰彇璁″垝婧愮殑鍝堝笇鐮佸拰閿両D浠ョ‘瀹氬畠鎵鍦ㄧ殑鍝堝笇琛ㄥ拰閿併 + * 2. 鑾峰彇閿侊紝纭繚鍦ㄥ鐞嗚鍒掓簮鏃舵病鏈夊苟鍙戞搷浣溿 + * 3.妫鏌ヨ鍒掓簮鏄惁宸茬粡鍦ㄦ棤鏁堣鍒掑垪琛ㄤ腑锛屽鏋滀笉鍦紝鍒欎粠鍝堝笇琛ㄤ腑鍒犻櫎瀹冿紝鍑忓皯璁″垝婧愭墍鍦ㄥ搱甯岃〃鐨勮鏁板櫒锛屽苟灏嗗叾娣诲姞鍒版棤鏁堣鍒掑垪琛ㄤ腑銆 + * 4. 閲婃斁閿侊紝瀹屾垚绉诲姩鎿嶄綔銆 + */ +void GlobalPlanCache::MoveIntoInvalidPlanList(CachedPlanSource *psrc) { if (psrc->gpc.status.InShareTable() && !psrc->gpc.status.IsValid()) { - GPCKey* key = psrc->gpc.key; - uint32 hashCode = GPCHashFunc((const void *) key, sizeof(*key)); + GPCKey *key = psrc->gpc.key; + uint32 hashCode = GPCHashFunc((const void *)key, sizeof(*key)); uint32 bucket_id = GetBucket(hashCode); int lock_id = m_array[bucket_id].lockId; (void)LWLockAcquire(GetMainLWLockByIndex(lock_id), LW_EXCLUSIVE); @@ -639,13 +817,26 @@ void GlobalPlanCache::MoveIntoInvalidPlanList(CachedPlanSource* psrc) LWLockRelease(GetMainLWLockByIndex(lock_id)); } } - -void GlobalPlanCache::RecreateCachePlan(CachedPlanSource* oldsource, const char* stmt_name, PreparedStatement *entry, - SPIPlanPtr spiplan, ListCell* spiplanCell, bool hasGetLock) +/* + * 鍔熻兘锛氶噸鏂板垱寤虹紦瀛樿鍒 + * + * 鍙傛暟锛 + * oldsource锛氬師璁″垝婧愭寚閽堬紝闇瑕侀噸鏂板垱寤虹殑璁″垝婧 + * stmt_name锛氳鍙ュ悕绉 + * entry锛氶澶勭悊璇彞鍏ュ彛 + * spiplan锛歋PI璁″垝鎸囬拡锛堝彲閫夛級 + * spiplanCell锛歋PI璁″垝鍗曞厓鎸囬拡锛堝彲閫夛級 + * hasGetLock锛氭槸鍚﹀凡鑾峰彇閿佹爣蹇 + * + * 娉ㄦ剰锛氳繖涓嚱鏁颁娇鐢ㄤ簡PG_TRY銆丳G_CATCH鍜孭G_END_TRY绛塒ostgreSQL寮傚父澶勭悊鏈哄埗鏉ュ鐞嗛敊璇儏鍐碉紝 + * 骞跺皢鏃犳晥鐨勮鍒掓簮绉诲叆鍏ㄥ眬璁″垝缂撳瓨鐨勬棤鏁堣鍒掑垪琛ㄤ腑銆 + */ +void GlobalPlanCache::RecreateCachePlan(CachedPlanSource *oldsource, const char *stmt_name, PreparedStatement *entry, + SPIPlanPtr spiplan, ListCell *spiplanCell, bool hasGetLock) { GPC_LOG("recreate plan", oldsource, oldsource->stmt_name); /* these operator may throw error, make sure shared plan is invalid first */ - CachedPlanSource *newsource = NULL; + CachedPlanSource *newsource = NULL; // 鏂扮殑璁″垝婧 PG_TRY(); { if (hasGetLock) { @@ -654,15 +845,18 @@ void GlobalPlanCache::RecreateCachePlan(CachedPlanSource* oldsource, const char* AcquireExecutorLocks(oldsource->gplan->stmt_list, false); } } + // 澶嶅埗鍘熻鍒掓簮浠ュ垱寤烘柊鐨勮鍒掓簮 newsource = CopyCachedPlan(oldsource, true); + // 鍒囨崲鍒版柊璁″垝婧愮殑鍐呭瓨涓婁笅鏂 MemoryContext oldcxt = MemoryContextSwitchTo(newsource->context); + // 璁剧疆鏂拌鍒掓簮鐨勭浉鍏冲睘鎬 newsource->stream_enabled = IsStreamSupport(); u_sess->exec_cxt.CurrentOpFusionObj = NULL; - Assert (oldsource->gpc.status.IsSharePlan()); + Assert(oldsource->gpc.status.IsSharePlan()); newsource->gpc.status.ShareInit(); // If the planSource is set to invalid, the AST must be analyzed again // because the meta has changed. - newsource->is_valid = false; + newsource->is_valid = false; // 濡傛灉璁″垝婧愯缃负鏃犳晥锛屽繀椤婚噸鏂拌繘琛孉ST鍒嗘瀽 bool has_lp = false; if (spiplan != NULL) { @@ -686,6 +880,7 @@ void GlobalPlanCache::RecreateCachePlan(CachedPlanSource* oldsource, const char* } #endif } + // 鎵ц璇硶鍒嗘瀽浠ョ‘淇濇柊璁″垝婧愭槸鏈夋晥鐨 (void)RevalidateCachedQuery(newsource, has_lp); MemoryContextSwitchTo(oldcxt); } @@ -718,17 +913,24 @@ void GlobalPlanCache::RecreateCachePlan(CachedPlanSource* oldsource, const char* RemovePlanSource(oldsource, stmt_name); } - +/* + * 鍔熻兘锛氭彁浜ゅ叏灞璁″垝缂撳瓨鐨勬洿鏀 + * + * 璇存槑锛 + * 杩欎釜鍑芥暟鐢ㄤ簬鎻愪氦鍏ㄥ眬璁″垝缂撳瓨鐨勬洿鏀癸紝鍏蜂綋鐨勬搷浣滃彇鍐充簬鏄惁澶勪簬澶氳妭鐐圭幆澧冦 + * 濡傛灉鏄崗璋冭妭鐐癸紙Coordinator锛夛紝鍒欒皟鐢–NCommit()鍑芥暟鎻愪氦鏇存敼锛 + * 濡傛灉鏄暟鎹妭鐐癸紙Datanode锛夛紝鍒欒皟鐢―NCommit()鍑芥暟鎻愪氦鏇存敼銆 + */ void GlobalPlanCache::Commit() { #ifdef ENABLE_MULTIPLE_NODES if (IS_PGXC_COORDINATOR) { - CNCommit(); + CNCommit(); // 鎻愪氦鍏ㄥ眬璁″垝缂撳瓨鏇存敼锛堝崗璋冭妭鐐癸級 } else { - DNCommit(); + DNCommit(); // 鎻愪氦鍏ㄥ眬璁″垝缂撳瓨鏇存敼锛堟暟鎹妭鐐癸級 } #else - CNCommit(); + CNCommit(); // 鎻愪氦鍏ㄥ眬璁″垝缂撳瓨鏇存敼锛堝崟鑺傜偣鐜锛 #endif } @@ -753,9 +955,8 @@ void GlobalPlanCache::DNCommit() Assert(plansource->magic == CACHEDPLANSOURCE_MAGIC); Assert(!plansource->gpc.status.InShareTable()); if (unlikely(plansource->magic != CACHEDPLANSOURCE_MAGIC)) { - ereport(PANIC, - (errcode(ERRCODE_UNDEFINED_PSTATEMENT), - errmsg("In gpc commit stage, plansource has already been freed"))); + ereport(PANIC, (errcode(ERRCODE_UNDEFINED_PSTATEMENT), + errmsg("In gpc commit stage, plansource has already been freed"))); } next_plansource = plansource->next_saved; @@ -777,6 +978,16 @@ void GlobalPlanCache::DNCommit() } } +/* + * 鍔熻兘锛氭彁浜ゅ崗璋冭妭鐐圭殑鍏ㄥ眬璁″垝缂撳瓨鏇存敼 + * + * 璇存槑锛 + * 杩欎釜鍑芥暟鐢ㄤ簬鎻愪氦鍗忚皟鑺傜偣鐨勫叏灞璁″垝缂撳瓨鏇存敼銆 + * 瀹冮鍏堣幏鍙栧苟澶勭悊 u_sess->pcache_cxt.first_saved_plan 涓殑璁″垝缂撳瓨婧愶紙plansource锛夛紝 + * 鐒跺悗鏍规嵁涓嶅悓鐨勬儏鍐靛皢杩欎簺璁″垝缂撳瓨婧愪繚瀛樺湪涓嶅悓鐨勫垪琛ㄤ腑锛屼緥濡 ungpc_saved_plan銆乫irst_saved_plan 绛夈 + * 鏈鍚庯紝瀵逛簬鐗瑰畾鐨勮鍒掔紦瀛樻簮锛屾牴鎹叾鏄惁鏈 SPI 绛惧悕绛夋儏鍐碉紝杩涜鐩稿簲鐨勫鐞嗐 + * 鍏蜂綋澶勭悊鍖呮嫭锛氫繚瀛樹负 SPI 璁″垝銆佸皾璇曞瓨鍌ㄤ负鍏ㄥ眬璁″垝缂撳瓨銆佷繚鎸佸湪 first_saved_plan 鍒楄〃涓瓑銆 + */ void GlobalPlanCache::CNCommit() { CachedPlanSource *next_plansource = NULL; @@ -785,53 +996,58 @@ void GlobalPlanCache::CNCommit() while (plansource != NULL) { Assert(plansource->magic == CACHEDPLANSOURCE_MAGIC); Assert(!plansource->gpc.status.InShareTable()); + if (unlikely(plansource->magic != CACHEDPLANSOURCE_MAGIC)) { - ereport(PANIC, - (errcode(ERRCODE_UNDEFINED_PSTATEMENT), - errmsg("In gpc commit stage, plansource has already been freed"))); + ereport(PANIC, (errcode(ERRCODE_UNDEFINED_PSTATEMENT), + errmsg("In gpc commit stage, plansource has already been freed"))); } next_plansource = plansource->next_saved; bool has_lp = false; + #ifdef ENABLE_MULTIPLE_NODES - has_lp = plansource->single_exec_node && - plansource->gplan == NULL && plansource->cplan == NULL && plansource->stmt_name; + // 妫鏌ユ槸鍚︿负杞婚噺绾т唬鐞嗚鍒 + has_lp = plansource->single_exec_node && plansource->gplan == NULL && plansource->cplan == NULL && + plansource->stmt_name; if (has_lp) { has_lp = (lightProxy::locateLpByStmtName(plansource->stmt_name) != NULL); } #endif + if (!plansource->gpc.status.IsSharePlan() || (plansource->gplan == NULL && plansource->cplan)) { - /* stream or private plan or cplan need put into ungpc_save_plan */ + // 瀵逛簬闈炲叡浜鍒掋佹垨鑰 gplan 涓虹┖涓 cplan 瀛樺湪鐨勮鍒掞紝灏嗗叾淇濆瓨鍒 ungpc_saved_plan 鍒楄〃涓 plansource->is_saved = true; if (!plansource->is_support_gplan && plansource->gpc.status.IsSharePlan()) plansource->gpc.status.SetKind(GPC_CPLAN); - Assert (!plansource->gpc.status.IsSharePlan()); + Assert(!plansource->gpc.status.IsSharePlan()); plansource->gpc.status.SetLoc(GPC_SHARE_IN_LOCAL_UNGPC_PLAN_LIST); plansource->next_saved = u_sess->pcache_cxt.ungpc_saved_plan; u_sess->pcache_cxt.ungpc_saved_plan = plansource; } else if (!plansource->is_valid || (plansource->gplan && !plansource->gplan->is_valid)) { + // 瀵逛簬鏃犳晥璁″垝锛坕s_valid 涓 false锛夋垨鑰 gplan 鏈夋晥浣 gplan 鏃犳晥鐨勮鍒掞紝灏嗗叾淇濆瓨鍒 first_saved_plan 鍒楄〃涓 plansource->is_valid = false; plansource->is_saved = true; - Assert (plansource->gpc.status.IsSharePlan()); + Assert(plansource->gpc.status.IsSharePlan()); plansource->gpc.status.SetStatus(GPC_INVALID); plansource->gpc.status.SetLoc(GPC_SHARE_IN_LOCAL_SAVE_PLAN_LIST); plansource->next_saved = u_sess->pcache_cxt.first_saved_plan; u_sess->pcache_cxt.first_saved_plan = plansource; } else if (plansource->gplan == NULL && plansource->cplan == NULL && !has_lp) { - /* get commit before create cachedplan or lp, not init gpckey. keep in first_saved_plan */ + // 瀵逛簬涓嶅叿澶 gplan 鎴 cplan锛屼笖闈炶交閲忕骇浠g悊璁″垝鐨勮鍒掞紝灏嗗叾淇濆瓨鍒 first_saved_plan 鍒楄〃涓 plansource->is_saved = true; - Assert (plansource->gpc.status.IsSharePlan()); + Assert(plansource->gpc.status.IsSharePlan()); plansource->gpc.status.SetLoc(GPC_SHARE_IN_LOCAL_SAVE_PLAN_LIST); plansource->next_saved = u_sess->pcache_cxt.first_saved_plan; u_sess->pcache_cxt.first_saved_plan = plansource; } else { + // 鍏朵粬鎯呭喌锛屾牴鎹槸鍚︽湁 SPI 绛惧悕绛夋儏鍐佃繘琛屽鐞 if (plansource->spi_signature.spi_key != INVALID_SPI_KEY) { Assert(!has_lp); Assert(plansource->gplan); Assert(plansource->is_support_gplan); - g_instance.plan_cache->SPICommit(plansource); + g_instance.plan_cache->SPICommit(plansource); // 淇濆瓨涓 SPI 璁″垝 } else { - PreparedStatement* ps = FetchPreparedStatement(plansource->stmt_name, true, false); + PreparedStatement *ps = FetchPreparedStatement(plansource->stmt_name, true, false); if (unlikely(ps == NULL)) { #ifdef MEMORY_CONTEXT_CHECKING ereport(PANIC, @@ -841,42 +1057,57 @@ void GlobalPlanCache::CNCommit() (errcode(ERRCODE_UNDEFINED_PSTATEMENT), errmsg("In gpc commit stage, fail to fetch prepare statement:%s", plansource->stmt_name))); } - TryStore(plansource, ps); + TryStore(plansource, ps); // 灏濊瘯瀛樺偍涓哄叏灞璁″垝缂撳瓨 } } plansource = next_plansource; } } - -void GlobalPlanCache::SPITryStore(CachedPlanSource* plansource, SPIPlanPtr spiplan, int nth) +/* + * 鍔熻兘锛氬皾璇曞皢璁″垝婧愬瓨鍌ㄥ埌鍏ㄥ眬璁″垝缂撳瓨涓 + * + * 鍙傛暟鍒楄〃锛 + * plansource锛氬緟瀛樺偍鐨勮鍒掓簮 + * spiplan锛歋PI 璁″垝 + * nth锛歋PI 璁″垝鍒楄〃涓殑绱㈠紩 + * + * 娉ㄦ剰锛 + * 鍑芥暟棣栧厛杩涜涓绯诲垪鏂█鏉ョ‘淇濆弬鏁板拰鐘舵佺殑鏈夋晥鎬с + * 鐒跺悗锛岃绠楄鍒掓簮鐨勫搱甯屽硷紙hashCode锛夛紝浠ュ強纭畾瀛樺偍妗剁殑绱㈠紩锛坆ucket_id锛夊拰閿佺殑鏍囪瘑锛坙ock_id锛夈 + * 鎺ョ潃锛屽嚱鏁拌幏鍙栭攣骞跺垏鎹㈠唴瀛樹笂涓嬫枃銆 + * 瀹冩鏌ユ槸鍚﹀湪鍏ㄥ眬璁″垝缂撳瓨涓壘鍒颁簡涓庤鍒掓簮鍖归厤鐨勮鍒掞紙found 鍙橀噺锛夈 + * 濡傛灉娌℃湁鎵惧埌鍖归厤鐨勮鍒掞紝鍒欏皢璁″垝婧愬瓨鍌ㄥ埌鍏ㄥ眬璁″垝缂撳瓨涓 + * 濡傛灉鎵惧埌浜嗗尮閰嶇殑璁″垝锛屽垯灏嗚鍒掓簮鏇挎崲涓哄尮閰嶈鍒掞紝骞跺皢鍘熻鍒掓簮浠庣紦瀛樹腑绉婚櫎銆 + * 鏈鍚庯紝鍑芥暟閲婃斁閿佸苟鍒囨崲鍥炲師鏉ョ殑鍐呭瓨涓婁笅鏂囥 + */ +void GlobalPlanCache::SPITryStore(CachedPlanSource *plansource, SPIPlanPtr spiplan, int nth) { - Assert (plansource != NULL); - Assert (plansource->magic == CACHEDPLANSOURCE_MAGIC); - Assert (!plansource->gpc.status.InShareTable()); - Assert (plansource->gpc.status.IsSharePlan()); - Assert (spiplan->saved); + Assert(plansource != NULL); + Assert(plansource->magic == CACHEDPLANSOURCE_MAGIC); + Assert(!plansource->gpc.status.InShareTable()); + Assert(plansource->gpc.status.IsSharePlan()); + Assert(spiplan->saved); - GPCKey* key = plansource->gpc.key; + GPCKey *key = plansource->gpc.key; - uint32 hashCode = GPCHashFunc((const void *) key, sizeof(*key)); + uint32 hashCode = GPCHashFunc((const void *)key, sizeof(*key)); uint32 bucket_id = GetBucket(hashCode); - Assert (bucket_id >= 0 && bucket_id < GPC_NUM_OF_BUCKETS); + Assert(bucket_id >= 0 && bucket_id < GPC_NUM_OF_BUCKETS); int lock_id = m_array[bucket_id].lockId; (void)LWLockAcquire(GetMainLWLockByIndex(lock_id), LW_EXCLUSIVE); MemoryContext oldcontext = MemoryContextSwitchTo(m_array[bucket_id].context); bool found = false; - GPCEntry *entry = (GPCEntry *)hash_search_with_hash_value(m_array[bucket_id].hash_tbl, - (const void*)key, hashCode, HASH_ENTER, &found); + GPCEntry *entry = (GPCEntry *)hash_search_with_hash_value(m_array[bucket_id].hash_tbl, (const void *)key, hashCode, + HASH_ENTER, &found); if (entry == NULL) { MemoryContextSwitchTo(oldcontext); LWLockRelease(GetMainLWLockByIndex(lock_id)); - ereport(ERROR, - (errcode(ERRCODE_UNDEFINED_PSTATEMENT), - errmsg("store global plan source failed due to memory allocation failed"))); + ereport(ERROR, (errcode(ERRCODE_UNDEFINED_PSTATEMENT), + errmsg("store global plan source failed due to memory allocation failed"))); } if (found == false) { @@ -886,14 +1117,14 @@ void GlobalPlanCache::SPITryStore(CachedPlanSource* plansource, SPIPlanPtr spipl entry->key.spi_signature = key->spi_signature; /* Set the magic number. */ entry->val.plansource = plansource; - //off the link + // off the link plansource->next_saved = NULL; INSTR_TIME_SET_CURRENT(entry->val.last_use_time); - //initialize the ref count . + // initialize the ref count . plansource->gpc.status.AddRefcount(); m_array[bucket_id].count++; - pg_atomic_fetch_add_u32((volatile uint32*)&plansource->gplan->global_refcount, 1); + pg_atomic_fetch_add_u32((volatile uint32 *)&plansource->gplan->global_refcount, 1); plansource->gplan->is_share = true; Assert(plansource->context->is_shared); MemoryContextSeal(plansource->context); @@ -904,10 +1135,10 @@ void GlobalPlanCache::SPITryStore(CachedPlanSource* plansource, SPIPlanPtr spipl plansource->gpc.status.SetLoc(GPC_SHARE_IN_SHARE_TABLE); } else { - //some guys win. - CachedPlanSource* newsource = entry->val.plansource; - ListCell* n_cell = list_nth_cell(spiplan->plancache_list, nth); - n_cell->data.ptr_value = (void*)newsource; + // some guys win. + CachedPlanSource *newsource = entry->val.plansource; + ListCell *n_cell = list_nth_cell(spiplan->plancache_list, nth); + n_cell->data.ptr_value = (void *)newsource; newsource->gpc.status.AddRefcount(); // purge old one. @@ -919,17 +1150,31 @@ void GlobalPlanCache::SPITryStore(CachedPlanSource* plansource, SPIPlanPtr spipl MemoryContextSwitchTo(oldcontext); LWLockRelease(GetMainLWLockByIndex(lock_id)); } - -void GlobalPlanCache::SPICommit(CachedPlanSource* plansource) +/* + * Commit a SPI plan to the Global Plan Cache. + * + * Parameters: + * - plansource: The CachedPlanSource to commit. + * + * Functionality: + * - This function commits a SPI plan to the Global Plan Cache. + * - It first checks various assertions to ensure the validity of parameters and states. + * - Then, it looks up the SPI plan in the SPIPlanCacheTable. + * - If found, it iterates through the SPI plan list and tries to store the plansource. + * - If it successfully stores the plansource, it sets the 'has_cachedplan' flag to true. + * - If it fails to find a matching plan or storing fails, it reports an error. + * - Finally, it performs additional assertions to check the consistency of the SPI plans. + */ +void GlobalPlanCache::SPICommit(CachedPlanSource *plansource) { - Assert (u_sess->SPI_cxt.SPICacheTable != NULL); - plpgsql_SPIPlanCacheEnt* entry = SPIPlanCacheTableLookup(plansource->spi_signature.spi_key); + Assert(u_sess->SPI_cxt.SPICacheTable != NULL); + plpgsql_SPIPlanCacheEnt *entry = SPIPlanCacheTableLookup(plansource->spi_signature.spi_key); Assert(entry != NULL); Assert(entry->func_oid != InvalidOid); - List* spiplan_list = entry->SPIplan_list; - ListCell* cell = NULL; + List *spiplan_list = entry->SPIplan_list; + ListCell *cell = NULL; bool has_cachedplan = false; - foreach(cell, spiplan_list) { + foreach (cell, spiplan_list) { SPIPlanPtr spi_plan = (SPIPlanPtr)lfirst(cell); if (spi_plan->id == plansource->spi_signature.spi_id) { SPITryStore(plansource, spi_plan, plansource->spi_signature.plansource_id); @@ -950,13 +1195,13 @@ void GlobalPlanCache::SPICommit(CachedPlanSource* plansource) } #ifdef USE_ASSERT_CHECKING - foreach(cell, spiplan_list) { + foreach (cell, spiplan_list) { SPIPlanPtr spi_plan = (SPIPlanPtr)lfirst(cell); - ListCell* cl = NULL; + ListCell *cl = NULL; if (list_length(spi_plan->plancache_list) == 0) continue; - foreach(cl, spi_plan->plancache_list) { - CachedPlanSource *cur = (CachedPlanSource*)(cl->data.ptr_value); + foreach (cl, spi_plan->plancache_list) { + CachedPlanSource *cur = (CachedPlanSource *)(cl->data.ptr_value); Assert(cur->magic == CACHEDPLANSOURCE_MAGIC); } } @@ -965,18 +1210,18 @@ void GlobalPlanCache::SPICommit(CachedPlanSource* plansource) void GlobalPlanCache::RemovePlanCacheInSPIPlan(SPIPlanPtr plan) { - Assert (plan->magic == _SPI_PLAN_MAGIC); + Assert(plan->magic == _SPI_PLAN_MAGIC); if (list_length(plan->plancache_list) > 0) { - ListCell* cell = NULL; - foreach(cell, plan->plancache_list) { - CachedPlanSource* plansource = (CachedPlanSource*)lfirst(cell); + ListCell *cell = NULL; + foreach (cell, plan->plancache_list) { + CachedPlanSource *plansource = (CachedPlanSource *)lfirst(cell); if (plansource->gpc.status.InShareTable()) { Assert(plan->saved); CN_GPC_LOG("drop shared spi plan, subrefcount", plansource, 0); /* move plansource into invalid list if during delet func */ if (u_sess->plsql_cxt.is_delete_function) { - GPCKey* gpckey = plansource->gpc.key; - uint32 hashCode = GPCHashFunc((const void *) gpckey, sizeof(*gpckey)); + GPCKey *gpckey = plansource->gpc.key; + uint32 hashCode = GPCHashFunc((const void *)gpckey, sizeof(*gpckey)); uint32 bucket_id = GetBucket(hashCode); int lock_id = m_array[bucket_id].lockId; (void)LWLockAcquire(GetMainLWLockByIndex(lock_id), LW_EXCLUSIVE); @@ -1005,11 +1250,10 @@ void GlobalPlanCache::RemovePlanCacheInSPIPlan(SPIPlanPtr plan) void GlobalPlanCache::CleanUpByTime() { List *gpckey_list = NULL; - const int maxlen_gpckey_list = 100; + const int maxlen_gpckey_list = 100; instr_time curTime; INSTR_TIME_SET_CURRENT(curTime); - for (uint32 bucket_id = 0; bucket_id < GPC_NUM_OF_BUCKETS; bucket_id++) - { + for (uint32 bucket_id = 0; bucket_id < GPC_NUM_OF_BUCKETS; bucket_id++) { int lock_id = m_array[bucket_id].lockId; /* Step 1: Try to find the code plan cache */ @@ -1020,10 +1264,10 @@ void GlobalPlanCache::CleanUpByTime() } HASH_SEQ_STATUS hash_seq; GPCEntry *entry = NULL; - CachedPlanSource* cur_plansource = NULL; + CachedPlanSource *cur_plansource = NULL; hash_seq_init(&hash_seq, m_array[bucket_id].hash_tbl); - while ((entry = (GPCEntry*)hash_seq_search(&hash_seq)) != NULL) { + while ((entry = (GPCEntry *)hash_seq_search(&hash_seq)) != NULL) { if (entry->val.used_count > 0) { entry->val.last_use_time = curTime; entry->val.used_count = 0; @@ -1032,8 +1276,8 @@ void GlobalPlanCache::CleanUpByTime() cur_plansource = entry->val.plansource; if (cur_plansource->gpc.status.RefCountZero() && INSTR_TIME_GET_DOUBLE(curTime) - INSTR_TIME_GET_DOUBLE(entry->val.last_use_time) > - u_sess->attr.attr_common.gpc_clean_timeout) { - GPCKey *dest_gpckey = (GPCKey *)palloc(sizeof(GPCKey)); + u_sess->attr.attr_common.gpc_clean_timeout) { + GPCKey *dest_gpckey = (GPCKey *)palloc(sizeof(GPCKey)); GPCKeyDeepCopy(&entry->key, dest_gpckey); gpckey_list = lappend(gpckey_list, dest_gpckey); @@ -1049,25 +1293,25 @@ void GlobalPlanCache::CleanUpByTime() /* Step 2: Try to remove plan cache */ if (gpckey_list && list_length(gpckey_list) > 0) { LWLockAcquire(GetMainLWLockByIndex(lock_id), LW_EXCLUSIVE); - ListCell* l = NULL; - foreach(l, gpckey_list) { + ListCell *l = NULL; + foreach (l, gpckey_list) { bool found = false; - GPCKey *key = (GPCKey *)lfirst(l); + GPCKey *key = (GPCKey *)lfirst(l); GPCEntry *entry = NULL; entry = (GPCEntry *)hash_search(m_array[bucket_id].hash_tbl, (void *)key, HASH_FIND, &found); if (entry) { cur_plansource = entry->val.plansource; if (cur_plansource->gpc.status.RefCountZero() && INSTR_TIME_GET_DOUBLE(curTime) - INSTR_TIME_GET_DOUBLE(entry->val.last_use_time) > - u_sess->attr.attr_common.gpc_clean_timeout) { + u_sess->attr.attr_common.gpc_clean_timeout) { GPC_LOG("drop shared plancache by time", cur_plansource, cur_plansource->stmt_name); DropCachedPlanInternal(cur_plansource); - hash_search(m_array[bucket_id].hash_tbl, (void *) key, HASH_REMOVE, &found); + hash_search(m_array[bucket_id].hash_tbl, (void *)key, HASH_REMOVE, &found); cur_plansource->magic = 0; MemoryContextUnSeal(cur_plansource->context); MemoryContextUnSeal(cur_plansource->query_context); if (cur_plansource->opFusionObj) { - OpFusion::DropGlobalOpfusion((OpFusion*)(cur_plansource->opFusionObj)); + OpFusion::DropGlobalOpfusion((OpFusion *)(cur_plansource->opFusionObj)); } MemoryContextDelete(cur_plansource->context); m_array[bucket_id].count--; @@ -1086,7 +1330,7 @@ void GlobalPlanCache::CleanUpByTime() } } -void CleanSessGPCPtr(knl_session_context* currentSession) +void CleanSessGPCPtr(knl_session_context *currentSession) { CachedPlanSource *psrc = currentSession->pcache_cxt.cur_stmt_psrc; currentSession->pcache_cxt.cur_stmt_psrc = NULL; @@ -1100,7 +1344,7 @@ void CleanSessGPCPtr(knl_session_context* currentSession) elog(PANIC, "wrong refcount"); } -void CleanSessionGPCDetach(knl_session_context* currentSession) +void CleanSessionGPCDetach(knl_session_context *currentSession) { if (IS_PGXC_COORDINATOR) return; @@ -1108,15 +1352,15 @@ void CleanSessionGPCDetach(knl_session_context* currentSession) elog(PANIC, "session's cur_stmt_psrc should be null when detach"); } - CachedPlanSource* plansource = currentSession->pcache_cxt.first_saved_plan; + CachedPlanSource *plansource = currentSession->pcache_cxt.first_saved_plan; while (plansource != NULL) { /* * When turing on the enable_global_plancache, there are some cases that * we cannot insert the plancache in the shared HTAB. No Prepare Statement - * on DN, so we can just drop shared plan and wait for next parse message + * on DN, so we can just drop shared plan and wait for next parse message * to create it again. */ - CachedPlanSource* next_plansource = plansource->next_saved; + CachedPlanSource *next_plansource = plansource->next_saved; if (plansource->gpc.status.IsPrivatePlan()) { /* private plan has reference on pointer like unname_stmt_psrc or spiplan */ GPC_LOG("invalid plan in sess detach", plansource, plansource->stmt_name); @@ -1133,4 +1377,3 @@ void CleanSessionGPCDetach(knl_session_context* currentSession) currentSession->pcache_cxt.first_saved_plan = NULL; currentSession->pcache_cxt.gpc_in_ddl = false; } - diff --git a/src/gausskernel/process/globalplancache/globalplancache_inval.cpp b/src/gausskernel/process/globalplancache/globalplancache_inval.cpp index 9c2568249..b2d5adc23 100644 --- a/src/gausskernel/process/globalplancache/globalplancache_inval.cpp +++ b/src/gausskernel/process/globalplancache/globalplancache_inval.cpp @@ -38,63 +38,102 @@ #include "utils/plancache.h" #include "utils/syscache.h" +/* + * 鍔熻兘锛氭鏌ュ叡浜紦瀛樺け鏁堟秷鎭槸鍚︾鍚堟潯浠 + * + * 鍙傛暟鍒楄〃锛 + * msg锛氭寚鍚 SharedInvalidationMessage 缁撴瀯鐨勬寚閽堬紝琛ㄧず鍏变韩缂撳瓨澶辨晥娑堟伅 + * + * 杩斿洖鍊硷細 + * 濡傛灉鍏变韩缂撳瓨澶辨晥娑堟伅绗﹀悎鏉′欢锛岃繑鍥 true锛涘惁鍒欒繑鍥 false + */ bool GlobalPlanCache::MsgCheck(const SharedInvalidationMessage *msg) { if (msg->id >= 0) { + // 濡傛灉娑堟伅鐨 id 澶т簬绛変簬 0 if (msg->cc.id == PROCOID || msg->cc.id == NAMESPACEOID || msg->cc.id == OPEROID || msg->cc.id == AMOPOPID) { + // 濡傛灉娑堟伅鐨 cc.id 鏄 PROCOID銆丯AMESPACEOID銆丱POID 鎴 AMOPOPID 涓殑浠讳綍涓涓紝杩斿洖 true return true; } } else if (msg->id == SHAREDINVALRELCACHE_ID || msg->id == SHAREDINVALPARTCACHE_ID) { + // 濡傛灉娑堟伅鐨 id 鏄 SHAREDINVALRELCACHE_ID 鎴 SHAREDINVALPARTCACHE_ID锛岃繑鍥 true return true; } - + // 濡傛灉浠ヤ笂鏉′欢閮戒笉婊¤冻锛岃繑鍥 false return false; } - -bool GlobalPlanCache::NeedDropEntryByLocalMsg(CachedPlanSource* plansource, int tot, const int *idx, const SharedInvalidationMessage *msgs) +/* + * 鍔熻兘锛氭牴鎹湰鍦板け鏁堟秷鎭垽鏂槸鍚﹂渶瑕佷涪寮冭鍒掔紦瀛橀」 + * + * 鍙傛暟鍒楄〃锛 + * plansource锛氭寚鍚 CachedPlanSource 缁撴瀯鐨勬寚閽堬紝琛ㄧず璁″垝婧愬璞 + * tot锛氬け鏁堟秷鎭殑鎬绘暟 + * idx锛氬け鏁堟秷鎭殑绱㈠紩鏁扮粍 + * msgs锛氭寚鍚 SharedInvalidationMessage 缁撴瀯鐨勬寚閽堬紝琛ㄧず澶辨晥娑堟伅鏁扮粍 + * + * 杩斿洖鍊硷細 + * 濡傛灉闇瑕佷涪寮冭鍒掔紦瀛橀」锛岃繑鍥 true锛涘惁鍒欒繑鍥 false + */ +bool GlobalPlanCache::NeedDropEntryByLocalMsg(CachedPlanSource *plansource, int tot, const int *idx, + const SharedInvalidationMessage *msgs) { + // 鑾峰彇璁″垝婧愬璞℃墍灞炵殑鏁版嵁搴 ID Oid database_id = plansource->gpc.key->env.plainenv.database_id; for (int j = 0; j < tot; j++) { const SharedInvalidationMessage *msg = &msgs[idx[j]]; + // 濡傛灉璁″垝婧愬璞″叿鏈夊師濮嬭В鏋愭爲锛屽苟涓斿師濮嬭В鏋愭爲鐨勭被鍨嬫槸 TransactionStmt锛屽垯璺宠繃璇ユ秷鎭殑澶勭悊 if ((plansource)->raw_parse_tree && IsA((plansource)->raw_parse_tree, TransactionStmt)) continue; if (msg->id >= 0) { - + // 濡傛灉娑堟伅鐨 id 澶т簬绛変簬 0 if (msg->cc.dbId == database_id || msg->cc.dbId == InvalidOid) { if (msg->cc.id == PROCOID) { + // 妫鏌ヨ鍒掔紦瀛橀」鐨勫け鏁堥」渚濊禆鎬э紝骞舵洿鏂 CheckInvalItemDependency(plansource, msg->cc.id, msg->cc.hashValue); } else if (msg->cc.id == NAMESPACEOID || msg->cc.id == OPEROID || msg->cc.id == AMOPOPID) { + // 閲嶇疆璁″垝缂撳瓨椤 ResetPlanCache(plansource); } } } else if (msg->id == SHAREDINVALRELCACHE_ID) { - if (msg->rc.dbId == database_id || msg->rc.dbId == InvalidOid) - { + // 濡傛灉娑堟伅鐨 id 鏄 SHAREDINVALRELCACHE_ID + if (msg->rc.dbId == database_id || msg->rc.dbId == InvalidOid) { + // 妫鏌ヨ鍒掔紦瀛橀」涓庡叧绯讳緷璧栨э紝骞舵洿鏂 CheckRelDependency(plansource, msg->rc.relId); } } else if (msg->id == SHAREDINVALPARTCACHE_ID) { + // 濡傛灉娑堟伅鐨 id 鏄 SHAREDINVALPARTCACHE_ID if (msg->pc.dbId == database_id || msg->pc.dbId == InvalidOid) { + // 妫鏌ヨ鍒掔紦瀛橀」涓庡垎鍖轰緷璧栨э紝骞舵洿鏂 CheckRelDependency(plansource, msg->pc.partId); } } + // 濡傛灉璁″垝婧愬璞¢渶瑕佷涪寮冨叡浜 GPC锛屽垯杩斿洖 true if (plansource->gpc.status.NeedDropSharedGPC()) { return true; } } + // 濡傛灉涓嶉渶瑕佷涪寮冭鍒掔紦瀛橀」锛岃繑鍥 false return false; - - } - +/* + * 鍔熻兘锛氭牴鎹け鏁堟秷鎭繘琛岃鍒掔紦瀛橀」鐨勫け鏁堝鐞 + * + * 鍙傛暟鍒楄〃锛 + * msgs锛氭寚鍚 SharedInvalidationMessage 缁撴瀯鐨勬寚閽堬紝琛ㄧず澶辨晥娑堟伅鏁扮粍 + * n锛氬け鏁堟秷鎭殑鏁伴噺 + */ void GlobalPlanCache::InvalMsg(const SharedInvalidationMessage *msgs, int n) { - int *idx = (int *)palloc0(n * sizeof(int)); - int tot = 0; + // 鍒嗛厤骞跺垵濮嬪寲涓涓储寮曟暟缁 + int *idx = (int *)palloc0(n * sizeof(int)); + int tot = 0; + // 閬嶅巻澶辨晥娑堟伅鏁扮粍锛岀瓫閫夊嚭闇瑕佸鐞嗙殑娑堟伅 for (int i = 0; i < n; i++) { const SharedInvalidationMessage *msg = &msgs[i]; @@ -103,20 +142,21 @@ void GlobalPlanCache::InvalMsg(const SharedInvalidationMessage *msgs, int n) } } + // 濡傛灉娌℃湁闇瑕佸鐞嗙殑娑堟伅锛岄噴鏀剧储寮曟暟缁勫苟杩斿洖 if (tot == 0) { pfree_ext(idx); - return ; + return; } /* Go through each bucket in the GPC HTAB and do some invalidation depending on the GPCInvalInfo we got.*/ - for (uint32 bucket_id = 0; bucket_id < GPC_NUM_OF_BUCKETS; bucket_id ++) { + for (uint32 bucket_id = 0; bucket_id < GPC_NUM_OF_BUCKETS; bucket_id++) { /* Ok so bucket is not empty. Get the bucket S-lock so we can iterate through it. */ int lock_id = m_array[bucket_id].lockId; LWLockAcquire(GetMainLWLockByIndex(lock_id), LW_EXCLUSIVE); MemoryContext oldcontext = MemoryContextSwitchTo(m_array[bucket_id].context); - - /* Check the number of entries in the bucket again. - * GPC Eviction might have removed the last entry while we were waiting for the shared lock. */ + + /* Check the number of entries in the bucket again. + * GPC Eviction might have removed the last entry while we were waiting for the shared lock. */ int bucketEntriesCount = m_array[bucket_id].count; if (0 == bucketEntriesCount) { MemoryContextSwitchTo(oldcontext); @@ -129,7 +169,7 @@ void GlobalPlanCache::InvalMsg(const SharedInvalidationMessage *msgs, int n) GPCEntry *entry = NULL; while ((entry = (GPCEntry *)hash_seq_search(&hash_seq)) != NULL) { - Assert (entry->val.plansource != NULL); + Assert(entry->val.plansource != NULL); /* for standby mode, Invalid Msg send by xlog thread, but xlog thread didn't set db id into MyDatabaseId. So we need check each plan's db id by gpc'key in NeedDropEntryByLocalMsg latter */ if (pmState == PM_RUN && @@ -138,7 +178,7 @@ void GlobalPlanCache::InvalMsg(const SharedInvalidationMessage *msgs, int n) } /* Atomic read the number of CachedEnvironment in this entry */ - if(NeedDropEntryByLocalMsg(entry->val.plansource, tot, idx, msgs)) { + if (NeedDropEntryByLocalMsg(entry->val.plansource, tot, idx, msgs)) { RemoveEntry(bucket_id, entry); } } @@ -147,5 +187,6 @@ void GlobalPlanCache::InvalMsg(const SharedInvalidationMessage *msgs, int n) LWLockRelease(GetMainLWLockByIndex(lock_id)); } + // 閲婃斁绱㈠紩鏁扮粍 pfree_ext(idx); } diff --git a/src/gausskernel/process/globalplancache/globalplancache_util.cpp b/src/gausskernel/process/globalplancache/globalplancache_util.cpp index b3c0927cf..f8e8c9462 100644 --- a/src/gausskernel/process/globalplancache/globalplancache_util.cpp +++ b/src/gausskernel/process/globalplancache/globalplancache_util.cpp @@ -1,26 +1,26 @@ /* -* Copyright (c) 2020 Huawei Technologies Co.,Ltd. -* -* openGauss is licensed under Mulan PSL v2. -* You can use this software according to the terms and conditions of the Mulan PSL v2. -* You may obtain a copy of Mulan PSL v2 at: -* -* http://license.coscl.org.cn/MulanPSL2 -* -* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, -* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, -* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. -* See the Mulan PSL v2 for more details. -* ------------------------------------------------------------------------- -* -* globalplancache_util.cpp -* global plan cache -* -* IDENTIFICATION -* src/gausskernel/process/globalplancache/globalplancache_util.cpp -* -* ------------------------------------------------------------------------- -*/ + * Copyright (c) 2020 Huawei Technologies Co.,Ltd. + * + * openGauss is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * + * http://license.coscl.org.cn/MulanPSL2 + * + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + * ------------------------------------------------------------------------- + * + * globalplancache_util.cpp + * global plan cache + * + * IDENTIFICATION + * src/gausskernel/process/globalplancache/globalplancache_util.cpp + * + * ------------------------------------------------------------------------- + */ #include "postgres.h" #include "knl/knl_variable.h" @@ -38,10 +38,17 @@ #include "utils/memutils.h" #include "utils/plancache.h" #include "utils/syscache.h" -void -GlobalPlanCache::FillClassicEnvSignatures(GPCEnv *env) +/* + * 鍔熻兘锛氬~鍏呯粡鍏哥幆澧冪鍚 + * + * 鍙傛暟鍒楄〃锛 + * env锛氭寚鍚 GPCEnv 缁撴瀯鐨勬寚閽堬紝琛ㄧず鐜閰嶇疆淇℃伅 + */ +void GlobalPlanCache::FillClassicEnvSignatures(GPCEnv *env) { + // 鍒濆鍖栫幆澧冪鍚嶄负0 env->plainenv.env_signature = 0; + // 閫愪釜璁剧疆鐜绛惧悕鐨勫悇浣嶏紝姣忎竴浣嶈〃绀轰竴涓幆澧冮厤缃殑寮鍏崇姸鎬 env->plainenv.env_signature |= u_sess->attr.attr_sql.enable_fast_numeric; env->plainenv.env_signature |= u_sess->attr.attr_sql.enable_global_stats << 1; env->plainenv.env_signature |= u_sess->attr.attr_sql.enable_hdfs_predicate_pushdown << 2; @@ -74,17 +81,14 @@ GlobalPlanCache::FillClassicEnvSignatures(GPCEnv *env) env->plainenv.env_signature |= g_instance.attr.attr_sql.enable_orc_cache << 29; env->plainenv.env_signature |= u_sess->attr.attr_sql.acceleration_with_compute_pool << 30; env->plainenv.env_signature |= u_sess->attr.attr_sql.enable_extrapolation_stats << 31; - } - /* * @Description:Fill in the environment signatures which are bitmaps for the boolean type GUC parameters * @in num: GPCEnv * @return - void -*/ -void -GlobalPlanCache::FillEnvSignatures(GPCEnv *env) + */ +void GlobalPlanCache::FillEnvSignatures(GPCEnv *env) { /* We should only call this function if env is not NULL and it's not filled */ Assert(env && !env->filled); @@ -126,19 +130,27 @@ GlobalPlanCache::FillEnvSignatures(GPCEnv *env) env->plainenv.env_signature2 |= u_sess->attr.attr_sql.enable_opfusion << 17; env->plainenv.env_signature2 |= u_sess->attr.attr_sql.enable_partition_opfusion << 18; } - -void -GlobalPlanCache::EnvFill(GPCEnv *env, bool depends_on_role) +/* + * 鍔熻兘锛氬~鍏呯幆澧冧俊鎭 + * + * 鍙傛暟鍒楄〃锛 + * env锛氭寚鍚 GPCEnv 缁撴瀯鐨勬寚閽堬紝琛ㄧず鐜閰嶇疆淇℃伅 + * depends_on_role锛氬竷灏斿硷紝琛ㄧず鏄惁渚濊禆浜庤鑹 + */ +void GlobalPlanCache::EnvFill(GPCEnv *env, bool depends_on_role) { /* We should only call this function if env is not NULL and it's not filled */ + // 鏂█锛氱‘淇 env 涓嶄负 NULL锛屼笖鏈濉厖杩 Assert(env && !env->filled); - + // 鍒濆鍖 env 涓0 errno_t rc = memset_s(env, sizeof(GPCEnv), 0, sizeof(GPCEnv)); securec_check(rc, "\0", "\0"); + // 濉厖鐜绛惧悕 FillEnvSignatures(env); + // 閫愪釜璁剧疆鐜閰嶇疆鍙傛暟 env->plainenv.best_agg_plan = u_sess->attr.attr_sql.best_agg_plan; env->plainenv.query_dop_tmp = u_sess->attr.attr_sql.query_dop_tmp; env->plainenv.rewrite_rule = u_sess->attr.attr_sql.rewrite_rule; @@ -174,46 +186,47 @@ GlobalPlanCache::EnvFill(GPCEnv *env, bool depends_on_role) env->plainenv.sql_beta_feature = u_sess->attr.attr_sql.sql_beta_feature; /* new GUC parameters which affect the plan */ + // 濉厖鏂扮殑 GUC 鍙傛暟 env->plainenv.qrw_inlist2join_optmode = u_sess->opt_cxt.qrw_inlist2join_optmode; env->plainenv.skew_strategy_store = u_sess->attr.attr_sql.skew_strategy_store; env->plainenv.database_id = u_sess->proc_cxt.MyDatabaseId; env->plainenv.plancachemode = u_sess->attr.attr_sql.g_planCacheMode; GlobalPlanCache::GetSchemaName(env); - + // 濉厖棰勬湡鐨勮绠楄妭鐐圭粍鍜岄粯璁ょ殑瀛樺偍鑺傜偣缁 if (u_sess->attr.attr_sql.expected_computing_nodegroup) { - int rc = memcpy_s(env->expected_computing_nodegroup, - NAMEDATALEN, - u_sess->attr.attr_sql.expected_computing_nodegroup, - strlen(u_sess->attr.attr_sql.expected_computing_nodegroup)); + int rc = + memcpy_s(env->expected_computing_nodegroup, NAMEDATALEN, u_sess->attr.attr_sql.expected_computing_nodegroup, + strlen(u_sess->attr.attr_sql.expected_computing_nodegroup)); securec_check(rc, "", ""); } else { - env->expected_computing_nodegroup[0] = '\0'; + env->expected_computing_nodegroup[0] = '\0'; } if (u_sess->attr.attr_sql.default_storage_nodegroup) { - int rc = memcpy_s(env->default_storage_nodegroup, - NAMEDATALEN, - u_sess->attr.attr_sql.default_storage_nodegroup, - strlen(u_sess->attr.attr_sql.default_storage_nodegroup)); + int rc = memcpy_s(env->default_storage_nodegroup, NAMEDATALEN, u_sess->attr.attr_sql.default_storage_nodegroup, + strlen(u_sess->attr.attr_sql.default_storage_nodegroup)); securec_check(rc, "", ""); } else { env->default_storage_nodegroup[0] = '\0'; } + // 璁剧疆渚濊禆瑙掕壊淇℃伅鍜岀敤鎴 ID env->depends_on_role = depends_on_role; env->user_oid = GetUserId(); } - -void -GlobalPlanCache::GetSchemaName(GPCEnv *env) +/* + * 鍔熻兘锛氳幏鍙栧綋鍓嶆ā寮忕殑妯″紡鍚嶇О + * + * 鍙傛暟鍒楄〃锛 + * env锛氭寚鍚 GPCEnv 缁撴瀯鐨勬寚閽堬紝琛ㄧず鐜閰嶇疆淇℃伅 + */ +void GlobalPlanCache::GetSchemaName(GPCEnv *env) { /* get schema name */ if (u_sess->attr.attr_common.namespace_current_schema) { - int rc = memcpy_s(env->schema_name, - NAMEDATALEN, - u_sess->attr.attr_common.namespace_current_schema, + int rc = memcpy_s(env->schema_name, NAMEDATALEN, u_sess->attr.attr_common.namespace_current_schema, strlen(u_sess->attr.attr_common.namespace_current_schema)); securec_check(rc, "", ""); } else { @@ -221,46 +234,77 @@ GlobalPlanCache::GetSchemaName(GPCEnv *env) } } - +/* + * 鍔熻兘锛氬叏灞璁″垝缂撳瓨閲嶇疆鍑芥暟 + * + * 璇存槑锛氭鍑芥暟鐢ㄤ簬閲嶇疆鍏ㄥ眬璁″垝缂撳瓨锛屽苟娓呴櫎鐩稿叧鍐呭瓨涓婁笅鏂囦腑鐨勬暟鎹 + */ void GPCResetAll() { pthread_mutex_lock(&g_instance.gpc_reset_lock); for (int i = 0; i < MAX_GLOBAL_CACHEMEM_NUM; ++i) { + // 瑙i櫎鍐呭瓨涓婁笅鏂囦腑鐨勫瓙涓婁笅鏂囧皝鍗帮紝浠ヤ究閲嶇疆 MemoryContextUnSealChildren(g_instance.cache_cxt.global_plancache_mem[i]); + // 閲嶇疆鍐呭瓨涓婁笅鏂囷紝娓呴櫎鍏朵腑鐨勬暟鎹 MemoryContextReset(g_instance.cache_cxt.global_plancache_mem[i]); } + // 鍒濆鍖栧叏灞璁″垝缂撳瓨 g_instance.plan_cache->Init(); pthread_mutex_unlock(&g_instance.gpc_reset_lock); + // 璁板綍鏃ュ織锛岃〃绀哄叏灞璁″垝缂撳瓨宸查噸缃 GPC_LOG("gpc reset all", 0, 0); } - -void GPCCleanDatanodeStatement(int dn_stmt_num, const char* stmt_name) +/* + * 鍔熻兘锛氭竻鐞嗘暟鎹妭鐐逛笂鐨勮鍙 + * + * 鍙傛暟鍒楄〃锛 + * dn_stmt_num锛氳娓呯悊鐨勮鍙ユ暟閲 + * stmt_name锛氬緟娓呯悊璇彞鐨勫悕绉 + * + * 璇存槑锛氭鍑芥暟鐢ㄤ簬娓呯悊鏁版嵁鑺傜偣涓婄殑鎸囧畾璇彞銆備粎鍦ㄥ崗璋冨櫒鑺傜偣涓旀彁渚涗簡鏈夋晥鐨勮鍙ュ悕绉版椂鎵ц銆 + */ +void GPCCleanDatanodeStatement(int dn_stmt_num, const char *stmt_name) { + // 濡傛灉璇彞鍚嶇О涓虹┖銆佷负绌哄瓧绗︿覆鎴栦笉鍦ㄥ崗璋冨櫒鑺傜偣涓婏紝鐩存帴杩斿洖 if (stmt_name == NULL || stmt_name[0] == '\0' || !IS_PGXC_COORDINATOR) return; int n = 0; char *tmp_name = NULL; + // 寰幆娓呯悊鎸囧畾鏁伴噺鐨勮鍙 for (n = 0; n < dn_stmt_num; n++) { + // 鑾峰彇褰撳墠瑕佹竻鐞嗙殑璇彞鍚嶇О tmp_name = get_datanode_statement_name(stmt_name, n); + // 璋冪敤 DropDatanodeStatement 鍑芥暟鏉ユ竻鐞嗚鍙 DropDatanodeStatement(tmp_name); + // 閲婃斁涓存椂璇彞鍚嶇О鐨勫唴瀛 pfree_ext(tmp_name); } } - -void GPCReGplan(CachedPlanSource* plansource) +/* + * 鍔熻兘锛氬皢 CachedPlanSource 鍒囨崲涓哄叏灞璁″垝锛坓plan锛 + * + * 鍙傛暟鍒楄〃锛 + * plansource锛氳鍒囨崲鐨 CachedPlanSource 瀵硅薄 + * + * 璇存槑锛氭鍑芥暟鐢ㄤ簬灏 CachedPlanSource 鍒囨崲涓哄叏灞璁″垝锛坓plan锛夈傚鏋滆璁″垝鏀寔 gplan 涓斿綋鍓嶄笉鏄叡浜姸鎬侊紝鍒欒繘琛屽垏鎹€ + * 鍒囨崲鍚庯紝灏嗚璁″垝绉诲姩鍒伴涓凡淇濆瓨鐨勮鍒掍腑锛屼互渚胯繘琛屽叏灞鍏变韩銆 + */ +void GPCReGplan(CachedPlanSource *plansource) { /* if is unshared for has cplan, and create gplan this time, * reset to shared and move to first_saved_plan */ if (!plansource->is_support_gplan || !plansource->gpc.status.IsUnShareCplan()) return; Assert(plansource->is_saved); + // 璁剧疆璁″垝涓哄叡浜姸鎬 plansource->gpc.status.SetKind(GPC_SHARED); /* move into first_saved_plan */ if (u_sess->pcache_cxt.ungpc_saved_plan == plansource) { u_sess->pcache_cxt.ungpc_saved_plan = plansource->next_saved; } else { - CachedPlanSource* psrc = NULL; + CachedPlanSource *psrc = NULL; + // 瀵绘壘骞舵洿鏂版湭鍏变韩璁″垝鍒楄〃 for (psrc = u_sess->pcache_cxt.ungpc_saved_plan; psrc; psrc = psrc->next_saved) { if (psrc->next_saved == plansource) { psrc->next_saved = plansource->next_saved; @@ -268,72 +312,104 @@ void GPCReGplan(CachedPlanSource* plansource) } } } + // 璁剧疆璁″垝鐨勪綅缃负鍦ㄦ湰鍦板凡淇濆瓨璁″垝鍒楄〃涓 plansource->gpc.status.SetLoc(GPC_SHARE_IN_LOCAL_SAVE_PLAN_LIST); + // 灏嗚鍒掔Щ鍔ㄥ埌棣栦釜宸蹭繚瀛樿鍒掍腑 plansource->next_saved = u_sess->pcache_cxt.first_saved_plan; u_sess->pcache_cxt.first_saved_plan = plansource; } - +/* + * 鍔熻兘锛氭竻鐞嗕笌浼氳瘽鐩稿叧鐨勫叏灞璁″垝缂撳瓨 + * + * 鍙傛暟鍒楄〃锛氭棤 + * + * 璇存槑锛氭鍑芥暟鐢ㄤ簬娓呯悊涓庝細璇濈浉鍏崇殑鍏ㄥ眬璁″垝缂撳瓨銆傚畠棣栧厛妫鏌ユ槸鍚﹀惎鐢ㄤ簡 CN-GPC锛堝叏灞璁″垝缂撳瓨锛夛紝 + * 濡傛灉鏈惎鐢ㄥ垯鐩存帴杩斿洖銆傜劧鍚庯紝瀹冧細鍒犻櫎鎵鏈夌殑宸茬粡鍑嗗濂界殑璇彞锛坧repared statements锛夈 + * 濡傛灉璁″垝澶勪簬鍏变韩鍐呭瓨涓紝鍒欏垹闄ゅ搴旂殑鍐呭瓨涓婁笅鏂囥 + */ void CNGPCCleanUpSession() { + // 濡傛灉鏈惎鐢 CN-GPC锛屽垯鐩存帴杩斿洖 if (!ENABLE_CN_GPC) { return; } + // 鍒犻櫎鎵鏈夊凡缁忓噯澶囧ソ鐨勮鍙 DropAllPreparedStatements(); /* if in shared memory, delete context. */ - CachedPlanSource* psrc = u_sess->pcache_cxt.ungpc_saved_plan; - CachedPlanSource* next = NULL; + CachedPlanSource *psrc = u_sess->pcache_cxt.ungpc_saved_plan; + CachedPlanSource *next = NULL; while (psrc != NULL) { next = psrc->next_saved; - Assert (!psrc->gpc.status.InShareTable()); + // 鏂█璁″垝涓嶅湪鍏变韩琛ㄤ腑 + Assert(!psrc->gpc.status.InShareTable()); + // 濡傛灉璁″垝涓嶆槸绉佹湁璁″垝锛屽垯鍒犻櫎 if (!psrc->gpc.status.IsPrivatePlan()) DropCachedPlan(psrc); psrc = next; } + // 娓呯悊宸蹭繚瀛樿鍒掑垪琛ㄤ腑鐨勮鍒 psrc = u_sess->pcache_cxt.first_saved_plan; while (psrc != NULL) { next = psrc->next_saved; - Assert (!psrc->gpc.status.InShareTable()); + // 鏂█璁″垝涓嶅湪鍏变韩琛ㄤ腑 + Assert(!psrc->gpc.status.InShareTable()); + // 濡傛灉璁″垝涓嶆槸绉佹湁璁″垝锛屽垯鍒犻櫎 if (!psrc->gpc.status.IsPrivatePlan()) DropCachedPlan(psrc); psrc = next; } } - +/* + * 鍔熻兘锛氭竻鐞嗕笌浼氳瘽鐩稿叧鐨勫凡淇濆瓨璁″垝 + * + * 鍙傛暟鍒楄〃锛氭棤 + * + * 璇存槑锛氭鍑芥暟鐢ㄤ簬娓呯悊涓庝細璇濈浉鍏崇殑宸蹭繚瀛樿鍒掋傚畠棣栧厛妫鏌ユ槸鍚﹀惎鐢ㄤ簡 GPC锛堝叏灞璁″垝缂撳瓨锛夛紝 + * 濡傛灉鏈惎鐢ㄦ垨鑰呮病鏈夐渶瑕佹竻鐞嗙殑璁″垝锛屽垯鐩存帴杩斿洖銆傜劧鍚庯紝瀹冨噺灏戞湭鍛藉悕璇彞锛坲nnamed statement锛 + * 鐨勫紩鐢ㄨ鏁帮紝濡傛灉璇ヨ鍙ュ湪鍏变韩琛ㄤ腑銆傛渶鍚庯紝瀹冩竻鐞嗗凡淇濆瓨璁″垝鍒楄〃鍜屾湭鍏变韩璁″垝鍒楄〃涓殑璁″垝锛 + * 濡傛灉杩欎簺璁″垝涓嶆槸绉佹湁璁″垝鐨勮瘽銆 + */ void GPCCleanUpSessionSavedPlan() { + // 濡傛灉鏈惎鐢 GPC 鎴栨病鏈夐渶瑕佹竻鐞嗙殑璁″垝锛屽垯鐩存帴杩斿洖 if (!ENABLE_GPC) { return; } - if (u_sess->pcache_cxt.first_saved_plan == NULL && - u_sess->pcache_cxt.unnamed_stmt_psrc == NULL && + if (u_sess->pcache_cxt.first_saved_plan == NULL && u_sess->pcache_cxt.unnamed_stmt_psrc == NULL && u_sess->pcache_cxt.ungpc_saved_plan == NULL) { return; } /* unnamed_stmt_psrc only save shared gpc plan or private plan, * so we only need to sub refcount for shared plan. */ + // 濡傛灉鏈懡鍚嶈鍙ュ瓨鍦ㄥ苟涓斿湪鍏变韩琛ㄤ腑锛屽垯鍑忓皯寮曠敤璁℃暟骞剁疆涓篘ULL if (u_sess->pcache_cxt.unnamed_stmt_psrc && u_sess->pcache_cxt.unnamed_stmt_psrc->gpc.status.InShareTable()) { u_sess->pcache_cxt.unnamed_stmt_psrc->gpc.status.SubRefCount(); u_sess->pcache_cxt.unnamed_stmt_psrc = NULL; } /* if in shared memory, delete context. */ /* For DN and CN */ - CachedPlanSource* psrc = u_sess->pcache_cxt.first_saved_plan; - CachedPlanSource* next = NULL; + CachedPlanSource *psrc = u_sess->pcache_cxt.first_saved_plan; + CachedPlanSource *next = NULL; u_sess->pcache_cxt.first_saved_plan = NULL; while (psrc != NULL) { next = psrc->next_saved; - Assert (!psrc->gpc.status.InShareTable()); + // 鏂█璁″垝涓嶅湪鍏变韩琛ㄤ腑 + Assert(!psrc->gpc.status.InShareTable()); + // 濡傛灉璁″垝涓嶆槸绉佹湁璁″垝锛屽垯鍒犻櫎 if (!psrc->gpc.status.IsPrivatePlan()) DropCachedPlan(psrc); psrc = next; } /* For CN */ + // 娓呯悊鏈叡浜鍒掑垪琛紙For CN锛 psrc = u_sess->pcache_cxt.ungpc_saved_plan; next = NULL; while (psrc != NULL) { next = psrc->next_saved; - Assert (!psrc->gpc.status.InShareTable()); + // 鏂█璁″垝涓嶅湪鍏变韩琛ㄤ腑 + Assert(!psrc->gpc.status.InShareTable()); + // 濡傛灉璁″垝涓嶆槸绉佹湁璁″垝锛屽垯鍒犻櫎 if (!psrc->gpc.status.IsPrivatePlan()) DropCachedPlan(psrc); psrc = next; @@ -341,75 +417,128 @@ void GPCCleanUpSessionSavedPlan() } /* incase change shared plan in execute stage, copy stmt into sess */ -List* CopyLocalStmt(const List* stmt_list, const MemoryContext parent_cxt, MemoryContext* plan_context) +/* + * 鍔熻兘锛氬鍒舵湰鍦拌鍙ュ垪琛 + * + * 鍙傛暟鍒楄〃锛 + * stmt_list锛氬緟澶嶅埗鐨勬湰鍦拌鍙ュ垪琛 + * parent_cxt锛氱埗鍐呭瓨涓婁笅鏂囷紝鏂板垱寤虹殑鍐呭瓨涓婁笅鏂囧皢浠ュ叾涓虹埗涓婁笅鏂 + * plan_context锛氱敤浜庡瓨鍌ㄦ柊鍒涘缓鐨勫唴瀛樹笂涓嬫枃 + * + * 杩斿洖鍊硷細澶嶅埗鍚庣殑鏈湴璇彞鍒楄〃 + * + * 璇存槑锛氭鍑芥暟鐢ㄤ簬澶嶅埗缁欏畾鐨勬湰鍦拌鍙ュ垪琛紝骞跺皢澶嶅埗鍚庣殑璇彞鍒楄〃瀛樺偍鍦ㄦ柊鐨勫唴瀛樹笂涓嬫枃涓 + * 鏂板唴瀛樹笂涓嬫枃浠 parent_cxt 涓虹埗涓婁笅鏂囧垱寤恒傚鍒跺畬鎴愬悗锛屽嚱鏁颁細灏嗘柊鐨勫唴瀛樹笂涓嬫枃瀛樺偍鍦 + * plan_context 鎸囬拡鎵鎸囧悜鐨勪綅缃 + */ +List *CopyLocalStmt(const List *stmt_list, const MemoryContext parent_cxt, MemoryContext *plan_context) { - *plan_context = AllocSetContextCreate(parent_cxt, - "CopyedStmt", - ALLOCSET_DEFAULT_MINSIZE, - ALLOCSET_DEFAULT_INITSIZE, + // 鍒涘缓鏂扮殑鍐呭瓨涓婁笅鏂囷紝浠 parent_cxt 涓虹埗涓婁笅鏂 + *plan_context = AllocSetContextCreate(parent_cxt, "CopyedStmt", ALLOCSET_DEFAULT_MINSIZE, ALLOCSET_DEFAULT_INITSIZE, ALLOCSET_DEFAULT_MAXSIZE); /* * Copy plan into the new context. */ MemoryContext oldcxt = MemoryContextSwitchTo(*plan_context); - List* stmts = (List*)copyObject(stmt_list); + List *stmts = (List *)copyObject(stmt_list); (void)MemoryContextSwitchTo(oldcxt); return stmts; } /* function for modify SPICacheTable, global procedure plancache */ - +/* + * 鍔熻兘锛氳绠 SPI 缂撳瓨鍝堝笇鍊 + * + * 鍙傛暟鍒楄〃锛 + * key锛氱敤浜庤绠楀搱甯屽肩殑閿 + * keysize锛氶敭鍊肩殑澶у皬 + * + * 杩斿洖鍊硷細璁$畻寰楀埌鐨勫搱甯屽 + * + * 璇存槑锛氭鍑芥暟鐢ㄤ簬璁$畻 SPI 缂撳瓨涓殑鍝堝笇鍊笺傚畠鎺ュ彈涓涓敭鍊硷紙key锛夊拰閿肩殑澶у皬锛坘eysize锛変綔涓鸿緭鍏ワ紝 + * 骞朵娇鐢ㄥ搱甯岀畻娉曡绠楀嚭涓涓搱甯屽间綔涓鸿繑鍥炵粨鏋溿傚鏋滈敭鍊间负 NULL锛屽嚱鏁板皢杩斿洖涓涓壒娈婂 INVALID_SPI_KEY銆 + */ uint32 SPICacheHashFunc(const void *key, Size keysize) { if (unlikely(key == NULL)) { + // 濡傛灉閿间负 NULL锛岃繑鍥炵壒娈婂 INVALID_SPI_KEY return INVALID_SPI_KEY; } + // 浣跨敤鍝堝笇绠楁硶璁$畻鍝堝笇鍊 uint32 val1 = DatumGetUInt32(hash_any((const unsigned char *)key, (int)keysize)); return val1; } /* add new func */ +/* + * 鍔熻兘锛氬悜 SPI 缂撳瓨琛ㄤ腑鎻掑叆鏉$洰 + * + * 鍙傛暟鍒楄〃锛 + * key锛氳鎻掑叆鐨勬潯鐩殑閿 + * func_oid锛氳鎻掑叆鐨勬潯鐩叧鑱旂殑鍑芥暟 OID + * + * 璇存槑锛氭鍑芥暟鐢ㄤ簬鍚 SPI 缂撳瓨琛ㄤ腑鎻掑叆鏂扮殑鏉$洰銆傚畠鎺ュ彈涓涓敭锛坘ey锛夊拰涓涓嚱鏁 OID锛坒unc_oid锛変綔涓鸿緭鍏ワ紝 + * 骞跺皢瀹冧滑鍏宠仈鍦ㄤ竴璧锋彃鍏ュ埌 SPI 缂撳瓨琛ㄤ腑銆傚鏋 SPI 缂撳瓨琛ㄤ负绌烘垨閿负鐗规畩鍊 INVALID_SPI_KEY锛屽垯鍑芥暟涓嶆墽琛屼换浣曟搷浣溿 + * 濡傛灉宸茬粡瀛樺湪鐩稿悓閿殑鏉$洰锛屽嚱鏁颁細鍒犻櫎璇ユ潯鐩苟鍙戝嚭璀﹀憡淇℃伅銆 + */ void SPICacheTableInsert(uint32 key, Oid func_oid) { if (unlikely(u_sess->SPI_cxt.SPICacheTable == NULL || key == INVALID_SPI_KEY)) return; + // 妫鏌ユ槸鍚﹀凡缁忓瓨鍦ㄧ浉鍚岀殑閿 bool found = false; - SPIPlanCacheEnt* hentry = (SPIPlanCacheEnt*)hash_search(u_sess->SPI_cxt.SPICacheTable, - (void*)(&key), HASH_ENTER, &found); + SPIPlanCacheEnt *hentry = + (SPIPlanCacheEnt *)hash_search(u_sess->SPI_cxt.SPICacheTable, (void *)(&key), HASH_ENTER, &found); SPI_GPC_LOG("insert spiplan entry", NULL, func_oid); if (found) { + // 濡傛灉宸茬粡瀛樺湪鐩稿悓閿殑鏉$洰锛岄噴鏀剧浉鍏崇殑璧勬簮骞跺彂鍑鸿鍛婁俊鎭 list_free_ext(hentry->SPIplan_list); hentry->SPIplan_list = NULL; elog(WARNING, "should not has same old function entry in SPICacheTable"); } else { hentry->SPIplan_list = NULL; } + // 鍏宠仈鍑芥暟 OID 鍒版潯鐩 hentry->func_oid = func_oid; } /* add plan for spi keep plan */ +/* + * 鍔熻兘锛氬悜 SPI 缂撳瓨琛ㄤ腑鐨勬潯鐩彃鍏 SPI 璁″垝 + * + * 鍙傛暟鍒楄〃锛 + * key锛氳鎻掑叆鐨勬潯鐩殑閿 + * spi_plan锛氳鎻掑叆鐨 SPI 璁″垝 + * + * 璇存槑锛氭鍑芥暟鐢ㄤ簬鍚 SPI 缂撳瓨琛ㄤ腑鐨勬寚瀹氭潯鐩彃鍏ユ柊鐨 SPI 璁″垝銆傚畠鎺ュ彈涓涓敭锛坘ey锛夊拰涓涓 SPI 璁″垝锛坰pi_plan锛 + * 浣滀负杈撳叆锛屽皢 SPI 璁″垝涓庣浉搴旂殑鏉$洰鍏宠仈璧锋潵銆傚鏋 SPI 缂撳瓨琛ㄤ负绌猴紝鍑芥暟涓嶆墽琛屼换浣曟搷浣溿 + * 濡傛灉宸茬粡瀛樺湪鐩稿悓閿殑鏉$洰锛屽嚱鏁颁細灏 SPI 璁″垝杩藉姞鍒拌鏉$洰鐨勮鍒掑垪琛ㄤ腑銆 + */ void SPICacheTableInsertPlan(uint32 key, SPIPlanPtr spi_plan) { if (unlikely(u_sess->SPI_cxt.SPICacheTable == NULL)) return; + // 妫鏌ユ槸鍚﹀凡缁忓瓨鍦ㄧ浉鍚岀殑閿 bool found = false; - Assert (spi_plan->saved); - SPIPlanCacheEnt* hentry = (SPIPlanCacheEnt*)hash_search(u_sess->SPI_cxt.SPICacheTable, - (void*)(&key), HASH_ENTER, &found); + Assert(spi_plan->saved); + SPIPlanCacheEnt *hentry = + (SPIPlanCacheEnt *)hash_search(u_sess->SPI_cxt.SPICacheTable, (void *)(&key), HASH_ENTER, &found); if (found) { #ifdef USE_ASSERT_CHECKING /* cannot has same spiplan in list */ - ListCell* cell = NULL; + // 涓嶈兘鍦ㄥ垪琛ㄤ腑鍖呭惈鐩稿悓鐨 SPI 璁″垝 + ListCell *cell = NULL; if (hentry->SPIplan_list != NULL) { - foreach(cell, hentry->SPIplan_list) { + foreach (cell, hentry->SPIplan_list) { SPIPlanPtr cur = (SPIPlanPtr)lfirst(cell); - Assert (cur->id != spi_plan->id); - Assert (cur != spi_plan); + Assert(cur->id != spi_plan->id); + Assert(cur != spi_plan); } } #endif SPI_GPC_LOG("insert spiplan into entry", spi_plan, hentry->func_oid); + // 鍒囨崲鍐呭瓨涓婁笅鏂囧苟灏 SPI 璁″垝杩藉姞鍒板垪琛ㄤ腑 MemoryContext old_cxt = MemoryContextSwitchTo(u_sess->SPI_cxt.SPICacheTable->hcxt); hentry->SPIplan_list = lappend(hentry->SPIplan_list, spi_plan); (void)MemoryContextSwitchTo(old_cxt); @@ -419,60 +548,100 @@ void SPICacheTableInsertPlan(uint32 key, SPIPlanPtr spi_plan) } /* only use when delete function, plancache will be freed in SPI_freeplan */ +/* + * 鍔熻兘锛氫粠 SPI 缂撳瓨琛ㄤ腑鍒犻櫎鎸囧畾閿殑鏉$洰 + * + * 鍙傛暟鍒楄〃锛 + * key锛氳鍒犻櫎鐨勬潯鐩殑閿 + * + * 璇存槑锛氭鍑芥暟鐢ㄤ簬浠 SPI 缂撳瓨琛ㄤ腑鍒犻櫎鎸囧畾閿殑鏉$洰銆傚畠鎺ュ彈涓涓敭锛坘ey锛変綔涓鸿緭鍏ワ紝 + * 骞跺湪 SPI 缂撳瓨琛ㄤ腑鏌ユ壘鍖归厤鐨勬潯鐩紝濡傛灉鎵惧埌鍒欏垹闄ゅ畠銆傚鏋 SPI 缂撳瓨琛ㄤ负绌烘垨鏈壘鍒板尮閰嶇殑鏉$洰锛 + * 鍑芥暟涓嶆墽琛屼换浣曟搷浣溿 + */ void SPIPlanCacheTableDelete(uint32 key) { if (unlikely(u_sess->SPI_cxt.SPICacheTable == NULL)) { return; } + // 鏌ユ壘骞跺垹闄ゆ寚瀹氶敭鐨勬潯鐩 bool found = false; - SPIPlanCacheEnt* hentry = (SPIPlanCacheEnt*)hash_search(u_sess->SPI_cxt.SPICacheTable, - (void*)(&key), HASH_REMOVE, &found); + SPIPlanCacheEnt *hentry = + (SPIPlanCacheEnt *)hash_search(u_sess->SPI_cxt.SPICacheTable, (void *)(&key), HASH_REMOVE, &found); if (hentry) { SPI_GPC_LOG("delete spiplan entry", NULL, hentry->func_oid); + // 閲婃斁璁″垝鍒楄〃涓殑鍐呭瓨 list_free_ext(hentry->SPIplan_list); } } - +/* + * 鍔熻兘锛氫粠 SPI 缂撳瓨琛ㄤ腑鐨勬寚瀹氶敭鐨勬潯鐩腑鍒犻櫎鐗瑰畾 SPI 璁″垝 + * + * 鍙傛暟鍒楄〃锛 + * key锛氳鏌ユ壘鐨勬潯鐩殑閿 + * plan锛氳鍒犻櫎鐨 SPI 璁″垝 + * + * 璇存槑锛氭鍑芥暟鐢ㄤ簬浠 SPI 缂撳瓨琛ㄤ腑鐨勬寚瀹氶敭鐨勬潯鐩腑鍒犻櫎鐗瑰畾鐨 SPI 璁″垝銆 + * 瀹冩帴鍙椾竴涓敭锛坘ey锛夊拰涓涓 SPI 璁″垝锛坧lan锛変綔涓鸿緭鍏ワ紝骞跺湪鎸囧畾鐨勬潯鐩腑鏌ユ壘鍖归厤鐨 SPI 璁″垝锛 + * 濡傛灉鎵惧埌鍒欏垹闄ゅ畠銆傚鏋 SPI 缂撳瓨琛ㄤ负绌恒佹湭鎵惧埌鍖归厤鐨勬潯鐩垨鏈壘鍒板尮閰嶇殑 SPI 璁″垝锛 + * 鍑芥暟涓嶆墽琛屼换浣曟搷浣溿 + */ void SPIPlanCacheTableDeletePlan(uint32 key, SPIPlanPtr plan) { if (unlikely(u_sess->SPI_cxt.SPICacheTable == NULL)) return; - SPIPlanCacheEnt* entry = SPIPlanCacheTableLookup(key); + // 鏌ユ壘鎸囧畾閿殑鏉$洰 + SPIPlanCacheEnt *entry = SPIPlanCacheTableLookup(key); if (entry != NULL) { #ifdef USE_ASSERT_CHECKING - ListCell* cell = NULL; - foreach(cell, entry->SPIplan_list) { + ListCell *cell = NULL; + foreach (cell, entry->SPIplan_list) { SPIPlanPtr spiplan = (SPIPlanPtr)lfirst(cell); + // 鏂█纭繚瑕佸垹闄ょ殑璁″垝涓庢煡鎵惧埌鐨勮鍒掑尮閰 if (spiplan->id == plan->id) Assert(plan == spiplan); } #endif SPI_GPC_LOG("delete spiplan from entry", plan, entry->func_oid); - entry->SPIplan_list = list_delete_ptr(entry->SPIplan_list, (void*)plan); + // 浠庡垪琛ㄤ腑鍒犻櫎鎸囧畾鐨 SPI 璁″垝 + entry->SPIplan_list = list_delete_ptr(entry->SPIplan_list, (void *)plan); } } - +/* + * 鍔熻兘锛氫娇 SPI 缂撳瓨琛ㄤ腑鎸囧畾閿殑璁″垝鏃犳晥 + * + * 鍙傛暟鍒楄〃锛 + * key锛氳鏌ユ壘鐨勬潯鐩殑閿 + * + * 璇存槑锛氭鍑芥暟鐢ㄤ簬浣 SPI 缂撳瓨琛ㄤ腑鎸囧畾閿殑璁″垝鏃犳晥銆傚畠鎺ュ彈涓涓敭锛坘ey锛変綔涓鸿緭鍏ワ紝 + * 鏌ユ壘鍖归厤鐨 SPI 缂撳瓨琛ㄦ潯鐩紝骞跺皢鎵鏈夌浉鍏崇殑璁″垝鏍囪涓烘棤鏁堛 + * 濡傛灉 SPI 缂撳瓨琛ㄤ负绌烘垨鏈壘鍒板尮閰嶇殑鏉$洰锛屽嚱鏁颁笉鎵ц浠讳綍鎿嶄綔銆 + */ void SPIPlanCacheTableInvalidPlan(uint32 key) { if (unlikely(u_sess->SPI_cxt.SPICacheTable == NULL)) { return; } bool found = false; - SPIPlanCacheEnt* hentry = (SPIPlanCacheEnt*)hash_search(u_sess->SPI_cxt.SPICacheTable, - (void*)(&key), HASH_REMOVE, &found); + // 鏌ユ壘鎸囧畾閿殑鏉$洰 + SPIPlanCacheEnt *hentry = + (SPIPlanCacheEnt *)hash_search(u_sess->SPI_cxt.SPICacheTable, (void *)(&key), HASH_REMOVE, &found); if (hentry) { SPI_GPC_LOG("invalid each spiplan entry", NULL, hentry->func_oid); - ListCell* cell = NULL; + ListCell *cell = NULL; foreach (cell, hentry->SPIplan_list) { SPIPlanPtr spiplan = (SPIPlanPtr)lfirst(cell); + // 妫鏌ヨ鍒掓槸鍚﹀叿鏈 plancache_list if (list_length(spiplan->plancache_list) == 0) continue; - ListCell* cl = NULL; + ListCell *cl = NULL; + // 閬嶅巻璁″垝涓殑姣忎釜 CachedPlanSource foreach (cl, spiplan->plancache_list) { - CachedPlanSource* plansource = (CachedPlanSource*)lfirst(cl); + CachedPlanSource *plansource = (CachedPlanSource *)lfirst(cl); + // 濡傛灉璁″垝鍦ㄥ叡浜〃涓紝灏嗗叾鐘舵佹爣璁颁负鏃犳晥 if (plansource->gpc.status.InShareTable()) { plansource->gpc.status.SetStatus(GPC_INVALID); } else { + // 鍚﹀垯锛屽皢璁″垝鏍囪涓烘棤鏁 plansource->is_valid = false; if (plansource->gplan) plansource->gplan->is_valid = false; @@ -481,7 +650,13 @@ void SPIPlanCacheTableInvalidPlan(uint32 key) } } } - +/* + * 鍔熻兘锛氬垵濮嬪寲 SPI 璁″垝缂撳瓨琛 + * + * 璇存槑锛氭鍑芥暟鐢ㄤ簬鍒濆鍖 SPI 璁″垝缂撳瓨琛ㄣ係PI 璁″垝缂撳瓨琛ㄧ敤浜庡瓨鍌ㄤ笌 SQL 鍑芥暟鐩稿叧鐨勮鍒掞紝 + * 鍏朵腑姣忎釜璁″垝閮戒笌涓涓敮涓鐨勯敭鍏宠仈銆傚湪鍒濆鍖栬繃绋嬩腑锛屽嚱鏁颁細璁剧疆鍚堥傜殑鍝堝笇鎺у埗缁撴瀯锛坈tl锛夛紝 + * 骞跺垱寤哄搱甯岃〃鏉ュ瓨鍌ㄨ鍒掔紦瀛樻潯鐩 + */ void SPICacheTableInit() { HASHCTL ctl; @@ -496,236 +671,355 @@ void SPICacheTableInit() ctl.entrysize = sizeof(SPIPlanCacheEnt); ctl.hash = uint32_hash; ctl.hcxt = u_sess->cache_mem_cxt; + // 鍒涘缓 SPI 璁″垝缂撳瓨琛 u_sess->SPI_cxt.SPICacheTable = hash_create("SPIPlanCacheTable", func_per_user, &ctl, HASH_ELEM | HASH_FUNCTION | HASH_CONTEXT); SPI_GPC_LOG("init spiplan cache table", NULL, 0); } - -SPIPlanCacheEnt* SPIPlanCacheTableLookup(uint32 key) +/* + * 鍔熻兘锛氭煡鎵 SPI 璁″垝缂撳瓨琛ㄤ腑鐨勬潯鐩 + * + * 璇存槑锛氭鍑芥暟鐢ㄤ簬鍦 SPI 璁″垝缂撳瓨琛ㄤ腑鏌ユ壘涓庣粰瀹氶敭鐩稿叧鐨 SPIPlanCacheEnt 鏉$洰銆 + * 濡傛灉鎵惧埌鍖归厤鐨勬潯鐩紝鍒欒繑鍥炶鏉$洰鐨勬寚閽堬紱濡傛灉鏈壘鍒板尮閰嶇殑鏉$洰锛屽垯杩斿洖 NULL銆 + */ +SPIPlanCacheEnt *SPIPlanCacheTableLookup(uint32 key) { if (unlikely(u_sess->SPI_cxt.SPICacheTable == NULL)) return NULL; bool found = false; - SPIPlanCacheEnt* hentry = (SPIPlanCacheEnt*)hash_search( - u_sess->SPI_cxt.SPICacheTable, (void*)(&key), HASH_FIND, &found); + // 浣跨敤鍝堝笇鏌ユ壘鍦 SPI 璁″垝缂撳瓨琛ㄤ腑鏌ユ壘鍖归厤鐨勬潯鐩 + SPIPlanCacheEnt *hentry = + (SPIPlanCacheEnt *)hash_search(u_sess->SPI_cxt.SPICacheTable, (void *)(&key), HASH_FIND, &found); if (found) - return hentry; + return hentry; // 濡傛灉鎵惧埌鍖归厤鐨勬潯鐩紝鍒欒繑鍥炶鏉$洰鐨勬寚閽 else - return NULL; + return NULL; // 濡傛灉鏈壘鍒板尮閰嶇殑鏉$洰锛屽垯杩斿洖 NULL } /* set unique id in PLpgSQL_expr for gpc */ -static void set_id_stmt(PLpgSQL_stmt* stmt, uint32* unique_id); -static void set_id_block(PLpgSQL_stmt_block* block, uint32* unique_id); -static void set_id_if(PLpgSQL_stmt_if* stmt, uint32* unique_id); -static void set_id_case(PLpgSQL_stmt_case* stmt, uint32* unique_id); -static void set_id_return_query(PLpgSQL_stmt_return_query* stmt, uint32* unique_id); -static void set_id_raise(PLpgSQL_stmt_raise* stmt, uint32* unique_id); -static void set_id_dynexecute(PLpgSQL_stmt_dynexecute* stmt, uint32* unique_id); -static void set_id_dynfors(PLpgSQL_stmt_dynfors* stmt, uint32* unique_id); -static void set_id_open(PLpgSQL_stmt_open* stmt, uint32* unique_id); -static void set_id_expr(PLpgSQL_expr* expr, uint32* unique_id); -static void set_id_stmts(List* stmts, uint32* unique_id); - -static void set_id_expr(PLpgSQL_expr* expr, uint32* unique_id) +static void set_id_stmt(PLpgSQL_stmt *stmt, uint32 *unique_id); +static void set_id_block(PLpgSQL_stmt_block *block, uint32 *unique_id); +static void set_id_if(PLpgSQL_stmt_if *stmt, uint32 *unique_id); +static void set_id_case(PLpgSQL_stmt_case *stmt, uint32 *unique_id); +static void set_id_return_query(PLpgSQL_stmt_return_query *stmt, uint32 *unique_id); +static void set_id_raise(PLpgSQL_stmt_raise *stmt, uint32 *unique_id); +static void set_id_dynexecute(PLpgSQL_stmt_dynexecute *stmt, uint32 *unique_id); +static void set_id_dynfors(PLpgSQL_stmt_dynfors *stmt, uint32 *unique_id); +static void set_id_open(PLpgSQL_stmt_open *stmt, uint32 *unique_id); +static void set_id_expr(PLpgSQL_expr *expr, uint32 *unique_id); +static void set_id_stmts(List *stmts, uint32 *unique_id); +/* + * 鍔熻兘锛氫负 PL/pgSQL 琛ㄨ揪寮忚缃敮涓鏍囪瘑绗 + * + * 鍙傛暟鍒楄〃锛 + * expr锛歅L/pgSQL 琛ㄨ揪寮 + * unique_id锛氱敤浜庡垎閰嶅敮涓鏍囪瘑绗︾殑璁℃暟鍣 + */ +static void set_id_expr(PLpgSQL_expr *expr, uint32 *unique_id) { + // 妫鏌ヨ緭鍏ョ殑琛ㄨ揪寮忔槸鍚︿负 NULL锛屽鏋滄槸 NULL锛屽垯鏃犻渶杩涜璁剧疆 if (expr == NULL) return; + + // 涓鸿〃杈惧紡璁剧疆鍞竴鏍囪瘑绗︼紝閫氳繃閫掑 unique_id 鎸囬拡鐨勫 expr->idx = ++(*unique_id); } -static void set_id_stmts(List* stmts, uint32* unique_id) +/* + * 鍔熻兘锛氫负 PL/pgSQL 璇彞鍒楄〃涓殑姣忎釜璇彞璁剧疆鍞竴鏍囪瘑绗 + * + * 鍙傛暟鍒楄〃锛 + * stmts锛歅L/pgSQL 璇彞鍒楄〃 + * unique_id锛氱敤浜庡垎閰嶅敮涓鏍囪瘑绗︾殑璁℃暟鍣 + */ +static void set_id_stmts(List *stmts, uint32 *unique_id) { - ListCell* s = NULL; + ListCell *s = NULL; + // 閬嶅巻璇彞鍒楄〃 foreach (s, stmts) { - set_id_stmt((PLpgSQL_stmt*)lfirst(s), unique_id); + // 涓哄綋鍓嶈鍙ヨ缃敮涓鏍囪瘑绗 + set_id_stmt((PLpgSQL_stmt *)lfirst(s), unique_id); } } -static void set_id_block(PLpgSQL_stmt_block* block, uint32* unique_id) +/* + * 鍔熻兘锛氫负 PL/pgSQL 鍧楄鍙ヨ缃敮涓鏍囪瘑绗 + * + * 鍙傛暟鍒楄〃锛 + * block锛歅L/pgSQL 鍧楄鍙 + * unique_id锛氱敤浜庡垎閰嶅敮涓鏍囪瘑绗︾殑璁℃暟鍣 + */ +static void set_id_block(PLpgSQL_stmt_block *block, uint32 *unique_id) { + // 涓哄潡璇彞涓殑璇彞鍒楄〃璁剧疆鍞竴鏍囪瘑绗 set_id_stmts(block->body, unique_id); + // 濡傛灉瀛樺湪寮傚父澶勭悊鍧 if (block->exceptions != NULL) { - ListCell* e = NULL; + ListCell *e = NULL; + // 閬嶅巻寮傚父澶勭悊鍧椾腑鐨勬瘡涓紓甯 foreach (e, block->exceptions->exc_list) { - PLpgSQL_exception* exc = (PLpgSQL_exception*)lfirst(e); + PLpgSQL_exception *exc = (PLpgSQL_exception *)lfirst(e); + // 涓哄紓甯稿鐞嗕腑鐨勮鍙ュ垪琛ㄨ缃敮涓鏍囪瘑绗 set_id_stmts(exc->action, unique_id); } } } - -static void set_id_if(PLpgSQL_stmt_if* stmt, uint32* unique_id) +/* + * 鍔熻兘锛氫负 PL/pgSQL IF 璇彞璁剧疆鍞竴鏍囪瘑绗 + * + * 鍙傛暟鍒楄〃锛 + * stmt锛歅L/pgSQL IF 璇彞 + * unique_id锛氱敤浜庡垎閰嶅敮涓鏍囪瘑绗︾殑璁℃暟鍣 + */ +static void set_id_if(PLpgSQL_stmt_if *stmt, uint32 *unique_id) { - ListCell* l = NULL; + ListCell *l = NULL; + // 涓 IF 璇彞鐨勬潯浠惰〃杈惧紡璁剧疆鍞竴鏍囪瘑绗 set_id_expr(stmt->cond, unique_id); + // 涓 IF 璇彞鐨勪富浣撹鍙ヨ缃敮涓鏍囪瘑绗 set_id_stmts(stmt->then_body, unique_id); + // 閬嶅巻 ELSE IF 瀛愬彞鍒楄〃 foreach (l, stmt->elsif_list) { - PLpgSQL_if_elsif* elif = (PLpgSQL_if_elsif*)lfirst(l); + PLpgSQL_if_elsif *elif = (PLpgSQL_if_elsif *)lfirst(l); + // 涓 ELSE IF 瀛愬彞鐨勬潯浠惰〃杈惧紡璁剧疆鍞竴鏍囪瘑绗 set_id_expr(elif->cond, unique_id); + // 涓 ELSE IF 瀛愬彞鐨勮鍙ュ垪琛ㄨ缃敮涓鏍囪瘑绗 set_id_stmts(elif->stmts, unique_id); } + // 涓 IF 璇彞鐨 ELSE 瀛愬彞璁剧疆鍞竴鏍囪瘑绗 set_id_stmts(stmt->else_body, unique_id); } -static void set_id_case(PLpgSQL_stmt_case* stmt, uint32* unique_id) +/* + * 鍔熻兘锛氫负 PL/pgSQL CASE 璇彞璁剧疆鍞竴鏍囪瘑绗 + * + * 鍙傛暟鍒楄〃锛 + * stmt锛歅L/pgSQL CASE 璇彞 + * unique_id锛氱敤浜庡垎閰嶅敮涓鏍囪瘑绗︾殑璁℃暟鍣 + */ +static void set_id_case(PLpgSQL_stmt_case *stmt, uint32 *unique_id) { - ListCell* l = NULL; + ListCell *l = NULL; + // 涓 IF 璇彞鐨勬潯浠惰〃杈惧紡璁剧疆鍞竴鏍囪瘑绗 set_id_expr(stmt->t_expr, unique_id); + // 閬嶅巻 CASE 璇彞鐨 WHEN 瀛愬彞鍒楄〃 foreach (l, stmt->case_when_list) { - PLpgSQL_case_when* cwt = (PLpgSQL_case_when*)lfirst(l); + PLpgSQL_case_when *cwt = (PLpgSQL_case_when *)lfirst(l); + // 涓 WHEN 瀛愬彞鐨勬潯浠惰〃杈惧紡璁剧疆鍞竴鏍囪瘑绗 set_id_expr(cwt->expr, unique_id); + // 涓 WHEN 瀛愬彞鐨勮鍙ュ垪琛ㄨ缃敮涓鏍囪瘑绗 set_id_stmts(cwt->stmts, unique_id); } + // 涓 CASE 璇彞鐨 ELSE 瀛愬彞璁剧疆鍞竴鏍囪瘑绗 set_id_stmts(stmt->else_stmts, unique_id); } - -static void set_id_open(PLpgSQL_stmt_open* stmt, uint32* unique_id) +/* + * 鍔熻兘锛氫负 PL/pgSQL OPEN 璇彞璁剧疆鍞竴鏍囪瘑绗 + * + * 鍙傛暟鍒楄〃锛 + * stmt锛歅L/pgSQL OPEN 璇彞 + * unique_id锛氱敤浜庡垎閰嶅敮涓鏍囪瘑绗︾殑璁℃暟鍣 + */ +static void set_id_open(PLpgSQL_stmt_open *stmt, uint32 *unique_id) { - ListCell* lc = NULL; + ListCell *lc = NULL; + // 涓 OPEN 璇彞鐨勫弬鏁版煡璇㈣〃杈惧紡璁剧疆鍞竴鏍囪瘑绗 set_id_expr(stmt->argquery, unique_id); + // 涓 OPEN 璇彞鐨勬煡璇㈣〃杈惧紡璁剧疆鍞竴鏍囪瘑绗 set_id_expr(stmt->query, unique_id); + // 涓 OPEN 璇彞鐨勫姩鎬佹煡璇㈣〃杈惧紡璁剧疆鍞竴鏍囪瘑绗 set_id_expr(stmt->dynquery, unique_id); + // 閬嶅巻 OPEN 璇彞鐨勫弬鏁板垪琛 foreach (lc, stmt->params) { - set_id_expr((PLpgSQL_expr*)lfirst(lc), unique_id); + // 涓哄弬鏁拌〃杈惧紡璁剧疆鍞竴鏍囪瘑绗 + set_id_expr((PLpgSQL_expr *)lfirst(lc), unique_id); } } -static void set_id_return_query(PLpgSQL_stmt_return_query* stmt, uint32* unique_id) +/* + * 鍔熻兘锛氫负 PL/pgSQL RETURN QUERY 璇彞璁剧疆鍞竴鏍囪瘑绗 + * + * 鍙傛暟鍒楄〃锛 + * stmt锛歅L/pgSQL RETURN QUERY 璇彞 + * unique_id锛氱敤浜庡垎閰嶅敮涓鏍囪瘑绗︾殑璁℃暟鍣 + */ +static void set_id_return_query(PLpgSQL_stmt_return_query *stmt, uint32 *unique_id) { - ListCell* lc = NULL; + ListCell *lc = NULL; + // 涓 RETURN QUERY 璇彞鐨勬煡璇㈣〃杈惧紡璁剧疆鍞竴鏍囪瘑绗 set_id_expr(stmt->query, unique_id); + // 涓 RETURN QUERY 璇彞鐨勫姩鎬佹煡璇㈣〃杈惧紡璁剧疆鍞竴鏍囪瘑绗 set_id_expr(stmt->dynquery, unique_id); + // 閬嶅巻 RETURN QUERY 璇彞鐨勫弬鏁板垪琛 foreach (lc, stmt->params) { - set_id_expr((PLpgSQL_expr*)lfirst(lc), unique_id); + // 涓哄弬鏁拌〃杈惧紡璁剧疆鍞竴鏍囪瘑绗 + set_id_expr((PLpgSQL_expr *)lfirst(lc), unique_id); } } -static void set_id_raise(PLpgSQL_stmt_raise* stmt, uint32* unique_id) +/* + * 鍔熻兘锛氫负 PL/pgSQL RAISE 璇彞璁剧疆鍞竴鏍囪瘑绗 + * + * 鍙傛暟鍒楄〃锛 + * stmt锛歅L/pgSQL RAISE 璇彞 + * unique_id锛氱敤浜庡垎閰嶅敮涓鏍囪瘑绗︾殑璁℃暟鍣 + */ +static void set_id_raise(PLpgSQL_stmt_raise *stmt, uint32 *unique_id) { - ListCell* lc = NULL; + ListCell *lc = NULL; + // 閬嶅巻 RAISE 璇彞鐨勫弬鏁板垪琛 foreach (lc, stmt->params) { - set_id_expr((PLpgSQL_expr*)lfirst(lc), unique_id); + // 涓哄弬鏁拌〃杈惧紡璁剧疆鍞竴鏍囪瘑绗 + set_id_expr((PLpgSQL_expr *)lfirst(lc), unique_id); } + // 閬嶅巻 RAISE 璇彞鐨勯夐」鍒楄〃 foreach (lc, stmt->options) { - PLpgSQL_raise_option* opt = (PLpgSQL_raise_option*)lfirst(lc); + PLpgSQL_raise_option *opt = (PLpgSQL_raise_option *)lfirst(lc); + // 涓洪夐」琛ㄨ揪寮忚缃敮涓鏍囪瘑绗 set_id_expr(opt->expr, unique_id); } } - -static void set_id_dynexecute(PLpgSQL_stmt_dynexecute* stmt, uint32* unique_id) +/* + * 鍔熻兘锛氫负 PL/pgSQL DYNEXECUTE 璇彞璁剧疆鍞竴鏍囪瘑绗 + * + * 鍙傛暟鍒楄〃锛 + * stmt锛歅L/pgSQL DYNEXECUTE 璇彞 + * unique_id锛氱敤浜庡垎閰嶅敮涓鏍囪瘑绗︾殑璁℃暟鍣 + */ +static void set_id_dynexecute(PLpgSQL_stmt_dynexecute *stmt, uint32 *unique_id) { - ListCell* lc = NULL; + ListCell *lc = NULL; + // 涓 DYNEXECUTE 璇彞鐨勬煡璇㈣〃杈惧紡璁剧疆鍞竴鏍囪瘑绗 set_id_expr(stmt->query, unique_id); + // 閬嶅巻 DYNEXECUTE 璇彞鐨勫弬鏁板垪琛 foreach (lc, stmt->params) { - set_id_expr((PLpgSQL_expr*)lfirst(lc), unique_id); + // 涓哄弬鏁拌〃杈惧紡璁剧疆鍞竴鏍囪瘑绗 + set_id_expr((PLpgSQL_expr *)lfirst(lc), unique_id); } } -static void set_id_dynfors(PLpgSQL_stmt_dynfors* stmt, uint32* unique_id) +/* + * 鍔熻兘锛氫负 PL/pgSQL DYNFORS 璇彞璁剧疆鍞竴鏍囪瘑绗 + * + * 鍙傛暟鍒楄〃锛 + * stmt锛歅L/pgSQL DYNFORS 璇彞 + * unique_id锛氱敤浜庡垎閰嶅敮涓鏍囪瘑绗︾殑璁℃暟鍣 + */ +static void set_id_dynfors(PLpgSQL_stmt_dynfors *stmt, uint32 *unique_id) { - ListCell* lc = NULL; + ListCell *lc = NULL; + // 涓 DYNFORS 璇彞鐨勪富浣撹鍙ヨ缃敮涓鏍囪瘑绗 set_id_stmts(stmt->body, unique_id); + // 涓 DYNFORS 璇彞鐨勬煡璇㈣〃杈惧紡璁剧疆鍞竴鏍囪瘑绗 set_id_expr(stmt->query, unique_id); + // 閬嶅巻 DYNFORS 璇彞鐨勫弬鏁板垪琛 foreach (lc, stmt->params) { - set_id_expr((PLpgSQL_expr*)lfirst(lc), unique_id); + // 涓哄弬鏁拌〃杈惧紡璁剧疆鍞竴鏍囪瘑绗 + set_id_expr((PLpgSQL_expr *)lfirst(lc), unique_id); } } - -static void set_id_stmt(PLpgSQL_stmt* stmt, uint32* unique_id) +/* + * 鍔熻兘锛氫负 PL/pgSQL 璇彞璁剧疆鍞竴鏍囪瘑绗 + * + * 鍙傛暟鍒楄〃锛 + * stmt锛歅L/pgSQL 璇彞 + * unique_id锛氱敤浜庡垎閰嶅敮涓鏍囪瘑绗︾殑璁℃暟鍣 + */ +static void set_id_stmt(PLpgSQL_stmt *stmt, uint32 *unique_id) { switch ((enum PLpgSQL_stmt_types)stmt->cmd_type) { case PLPGSQL_STMT_BLOCK: - set_id_block((PLpgSQL_stmt_block*)stmt, unique_id); + set_id_block((PLpgSQL_stmt_block *)stmt, unique_id); break; case PLPGSQL_STMT_ASSIGN: - set_id_expr(((PLpgSQL_stmt_assign*)stmt)->expr, unique_id); + set_id_expr(((PLpgSQL_stmt_assign *)stmt)->expr, unique_id); break; case PLPGSQL_STMT_IF: - set_id_if((PLpgSQL_stmt_if*)stmt, unique_id); + set_id_if((PLpgSQL_stmt_if *)stmt, unique_id); break; case PLPGSQL_STMT_CASE: - set_id_case((PLpgSQL_stmt_case*)stmt, unique_id); + set_id_case((PLpgSQL_stmt_case *)stmt, unique_id); break; case PLPGSQL_STMT_LOOP: - set_id_stmts(((PLpgSQL_stmt_loop*)stmt)->body, unique_id); + set_id_stmts(((PLpgSQL_stmt_loop *)stmt)->body, unique_id); break; case PLPGSQL_STMT_WHILE: - set_id_expr(((PLpgSQL_stmt_while*)stmt)->cond, unique_id); - set_id_stmts(((PLpgSQL_stmt_while*)stmt)->body, unique_id); + set_id_expr(((PLpgSQL_stmt_while *)stmt)->cond, unique_id); + set_id_stmts(((PLpgSQL_stmt_while *)stmt)->body, unique_id); break; case PLPGSQL_STMT_FORI: - set_id_expr(((PLpgSQL_stmt_fori*)stmt)->lower, unique_id); - set_id_expr(((PLpgSQL_stmt_fori*)stmt)->upper, unique_id); - set_id_expr(((PLpgSQL_stmt_fori*)stmt)->step, unique_id); - set_id_stmts(((PLpgSQL_stmt_fori*)stmt)->body, unique_id); + set_id_expr(((PLpgSQL_stmt_fori *)stmt)->lower, unique_id); + set_id_expr(((PLpgSQL_stmt_fori *)stmt)->upper, unique_id); + set_id_expr(((PLpgSQL_stmt_fori *)stmt)->step, unique_id); + set_id_stmts(((PLpgSQL_stmt_fori *)stmt)->body, unique_id); break; case PLPGSQL_STMT_FORS: - set_id_stmts(((PLpgSQL_stmt_fors*)stmt)->body, unique_id); - set_id_expr(((PLpgSQL_stmt_fors*)stmt)->query, unique_id); + set_id_stmts(((PLpgSQL_stmt_fors *)stmt)->body, unique_id); + set_id_expr(((PLpgSQL_stmt_fors *)stmt)->query, unique_id); break; case PLPGSQL_STMT_FORC: - set_id_stmts(((PLpgSQL_stmt_forc*)stmt)->body, unique_id); - set_id_expr(((PLpgSQL_stmt_forc*)stmt)->argquery, unique_id); + set_id_stmts(((PLpgSQL_stmt_forc *)stmt)->body, unique_id); + set_id_expr(((PLpgSQL_stmt_forc *)stmt)->argquery, unique_id); break; case PLPGSQL_STMT_FOREACH_A: - set_id_expr(((PLpgSQL_stmt_foreach_a*)stmt)->expr, unique_id); - set_id_stmts(((PLpgSQL_stmt_foreach_a*)stmt)->body, unique_id); + set_id_expr(((PLpgSQL_stmt_foreach_a *)stmt)->expr, unique_id); + set_id_stmts(((PLpgSQL_stmt_foreach_a *)stmt)->body, unique_id); break; case PLPGSQL_STMT_EXIT: - set_id_expr(((PLpgSQL_stmt_exit*)stmt)->cond, unique_id); + set_id_expr(((PLpgSQL_stmt_exit *)stmt)->cond, unique_id); break; case PLPGSQL_STMT_RETURN: - set_id_expr(((PLpgSQL_stmt_return*)stmt)->expr, unique_id); + set_id_expr(((PLpgSQL_stmt_return *)stmt)->expr, unique_id); break; case PLPGSQL_STMT_RETURN_NEXT: - set_id_expr(((PLpgSQL_stmt_return_next*)stmt)->expr, unique_id); + set_id_expr(((PLpgSQL_stmt_return_next *)stmt)->expr, unique_id); break; case PLPGSQL_STMT_RETURN_QUERY: - set_id_return_query((PLpgSQL_stmt_return_query*)stmt, unique_id); + set_id_return_query((PLpgSQL_stmt_return_query *)stmt, unique_id); break; case PLPGSQL_STMT_RAISE: - set_id_raise((PLpgSQL_stmt_raise*)stmt, unique_id); + set_id_raise((PLpgSQL_stmt_raise *)stmt, unique_id); break; case PLPGSQL_STMT_EXECSQL: - set_id_expr(((PLpgSQL_stmt_execsql*)stmt)->sqlstmt, unique_id); + set_id_expr(((PLpgSQL_stmt_execsql *)stmt)->sqlstmt, unique_id); break; case PLPGSQL_STMT_DYNEXECUTE: - set_id_dynexecute((PLpgSQL_stmt_dynexecute*)stmt, unique_id); + set_id_dynexecute((PLpgSQL_stmt_dynexecute *)stmt, unique_id); break; case PLPGSQL_STMT_DYNFORS: - set_id_dynfors((PLpgSQL_stmt_dynfors*)stmt, unique_id); + set_id_dynfors((PLpgSQL_stmt_dynfors *)stmt, unique_id); break; case PLPGSQL_STMT_OPEN: - set_id_open((PLpgSQL_stmt_open*)stmt, unique_id); + set_id_open((PLpgSQL_stmt_open *)stmt, unique_id); break; case PLPGSQL_STMT_FETCH: - set_id_expr(((PLpgSQL_stmt_fetch*)stmt)->expr, unique_id); + set_id_expr(((PLpgSQL_stmt_fetch *)stmt)->expr, unique_id); break; case PLPGSQL_STMT_PERFORM: - set_id_expr(((PLpgSQL_stmt_perform*)stmt)->expr, unique_id); + set_id_expr(((PLpgSQL_stmt_perform *)stmt)->expr, unique_id); break; default: break; } } -void set_func_expr_unique_id(PLpgSQL_function* func) +void set_func_expr_unique_id(PLpgSQL_function *func) { uint32 unique_id = 0; int i; for (i = 0; i < func->ndatums; i++) { - PLpgSQL_datum* d = func->datums[i]; + PLpgSQL_datum *d = func->datums[i]; switch (d->dtype) { case PLPGSQL_DTYPE_VAR: { - PLpgSQL_var* var = (PLpgSQL_var*)d; + PLpgSQL_var *var = (PLpgSQL_var *)d; set_id_expr(var->default_val, &unique_id); set_id_expr(var->cursor_explicit_expr, &unique_id); } break; case PLPGSQL_DTYPE_ARRAYELEM: - set_id_expr(((PLpgSQL_arrayelem*)d)->subscript, &unique_id); + set_id_expr(((PLpgSQL_arrayelem *)d)->subscript, &unique_id); break; case PLPGSQL_DTYPE_ROW: case PLPGSQL_DTYPE_RECORD: { - PLpgSQL_row* row = (PLpgSQL_row*)d; + PLpgSQL_row *row = (PLpgSQL_row *)d; set_id_expr(row->default_val, &unique_id); } break; default: @@ -736,14 +1030,21 @@ void set_func_expr_unique_id(PLpgSQL_function* func) set_id_block(func->action, &unique_id); } } - +/* + * 鍔熻兘锛氬垽鏂槸鍚﹀惎鐢 GPC 瑙f瀽 + * + * 鍙傛暟鍒楄〃锛 + * node锛氳瑙f瀽鐨勮妭鐐 + * + * 杩斿洖鍊硷細濡傛灉鍚敤 GPC 瑙f瀽锛岃繑鍥 true锛屽惁鍒欒繑鍥 false + */ bool SPIParseEnableGPC(const Node *node) { if (node == NULL) return false; switch (nodeTag(node)) { case T_SelectStmt: - if (((SelectStmt*)node)->intoClause) + if (((SelectStmt *)node)->intoClause) return false; /* fall through */ case T_MergeStmt: @@ -760,4 +1061,3 @@ bool SPIParseEnableGPC(const Node *node) /* keep compiler quite */ return false; } - diff --git a/src/gausskernel/process/job/gs_job_calendar.cpp b/src/gausskernel/process/job/gs_job_calendar.cpp index a9a8f85a0..e88508f14 100644 --- a/src/gausskernel/process/job/gs_job_calendar.cpp +++ b/src/gausskernel/process/job/gs_job_calendar.cpp @@ -23,10 +23,10 @@ * ------------------------------------------------------------------------- */ - #include "postgres.h" - #include "miscadmin.h" - #include "utils/builtins.h" - #include "utils/dbe_scheduler.h" +#include "postgres.h" +#include "miscadmin.h" +#include "utils/builtins.h" +#include "utils/dbe_scheduler.h" /* * repeat_interval = frequency_clause @@ -53,7 +53,7 @@ */ /* Initialize calendaring fields */ -static bool IsLegalIntervalStr(const char* str, bool numeric_only = false); +static bool IsLegalIntervalStr(const char *str, bool numeric_only = false); static char *get_calendar_clause_val(char **tokens, const char *clause, bool numeric_only = false); static char **tokenize_str(char *src, const char *delims, int fields); static int validate_field_names(char **toks); @@ -66,9 +66,9 @@ static bool get_calendar_freqency(Calendar calendar, char **tokens); static void get_calendar_n_interval(Calendar calendar, char **tokens); static char *get_calendar_bymonth_val(Calendar calendar, char **tokens); static void get_calendar_bymonth(Calendar calendar, char **tokens); -static void get_calendar_byweekno(Calendar calendar, char **tokens); /* unsupported */ +static void get_calendar_byweekno(Calendar calendar, char **tokens); /* unsupported */ static void get_calendar_byyearday(Calendar calendar, char **tokens); /* unsupported */ -static void get_calendar_bydate(Calendar calendar, char **tokens); /* unsupported */ +static void get_calendar_bydate(Calendar calendar, char **tokens); /* unsupported */ static char *get_calendar_bymonthday_val(Calendar calendar, char **tokens); static void get_calendar_bymonthday(Calendar calendar, char **tokens); static void get_calendar_byday(Calendar calendar, char **tokens); /* unsupported */ @@ -97,10 +97,10 @@ static bool find_nearest_calendar_time(Calendar calendar, TimestampTz *timeline, /* Calendaring Interval Calculator */ static void prepare_calendar_period(Calendar calendar, TimestampTz base_date, TimestampTz *timeline); static void evaluate_calendar_bymonth(Calendar calendar, TimestampTz *timeline, int *cnt); -static void evaluate_calendar_byweekno(Calendar calendar, TimestampTz *timeline, int *cnt); /* unsupported */ +static void evaluate_calendar_byweekno(Calendar calendar, TimestampTz *timeline, int *cnt); /* unsupported */ static void evaluate_calendar_byyearday(Calendar calendar, TimestampTz *timeline, int *cnt); /* unsupported */ static void evaluate_calendar_bymonthday(Calendar calendar, TimestampTz *timeline, int *cnt); -static void evaluate_calendar_byhour(Calendar calendar, TimestampTz *timeline, int *cnt); /* sub_timeline */ +static void evaluate_calendar_byhour(Calendar calendar, TimestampTz *timeline, int *cnt); /* sub_timeline */ static void evaluate_calendar_byminute(Calendar calendar, TimestampTz *timeline, int *cnt); /* sub_timeline */ static void evaluate_calendar_bysecond(Calendar calendar, TimestampTz *timeline, int *cnt); /* sub_timeline */ static bool evaluate_calendar_period(Calendar calendar, TimestampTz *timeline, TimestampTz *sub_timeline, @@ -115,7 +115,7 @@ static TimestampTz evaluate_calendar_interval(Calendar calendar, TimestampTz sta * @return true legal * @return false illegal */ -static bool IsLegalIntervalStr(const char* str, bool numeric_only) +static bool IsLegalIntervalStr(const char *str, bool numeric_only) { size_t NBytes = (unsigned int)strlen(str); if (NBytes > (MAX_CALENDAR_FIELD_LEN)) { @@ -141,7 +141,6 @@ static bool IsLegalIntervalStr(const char* str, bool numeric_only) return true; } - /* * @brief get_calendar_clause * Get calendar clause and return its value; @@ -154,7 +153,7 @@ static char *get_calendar_clause_val(char **tokens, const char *clause, bool num char *val = NULL; for (int i = 0; i < MAX_CALENDAR_FIELDS; i += 2) { if (tokens[i] != NULL && pg_strcasecmp(tokens[i], clause) == 0) { - val = tokens[i + 1]; /* get clause's value */ + val = tokens[i + 1]; /* get clause's value */ break; } } @@ -163,10 +162,10 @@ static char *get_calendar_clause_val(char **tokens, const char *clause, bool num } if (!IsLegalIntervalStr(val, numeric_only)) { - ereport(ERROR, (errmodule(MOD_JOB), errcode(ERRCODE_OPERATE_FAILED), - errmsg("Fail to evaluate calendaring string."), - errdetail("Invalid value string for clause \'%s\'", clause), errcause("N/A"), - erraction("Please modify the calendaring string."))); + ereport(ERROR, + (errmodule(MOD_JOB), errcode(ERRCODE_OPERATE_FAILED), errmsg("Fail to evaluate calendaring string."), + errdetail("Invalid value string for clause \'%s\'", clause), errcause("N/A"), + erraction("Please modify the calendaring string."))); } return val; } @@ -205,10 +204,10 @@ static bool get_calendar_freqency(Calendar calendar, char **tokens) calendar->frequency = SECONDLY; } else { pfree_ext(tokens); - ereport(ERROR, (errmodule(MOD_JOB), errcode(ERRCODE_OPERATE_FAILED), - errmsg("Fail to evaluate calendaring string."), - errdetail("Invalid frequency value \'%s\'.", val), errcause("N/A"), - erraction("Please modify the calendaring string."))); + ereport(ERROR, + (errmodule(MOD_JOB), errcode(ERRCODE_OPERATE_FAILED), errmsg("Fail to evaluate calendaring string."), + errdetail("Invalid frequency value \'%s\'.", val), errcause("N/A"), + erraction("Please modify the calendaring string."))); } return true; } @@ -223,7 +222,7 @@ static bool get_calendar_freqency(Calendar calendar, char **tokens) */ static void get_calendar_n_interval(Calendar calendar, char **tokens) { - calendar->interval = 1; /* we ALWAYS set interval to 1 */ + calendar->interval = 1; /* we ALWAYS set interval to 1 */ char *val = get_calendar_clause_val(tokens, "interval", true); if (val == NULL) { return; @@ -232,10 +231,10 @@ static void get_calendar_n_interval(Calendar calendar, char **tokens) int num = atoi(val); if (num < 1 || num > MAX_CALENDAR_INTERVAL_NUM) { pfree_ext(tokens); - ereport(ERROR, (errmodule(MOD_JOB), errcode(ERRCODE_OPERATE_FAILED), - errmsg("Fail to evaluate calendaring string."), - errdetail("Interval \'%d\' not in range [1, 99].", num), errcause("N/A"), - erraction("Please modify the calendaring string."))); + ereport(ERROR, + (errmodule(MOD_JOB), errcode(ERRCODE_OPERATE_FAILED), errmsg("Fail to evaluate calendaring string."), + errdetail("Interval \'%d\' not in range [1, 99].", num), errcause("N/A"), + erraction("Please modify the calendaring string."))); } calendar->interval = num; } @@ -306,10 +305,10 @@ static void get_calendar_bymonth(Calendar calendar, char **tokens) } } if (month == 0) { - ereport(ERROR, (errmodule(MOD_JOB), errcode(ERRCODE_OPERATE_FAILED), - errmsg("Fail to evaluate calendaring string."), - errdetail("Invalid month token \'%s\'.", val), errcause("N/A"), - erraction("Please modify the calendaring string."))); + ereport(ERROR, + (errmodule(MOD_JOB), errcode(ERRCODE_OPERATE_FAILED), + errmsg("Fail to evaluate calendaring string."), errdetail("Invalid month token \'%s\'.", val), + errcause("N/A"), erraction("Please modify the calendaring string."))); } } else { /* numeric in */ @@ -352,10 +351,10 @@ static void get_calendar_byweekno(Calendar calendar, char **tokens) { char *val = get_calendar_clause_val(tokens, "byweekno", true); if (val != NULL) { - ereport(ERROR, (errmodule(MOD_JOB), errcode(ERRCODE_OPERATE_FAILED), - errmsg("Fail to evaluate calendaring string."), - errdetail("BYWEEKNO clause is currently unsupported."), errcause("N/A"), - erraction("Please modify the calendaring string."))); + ereport(ERROR, + (errmodule(MOD_JOB), errcode(ERRCODE_OPERATE_FAILED), errmsg("Fail to evaluate calendaring string."), + errdetail("BYWEEKNO clause is currently unsupported."), errcause("N/A"), + erraction("Please modify the calendaring string."))); } } @@ -373,10 +372,10 @@ static void get_calendar_byyearday(Calendar calendar, char **tokens) { char *val = get_calendar_clause_val(tokens, "byyearday", true); if (val != NULL) { - ereport(ERROR, (errmodule(MOD_JOB), errcode(ERRCODE_OPERATE_FAILED), - errmsg("Fail to evaluate calendaring string."), - errdetail("BYYEARDAY clause is currently unsupported."), errcause("N/A"), - erraction("Please modify the calendaring string."))); + ereport(ERROR, + (errmodule(MOD_JOB), errcode(ERRCODE_OPERATE_FAILED), errmsg("Fail to evaluate calendaring string."), + errdetail("BYYEARDAY clause is currently unsupported."), errcause("N/A"), + erraction("Please modify the calendaring string."))); } } @@ -393,16 +392,26 @@ static void get_calendar_bydate(Calendar calendar, char **tokens) { char *val = get_calendar_clause_val(tokens, "byweekno", true); if (val != NULL) { - ereport(ERROR, (errmodule(MOD_JOB), errcode(ERRCODE_OPERATE_FAILED), - errmsg("Fail to evaluate calendaring string."), - errdetail("BYDATE clause is currently unsupported."), errcause("N/A"), - erraction("Please modify the calendaring string."))); + ereport(ERROR, + (errmodule(MOD_JOB), errcode(ERRCODE_OPERATE_FAILED), errmsg("Fail to evaluate calendaring string."), + errdetail("BYDATE clause is currently unsupported."), errcause("N/A"), + erraction("Please modify the calendaring string."))); } } - +/* + * 鍔熻兘锛氳幏鍙栨棩鍘嗚鍒欎腑鐨 "byhour" 瀛愬彞鐨勫 + * + * 鍙傛暟鍒楄〃锛 + * calendar锛氭棩鍘嗚鍒 + * tokens锛氭棩鍘嗚鍒欎腑鐨勬爣璁 + * + * 杩斿洖鍊硷細 + * 濡傛灉瀛樺湪 "byhour" 瀛愬彞锛屽垯杩斿洖鍏跺硷紱鍚﹀垯杩斿洖 NULL銆 + */ static char *get_calendar_bymonthday_val(Calendar calendar, char **tokens) { + // 鑾峰彇 "byhour" 瀛愬彞鐨勫 char *val = get_calendar_clause_val(tokens, "bymonthday", true); if (val != NULL) { /* apply bymonthday rule if bymonthday is specified */ @@ -421,10 +430,10 @@ static char *get_calendar_bymonthday_val(Calendar calendar, char **tokens) calendar->monthday_len = 0; } /* We cannot optimize any further since monthday/yearday are not perfectly periodic */ + // 娌℃湁鎸囧畾 "byhour" 瀛愬彞锛岃繑鍥 NULL return NULL; } - /* * @brief get_calendar_bymonth * Get bymonthday_clause. @@ -449,10 +458,10 @@ static void get_calendar_bymonthday(Calendar calendar, char **tokens) while (tok != NULL) { int monthday = atoi(tok); if (monthday < -(DAYS_PER_MONTH + 1) || monthday > (DAYS_PER_MONTH + 1) || monthday == 0) { - ereport(ERROR, (errmodule(MOD_JOB), errcode(ERRCODE_OPERATE_FAILED), - errmsg("Fail to evaluate calendaring string."), - errdetail("Invalid monthday \'%d\'.", monthday), errcause("N/A"), - erraction("Please modify the calendaring string."))); + ereport(ERROR, + (errmodule(MOD_JOB), errcode(ERRCODE_OPERATE_FAILED), + errmsg("Fail to evaluate calendaring string."), errdetail("Invalid monthday \'%d\'.", monthday), + errcause("N/A"), erraction("Please modify the calendaring string."))); } tok = strtok_s(NULL, ",", &context); @@ -505,14 +514,13 @@ static void get_calendar_byday(Calendar calendar, char **tokens) { char *val = get_calendar_clause_val(tokens, "byday", true); if (val != NULL) { - ereport(ERROR, (errmodule(MOD_JOB), errcode(ERRCODE_OPERATE_FAILED), - errmsg("Fail to evaluate calendaring string."), - errdetail("BYDAY clause is currently unsupported."), errcause("N/A"), - erraction("Please modify the calendaring string."))); + ereport(ERROR, + (errmodule(MOD_JOB), errcode(ERRCODE_OPERATE_FAILED), errmsg("Fail to evaluate calendaring string."), + errdetail("BYDAY clause is currently unsupported."), errcause("N/A"), + erraction("Please modify the calendaring string."))); } } - static char *get_calendar_byhour_val(Calendar calendar, char **tokens) { char *val = get_calendar_clause_val(tokens, "byhour", true); @@ -568,10 +576,10 @@ static void get_calendar_byhour(Calendar calendar, char **tokens) while (tok != NULL) { int hour = atoi(tok); if (hour < 0 || hour >= HOURS_PER_DAY) { - ereport(ERROR, (errmodule(MOD_JOB), errcode(ERRCODE_OPERATE_FAILED), - errmsg("Fail to evaluate calendaring string."), - errdetail("Invalid time \'%d\' o\' clock.", hour), errcause("N/A"), - erraction("Please modify the calendaring string."))); + ereport(ERROR, + (errmodule(MOD_JOB), errcode(ERRCODE_OPERATE_FAILED), + errmsg("Fail to evaluate calendaring string."), errdetail("Invalid time \'%d\' o\' clock.", hour), + errcause("N/A"), erraction("Please modify the calendaring string."))); } tok = strtok_s(NULL, ",", &context); @@ -590,9 +598,19 @@ static void get_calendar_byhour(Calendar calendar, char **tokens) calendar->byfields |= INTERVAL_BYHOUR; } - +/* + * 鍔熻兘锛氳幏鍙栨棩鍘嗚鍒欎腑鐨 "byminute" 瀛愬彞鐨勫 + * + * 鍙傛暟鍒楄〃锛 + * calendar锛氭棩鍘嗚鍒 + * tokens锛氭棩鍘嗚鍒欎腑鐨勬爣璁 + * + * 杩斿洖鍊硷細 + * 濡傛灉瀛樺湪 "byminute" 瀛愬彞锛屽垯杩斿洖鍏跺硷紱鍚﹀垯杩斿洖 NULL銆 + */ static char *get_calendar_byminute_val(Calendar calendar, char **tokens) { + // 鑾峰彇 "byminute" 瀛愬彞鐨勫 char *val = get_calendar_clause_val(tokens, "byminute", true); if (val != NULL) { /* apply byminute rule if byminute is specified */ @@ -621,6 +639,7 @@ static char *get_calendar_byminute_val(Calendar calendar, char **tokens) calendar->minute_len *= -1; calendar->byminute[0] = mod; } + // 娌℃湁鎸囧畾 "byminute" 瀛愬彞锛岃繑鍥 NULL return NULL; } @@ -667,15 +686,26 @@ static void get_calendar_byminute(Calendar calendar, char **tokens) calendar->time_depth *= (calendar->minute_len == 0) ? 1 : calendar->minute_len; calendar->byfields |= INTERVAL_BYMINUTE; } - +/* + * 鍔熻兘锛氳幏鍙栨棩鍘嗚鍒欎腑鐨 "bysecond" 瀛愬彞鐨勫 + * + * 鍙傛暟鍒楄〃锛 + * calendar锛氭棩鍘嗚鍒 + * tokens锛氭棩鍘嗚鍒欎腑鐨勬爣璁 + * + * 杩斿洖鍊硷細 + * 濡傛灉瀛樺湪 "bysecond" 瀛愬彞锛屽垯杩斿洖鍏跺硷紱鍚﹀垯杩斿洖 NULL銆 + */ static char *get_calendar_bysecond_val(Calendar calendar, char **tokens) { + // 鑾峰彇 "bysecond" 瀛愬彞鐨勫 char *val = get_calendar_clause_val(tokens, "bysecond", true); if (val != NULL) { /* apply bysecond rule if bysecond is specified */ return val; } + // 鏂█锛岀‘淇濋鐜囦笉楂樹簬 SECONDLY Assert(calendar->frequency <= SECONDLY); /* Even higher frequency is unavailable */ if (calendar->frequency < SECONDLY) { @@ -693,6 +723,7 @@ static char *get_calendar_bysecond_val(Calendar calendar, char **tokens) calendar->second_len *= -1; calendar->bysecond[0] = mod; } + // 娌℃湁鎸囧畾 "bysecond" 瀛愬彞锛岃繑鍥 NULL return NULL; } @@ -740,7 +771,6 @@ static void get_calendar_bysecond(Calendar calendar, char **tokens) calendar->byfields |= INTERVAL_BYSECOND; } - /* * @brief tokenize_str * Tokenize string with given delimiters. @@ -766,13 +796,21 @@ static char **tokenize_str(char *src, const char *delims, int fields) } return tokens; } - +/* + * 鍔熻兘锛氶獙璇佹棩鍘嗚鍒欎腑鐨勫瓧娈靛悕鏄惁鏈夋晥 + * + * 鍙傛暟鍒楄〃锛 + * toks锛氭棩鍘嗚鍒欎腑鐨勬爣璁版暟缁 + * + * 杩斿洖鍊硷細 + * 濡傛灉瀛楁鍚嶆湁鏁堬紝鍒欒繑鍥 -1锛涘惁鍒欒繑鍥炲瓧娈靛悕鍦ㄦ爣璁版暟缁勪腑鐨勪綅缃 + */ static int validate_field_names(char **toks) { bool valid = false; const int name_pos_step = 2; - const char *supported_fields[SUPPORTED_FIELDS] = {"freq", "interval", "bymonth", "bymonthday", "byhour", - "byminute", "bysecond"}; + const char *supported_fields[SUPPORTED_FIELDS] = {"freq", "interval", "bymonth", "bymonthday", + "byhour", "byminute", "bysecond"}; bool fields_used[SUPPORTED_FIELDS] = {0}; for (int i = 0; i < MAX_CALENDAR_FIELDS; i += name_pos_step) { for (int j = 0; j < SUPPORTED_FIELDS; j++) { @@ -791,7 +829,7 @@ static int validate_field_names(char **toks) fields_used[j] = true; valid = true; } - break; /* here is way pass guarding condition, break it */ + break; /* here is way pass guarding condition, break it */ } if (!valid) { return i; @@ -815,19 +853,18 @@ Calendar interpret_calendar_interval(char *calendar_str) /* Make token lists */ char **str_toks = tokenize_str(calendar_str, " =;", MAX_CALENDAR_FIELDS); if (str_toks == NULL) { - ereport(ERROR, (errmodule(MOD_JOB), errcode(ERRCODE_OPERATE_FAILED), - errmsg("Fail to evaluate calendaring string."), - errdetail("Unable to parse calendaring string."), - errcause("Calendaring string is too long/invalid"), - erraction("Please modify the calendaring string."))); + ereport(ERROR, + (errmodule(MOD_JOB), errcode(ERRCODE_OPERATE_FAILED), errmsg("Fail to evaluate calendaring string."), + errdetail("Unable to parse calendaring string."), errcause("Calendaring string is too long/invalid"), + erraction("Please modify the calendaring string."))); } int pos = validate_field_names(str_toks); if (pos >= 0) { - ereport(ERROR, (errmodule(MOD_JOB), errcode(ERRCODE_OPERATE_FAILED), - errmsg("Fail to evaluate calendaring string."), - errdetail("Incorrect/duplicate clause name '%s'.", str_toks[pos]), errcause("N/A"), - erraction("Please modify the calendaring string."))); + ereport(ERROR, + (errmodule(MOD_JOB), errcode(ERRCODE_OPERATE_FAILED), errmsg("Fail to evaluate calendaring string."), + errdetail("Incorrect/duplicate clause name '%s'.", str_toks[pos]), errcause("N/A"), + erraction("Please modify the calendaring string."))); } /* Make Calendar */ @@ -1028,7 +1065,7 @@ static void evaluate_calendar_bymonthday(Calendar calendar, TimestampTz *timelin *cnt = 0; int tz = 0; fsec_t fsec; - struct pg_tm tt, *tm = &tt; /* POSIX time struct, see NOTE above */ + struct pg_tm tt, *tm = &tt; /* POSIX time struct, see NOTE above */ copy_calendar_dates(timeline, calendar->monthday_len, chunk); for (int i = 0; i < calendar->monthday_len; i++) { if (calendar->bymonthday[i] < 0) { @@ -1222,8 +1259,7 @@ static void fastforward_calendar_period(Calendar calendar, TimestampTz *start_da errmsg("Cannot evaluate calendar clause."), errdetail("Broken interval clause."), errcause("N/A"), erraction("Please modify the calendaring string."))); } - Datum pace_datum = DirectFunctionCall2(interval_part, CStringGetTextDatum("epoch"), - PointerGetDatum(period)); + Datum pace_datum = DirectFunctionCall2(interval_part, CStringGetTextDatum("epoch"), PointerGetDatum(period)); int pace = (int)DatumGetFloat8(pace_datum); pfree_ext(period); @@ -1237,8 +1273,8 @@ static void fastforward_calendar_period(Calendar calendar, TimestampTz *start_da Interval *ff_span = get_calendar_period(calendar, num_of_periods); if (ff_span == NULL) { ereport(ERROR, (errmodule(MOD_JOB), errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE), - errmsg("Cannot evaluate calendar clause."), errdetail("Broken interval clause."), - errcause("N/A"), erraction("Please modify the calendaring string."))); + errmsg("Cannot evaluate calendar clause."), errdetail("Broken interval clause."), + errcause("N/A"), erraction("Please modify the calendaring string."))); } new_start_date = DatumGetTimestampTz(timestamp_pl_interval(*start_date, ff_span)); pfree_ext(ff_span); @@ -1397,7 +1433,7 @@ static void prepare_calendar_period(Calendar calendar, TimestampTz base_date, Ti } fsec_t fsec; - struct pg_tm tt, *tm = &tt; /* POSIX time struct, see NOTE above */ + struct pg_tm tt, *tm = &tt; /* POSIX time struct, see NOTE above */ int tz; if (timestamp2tm(base_date, &tz, tm, &fsec, NULL, NULL) != 0) { ereport(ERROR, (errmodule(MOD_JOB), errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE), @@ -1431,7 +1467,6 @@ static TimestampTz get_next_calendar_period(Calendar calendar, TimestampTz base_ return base_date; } - /* * @brief evaluate_calendar_interval * Calculate next date base on start date. @@ -1516,9 +1551,9 @@ Datum evaluate_repeat_interval(Datum calendar_in, Datum start_date, Datum date_a */ Datum evaluate_calendar_string_internal(PG_FUNCTION_ARGS) { - Datum string = PG_GETARG_DATUM(0); /* calendar string */ - Datum start_date = PG_GETARG_DATUM(1); /* start date */ - Datum date_after = PG_GETARG_DATUM(2); /* return date after */ + Datum string = PG_GETARG_DATUM(0); /* calendar string */ + Datum start_date = PG_GETARG_DATUM(1); /* start date */ + Datum date_after = PG_GETARG_DATUM(2); /* return date after */ Datum new_next_date = evaluate_repeat_interval(string, start_date, date_after); PG_RETURN_DATUM(new_next_date); } \ No newline at end of file diff --git a/src/gausskernel/process/main/main.cpp b/src/gausskernel/process/main/main.cpp index 6a6ca1027..81528d302 100755 --- a/src/gausskernel/process/main/main.cpp +++ b/src/gausskernel/process/main/main.cpp @@ -61,60 +61,63 @@ THR_LOCAL bool IsInitdb = false; size_t mmap_threshold = (size_t)0xffffffff; -const char* progname = NULL; +const char *progname = NULL; -static void startup_hacks(const char* progname); -static void help(const char* progname); -static void check_root(const char* progname); -static char* get_current_username(const char* progname); +static void startup_hacks(const char *progname); +static void help(const char *progname); +static void check_root(const char *progname); +static char *get_current_username(const char *progname); static void syscall_lock_init(void); -extern int encrypte_main(int argc, char* const argv[]); +extern int encrypte_main(int argc, char *const argv[]); /* * Any openGauss server process begins execution here. */ -int main(int argc, char* argv[]) +/* + * 鍔熻兘锛欸aussDB 涓诲嚱鏁 + * + * 鍙傛暟鍒楄〃锛 + * argc锛氬懡浠よ鍙傛暟鐨勬暟閲 + * argv锛氬懡浠よ鍙傛暟鐨勫瓧绗︿覆鏁扮粍 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁拌礋璐 GaussDB 鐨勫惎鍔ㄥ拰涓昏鎺у埗娴佺▼銆傚畠浼氭牴鎹懡浠よ鍙傛暟鍒嗗彂鍒颁笉鍚岀殑瀛愮▼搴忥紝濡 + * initdb銆丳ostmaster銆丟ucInfoMain绛夈 鍦ㄥ惎鍔ㄨ繃绋嬩腑锛屼細杩涜涓绯诲垪鍒濆鍖栨搷浣滐紝鍖呮嫭鍐呭瓨绠$悊銆佷俊鍙峰鐞嗐佸湴鍖鸿缃瓑銆 + * 鏍规嵁鍛戒护琛屽弬鏁帮紝鍙兘鎵ц鍒濆鍖栨暟鎹簱銆佹樉绀洪厤缃俊鎭垨鍚姩涓 Postmaster 杩涚▼銆 + */ +int main(int argc, char *argv[]) { - char* mmap_env = NULL; - syscall_lock_init(); + char *mmap_env = NULL; + syscall_lock_init(); // 鍒濆鍖栫郴缁熻皟鐢ㄩ攣 mmap_env = gs_getenv_r("GAUSS_MMAP_THRESHOLD"); if (mmap_env != NULL) { - check_backend_env(mmap_env); - mmap_threshold = (size_t)atol(mmap_env); + check_backend_env(mmap_env); // 妫鏌ュ悗绔幆澧冨彉閲 + mmap_threshold = (size_t)atol(mmap_env); // 璁剧疆鍐呭瓨鏄犲皠闃堝 } - knl_instance_init(); + knl_instance_init(); // 鍒濆鍖栧唴鏍稿疄渚 + // 鍒涘缓澧為噺妫鏌ョ偣涓婁笅鏂 g_instance.increCheckPoint_context = AllocSetContextCreate( - INSTANCE_GET_MEM_CXT_GROUP(MEMORY_CONTEXT_STORAGE), - "IncreCheckPointContext", - ALLOCSET_DEFAULT_MINSIZE, - ALLOCSET_DEFAULT_INITSIZE, - ALLOCSET_DEFAULT_MAXSIZE, - SHARED_CONTEXT); + INSTANCE_GET_MEM_CXT_GROUP(MEMORY_CONTEXT_STORAGE), "IncreCheckPointContext", ALLOCSET_DEFAULT_MINSIZE, + ALLOCSET_DEFAULT_INITSIZE, ALLOCSET_DEFAULT_MAXSIZE, SHARED_CONTEXT); - g_instance.account_context = AllocSetContextCreate(g_instance.instance_context, - "StandbyAccontContext", - ALLOCSET_DEFAULT_MINSIZE, - ALLOCSET_DEFAULT_INITSIZE, - ALLOCSET_DEFAULT_MAXSIZE, - SHARED_CONTEXT); - - g_instance.comm_cxt.comm_global_mem_cxt = AllocSetContextCreate(g_instance.instance_context, - "CommunnicatorGlobalMemoryContext", - ALLOCSET_DEFAULT_MINSIZE, - ALLOCSET_DEFAULT_INITSIZE, - ALLOCSET_DEFAULT_MAXSIZE, - SHARED_CONTEXT); + // 鍒涘缓甯愭埛涓婁笅鏂 + g_instance.account_context = + AllocSetContextCreate(g_instance.instance_context, "StandbyAccontContext", ALLOCSET_DEFAULT_MINSIZE, + ALLOCSET_DEFAULT_INITSIZE, ALLOCSET_DEFAULT_MAXSIZE, SHARED_CONTEXT); - g_instance.builtin_proc_context = AllocSetContextCreate(g_instance.instance_context, - "builtin_procGlobalMemoryContext", - ALLOCSET_DEFAULT_MINSIZE, - ALLOCSET_DEFAULT_INITSIZE, - ALLOCSET_DEFAULT_MAXSIZE, - SHARED_CONTEXT); + // 鍒涘缓閫氫俊鍏ㄥ眬鍐呭瓨涓婁笅鏂 + g_instance.comm_cxt.comm_global_mem_cxt = + AllocSetContextCreate(g_instance.instance_context, "CommunnicatorGlobalMemoryContext", ALLOCSET_DEFAULT_MINSIZE, + ALLOCSET_DEFAULT_INITSIZE, ALLOCSET_DEFAULT_MAXSIZE, SHARED_CONTEXT); + + // 鍒涘缓鍐呯疆杩囩▼鍏ㄥ眬鍐呭瓨涓婁笅鏂 + g_instance.builtin_proc_context = + AllocSetContextCreate(g_instance.instance_context, "builtin_procGlobalMemoryContext", ALLOCSET_DEFAULT_MINSIZE, + ALLOCSET_DEFAULT_INITSIZE, ALLOCSET_DEFAULT_MAXSIZE, SHARED_CONTEXT); /* * Fire up essential subsystems: error and memory management * @@ -126,8 +129,9 @@ int main(int argc, char* argv[]) PmTopMemoryContext = t_thrd.top_mem_cxt; - knl_thread_init(MASTER_THREAD); + knl_thread_init(MASTER_THREAD); // 鍒濆鍖栧唴鏍哥嚎绋 + // 鍒涘缓浼細璇濅笂涓嬫枃 t_thrd.fake_session = create_session_context(t_thrd.top_mem_cxt, 0); t_thrd.fake_session->status = KNL_SESS_FAKE; @@ -137,19 +141,21 @@ int main(int argc, char* argv[]) MemoryContextSwitchTo(THREAD_GET_MEM_CXT_GROUP(MEMORY_CONTEXT_DEFAULT)); - progname = get_progname(argv[0]); + progname = get_progname(argv[0]); // 鑾峰彇绋嬪簭鍚 /* * Platform-specific startup hacks */ + // 骞冲彴鐗瑰畾鐨勫惎鍔ㄦ搷浣 startup_hacks(progname); /* if gaussdb's name is gs_encrypt, so run in encrypte_main() */ + // 濡傛灉绋嬪簭鍚嶆槸 "gs_encrypt"锛屽垯鎵ц encrypte_main() 鍑芥暟 if (!strcmp(progname, "gs_encrypt")) { return encrypte_main(argc, argv); } - init_plog_global_mem(); + init_plog_global_mem(); // 鍒濆鍖栧叏灞鏃ュ織鍐呭瓨 /* * Remember the physical location of the initially given argv[] array for @@ -191,7 +197,7 @@ int main(int argc, char* argv[]) * environment. If there is nothing there we fall back on the codepage. */ { - char* env_locale = NULL; + char *env_locale = NULL; if ((env_locale = gs_getenv_r("LC_COLLATE")) != NULL) { check_backend_env(env_locale); @@ -258,8 +264,8 @@ int main(int argc, char* argv[]) pgwin32_signal_initialize(); #endif - t_thrd.mem_cxt.gs_signal_mem_cxt = AllocSetContextCreate( - t_thrd.top_mem_cxt, "gs_signal", ALLOCSET_DEFAULT_MINSIZE, ALLOCSET_DEFAULT_INITSIZE, ALLOCSET_DEFAULT_MAXSIZE); + t_thrd.mem_cxt.gs_signal_mem_cxt = AllocSetContextCreate(t_thrd.top_mem_cxt, "gs_signal", ALLOCSET_DEFAULT_MINSIZE, + ALLOCSET_DEFAULT_INITSIZE, ALLOCSET_DEFAULT_MAXSIZE); if (NULL == t_thrd.mem_cxt.gs_signal_mem_cxt) { ereport(LOG, (errmsg("could not start a new thread, because of no enough system resource. "))); proc_exit(1); @@ -310,7 +316,7 @@ int main(int argc, char* argv[]) * is too brain-dead to provide a standard C execution environment * without help. Avoid adding more here, if you can. */ -static void startup_hacks(const char* progname) +static void startup_hacks(const char *progname) { /* * On some platforms, unaligned memory accesses result in a kernel trap; @@ -363,7 +369,8 @@ static void startup_hacks(const char* progname) * Help display should match the options accepted by PostmasterMain() * and PostgresMain(). */ -static void help(const char* progname) +// 姝ゅ嚱鏁扮敤浜庡瀹冩敮鎸佺殑鍛戒护琛岄夐」鍜岀敤娉曡繘琛岃鏄庛傝繖鏈夊姪浜庣悊瑙d唬鐮佺殑鍔熻兘鍜屽浣曚娇鐢ㄨ繖浜涢夐」鏉ヨ繍琛岀▼搴忋 +static void help(const char *progname) { printf(_("%s is the gaussdb server.\n\n"), progname); printf(_("Usage:\n %s [OPTION]...\n\n"), progname); @@ -462,7 +469,7 @@ static void help(const char* progname) #endif } -static void check_root(const char* progname) +static void check_root(const char *progname) { #ifndef WIN32 if (geteuid() == 0) { @@ -496,29 +503,49 @@ static void check_root(const char* progname) } #endif /* WIN32 */ } - -static char* get_current_username(const char* progname) +/* + * 鍔熻兘锛氳幏鍙栧綋鍓嶆搷浣滅郴缁熺敤鎴风殑鐢ㄦ埛鍚 + * + * 鍙傛暟鍒楄〃锛 + * progname锛氱▼搴忕殑鍚嶇О锛岀敤浜庨敊璇秷鎭 + * + * 杩斿洖鍊硷細 + * 褰撳墠鐢ㄦ埛鐨勭敤鎴峰悕锛屼互瀛楃涓插舰寮忚繑鍥 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁板湪涓嶅悓鐨勬搷浣滅郴缁熶笅浣跨敤涓嶅悓鐨勬柟娉曡幏鍙栫敤鎴峰悕銆 + * 鍦 Unix-like 绯荤粺涓嬶紝浣跨敤 getpwuid 鍑芥暟鑾峰彇鐢ㄦ埛鍚嶃 + * 鍦 Windows 绯荤粺涓嬶紝浣跨敤 GetUserName 鍑芥暟鑾峰彇鐢ㄦ埛鍚嶃 + * 鍑芥暟鍐呴儴鍖呭惈绾跨▼瀹夊叏鎺柦锛屼互纭繚鍦ㄥ绾跨▼鐜涓殑姝g‘鎬с + */ +static char *get_current_username(const char *progname) { #ifndef WIN32 - struct passwd* pw = NULL; - char* pRet = NULL; + struct passwd *pw = NULL; + char *pRet = NULL; + /* 鑾峰彇 getpwuid 鍑芥暟鐨勯攣锛屼互纭繚绾跨▼瀹夊叏 */ (void)syscalllockAcquire(&getpwuid_lock); + /* 鑾峰彇褰撳墠鐢ㄦ埛鐨勫瘑鐮侀」 */ pw = getpwuid(geteuid()); if (pw == NULL) { + /* 閲婃斁閿佸苟鎶ュ憡閿欒锛屽鏋滆幏鍙栧瘑鐮侀」澶辫触 */ (void)syscalllockRelease(&getpwuid_lock); write_stderr("%s: invalid effective UID: %d\n", progname, (int)geteuid()); exit(1); } /* Allocate new memory because later getpwuid() calls can overwrite it. */ pRet = MemoryContextStrdup(SESS_GET_MEM_CXT_GROUP(MEMORY_CONTEXT_CBB), pw->pw_name); + /* 閲婃斁閿佸苟杩斿洖鐢ㄦ埛鍚 */ (void)syscalllockRelease(&getpwuid_lock); return pRet; #else unsigned long namesize = 256 /* UNLEN */ + 1; - char* name = NULL; + char *name = NULL; + /* 鍦ㄥ唴瀛樹笂鍒嗛厤绌洪棿浠ュ瓨鍌ㄧ敤鎴峰悕 */ name = MemoryContextAlloc(SESS_GET_MEM_CXT_GROUP(MEMORY_CONTEXT_CBB), namesize); + /* 灏濊瘯鑾峰彇 Windows 鐢ㄦ埛鍚 */ if (!GetUserName(name, &namesize)) { write_stderr("%s: could not determine user name (GetUserName failed)\n", progname); exit(1); @@ -527,12 +554,29 @@ static char* get_current_username(const char* progname) return name; #endif } - +/* + * 鍔熻兘锛氬垵濮嬪寲绯荤粺璋冪敤閿 + * + * 鍙傛暟锛氭棤 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庡垵濮嬪寲澶氫釜绯荤粺璋冪敤閿侊紝浠ョ‘淇濆湪澶氱嚎绋嬬幆澧冧腑鐨勬纭с + * 姣忎釜閿佺敤浜庝繚鎶や笉鍚岀殑绯荤粺璋冪敤锛屼互閬垮厤骞跺彂璋冪敤鏃剁殑绔炰簤鏉′欢銆 + */ static void syscall_lock_init(void) { + /* 鍒濆鍖栬幏鍙栫敤鎴峰瘑鐮侀」鐨勯攣 */ syscalllockInit(&getpwuid_lock); + + /* 鍒濆鍖栫幆澧冨彉閲忛攣 */ syscalllockInit(&env_lock); + + /* 鍒濆鍖 dlerror 鍑芥暟鐨勯攣 */ syscalllockInit(&dlerror_lock); + + /* 鍒濆鍖 Kerberos 杩炴帴閿 */ syscalllockInit(&kerberos_conn_lock); + + /* 鍒濆鍖栬鍙栧姞瀵嗘暟鎹殑閿 */ syscalllockInit(&read_cipher_lock); } diff --git a/src/gausskernel/process/postmaster/.vscode/settings.json b/src/gausskernel/process/postmaster/.vscode/settings.json new file mode 100644 index 000000000..decddbd7b --- /dev/null +++ b/src/gausskernel/process/postmaster/.vscode/settings.json @@ -0,0 +1,8 @@ +{ + "files.associations": { + "array": "cpp", + "string_view": "cpp", + "initializer_list": "cpp", + "utility": "cpp" + } +} \ No newline at end of file diff --git a/src/gausskernel/process/postmaster/aiocompleter.cpp b/src/gausskernel/process/postmaster/aiocompleter.cpp index 6d055f45e..0e05fbe9a 100644 --- a/src/gausskernel/process/postmaster/aiocompleter.cpp +++ b/src/gausskernel/process/postmaster/aiocompleter.cpp @@ -1,3 +1,20 @@ +/* + 涓嬫娉ㄩ噴鎻忚堪浜嗘枃浠剁殑鐗堟潈淇℃伅浠ュ強瀵逛簬AIO瀹屾垚绾跨▼鐨勫熀鏈粙缁嶃傚畠浠敤浜庡鐞嗗紓姝O璇锋眰锛屼互鍙婂浣曞惎鍔ㄥ拰鍋滄杩欎簺绾跨▼銆 + * aiocompleter.cpp鏂囦欢鐨勬暣浣撳姛鑳芥槸鐢ㄤ簬AIO 瀹屾垚鍣ㄧ嚎绋嬪畬鎴愰鍙栵紙Prefetch 锛夊拰鍚庣鍐欏叆锛圔ackWrite 锛塈/O鎿嶄綔 + * 浣跨敤鍦烘櫙锛欰IO 瀹屾垚鍣ㄧ嚎绋嬩娇鐢 Linux Native AIO 瀹屾垚 AIO 璇锋眰銆 + * 鍗曚釜 AIO 瀹屾垚鍣ㄧ嚎绋嬩负涓庣壒瀹 AIO 涓婁笅鏂囧拰 I/O 浼樺厛绾х浉鍏宠仈鐨 AIO 闃熷垪鎻愪緵鏈嶅姟銆 + * 1. 鍋滄锛氬彧鑳藉湪鎵鏈夊伐浣滅嚎绋嬫垨鍚庡彴鏁版嵁鍐欙紙bgwriter锛夌嚎绋嬮兘宸插仠姝㈠悗锛孉IO瀹屾垚鍣ㄧ嚎绋嬫墠鑳藉仠姝€ + * + * 2. 鍚姩锛氬綋postmaster鍚姩瀛愯繘绋嬬粨鏉熸垨鏄湪鎵ц褰掓。鎭㈠鐨勫紑濮嬶紝AIO瀹屾垚鍣ㄧ嚎绋嬩細绔嬪嵆鍚姩锛屽苟涓旀寔缁繚鎸佸紑鍚姸鎬侊紝鐩村埌postemaster涓嬭揪缁堟鍛戒护 + * [1.姝e父缁堟锛歋IGTERM鎸囦护锛氭寚绀虹嚎绋嬬瓑寰呬换浣曟寕璧风殑 AIO 骞跺仛濂介鍑哄噯澶囥 +<<<<<<< HEAD + * 2.绱фョ粓姝細SIGQUIT鎸囦护锛氬綋AIO瀹屾垚鍣ㄧ嚎绋嬫剰澶栭鍑猴紝postmaster浼氬皢鍏惰涓衡滃悗绔穿婧冣濈姸鎬侊紝鍏变韩鍐呭瓨鍙兘閬彈鎹熷潖. + * 姝ゆ椂閫氳繃SIGQUIT鎸囦护缁堟鍓╀綑鐨勫悗绔悗鍚姩鎭㈠寰幆] +======= + * 2.绱фョ粓姝細SIGQUIT鎸囦护锛氬綋AIO瀹屾垚鍣ㄧ嚎绋嬫剰澶栭鍑猴紝postmaster浼氬皢鍏惰涓衡滃悗绔穿婧冣濈姸鎬侊紝鍏变韩鍐呭瓨鍙兘閬彈鎹熷潖锛屾鏃堕氳繃SIGQUIT鎸囦护缁堟鍓╀綑鐨勫悗绔悗鍚姩鎭㈠寰幆] +>>>>>>> 108c7fd5357dfbed4193fd5eb60e4bd6db01031f + * + */ /* * Copyright (c) 2020 Huawei Technologies Co.,Ltd. * @@ -39,6 +56,7 @@ * * ------------------------------------------------------------------------- */ +/*寮曞叆鎵闇鐨勭郴缁熷簱鍜屾ā鍧椼*/ #include "postgres.h" #include "knl/knl_variable.h" #include "gssignal/gs_signal.h" @@ -52,6 +70,15 @@ #include "utils/memutils.h" #include +/* +瑙i噴浜咥IO completer绾跨▼鐨勭粨鏋勫拰鏁扮粍銆傛瘡涓嚎绋嬮兘鏈変竴涓敮涓鐨勪笂涓嬫枃锛屽彲鑳藉鐞嗕笉鍚岀被鍨嬬殑璇锋眰銆 +aioCompltrThread_t 缁撴瀯瀵瑰簲浜庢瘡涓狝IO completer绾跨▼锛屽瓨鍌ㄥ湪 compltrArray 鏁扮粍涓紝璇ユ暟缁勫寘鍚 MAX_AIOCOMPLTR_THREADS 涓Ы浣嶃 +compltrArray 鏁扮粍鍦 postmaster 涓婁笅鏂囦腑瀹氫箟銆 + +绗竴缁勫弬鏁 context銆乪ventsp 鍜 tid 鏄湪绾跨▼鍚姩鏃惰缃殑锛屽畠浠姣忎釜绾跨▼閮芥槸鍞竴鐨勩 +cmpltrDesc 鎸囬拡鎸囧悜 compltrDescArray 涓殑 AioCompltrDesc_t 缁撴瀯锛屽叾涓寘鍚簡瀹屾垚鍣ㄧ殑鍙傛暟銆傚悓绫诲瀷鐨勫畬鎴愬櫒鍏变韩鐩稿悓鐨勬弿杩扮銆 +compltrDescArray 鏁扮粍涓湁 NUM_AIOCOMPLTR_TYPES 涓 AioCompltrDesc_t 缁撴瀯锛屾瘡涓粨鏋勪唬琛ㄤ竴涓 AioCompltrType銆 +*/ /* * Each AIO completer thread has a unique context, and potentially * processes different types of requests. There is an aioCompltrThread_t @@ -69,46 +96,69 @@ * The compltrDescArray array is defined in the postmaster context. * */ -int CompltrReadReq(void* aioDesc, long res); -int CompltrWriteReq(void* aioDesc, long res); -int CompltrReadCUReq(void* aioDesc, long res); -int CompltrWriteCUReq(void* aioDesc, long res); +/* + 杩欓噷澹版槑浜嗕竴浜涘嚱鏁板師鍨嬶紝鐢ㄤ簬澶勭悊涓嶅悓绫诲瀷鐨凙IO璇锋眰銆 +*/ +int CompltrReadReq(void* aioDesc, long res);// 鍙戣捣寮傛璇诲彇璇锋眰 +int CompltrWriteReq(void* aioDesc, long res);// 鍙戣捣寮傛鍐欏叆璇锋眰 +int CompltrReadCUReq(void* aioDesc, long res);// 鍙戣捣寮傛璇诲彇CU锛圕ontrol Unit锛屾帶鍒跺崟鍏冿級璇锋眰 +int CompltrWriteCUReq(void* aioDesc, long res);// 鍙戣捣寮傛鍐欏叆CU璇锋眰 -ThreadId Compltrfork_exec(int compltrIdx); +ThreadId Compltrfork_exec(int compltrIdx);// 鍒涘缓绾跨▼骞舵墽琛屽紓姝/O澶勭悊 /* * GUC parameters */ /* Maximum number of Completer threads -compile time define */ -#define MAX_AIOCOMPLTR_THREADS 4 +#define MAX_AIOCOMPLTR_THREADS 4 //鍦ㄧ紪璇戞椂瀹氫箟鐨勫畯锛岀敤浜庤缃紓姝/O鎿嶄綔瀹屾垚鑰呯嚎绋嬫睜鐨勬渶澶х嚎绋嬫暟閲忋傜敤浜庨檺鍒朵簡鍙互鍚屾椂杩愯鐨勫畬鎴愯呯嚎绋嬬殑鏈澶ф暟閲忋 /* Number of Completer threads and the number of sets of Completers */ -const int AioCompltrThreads = 4; -int AioCompltrSets = 1; -const int AioCompltrShutdownTimeout = 1; +const int AioCompltrThreads = 4;// 鏁存暟甯搁噺锛岃〃绀哄紓姝/O鎿嶄綔瀹屾垚鑰呯嚎绋嬫睜涓殑绾跨▼鏁伴噺銆傝繖閲岃缃簡4涓畬鎴愯呯嚎绋嬨 +int AioCompltrSets = 1; // 鏁存暟鍙橀噺锛岃〃绀哄畬鎴愯呯嚎绋嬫睜鐨勯泦鏁般傛澶勮缃彧鏈変竴涓嚎绋嬫睜闆嗐 +const int AioCompltrShutdownTimeout = 1;// 鏁存暟甯搁噺锛岃〃绀哄紓姝/O瀹屾垚鑰呯嚎绋嬫睜鍏抽棴鐨勮秴鏃舵椂闂达紝姝ゅ璁剧疆涓1绉掋 /* Completer callback to handle the AIO event */ -typedef int (*AioCallback_t)(void*, long); +typedef int (*AioCallback_t)(void*, long);// 瀹氫箟鍑芥暟鎸囬拡绫诲瀷 AioCallback_t锛岀敤浜庤〃绀哄紓姝/O浜嬩欢鐨凜ompleter鍥炶皟鍑芥暟銆 + // 鎸囧悜涓涓弬鏁颁负 (void*, long) 骞惰繑鍥 int 绫诲瀷鐨勫嚱鏁 /* * Completer Thread definitions */ +/* +缁撴瀯浣撶被鍨 AioCompltrDesc锛岀敤浜庢弿杩癆IO瀹屾垚鍣ㄧ殑鐗规с佸弬鏁颁互鍙婅姹傚睘鎬с +瀹冨寘鍚互涓嬪瓧娈碉細 + reqtype: AioCompltrType锛岃〃绀哄畬鎴愬櫒鐨勭被鍨嬶紝鐢ㄤ簬鏍囪瘑涓嶅悓绫诲瀷鐨凙IO璇锋眰銆 + callback: AioCallback_t锛屾槸涓涓嚱鏁版寚閽堬紝鎸囧悜鐢ㄤ簬澶勭悊AIO浜嬩欢鐨勫洖璋冨嚱鏁般 + maxevents: int锛岃〃绀哄厑璁稿悓鏃跺鐞嗙殑鏈澶IO浜嬩欢鏁伴噺銆 + min_nr: int锛岃〃绀虹瓑寰呯殑鏈灏忎簨浠舵暟閲忥紝褰撹揪鍒版鏁伴噺鏃讹紝瀹屾垚鍣ㄥ彲浠ュ紑濮嬪鐞嗚繖浜涗簨浠躲 + max_nr: int锛岃〃绀烘渶澶у彲妫绱㈢殑浜嬩欢鏁伴噺锛屽嵆涓娆′粠鍐呮牳鑾峰彇鐨勬渶澶т簨浠舵暟閲忋 + timeout: int锛岃〃绀虹瓑寰呬簨浠剁殑鏈澶ф椂闂达紝瓒呰繃姝ゆ椂闂村悗锛屽畬鎴愬櫒鍙互澶勭悊宸茶幏鍙栫殑浜嬩欢銆 + reqprio: AioPriority锛岃〃绀篈IO璇锋眰鐨勪紭鍏堢骇銆 +*/ typedef struct AioCompltrDesc { /* Completer characteristics */ - AioCompltrType reqtype; /* Completer type */ - AioCallback_t callback; /* Completer function */ - int maxevents; /* AIO Maximum events in progress */ + AioCompltrType reqtype; /* Completer type 琛ㄧず瀹屾垚鍣ㄧ殑绫诲瀷锛岀敤浜庢爣璇嗕笉鍚岀被鍨嬬殑AIO璇锋眰銆*/ + AioCallback_t callback; /* Completer function 鍑芥暟鎸囬拡锛屾寚鍚戠敤浜庡鐞咥IO浜嬩欢鐨勫洖璋冨嚱鏁*/ + int maxevents; /* AIO Maximum events in progress 琛ㄧず鍏佽鍚屾椂澶勭悊鐨勬渶澶IO浜嬩欢鏁伴噺*/ /* Completer parameters */ - int min_nr; /* Min number of events to wait for */ - int max_nr; /* Max number of events to retrieve */ - int timeout; /* Max time to wait */ + int min_nr; /* Min number of events to wait for 绀虹瓑寰呯殑鏈灏忎簨浠舵暟閲忥紝褰撹揪鍒版鏁伴噺鏃讹紝瀹屾垚鍣ㄥ彲浠ュ紑濮嬪鐞嗚繖浜涗簨浠*/ + int max_nr; /* Max number of events to retrieve 琛ㄧず鏈澶у彲妫绱㈢殑浜嬩欢鏁伴噺锛屽嵆涓娆′粠鍐呮牳鑾峰彇鐨勬渶澶т簨浠舵暟閲*/ + int timeout; /* Max time to wait 琛ㄧず绛夊緟浜嬩欢鐨勬渶澶ф椂闂达紝瓒呰繃姝ゆ椂闂村悗锛屽畬鎴愬櫒鍙互澶勭悊宸茶幏鍙栫殑浜嬩欢*/ /* Request properties */ - AioPriority reqprio; /* Request priority served */ + AioPriority reqprio; /* Request priority served 琛ㄧずAIO璇锋眰鐨勪紭鍏堢骇*/ } AioCompltrDesc_t; +/* + AioCompltrThread_t 缁撴瀯浣擄紝鐢ㄤ簬琛ㄧず寮傛I/O Completer绾跨▼鐨勪俊鎭拰鐘舵併 + + context锛歩o_context_t 琛ㄧず寮傛I/O涓婁笅鏂囷紝鐢ㄤ簬绠$悊鍜岃窡韪紓姝/O鎿嶄綔銆 + eventsp锛歴truct io_event* 鎸囧悜 io_event 缁撴瀯浣撶殑鎸囬拡锛岃〃绀哄紓姝/O浜嬩欢鐨勬寚閽堟暟缁勩傜敤浜庡瓨鍌ㄥ紓姝/O鎿嶄綔鐨勪簨浠讹紝浠ヤ究鍚庣画澶勭悊銆 + tid锛歍hreadId 琛ㄧず寮傛I/O Completer绾跨▼鐨勭嚎绋婭D銆傜敤浜庢爣璇嗗拰绠$悊绾跨▼銆 + compltrDescp锛欰ioCompltrDesc_t* 鎸囧悜 AioCompltrDesc_t 绫诲瀷鐨勬寚閽堬紝AioCompltrDesc_t鐢ㄤ簬鎻忚堪AIO瀹屾垚鍣ㄧ殑鐗规с佸弬鏁颁互鍙婅姹傚睘鎬 +*/ typedef struct { io_context_t context; /* AIO context */ struct io_event* eventsp; /* AIO events to process */ @@ -116,6 +166,8 @@ typedef struct { AioCompltrDesc_t* compltrDescp; /* Completer descriptor */ } AioCompltrThread_t; + + /* * The compltrDescArray contains the description of the different types * of completer threads. These are used to setup the context for each @@ -158,6 +210,20 @@ typedef struct { * policy employed. CFQ takes into account the priorities, but there is also a * wide gulf between the priority of sync and async i/o that dwarfs these. */ +/* +鍒濆鍖朿ompltrDescArray鏁扮粍锛岀敤浜庨厤缃笉鍚岀被鍨嬬殑寮傛I/O Completer绾跨▼鐨勫弬鏁般 + +- AioCompltrDesc_t锛欰ioCompltrDesc缁撴瀯浣撶被鍨嬶紝鐢ㄤ簬鎻忚堪AIO Completer鐨勭壒鎬с佸弬鏁颁互鍙婅姹傚睘鎬с +- NUM_AIOCOMPLTR_TYPES锛氬父閲忥紝琛ㄧず寮傛I/O Completer绾跨▼鐨勭被鍨嬫暟閲忋傛暟缁 compltrDescArray鐨勫ぇ灏 +- compltrDescArray[NUM_AIOCOMPLTR_TYPES]锛氬寘鍚簡涓嶅悓绫诲瀷鐨勫紓姝/O Completer绾跨▼鐨勬弿杩颁俊鎭殑鏁扮粍銆 +- `PageListPrefetchType`锛氶〉鍒楄〃棰勫彇璇锋眰绫诲瀷銆傝绫诲瀷鐨勫紓姝/O瀹屾垚鍣ㄧ嚎绋嬪鐞嗗悗鍙板紓姝ヨ鍙栨暟鎹〉鍒板唴瀛樼殑璇锋眰锛屼互鍑忓皯鏌ヨ鎴栨搷浣滄椂鐨勫欢杩熴 + +- `PageListBackWriteType`锛氶〉鍒楄〃鍚庡彴鍐欏叆璇锋眰绫诲瀷銆傝绫诲瀷鐨勫紓姝/O瀹屾垚鍣ㄧ嚎绋嬪鐞嗗皢鏁版嵁椤典粠鍐呭瓨鍐欏洖纾佺洏鐨勮姹傦紝閫氬父鐢ㄤ簬鎵ц鍚庡彴鐨勬暟鎹〉鍥炲啓鎿嶄綔銆 + +- `CUListPrefetchType`锛欳U锛圕olumn Unit锛夊垪琛ㄩ鍙栬姹傜被鍨嬨傜被浼间簬椤靛垪琛ㄩ鍙栵紝璇ョ被鍨嬬殑寮傛I/O瀹屾垚鍣ㄧ嚎绋嬪鐞嗗悗鍙板紓姝ヨ鍙栧垪瀛樺偍鍗曞厓锛圕U锛夊埌鍐呭瓨鐨勮姹傦紝浠ヤ紭鍖栨煡璇㈡ц兘銆 + +- `CUListWriteType`锛欳U鍒楄〃鍐欏叆璇锋眰绫诲瀷銆備笌椤靛垪琛ㄥ悗鍙板啓鍏ョ被浼硷紝璇ョ被鍨嬬殑寮傛I/O瀹屾垚鍣ㄧ嚎绋嬪鐞嗗皢淇敼鍚庣殑鍒楀瓨鍌ㄥ崟鍏冿紙CU锛変粠鍐呭瓨鍐欏洖纾佺洏鐨勮姹傘 +*/ AioCompltrDesc_t compltrDescArray[NUM_AIOCOMPLTR_TYPES] = { /* reqtype, callback, maxevents, min_nr, max_nr, tsec, reqprio */ {PageListPrefetchType, CompltrReadReq, 65536, 1, 16384, 60, HighPri}, @@ -171,18 +237,25 @@ AioCompltrDesc_t compltrDescArray[NUM_AIOCOMPLTR_TYPES] = { * any AIO Completer theads. The Array contains one element for * each completer thread. */ -AioCompltrThread_t compltrArray[MAX_AIOCOMPLTR_THREADS]; + +AioCompltrThread_t compltrArray[MAX_AIOCOMPLTR_THREADS]; // MAX_AIOCOMPLTR_THREADS 4 /* * AioCompltrReady flag is set/cleared from the postmaster * context. It is used to remember the Completer state. + * 鐢ㄤ簬鏍囪寮傛I/O瀹屾垚鑰呯嚎绋嬫槸鍚﹀噯澶囧氨缁 */ -static bool volatile AioCompltrReady = false; +static bool volatile AioCompltrReady = false;// 鍒濆鍖杅alse锛岃〃绀哄紓姝/O瀹屾垚鍣ㄧ嚎绋嬪皻鏈噯澶囧氨缁 -/* Associate a template with a thread index */ +/* Associate a template with a thread index +鐢ㄤ簬鍏宠仈绾跨▼绱㈠紩锛坱hreadIdx锛変笌Completer鎻忚堪鏁扮粍 compltrDescArray 涓殑妯℃澘 +*/ #define AIOCOMPLTR_TEMPLATE(threadIdx) (&compltrDescArray[(threadIdx) % NUM_AIOCOMPLTR_TYPES]) -/* Determine a completer thread index to be used for a given type and h val */ +/* Determine a completer thread index to be used for a given type and h val +鐢ㄤ簬纭畾缁欏畾绫诲瀷锛坱ypeIdx锛夊拰鍝堝笇鍊硷紙h锛夌殑寮傛I/O Completer绾跨▼绱㈠紩銆 +閫氳繃璁$畻鍑哄湪 compltrArray 涓殑绱㈠紩锛屼互閫夋嫨閫傚綋鐨凜ompleter绾跨▼鏉ュ鐞嗙壒瀹氱被鍨嬬殑寮傛I/O璇锋眰銆 +*/ #define AIOCOMPLTR_THREAD_IDX(typeIdx, h) ((((h) % AioCompltrSets) * NUM_AIOCOMPLTR_TYPES) + (typeIdx)) /* @@ -193,6 +266,9 @@ static bool volatile AioCompltrReady = false; * @Return: true start ok * @See also: */ +/*鐢ㄤ簬妫鏌ュ紓姝/O瀹屾垚鑰呮槸鍚﹀凡缁忓惎鍔ㄧ殑鍑芥暟銆 + *杩斿洖甯冨皵鍊硷細濡傛灉寮傛I/O Completers宸插噯澶囧氨缁紝鍒欒繑鍥 true锛屽惁鍒欒繑鍥 false +*/ bool AioCompltrIsReady(void) { return AioCompltrReady; @@ -204,6 +280,9 @@ bool AioCompltrIsReady(void) * @Return: function ptr * @See also: */ +/*鐢ㄤ簬鑾峰彇鐗瑰畾璇锋眰绫诲瀷鐨勫洖璋冨嚱鏁扮殑鍑芥暟銆 + *鎺ュ彈涓涓弬鏁 reqType锛岃〃绀哄紓姝/O completer绫诲瀷锛 + *杩斿洖涓庤绫诲瀷鐩稿叧鑱旂殑鍥炶皟鍑芥暟鎸囬拡銆*/ AioCallback_t ComptrCallback(AioCompltrType reqType) { return compltrDescArray[reqType].callback; @@ -215,6 +294,10 @@ AioCallback_t ComptrCallback(AioCompltrType reqType) * @Return: Request priority * @See also: */ +/*鐢ㄤ簬鑾峰彇鐗瑰畾璇锋眰绫诲瀷鐨勪紭鍏堢骇鐨勫嚱鏁般 + *鎺ュ彈涓涓弬鏁 reqType锛岃〃绀哄紓姝/O completer绫诲瀷 + *杩斿洖璇ョ被鍨嬭姹傜殑浼樺厛绾с + */ short CompltrPriority(AioCompltrType reqType) { return compltrDescArray[reqType].reqprio; @@ -228,6 +311,10 @@ short CompltrPriority(AioCompltrType reqType) * @Return:io_context * @See also: */ +/*鐢ㄤ簬鑾峰彇鐗瑰畾璇锋眰绫诲瀷鐨勫畬鎴愯呬笂涓嬫枃鐨勫嚱鏁般 + *鎺ュ彈涓や釜鍙傛暟锛宺eqType 琛ㄧず寮傛I/O completer绫诲瀷锛宧 琛ㄧず绱㈠紩 + *鏍规嵁绫诲瀷鍜岀储寮曡幏鍙栫浉搴旂殑completer涓婁笅鏂囷紙io_context_t锛 + */ io_context_t CompltrContext(AioCompltrType reqType, int h) { return compltrArray[AIOCOMPLTR_THREAD_IDX(reqType, h)].context; @@ -237,9 +324,12 @@ io_context_t CompltrContext(AioCompltrType reqType, int h) /* * Signal handlers */ -static void CompltrConfig(SIGNAL_ARGS); -static void CompltrQuickDie(SIGNAL_ARGS); -static void CompltrShutdown(SIGNAL_ARGS); +/* +鐢ㄤ簬鍐呴儴瀹炵幇鍜屽鐞嗙壒瀹氱殑淇″彿浜嬩欢鐨勭鏈夊嚱鏁板師鍨嬪0鏄庯紝褰撲俊鍙蜂簨浠跺彂鐢熸椂璋冪敤銆 +*/ +static void CompltrConfig(SIGNAL_ARGS);// 鐢ㄤ簬閰嶇疆寮傛I/O completer鐨勭浉鍏冲弬鏁板拰璁剧疆 +static void CompltrQuickDie(SIGNAL_ARGS);// 鐢ㄤ簬蹇熺粓姝㈠紓姝/O completer绾跨▼銆 +static void CompltrShutdown(SIGNAL_ARGS);// 鐢ㄤ簬鍦ㄥ紓姝/O completer绾跨▼閫鍑烘椂鎵ц娓呯悊鍜屽叧闂搷浣 /* * @Description: Compltrfork_exec() and AioCompltrStart() are used to start the @@ -260,9 +350,17 @@ static void CompltrShutdown(SIGNAL_ARGS); * @Return: thread id * @See also: */ +/* +鐢ㄤ簬鍚姩寮傛I/O Completer绾跨▼銆傚湪褰撳墠鐨勫疄鐜颁腑锛宱penGauss骞朵笉鏀寔寮傛I/O锛屾墍浠ヨ鍑芥暟鍙細鍙戝嚭閿欒娑堟伅琛ㄧず涓嶆敮鎸侊紝骞惰繑鍥炴棤鏁堢殑绾跨▼ID銆 + +璇ュ嚱鏁颁細鏍煎紡鍖栧懡浠よ鍙傛暟鍒楄〃锛坅rglist锛夛紝鐒跺悗浣跨敤 fork 鍜 exec 鍑芥暟鍒涘缓涓涓柊鐨勭嚎绋嬫潵鎵ц寮傛I/O Completer绾跨▼鐨勫鐞嗐 +鍏朵腑锛宑ompltrIdx 琚浆鎹负涓涓3瀛楃鐨勫瓧绗︿覆锛岃繖鏍峰彲浠ラ伩鍏嶅湪浠g爜涓渶瑕佺壒娈婂鐞嗚繖涓弬鏁帮紝鍥犱负鍙傛暟鐨勪紶閫掑湪鎵ц杩囩▼涓凡缁忚澶勭悊濂戒簡銆 +*/ ThreadId Compltrfork_exec(int compltrIdx) { + // 鍙戝嚭閿欒娑堟伅锛岃〃绀轰笉鏀寔寮傛I/O ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("openGauss current do not support AIO"))); + // 杩斿洖鏃犳晥鐨勭嚎绋婭D return InvalidTid; } @@ -287,87 +385,101 @@ ThreadId Compltrfork_exec(int compltrIdx) */ int AioCompltrStart(void) { - int error = 0; - int try_times = 0; + int error = 0;// 閿欒鐮佸垵濮嬪寲 + int try_times = 0;// 灏濊瘯娆℃暟鍒濆鍖 /* * Only allow MAX_AIOCOMPLTR_THREADS */ + //妫鏌ュ綋鍓嶉厤缃殑 AIO Completer 绾跨▼鏁伴噺鏄惁瓒呰繃浜嗛瀹氫箟鐨勬渶澶ф暟閲 MAX_AIOCOMPLTR_THREADS if (AioCompltrThreads > MAX_AIOCOMPLTR_THREADS) { - error = 1; - return error; + error = 1;// 璁剧疆閿欒鐮 + return error;// 杩斿洖閿欒鐮,涓柇鍑芥暟鎵ц } - + // 璋冪敤瀹夊叏鍐呭瓨鍑芥暟memset_s 鍒濆鍖 compltrArray锛屽皢鍐呭瓨璁剧疆涓洪浂 errno_t rc = memset_s(&compltrArray, sizeof(AioCompltrThread_t) * MAX_AIOCOMPLTR_THREADS, 0, sizeof(AioCompltrThread_t) * MAX_AIOCOMPLTR_THREADS); + //閿欒妫鏌,鐢ㄤ簬纭繚 memset_s 鍑芥暟鏄惁鎵ц鎴愬姛銆傚鏋 rc锛堣繑鍥炲硷級涓嶄负闆讹紝琛ㄧず鍐呭瓨鍒濆鍖栧嚭鐜颁簡閿欒 securec_check(rc, "\0", "\0"); /* * Initialize the compltrArray */ + //鍒濆鍖 compltrArray 鏁扮粍 for (int i = 0; i < AioCompltrThreads; i++) { - try_times = 0; + try_times = 0;// 灏濊瘯娆℃暟褰掗浂 /* Assign a template to the thread descriptor */ - compltrArray[i].compltrDescp = AIOCOMPLTR_TEMPLATE(i); + compltrArray[i].compltrDescp = AIOCOMPLTR_TEMPLATE(i);// 涓虹嚎绋嬫弿杩扮鍒嗛厤瀵瑰簲鐨勬ā鏉 /* Create the i/o queue and fill in the context */ do { + // 浣跨敤 io_setup 鍑芥暟鍒涘缓寮傛 I/O 闃熷垪锛屽弬鏁颁负褰撳墠绾跨▼鐨勬渶澶т簨浠舵暟鍜岄槦鍒椾笂涓嬫枃銆 error = io_setup(compltrArray[i].compltrDescp->maxevents, &compltrArray[i].context); + // 濡傛灉鎴愬姛鍒涘缓闃熷垪鎴栬呴亣鍒扮殑閿欒涓嶆槸 EAGAIN锛堣〃绀鸿祫婧愭殏鏃朵笉鍙敤锛夛紝鍒欒烦鍑哄惊鐜 if (error == 0 || error != -EAGAIN) { break; } - try_times++; + try_times++; // 灏濊瘯娆℃暟澧炲姞 + // 鎵撳嵃鏃ュ織锛岃褰曞綋鍓嶅皾璇曠殑绾跨▼ID銆佸皾璇曟鏁板拰閿欒鐮併 ereport(LOG, (errmsg("AIO Startup, Completer thread id =%d try times=%d, error=%d", i, try_times, error))); - pg_usleep(100000L); - } while (try_times < 5); + pg_usleep(100000L);// 寤惰繜 100,000 寰锛0.1 绉掞級锛岀劧鍚庣户缁笅涓娆″皾璇曘 + } while (try_times < 5);// 寰幆缁х画锛岀洿鍒版垚鍔熷垱寤洪槦鍒楁垨鑰呭皾璇曟鏁拌揪鍒 5 娆° if (error != 0) { - goto AioCompltrStartError; + goto AioCompltrStartError;// 鍙戠敓閿欒鏃惰烦杞埌閿欒澶勭悊鏍囩 } /* Allocate the event array for the thread */ + /* 涓虹嚎绋嬪垎閰嶄簨浠舵暟缁勭殑鍐呭瓨 鐢ㄤ簬瀛樺偍浜嬩欢鏁扮粍 + compltrArray[i].compltrDescp->max_nr 琛ㄧず浜嬩欢鏁扮粍鐨勬渶澶уぇ灏忥紝sizeof(struct io_event) 琛ㄧず鍗曚釜浜嬩欢鐨勫ぇ灏忋*/ compltrArray[i].eventsp = (io_event*)malloc(compltrArray[i].compltrDescp->max_nr * sizeof(struct io_event)); - + // 妫鏌ュ唴瀛樺垎閰嶆槸鍚︽垚鍔燂紝澶辫触鍒欒繘鍏f璇彞鍐呴儴 if (compltrArray[i].eventsp == (struct io_event*)NULL) { /* malloc failed for some reason... */ - error = 2; + error = 2;// 璁剧疆閿欒鐮佷负 2锛岃〃绀哄唴瀛樺垎閰嶅け璐 + //鎵撳嵃鏃ュ織锛岃褰曞唴瀛樺垎閰嶅け璐ョ殑璇︾粏淇℃伅锛屽寘鎷渶澶т簨浠舵暟鍜岄敊璇爜銆 ereport(LOG, (errmsg("AIO Startup malloc io_event failed: max_nr(%d), %d", compltrArray[i].compltrDescp->max_nr, error))); + // 璺宠浆鍒伴敊璇鐞嗘爣绛 AioCompltrStartError锛屾墽琛岄敊璇鐞嗘搷浣 goto AioCompltrStartError; } /* Start AIO Completer thread */ + //浣跨敤 Compltrfork_exec(i) 鍑芥暟鍚姩涓涓紓姝 I/O 瀹屾垚绾跨▼锛屽苟灏嗙嚎绋嬬储寮 i 浣滀负鍙傛暟浼犻掔粰鍑芥暟銆傚嚱鏁拌繑鍥炵嚎绋嬬殑 ID銆 compltrArray[i].tid = Compltrfork_exec(i); + // 妫鏌ョ嚎绋嬫槸鍚︽垚鍔熷惎鍔ㄣ傚鏋滃惎鍔ㄥけ璐ワ紝浼氳繘鍏ユ潯浠跺唴閮ㄣ if (compltrArray[i].tid == (ThreadId)-1) { /* starting a thread failed */ - error = 3; + error = 3;// 璁剧疆閿欒鐮佷负 3锛岃〃绀哄惎鍔ㄧ嚎绋嬪け璐 + // 鎵撳嵃鏃ュ織锛岃褰曞惎鍔ㄧ嚎绋嬪け璐ョ殑璇︾粏淇℃伅锛屽寘鎷敊璇爜銆 ereport(LOG, (errmsg("Start AIO Completer thread failed: %d", error))); - goto AioCompltrStartError; + goto AioCompltrStartError; // 鍙戠敓閿欒鏃惰烦杞埌閿欒澶勭悊鏍囩 } }; /* The AIO Completers are open for business */ - AioCompltrReady = true; + AioCompltrReady = true;// AIO Completers 鍑嗗灏辩华 /* successful return */ return 0; +//閿欒澶勭悊鏍囩 AioCompltrStartError 鏍囪瘑閿欒澶勭悊鐨勮捣濮嬩綅缃 AioCompltrStartError: /* * If anything went wrong, then stop any threads started * and deallocate the resources. */ - AioCompltrStop(SIGTERM); - ereport(LOG, (errmsg("AIO Startup Failed,error=%d", error))); + AioCompltrStop(SIGTERM);// 鍋滄宸插惎鍔ㄧ殑寮傛 I/O 瀹屾垚绾跨▼骞堕噴鏀捐祫婧 + ereport(LOG, (errmsg("AIO Startup Failed,error=%d", error)));// 璁板綍鍚姩澶辫触鐨勯敊璇棩蹇 - return error; + return error;// 杩斿洖閿欒鐮 } /* @@ -380,39 +492,45 @@ AioCompltrStartError: void AioCompltrStop(int signal) { gs_thread_t thread; - AioCompltrReady = false; + AioCompltrReady = false;// 鍋滄AIO Completer绾跨▼鐨勬爣蹇楄缃负false锛岃〃绀虹嚎绋嬩笉鍐嶈繍琛 /* * Stop the threads in the compltrArray. */ + // 寰幆閬嶅巻AIO Completer绾跨▼鏁扮粍锛屽仠姝㈡墍鏈夌嚎绋 for (int i = 0; i < AioCompltrThreads; i++) { /* * Stop the threads that were started */ + // 妫鏌ョ嚎绋嬫爣璇嗙鏄惁鏈夋晥 if (compltrArray[i].tid != 0) { + // 濡傛灉绾跨▼宸插惎鍔紝浣跨敤gs_signal_send鍑芥暟鍚戠嚎绋嬪彂閫佷俊鍙峰仠姝㈢嚎绋嬶紝灏嗕紶鍏ョ殑signal浣滀负淇″彿绫诲瀷銆 if (gs_signal_send(compltrArray[i].tid, signal) < 0) { + // 濡傛灉鍙戦佷俊鍙峰け璐ワ紝璁板綍閿欒鏃ュ織锛屾寚鏄庡摢涓嚎绋嬬殑淇″彿鍙戦佸け璐ャ ereport(LOG, (errmsg("kill(%ld,%d) failed: %m", (long)(compltrArray[i].tid), signal))); } } } - + // 濡傛灉鏁版嵁搴撴鍦ㄥ穿婧冿紝鍙渶鏉姝籧ompleters骞堕鍑恒 if (signal == SIGQUIT) { /* * if the database is crashing just kill the completers * and bail-out. */ - return; + return;// 鐩存帴杩斿洖锛屾潃姝籧ompleters骞堕鍑 } /* * Wait for the stopped threads to exit. */ + // 寰幆閬嶅巻AIO Completer绾跨▼鏁扮粍锛岀瓑寰匒IO Completer绾跨▼閫鍑哄苟杩涜娓呯悊 for (int i = 0; i < AioCompltrThreads; i++) { /* * Wait for the killed threads to exit */ - if (compltrArray[i].tid != 0) { - thread.thid = compltrArray[i].tid; + if (compltrArray[i].tid != 0) {// 妫鏌ョ嚎绋嬫爣璇嗙鏄惁鏈夋晥 + thread.thid = compltrArray[i].tid;// 淇濆瓨绾跨▼鏍囪瘑绗︼紝鐢ㄤ簬绛夊緟绾跨▼閫鍑 + // 浣跨敤gs_thread_join鍑芥暟绛夊緟绾跨▼閫鍑恒傚鏋滆繑鍥炲间笉涓0锛岃〃绀虹瓑寰呯嚎绋嬮鍑哄け璐ャ if (gs_thread_join(thread, NULL) != 0) { /* * If the thread does not exist, treat it as normal exit and we continue to @@ -420,12 +538,14 @@ void AioCompltrStop(int signal) * not know the current status of the thread and it's better to quit directly * which sames more safely. */ - if (ESRCH == pthread_kill(thread.thid, 0)) + if (ESRCH == pthread_kill(thread.thid, 0)) // 浣跨敤pthread_kill鍑芥暟妫鏌ョ嚎绋嬫槸鍚︿笉瀛樺湪 + // 濡傛灉绾跨▼涓嶅瓨鍦紝璁板綍閿欒鏃ュ織 ereport(LOG, (errmsg("failed to join thread %lu, no such process", thread.thid))); else + // 濡傛灉绾跨▼瀛樺湪浣嗘棤娉曠瓑寰呭叾閫鍑猴紝鏍囪绾跨▼宕╂簝 HandleChildCrash(thread.thid, 1, "AIO process"); } - compltrArray[i].tid = (pid_t)0; + compltrArray[i].tid = (pid_t)0; // 娓呯┖绾跨▼鏍囪瘑绗︼紝琛ㄧず绾跨▼宸茬粡閫鍑 } } @@ -433,18 +553,20 @@ void AioCompltrStop(int signal) * Deallocate their context and event arrays, if any */ for (int i = 0; i < AioCompltrThreads; i++) { - compltrArray[i].compltrDescp = (AioCompltrDesc_t*)NULL; + compltrArray[i].compltrDescp = (AioCompltrDesc_t*)NULL;// // 娓呯┖绾跨▼鎻忚堪绗︽寚閽堬紝闃叉鎮┖鎸囬拡 /* destroy the AIO context */ + // 濡傛灉AIO涓婁笅鏂囧瓨鍦 if (compltrArray[i].context) { - io_destroy(compltrArray[i].context); - compltrArray[i].context = (io_context_t)NULL; + io_destroy(compltrArray[i].context);// 閿姣丄IO涓婁笅鏂囷紝閲婃斁鐩稿叧璧勬簮 + compltrArray[i].context = (io_context_t)NULL;// 娓呯┖AIO涓婁笅鏂囨寚閽堬紝闃叉鎮┖鎸囬拡 } /* Deallocate the events array */ + // 濡傛灉浜嬩欢鏁扮粍鎸囬拡瀛樺湪 if (compltrArray[i].eventsp) { - free(compltrArray[i].eventsp); - compltrArray[i].eventsp = (struct io_event*)NULL; + free(compltrArray[i].eventsp);// 閲婃斁浜嬩欢鏁扮粍鐨勫唴瀛橈紝闃叉鍐呭瓨娉勬紡 + compltrArray[i].eventsp = (struct io_event*)NULL;// 娓呯┖浜嬩欢鏁扮粍鎸囬拡锛岄槻姝㈡偓绌烘寚閽 } } @@ -460,29 +582,35 @@ void AioCompltrStop(int signal) */ void AioCompltrMain(int ac, char** av) { + // 妫鏌ュ懡浠よ鍙傛暟鏁伴噺鏄惁瓒冲 if (ac < 4) { ereport(WARNING, (errmsg("invalid AIO argument num:%d", ac))); exit(1); } /* compltrIdx identifies this thread. */ + // 瑙f瀽Completer绾跨▼鐨勭储寮 int compltrIdx = atoi(av[3]); /* * Global thread local shortcuts to the completer descriptor * in the compltrArray, these are assigned on entry. */ - io_context_t context = compltrArray[compltrIdx].context; - io_event* eventsp = compltrArray[compltrIdx].eventsp; - AioCompltrDesc_t* compltrDescp = compltrArray[compltrIdx].compltrDescp; - int min_nr = compltrDescp->min_nr; - int max_nr = compltrDescp->max_nr; - struct timespec timeout; - struct timespec shutdown_timeout; - timeout.tv_sec = compltrDescp->timeout; - timeout.tv_nsec = 0; - shutdown_timeout.tv_sec = AioCompltrShutdownTimeout; - shutdown_timeout.tv_nsec = 0; - AioCallback_t callback = compltrDescp->callback; + /* + 浣跨敤鏈湴鍙橀噺鎻愬墠鑾峰彇瀵瑰畬鎴愬櫒鎻忚堪绗︿腑鐩稿叧淇℃伅鐨勫紩鐢紝浠ヤ究鍚庣画浠g爜涓娇鐢ㄣ備粠鑰屽噺灏戝啑浣欑殑鎿嶄綔锛屾彁楂樹唬鐮佸彲璇绘у拰鎬ц兘銆 + 鍏朵腑鍖呮嫭浜咥IO涓婁笅鏂囥佷簨浠舵暟缁勬寚閽堛佹渶灏/鏈澶х瓑寰呬簨浠舵暟閲忋佽秴鏃惰缃拰AIO鍥炶皟鍑芥暟绛変俊鎭殑鑾峰彇銆 + */ + io_context_t context = compltrArray[compltrIdx].context; // AIO涓婁笅鏂 + io_event* eventsp = compltrArray[compltrIdx].eventsp;// 浜嬩欢鏁扮粍鎸囬拡 + AioCompltrDesc_t* compltrDescp = compltrArray[compltrIdx].compltrDescp;// 瀹屾垚鍣ㄦ弿杩扮鎸囬拡 + int min_nr = compltrDescp->min_nr;// 鏈灏忕瓑寰呬簨浠舵暟閲 + int max_nr = compltrDescp->max_nr; // 鏈澶у彲妫绱㈢殑浜嬩欢鏁伴噺 + struct timespec timeout;// 浜嬩欢绛夊緟瓒呮椂 + struct timespec shutdown_timeout; // 鍏抽棴绛夊緟瓒呮椂 + timeout.tv_sec = compltrDescp->timeout;// 璁剧疆绛夊緟浜嬩欢瓒呮椂鐨勭鏁 + timeout.tv_nsec = 0; // 璁剧疆绛夊緟浜嬩欢瓒呮椂鐨勭撼绉掓暟 + shutdown_timeout.tv_sec = AioCompltrShutdownTimeout;// 璁剧疆鍏抽棴绛夊緟瓒呮椂鐨勭鏁 + shutdown_timeout.tv_nsec = 0;// 璁剧疆鍏抽棴绛夊緟瓒呮椂鐨勭撼绉掓暟 + AioCallback_t callback = compltrDescp->callback;// 鑾峰彇AIO鍥炶皟鍑芥暟鐨勬寚閽 /* * Handle signals the postmaster might send us @@ -490,27 +618,28 @@ void AioCompltrMain(int ac, char** av) * SIGQUIT causes immediate exit without cleanup. * SIGUSR1 is presently unused- reserved for future use. */ - (void)gspqsignal(SIGHUP, CompltrConfig); /* retrieve config */ - (void)gspqsignal(SIGINT, SIG_IGN); - (void)gspqsignal(SIGTERM, CompltrShutdown); /* shutdown */ - (void)gspqsignal(SIGQUIT, CompltrQuickDie); /* hard crash time */ - (void)gspqsignal(SIGALRM, SIG_IGN); - (void)gspqsignal(SIGPIPE, SIG_IGN); - (void)gspqsignal(SIGUSR1, SIG_IGN); /* reserved */ - (void)gspqsignal(SIGUSR2, SIG_IGN); + //涓哄紓姝/O Completer绾跨▼璁剧疆淇″彿澶勭悊鏂瑰紡锛岀‘淇濈嚎绋嬭兘澶熼傚綋鍦板搷搴斾笉鍚岀殑淇″彿 + (void)gspqsignal(SIGHUP, CompltrConfig); /* retrieve config */ //SIGHUP 淇″彿灏嗚Е鍙 CompltrConfig 鍑芥暟锛岀敤浜庨噸鏂板姞杞介厤缃 + (void)gspqsignal(SIGINT, SIG_IGN);// SIGINT 淇″彿琚拷鐣ワ紝涓嶄細涓柇绾跨▼鎵ц銆 + (void)gspqsignal(SIGTERM, CompltrShutdown); /* shutdown */ //SIGTERM 淇″彿灏嗚Е鍙 CompltrShutdown 鍑芥暟锛岀敤浜庤繘琛岀嚎绋嬪叧闂拰娓呯悊銆 + (void)gspqsignal(SIGQUIT, CompltrQuickDie); /* hard crash time */ // SIGQUIT 淇″彿灏嗚Е鍙 CompltrQuickDie 鍑芥暟锛岀敤浜庡揩閫熺粓姝㈢嚎绋嬫墽琛屻 + (void)gspqsignal(SIGALRM, SIG_IGN);// SIGALRM 淇″彿琚拷鐣ャ + (void)gspqsignal(SIGPIPE, SIG_IGN);// SIGPIPE 淇″彿琚拷鐣ャ + (void)gspqsignal(SIGUSR1, SIG_IGN); /* reserved */ //SIGUSR1 淇″彿閮借蹇界暐銆 + (void)gspqsignal(SIGUSR2, SIG_IGN);// SIGUSR2 淇″彿琚拷鐣ャ /* * Reset some signals that are accepted by postmaster but we don't * need. */ - (void)gspqsignal(SIGCHLD, SIG_DFL); - (void)gspqsignal(SIGTTIN, SIG_DFL); - (void)gspqsignal(SIGTTOU, SIG_DFL); - (void)gspqsignal(SIGCONT, SIG_DFL); - (void)gspqsignal(SIGWINCH, SIG_DFL); + (void)gspqsignal(SIGCHLD, SIG_DFL);// 鎭㈠榛樿澶勭悊 SIGCHLD 淇″彿 + (void)gspqsignal(SIGTTIN, SIG_DFL);// 鎭㈠榛樿澶勭悊 SIGTTIN 淇″彿 + (void)gspqsignal(SIGTTOU, SIG_DFL); // 鎭㈠榛樿澶勭悊 SIGTTOU 淇″彿 + (void)gspqsignal(SIGCONT, SIG_DFL);// 鎭㈠榛樿澶勭悊 SIGCONT 淇″彿 + (void)gspqsignal(SIGWINCH, SIG_DFL);// 鎭㈠榛樿澶勭悊 SIGWINCH 淇″彿 /* We allow SIGQUIT (quickdie) at all times */ - sigdelset(&t_thrd.libpq_cxt.BlockSig, SIGQUIT); + sigdelset(&t_thrd.libpq_cxt.BlockSig, SIGQUIT);// 鍏佽 SIGQUIT (quickdie) 淇″彿闅忔椂琚帴鏀 /* Create a resource owner to keep track of our resources (buffer * pins etc... @@ -524,20 +653,22 @@ void AioCompltrMain(int ac, char** av) /* * Unblock signals (blocked when postmaster forked us) */ - gs_signal_setmask(&t_thrd.libpq_cxt.UnBlockSig, NULL); - (void)gs_signal_unblock_sigusr2(); + gs_signal_setmask(&t_thrd.libpq_cxt.UnBlockSig, NULL);// 瑙i櫎涔嬪墠鍦ㄤ富杩涚▼涓樆濉炵殑淇″彿 + (void)gs_signal_unblock_sigusr2();// 瑙i櫎瀵 SIGUSR2 淇″彿鐨勯樆濉 /* Announce that the Completer has been started */ - ereport(LOG, (errmsg("AIO Completer %d STARTED.", compltrIdx))); + ereport(LOG, (errmsg("AIO Completer %d STARTED.", compltrIdx)));// 鍦ㄦ棩蹇椾腑璁板綍寮傛I/O Completer绾跨▼宸茬粡鍚姩 for (;;) { - int eventsReceived; + int eventsReceived;//瀛樺偍浠 io_getevents 鍑芥暟涓幏鍙栫殑宸插畬鎴愮殑寮傛I/O浜嬩欢鏁伴噺鎴栭敊璇唬鐮 /* * Reload configuration -if requested. */ + // 濡傛灉鏈夐噸鏂板姞杞介厤缃殑璇锋眰锛岃繘琛岀浉搴旂殑澶勭悊锛屼絾鍦ㄦ浠g爜娈典腑琚鐢ㄤ簡 if (t_thrd.aio_cxt.config_requested) { /* disabled config request, not time for this now. ProcessConfigFile PGC_SIGHUP; */ + // 濡傛灉閰嶇疆閲嶈浇璇锋眰琚缃紝杩欐浠g爜浼氱鐢ㄩ厤缃姹傚苟鐣ヨ繃鍚庣画鐨勫鐞嗭紝浠ラ伩鍏嶅湪褰撳墠涓婁笅鏂囦腑閲嶆柊鍔犺浇閰嶇疆鏂囦欢 t_thrd.aio_cxt.config_requested = false; } @@ -548,11 +679,12 @@ void AioCompltrMain(int ac, char** av) * allow the thread to exit quickly when its time comes. * Once shutdown is requested, there is no going back. */ + // 濡傛灉鏀跺埌浜嗗叧闂姹 if (t_thrd.aio_cxt.shutdown_requested) { - timeout = shutdown_timeout; + timeout = shutdown_timeout;// 璁剧疆瓒呮椂鏃堕棿涓簊hutdown_timeout锛屼互渚垮揩閫熼鍑虹嚎绋 - ereport(LOG, (errmsg("AIO Completer %d EXITED.", compltrIdx))); - proc_exit(0); + ereport(LOG, (errmsg("AIO Completer %d EXITED.", compltrIdx)));// 璁板綍鏃ュ織锛岃〃绀篈IO Completer姝e湪閫鍑 + proc_exit(0);// 閫鍑虹嚎绋 } /* @@ -560,12 +692,15 @@ void AioCompltrMain(int ac, char** av) * on the given context. Retry if the syscall is * interrupted. */ + // 绛夊緟涓浜汚IO璇锋眰瀹屾垚鍦ㄧ粰瀹氱殑涓婁笅鏂囦腑锛屾渶灏忕瓑寰呬簨浠舵暟閲忎负min_nr锛屾渶澶т负max_nr锛屾渶闀跨瓑寰呮椂闂寸敱timeout鎸囧畾 + // 杩斿洖鍊兼槸涓涓暣鏁帮紝琛ㄧず鎴愬姛鑾峰彇鐨勪簨浠舵暟閲忋傚鏋滆繑鍥炲间负璐熸暟锛岃〃绀哄彂鐢熶簡閿欒锛 eventsReceived = io_getevents(context, min_nr, max_nr, eventsp, &timeout); /* * If io_getevents() got interrupted, * take the opportunity to check for pending requests. * Then restart the io_getevents() call. */ + // 濡傛灉 io_getevents() 琚腑鏂紝閲嶆柊灏濊瘯鑾峰彇浜嬩欢 if (eventsReceived == -EINTR) { continue; } @@ -573,11 +708,13 @@ void AioCompltrMain(int ac, char** av) /* * io_getevents() reports errors as negative values. */ + // io_getevents() 鎶ュ憡閿欒鐨勮繑鍥炲间负璐熸暟 if (eventsReceived < 0) { /* Report error */ + // 璁板綍閿欒鏃ュ織锛屽彂鍑 PANIC 绾у埆鐨勯敊璇姤鍛 ereport(PANIC, (errmsg("AIO Completer io_getevents() failed: error %d .", eventsReceived))); } - + // 鏂█锛岀‘淇 eventsReceived 涓嶈秴杩囨渶澶ф暟閲 Assert(eventsReceived <= max_nr); /* @@ -585,22 +722,26 @@ void AioCompltrMain(int ac, char** av) * We expect 0 to max_nr requests. The obj here is * the I/O request and the db context. */ + // 閫愪釜閬嶅巻銆佸鐞嗗紓姝/O浜嬩欢鏁扮粍涓殑姣忎釜浜嬩欢锛屾墽琛岀壒瀹氭搷浣滄垨鍥炶皟鍑芥暟銆 for (struct io_event* eventp = eventsp; eventsReceived--; eventp++) { - callback((void*)eventp->obj, eventp->res); + callback((void*)eventp->obj, eventp->res);// 璋冪敤鍥炶皟鍑芥暟锛屼紶鍏 I/O 璇锋眰鐨 obj 鍜岀粨鏋 } } + // 鎵鏈変簨浠跺鐞嗗畬鎴愬悗锛岀嚎绋嬪嵆灏嗛鍑 + // 璁板綍绾跨▼閫鍑虹殑鏃ュ織淇℃伅 ereport(LOG, (errmsg("AIO Completer %d EXITED.", compltrIdx))); - exit(0); + exit(0);// 閫鍑虹嚎绋嬶紝杩斿洖鐘舵佺爜 0 } /* * @Description: signal handler routines for config,not used now * @See also: */ +// 淇″彿澶勭悊绋嬪簭锛岀敤浜庡鐞嗛厤缃姹傦紝鐩墠鏈娇鐢 static void CompltrConfig(SIGNAL_ARGS) { - t_thrd.aio_cxt.config_requested = true; + t_thrd.aio_cxt.config_requested = true;// 鏍囪閰嶇疆璇锋眰涓簍rue,琛ㄧず閰嶇疆璇锋眰宸茬粡鍙戠敓 } /* @@ -609,31 +750,33 @@ static void CompltrConfig(SIGNAL_ARGS) * so we need to stop what we're doing and exit. * @See also: */ +// 蹇熼鍑虹殑淇″彿澶勭悊绋嬪簭锛屽綋postmaster閫氳繃SIGQUIT淇″彿鍙戝嚭缁堟璇锋眰鏃惰Е鍙 static void CompltrQuickDie(SIGNAL_ARGS) { - PG_SETMASK(&t_thrd.libpq_cxt.BlockSig); + PG_SETMASK(&t_thrd.libpq_cxt.BlockSig);// 闃诲鎵鏈変俊鍙 /* * We DO NOT want to run proc_exit() callbacks -- we're here because * shared memory may be corrupted. Like the other postmaster * children, ...Just nail the windows shut and get out of town.... */ - on_exit_reset(); + on_exit_reset();// 閲嶇疆杩涚▼閫鍑哄洖璋 /* * Note we do exit(2) not exit(0)... * ...just like the other postmaster children. */ - exit(2); + exit(2);// 浠ラ鍑虹爜2閫鍑猴紝绫讳技鍏朵粬涓绘帶杩涚▼瀛愯繘绋嬬殑鍋氭硶 } /* * @Description: CompltrShutdown() occurs when signalled SIGTERM by the postmaster. * @See also: */ +// 鍏抽棴淇″彿澶勭悊绋嬪簭锛屽綋postmaster閫氳繃SIGTERM淇″彿鍙戝嚭鍏抽棴璇锋眰鏃惰Е鍙 static void CompltrShutdown(SIGNAL_ARGS) { - t_thrd.aio_cxt.shutdown_requested = true; + t_thrd.aio_cxt.shutdown_requested = true;// 璁剧疆寮傛I/O Completer绾跨▼鐨勫叧闂姹傛爣蹇 } /** @@ -641,12 +784,809 @@ static void CompltrShutdown(SIGNAL_ARGS) * @in void * @return void */ +// 鍒濆鍖栧紓姝/O鐨勮祫婧 void AioResourceInitialize(void) { + // 鍒涘缓涓涓叡浜唴瀛樹笂涓嬫枃鐢ㄤ簬寮傛I/O璧勬簮锛屼互渚胯繘琛屽唴瀛樺垎閰嶅拰绠$悊 AdioSharedContext = AllocSetContextCreate((MemoryContext)g_instance.instance_context, - "AdioSharedMemory", - ALLOCSET_DEFAULT_MINSIZE, - ALLOCSET_DEFAULT_INITSIZE, - ALLOCSET_DEFAULT_MAXSIZE, - SHARED_CONTEXT); + "AdioSharedMemory",// 璁剧疆涓婁笅鏂囩殑鍚嶇О锛岀敤浜庢爣璇嗗拰璇嗗埆姝や笂涓嬫枃銆 + ALLOCSET_DEFAULT_MINSIZE,//璁剧疆涓婁笅鏂囩殑鍒濆鏈灏忓唴瀛樺垎閰嶅ぇ灏 + ALLOCSET_DEFAULT_INITSIZE,//璁剧疆涓婁笅鏂囩殑鍒濆鍐呭瓨姹犲ぇ灏 + ALLOCSET_DEFAULT_MAXSIZE,// 璁剧疆涓婁笅鏂囩殑鏈澶у唴瀛樻睜澶у皬 + SHARED_CONTEXT);// 璁剧疆涓婁笅鏂囩殑鏍囧織锛屾寚绀哄畠鏄竴涓叡浜笂涓嬫枃 +<<<<<<< HEAD +======= +} +/* + 涓嬫娉ㄩ噴鎻忚堪浜嗘枃浠剁殑鐗堟潈淇℃伅浠ュ強瀵逛簬AIO瀹屾垚绾跨▼鐨勫熀鏈粙缁嶃傚畠浠敤浜庡鐞嗗紓姝O璇锋眰锛屼互鍙婂浣曞惎鍔ㄥ拰鍋滄杩欎簺绾跨▼銆 + * aiocompleter.cpp鏂囦欢鐨勬暣浣撳姛鑳芥槸鐢ㄤ簬AIO 瀹屾垚鍣ㄧ嚎绋嬪畬鎴愰鍙栵紙Prefetch 锛夊拰鍚庣鍐欏叆锛圔ackWrite 锛塈/O鎿嶄綔 + * 浣跨敤鍦烘櫙锛欰IO 瀹屾垚鍣ㄧ嚎绋嬩娇鐢 Linux Native AIO 瀹屾垚 AIO 璇锋眰銆 + * 鍗曚釜 AIO 瀹屾垚鍣ㄧ嚎绋嬩负涓庣壒瀹 AIO 涓婁笅鏂囧拰 I/O 浼樺厛绾х浉鍏宠仈鐨 AIO 闃熷垪鎻愪緵鏈嶅姟銆 + * 1. 鍋滄锛氬彧鑳藉湪鎵鏈夊伐浣滅嚎绋嬫垨鍚庡彴鏁版嵁鍐欙紙bgwriter锛夌嚎绋嬮兘宸插仠姝㈠悗锛孉IO瀹屾垚鍣ㄧ嚎绋嬫墠鑳藉仠姝€ + * + * 2. 鍚姩锛氬綋postmaster鍚姩瀛愯繘绋嬬粨鏉熸垨鏄湪鎵ц褰掓。鎭㈠鐨勫紑濮嬶紝AIO瀹屾垚鍣ㄧ嚎绋嬩細绔嬪嵆鍚姩锛屽苟涓旀寔缁繚鎸佸紑鍚姸鎬侊紝鐩村埌postemaster涓嬭揪缁堟鍛戒护 + * [1.姝e父缁堟锛歋IGTERM鎸囦护锛氭寚绀虹嚎绋嬬瓑寰呬换浣曟寕璧风殑 AIO 骞跺仛濂介鍑哄噯澶囥 + * 2.绱фョ粓姝細SIGQUIT鎸囦护锛氬綋AIO瀹屾垚鍣ㄧ嚎绋嬫剰澶栭鍑猴紝postmaster浼氬皢鍏惰涓衡滃悗绔穿婧冣濈姸鎬侊紝鍏变韩鍐呭瓨鍙兘閬彈鎹熷潖锛屾鏃堕氳繃SIGQUIT鎸囦护缁堟鍓╀綑鐨勫悗绔悗鍚姩鎭㈠寰幆] + * + */ +/* + * Copyright (c) 2020 Huawei Technologies Co.,Ltd. + * + * openGauss is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * + * http://license.coscl.org.cn/MulanPSL2 + * + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + * ------------------------------------------------------------------------- + * + * aiocompleter.cpp + * + * The AIO completer threads complete Prefetch and BackWrite I/O so they + * may only be stopped after all the worker threads or bgwrite threads have + * been stopped. + * + * The aiocompleter threads complete AIO requests using Linux Native AIO. + * A single AIO completer thread serves on AIO queue associated with a + * specific AIO context and I/O priority. + * + * The AIO completer threads are started by the postmaster as soon as the + * startup subprocess finishes, or as soon as recovery begins if we are + * doing archive recovery. They remain alive until the postmaster commands + * them to terminate. Normal termination is by SIGTERM, which instructs the + * threads to wait for any pending AIO and be prepared to exit. + * via exit(0). Emergency termination is by SIGQUIT. + * + * If completer thread exits unexpectedly, the postmaster treats that the same + * as a backend crash: shared memory may be corrupted, so remaining backends + * should be killed by SIGQUIT and then a recovery cycle started. + * + * IDENTIFICATION + * src/gausskernel/process/postmaster/aiocompleter.cpp + * + * ------------------------------------------------------------------------- + */ +/*寮曞叆鎵闇鐨勭郴缁熷簱鍜屾ā鍧椼*/ +#include "postgres.h" +#include "knl/knl_variable.h" +#include "gssignal/gs_signal.h" +#include "libpq/pqsignal.h" +#include "postmaster/aiocompleter.h" +#include "postmaster/postmaster.h" +#include "storage/smgr/fd.h" +#include "storage/ipc.h" +#include "storage/pmsignal.h" +#include "utils/guc.h" +#include "utils/memutils.h" +#include + +/* +瑙i噴浜咥IO completer绾跨▼鐨勭粨鏋勫拰鏁扮粍銆傛瘡涓嚎绋嬮兘鏈変竴涓敮涓鐨勪笂涓嬫枃锛屽彲鑳藉鐞嗕笉鍚岀被鍨嬬殑璇锋眰銆 +aioCompltrThread_t 缁撴瀯瀵瑰簲浜庢瘡涓狝IO completer绾跨▼锛屽瓨鍌ㄥ湪 compltrArray 鏁扮粍涓紝璇ユ暟缁勫寘鍚 MAX_AIOCOMPLTR_THREADS 涓Ы浣嶃 +compltrArray 鏁扮粍鍦 postmaster 涓婁笅鏂囦腑瀹氫箟銆 + +绗竴缁勫弬鏁 context銆乪ventsp 鍜 tid 鏄湪绾跨▼鍚姩鏃惰缃殑锛屽畠浠姣忎釜绾跨▼閮芥槸鍞竴鐨勩 +cmpltrDesc 鎸囬拡鎸囧悜 compltrDescArray 涓殑 AioCompltrDesc_t 缁撴瀯锛屽叾涓寘鍚簡瀹屾垚鍣ㄧ殑鍙傛暟銆傚悓绫诲瀷鐨勫畬鎴愬櫒鍏变韩鐩稿悓鐨勬弿杩扮銆 +compltrDescArray 鏁扮粍涓湁 NUM_AIOCOMPLTR_TYPES 涓 AioCompltrDesc_t 缁撴瀯锛屾瘡涓粨鏋勪唬琛ㄤ竴涓 AioCompltrType銆 +*/ +/* + * Each AIO completer thread has a unique context, and potentially + * processes different types of requests. There is an aioCompltrThread_t + * structure for each completer thread, located in the compltrArray. + * The compltrArray contains MAX_AIOCOMPLTR_THREADS slots. + * The compltrArray is defined in the postmaster context. + * + * The first three parameters context, eventsp and tid + * are set when the thread is started, they are unique to each thread. + * The cmpltrDesc pointer points to a AioCompltrDesc_t structure in the + * compltrDescArray containing the parameters for the completer. + * Completers of the same type use the same descriptor. + * The compltrDescArray has NUM_AIOCOMPLTR_TYPES AioCompltrDesc_t structures + * one for each AioCompltrType. + * The compltrDescArray array is defined in the postmaster context. + * + */ +/* + 杩欓噷澹版槑浜嗕竴浜涘嚱鏁板師鍨嬶紝鐢ㄤ簬澶勭悊涓嶅悓绫诲瀷鐨凙IO璇锋眰銆 +*/ +int CompltrReadReq(void* aioDesc, long res);// 鍙戣捣寮傛璇诲彇璇锋眰 +int CompltrWriteReq(void* aioDesc, long res);// 鍙戣捣寮傛鍐欏叆璇锋眰 +int CompltrReadCUReq(void* aioDesc, long res);// 鍙戣捣寮傛璇诲彇CU锛圕ontrol Unit锛屾帶鍒跺崟鍏冿級璇锋眰 +int CompltrWriteCUReq(void* aioDesc, long res);// 鍙戣捣寮傛鍐欏叆CU璇锋眰 + +ThreadId Compltrfork_exec(int compltrIdx);// 鍒涘缓绾跨▼骞舵墽琛屽紓姝/O澶勭悊 + +/* + * GUC parameters + */ +/* Maximum number of Completer threads -compile time define */ +#define MAX_AIOCOMPLTR_THREADS 4 //鍦ㄧ紪璇戞椂瀹氫箟鐨勫畯锛岀敤浜庤缃紓姝/O鎿嶄綔瀹屾垚鑰呯嚎绋嬫睜鐨勬渶澶х嚎绋嬫暟閲忋傜敤浜庨檺鍒朵簡鍙互鍚屾椂杩愯鐨勫畬鎴愯呯嚎绋嬬殑鏈澶ф暟閲忋 + +/* Number of Completer threads and the number of sets of Completers */ +const int AioCompltrThreads = 4;// 鏁存暟甯搁噺锛岃〃绀哄紓姝/O鎿嶄綔瀹屾垚鑰呯嚎绋嬫睜涓殑绾跨▼鏁伴噺銆傝繖閲岃缃簡4涓畬鎴愯呯嚎绋嬨 +int AioCompltrSets = 1; // 鏁存暟鍙橀噺锛岃〃绀哄畬鎴愯呯嚎绋嬫睜鐨勯泦鏁般傛澶勮缃彧鏈変竴涓嚎绋嬫睜闆嗐 +const int AioCompltrShutdownTimeout = 1;// 鏁存暟甯搁噺锛岃〃绀哄紓姝/O瀹屾垚鑰呯嚎绋嬫睜鍏抽棴鐨勮秴鏃舵椂闂达紝姝ゅ璁剧疆涓1绉掋 + +/* Completer callback to handle the AIO event */ +typedef int (*AioCallback_t)(void*, long);// 瀹氫箟鍑芥暟鎸囬拡绫诲瀷 AioCallback_t锛岀敤浜庤〃绀哄紓姝/O浜嬩欢鐨凜ompleter鍥炶皟鍑芥暟銆 + // 鎸囧悜涓涓弬鏁颁负 (void*, long) 骞惰繑鍥 int 绫诲瀷鐨勫嚱鏁 + +/* + * Completer Thread definitions + */ +/* +缁撴瀯浣撶被鍨 AioCompltrDesc锛岀敤浜庢弿杩癆IO瀹屾垚鍣ㄧ殑鐗规с佸弬鏁颁互鍙婅姹傚睘鎬с +瀹冨寘鍚互涓嬪瓧娈碉細 + reqtype: AioCompltrType锛岃〃绀哄畬鎴愬櫒鐨勭被鍨嬶紝鐢ㄤ簬鏍囪瘑涓嶅悓绫诲瀷鐨凙IO璇锋眰銆 + callback: AioCallback_t锛屾槸涓涓嚱鏁版寚閽堬紝鎸囧悜鐢ㄤ簬澶勭悊AIO浜嬩欢鐨勫洖璋冨嚱鏁般 + maxevents: int锛岃〃绀哄厑璁稿悓鏃跺鐞嗙殑鏈澶IO浜嬩欢鏁伴噺銆 + min_nr: int锛岃〃绀虹瓑寰呯殑鏈灏忎簨浠舵暟閲忥紝褰撹揪鍒版鏁伴噺鏃讹紝瀹屾垚鍣ㄥ彲浠ュ紑濮嬪鐞嗚繖浜涗簨浠躲 + max_nr: int锛岃〃绀烘渶澶у彲妫绱㈢殑浜嬩欢鏁伴噺锛屽嵆涓娆′粠鍐呮牳鑾峰彇鐨勬渶澶т簨浠舵暟閲忋 + timeout: int锛岃〃绀虹瓑寰呬簨浠剁殑鏈澶ф椂闂达紝瓒呰繃姝ゆ椂闂村悗锛屽畬鎴愬櫒鍙互澶勭悊宸茶幏鍙栫殑浜嬩欢銆 + reqprio: AioPriority锛岃〃绀篈IO璇锋眰鐨勪紭鍏堢骇銆 +*/ +typedef struct AioCompltrDesc { + /* Completer characteristics */ + AioCompltrType reqtype; /* Completer type 琛ㄧず瀹屾垚鍣ㄧ殑绫诲瀷锛岀敤浜庢爣璇嗕笉鍚岀被鍨嬬殑AIO璇锋眰銆*/ + AioCallback_t callback; /* Completer function 鍑芥暟鎸囬拡锛屾寚鍚戠敤浜庡鐞咥IO浜嬩欢鐨勫洖璋冨嚱鏁*/ + int maxevents; /* AIO Maximum events in progress 琛ㄧず鍏佽鍚屾椂澶勭悊鐨勬渶澶IO浜嬩欢鏁伴噺*/ + + /* Completer parameters */ + int min_nr; /* Min number of events to wait for 绀虹瓑寰呯殑鏈灏忎簨浠舵暟閲忥紝褰撹揪鍒版鏁伴噺鏃讹紝瀹屾垚鍣ㄥ彲浠ュ紑濮嬪鐞嗚繖浜涗簨浠*/ + int max_nr; /* Max number of events to retrieve 琛ㄧず鏈澶у彲妫绱㈢殑浜嬩欢鏁伴噺锛屽嵆涓娆′粠鍐呮牳鑾峰彇鐨勬渶澶т簨浠舵暟閲*/ + int timeout; /* Max time to wait 琛ㄧず绛夊緟浜嬩欢鐨勬渶澶ф椂闂达紝瓒呰繃姝ゆ椂闂村悗锛屽畬鎴愬櫒鍙互澶勭悊宸茶幏鍙栫殑浜嬩欢*/ + + /* Request properties */ + AioPriority reqprio; /* Request priority served 琛ㄧずAIO璇锋眰鐨勪紭鍏堢骇*/ + +} AioCompltrDesc_t; + +/* + AioCompltrThread_t 缁撴瀯浣擄紝鐢ㄤ簬琛ㄧず寮傛I/O Completer绾跨▼鐨勪俊鎭拰鐘舵併 + + context锛歩o_context_t 琛ㄧず寮傛I/O涓婁笅鏂囷紝鐢ㄤ簬绠$悊鍜岃窡韪紓姝/O鎿嶄綔銆 + eventsp锛歴truct io_event* 鎸囧悜 io_event 缁撴瀯浣撶殑鎸囬拡锛岃〃绀哄紓姝/O浜嬩欢鐨勬寚閽堟暟缁勩傜敤浜庡瓨鍌ㄥ紓姝/O鎿嶄綔鐨勪簨浠讹紝浠ヤ究鍚庣画澶勭悊銆 + tid锛歍hreadId 琛ㄧず寮傛I/O Completer绾跨▼鐨勭嚎绋婭D銆傜敤浜庢爣璇嗗拰绠$悊绾跨▼銆 + compltrDescp锛欰ioCompltrDesc_t* 鎸囧悜 AioCompltrDesc_t 绫诲瀷鐨勬寚閽堬紝AioCompltrDesc_t鐢ㄤ簬鎻忚堪AIO瀹屾垚鍣ㄧ殑鐗规с佸弬鏁颁互鍙婅姹傚睘鎬 +*/ +typedef struct { + io_context_t context; /* AIO context */ + struct io_event* eventsp; /* AIO events to process */ + ThreadId tid; /* AIO thread tid */ + AioCompltrDesc_t* compltrDescp; /* Completer descriptor */ +} AioCompltrThread_t; + + + +/* + * The compltrDescArray contains the description of the different types + * of completer threads. These are used to setup the context for each + * completer thread. Each type could potentially has a unique set + * of parameters. + * + * For now, only the completer function and priority varies. + * The rest of the values are the same for all the threads: + * + * reqtype and callback + * The reqtype is the type of async I/O request. The + * callback is the function used to process the request. + * The completers are configured to each handle a different type + * of request. The type of request dictates the callback used. + * At least that is the case now, this could change in the future. + * + * maxevents + * The number of requests in the queue for the context is limited to 64K here. + * So in total, the 4 threads require 64k * 4 io descriptors. + * Typically the system io descriptor maximum is 64k. + * Verify that there are sufficient available by checking aio-max-nr. + * Compare /proc/sys/fs/aio-nr against /proc/sys/fs/aio-max-nr to determine + * whether the limit is too small. It is advisable to set fs.aio-max-nr to + * 1048576 (1m) in /etc/sysctl.conf. + * + * min_nr, max_nr and timeout + * The minimum number of requests to return is set to 1, this + * makes io_getevents a blocking call that sleeps until one i/o is available. + * The maximum number of requests in the queue is arbitrarily set + * to here, but it could be as large as the entire queue. + * The maximum wait is set to 10 minutes, but any nonzero value will allow + * io_getevents() to enter an interruptable sleep (Returning -EINTR + * when a signal arrives). + * + * priority + * The priority values are intended to give specific Page List prefetchs the + * highest priority, while giving Range prefetch and Range write-back a + * medium priority, and the periodic write-back the lowest priority. + * The effectiveness of these relative settings depends upon the i/o scheduling + * policy employed. CFQ takes into account the priorities, but there is also a + * wide gulf between the priority of sync and async i/o that dwarfs these. + */ +/* +鍒濆鍖朿ompltrDescArray鏁扮粍锛岀敤浜庨厤缃笉鍚岀被鍨嬬殑寮傛I/O Completer绾跨▼鐨勫弬鏁般 + +- AioCompltrDesc_t锛欰ioCompltrDesc缁撴瀯浣撶被鍨嬶紝鐢ㄤ簬鎻忚堪AIO Completer鐨勭壒鎬с佸弬鏁颁互鍙婅姹傚睘鎬с +- NUM_AIOCOMPLTR_TYPES锛氬父閲忥紝琛ㄧず寮傛I/O Completer绾跨▼鐨勭被鍨嬫暟閲忋傛暟缁 compltrDescArray鐨勫ぇ灏 +- compltrDescArray[NUM_AIOCOMPLTR_TYPES]锛氬寘鍚簡涓嶅悓绫诲瀷鐨勫紓姝/O Completer绾跨▼鐨勬弿杩颁俊鎭殑鏁扮粍銆 +- `PageListPrefetchType`锛氶〉鍒楄〃棰勫彇璇锋眰绫诲瀷銆傝绫诲瀷鐨勫紓姝/O瀹屾垚鍣ㄧ嚎绋嬪鐞嗗悗鍙板紓姝ヨ鍙栨暟鎹〉鍒板唴瀛樼殑璇锋眰锛屼互鍑忓皯鏌ヨ鎴栨搷浣滄椂鐨勫欢杩熴 + +- `PageListBackWriteType`锛氶〉鍒楄〃鍚庡彴鍐欏叆璇锋眰绫诲瀷銆傝绫诲瀷鐨勫紓姝/O瀹屾垚鍣ㄧ嚎绋嬪鐞嗗皢鏁版嵁椤典粠鍐呭瓨鍐欏洖纾佺洏鐨勮姹傦紝閫氬父鐢ㄤ簬鎵ц鍚庡彴鐨勬暟鎹〉鍥炲啓鎿嶄綔銆 + +- `CUListPrefetchType`锛欳U锛圕olumn Unit锛夊垪琛ㄩ鍙栬姹傜被鍨嬨傜被浼间簬椤靛垪琛ㄩ鍙栵紝璇ョ被鍨嬬殑寮傛I/O瀹屾垚鍣ㄧ嚎绋嬪鐞嗗悗鍙板紓姝ヨ鍙栧垪瀛樺偍鍗曞厓锛圕U锛夊埌鍐呭瓨鐨勮姹傦紝浠ヤ紭鍖栨煡璇㈡ц兘銆 + +- `CUListWriteType`锛欳U鍒楄〃鍐欏叆璇锋眰绫诲瀷銆備笌椤靛垪琛ㄥ悗鍙板啓鍏ョ被浼硷紝璇ョ被鍨嬬殑寮傛I/O瀹屾垚鍣ㄧ嚎绋嬪鐞嗗皢淇敼鍚庣殑鍒楀瓨鍌ㄥ崟鍏冿紙CU锛変粠鍐呭瓨鍐欏洖纾佺洏鐨勮姹傘 +*/ +AioCompltrDesc_t compltrDescArray[NUM_AIOCOMPLTR_TYPES] = { + /* reqtype, callback, maxevents, min_nr, max_nr, tsec, reqprio */ + {PageListPrefetchType, CompltrReadReq, 65536, 1, 16384, 60, HighPri}, + {PageListBackWriteType, CompltrWriteReq, 65536, 1, 16384, 60, HighPri}, + {CUListPrefetchType, CompltrReadCUReq, 65536, 1, 16384, 60, HighPri}, + {CUListWriteType, CompltrWriteCUReq, 65536, 1, 16384, 60, HighPri}}; + +/* + * AIO Completer Array defines the AIO completer threads, it is + * initialized by the postmaster using CompltrAioInit prior to starting + * any AIO Completer theads. The Array contains one element for + * each completer thread. + */ + +AioCompltrThread_t compltrArray[MAX_AIOCOMPLTR_THREADS]; // MAX_AIOCOMPLTR_THREADS 4 + +/* + * AioCompltrReady flag is set/cleared from the postmaster + * context. It is used to remember the Completer state. + * 鐢ㄤ簬鏍囪寮傛I/O瀹屾垚鑰呯嚎绋嬫槸鍚﹀噯澶囧氨缁 + */ +static bool volatile AioCompltrReady = false;// 鍒濆鍖杅alse锛岃〃绀哄紓姝/O瀹屾垚鍣ㄧ嚎绋嬪皻鏈噯澶囧氨缁 + +/* Associate a template with a thread index +鐢ㄤ簬鍏宠仈绾跨▼绱㈠紩锛坱hreadIdx锛変笌Completer鎻忚堪鏁扮粍 compltrDescArray 涓殑妯℃澘 +*/ +#define AIOCOMPLTR_TEMPLATE(threadIdx) (&compltrDescArray[(threadIdx) % NUM_AIOCOMPLTR_TYPES]) + +/* Determine a completer thread index to be used for a given type and h val +鐢ㄤ簬纭畾缁欏畾绫诲瀷锛坱ypeIdx锛夊拰鍝堝笇鍊硷紙h锛夌殑寮傛I/O Completer绾跨▼绱㈠紩銆 +閫氳繃璁$畻鍑哄湪 compltrArray 涓殑绱㈠紩锛屼互閫夋嫨閫傚綋鐨凜ompleter绾跨▼鏉ュ鐞嗙壒瀹氱被鍨嬬殑寮傛I/O璇锋眰銆 +*/ +#define AIOCOMPLTR_THREAD_IDX(typeIdx, h) ((((h) % AioCompltrSets) * NUM_AIOCOMPLTR_TYPES) + (typeIdx)) + +/* + * Exported functions + */ +/* + * @Description: Check whether the Completers have been started + * @Return: true start ok + * @See also: + */ +/*鐢ㄤ簬妫鏌ュ紓姝/O瀹屾垚鑰呮槸鍚﹀凡缁忓惎鍔ㄧ殑鍑芥暟銆 + *杩斿洖甯冨皵鍊硷細濡傛灉寮傛I/O Completers宸插噯澶囧氨缁紝鍒欒繑鍥 true锛屽惁鍒欒繑鍥 false +*/ +bool AioCompltrIsReady(void) +{ + return AioCompltrReady; +} + +/* + * @Description: Obtain callback for request type + * @Param[IN] reqType: aio completer type + * @Return: function ptr + * @See also: + */ +/*鐢ㄤ簬鑾峰彇鐗瑰畾璇锋眰绫诲瀷鐨勫洖璋冨嚱鏁扮殑鍑芥暟銆 + *鎺ュ彈涓涓弬鏁 reqType锛岃〃绀哄紓姝/O completer绫诲瀷锛 + *杩斿洖涓庤绫诲瀷鐩稿叧鑱旂殑鍥炶皟鍑芥暟鎸囬拡銆*/ +AioCallback_t ComptrCallback(AioCompltrType reqType) +{ + return compltrDescArray[reqType].callback; +} + +/* + * @Description: Obtain the priority for the request type + * @Param[IN] reqType: aio completer type + * @Return: Request priority + * @See also: + */ +/*鐢ㄤ簬鑾峰彇鐗瑰畾璇锋眰绫诲瀷鐨勪紭鍏堢骇鐨勫嚱鏁般 + *鎺ュ彈涓涓弬鏁 reqType锛岃〃绀哄紓姝/O completer绫诲瀷 + *杩斿洖璇ョ被鍨嬭姹傜殑浼樺厛绾с + */ +short CompltrPriority(AioCompltrType reqType) +{ + return compltrDescArray[reqType].reqprio; +} + +/* + * @Description: Obtain the completer context for the i/o request, Must consult the AioCompltrArray + * to find the specific thread to get its context. + * @Param[IN] h: index + * @Param[IN] reqType: aio completer type + * @Return:io_context + * @See also: + */ +/*鐢ㄤ簬鑾峰彇鐗瑰畾璇锋眰绫诲瀷鐨勫畬鎴愯呬笂涓嬫枃鐨勫嚱鏁般 + *鎺ュ彈涓や釜鍙傛暟锛宺eqType 琛ㄧず寮傛I/O completer绫诲瀷锛宧 琛ㄧず绱㈠紩 + *鏍规嵁绫诲瀷鍜岀储寮曡幏鍙栫浉搴旂殑completer涓婁笅鏂囷紙io_context_t锛 + */ +io_context_t CompltrContext(AioCompltrType reqType, int h) +{ + return compltrArray[AIOCOMPLTR_THREAD_IDX(reqType, h)].context; +} + +/* Prototypes for private functions */ +/* + * Signal handlers + */ +/* +鐢ㄤ簬鍐呴儴瀹炵幇鍜屽鐞嗙壒瀹氱殑淇″彿浜嬩欢鐨勭鏈夊嚱鏁板師鍨嬪0鏄庯紝褰撲俊鍙蜂簨浠跺彂鐢熸椂璋冪敤銆 +*/ +static void CompltrConfig(SIGNAL_ARGS);// 鐢ㄤ簬閰嶇疆寮傛I/O completer鐨勭浉鍏冲弬鏁板拰璁剧疆 +static void CompltrQuickDie(SIGNAL_ARGS);// 鐢ㄤ簬蹇熺粓姝㈠紓姝/O completer绾跨▼銆 +static void CompltrShutdown(SIGNAL_ARGS);// 鐢ㄤ簬鍦ㄥ紓姝/O completer绾跨▼閫鍑烘椂鎵ц娓呯悊鍜屽叧闂搷浣 + +/* + * @Description: Compltrfork_exec() and AioCompltrStart() are used to start the + * completer threads. + * + * PG was designed to start processes and pass parameters on the + * command line and via shared memory. We do not need to do + * that with our threads implementation, but rather than change all that + * now we are going to pass the compltrIdx on the command line + * and allow the running thread to find its descriptor in the compltrArray + * in the global context. + * + * Compltrfork_exec formats the arglist, then fork and exec the AIO + * Completer thread. The compltrIdx is converted to a 3 character string, + * so that the parameter does not have to be handled specially by the + * intervening PG code. + * @Param[IN] compltrIdx: aio thread index + * @Return: thread id + * @See also: + */ +/* +鐢ㄤ簬鍚姩寮傛I/O Completer绾跨▼銆傚湪褰撳墠鐨勫疄鐜颁腑锛宱penGauss骞朵笉鏀寔寮傛I/O锛屾墍浠ヨ鍑芥暟鍙細鍙戝嚭閿欒娑堟伅琛ㄧず涓嶆敮鎸侊紝骞惰繑鍥炴棤鏁堢殑绾跨▼ID銆 + +璇ュ嚱鏁颁細鏍煎紡鍖栧懡浠よ鍙傛暟鍒楄〃锛坅rglist锛夛紝鐒跺悗浣跨敤 fork 鍜 exec 鍑芥暟鍒涘缓涓涓柊鐨勭嚎绋嬫潵鎵ц寮傛I/O Completer绾跨▼鐨勫鐞嗐 +鍏朵腑锛宑ompltrIdx 琚浆鎹负涓涓3瀛楃鐨勫瓧绗︿覆锛岃繖鏍峰彲浠ラ伩鍏嶅湪浠g爜涓渶瑕佺壒娈婂鐞嗚繖涓弬鏁帮紝鍥犱负鍙傛暟鐨勪紶閫掑湪鎵ц杩囩▼涓凡缁忚澶勭悊濂戒簡銆 +*/ +ThreadId Compltrfork_exec(int compltrIdx) +{ + // 鍙戝嚭閿欒娑堟伅锛岃〃绀轰笉鏀寔寮傛I/O + ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("openGauss current do not support AIO"))); + // 杩斿洖鏃犳晥鐨勭嚎绋婭D + return InvalidTid; +} + +/* + * @Description: AioCompltrStart + * Set-up the Aio Completer thread descriptors and start the threads. + * This function is invoked in the global context by the postmaster + * to start all the Aio Completer Threads. + * + * Globals + * The compltrArray and AioCompltrThreads + * are globals that control the allocation and configuration of the + * AIO completer threads. + * + * AioCompltrThreads is the number of AIO completer threads. + * Each Completer thread has a unique AioCompltrThread_t context in the + * compltrArray. Each Completer refers to a compltrDescp that + * contains the parameters for the type of request the Completer servers. + * Each Completer context also contains an AIO context and event array. + * @Return: 0 --success; error --failed + * @See also: + */ +int AioCompltrStart(void) +{ + int error = 0;// 閿欒鐮佸垵濮嬪寲 + int try_times = 0;// 灏濊瘯娆℃暟鍒濆鍖 + + /* + * Only allow MAX_AIOCOMPLTR_THREADS + */ + //妫鏌ュ綋鍓嶉厤缃殑 AIO Completer 绾跨▼鏁伴噺鏄惁瓒呰繃浜嗛瀹氫箟鐨勬渶澶ф暟閲 MAX_AIOCOMPLTR_THREADS + if (AioCompltrThreads > MAX_AIOCOMPLTR_THREADS) { + error = 1;// 璁剧疆閿欒鐮 + return error;// 杩斿洖閿欒鐮,涓柇鍑芥暟鎵ц + } + // 璋冪敤瀹夊叏鍐呭瓨鍑芥暟memset_s 鍒濆鍖 compltrArray锛屽皢鍐呭瓨璁剧疆涓洪浂 + errno_t rc = memset_s(&compltrArray, + sizeof(AioCompltrThread_t) * MAX_AIOCOMPLTR_THREADS, + 0, + sizeof(AioCompltrThread_t) * MAX_AIOCOMPLTR_THREADS); + //閿欒妫鏌,鐢ㄤ簬纭繚 memset_s 鍑芥暟鏄惁鎵ц鎴愬姛銆傚鏋 rc锛堣繑鍥炲硷級涓嶄负闆讹紝琛ㄧず鍐呭瓨鍒濆鍖栧嚭鐜颁簡閿欒 + securec_check(rc, "\0", "\0"); + + /* + * Initialize the compltrArray + */ + //鍒濆鍖 compltrArray 鏁扮粍 + for (int i = 0; i < AioCompltrThreads; i++) { + try_times = 0;// 灏濊瘯娆℃暟褰掗浂 + /* Assign a template to the thread descriptor */ + compltrArray[i].compltrDescp = AIOCOMPLTR_TEMPLATE(i);// 涓虹嚎绋嬫弿杩扮鍒嗛厤瀵瑰簲鐨勬ā鏉 + + /* Create the i/o queue and fill in the context */ + do { + // 浣跨敤 io_setup 鍑芥暟鍒涘缓寮傛 I/O 闃熷垪锛屽弬鏁颁负褰撳墠绾跨▼鐨勬渶澶т簨浠舵暟鍜岄槦鍒椾笂涓嬫枃銆 + error = io_setup(compltrArray[i].compltrDescp->maxevents, &compltrArray[i].context); + // 濡傛灉鎴愬姛鍒涘缓闃熷垪鎴栬呴亣鍒扮殑閿欒涓嶆槸 EAGAIN锛堣〃绀鸿祫婧愭殏鏃朵笉鍙敤锛夛紝鍒欒烦鍑哄惊鐜 + if (error == 0 || error != -EAGAIN) { + break; + } + + try_times++; // 灏濊瘯娆℃暟澧炲姞 + // 鎵撳嵃鏃ュ織锛岃褰曞綋鍓嶅皾璇曠殑绾跨▼ID銆佸皾璇曟鏁板拰閿欒鐮併 + ereport(LOG, (errmsg("AIO Startup, Completer thread id =%d try times=%d, error=%d", i, try_times, error))); + pg_usleep(100000L);// 寤惰繜 100,000 寰锛0.1 绉掞級锛岀劧鍚庣户缁笅涓娆″皾璇曘 + } while (try_times < 5);// 寰幆缁х画锛岀洿鍒版垚鍔熷垱寤洪槦鍒楁垨鑰呭皾璇曟鏁拌揪鍒 5 娆° + + if (error != 0) { + goto AioCompltrStartError;// 鍙戠敓閿欒鏃惰烦杞埌閿欒澶勭悊鏍囩 + } + + /* Allocate the event array for the thread */ + /* 涓虹嚎绋嬪垎閰嶄簨浠舵暟缁勭殑鍐呭瓨 鐢ㄤ簬瀛樺偍浜嬩欢鏁扮粍 + compltrArray[i].compltrDescp->max_nr 琛ㄧず浜嬩欢鏁扮粍鐨勬渶澶уぇ灏忥紝sizeof(struct io_event) 琛ㄧず鍗曚釜浜嬩欢鐨勫ぇ灏忋*/ + compltrArray[i].eventsp = (io_event*)malloc(compltrArray[i].compltrDescp->max_nr * sizeof(struct io_event)); + // 妫鏌ュ唴瀛樺垎閰嶆槸鍚︽垚鍔燂紝澶辫触鍒欒繘鍏f璇彞鍐呴儴 + if (compltrArray[i].eventsp == (struct io_event*)NULL) { + + /* malloc failed for some reason... */ + error = 2;// 璁剧疆閿欒鐮佷负 2锛岃〃绀哄唴瀛樺垎閰嶅け璐 + //鎵撳嵃鏃ュ織锛岃褰曞唴瀛樺垎閰嶅け璐ョ殑璇︾粏淇℃伅锛屽寘鎷渶澶т簨浠舵暟鍜岄敊璇爜銆 + ereport(LOG, + (errmsg("AIO Startup malloc io_event failed: max_nr(%d), %d", + compltrArray[i].compltrDescp->max_nr, + error))); + // 璺宠浆鍒伴敊璇鐞嗘爣绛 AioCompltrStartError锛屾墽琛岄敊璇鐞嗘搷浣 + goto AioCompltrStartError; + } + + /* Start AIO Completer thread */ + //浣跨敤 Compltrfork_exec(i) 鍑芥暟鍚姩涓涓紓姝 I/O 瀹屾垚绾跨▼锛屽苟灏嗙嚎绋嬬储寮 i 浣滀负鍙傛暟浼犻掔粰鍑芥暟銆傚嚱鏁拌繑鍥炵嚎绋嬬殑 ID銆 + compltrArray[i].tid = Compltrfork_exec(i); + + // 妫鏌ョ嚎绋嬫槸鍚︽垚鍔熷惎鍔ㄣ傚鏋滃惎鍔ㄥけ璐ワ紝浼氳繘鍏ユ潯浠跺唴閮ㄣ + if (compltrArray[i].tid == (ThreadId)-1) { + /* starting a thread failed */ + error = 3;// 璁剧疆閿欒鐮佷负 3锛岃〃绀哄惎鍔ㄧ嚎绋嬪け璐 + // 鎵撳嵃鏃ュ織锛岃褰曞惎鍔ㄧ嚎绋嬪け璐ョ殑璇︾粏淇℃伅锛屽寘鎷敊璇爜銆 + ereport(LOG, (errmsg("Start AIO Completer thread failed: %d", error))); + goto AioCompltrStartError; // 鍙戠敓閿欒鏃惰烦杞埌閿欒澶勭悊鏍囩 + } + }; + + /* The AIO Completers are open for business */ + AioCompltrReady = true;// AIO Completers 鍑嗗灏辩华 + + /* successful return */ + return 0; + +//閿欒澶勭悊鏍囩 AioCompltrStartError 鏍囪瘑閿欒澶勭悊鐨勮捣濮嬩綅缃 +AioCompltrStartError: + /* + * If anything went wrong, then stop any threads started + * and deallocate the resources. + */ + AioCompltrStop(SIGTERM);// 鍋滄宸插惎鍔ㄧ殑寮傛 I/O 瀹屾垚绾跨▼骞堕噴鏀捐祫婧 + ereport(LOG, (errmsg("AIO Startup Failed,error=%d", error)));// 璁板綍鍚姩澶辫触鐨勯敊璇棩蹇 + + return error;// 杩斿洖閿欒鐮 +} + +/* + * @Description: Stop the Completer threads, cleanup any partially started ones. + * Send SIGQUIT and forget about the threads. + * The caller must ensure that no AIO is in progress prior to using this function. + * @Param[IN] signal:signal + * @See also: + */ +void AioCompltrStop(int signal) +{ + gs_thread_t thread; + AioCompltrReady = false;// 鍋滄AIO Completer绾跨▼鐨勬爣蹇楄缃负false锛岃〃绀虹嚎绋嬩笉鍐嶈繍琛 + + /* + * Stop the threads in the compltrArray. + */ + // 寰幆閬嶅巻AIO Completer绾跨▼鏁扮粍锛屽仠姝㈡墍鏈夌嚎绋 + for (int i = 0; i < AioCompltrThreads; i++) { + /* + * Stop the threads that were started + */ + // 妫鏌ョ嚎绋嬫爣璇嗙鏄惁鏈夋晥 + if (compltrArray[i].tid != 0) { + // 濡傛灉绾跨▼宸插惎鍔紝浣跨敤gs_signal_send鍑芥暟鍚戠嚎绋嬪彂閫佷俊鍙峰仠姝㈢嚎绋嬶紝灏嗕紶鍏ョ殑signal浣滀负淇″彿绫诲瀷銆 + if (gs_signal_send(compltrArray[i].tid, signal) < 0) { + // 濡傛灉鍙戦佷俊鍙峰け璐ワ紝璁板綍閿欒鏃ュ織锛屾寚鏄庡摢涓嚎绋嬬殑淇″彿鍙戦佸け璐ャ + ereport(LOG, (errmsg("kill(%ld,%d) failed: %m", (long)(compltrArray[i].tid), signal))); + } + } + } + // 濡傛灉鏁版嵁搴撴鍦ㄥ穿婧冿紝鍙渶鏉姝籧ompleters骞堕鍑恒 + if (signal == SIGQUIT) { + /* + * if the database is crashing just kill the completers + * and bail-out. + */ + return;// 鐩存帴杩斿洖锛屾潃姝籧ompleters骞堕鍑 + } + + /* + * Wait for the stopped threads to exit. + */ + // 寰幆閬嶅巻AIO Completer绾跨▼鏁扮粍锛岀瓑寰匒IO Completer绾跨▼閫鍑哄苟杩涜娓呯悊 + for (int i = 0; i < AioCompltrThreads; i++) { + /* + * Wait for the killed threads to exit + */ + if (compltrArray[i].tid != 0) {// 妫鏌ョ嚎绋嬫爣璇嗙鏄惁鏈夋晥 + thread.thid = compltrArray[i].tid;// 淇濆瓨绾跨▼鏍囪瘑绗︼紝鐢ㄤ簬绛夊緟绾跨▼閫鍑 + // 浣跨敤gs_thread_join鍑芥暟绛夊緟绾跨▼閫鍑恒傚鏋滆繑鍥炲间笉涓0锛岃〃绀虹瓑寰呯嚎绋嬮鍑哄け璐ャ + if (gs_thread_join(thread, NULL) != 0) { + /* + * If the thread does not exist, treat it as normal exit and we continue to + * do our clean-up work. Otherwise, we treate it as crashed 'cause we do + * not know the current status of the thread and it's better to quit directly + * which sames more safely. + */ + if (ESRCH == pthread_kill(thread.thid, 0)) // 浣跨敤pthread_kill鍑芥暟妫鏌ョ嚎绋嬫槸鍚︿笉瀛樺湪 + // 濡傛灉绾跨▼涓嶅瓨鍦紝璁板綍閿欒鏃ュ織 + ereport(LOG, (errmsg("failed to join thread %lu, no such process", thread.thid))); + else + // 濡傛灉绾跨▼瀛樺湪浣嗘棤娉曠瓑寰呭叾閫鍑猴紝鏍囪绾跨▼宕╂簝 + HandleChildCrash(thread.thid, 1, "AIO process"); + } + compltrArray[i].tid = (pid_t)0; // 娓呯┖绾跨▼鏍囪瘑绗︼紝琛ㄧず绾跨▼宸茬粡閫鍑 + } + } + + /* + * Deallocate their context and event arrays, if any + */ + for (int i = 0; i < AioCompltrThreads; i++) { + compltrArray[i].compltrDescp = (AioCompltrDesc_t*)NULL;// // 娓呯┖绾跨▼鎻忚堪绗︽寚閽堬紝闃叉鎮┖鎸囬拡 + + /* destroy the AIO context */ + // 濡傛灉AIO涓婁笅鏂囧瓨鍦 + if (compltrArray[i].context) { + io_destroy(compltrArray[i].context);// 閿姣丄IO涓婁笅鏂囷紝閲婃斁鐩稿叧璧勬簮 + compltrArray[i].context = (io_context_t)NULL;// 娓呯┖AIO涓婁笅鏂囨寚閽堬紝闃叉鎮┖鎸囬拡 + } + + /* Deallocate the events array */ + // 濡傛灉浜嬩欢鏁扮粍鎸囬拡瀛樺湪 + if (compltrArray[i].eventsp) { + free(compltrArray[i].eventsp);// 閲婃斁浜嬩欢鏁扮粍鐨勫唴瀛橈紝闃叉鍐呭瓨娉勬紡 + compltrArray[i].eventsp = (struct io_event*)NULL;// 娓呯┖浜嬩欢鏁扮粍鎸囬拡锛岄槻姝㈡偓绌烘寚閽 + } + } + + /* successful return */ + return; +} + +/* + * @Description: Main entry point for an AIO Completer thread + * @Param[IN] ac: param count + * @Param[IN] av: param list + * @See also: + */ +void AioCompltrMain(int ac, char** av) +{ + // 妫鏌ュ懡浠よ鍙傛暟鏁伴噺鏄惁瓒冲 + if (ac < 4) { + ereport(WARNING, (errmsg("invalid AIO argument num:%d", ac))); + exit(1); + } + /* compltrIdx identifies this thread. */ + // 瑙f瀽Completer绾跨▼鐨勭储寮 + int compltrIdx = atoi(av[3]); + + /* + * Global thread local shortcuts to the completer descriptor + * in the compltrArray, these are assigned on entry. + */ + /* + 浣跨敤鏈湴鍙橀噺鎻愬墠鑾峰彇瀵瑰畬鎴愬櫒鎻忚堪绗︿腑鐩稿叧淇℃伅鐨勫紩鐢紝浠ヤ究鍚庣画浠g爜涓娇鐢ㄣ備粠鑰屽噺灏戝啑浣欑殑鎿嶄綔锛屾彁楂樹唬鐮佸彲璇绘у拰鎬ц兘銆 + 鍏朵腑鍖呮嫭浜咥IO涓婁笅鏂囥佷簨浠舵暟缁勬寚閽堛佹渶灏/鏈澶х瓑寰呬簨浠舵暟閲忋佽秴鏃惰缃拰AIO鍥炶皟鍑芥暟绛変俊鎭殑鑾峰彇銆 + */ + io_context_t context = compltrArray[compltrIdx].context; // AIO涓婁笅鏂 + io_event* eventsp = compltrArray[compltrIdx].eventsp;// 浜嬩欢鏁扮粍鎸囬拡 + AioCompltrDesc_t* compltrDescp = compltrArray[compltrIdx].compltrDescp;// 瀹屾垚鍣ㄦ弿杩扮鎸囬拡 + int min_nr = compltrDescp->min_nr;// 鏈灏忕瓑寰呬簨浠舵暟閲 + int max_nr = compltrDescp->max_nr; // 鏈澶у彲妫绱㈢殑浜嬩欢鏁伴噺 + struct timespec timeout;// 浜嬩欢绛夊緟瓒呮椂 + struct timespec shutdown_timeout; // 鍏抽棴绛夊緟瓒呮椂 + timeout.tv_sec = compltrDescp->timeout;// 璁剧疆绛夊緟浜嬩欢瓒呮椂鐨勭鏁 + timeout.tv_nsec = 0; // 璁剧疆绛夊緟浜嬩欢瓒呮椂鐨勭撼绉掓暟 + shutdown_timeout.tv_sec = AioCompltrShutdownTimeout;// 璁剧疆鍏抽棴绛夊緟瓒呮椂鐨勭鏁 + shutdown_timeout.tv_nsec = 0;// 璁剧疆鍏抽棴绛夊緟瓒呮椂鐨勭撼绉掓暟 + AioCallback_t callback = compltrDescp->callback;// 鑾峰彇AIO鍥炶皟鍑芥暟鐨勬寚閽 + + /* + * Handle signals the postmaster might send us + * SIGTERM causes the thread to prepare to exit + * SIGQUIT causes immediate exit without cleanup. + * SIGUSR1 is presently unused- reserved for future use. + */ + //涓哄紓姝/O Completer绾跨▼璁剧疆淇″彿澶勭悊鏂瑰紡锛岀‘淇濈嚎绋嬭兘澶熼傚綋鍦板搷搴斾笉鍚岀殑淇″彿 + (void)gspqsignal(SIGHUP, CompltrConfig); /* retrieve config */ //SIGHUP 淇″彿灏嗚Е鍙 CompltrConfig 鍑芥暟锛岀敤浜庨噸鏂板姞杞介厤缃 + (void)gspqsignal(SIGINT, SIG_IGN);// SIGINT 淇″彿琚拷鐣ワ紝涓嶄細涓柇绾跨▼鎵ц銆 + (void)gspqsignal(SIGTERM, CompltrShutdown); /* shutdown */ //SIGTERM 淇″彿灏嗚Е鍙 CompltrShutdown 鍑芥暟锛岀敤浜庤繘琛岀嚎绋嬪叧闂拰娓呯悊銆 + (void)gspqsignal(SIGQUIT, CompltrQuickDie); /* hard crash time */ // SIGQUIT 淇″彿灏嗚Е鍙 CompltrQuickDie 鍑芥暟锛岀敤浜庡揩閫熺粓姝㈢嚎绋嬫墽琛屻 + (void)gspqsignal(SIGALRM, SIG_IGN);// SIGALRM 淇″彿琚拷鐣ャ + (void)gspqsignal(SIGPIPE, SIG_IGN);// SIGPIPE 淇″彿琚拷鐣ャ + (void)gspqsignal(SIGUSR1, SIG_IGN); /* reserved */ //SIGUSR1 淇″彿閮借蹇界暐銆 + (void)gspqsignal(SIGUSR2, SIG_IGN);// SIGUSR2 淇″彿琚拷鐣ャ + + /* + * Reset some signals that are accepted by postmaster but we don't + * need. + */ + (void)gspqsignal(SIGCHLD, SIG_DFL);// 鎭㈠榛樿澶勭悊 SIGCHLD 淇″彿 + (void)gspqsignal(SIGTTIN, SIG_DFL);// 鎭㈠榛樿澶勭悊 SIGTTIN 淇″彿 + (void)gspqsignal(SIGTTOU, SIG_DFL); // 鎭㈠榛樿澶勭悊 SIGTTOU 淇″彿 + (void)gspqsignal(SIGCONT, SIG_DFL);// 鎭㈠榛樿澶勭悊 SIGCONT 淇″彿 + (void)gspqsignal(SIGWINCH, SIG_DFL);// 鎭㈠榛樿澶勭悊 SIGWINCH 淇″彿 + + /* We allow SIGQUIT (quickdie) at all times */ + sigdelset(&t_thrd.libpq_cxt.BlockSig, SIGQUIT);// 鍏佽 SIGQUIT (quickdie) 淇″彿闅忔椂琚帴鏀 + + /* Create a resource owner to keep track of our resources (buffer + * pins etc... + * + * Create a memory context if we ever allocate memory here... + * + * Handle exceptions like from ereport, elog if we do not want + * to just die... +// AioCompltrMain() perhaps need better exception handling? jeh + */ + /* + * Unblock signals (blocked when postmaster forked us) + */ + gs_signal_setmask(&t_thrd.libpq_cxt.UnBlockSig, NULL);// 瑙i櫎涔嬪墠鍦ㄤ富杩涚▼涓樆濉炵殑淇″彿 + (void)gs_signal_unblock_sigusr2();// 瑙i櫎瀵 SIGUSR2 淇″彿鐨勯樆濉 + + /* Announce that the Completer has been started */ + ereport(LOG, (errmsg("AIO Completer %d STARTED.", compltrIdx)));// 鍦ㄦ棩蹇椾腑璁板綍寮傛I/O Completer绾跨▼宸茬粡鍚姩 + + for (;;) { + int eventsReceived;//瀛樺偍浠 io_getevents 鍑芥暟涓幏鍙栫殑宸插畬鎴愮殑寮傛I/O浜嬩欢鏁伴噺鎴栭敊璇唬鐮 + + /* + * Reload configuration -if requested. + */ + // 濡傛灉鏈夐噸鏂板姞杞介厤缃殑璇锋眰锛岃繘琛岀浉搴旂殑澶勭悊锛屼絾鍦ㄦ浠g爜娈典腑琚鐢ㄤ簡 + if (t_thrd.aio_cxt.config_requested) { + /* disabled config request, not time for this now. ProcessConfigFile PGC_SIGHUP; */ + // 濡傛灉閰嶇疆閲嶈浇璇锋眰琚缃紝杩欐浠g爜浼氱鐢ㄩ厤缃姹傚苟鐣ヨ繃鍚庣画鐨勫鐞嗭紝浠ラ伩鍏嶅湪褰撳墠涓婁笅鏂囦腑閲嶆柊鍔犺浇閰嶇疆鏂囦欢 + t_thrd.aio_cxt.config_requested = false; + } + + /* + * If shutdown is requested, set shutdown_pending and + * restart io_getevents() if it was interrupted. + * The io_getevents() timeout is reduced to shutdown_timeout to + * allow the thread to exit quickly when its time comes. + * Once shutdown is requested, there is no going back. + */ + // 濡傛灉鏀跺埌浜嗗叧闂姹 + if (t_thrd.aio_cxt.shutdown_requested) { + timeout = shutdown_timeout;// 璁剧疆瓒呮椂鏃堕棿涓簊hutdown_timeout锛屼互渚垮揩閫熼鍑虹嚎绋 + + ereport(LOG, (errmsg("AIO Completer %d EXITED.", compltrIdx)));// 璁板綍鏃ュ織锛岃〃绀篈IO Completer姝e湪閫鍑 + proc_exit(0);// 閫鍑虹嚎绋 + } + + /* + * Wait for some AIO request(s) to complete + * on the given context. Retry if the syscall is + * interrupted. + */ + // 绛夊緟涓浜汚IO璇锋眰瀹屾垚鍦ㄧ粰瀹氱殑涓婁笅鏂囦腑锛屾渶灏忕瓑寰呬簨浠舵暟閲忎负min_nr锛屾渶澶т负max_nr锛屾渶闀跨瓑寰呮椂闂寸敱timeout鎸囧畾 + // 杩斿洖鍊兼槸涓涓暣鏁帮紝琛ㄧず鎴愬姛鑾峰彇鐨勪簨浠舵暟閲忋傚鏋滆繑鍥炲间负璐熸暟锛岃〃绀哄彂鐢熶簡閿欒锛 + eventsReceived = io_getevents(context, min_nr, max_nr, eventsp, &timeout); + /* + * If io_getevents() got interrupted, + * take the opportunity to check for pending requests. + * Then restart the io_getevents() call. + */ + // 濡傛灉 io_getevents() 琚腑鏂紝閲嶆柊灏濊瘯鑾峰彇浜嬩欢 + if (eventsReceived == -EINTR) { + continue; + } + + /* + * io_getevents() reports errors as negative values. + */ + // io_getevents() 鎶ュ憡閿欒鐨勮繑鍥炲间负璐熸暟 + if (eventsReceived < 0) { + /* Report error */ + // 璁板綍閿欒鏃ュ織锛屽彂鍑 PANIC 绾у埆鐨勯敊璇姤鍛 + ereport(PANIC, (errmsg("AIO Completer io_getevents() failed: error %d .", eventsReceived))); + } + // 鏂█锛岀‘淇 eventsReceived 涓嶈秴杩囨渶澶ф暟閲 + Assert(eventsReceived <= max_nr); + + /* + * Call the callback for each event returned + * We expect 0 to max_nr requests. The obj here is + * the I/O request and the db context. + */ + // 閫愪釜閬嶅巻銆佸鐞嗗紓姝/O浜嬩欢鏁扮粍涓殑姣忎釜浜嬩欢锛屾墽琛岀壒瀹氭搷浣滄垨鍥炶皟鍑芥暟銆 + for (struct io_event* eventp = eventsp; eventsReceived--; eventp++) { + callback((void*)eventp->obj, eventp->res);// 璋冪敤鍥炶皟鍑芥暟锛屼紶鍏 I/O 璇锋眰鐨 obj 鍜岀粨鏋 + } + } + // 鎵鏈変簨浠跺鐞嗗畬鎴愬悗锛岀嚎绋嬪嵆灏嗛鍑 + + // 璁板綍绾跨▼閫鍑虹殑鏃ュ織淇℃伅 + ereport(LOG, (errmsg("AIO Completer %d EXITED.", compltrIdx))); + exit(0);// 閫鍑虹嚎绋嬶紝杩斿洖鐘舵佺爜 0 +} + +/* + * @Description: signal handler routines for config,not used now + * @See also: + */ +// 淇″彿澶勭悊绋嬪簭锛岀敤浜庡鐞嗛厤缃姹傦紝鐩墠鏈娇鐢 +static void CompltrConfig(SIGNAL_ARGS) +{ + t_thrd.aio_cxt.config_requested = true;// 鏍囪閰嶇疆璇锋眰涓簍rue,琛ㄧず閰嶇疆璇锋眰宸茬粡鍙戠敓 +} + +/* + * @Description: CompltrQuickDie() occurs when signalled SIGQUIT by the postmaster. + * Some backend has bought the farm, + * so we need to stop what we're doing and exit. + * @See also: + */ +// 蹇熼鍑虹殑淇″彿澶勭悊绋嬪簭锛屽綋postmaster閫氳繃SIGQUIT淇″彿鍙戝嚭缁堟璇锋眰鏃惰Е鍙 +static void CompltrQuickDie(SIGNAL_ARGS) +{ + PG_SETMASK(&t_thrd.libpq_cxt.BlockSig);// 闃诲鎵鏈変俊鍙 + + /* + * We DO NOT want to run proc_exit() callbacks -- we're here because + * shared memory may be corrupted. Like the other postmaster + * children, ...Just nail the windows shut and get out of town.... + */ + on_exit_reset();// 閲嶇疆杩涚▼閫鍑哄洖璋 + + /* + * Note we do exit(2) not exit(0)... + * ...just like the other postmaster children. + */ + exit(2);// 浠ラ鍑虹爜2閫鍑猴紝绫讳技鍏朵粬涓绘帶杩涚▼瀛愯繘绋嬬殑鍋氭硶 +} + +/* + * @Description: CompltrShutdown() occurs when signalled SIGTERM by the postmaster. + * @See also: + */ +// 鍏抽棴淇″彿澶勭悊绋嬪簭锛屽綋postmaster閫氳繃SIGTERM淇″彿鍙戝嚭鍏抽棴璇锋眰鏃惰Е鍙 +static void CompltrShutdown(SIGNAL_ARGS) +{ + t_thrd.aio_cxt.shutdown_requested = true;// 璁剧疆寮傛I/O Completer绾跨▼鐨勫叧闂姹傛爣蹇 +} + +/** + * @Description: Initialize Resource used by adio + * @in void + * @return void + */ +// 鍒濆鍖栧紓姝/O鐨勮祫婧 +void AioResourceInitialize(void) +{ + // 鍒涘缓涓涓叡浜唴瀛樹笂涓嬫枃鐢ㄤ簬寮傛I/O璧勬簮锛屼互渚胯繘琛屽唴瀛樺垎閰嶅拰绠$悊 + AdioSharedContext = AllocSetContextCreate((MemoryContext)g_instance.instance_context, + "AdioSharedMemory",// 璁剧疆涓婁笅鏂囩殑鍚嶇О锛岀敤浜庢爣璇嗗拰璇嗗埆姝や笂涓嬫枃銆 + ALLOCSET_DEFAULT_MINSIZE,//璁剧疆涓婁笅鏂囩殑鍒濆鏈灏忓唴瀛樺垎閰嶅ぇ灏 + ALLOCSET_DEFAULT_INITSIZE,//璁剧疆涓婁笅鏂囩殑鍒濆鍐呭瓨姹犲ぇ灏 + ALLOCSET_DEFAULT_MAXSIZE,// 璁剧疆涓婁笅鏂囩殑鏈澶у唴瀛樻睜澶у皬 + SHARED_CONTEXT);// 璁剧疆涓婁笅鏂囩殑鏍囧織锛屾寚绀哄畠鏄竴涓叡浜笂涓嬫枃 +>>>>>>> 108c7fd5357dfbed4193fd5eb60e4bd6db01031f } diff --git a/src/gausskernel/process/postmaster/alarmchecker.cpp b/src/gausskernel/process/postmaster/alarmchecker.cpp index 2ffe93696..4ba9d67ff 100644 --- a/src/gausskernel/process/postmaster/alarmchecker.cpp +++ b/src/gausskernel/process/postmaster/alarmchecker.cpp @@ -22,6 +22,7 @@ * * ------------------------------------------------------------------------- */ +// 璇ユ枃浠跺疄鐜颁簡openGauss鐨勬姤璀︽鏌ョ嚎绋嬪姛鑳斤紝涓昏鐢ㄤ簬妫鏌ユ暟鎹簱杩愯杩囩▼涓殑寮傚父鎯呭喌骞惰繘琛岀浉搴旂殑鎶ヨ澶勭悊 #include "postgres.h" #include "knl/knl_variable.h" @@ -48,64 +49,77 @@ #include "replication/walsender.h" // declare the global variable of alarm module -int g_alarmReportInterval; -char g_alarmComponentPath[MAXPGPATH]; -int g_alarmReportMaxCount; +// 澹版槑鐢ㄤ簬鎺у埗鎶ヨ妯″潡琛屼负鐨勫叏灞鍙橀噺 +int g_alarmReportInterval; // 鎶ヨ涓婃姤鐨勬椂闂撮棿闅旓紙鍗曚綅锛氱锛 +char g_alarmComponentPath[MAXPGPATH]; // 鎶ヨ缁勪欢璺緞锛屽瓨鍌ㄦ姤璀︿俊鎭殑缁勪欢鐨勮矾寰勶紙闀垮害涓篗AXPGPATH锛 +int g_alarmReportMaxCount; // 鏈澶ф姤璀︿笂鎶ユ鏁 /* seconds, interval of alarm check loop. */ -static const int AlarmCheckInterval = 1; +static const int AlarmCheckInterval = 1; // 鎶ヨ妫鏌ュ惊鐜殑鏃堕棿闂撮殧锛屽垵濮嬭缃负1绉 -bool enable_alarm = false; +bool enable_alarm = false; // 琛ㄧず鏄惁鍚敤鎶ヨ鍔熻兘銆傚垵濮嬪间负false锛岄氳繃璁剧疆涓簍rue鏉ュ惎鐢ㄦ姤璀﹀姛鑳 -static Alarm* DataInstAlarmList = NULL; +static Alarm* DataInstAlarmList = NULL; // 鎸囧悜 Alarm 缁撴瀯浣撶殑鎸囬拡锛岃〃绀烘姤璀﹂」鐨勫垪琛ㄣ傛姤璀﹂」鏄敤浜庢娴嬩笉鍚岀被鍨嬫姤璀︾殑閰嶇疆淇℃伅鍜屽鐞嗗嚱鏁扮殑闆嗗悎銆 -static int DataInstAlarmListSize = 0; +static int DataInstAlarmListSize = 0; // 鎶ヨ椤瑰垪琛ㄧ殑澶у皬锛屽嵆鍒楄〃涓姤璀﹂」鐨勬暟閲 -AlarmCheckResult DataOrRedoDirNotExistChecker(Alarm* alarm, AlarmAdditionalParam* additionalParam); +// 鍑芥暟鍘熷瀷澹版槑 +AlarmCheckResult DataOrRedoDirNotExistChecker(Alarm* alarm, AlarmAdditionalParam* additionalParam);//鎶ヨ妫鏌ュ嚱鏁帮紝鐢ㄤ簬妫鏌ユ暟鎹洰褰曟垨閲嶅仛鏃ュ織鐩綍鏄惁瀛樺湪 -static void DataInstAlarmItemInitialize(void); -static void acSighupHandler(SIGNAL_ARGS); -static void acSigquitHandler(SIGNAL_ARGS); +static void DataInstAlarmItemInitialize(void); // 鎶ヨ椤瑰垵濮嬪寲鍑芥暟锛岀敤浜庡垵濮嬪寲鏁版嵁瀹炰緥鐨勬姤璀﹂」鍒楄〃銆 -extern AlarmCheckResult DataInstArchChecker(Alarm* alarm, AlarmAdditionalParam* additionalParam); -extern AlarmCheckResult ConnAuthMethodChecker(Alarm* alarm, AlarmAdditionalParam* additionalParam); +static void acSighupHandler(SIGNAL_ARGS); // SIGHUP淇″彿澶勭悊鍑芥暟锛岀敤浜庡湪鏀跺埌SIGHUP淇″彿鏃惰缃浉鍏虫爣蹇 +static void acSigquitHandler(SIGNAL_ARGS); // SIGQUIT淇″彿澶勭悊鍑芥暟鐨勫師鍨嬶紝鐢ㄤ簬鍦ㄦ敹鍒癝IGQUIT淇″彿鏃惰缃浉鍏虫爣蹇椼 +// 鏁版嵁瀹炰緥褰掓。妫鏌ュ嚱鏁帮紝鐢ㄤ簬妫鏌ユ暟鎹疄渚嬬殑褰掓。鐘舵 +extern AlarmCheckResult DataInstArchChecker(Alarm* alarm, AlarmAdditionalParam* additionalParam); +// 杩炴帴璁よ瘉鏂规硶妫鏌ュ嚱鏁帮紝鐢ㄤ簬妫鏌ヨ繛鎺ョ殑璁よ瘉鏂规硶鏄惁寮傚父 +extern AlarmCheckResult ConnAuthMethodChecker(Alarm* alarm, AlarmAdditionalParam* additionalParam); +// 鏁版嵁瀹炰緥杩炴帴鍒癎TM鐨勬鏌ュ嚱鏁帮紝鐢ㄤ簬妫鏌ユ暟鎹疄渚嬭繛鎺ュ埌GTM鐨勭姸鎬 extern AlarmCheckResult DataInstConnToGTMChecker(Alarm* alarm, AlarmAdditionalParam* additionalParam); +// 鍒濆鍖栨暟鎹疄渚嬫姤璀﹀垪琛 void DataInstAlarmItemInitialize(void) { + // 璁剧疆鏁版嵁瀹炰緥鎶ヨ椤圭殑鏁伴噺涓6 DataInstAlarmListSize = 6; + // 鍒嗛厤鍐呭瓨鏉ュ瓨鍌ㄦ暟鎹疄渚嬫姤璀﹂」 DataInstAlarmList = (Alarm*)AlarmAlloc(sizeof(Alarm) * DataInstAlarmListSize); + // 妫鏌ュ唴瀛樺垎閰嶆槸鍚︽垚鍔燂紝濡傛灉澶辫触鍒欒褰曢敊璇棩蹇楀苟閫鍑虹▼搴 if (NULL == DataInstAlarmList) { AlarmLog(ALM_LOG, "Out of memory: DataInstAlarmItemInitialize failed."); exit(1); } - // ALM_AI_MissingDataInstDataOrRedoDir + // 鍒濆鍖栧悇涓暟鎹疄渚嬫姤璀﹂」 鍙傛暟鍒楄〃涓悗涓変釜鍒嗗埆涓烘姤璀﹂」鐨勭被鍨嬨佷弗閲嶆х骇鍒紝浠ュ強瀵瑰簲鐨勬鏌ュ嚱鏁 + // ALM_AI_MissingDataInstDataOrRedoDir 鎶ヨ椤 AlarmItemInitialize( &(DataInstAlarmList[0]), ALM_AI_MissingDataInstDataOrRedoDir, ALM_AS_Normal, DataOrRedoDirNotExistChecker); - // ALM_AI_MissingDataInstWalSegmt + // ALM_AI_MissingDataInstWalSegmt 鎶ヨ椤 AlarmItemInitialize( &(DataInstAlarmList[1]), ALM_AI_MissingDataInstWalSegmt, ALM_AS_Normal, WalSegmentsRemovedChecker); - // ALM_AI_TooManyDataInstConn + // ALM_AI_TooManyDataInstConn 鎶ヨ椤 AlarmItemInitialize(&(DataInstAlarmList[2]), ALM_AI_TooManyDataInstConn, ALM_AS_Normal, ConnectionOverloadChecker); - // ALM_AI_AbnormalDataInstArch + // ALM_AI_AbnormalDataInstArch 鎶ヨ椤 AlarmItemInitialize(&(DataInstAlarmList[3]), ALM_AI_AbnormalDataInstArch, ALM_AS_Normal, DataInstArchChecker); - // ALM_AI_AbnormalDataInstConnAuthMethod + // ALM_AI_AbnormalDataInstConnAuthMethod 鎶ヨ椤 AlarmItemInitialize( &(DataInstAlarmList[4]), ALM_AI_AbnormalDataInstConnAuthMethod, ALM_AS_Normal, ConnAuthMethodChecker); - // ALM_AI_AbnormalDataInstConnToGTM + // ALM_AI_AbnormalDataInstConnToGTM 鎶ヨ椤 AlarmItemInitialize( &(DataInstAlarmList[5]), ALM_AI_AbnormalDataInstConnToGTM, ALM_AS_Normal, DataInstConnToGTMChecker); } +// 鐗瑰畾鏉′欢涓嬪惎鍔ㄦ姤璀︽鏌ョ嚎绋嬶紝浠ヤ究瀹氭湡妫鏌ョ郴缁熺姸鎬佸苟杩涜鎶ヨ澶勭悊銆 ThreadId startAlarmChecker(void) { + // 濡傛灉涓嶆槸鍦≒ostmaster鐜涓嬫垨鑰呮姤璀﹀姛鑳借绂佺敤锛屽垯鐩存帴杩斿洖0锛岃〃绀烘湭鍚姩鎶ヨ妫鏌ョ嚎绋 if (!IsPostmasterEnvironment || !enable_alarm) { return 0; } - + // 鍚﹀垯锛岃皟鐢╥nitialize_util_thread鍑芥暟鍚姩鎶ヨ妫鏌ョ嚎绋嬶紝骞惰繑鍥炵嚎绋婭D return initialize_util_thread(ALARMCHECK); } +// 缁存姢涓涓懆鏈熸х殑鎶ヨ妫鏌ョ嚎绋嬶紝鐢ㄤ簬鍙婃椂鍙戠幇绯荤粺寮傚父鎯呭喌骞惰繘琛岀浉搴旂殑澶勭悊銆 NON_EXEC_STATIC void AlarmCheckerMain() { @@ -113,21 +127,23 @@ NON_EXEC_STATIC void AlarmCheckerMain() IsUnderPostmaster = true; /* reset t_thrd.proc_cxt.MyProcPid */ - t_thrd.proc_cxt.MyProcPid = gs_thread_self(); + t_thrd.proc_cxt.MyProcPid = gs_thread_self(); //灏嗗綋鍓嶇嚎绋嬬殑绯荤粺绾х嚎绋婭D鍒嗛厤缁橫yProcPid锛屼互鏍囪瘑褰撳墠绾跨▼ /* record Start Time for logging */ - t_thrd.proc_cxt.MyStartTime = time(NULL); + t_thrd.proc_cxt.MyStartTime = time(NULL); //鑾峰彇褰撳墠鐨勭郴缁熸椂闂达紝鍗宠褰曠嚎绋嬬殑鍚姩鏃堕棿銆 /* reord my name */ - t_thrd.proc_cxt.MyProgName = "AlarmChecker"; + t_thrd.proc_cxt.MyProgName = "AlarmChecker"; // 璁剧疆绾跨▼鐨勫悕绉帮紝鐢ㄤ簬鏍囪瘑褰撳墠绾跨▼鐨勫悕绉 /* Identify myself via ps */ - init_ps_display("AlarmChecker", "", "", ""); + init_ps_display("AlarmChecker", "", "", ""); // 璁剧疆绾跨▼鍦ㄨ繘绋嬬姸鎬侊紙ps锛夋樉绀轰腑鐨勬爣璇嗕负 "AlarmChecker" - AlarmLog(ALM_LOG, "alarm checker started."); + AlarmLog(ALM_LOG, "alarm checker started."); // 璁板綍鎶ヨ妫鏌ョ嚎绋嬪惎鍔ㄤ俊鎭 + // 鍒濆鍖朙atch鏀寔锛岀敤浜庣瓑寰匧atch鐨勮Е鍙 InitializeLatchSupport(); /* needed for latch waits */ + // 鍒濆鍖栫敤浜庝俊鍙峰鐞嗙殑绉佹湁Latch锛屼互渚垮湪淇″彿鍒拌揪鏃跺敜閱掔嚎绋嬫墽琛岀浉搴旂殑澶勭悊 /* Initialize private latch for use by signal handlers */ InitLatch(&t_thrd.alarm_cxt.AlarmCheckerLatch); @@ -139,10 +155,15 @@ NON_EXEC_STATIC void AlarmCheckerMain() * want to wait for the backends to exit, whereupon the postmaster will * tell us it's okay to shut down (via SIGUSR2). */ + // 澶勭悊浜嗕俊鍙风殑璁剧疆鍜屽拷鐣ワ紝纭繚鎶ヨ妫鏌ョ嚎绋嬭兘澶熸纭搷搴旀垨蹇界暐涓嶅悓鐨勪俊鍙 + // 灏哠IGHUP淇″彿鐨勫鐞嗗嚱鏁拌缃负acSighupHandler銆傚綋鏀跺埌SIGHUP淇″彿鏃讹紝浼氳Е鍙戣淇″彿澶勭悊鍑芥暟锛岀敤浜庤鍙栭厤缃枃浠剁殑鏍囧織浣嶃 (void)gspqsignal(SIGHUP, acSighupHandler); /* set flag to read config file */ + // 灏哠IGINT鍜孲IGTERM淇″彿鐨勫鐞嗚缃负蹇界暐鐘舵侊紝褰撴敹鍒拌繖涓や釜淇″彿鏃讹紝涓嶄細瑙﹀彂浠讳綍澶勭悊銆 (void)gspqsignal(SIGINT, SIG_IGN); (void)gspqsignal(SIGTERM, SIG_IGN); + // 灏哠IGQUIT淇″彿鐨勫鐞嗗嚱鏁拌缃负acSigquitHandler銆傚綋鏀跺埌SIGQUIT淇″彿鏃讹紝浼氳Е鍙戣淇″彿澶勭悊鍑芥暟锛岀敤浜庢墽琛屽揩閫熼鍑烘搷浣溿 (void)gspqsignal(SIGQUIT, acSigquitHandler); + // 灏哠IGALRM銆丼IGPIPE銆丼IGUSR1銆丼IGUSR2淇″彿鐨勫鐞嗚缃负蹇界暐鐘舵侊紝鍗冲綋鏀跺埌浠ヤ笂淇″彿鏃讹紝涓嶄細瑙﹀彂浠讳綍澶勭悊銆 (void)gspqsignal(SIGALRM, SIG_IGN); (void)gspqsignal(SIGPIPE, SIG_IGN); (void)gspqsignal(SIGUSR1, SIG_IGN); @@ -151,46 +172,57 @@ NON_EXEC_STATIC void AlarmCheckerMain() /* * Reset some signals that are accepted by postmaster but not here */ - (void)gspqsignal(SIGCHLD, SIG_DFL); - (void)gspqsignal(SIGTTIN, SIG_DFL); - (void)gspqsignal(SIGTTOU, SIG_DFL); - (void)gspqsignal(SIGCONT, SIG_DFL); - (void)gspqsignal(SIGWINCH, SIG_DFL); + // 閲嶇疆涓浜涗俊鍙风殑榛樿澶勭悊鏂瑰紡锛屼互纭繚鎶ヨ妫鏌ョ嚎绋嬩笉浼氬共鎵板叾浠栦俊鍙风殑澶勭悊 + // 灏嗕俊鍙风殑澶勭悊璁剧疆涓洪粯璁ゅ鐞嗘柟寮 SIG_DFL + (void)gspqsignal(SIGCHLD, SIG_DFL); // 瀛愯繘绋嬬姸鎬佸彉鍖栦俊鍙 + (void)gspqsignal(SIGTTIN, SIG_DFL); // 鍚庡彴杩涚▼璇曞浘浠庣粓绔鍙栨椂鍙戦佺殑淇″彿 + (void)gspqsignal(SIGTTOU, SIG_DFL); // 鍚庡彴杩涚▼璇曞浘鍚戠粓绔啓鍏ユ椂鍙戦佺殑淇″彿 + (void)gspqsignal(SIGCONT, SIG_DFL); // 鐢ㄤ簬缁х画鍋滄鐨勮繘绋嬬殑淇″彿 + (void)gspqsignal(SIGWINCH, SIG_DFL); // 缁堢绐楀彛澶у皬鍙戠敓鍙樺寲鏃跺彂閫佺殑淇″彿 + // 澶勭悊淇″彿鎺╃爜锛屼互鍏佽鎺ユ敹涓浜涚壒瀹氱殑淇″彿 gs_signal_setmask(&t_thrd.libpq_cxt.UnBlockSig, NULL); (void)gs_signal_unblock_sigusr2(); /* all is done info top memory context. */ + // 鍒囨崲褰撳墠绾跨▼鐨勫唴瀛樹笂涓嬫枃鍒伴粯璁ょ殑鍐呭瓨涓婁笅鏂囩粍 (void)MemoryContextSwitchTo(THREAD_GET_MEM_CXT_GROUP(MEMORY_CONTEXT_DEFAULT)); - + // 璋冪敤鍑芥暟锛屽垵濮嬪寲鏁版嵁瀹炰緥鐨勬姤璀﹀垪琛 DataInstAlarmItemInitialize(); + // 鎶ヨ妫鏌ョ嚎绋嬬殑涓昏宸ヤ綔寰幆锛岀敤浜庢寔缁繘琛屾姤璀︽鏌ュ拰澶勭悊 for (;;) { /* Clear any already-pending wakeups */ + //灏嗘姤璀︽鏌ョ嚎绋嬬殑绉佹湁Latch閲嶇疆涓烘湭瑙﹀彂鐘舵侊紝闃叉鍦ㄧ瓑寰呮湡闂村彲鑳藉彂鐢熺殑绔炰簤鏉′欢鎴栨剰澶栬Е鍙戙 ResetLatch(&t_thrd.alarm_cxt.AlarmCheckerLatch); /* the normal shutdown case */ + // 濡傛灉鏀跺埌浜嗙粓姝俊鍙凤紝閫鍑哄惊鐜 if (t_thrd.alarm_cxt.gotSigdie) break; /* * reload the postgresql.conf */ + // 濡傛灉鏀跺埌浜嗛噸鏂板姞杞介厤缃枃浠剁殑淇″彿 if (t_thrd.alarm_cxt.gotSighup) { + // 璁剧疆涓 false锛岃〃绀烘姤璀︽鏌ョ嚎绋嬩笉鍐嶉渶瑕侀噸鏂板姞杞介厤缃枃浠躲 + // 鐢ㄤ簬澶勭悊 SIGHUP 淇″彿鎵ц鎿嶄綔锛屾爣璁板凡缁忕悊閲嶆柊鍔犺浇閰嶇疆鏂囦欢鐨勮姹傦紝浠ヤ究绾跨▼鍦ㄤ笅娆″惊鐜凯浠f椂涓嶄細鍐嶆瑙﹀彂閲嶆柊鍔犺浇 t_thrd.alarm_cxt.gotSighup = false; - ProcessConfigFile(PGC_SIGHUP); + ProcessConfigFile(PGC_SIGHUP); // 璋冪敤ProcessConfigFile鍑芥暟閲嶆柊鍔犺浇閰嶇疆鏂囦欢 } - + // 璋冪敤AlarmCheckerLoop鍑芥暟杩涜鎶ヨ妫鏌 AlarmCheckerLoop(DataInstAlarmList, DataInstAlarmListSize); /* * Sleep until there's something to do */ + // 绛夊緟涓娈垫椂闂达紝绛夊緟Latch琚缃垨瓒呮椂 (void)WaitLatch(&t_thrd.alarm_cxt.AlarmCheckerLatch, WL_LATCH_SET | WL_TIMEOUT, AlarmCheckInterval * 1000); } - + // 璁板綍鏃ュ織锛屾爣璇嗘姤璀︽鏌ョ嚎绋嬫鍦ㄥ叧闂 AlarmLog(ALM_LOG, "alarm checker shutting down..."); - + // 璋冪敤 proc_exit 鍑芥暟缁堟绾跨▼鎵ц銆傚弬鏁 0 琛ㄧず姝e父閫鍑猴紝绾跨▼灏嗗湪姝ゅ缁堟骞堕噴鏀剧浉鍏宠祫婧 proc_exit(0); } @@ -203,15 +235,16 @@ NON_EXEC_STATIC void AlarmCheckerMain() * Description : * Notes : */ +// 淇″彿澶勭悊鍑芥暟锛岀敤浜庡鐞 SIGHUP 淇″彿锛屽苟璁剧疆鐩稿簲鐨勬爣蹇 static void acSighupHandler(SIGNAL_ARGS) { - int save_errno = errno; + int save_errno = errno; // 淇濆瓨褰撳墠 errno 鐨勫硷紝浠ヤ究鍚庣画鎭㈠ - t_thrd.alarm_cxt.gotSighup = true; + t_thrd.alarm_cxt.gotSighup = true; // 灏嗙嚎绋嬩笂涓嬫枃涓殑 gotSighup 鏍囧織璁剧疆涓 true锛岃〃绀烘敹鍒颁簡 SIGHUP 淇″彿 - SetLatch(&t_thrd.alarm_cxt.AlarmCheckerLatch); + SetLatch(&t_thrd.alarm_cxt.AlarmCheckerLatch); // 浣跨敤 SetLatch 鍑芥暟瑙﹀彂绾跨▼鐨勭鏈 Latch锛屼互渚垮敜閱掔嚎绋嬪苟澶勭悊淇″彿 - errno = save_errno; + errno = save_errno;// 鎭㈠涔嬪墠淇濆瓨鐨 errno 鍊硷紝纭繚涓嶅奖鍝嶅叾浠栦唬鐮佸 errno 鐨勬搷浣 } /* @@ -220,84 +253,96 @@ static void acSighupHandler(SIGNAL_ARGS) * Description : * Notes : */ +// 淇″彿澶勭悊鍑芥暟锛岀敤浜庡鐞 SIGTERM 鎴 SIGINT 淇″彿锛屽苟璁剧疆鐩稿簲鐨勬爣蹇 static void acSigquitHandler(SIGNAL_ARGS) { - int save_errno = errno; + int save_errno = errno;// 淇濆瓨褰撳墠 errno 鐨勫硷紝浠ヤ究鍚庣画鎭㈠ - t_thrd.alarm_cxt.gotSigdie = true; + t_thrd.alarm_cxt.gotSigdie = true;// 灏嗙嚎绋嬩笂涓嬫枃涓殑 gotSigdie 鏍囧織璁剧疆涓 true锛岃〃绀烘敹鍒颁簡 SIGTERM 鎴 SIGINT 淇″彿 - SetLatch(&t_thrd.alarm_cxt.AlarmCheckerLatch); + SetLatch(&t_thrd.alarm_cxt.AlarmCheckerLatch);// 浣跨敤 SetLatch 鍑芥暟瑙﹀彂绾跨▼鐨勭鏈 Latch锛屼互渚垮敜閱掔嚎绋嬪苟澶勭悊淇″彿 - errno = save_errno; + errno = save_errno;// 鎭㈠涔嬪墠淇濆瓨鐨 errno 鍊硷紝纭繚涓嶅奖鍝嶅叾浠栦唬鐮佸 errno 鐨勬搷浣 } +// 鐢ㄤ簬妫鏌ョ洰褰曟槸鍚﹀瓨鍦紝浠ュ強鐩綍鏄惁鍏锋湁鍚堥傜殑灞炴у拰鏉冮檺锛屽嵆妫鏌ョ洰褰曠殑鏈夋晥鎬с bool isDirExist(const char* dir) { + // 鍒涘缓涓涓敤浜庡瓨鏀炬枃浠/鐩綍灞炴т俊鎭殑缁撴瀯浣 struct stat stat_buf; - + // 浣跨敤 stat 鍑芥暟鑾峰彇鐩綍鐨勭姸鎬佷俊鎭紝濡傛灉杩斿洖鍊间笉绛変簬0锛屽垯琛ㄧず鐩綍涓嶅瓨鍦 if (stat(dir, &stat_buf) != 0) return false; - + // 浣跨敤 S_ISDIR 瀹忓垽鏂洰褰曠殑鏂囦欢绫诲瀷鏄惁涓虹洰褰曪紝濡傛灉涓嶆槸鐩綍绫诲瀷锛屽垯杩斿洖 false if (!S_ISDIR(stat_buf.st_mode)) return false; + // 濡傛灉涓嶅湪 Windows 骞冲彴涓斾笉鍦 Cygwin 鐜涓 #if !defined(WIN32) && !defined(__CYGWIN__) - + // 妫鏌ョ洰褰曠殑鎷ユ湁鑰呮槸鍚︿负褰撳墠鐢ㄦ埛锛屽鏋滀笉鏄垯杩斿洖 false if (stat_buf.st_uid != geteuid()) return false; - + // 妫鏌ョ洰褰曠殑鏉冮檺鏄惁涓虹敤鎴峰彲璇汇佸啓鍜屾墽琛屾潈闄愶紝濡傛灉涓嶆槸鍒欒繑鍥 false if ((stat_buf.st_mode & S_IRWXU) != S_IRWXU) return false; #endif - + // 濡傛灉浠ヤ笂鏉′欢閮芥弧瓒筹紝鍒欒繑鍥 true锛岃〃绀虹洰褰曞瓨鍦ㄤ笖绗﹀悎瑕佹眰 return true; } AlarmCheckResult DataOrRedoDirNotExistChecker(Alarm* alarm, AlarmAdditionalParam* additionalParam) { + // 妫鏌 data 鐩綍鍜 pg_xlog 鐩綍鏄惁瀛樺湪 if (isDirExist(t_thrd.proc_cxt.DataDir) && isDirExist("pg_xlog")) { // fill the alarm message - WriteAlarmAdditionalInfo(additionalParam, - g_instance.attr.attr_common.PGXCNodeName, + // 濉啓鎶ヨ淇℃伅 + WriteAlarmAdditionalInfo(additionalParam, //additionalParam锛氭姤璀︾殑闄勫姞鍙傛暟锛岀敤浜庡瓨鍌ㄦ姤璀︿俊鎭殑璇︾粏鍐呭 + g_instance.attr.attr_common.PGXCNodeName, // 鏁版嵁搴撳疄渚嬬殑鍚嶇О锛岀敤浜庢爣璇嗘姤璀﹀彂鐢熺殑瀹炰緥 "", "", - alarm, - ALM_AT_Resume, - g_instance.attr.attr_common.PGXCNodeName); - return ALM_ACR_Normal; + alarm, //鎶ヨ鐨勭被鍨嬫垨鎻忚堪锛岀敤浜庢爣璇嗗叿浣撶殑鎶ヨ鍘熷洜鎴栭棶棰 + ALM_AT_Resume,// 璁剧疆鎶ヨ鍔ㄤ綔涓衡滄仮澶嶁濓紝琛ㄧず鎶ヨ鏉′欢宸茬粡瑙e喅 + g_instance.attr.attr_common.PGXCNodeName); //鏁版嵁搴撳疄渚嬬殑鍚嶇О锛岀敤浜庡~鍐欐姤璀︿俊鎭 + return ALM_ACR_Normal;// 杩斿洖鎶ヨ妫鏌ョ粨鏋滀负鈥滄甯糕 } else { // fill the alarm message + // 濉啓鎶ヨ淇℃伅 WriteAlarmAdditionalInfo(additionalParam, g_instance.attr.attr_common.PGXCNodeName, "", "", alarm, - ALM_AT_Fault, + ALM_AT_Fault, // 璁剧疆鎶ヨ鍔ㄤ綔涓衡滄晠闅溾 g_instance.attr.attr_common.PGXCNodeName); - return ALM_ACR_Abnormal; + return ALM_ACR_Abnormal;// 杩斿洖鎶ヨ妫鏌ョ粨鏋滀负鈥滃紓甯糕 } } /* implementation of alarm module. */ +// 鐢ㄤ簬閲婃斁鍔ㄦ佸垎閰嶇殑鍐呭瓨锛岄伩鍏嶅唴瀛樻硠婕 void AlarmFree(void* pointer) { - if (pointer != NULL) - pfree(pointer); + if (pointer != NULL)// 妫鏌ユ寚閽堟槸鍚﹂潪绌 + pfree(pointer); // 浣跨敤 pfree 鍑芥暟閲婃斁鍐呭瓨 } +// 鐢ㄤ簬鍒嗛厤鎸囧畾澶у皬鐨勫唴瀛樺潡 void* AlarmAlloc(size_t size) { - return palloc(size); + return palloc(size);// 璋冪敤 palloc 鍑芥暟鍒嗛厤鎸囧畾澶у皬鐨勫唴瀛樺潡锛屽苟杩斿洖鍒嗛厤鐨勫唴瀛樺潡鎸囬拡 } +// 鏃ュ織杈撳嚭鍑芥暟锛岀敤浜庡湪涓嶅悓绾у埆杈撳嚭鎶ヨ淇℃伅 +// 杈撳叆鍙傛暟鍒嗗埆涓烘姤璀︾骇鍒佸墠缂鍜屾姤璀︽枃鏈紝鏍规嵁闇瑕佽緭鍑轰笉鍚岀骇鍒殑鎶ヨ淇℃伅浠ヨ繘琛岀洃鎺у拰璋冭瘯銆 void AlarmLogImplementation(int level, const char* prefix, const char* logtext) { + // 浣跨敤 switch 璇彞鏍规嵁涓嶅悓鐨勭骇鍒夋嫨涓嶅悓鐨勬棩蹇楄緭鍑哄嚱鏁板苟杈撳嚭淇℃伅 switch (level) { - case ALM_DEBUG: + case ALM_DEBUG:// 鍦 DEBUG3 绾у埆杈撳嚭鎶ヨ淇℃伅锛屼娇鐢 errmsg 鍑芥暟杈撳嚭甯︽湁鍓嶇紑鍜屾枃鏈殑鏃ュ織 ereport(DEBUG3, (errmsg("%s%s", prefix, logtext))); break; - case ALM_LOG: + case ALM_LOG:// 鍦 LOG 绾у埆杈撳嚭鎶ヨ淇℃伅锛屼娇鐢 errmsg 鍑芥暟杈撳嚭甯︽湁鍓嶇紑鍜屾枃鏈殑鏃ュ織 ereport(LOG, (errmsg("%s%s", prefix, logtext))); break; default: diff --git a/src/gausskernel/process/postmaster/autovacuum.cpp b/src/gausskernel/process/postmaster/autovacuum.cpp index a1764d695..6629ed118 100755 --- a/src/gausskernel/process/postmaster/autovacuum.cpp +++ b/src/gausskernel/process/postmaster/autovacuum.cpp @@ -127,60 +127,69 @@ #include "storage/lmgr.h" /* struct to keep tuples stat that fetchs from DataNode */ +// 瀹氫箟浜嗙粨鏋勪綋锛岀敤浜庡瓨鍌ㄤ粠 DataNode 鑾峰彇鐨勫厓缁勭粺璁′俊鎭 typedef struct avw_info { - PgStat_StatTabKey tabkey; - int64 n_dead_tuples; - int64 n_live_tuples; - int64 changes_since_analyze; + PgStat_StatTabKey tabkey;// 琛ㄧ殑缁熻淇℃伅閿紝鍖呮嫭琛ㄧ殑鏍囪瘑绗﹀拰缁熻鏍囧織 + int64 n_dead_tuples;// 琛ㄤ腑宸叉爣璁颁负姝讳骸锛堝緟娓呯悊锛夌殑鍏冪粍鏁伴噺 + int64 n_live_tuples;// 琛ㄤ腑褰撳墠瀛樻椿鐨勫厓缁勬暟閲忥紝鍗冲皻鏈娓呯悊鐨勫厓缁勬暟閲 + int64 changes_since_analyze;// 鑷笂娆″垎鏋愪互鏉ュ彂鐢熺殑琛ㄤ腑鏇存敼锛堟彃鍏ャ佹洿鏂般佸垹闄わ級鐨勬暟閲 } avw_info; /* struct to keep track of databases in worker */ + // 鐢ㄤ簬鍦ㄥ伐浣滆呬腑璺熻釜鏁版嵁搴撶殑缁撴瀯浣 typedef struct avw_dbase { - Oid adw_datid; - char* adw_name; - TransactionId adw_frozenxid; - MultiXactId adw_frozenmulti; - PgStat_StatDBEntry* adw_entry; + Oid adw_datid;// 鏁版嵁搴撶殑 OID锛堝璞℃爣璇嗙锛 + char* adw_name; // 鏁版嵁搴撶殑鍚嶇О + TransactionId adw_frozenxid; // 鏁版嵁搴撶殑鍐荤粨浜嬪姟 ID + MultiXactId adw_frozenmulti;// 鏁版嵁搴撶殑鍐荤粨澶氫簨鍔 ID + PgStat_StatDBEntry* adw_entry;// 鏁版嵁搴撶殑缁熻淇℃伅鏉$洰鎸囬拡 } avw_dbase; -NON_EXEC_STATIC void AutoVacWorkerMain(); -NON_EXEC_STATIC void AutoVacLauncherMain(); +NON_EXEC_STATIC void AutoVacWorkerMain();// 鑷姩娓呯悊宸ヤ綔鑰呯殑涓昏鍏ュ彛鐐 +NON_EXEC_STATIC void AutoVacLauncherMain();// 鑷姩娓呯悊鍚姩鍣ㄧ殑涓昏鍏ュ彛鐐 -static Oid do_start_worker(void); +static Oid do_start_worker(void);// 鍚姩鑷姩娓呯悊宸ヤ綔鑰 +// 鏍规嵁鏄惁鍙互鍚姩宸ヤ綔鑰呫佹槸鍚﹂掑綊浠ュ強鏃堕棿闂撮殧绛夊洜绱犳潵鍐冲畾鍚姩鍣ㄧ殑浼戠湢鏃堕棿 static void launcher_determine_sleep(bool canlaunch, bool recursing, struct timeval* nap); -static void launch_worker(TimestampTz now); -static List* get_database_list(void); -static void rebuild_database_list(Oid newdb); -static int db_comparator(const void* a, const void* b); -static void autovac_balance_cost(void); +static void launch_worker(TimestampTz now);// 鍚姩鑷姩娓呯悊宸ヤ綔鑰咃紝鐢ㄤ簬鎵ц琛ㄧ殑娓呯悊浠诲姟 +static List* get_database_list(void);// 鑾峰彇鏁版嵁搴撳垪琛 +static void rebuild_database_list(Oid newdb);// 閲嶅缓鏁版嵁搴撳垪琛紝鐢ㄤ簬纭畾鍝簺鏁版嵁搴撻渶瑕佽繘琛岃嚜鍔ㄦ竻鐞 +static int db_comparator(const void* a, const void* b);// 鏁版嵁搴撴瘮杈冨櫒鍑芥暟锛岀敤浜庡鏁版嵁搴撳垪琛ㄨ繘琛屾帓搴 +static void autovac_balance_cost(void);// 鏍规嵁涓嶅悓宸ヤ綔鑰呬箣闂寸殑鎴愭湰骞宠 锛岃皟鏁磋嚜鍔ㄦ竻鐞嗙殑寤惰繜 -static void do_autovacuum(void); -static void FreeWorkerInfo(int code, Datum arg); +static void do_autovacuum(void);// 鎵ц瀹為檯鐨勮嚜鍔ㄦ竻鐞嗘搷浣 +static void FreeWorkerInfo(int code, Datum arg);// 閲婃斁宸ヤ綔鑰呬俊鎭 /* add parameter toast_table_map by data partition. */ +// 閲嶆柊妫鏌ヨ嚜鍔ㄦ竻鐞嗗拰鍒嗘瀽鐨勮〃锛岀‘瀹氭槸鍚﹂渶瑕佹墽琛屾竻鐞嗘搷浣 static autovac_table* table_recheck_autovac( vacuum_object* vacObj, HTAB* table_toast_map, HTAB* toast_table_map, TupleDesc pg_class_desc); static void relation_needs_vacanalyze(Oid relid, AutoVacOpts* relopts, Form_pg_class classForm, HeapTuple tuple, PgStat_StatTabEntry* tabentry, bool allowAnalyze, bool allowVacuum, bool is_recheck, bool* dovacuum, bool* doanalyze, bool* need_freeze); - +// 鎵ц瀹為檯鐨勮嚜鍔ㄦ竻鐞嗗拰鍒嗘瀽鎿嶄綔 static void autovacuum_do_vac_analyze(autovac_table* tab, BufferAccessStrategy bstrategy); +// 鎵ц鏈湴锛堥潪骞惰锛夌殑鑷姩娓呯悊鍜屽垎鏋愭搷浣 static void autovacuum_local_vac_analyze(autovac_table* tab, BufferAccessStrategy bstrategy); /* add parameter statFlag by data partition. */ +// 鑾峰彇涓庤〃鐩稿叧鐨勭粺璁′俊鎭潯鐩 static PgStat_StatTabEntry* get_pgstat_tabentry_relid( Oid relid, bool isshared, uint32 statFlag, PgStat_StatDBEntry* shared, PgStat_StatDBEntry* dbentry); -static void autovac_report_activity(autovac_table* tab); -static void avl_sighup_handler(SIGNAL_ARGS); -static void avl_sigusr2_handler(SIGNAL_ARGS); -static void avl_sigterm_handler(SIGNAL_ARGS); -static void autovac_refresh_stats(void); +static void autovac_report_activity(autovac_table* tab);// 鎶ュ憡鑷姩娓呯悊鐨勬椿鍔ㄧ姸鎬 +static void avl_sighup_handler(SIGNAL_ARGS);// 淇″彿澶勭悊鍑芥暟锛岀敤浜庡鐞 SIGHUP 淇″彿 +static void avl_sigusr2_handler(SIGNAL_ARGS);// 淇″彿澶勭悊鍑芥暟锛岀敤浜庡鐞 SIGUSR2 淇″彿 +static void avl_sigterm_handler(SIGNAL_ARGS);// 淇″彿澶勭悊鍑芥暟锛岀敤浜庡鐞 SIGTERM 淇″彿 +static void autovac_refresh_stats(void);// 鍒锋柊缁熻淇℃伅 +// 澶勭悊鍒嗗尯琛ㄧ殑鑷姩娓呯悊鍜屽垎鏋愰渶姹 static void partition_needs_vacanalyze(Oid partid, AutoVacOpts* relopts, Form_pg_partition partForm, HeapTuple partTuple, at_partitioned_table* ap_entry, PgStat_StatTabEntry* tabentry, bool is_recheck, bool* dovacuum, bool* doanalyze, bool* need_freeze); +// 閲嶆柊妫鏌ュ垎鍖鸿〃鐨勮嚜鍔ㄦ竻鐞嗗拰鍒嗘瀽闇姹 static autovac_table* partition_recheck_autovac( vacuum_object* vacObj, HTAB* table_relopt_map, HTAB* partitioned_tables_map, TupleDesc pg_class_desc); +// 鎵ц MPP 琛ㄧ殑娓呯悊鎿嶄綔 extern void DoVacuumMppTable(VacuumStmt* stmt, const char* queryString, bool isTopLevel, bool sentToRemote); /* * Called when the AutoVacuum is ending. @@ -200,13 +209,13 @@ static void autoVacQuitAndClean(int code, Datum arg) /******************************************************************** * AUTOVACUUM LAUNCHER CODE ********************************************************************/ -#ifdef EXEC_BACKEND +#ifdef EXEC_BACKEND// 濡傛灉鍦ㄦ墽琛屽悗绔唬鐮侊紙EXEC_BACKEND锛夋椂锛岄渶瑕佷粠澶栭儴璁剧疆 /* * We need this set from the outside, before InitProcess is called */ void AutovacuumLauncherIAm(void) { - t_thrd.role = AUTOVACUUM_LAUNCHER; + t_thrd.role = AUTOVACUUM_LAUNCHER;// 璁剧疆绾跨▼瑙掕壊锛岀敤浜庢爣璇嗗綋鍓嶇嚎绋嬫槸鑷姩娓呯悊鍚姩鍣 } #endif @@ -215,36 +224,37 @@ void AutovacuumLauncherIAm(void) */ NON_EXEC_STATIC void AutoVacLauncherMain() { - sigjmp_buf local_sigjmp_buf; + sigjmp_buf local_sigjmp_buf;// 鐢ㄤ簬寮傚父璺宠浆鐨勮烦杞紦鍐插尯 /* we are a postmaster subprocess now */ - IsUnderPostmaster = true; + IsUnderPostmaster = true;// 鍦ㄥ悗鍙拌繘绋嬩腑璁剧疆 t_thrd.role = AUTOVACUUM_LAUNCHER; /* reset t_thrd.proc_cxt.MyProcPid */ - t_thrd.proc_cxt.MyProcPid = gs_thread_self(); + t_thrd.proc_cxt.MyProcPid = gs_thread_self();// 鑾峰彇褰撳墠绾跨▼ID /* record Start Time for logging */ - t_thrd.proc_cxt.MyStartTime = time(NULL); + t_thrd.proc_cxt.MyStartTime = time(NULL);// 璁板綍杩涚▼鍚姩鏃堕棿 - t_thrd.proc_cxt.MyProgName = "AutoVacLauncher"; - u_sess->attr.attr_common.application_name = pstrdup("AutoVacLauncher"); + t_thrd.proc_cxt.MyProgName = "AutoVacLauncher";// 璁剧疆杩涚▼鍚嶇О + u_sess->attr.attr_common.application_name = pstrdup("AutoVacLauncher"); // 璁剧疆搴旂敤绋嬪簭鍚嶇О /* Identify myself via ps */ - init_ps_display("autovacuum launcher process", "", "", ""); + init_ps_display("autovacuum launcher process", "", "", "");// 璁剧疆杩涚▼鐘舵佷俊鎭 - ereport(LOG, (errmsg("autovacuum launcher started"))); + ereport(LOG, (errmsg("autovacuum launcher started")));// 杈撳嚭鏃ュ織锛岃〃绀鸿嚜鍔ㄦ竻鐞嗗惎鍔ㄥ櫒宸插惎鍔 - if (u_sess->attr.attr_security.PostAuthDelay) - pg_usleep(u_sess->attr.attr_security.PostAuthDelay * 1000000L); + if (u_sess->attr.attr_security.PostAuthDelay) // 濡傛灉鍦ㄩ厤缃枃浠朵腑璁剧疆浜 PostAuthDelay + pg_usleep(u_sess->attr.attr_security.PostAuthDelay * 1000000L); // 璁剧疆浼戠湢鏃堕棿 - SetProcessingMode(InitProcessing); + SetProcessingMode(InitProcessing);// 璁剧疆杩涚▼澶勭悊妯″紡涓哄垵濮嬪寲 /* * Set up signal handlers. We operate on databases much like a regular * backend, so we use the same signal handling. See equivalent code in * tcop/postgres.c. */ + // 璁剧疆淇″彿澶勭悊绋嬪簭 gspqsignal(SIGHUP, avl_sighup_handler); gspqsignal(SIGINT, StatementCancelHandler); gspqsignal(SIGTERM, avl_sigterm_handler); @@ -259,7 +269,7 @@ NON_EXEC_STATIC void AutoVacLauncherMain() gspqsignal(SIGCHLD, SIG_DFL); /* Early initialization */ - BaseInit(); + BaseInit();// 鍒濆鍖栧熀纭鐜 /* * Create a per-backend PGPROC struct in shared memory, except in the @@ -267,17 +277,17 @@ NON_EXEC_STATIC void AutoVacLauncherMain() * this before we can use LWLocks (and in the EXEC_BACKEND case we already * had to do some stuff with LWLocks). */ -#ifndef EXEC_BACKEND - InitProcess(); +#ifndef EXEC_BACKEND// 鍦 EXEC_BACKEND 鎯呭喌涓嬩笉闇瑕 InitProcess锛屽洜涓哄湪 SubPostmasterMain 涓凡缁忔墽琛岃繃浜 + InitProcess();// 鍒濆鍖栬繘绋 #endif + // 鍒濆鍖栬繛鎺ユ暟鎹簱鍜岀敤鎴疯韩浠 + t_thrd.proc_cxt.PostInit->SetDatabaseAndUser(NULL, InvalidOid, NULL);// 璁剧疆鏁版嵁搴撳拰鐢ㄦ埛韬唤 + t_thrd.proc_cxt.PostInit->InitAutoVacLauncher();// 鍒濆鍖栬嚜鍔ㄦ竻鐞嗗惎鍔ㄥ櫒 - t_thrd.proc_cxt.PostInit->SetDatabaseAndUser(NULL, InvalidOid, NULL); - t_thrd.proc_cxt.PostInit->InitAutoVacLauncher(); - - SetProcessingMode(NormalProcessing); + SetProcessingMode(NormalProcessing);// 璁剧疆杩涚▼澶勭悊妯″紡涓烘甯 /* If we exit, first try and clean connections and memory */ - on_proc_exit(autoVacQuitAndClean, 0); + on_proc_exit(autoVacQuitAndClean, 0);// 鍦ㄩ鍑烘椂璋冪敤娓呯悊鍑芥暟 /* * Create a memory context that we will do all our work in. We do this so @@ -285,94 +295,96 @@ NON_EXEC_STATIC void AutoVacLauncherMain() * possible memory leaks. */ t_thrd.autovacuum_cxt.AutovacMemCxt = AllocSetContextCreate(t_thrd.top_mem_cxt, "Autovacuum Launcher", - ALLOCSET_DEFAULT_MINSIZE, ALLOCSET_DEFAULT_INITSIZE, ALLOCSET_DEFAULT_MAXSIZE); - (void)MemoryContextSwitchTo(t_thrd.autovacuum_cxt.AutovacMemCxt); + ALLOCSET_DEFAULT_MINSIZE, ALLOCSET_DEFAULT_INITSIZE, ALLOCSET_DEFAULT_MAXSIZE);// 鍒涘缓鑷姩娓呯悊鍚姩鍣ㄥ唴瀛樹笂涓嬫枃 + (void)MemoryContextSwitchTo(t_thrd.autovacuum_cxt.AutovacMemCxt);// 鍒囨崲鍒拌嚜鍔ㄦ竻鐞嗗惎鍔ㄥ櫒涓婁笅鏂 /* * If an exception is encountered, processing resumes here. * * This code is a stripped down version of PostgresMain error recovery. */ - int curTryCounter; - int* oldTryCounter = NULL; + int curTryCounter;// 褰撳墠鐨 try 鍧楄鏁板櫒 + int* oldTryCounter = NULL;// 鎸囧悜鏃х殑 try 鍧楄鏁板櫒鐨勬寚閽堬紝鍒濆鍖栦负 NULL if (sigsetjmp(local_sigjmp_buf, 1) != 0) { - gstrace_tryblock_exit(true, oldTryCounter); + gstrace_tryblock_exit(true, oldTryCounter);// 閫鍑哄綋鍓嶇殑 try 鍧楋紝骞惰繘琛岀浉鍏虫竻鐞 /* since not using PG_TRY, must reset error stack by hand */ - t_thrd.log_cxt.error_context_stack = NULL; + t_thrd.log_cxt.error_context_stack = NULL;// 鎵嬪姩娓呯┖閿欒鍫嗘爤 - t_thrd.log_cxt.call_stack = NULL; + t_thrd.log_cxt.call_stack = NULL;// 鎵嬪姩娓呯┖璋冪敤鍫嗘爤 /* Prevents interrupts while cleaning up */ - HOLD_INTERRUPTS(); + HOLD_INTERRUPTS();// 闃绘涓柇锛岄槻姝㈡竻鐞嗚繃绋嬩腑琚腑鏂 /* Forget any pending QueryCancel request */ - t_thrd.int_cxt.QueryCancelPending = false; - disable_sig_alarm(true); + t_thrd.int_cxt.QueryCancelPending = false;// 娓呴櫎鎸傝捣鐨勫彇娑堣姹 + disable_sig_alarm(true);// 鍏抽棴瀹氭椂鍣ㄤ腑鏂紝浠ュ厤骞叉壈娓呯悊杩囩▼ t_thrd.int_cxt.QueryCancelPending = false; /* again in case timeout occurred */ /* Report the error to the server log */ - EmitErrorReport(); + EmitErrorReport();// 灏嗛敊璇俊鎭姤鍛婂埌鏈嶅姟鍣ㄦ棩蹇 /* Abort the current transaction in order to recover */ - AbortCurrentTransaction(); + AbortCurrentTransaction();// 涓褰撳墠浜嬪姟浠ヨ繘琛屾仮澶 /* release resource held by lsc */ - AtEOXact_SysDBCache(false); + AtEOXact_SysDBCache(false);// 閲婃斁鐢 lsc锛圠ocal Storage Cache锛夋寔鏈夌殑璧勬簮 /* * Now return to normal top-level context and clear ErrorContext for * next time. */ - (void)MemoryContextSwitchTo(t_thrd.autovacuum_cxt.AutovacMemCxt); - FlushErrorState(); + (void)MemoryContextSwitchTo(t_thrd.autovacuum_cxt.AutovacMemCxt);// 鍒囨崲鍒版甯哥殑椤剁骇鍐呭瓨涓婁笅鏂 + FlushErrorState(); // 娓呯┖閿欒鐘舵 /* Flush any leaked data in the top-level context */ - MemoryContextResetAndDeleteChildren(t_thrd.autovacuum_cxt.AutovacMemCxt); + MemoryContextResetAndDeleteChildren(t_thrd.autovacuum_cxt.AutovacMemCxt);// 娓呯┖椤剁骇涓婁笅鏂囦腑鐨勪换浣曟硠婕忔暟鎹 /* don't leave dangling pointers to freed memory */ - t_thrd.autovacuum_cxt.DatabaseListCxt = NULL; + t_thrd.autovacuum_cxt.DatabaseListCxt = NULL;// 娓呯┖鎸囧悜宸查噴鏀惧唴瀛樼殑鎸囬拡 t_thrd.autovacuum_cxt.DatabaseList = NULL; /* * Make sure pgstat also considers our stat data as gone. Note: we * mustn't use autovac_refresh_stats here. */ - pgstat_clear_snapshot(); + pgstat_clear_snapshot();// 娓呴櫎缁熻蹇収鏁版嵁锛岀‘淇濈粺璁℃暟鎹殑鍑嗙‘鎬 /* Now we can allow interrupts again */ - RESUME_INTERRUPTS(); + RESUME_INTERRUPTS();// 鎭㈠涓柇鐨勫厑璁 /* if in shutdown mode, no need for anything further; just go away */ if (t_thrd.autovacuum_cxt.got_SIGTERM) - goto shutdown; + goto shutdown;// 濡傛灉澶勪簬鍏抽棴妯″紡锛屼笉闇瑕佽繘琛屽叾浠栨搷浣滐紝鐩存帴閫鍑 /* * Sleep at least 1 second after any error. We don't want to be * filling the error logs as fast as we can. */ - pg_usleep(1000000L); + pg_usleep(1000000L); // 鍦ㄩ敊璇悗鑷冲皯鐫$湢1绉掞紝浠ュ厤杩囧揩濉厖閿欒鏃ュ織 } - oldTryCounter = gstrace_tryblock_entry(&curTryCounter); + oldTryCounter = gstrace_tryblock_entry(&curTryCounter); // 杩涘叆涓涓柊鐨 try 鍧楋紝杩斿洖鏃х殑 try 鍧楄鏁板櫒 /* We can now handle ereport(ERROR) */ - t_thrd.log_cxt.PG_exception_stack = &local_sigjmp_buf; + t_thrd.log_cxt.PG_exception_stack = &local_sigjmp_buf; // 璁剧疆閿欒澶勭悊鏍堬紝鍙互澶勭悊 ereport(ERROR) /* must unblock signals before calling rebuild_database_list */ - gs_signal_setmask(&t_thrd.libpq_cxt.UnBlockSig, NULL); - gs_signal_unblock_sigusr2(); + gs_signal_setmask(&t_thrd.libpq_cxt.UnBlockSig, NULL);// 鍦ㄨ皟鐢 rebuild_database_list 涔嬪墠锛岃В闄や俊鍙峰睆钄 + gs_signal_unblock_sigusr2();// 瑙i櫎瀵 SIGUSR2 淇″彿鐨勫睆钄 /* * Force zero_damaged_pages OFF in the autovac process, even if it is set * in postgresql.conf. We don't really want such a dangerous option being * applied non-interactively. */ + // 寮哄埗灏 zero_damaged_pages 璁剧疆涓 "false"锛屼互閬垮厤闈炰氦浜掑紡搴旂敤 SetConfigOption("zero_damaged_pages", "false", PGC_SUSET, PGC_S_OVERRIDE); /* * Force statement_timeout to zero to avoid a timeout setting from * preventing regular maintenance from being executed. */ + // 寮哄埗灏 statement_timeout 璁剧疆涓 0锛屼互閬垮厤闃绘甯歌缁存姢鐨勬墽琛 SetConfigOption("statement_timeout", "0", PGC_SUSET, PGC_S_OVERRIDE); /* @@ -380,18 +392,20 @@ NON_EXEC_STATIC void AutoVacLauncherMain() * to pay the overhead of serializable mode, nor add any risk of causing * deadlocks or delaying other transactions. */ + + // 寮哄埗灏 default_transaction_isolation 璁剧疆涓 "read committed" SetConfigOption("default_transaction_isolation", "read committed", PGC_SUSET, PGC_S_OVERRIDE); /* * In emergency mode, just start a worker (unless shutdown was requested) * and go away. */ - if (!AutoVacuumingActive()) { - if (!t_thrd.autovacuum_cxt.got_SIGTERM) - do_start_worker(); + if (!AutoVacuumingActive()) { // 濡傛灉涓嶅浜庤嚜鍔ㄦ竻鐞嗘ā寮 + if (!t_thrd.autovacuum_cxt.got_SIGTERM) // 濡傛灉娌℃湁鏀跺埌鍏抽棴璇锋眰 + do_start_worker();// 鍚姩涓涓柊鐨勫伐浣滆繘绋 proc_exit(0); /* done */ } - + // 璁剧疆褰撳墠鑷姩娓呯悊杩涚▼鐨勮繘绋嬪彿鍒板叡浜唴瀛樹腑 t_thrd.autovacuum_cxt.AutoVacuumShmem->av_launcherpid = t_thrd.proc_cxt.MyProcPid; /* @@ -401,15 +415,15 @@ NON_EXEC_STATIC void AutoVacLauncherMain() * correct because the only operation is to add autovacuum_naptime to the * entry, and time always increases). */ - rebuild_database_list(InvalidOid); + rebuild_database_list(InvalidOid); // 鍒涘缓鍒濆鐨勬暟鎹簱鍒楄〃锛屾寜鐓 next_time 鐨勯掑噺椤哄簭鎺掑簭 /* loop until shutdown request */ - while (!t_thrd.autovacuum_cxt.got_SIGTERM) { - struct timeval nap; - TimestampTz current_time = 0; - bool can_launch = false; - Dlelem* elem = NULL; - int rc; + while (!t_thrd.autovacuum_cxt.got_SIGTERM) {// 鍦ㄦ病鏈夋敹鍒板叧闂姹傛椂寰幆鎵ц + struct timeval nap; // 鐢ㄤ簬璁$畻涓嬫寰幆绛夊緟鐨勬椂闂撮棿闅 + TimestampTz current_time = 0;// 鏃堕棿鎴筹紝鐢ㄤ簬璁板綍褰撳墠鐨勬椂闂 + bool can_launch = false;// 琛ㄧず鏄惁鍙互鍚姩鏂扮殑鑷姩娓呯悊宸ヤ綔杩涚▼ + Dlelem* elem = NULL;// 鍙屽悜閾捐〃鍏冪礌鎸囬拡锛岀敤浜庨亶鍘嗘暟鎹簱鍒楄〃 + int rc;// 鐢ㄤ簬瀛樺偍WaitLatch鍑芥暟鐨勮繑鍥炲 /* * This loop is a bit different from the normal use of WaitLatch, @@ -417,63 +431,66 @@ NON_EXEC_STATIC void AutoVacLauncherMain() * process. So it's WaitLatch, then ResetLatch, then check for * wakening conditions. */ - launcher_determine_sleep((t_thrd.autovacuum_cxt.AutoVacuumShmem->av_freeWorkers != NULL), false, &nap); + + launcher_determine_sleep((t_thrd.autovacuum_cxt.AutoVacuumShmem->av_freeWorkers != NULL), false, &nap);// 纭畾浼戠湢鏃堕棿鍜屾潯浠 /* * Wait until naptime expires or we get some type of signal (all the * signal handlers will wake us by calling SetLatch). */ - rc = WaitLatch(&t_thrd.proc->procLatch, WL_LATCH_SET | WL_TIMEOUT | WL_POSTMASTER_DEATH, - (nap.tv_sec * 1000L) + (nap.tv_usec / 1000L)); + rc = WaitLatch(&t_thrd.proc->procLatch, // 绛夊緟鐨勬爣蹇楋紙latch锛 + WL_LATCH_SET | WL_TIMEOUT | WL_POSTMASTER_DEATH,// 绛夊緟鐨勬潯浠舵爣蹇 + (nap.tv_sec * 1000L) + (nap.tv_usec / 1000L));// 绛夊緟鐨勬椂闂 - ResetLatch(&t_thrd.proc->procLatch); + ResetLatch(&t_thrd.proc->procLatch);// 閲嶇疆鐢ㄤ簬淇″彿澶勭悊鐨 latch /* Process sinval catchup interrupts that happened while sleeping */ - ProcessCatchupInterrupt(); + ProcessCatchupInterrupt(); // 澶勭悊鍦ㄧ潯鐪犳湡闂村彂鐢熺殑 sinval 涓柇 /* * Emergency bailout if postmaster has died. This is to avoid the * necessity for manual cleanup of all postmaster children. */ - if (((unsigned int)rc) & WL_POSTMASTER_DEATH) - proc_exit(1); + if (((unsigned int)rc) & WL_POSTMASTER_DEATH)// 鏀跺埌浜 postmaster 缁堟淇″彿 + proc_exit(1);// 绱фラ鍑猴紝閬垮厤闇瑕佹墜鍔ㄦ竻鐞嗘墍鏈 postmaster 瀛愯繘绋 /* the normal shutdown case */ - if (t_thrd.autovacuum_cxt.got_SIGTERM) - break; + if (t_thrd.autovacuum_cxt.got_SIGTERM)// 鏀跺埌浜嗘甯稿叧闂俊鍙 + break;// 閫鍑哄惊鐜紝缁撴潫鑷姩娓呯悊杩涚▼ - if (t_thrd.autovacuum_cxt.got_SIGHUP) { - t_thrd.autovacuum_cxt.got_SIGHUP = false; - ProcessConfigFile(PGC_SIGHUP); + if (t_thrd.autovacuum_cxt.got_SIGHUP) { // 鏀跺埌浜 SIGHUP 淇″彿锛屽嵆閲嶆柊鍔犺浇閰嶇疆鏂囦欢鐨勪俊鍙 + t_thrd.autovacuum_cxt.got_SIGHUP = false; // 鏍囪涓哄凡澶勭悊 + ProcessConfigFile(PGC_SIGHUP); // 閲嶆柊鍔犺浇閰嶇疆鏂囦欢 /* shutdown requested in config file? */ - if (!AutoVacuumingActive()) + if (!AutoVacuumingActive())// 濡傛灉鍦ㄩ厤缃枃浠朵腑璇锋眰浜嗗叧闂 break; /* rebalance in case the default cost parameters changed */ - LWLockAcquire(AutovacuumLock, LW_EXCLUSIVE); - autovac_balance_cost(); - LWLockRelease(AutovacuumLock); + LWLockAcquire(AutovacuumLock, LW_EXCLUSIVE); // 鑾峰彇鑷姩娓呯悊閿侊紝浠ヨ繘琛屾帓琛℃搷浣 + autovac_balance_cost(); // 鎵ц鎺掕 鎿嶄綔浠ラ噸鏂板钩琛¢粯璁ゆ垚鏈弬鏁 + LWLockRelease(AutovacuumLock);// 閲婃斁鑷姩娓呯悊閿 /* rebuild the list in case the naptime changed */ - rebuild_database_list(InvalidOid); + rebuild_database_list(InvalidOid); // 閲嶅缓鏁版嵁搴撳垪琛紝浠ラ槻 naptime 鍙戠敓鍙樺寲 } /* * a worker finished, or postmaster signalled failure to start a * worker */ - if (t_thrd.autovacuum_cxt.got_SIGUSR2) { - t_thrd.autovacuum_cxt.got_SIGUSR2 = false; + if (t_thrd.autovacuum_cxt.got_SIGUSR2) {// 鏀跺埌浜 SIGUSR2 淇″彿 + t_thrd.autovacuum_cxt.got_SIGUSR2 = false; // 鏍囪涓哄凡澶勭悊淇″彿 /* rebalance cost limits, if needed */ + // 妫鏌ヨ嚜鍔ㄦ竻鐞嗗叡浜唴瀛樹腑鐨 av_signal 鏁扮粍锛岀湅鏄惁鏀跺埌浜嗛渶瑕侀噸鏂板钩琛℃竻鐞嗘垚鏈檺鍒剁殑淇″彿 if (t_thrd.autovacuum_cxt.AutoVacuumShmem->av_signal[AutoVacRebalance]) { - LWLockAcquire(AutovacuumLock, LW_EXCLUSIVE); - t_thrd.autovacuum_cxt.AutoVacuumShmem->av_signal[AutoVacRebalance] = false; - autovac_balance_cost(); - LWLockRelease(AutovacuumLock); + LWLockAcquire(AutovacuumLock, LW_EXCLUSIVE);// 鑾峰彇鑷姩娓呯悊閿侊紝浠ヨ繘琛屾帓琛℃搷浣 + t_thrd.autovacuum_cxt.AutoVacuumShmem->av_signal[AutoVacRebalance] = false;// 鏍囪涓哄凡澶勭悊鎺掕 淇″彿 + autovac_balance_cost();// 鎵ц鎺掕 鎿嶄綔浠ラ噸鏂板钩琛℃竻鐞嗘垚鏈檺鍒 + LWLockRelease(AutovacuumLock); // 閲婃斁鑷姩娓呯悊閿 } - + // 妫鏌ユ槸鍚﹀湪灏濊瘯鍚姩涓涓柊鐨勫伐浣滆繘绋嬫椂澶辫触 if (t_thrd.autovacuum_cxt.AutoVacuumShmem->av_signal[AutoVacForkFailed]) { /* * If the postmaster failed to start a new worker, we sleep @@ -485,9 +502,9 @@ NON_EXEC_STATIC void AutoVacLauncherMain() * I don't think it makes much sense, because a future start * of a worker will continue to fail in the same way. */ - t_thrd.autovacuum_cxt.AutoVacuumShmem->av_signal[AutoVacForkFailed] = false; - pg_usleep(1000000L); /* 1s */ - SendPostmasterSignal(PMSIGNAL_START_AUTOVAC_WORKER); + t_thrd.autovacuum_cxt.AutoVacuumShmem->av_signal[AutoVacForkFailed] = false;// 娓呴櫎鏍囧織浣嶏紝閬垮厤閲嶅澶勭悊 + pg_usleep(1000000L); /* 1s */ // 浼戠湢 1 绉掞紝绛夊緟涓娈垫椂闂达紝浠ヤ究閲嶆柊灏濊瘯 + SendPostmasterSignal(PMSIGNAL_START_AUTOVAC_WORKER); // 鍙戦佷俊鍙风粰涓绘帶杩涚▼浠ュ惎鍔ㄦ柊鐨勫伐浣滆繘绋 continue; } } @@ -498,14 +515,14 @@ NON_EXEC_STATIC void AutoVacLauncherMain() * launcher slot available. Second, we need to make sure that no * other worker failed while starting up. */ - current_time = GetCurrentTimestamp(); - LWLockAcquire(AutovacuumLock, LW_SHARED); - + current_time = GetCurrentTimestamp();// 鑾峰彇褰撳墠鏃堕棿鎴 + LWLockAcquire(AutovacuumLock, LW_SHARED);// 鑾峰彇鑷姩娓呯悊閿佺殑鍏变韩妯″紡閿侊紝鐢ㄤ簬鍚屾鑷姩娓呯悊杩涚▼涔嬮棿鐨勮闂 + // 妫鏌ユ槸鍚﹀瓨鍦ㄥ彲鐢ㄧ殑 launcher slot锛堝惎鍔ㄥ櫒妲戒綅锛夛紝鐢ㄤ簬鍚姩宸ヤ綔杩涚▼ can_launch = (t_thrd.autovacuum_cxt.AutoVacuumShmem->av_freeWorkers != NULL); - if (t_thrd.autovacuum_cxt.AutoVacuumShmem->av_startingWorker != NULL) { + if (t_thrd.autovacuum_cxt.AutoVacuumShmem->av_startingWorker != NULL) {// 鍒ゆ柇鏄惁鏈夋鍦ㄥ惎鍔ㄧ殑宸ヤ綔杩涚▼ int waittime; - WorkerInfo worker = t_thrd.autovacuum_cxt.AutoVacuumShmem->av_startingWorker; + WorkerInfo worker = t_thrd.autovacuum_cxt.AutoVacuumShmem->av_startingWorker;// 淇濆瓨姝e湪鍚姩鐨勫伐浣滆繘绋嬩俊鎭 /* * We can't launch another worker when another one is still @@ -522,10 +539,12 @@ NON_EXEC_STATIC void AutoVacLauncherMain() * before the worker removes the WorkerInfo from the * startingWorker pointer. */ + // 璁$畻绛夊緟鏃堕棿 waittime锛岀‘淇濈瓑寰呮椂闂翠笉瓒呰繃 60 绉 waittime = Min(u_sess->attr.attr_storage.autovacuum_naptime, 60) * 1000; + // 濡傛灉鍚姩鏃堕棿涓庡綋鍓嶆椂闂村樊瓒呰繃绛夊緟鏃堕棿锛岃〃鏄庡伐浣滆繘绋嬪彲鑳藉湪鍚姩鏃跺け璐ワ紝鎴栬呭惎鍔ㄦ椂闂磋繃闀 if (TimestampDifferenceExceeds(worker->wi_launchtime, current_time, waittime)) { - LWLockRelease(AutovacuumLock); - LWLockAcquire(AutovacuumLock, LW_EXCLUSIVE); + LWLockRelease(AutovacuumLock); // 閲婃斁涔嬪墠鑾峰彇鐨勮嚜鍔ㄦ竻鐞嗛攣锛堝叡浜ā寮忥級 + LWLockAcquire(AutovacuumLock, LW_EXCLUSIVE); // 閲嶆柊浠ョ嫭鍗犳ā寮忚幏鍙栭攣锛屼互杩涜鐘舵佹洿鏂 /* * No other process can put a worker in starting mode, so if @@ -533,39 +552,40 @@ NON_EXEC_STATIC void AutoVacLauncherMain() * we assume it's the same one we saw above (so we don't * recheck the launch time). */ - if (t_thrd.autovacuum_cxt.AutoVacuumShmem->av_startingWorker != NULL) { - worker = t_thrd.autovacuum_cxt.AutoVacuumShmem->av_startingWorker; - worker->wi_dboid = InvalidOid; - worker->wi_tableoid = InvalidOid; - worker->wi_parentoid = InvalidOid; - worker->wi_sharedrel = false; - worker->wi_proc = NULL; - worker->wi_launchtime = 0; - worker->wi_links.next = (SHM_QUEUE*)t_thrd.autovacuum_cxt.AutoVacuumShmem->av_freeWorkers; - t_thrd.autovacuum_cxt.AutoVacuumShmem->av_freeWorkers = worker; - t_thrd.autovacuum_cxt.AutoVacuumShmem->av_startingWorker = NULL; - ereport(WARNING, (errmsg("worker took too long to start; canceled"))); + if (t_thrd.autovacuum_cxt.AutoVacuumShmem->av_startingWorker != NULL) {// 妫鏌ユ槸鍚︿粛鐒跺瓨鍦ㄦ鍦ㄥ惎鍔ㄧ殑宸ヤ綔杩涚▼ + worker = t_thrd.autovacuum_cxt.AutoVacuumShmem->av_startingWorker; // 鑾峰彇姝e湪鍚姩鐨勫伐浣滆繘绋嬩俊鎭 + // 閲嶇疆宸ヤ綔杩涚▼淇℃伅 + worker->wi_dboid = InvalidOid; // 閲嶇疆鏁版嵁搴 OID + worker->wi_tableoid = InvalidOid; // 閲嶇疆琛 OID + worker->wi_parentoid = InvalidOid; // 閲嶇疆鐖惰〃 OID + worker->wi_sharedrel = false; // 閲嶇疆鏄惁涓哄叡浜〃鏍囧織 + worker->wi_proc = NULL; // 閲嶇疆宸ヤ綔杩涚▼鐩稿叧鐨勮繘绋嬩俊鎭 + worker->wi_launchtime = 0; // 閲嶇疆宸ヤ綔杩涚▼鐨勫惎鍔ㄦ椂闂 + worker->wi_links.next = (SHM_QUEUE*)t_thrd.autovacuum_cxt.AutoVacuumShmem->av_freeWorkers; // 灏嗗伐浣滆繘绋嬫坊鍔犲埌鍙敤宸ヤ綔杩涚▼閾捐〃 + t_thrd.autovacuum_cxt.AutoVacuumShmem->av_freeWorkers = worker; // 鏇存柊鍙敤宸ヤ綔杩涚▼閾捐〃 + t_thrd.autovacuum_cxt.AutoVacuumShmem->av_startingWorker = NULL; // 灏嗘鍦ㄥ惎鍔ㄧ殑宸ヤ綔杩涚▼鎸囬拡缃负绌 + ereport(WARNING, (errmsg("worker took too long to start; canceled"))); //鍙戦佽鍛婃秷鎭紝璇存槑鐢变簬宸ヤ綔杩涚▼鍚姩鏃堕棿杩囬暱鑰岃鍙栨秷 } } else - can_launch = false; + can_launch = false; //姝e湪鍚姩鐨勫伐浣滆繘绋嬬殑鍚姩鏃堕棿鏈秴杩囩瓑寰呮椂闂达紝灏 can_launch 璁句负 false锛岃〃绀烘棤娉曞惎鍔ㄦ柊鐨勫伐浣滆繘绋 } - LWLockRelease(AutovacuumLock); /* either shared or exclusive */ + LWLockRelease(AutovacuumLock); /* either shared or exclusive */ //閲婃斁浜掓枼閿 /* if we can't do anything, just go back to sleep */ - if (!can_launch) + if (!can_launch) // 濡傛灉鏃犳硶鎵ц浠讳綍鎿嶄綔锛屽氨閲嶆柊杩涘叆浼戠湢鐘舵 continue; /* We're OK to start a new worker */ - elem = DLGetTail(t_thrd.autovacuum_cxt.DatabaseList); + elem = DLGetTail(t_thrd.autovacuum_cxt.DatabaseList); // 鑾峰彇鏁版嵁搴撳垪琛ㄧ殑鏈鍚庝竴涓厓绱 if (elem != NULL) { - avl_dbase* avdb = (avl_dbase*)DLE_VAL(elem); + avl_dbase* avdb = (avl_dbase*)DLE_VAL(elem); // 鑾峰彇鏁版嵁搴撲俊鎭 /* * launch a worker if next_worker is right now or it is in the * past */ if (TimestampDifferenceExceeds(avdb->adl_next_worker, current_time, 0)) - launch_worker(current_time); + launch_worker(current_time); // 鍚姩宸ヤ綔杩涚▼ } else { /* * Special case when the list is empty: start a worker right away. @@ -575,14 +595,14 @@ NON_EXEC_STATIC void AutoVacLauncherMain() * quickly (at most once every autovacuum_naptime when the list is * empty). */ - launch_worker(current_time); + launch_worker(current_time);// 褰撳垪琛ㄤ负绌烘椂锛岀珛鍗冲惎鍔ㄥ伐浣滆繘绋 } } /* Normal exit from the autovac launcher is here */ -shutdown: - ereport(LOG, (errmsg("autovacuum launcher shutting down"))); - t_thrd.autovacuum_cxt.AutoVacuumShmem->av_launcherpid = 0; +shutdown: // 姝e父浠庤嚜鍔ㄦ竻鐞嗚繘绋嬮鍑 + ereport(LOG, (errmsg("autovacuum launcher shutting down"))); // 璁板綍鏃ュ織锛岃〃绀鸿嚜鍔ㄦ竻鐞嗚繘绋嬫鍦ㄥ叧闂 + t_thrd.autovacuum_cxt.AutoVacuumShmem->av_launcherpid = 0; // 灏嗚嚜鍔ㄦ竻鐞嗚繘绋嬬殑杩涚▼ ID 缃负 0 proc_exit(0); /* done */ } @@ -604,24 +624,26 @@ static void launcher_determine_sleep(bool canlaunch, bool recursing, struct time * in the past; if the first entry has too close a next_worker value, or a * time in the past, we will sleep a small nominal time. */ + // 濡傛灉涓嶈兘鍚姩鏂扮殑宸ヤ綔杩涚▼锛坈anlaunch = false锛夛紝鍒欏皢浼戠湢鏃堕棿璁剧疆涓洪厤缃弬鏁 autovacuum_naptime 鎵鎸囧畾鐨勬椂闂淬 if (!canlaunch) { nap->tv_sec = u_sess->attr.attr_storage.autovacuum_naptime; nap->tv_usec = 0; + // 濡傛灉鏁版嵁搴撳垪琛ㄤ笉涓虹┖锛屾壘鍒板垪琛ㄤ腑鏈鍚庝竴涓厓绱狅紙鏈鍚庝竴涓暟鎹簱锛夊苟鑾峰彇鍏朵笅娆″伐浣滄墽琛岀殑鏃堕棿銆 } else if ((elem = DLGetTail(t_thrd.autovacuum_cxt.DatabaseList)) != NULL) { - avl_dbase* avdb = (avl_dbase*)DLE_VAL(elem); - TimestampTz current_time = GetCurrentTimestamp(); - TimestampTz next_wakeup; - long secs; - int usecs; - - next_wakeup = avdb->adl_next_worker; - TimestampDifference(current_time, next_wakeup, &secs, &usecs); + avl_dbase* avdb = (avl_dbase*)DLE_VAL(elem); // 杞崲鍏冪礌鍊间负avl_dbase缁撴瀯浣撴寚閽 + TimestampTz current_time = GetCurrentTimestamp(); // 鑾峰彇褰撳墠鏃堕棿 + TimestampTz next_wakeup; // 涓嬩竴涓伐浣滆繘绋嬪簲璇ュ敜閱掔殑鏃堕棿 + long secs; // 鏃堕棿鐨勭鏁伴儴鍒 + int usecs; // 鏃堕棿鐨勫井绉掓暟閮ㄥ垎 + next_wakeup = avdb->adl_next_worker; // 鑾峰彇涓嬩竴涓伐浣滆繘绋嬪簲璇ュ敜閱掔殑鏃堕棿 + TimestampDifference(current_time, next_wakeup, &secs, &usecs); // 璁$畻褰撳墠鏃堕棿涓庡敜閱掓椂闂寸殑宸 + // 璁剧疆浼戠湢鏃堕棿涓哄樊鍊 nap->tv_sec = secs; nap->tv_usec = usecs; } else { /* list is empty, sleep for whole autovacuum_naptime seconds */ - nap->tv_sec = u_sess->attr.attr_storage.autovacuum_naptime; + nap->tv_sec = u_sess->attr.attr_storage.autovacuum_naptime; // 濡傛灉鏁版嵁搴撳垪琛ㄤ负绌猴紝浣跨敤autovacuum_naptime浣滀负浼戠湢鏃堕棿 nap->tv_usec = 0; } @@ -636,6 +658,7 @@ static void launcher_determine_sleep(bool canlaunch, bool recursing, struct time * in the future, but it seems best not to trust too much on that. */ if (nap->tv_sec == 0 && nap->tv_usec == 0 && !recursing) { + // 濡傛灉浼戠湢鏃堕棿涓洪浂涓斾笉鏄掑綊璋冪敤锛屽垯閲嶆柊鏋勫缓鏁版嵁搴撳垪琛ㄥ苟閲嶆柊璁$畻浼戠湢鏃堕棿 rebuild_database_list(InvalidOid); launcher_determine_sleep(canlaunch, true, nap); return; @@ -643,6 +666,7 @@ static void launcher_determine_sleep(bool canlaunch, bool recursing, struct time /* The smallest time we'll allow the launcher to sleep. */ if (nap->tv_sec <= 0 && nap->tv_usec <= MIN_AUTOVAC_SLEEPTIME * 1000) { + // 濡傛灉浼戠湢鏃堕棿灏忎簬绛変簬鏈灏忎紤鐪犳椂闂达紝璁剧疆浼戠湢鏃堕棿涓烘渶灏忎紤鐪犳椂闂寸殑寰鍊 nap->tv_sec = 0; nap->tv_usec = (__suseconds_t)(MIN_AUTOVAC_SLEEPTIME * 1000); } @@ -663,24 +687,25 @@ static void launcher_determine_sleep(bool canlaunch, bool recursing, struct time */ static void rebuild_database_list(Oid newdb) { - List* dblist = NIL; - ListCell* cell = NULL; - MemoryContext newcxt; - MemoryContext oldcxt; - MemoryContext tmpcxt; - HASHCTL hctl; - uint score; - uint nelems; - HTAB* dbhash = NULL; + List* dblist = NIL; // 瀛樺偍鏁版嵁搴撳垪琛ㄧ殑閾捐〃 + ListCell* cell = NULL; // 閾捐〃杩唬鍣 + MemoryContext newcxt; // 鍒涘缓鏂扮殑鍐呭瓨涓婁笅鏂囦互瀹圭撼鏂扮殑鏁版嵁搴撳垪琛 + MemoryContext oldcxt; // 淇濆瓨鏃х殑鍐呭瓨涓婁笅鏂 + MemoryContext tmpcxt; // 涓存椂鍐呭瓨涓婁笅鏂 + HASHCTL hctl; // 鍝堝笇琛ㄦ帶鍒剁粨鏋 + uint score; // 涓烘暟鎹簱鍒嗛厤鐨勫緱鍒 + uint nelems; // 鏁版嵁搴撴暟閲 + HTAB* dbhash = NULL; // 鍝堝笇琛ㄧ敤浜庡瓨鍌ㄦ暟鎹簱 /* use fresh stats */ autovac_refresh_stats(); + // 涓烘柊鐨勬暟鎹簱鍒楄〃鍜屼复鏃朵笂涓嬫枃鍒嗛厤鍐呭瓨 newcxt = AllocSetContextCreate(t_thrd.autovacuum_cxt.AutovacMemCxt, "AV dblist", ALLOCSET_DEFAULT_MINSIZE, ALLOCSET_DEFAULT_INITSIZE, ALLOCSET_DEFAULT_MAXSIZE); tmpcxt = AllocSetContextCreate( newcxt, "tmp AV dblist", ALLOCSET_DEFAULT_MINSIZE, ALLOCSET_DEFAULT_INITSIZE, ALLOCSET_DEFAULT_MAXSIZE); - oldcxt = MemoryContextSwitchTo(tmpcxt); + oldcxt = MemoryContextSwitchTo(tmpcxt); // 灏嗗綋鍓嶄笂涓嬫枃鍒囨崲涓轰复鏃朵笂涓嬫枃 /* * Implementing this is not as simple as it sounds, because we need to put @@ -698,54 +723,55 @@ static void rebuild_database_list(Oid newdb) * score, and finally put the array elements into the new doubly linked * list. */ - hctl.keysize = sizeof(Oid); - hctl.entrysize = sizeof(avl_dbase); - hctl.hash = oid_hash; - hctl.hcxt = tmpcxt; - dbhash = hash_create("db hash", 20, &hctl, HASH_ELEM | HASH_FUNCTION | HASH_CONTEXT); + // 鍒濆鍖栧搱甯岃〃鎺у埗缁撴瀯 + hctl.keysize = sizeof(Oid); // 閿殑澶у皬 + hctl.entrysize = sizeof(avl_dbase); // 鍝堝笇琛ㄥ厓绱犵殑澶у皬 + hctl.hash = oid_hash; // 浣跨敤Oid浣滀负鍝堝笇鍑芥暟 + hctl.hcxt = tmpcxt; // 鍝堝笇琛ㄧ殑涓婁笅鏂囦娇鐢ㄤ复鏃朵笂涓嬫枃 + dbhash = hash_create("db hash", 20, &hctl, HASH_ELEM | HASH_FUNCTION | HASH_CONTEXT); // 鍒涘缓鍝堝笇琛紝20涓Ы浣 /* start by inserting the new database */ score = 0; - if (OidIsValid(newdb)) { + if (OidIsValid(newdb)) { // 妫鏌ユ柊鏁版嵁搴撶殑鏈夋晥鎬 avl_dbase* db = NULL; PgStat_StatDBEntry* entry = NULL; /* only consider this database if it has a pgstat entry */ - entry = pgstat_fetch_stat_dbentry(newdb); - if (entry != NULL) { + entry = pgstat_fetch_stat_dbentry(newdb); // 鑾峰彇鏂版暟鎹簱鐨勭粺璁′俊鎭 + if (entry != NULL) {// 浠呰冭檻鍏锋湁缁熻淇℃伅鐨勬暟鎹簱 /* we assume it isn't found because the hash was just created */ - db = (avl_dbase*)hash_search(dbhash, &newdb, HASH_ENTER, NULL); + db = (avl_dbase*)hash_search(dbhash, &newdb, HASH_ENTER, NULL); // 鍦ㄥ搱甯岃〃涓煡鎵炬垨鎻掑叆鏂版暟鎹簱鐨勬潯鐩 /* hash_search already filled in the key */ - db->adl_score = score++; + db->adl_score = score++;// 璁剧疆鏁版嵁搴撶殑鍒嗘暟锛堜紭鍏堢骇锛 /* next_worker is filled in later */ } } /* Now insert the databases from the existing list */ - if (t_thrd.autovacuum_cxt.DatabaseList != NULL) { + if (t_thrd.autovacuum_cxt.DatabaseList != NULL) { // 濡傛灉宸茬粡瀛樺湪鏁版嵁搴撳垪琛 Dlelem* elem = NULL; - elem = DLGetHead(t_thrd.autovacuum_cxt.DatabaseList); - while (elem != NULL) { + elem = DLGetHead(t_thrd.autovacuum_cxt.DatabaseList); // 浠庡ご閮ㄨ幏鍙栫涓涓厓绱 + while (elem != NULL) { // 閬嶅巻鐜版湁鏁版嵁搴撳垪琛 avl_dbase* avdb = (avl_dbase*)DLE_VAL(elem); avl_dbase* db = NULL; bool found = false; PgStat_StatDBEntry* entry = NULL; - elem = DLGetSucc(elem); + elem = DLGetSucc(elem);// 鑾峰彇涓嬩竴涓厓绱 /* * skip databases with no stat entries -- in particular, this gets * rid of dropped databases */ - entry = pgstat_fetch_stat_dbentry(avdb->adl_datid); - if (entry == NULL) + entry = pgstat_fetch_stat_dbentry(avdb->adl_datid); // 鑾峰彇鏁版嵁搴撶粺璁′俊鎭 + if (entry == NULL) // 璺宠繃娌℃湁缁熻淇℃伅鐨勬暟鎹簱锛岀壒鍒槸宸插垹闄ょ殑鏁版嵁搴 continue; - db = (avl_dbase*)hash_search(dbhash, &(avdb->adl_datid), HASH_ENTER, &found); + db = (avl_dbase*)hash_search(dbhash, &(avdb->adl_datid), HASH_ENTER, &found); // 鍦ㄥ搱甯岃〃涓煡鎵炬垨鎻掑叆鏁版嵁搴撴潯鐩 - if (!found) { + if (!found) { // 濡傛灉鍦ㄥ搱甯岃〃涓湭鎵惧埌鏁版嵁搴撴潯鐩紝鍒欒缃暟鎹簱鐨勫垎鏁板苟閫掑 score 鍊 /* hash_search already filled in the key */ db->adl_score = score++; /* next_worker is filled in later */ @@ -754,19 +780,19 @@ static void rebuild_database_list(Oid newdb) } /* finally, insert all qualifying databases not previously inserted */ - dblist = get_database_list(); - foreach (cell, dblist) { - avw_dbase* avdb = (avw_dbase*)lfirst(cell); - avl_dbase* db = NULL; - bool found = false; - PgStat_StatDBEntry* entry = NULL; + dblist = get_database_list(); // 鑾峰彇鏁版嵁搴撳垪琛 + foreach (cell, dblist) { // 閬嶅巻鏁版嵁搴撳垪琛 + avw_dbase* avdb = (avw_dbase*)lfirst(cell); // 浠庨摼琛ㄨ妭鐐逛腑鑾峰彇 avw_dbase 缁撴瀯浣撴寚閽 + avl_dbase* db = NULL; // 鐢ㄤ簬瀛樺偍鍝堝笇琛ㄤ腑鐨勬暟鎹簱鏉$洰 + bool found = false; // 鎸囩ず鏄惁鍦ㄥ搱甯岃〃涓壘鍒版暟鎹簱鏉$洰 + PgStat_StatDBEntry* entry = NULL; // 鐢ㄤ簬瀛樺偍鏁版嵁搴撶殑缁熻淇℃伅 /* only consider databases with a pgstat entry */ - entry = pgstat_fetch_stat_dbentry(avdb->adw_datid); + entry = pgstat_fetch_stat_dbentry(avdb->adw_datid); // 浠呰冭檻鍏锋湁 pgstat 缁熻淇℃伅鐨勬暟鎹簱 if (entry == NULL) continue; - db = (avl_dbase*)hash_search(dbhash, &(avdb->adw_datid), HASH_ENTER, &found); + db = (avl_dbase*)hash_search(dbhash, &(avdb->adw_datid), HASH_ENTER, &found); // 鍦ㄥ搱甯岃〃涓悳绱㈡暟鎹簱鏉$洰 /* only update the score if the database was not already on the hash */ if (!found) { /* hash_search already filled in the key */ @@ -774,12 +800,13 @@ static void rebuild_database_list(Oid newdb) /* next_worker is filled in later */ } } - nelems = score; + nelems = score; // 鏇存柊鏁版嵁搴撴潯鐩暟閲 /* from here on, the allocated memory belongs to the new list */ - (void)MemoryContextSwitchTo(newcxt); - t_thrd.autovacuum_cxt.DatabaseList = DLNewList(); + (void)MemoryContextSwitchTo(newcxt); // 鍒囨崲褰撳墠鍐呭瓨涓婁笅鏂囦负鏂扮殑涓婁笅鏂囷紝鍒嗛厤鐨勫唴瀛樺皢灞炰簬鏂扮殑鍒楄〃 + t_thrd.autovacuum_cxt.DatabaseList = DLNewList(); // 鍒涘缓涓涓柊鐨勫弻鍚戦摼琛ㄦ潵瀛樺偍鏁版嵁搴撳垪琛 + // 濡傛灉鏁版嵁搴撴潯鐩暟閲忓ぇ浜0 if (nelems > 0) { TimestampTz current_time; int millis_increment; @@ -789,6 +816,7 @@ static void rebuild_database_list(Oid newdb) uint i; int rc = 0; + // 濡傛灉鏁版嵁搴撴潯鐩暟閲忓お澶э紝瓒呭嚭浜嗘渶澶у垎閰嶅ぇ灏忥紝鎶ラ敊 if (unlikely(nelems > MaxAllocSize / sizeof(avl_dbase))) { ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("Invalid database num:%u", nelems))); } @@ -796,11 +824,12 @@ static void rebuild_database_list(Oid newdb) /* put all the hash elements into an array */ dbary = (avl_dbase*)palloc(nelems * sizeof(avl_dbase)); + // 閬嶅巻鍝堝笇琛紝灏嗗厓绱犲鍒跺埌鏁扮粍涓 i = 0; hash_seq_init(&seq, dbhash); while ((db = (avl_dbase*)hash_seq_search(&seq)) != NULL) { rc = memcpy_s(&(dbary[i++]), sizeof(avl_dbase), db, sizeof(avl_dbase)); - securec_check(rc, "\0", "\0"); + securec_check(rc, "\0", "\0"); // 妫鏌ュ鍒舵搷浣滄槸鍚︽垚鍔 } /* sort the array */ @@ -813,40 +842,43 @@ static void rebuild_database_list(Oid newdb) * coded not to allow), silently use a larger naptime (but don't touch * the GUC variable). */ + // 璁$畻鏁版嵁搴撲箣闂寸殑鏃堕棿闂撮殧锛屽皢姣澧為噺璁句负 (autovacuum_naptime / nelems) * 1000 millis_increment = (int)(1000.0 * u_sess->attr.attr_storage.autovacuum_naptime / nelems); + // 濡傛灉璁$畻寰楀埌鐨勬绉掑閲忓皬浜庣瓑浜庢渶灏忎紤鐪犳椂闂达紝鍒欏皢鍏惰涓 (MIN_AUTOVAC_SLEEPTIME * 1.1) + // 纭繚浼戠湢鏃堕棿涓嶄細浣庝簬鏈灏忎紤鐪犳椂闂达紝浠ラ伩鍏嶈繃浜庨绻佺殑鍞ら啋鍜屾墽琛 if (millis_increment <= MIN_AUTOVAC_SLEEPTIME) { millis_increment = (int)(MIN_AUTOVAC_SLEEPTIME * 1.1); } - current_time = GetCurrentTimestamp(); + current_time = GetCurrentTimestamp(); // 鑾峰彇褰撳墠鏃堕棿鎴 /* * move the elements from the array into the dllist, setting the * next_worker while walking the array */ - for (i = 0; i < nelems; i++) { + for (i = 0; i < nelems; i++) { // 灏嗘暟缁勪腑鐨勫厓绱犵Щ鍏ュ弻鍚戦摼琛ㄤ腑 avl_dbase* db_tmp = (avl_dbase*)&(dbary[i]); Dlelem* elem = NULL; - current_time = TimestampTzPlusMilliseconds(current_time, millis_increment); + current_time = TimestampTzPlusMilliseconds(current_time, millis_increment); // 璁$畻涓嬩竴涓伐浣滄椂闂 db_tmp->adl_next_worker = current_time; - elem = DLNewElem(db_tmp); + elem = DLNewElem(db_tmp); // 鍒涘缓閾捐〃鍏冪礌骞舵坊鍔犲埌閾捐〃澶撮儴 /* later elements should go closer to the head of the list */ DLAddHead(t_thrd.autovacuum_cxt.DatabaseList, elem); } } /* all done, clean up memory */ - if (t_thrd.autovacuum_cxt.DatabaseListCxt != NULL) - MemoryContextDelete(t_thrd.autovacuum_cxt.DatabaseListCxt); - MemoryContextDelete(tmpcxt); - t_thrd.autovacuum_cxt.DatabaseListCxt = newcxt; - (void)MemoryContextSwitchTo(oldcxt); + if (t_thrd.autovacuum_cxt.DatabaseListCxt != NULL) // 妫鏌ユ槸鍚︽湁鏃х殑鏁版嵁搴撳垪琛ㄥ唴瀛樹笂涓嬫枃 + MemoryContextDelete(t_thrd.autovacuum_cxt.DatabaseListCxt); // 濡傛灉鏈夊垯鍒犻櫎锛岄噴鏀炬棫鐨勬暟鎹簱鍒楄〃鍐呭瓨 + MemoryContextDelete(tmpcxt); // 閲婃斁涓存椂鍐呭瓨涓婁笅鏂 + t_thrd.autovacuum_cxt.DatabaseListCxt = newcxt; // 灏嗘柊鐨勫唴瀛樹笂涓嬫枃璧嬪肩粰鏁版嵁搴撳垪琛ㄧ殑涓婁笅鏂 + (void)MemoryContextSwitchTo(oldcxt); // 鍒囨崲鍥炰箣鍓嶇殑鍐呭瓨涓婁笅鏂 } /* qsort comparator for avl_dbase, using adl_score */ -static int db_comparator(const void* a, const void* b) +static int db_comparator(const void* a, const void* b) // 鎺掑簭瀛樺偍鍦ㄦ暟缁勪腑鐨刟vl_dbase缁撴瀯浣 { if (((const avl_dbase*)a)->adl_score == ((const avl_dbase*)b)->adl_score) { return 0; @@ -868,25 +900,25 @@ static int db_comparator(const void* a, const void* b) */ static Oid do_start_worker(void) { - List* dblist = NIL; + List* dblist = NIL; // 鏁版嵁搴撳垪琛 ListCell* cell = NULL; - TransactionId xidForceLimit; + TransactionId xidForceLimit; // 浜嬪姟 ID 闄愬埗锛岀敤浜庡喅瀹氫綍鏃跺己鍒舵墽琛 VACUUM 鎿嶄綔 #ifndef ENABLE_MULTIPLE_NODES - MultiXactId multiForceLimit; + MultiXactId multiForceLimit; // 澶氫簨鍔 ID 闄愬埗 #endif - bool for_xid_wrap = false; - bool for_multi_wrap = false; - avw_dbase* avdb = NULL; - TimestampTz current_time; - bool skipit = false; - Oid retval = InvalidOid; - MemoryContext tmpcxt, oldcxt; + bool for_xid_wrap = false; // 鐢ㄤ簬鏍囪鏄惁璺ㄨ秺浜 XID 杈圭晫 + bool for_multi_wrap = false; // 鐢ㄤ簬鏍囪鏄惁璺ㄨ秺浜嗗浜嬪姟 ID 杈圭晫 + avw_dbase* avdb = NULL; // 鏁版嵁搴撶粨鏋勪綋 + TimestampTz current_time; // 褰撳墠鏃堕棿鎴 + bool skipit = false; // 鏍囪鏄惁闇瑕佽烦杩囨煇涓暟鎹簱 + Oid retval = InvalidOid; // 鍑芥暟杩斿洖鐨勮澶勭悊鐨勬暟鎹簱 OID锛岄粯璁や负 InvalidOid + MemoryContext tmpcxt, oldcxt; // 涓存椂鍐呭瓨涓婁笅鏂囧拰鏃у唴瀛樹笂涓嬫枃 /* return quickly when there are no free workers */ LWLockAcquire(AutovacuumLock, LW_SHARED); if (t_thrd.autovacuum_cxt.AutoVacuumShmem->av_freeWorkers == NULL) { LWLockRelease(AutovacuumLock); - AUTOVAC_LOG(LOG, "no free autovaccm worker"); + AUTOVAC_LOG(LOG, "no free autovaccm worker"); // 璁板綍鏃ュ織锛屾病鏈夊彲鐢ㄧ殑鑷姩娓呯悊宸ヤ綔杩涚▼ return InvalidOid; } @@ -896,22 +928,25 @@ static Oid do_start_worker(void) * Create and switch to a temporary context to avoid leaking the memory * allocated for the database list. */ + // 鍒涘缓骞跺垏鎹㈠埌涓存椂涓婁笅鏂囨潵瀛樺偍鏁版嵁搴撳垪琛ㄧ殑鍐呭瓨鍒嗛厤 tmpcxt = AllocSetContextCreate(CurrentMemoryContext, "Start worker tmp cxt", ALLOCSET_DEFAULT_MINSIZE, ALLOCSET_DEFAULT_INITSIZE, ALLOCSET_DEFAULT_MAXSIZE); oldcxt = MemoryContextSwitchTo(tmpcxt); /* use fresh stats */ - autovac_refresh_stats(); + autovac_refresh_stats(); // 鏇存柊缁熻鏁版嵁 /* Get a list of databases */ - dblist = get_database_list(); + dblist = get_database_list(); // 鑾峰彇鏁版嵁搴撳垪琛 /* * Determine the oldest datfrozenxid64/relfrozenxid64 that we will allow to * pass without forcing a vacuum. (This limit can be tightened for * particular tables, but not loosened.) */ - t_thrd.autovacuum_cxt.recentXid = ReadNewTransactionId(); + t_thrd.autovacuum_cxt.recentXid = ReadNewTransactionId(); // 璇诲彇鏈鏂扮殑浜嬪姟 ID + // 鍒ゆ柇鏈杩戠殑浜嬪姟ID鏄惁瓒呰繃浜嗛槇鍊硷紝鐢ㄤ簬璁$畻鍦ㄤ綍绉嶆儏鍐典笅闇瑕佸己鍒舵墽琛孷ACUUM鎿嶄綔鐨勬渶鏃╀簨鍔D闄愬埗 + // autovacuum_freeze_max_age 鏄竴涓狦UC鍙傛暟锛岃〃绀烘墽琛孷ACUUM鎿嶄綔鐨勬渶澶т簨鍔D鑼冨洿銆 if (t_thrd.autovacuum_cxt.recentXid > FirstNormalTransactionId + (uint64)g_instance.attr.attr_storage.autovacuum_freeze_max_age) xidForceLimit = t_thrd.autovacuum_cxt.recentXid - @@ -921,7 +956,8 @@ static Oid do_start_worker(void) #ifndef ENABLE_MULTIPLE_NODES /* Also determine the oldest datminmxid we will consider. */ - t_thrd.autovacuum_cxt.recentMulti = ReadNextMultiXactId(); + t_thrd.autovacuum_cxt.recentMulti = ReadNextMultiXactId(); // 璇诲彇鏈鏂扮殑澶氫簨鍔 ID + // 鍒ゆ柇鏈杩戠殑澶氫簨鍔D鏄惁瓒呰繃浜嗛槇鍊 if (t_thrd.autovacuum_cxt.recentMulti > FirstMultiXactId + (uint64)g_instance.attr.attr_storage.autovacuum_freeze_max_age) multiForceLimit = t_thrd.autovacuum_cxt.recentMulti - @@ -945,6 +981,7 @@ static Oid do_start_worker(void) * isn't clear how to construct a metric that measures that and not cause * starvation for less busy databases. */ + // 鍒濆鍖 avdb = NULL; for_xid_wrap = false; for_multi_wrap = false; @@ -954,15 +991,18 @@ static Oid do_start_worker(void) Dlelem* elem = NULL; /* Check to see if this one is need freeze */ + // 妫鏌ユ槸鍚﹂渶瑕佸喕缁撳綋鍓嶆暟鎹簱鐨勪簨鍔D浠ヨ繘琛孷ACUUM if (TransactionIdPrecedes(tmp->adw_frozenxid, xidForceLimit)) { + // 濡傛灉褰撳墠鏁版嵁搴撶殑鍐荤粨浜嬪姟ID鏃╀簬闄愬埗鐨勪簨鍔D锛岃〃绀洪渶瑕佽繘琛岃嚜鍔╒ACUUM锛屼互闃叉浜嬪姟ID鑰楀敖 if (avdb == NULL || TransactionIdPrecedes(tmp->adw_frozenxid, avdb->adw_frozenxid)) - avdb = tmp; - for_xid_wrap = true; + avdb = tmp; // 灏哸vdb璁剧疆涓哄綋鍓嶆暟鎹簱锛屼互閫夋嫨鏈鏃╅渶瑕佽嚜鍔╒ACUUM鐨勬暟鎹簱 + for_xid_wrap = true; // 璁剧疆鏍囧織鍙橀噺锛岃〃绀哄凡缁忚冭檻浜嗛渶瑕佽繘琛屼簨鍔D鍥炵粫鐨勬儏鍐 continue; } else if (for_xid_wrap) continue; /* ignore not-at-risk DBs */ #ifndef ENABLE_MULTIPLE_NODES else if (MultiXactIdPrecedes(tmp->adw_frozenmulti, multiForceLimit)) { + // 鍦ㄩ潪澶氳妭鐐归厤缃笅锛屾鏌ュ綋鍓嶆暟鎹簱鐨勫喕缁撳浜嬪姟ID鏄惁鏃╀簬闄愬埗鐨勫浜嬪姟ID if (avdb == NULL || MultiXactIdPrecedes(tmp->adw_frozenmulti, avdb->adw_frozenmulti)) avdb = tmp; for_multi_wrap = true; @@ -972,7 +1012,7 @@ static Oid do_start_worker(void) #endif /* Find pgstat entry if any */ - tmp->adw_entry = pgstat_fetch_stat_dbentry(tmp->adw_datid); + tmp->adw_entry = pgstat_fetch_stat_dbentry(tmp->adw_datid); // 鏌ユ壘鏁版嵁搴撶殑缁熻淇℃伅锛坧gstat entry锛 /* * Skip a database with no pgstat entry; it means it hasn't seen any @@ -994,11 +1034,12 @@ static Oid do_start_worker(void) while (elem != NULL) { avl_dbase* dbp = (avl_dbase*)DLE_VAL(elem); - if (dbp->adl_datid == tmp->adw_datid) { + if (dbp->adl_datid == tmp->adw_datid) { // 妫鏌ヤ袱涓暟鎹簱鐨勬暟鎹〃鏄惁鐩稿悓 /* * Skip this database if its next_worker value falls between * the current time and the current time plus naptime. */ + // 鍒ゆ柇鏄惁璺宠繃褰撳墠鐨勬暟鎹簱 if (!TimestampDifferenceExceeds(dbp->adl_next_worker, current_time, 0) && !TimestampDifferenceExceeds( current_time, dbp->adl_next_worker, u_sess->attr.attr_storage.autovacuum_naptime * 1000)) @@ -1006,7 +1047,7 @@ static Oid do_start_worker(void) break; } - elem = DLGetPred(elem); + elem = DLGetPred(elem);// 鑾峰彇鍓嶄竴涓摼琛ㄥ厓绱 } if (skipit) continue; @@ -1023,38 +1064,44 @@ static Oid do_start_worker(void) if (avdb != NULL) { WorkerInfo worker = NULL; - LWLockAcquire(AutovacuumLock, LW_EXCLUSIVE); + LWLockAcquire(AutovacuumLock, LW_EXCLUSIVE); // 鑾峰彇鐙崰閿佷互淇敼鑷姩娓呯悊鐩稿叧鍏变韩鍐呭瓨鏁版嵁 /* * Get a worker entry from the freelist. We checked above, so there * really should be a free slot -- complain very loudly if there * isn't. */ + // 浠庣┖闂插伐浣滆繘绋嬮摼琛ㄤ腑鑾峰彇涓涓┖闂插伐浣滆繘绋嬫潯鐩 worker = t_thrd.autovacuum_cxt.AutoVacuumShmem->av_freeWorkers; if (worker == NULL) ereport(FATAL, (errmsg("no free worker found"))); + // 灏嗚幏鍙栫殑宸ヤ綔杩涚▼鏉$洰浠庣┖闂查摼琛ㄤ腑绉婚櫎 t_thrd.autovacuum_cxt.AutoVacuumShmem->av_freeWorkers = (WorkerInfo)worker->wi_links.next; - worker->wi_dboid = avdb->adw_datid; - worker->wi_proc = NULL; - worker->wi_launchtime = GetCurrentTimestamp(); + // 璁剧疆宸ヤ綔杩涚▼鐨勭浉鍏充俊鎭 + worker->wi_dboid = avdb->adw_datid; // 璁剧疆宸ヤ綔杩涚▼澶勭悊鐨勬暟鎹簱鏍囪瘑 + worker->wi_proc = NULL; // 鍒濆鍖栧伐浣滆繘绋嬬殑杩涚▼淇℃伅 + worker->wi_launchtime = GetCurrentTimestamp(); // 璁板綍宸ヤ綔杩涚▼鍚姩鐨勬椂闂 + // 灏嗚鍚姩鐨勫伐浣滆繘绋嬭缃埌鍏变韩鍐呭瓨涓紝浠ラ氱煡Postmaster鍚姩宸ヤ綔杩涚▼ t_thrd.autovacuum_cxt.AutoVacuumShmem->av_startingWorker = worker; - LWLockRelease(AutovacuumLock); + LWLockRelease(AutovacuumLock); // 閲婃斁鐙崰閿 + // 鍚慞ostmaster鍙戦佷俊鍙凤紝閫氱煡鍚姩鑷姩娓呯悊宸ヤ綔杩涚▼ SendPostmasterSignal(PMSIGNAL_START_AUTOVAC_WORKER); - retval = avdb->adw_datid; + retval = avdb->adw_datid; // 璁剧疆杩斿洖鍊间负瑕佸鐞嗙殑鏁版嵁搴撴爣璇 } else if (skipit) { /* * If we skipped all databases on the list, rebuild it, because it * probably contains a dropped database. */ - rebuild_database_list(InvalidOid); + rebuild_database_list(InvalidOid); // 濡傛灉璺宠繃浜嗘墍鏈夋暟鎹簱锛屽垯閲嶆柊鏋勫缓鏁版嵁搴撳垪琛 } + // 鍒囨崲鍥炲師濮嬪唴瀛樹笂涓嬫枃骞堕噴鏀句复鏃跺唴瀛樹笂涓嬫枃 (void)MemoryContextSwitchTo(oldcxt); MemoryContextDelete(tmpcxt); @@ -1077,28 +1124,30 @@ static void launch_worker(TimestampTz now) Oid dbid; Dlelem* elem = NULL; - dbid = do_start_worker(); + dbid = do_start_worker(); // 閫夋嫨骞跺惎鍔ㄤ竴涓嚜鍔ㄦ竻鐞嗗伐浣滆繘绋 if (OidIsValid(dbid)) { /* * Walk the database list and update the corresponding entry. If the * database is not on the list, we'll recreate the list. */ + // 閬嶅巻鏁版嵁搴撳垪琛ㄤ互鏇存柊鐩稿簲鐨勬暟鎹簱鏉$洰 elem = (t_thrd.autovacuum_cxt.DatabaseList == NULL) ? NULL : DLGetHead(t_thrd.autovacuum_cxt.DatabaseList); while (elem != NULL) { avl_dbase* avdb = (avl_dbase*)DLE_VAL(elem); - if (avdb->adl_datid == dbid) { + if (avdb->adl_datid == dbid) { // 鏌ユ壘涓庡綋鍓嶅惎鍔ㄧ殑鏁版嵁搴撴爣璇嗗尮閰嶇殑鏁版嵁搴撴潯鐩 /* * add autovacuum_naptime seconds to the current time, and use * that as the new "next_worker" field for this database. */ + // 璁$畻涓嬩竴涓伐浣滄椂闂村苟鏇存柊鏁版嵁搴撴潯鐩殑 next_worker 瀛楁 avdb->adl_next_worker = TimestampTzPlusMilliseconds(now, u_sess->attr.attr_storage.autovacuum_naptime * 1000); - DLMoveToFront(elem); + DLMoveToFront(elem); // 灏嗗綋鍓嶅厓绱犵Щ鍔ㄥ埌閾捐〃澶撮儴 break; } - elem = DLGetSucc(elem); + elem = DLGetSucc(elem); // 鑾峰彇涓嬩竴涓摼琛ㄥ厓绱 } /* @@ -1108,6 +1157,7 @@ static void launch_worker(TimestampTz now) * pgstat entry, but this is not a problem because we don't want to * schedule workers regularly into those in any case. */ + // 濡傛灉鏁版嵁搴撲笉鍦ㄦ暟鎹簱鍒楄〃涓紝閲嶆柊鏋勫缓鍒楄〃 if (elem == NULL) rebuild_database_list(dbid); } @@ -1120,17 +1170,18 @@ static void launch_worker(TimestampTz now) */ void AutoVacWorkerFailed(void) { - t_thrd.autovacuum_cxt.AutoVacuumShmem->av_signal[AutoVacForkFailed] = true; + // 鍦ㄦ棤娉昮ork鍑哄伐浣滆繘绋嬫椂锛岀敱Postmaster璋冪敤鍚戣嚜鍔ㄦ竻鐞嗚繘绋嬪彂閫佷俊鍙 + t_thrd.autovacuum_cxt.AutoVacuumShmem->av_signal[AutoVacForkFailed] = true; } /* SIGHUP: set flag to re-read config file at next convenient time */ static void avl_sighup_handler(SIGNAL_ARGS) { int save_errno = errno; - + // 鏀跺埌SIGHUP淇″彿鏃讹紝璁剧疆鏍囧織浠ュ湪涓嬩竴涓柟渚跨殑鏃堕棿閲嶆柊璇诲彇閰嶇疆鏂囦欢 t_thrd.autovacuum_cxt.got_SIGHUP = true; if (t_thrd.proc) - SetLatch(&t_thrd.proc->procLatch); + SetLatch(&t_thrd.proc->procLatch); // 璁剧疆杩涚▼鏍囪瘑浠ュ敜閱掕繘绋 errno = save_errno; } @@ -1139,10 +1190,10 @@ static void avl_sighup_handler(SIGNAL_ARGS) static void avl_sigusr2_handler(SIGNAL_ARGS) { int save_errno = errno; - + // 鏀跺埌 SIGUSR2 淇″彿鏃讹紝璁剧疆鏍囧織浠ヨ〃绀轰竴涓伐浣滆繘绋嬫鍦ㄨ繍琛屻佸垰鍒氬畬鎴愶紝鎴栬呭湪 fork 鏃跺け璐 t_thrd.autovacuum_cxt.got_SIGUSR2 = true; if (t_thrd.proc) - SetLatch(&t_thrd.proc->procLatch); + SetLatch(&t_thrd.proc->procLatch); // 璁剧疆杩涚▼鏍囪瘑浠ュ敜閱掕繘绋 errno = save_errno; } @@ -1151,10 +1202,10 @@ static void avl_sigusr2_handler(SIGNAL_ARGS) static void avl_sigterm_handler(SIGNAL_ARGS) { int save_errno = errno; - + // 鏀跺埌 SIGTERM 淇″彿鏃讹紝璁剧疆鏍囧織浠ヨ〃绀鸿繘绋嬮渶瑕佺粓姝 t_thrd.autovacuum_cxt.got_SIGTERM = true; if (t_thrd.proc) - SetLatch(&t_thrd.proc->procLatch); + SetLatch(&t_thrd.proc->procLatch); // 璁剧疆杩涚▼鏍囪瘑浠ュ敜閱掕繘绋 errno = save_errno; } @@ -1177,12 +1228,12 @@ void AutovacuumWorkerIAm(void) */ NON_EXEC_STATIC void AutoVacWorkerMain() { - sigjmp_buf local_sigjmp_buf; + sigjmp_buf local_sigjmp_buf; // 璁剧疆璺宠浆鏍囧織浠ュ疄鐜拌烦鍑哄紓甯 Oid dbid; char user[NAMEDATALEN]; /* we are a postmaster subprocess now */ - IsUnderPostmaster = true; + IsUnderPostmaster = true; // 灏嗗綋鍓嶈繘绋嬫爣璇嗕负鍚庡彴杩涚▼ t_thrd.role = AUTOVACUUM_WORKER; /* reset t_thrd.proc_cxt.MyProcPid */ @@ -1191,12 +1242,12 @@ NON_EXEC_STATIC void AutoVacWorkerMain() /* record Start Time for logging */ t_thrd.proc_cxt.MyStartTime = time(NULL); - t_thrd.proc_cxt.MyProgName = "AutoVacWorker"; + t_thrd.proc_cxt.MyProgName = "AutoVacWorker"; // 璁剧疆杩涚▼鍚 /* Identify myself via ps */ init_ps_display("autovacuum worker process", "", "", ""); - SetProcessingMode(InitProcessing); + SetProcessingMode(InitProcessing); // 璁剧疆澶勭悊妯″紡涓哄垵濮嬪寲 /* * Set up signal handlers. We operate on databases much like a regular @@ -1210,6 +1261,7 @@ NON_EXEC_STATIC void AutoVacWorkerMain() * SIGINT is used to signal canceling the current table's vacuum; SIGTERM * means abort and exit cleanly, and SIGQUIT means abandon ship. */ + // 璁剧疆淇″彿澶勭悊鍑芥暟 (void)gspqsignal(SIGINT, StatementCancelHandler); (void)gspqsignal(SIGTERM, die); (void)gspqsignal(SIGQUIT, quickdie); @@ -1245,8 +1297,8 @@ NON_EXEC_STATIC void AutoVacWorkerMain() */ int curTryCounter; int* oldTryCounter = NULL; - if (sigsetjmp(local_sigjmp_buf, 1) != 0) { - gstrace_tryblock_exit(true, oldTryCounter); + if (sigsetjmp(local_sigjmp_buf, 1) != 0) { // 浣跨敤 sigsetjmp 璁剧疆涓涓繑鍥炵偣锛屼互渚垮湪鍑虹幇寮傚父鏃惰烦杞洖鍒版澶 + gstrace_tryblock_exit(true, oldTryCounter); // 閫鍑 gstrace_tryblock 鍧 /* Prevents interrupts while cleaning up */ HOLD_INTERRUPTS(); @@ -1263,12 +1315,12 @@ NON_EXEC_STATIC void AutoVacWorkerMain() */ proc_exit(0); } - oldTryCounter = gstrace_tryblock_entry(&curTryCounter); + oldTryCounter = gstrace_tryblock_entry(&curTryCounter); // 杩涘叆 gstrace_tryblock 鍧楋紝璁板綍褰撳墠灏濊瘯娆℃暟 /* We can now handle ereport(ERROR) */ t_thrd.log_cxt.PG_exception_stack = &local_sigjmp_buf; - gs_signal_setmask(&t_thrd.libpq_cxt.UnBlockSig, NULL); + gs_signal_setmask(&t_thrd.libpq_cxt.UnBlockSig, NULL); // 瑙i櫎淇″彿鐨勯樆濉炵姸鎬 (void)gs_signal_unblock_sigusr2(); /* @@ -1276,12 +1328,14 @@ NON_EXEC_STATIC void AutoVacWorkerMain() * in postgresql.conf. We don't really want such a dangerous option being * applied non-interactively. */ + // 鍦 autovac 杩涚▼涓己鍒跺叧闂 zero_damaged_pages SetConfigOption("zero_damaged_pages", "false", PGC_SUSET, PGC_S_OVERRIDE); /* * Force statement_timeout to zero to avoid a timeout setting from * preventing regular maintenance from being executed. */ + // 灏 statement_timeout 寮哄埗涓洪浂锛屼互閬垮厤瓒呮椂闄愬埗褰卞搷鑷姩娓呯悊鎿嶄綔 SetConfigOption("statement_timeout", "0", PGC_SUSET, PGC_S_OVERRIDE); /* @@ -1289,11 +1343,13 @@ NON_EXEC_STATIC void AutoVacWorkerMain() * to pay the overhead of serializable mode, nor add any risk of causing * deadlocks or delaying other transactions. */ + // 寮哄埗 default_transaction_isolation 涓 READ COMMITTED锛屼互閬垮厤涓嶅繀瑕佺殑浜嬪姟闅旂绾у埆 SetConfigOption("default_transaction_isolation", "read committed", PGC_SUSET, PGC_S_OVERRIDE); /* * Get the info about the database we're going to work on. */ + // 鑾峰彇瑕佸鐞嗙殑鏁版嵁搴撶殑淇℃伅 LWLockAcquire(AutovacuumLock, LW_EXCLUSIVE); /* @@ -1302,33 +1358,35 @@ NON_EXEC_STATIC void AutoVacWorkerMain() * launcher might have decided to remove it from the queue and start * again. */ + // 妫鏌ユ槸鍚﹀瓨鍦ㄦ鍦ㄥ惎鍔ㄧ殑宸ヤ綔杩涚▼ if (t_thrd.autovacuum_cxt.AutoVacuumShmem->av_startingWorker != NULL) { t_thrd.autovacuum_cxt.MyWorkerInfo = t_thrd.autovacuum_cxt.AutoVacuumShmem->av_startingWorker; - dbid = t_thrd.autovacuum_cxt.MyWorkerInfo->wi_dboid; - t_thrd.autovacuum_cxt.MyWorkerInfo->wi_proc = t_thrd.proc; + dbid = t_thrd.autovacuum_cxt.MyWorkerInfo->wi_dboid; // 鑾峰彇褰撳墠宸ヤ綔杩涚▼鎵澶勭悊鐨勬暟鎹簱鏍囪瘑 + t_thrd.autovacuum_cxt.MyWorkerInfo->wi_proc = t_thrd.proc; // 璁剧疆褰撳墠宸ヤ綔杩涚▼鐨 PGPROC 缁撴瀯鎸囬拡 /* insert into the running list */ - SHMQueueInsertBefore( + SHMQueueInsertBefore( // 鎻掑叆杩愯鍒楄〃 &t_thrd.autovacuum_cxt.AutoVacuumShmem->av_runningWorkers, &t_thrd.autovacuum_cxt.MyWorkerInfo->wi_links); /* * remove from the "starting" pointer, so that the launcher can start * a new worker if required */ + // 绉婚櫎鎸囬拡锛屼互渚垮惎鍔ㄥ櫒鍙互鍦ㄩ渶瑕佹椂鍚姩鏂扮殑宸ヤ綔绋嬪簭 t_thrd.autovacuum_cxt.AutoVacuumShmem->av_startingWorker = NULL; - LWLockRelease(AutovacuumLock); + LWLockRelease(AutovacuumLock); // 閲婃斁鑷姩娓呯悊閿 - on_shmem_exit(FreeWorkerInfo, 0); - on_shmem_exit(PGXCNodeCleanAndRelease, 0); + on_shmem_exit(FreeWorkerInfo, 0); // 鍦ㄩ鍑烘椂璋冪敤 FreeWorkerInfo 鍑芥暟 + on_shmem_exit(PGXCNodeCleanAndRelease, 0); // 鍦ㄩ鍑烘椂璋冪敤 PGXCNodeCleanAndRelease 鍑芥暟 /* wake up the launcher */ - if (t_thrd.autovacuum_cxt.AutoVacuumShmem->av_launcherpid != 0) + if (t_thrd.autovacuum_cxt.AutoVacuumShmem->av_launcherpid != 0) // 濡傛灉璁剧疆浜 launcher 杩涚▼ ID锛屽垯鍙戦 SIGUSR2 淇″彿鍞ら啋 launcher 杩涚▼ gs_signal_send(t_thrd.autovacuum_cxt.AutoVacuumShmem->av_launcherpid, SIGUSR2); } else { /* no worker entry for me, go away */ ereport(WARNING, (errmsg("autovacuum worker started without a worker entry"))); - dbid = InvalidOid; - LWLockRelease(AutovacuumLock); + dbid = InvalidOid; // 璁剧疆鏁版嵁搴撴爣璇嗕负鏃犳晥鍊 + LWLockRelease(AutovacuumLock); // 閲婃斁鑷姩娓呯悊閿 } if (OidIsValid(dbid)) { @@ -1343,6 +1401,7 @@ NON_EXEC_STATIC void AutoVacWorkerMain() * database, rather than making any progress on stuff it can connect * to. */ + // 鍦ㄨ嚜鍔ㄦ竻鐞嗚繘绋嬪惎鍔ㄦ椂鎶ュ憡淇℃伅缁欑粺璁′俊鎭敹闆嗗櫒 pgstat_report_autovac(dbid); AUTOVAC_LOG(LOG, "report autovac startup on database %u to stats collector", dbid); @@ -1352,14 +1411,16 @@ NON_EXEC_STATIC void AutoVacWorkerMain() * Note: if we have selected a just-deleted database (due to using * stale stats info), we'll fail and exit here. */ + // 杩炴帴鍒版墍閫夋暟鎹簱 t_thrd.proc_cxt.PostInit->SetDatabaseAndUser(NULL, dbid, NULL); t_thrd.proc_cxt.PostInit->InitAutoVacWorker(); t_thrd.proc_cxt.PostInit->GetDatabaseName(dbname); - SetProcessingMode(NormalProcessing); - set_ps_display(dbname, false); - ereport(LOG, (errmsg("start autovacuum on database \"%s\"", dbname))); + SetProcessingMode(NormalProcessing); // 璁剧疆澶勭悊妯″紡涓烘甯稿鐞 + set_ps_display(dbname, false); // 璁剧疆杩涚▼鐘舵佹樉绀轰负鏁版嵁搴撳悕 + ereport(LOG, (errmsg("start autovacuum on database \"%s\"", dbname))); // 璁板綍鏃ュ織锛屽紑濮嬪鏁版嵁搴撴墽琛岃嚜鍔ㄦ竻鐞嗘搷浣 + // 濡傛灉閰嶇疆浜 PostAuthDelay锛屽垯鍦ㄥ惎鍔ㄥ悗鏆傚仠涓娈垫椂闂 if (u_sess->attr.attr_security.PostAuthDelay) pg_usleep(u_sess->attr.attr_security.PostAuthDelay * 1000000L); @@ -1369,6 +1430,7 @@ NON_EXEC_STATIC void AutoVacWorkerMain() * t_thrd.mem_cxt.msg_mem_cxt is reset once per iteration of the main loop, ie, upon * completion of processing of each command message from the client. */ + // 鍦ㄤ富寰幆涓垱寤哄唴瀛樹笂涓嬫枃 t_thrd.mem_cxt.msg_mem_cxt = AllocSetContextCreate(t_thrd.top_mem_cxt, "MessageContext", ALLOCSET_DEFAULT_MINSIZE, ALLOCSET_DEFAULT_INITSIZE, ALLOCSET_DEFAULT_MAXSIZE); @@ -1379,25 +1441,40 @@ NON_EXEC_STATIC void AutoVacWorkerMain() * Create a resource owner to keep track of our resources (currently only * buffer pins). */ + // 鍦ㄨ嚜鍔ㄦ竻鐞嗚繘绋嬩腑鍒涘缓涓涓祫婧愭墍鏈夎咃紝鐢ㄤ簬璺熻釜鍒嗛厤鐨勮祫婧 t_thrd.utils_cxt.CurrentResourceOwner = ResourceOwnerCreate(NULL, "AutoVacuumWorker", THREAD_GET_MEM_CXT_GROUP(MEMORY_CONTEXT_STORAGE)); + /* + * 淇濆瓨褰撳墠鍐呭瓨涓婁笅鏂囷紝骞跺垏鎹㈠埌 SESS_GET_MEM_CXT_GROUP(MEMORY_CONTEXT_STORAGE)銆 + * 杩欐槸涓轰簡鍦ㄦ墽琛屽悗缁搷浣滄椂浣跨敤鍚堥傜殑鍐呭瓨涓婁笅鏂囥 + */ oldcontext = MemoryContextSwitchTo(SESS_GET_MEM_CXT_GROUP(MEMORY_CONTEXT_STORAGE)); + /* + * 濡傛灉褰撳墠杩涚▼鐨 MyProcPort 鏁版嵁鎴愬憳涓繚瀛樹簡鏁版嵁搴撳悕鐨勫唴瀛樺垯閲婃斁銆備负浜嗛伩鍏嶅唴瀛樻硠婕忋 + */ if (u_sess->proc_cxt.MyProcPort->database_name) pfree_ext(u_sess->proc_cxt.MyProcPort->database_name); if (u_sess->proc_cxt.MyProcPort->user_name) pfree_ext(u_sess->proc_cxt.MyProcPort->user_name); - u_sess->proc_cxt.MyProcPort->database_name = pstrdup(dbname); - u_sess->proc_cxt.MyProcPort->user_name = (char*)GetSuperUserName((char*)user); + u_sess->proc_cxt.MyProcPort->database_name = pstrdup(dbname); // 灏嗘暟鎹簱鍚嶅鍒跺埌 MyProcPort 鏁版嵁鎴愬憳 + u_sess->proc_cxt.MyProcPort->user_name = (char*)GetSuperUserName((char*)user); // 灏嗚秴绾х敤鎴风殑鐢ㄦ埛鍚嶅鍒跺埌 MyProcPort 鏁版嵁鎴愬憳涓 + /* + * 鍒囨崲鍥炰箣鍓嶄繚瀛樼殑鍐呭瓨涓婁笅鏂囷紝浠ヤ究缁х画鍦ㄥ師鏉ョ殑涓婁笅鏂囦腑杩涜鍚庣画鎿嶄綔銆 + */ (void)MemoryContextSwitchTo(oldcontext); /* Get classified list of node Oids for do analyze in coordinator. */ + /* + * 鍒濆鍖栬繛鎺ユ睜鍙ユ焺锛屽噯澶囪繘琛屽垎鏋愭搷浣溿 + * 杩欏彲鑳芥槸鍦ㄥ崗璋冭妭鐐逛笂杩涜鐨勪竴浜涙搷浣滐紝涓庡垎鏋愮浉鍏炽 + */ exec_init_poolhandles(); /* And do an appropriate amount of work */ - t_thrd.autovacuum_cxt.recentXid = ReadNewTransactionId(); - t_thrd.autovacuum_cxt.recentMulti = ReadNextMultiXactId(); - do_autovacuum(); + t_thrd.autovacuum_cxt.recentXid = ReadNewTransactionId(); // 璇诲彇鏈鏂扮殑浜嬪姟 ID锛屽苟灏嗗叾瀛樺偍鍦ㄨ嚜鍔ㄦ竻鐞嗕笂涓嬫枃涓 + t_thrd.autovacuum_cxt.recentMulti = ReadNextMultiXactId(); // 璇诲彇鏈鏂扮殑澶氫簨鍔 ID锛屽苟灏嗗叾瀛樺偍鍦ㄨ嚜鍔ㄦ竻鐞嗕笂涓嬫枃涓 + do_autovacuum(); // 鏍规嵁鍓嶉潰鐨勮缃拰璇诲彇鐨勪簨鍔 ID锛岃繘琛岀浉搴旂殑鑷姩娓呯悊宸ヤ綔 } /* @@ -1413,10 +1490,10 @@ NON_EXEC_STATIC void AutoVacWorkerMain() */ static void FreeWorkerInfo(int code, Datum arg) { - if (t_thrd.autovacuum_cxt.MyWorkerInfo != NULL) { + if (t_thrd.autovacuum_cxt.MyWorkerInfo != NULL) { // 濡傛灉褰撳墠宸ヤ綔杩涚▼淇℃伅瀛樺湪 LWLockAcquire(AutovacuumLock, LW_EXCLUSIVE); /* double check */ - if (t_thrd.autovacuum_cxt.MyWorkerInfo == NULL) { + if (t_thrd.autovacuum_cxt.MyWorkerInfo == NULL) { // 鍐嶆妫鏌ヤ互纭繚娌℃湁鍏朵粬杩涚▼淇敼浜嗗伐浣滆繘绋嬩俊鎭 LWLockRelease(AutovacuumLock); return; } @@ -1434,7 +1511,8 @@ static void FreeWorkerInfo(int code, Datum arg) */ t_thrd.autovacuum_cxt.AutovacuumLauncherPid = t_thrd.autovacuum_cxt.AutoVacuumShmem->av_launcherpid; - SHMQueueDelete(&t_thrd.autovacuum_cxt.MyWorkerInfo->wi_links); + SHMQueueDelete(&t_thrd.autovacuum_cxt.MyWorkerInfo->wi_links); // 浠庤繍琛屽伐浣滆繘绋嬮槦鍒椾腑鍒犻櫎褰撳墠宸ヤ綔杩涚▼淇℃伅 + // 閲嶇疆宸ヤ綔杩涚▼淇℃伅涓殑鍚勪釜瀛楁 t_thrd.autovacuum_cxt.MyWorkerInfo->wi_links.next = (SHM_QUEUE*)t_thrd.autovacuum_cxt.AutoVacuumShmem->av_freeWorkers; t_thrd.autovacuum_cxt.MyWorkerInfo->wi_dboid = InvalidOid; @@ -1446,14 +1524,16 @@ static void FreeWorkerInfo(int code, Datum arg) t_thrd.autovacuum_cxt.MyWorkerInfo->wi_cost_delay = 0; t_thrd.autovacuum_cxt.MyWorkerInfo->wi_cost_limit = 0; t_thrd.autovacuum_cxt.MyWorkerInfo->wi_cost_limit_base = 0; + // 灏嗗綋鍓嶅伐浣滆繘绋嬩俊鎭坊鍔犲埌绌洪棽宸ヤ綔杩涚▼闃熷垪涓 t_thrd.autovacuum_cxt.AutoVacuumShmem->av_freeWorkers = t_thrd.autovacuum_cxt.MyWorkerInfo; /* not mine anymore */ - t_thrd.autovacuum_cxt.MyWorkerInfo = NULL; + t_thrd.autovacuum_cxt.MyWorkerInfo = NULL; // 瑙i櫎鏍囪锛岃〃绀轰笉鍐嶆槸褰撳墠宸ヤ綔杩涚▼淇℃伅 /* * now that we're inactive, cause a rebalancing of the surviving * workers */ + // 鐜板湪涓嶅啀鏄椿璺冨伐浣滆繘绋嬶紝閫氱煡 launcher 杩涚▼杩涜閲嶅钩琛 t_thrd.autovacuum_cxt.AutoVacuumShmem->av_signal[AutoVacRebalance] = true; LWLockRelease(AutovacuumLock); } @@ -1465,7 +1545,7 @@ static void FreeWorkerInfo(int code, Datum arg) */ void AutoVacuumUpdateDelay(void) { - if (t_thrd.autovacuum_cxt.MyWorkerInfo) { + if (t_thrd.autovacuum_cxt.MyWorkerInfo) { // 鏇存柊鎴愭湰寤惰繜鍙傛暟 u_sess->attr.attr_storage.VacuumCostDelay = t_thrd.autovacuum_cxt.MyWorkerInfo->wi_cost_delay; u_sess->attr.attr_storage.VacuumCostLimit = t_thrd.autovacuum_cxt.MyWorkerInfo->wi_cost_limit; } @@ -1487,6 +1567,7 @@ static void autovac_balance_cost(void) * note: in cost_limit, zero also means use value from elsewhere, because * zero is not a valid value. */ + // 纭畾鍚勪釜宸ヤ綔杩涚▼鐨勬垚鏈檺鍒讹紝浠ュ钩鍧囧垎閰 I/O 璧勬簮 int vac_cost_limit = (u_sess->attr.attr_storage.autovacuum_vac_cost_limit > 0 ? u_sess->attr.attr_storage.autovacuum_vac_cost_limit : u_sess->attr.attr_storage.VacuumCostLimit); @@ -1498,18 +1579,22 @@ static void autovac_balance_cost(void) WorkerInfo worker = NULL; /* not set? nothing to do */ - if (vac_cost_limit <= 0 || vac_cost_delay <= 0) { + if (vac_cost_limit <= 0 || vac_cost_delay <= 0) { // 鑻ユ湭璁剧疆鎴愭湰闄愬埗锛屾棤闇鎿嶄綔 return; } /* caculate the total base cost limit of active workers */ + // 璁$畻褰撳墠鎵鏈夋椿璺冨伐浣滆繘绋嬬殑鍩哄噯鎴愭湰闄愬埗鎬诲拰 cost_total = 0.0; + // 鍒濆鍖栨寚閽堬紝浠庢椿璺冨伐浣滆繘绋嬪垪琛ㄧ殑寮澶村紑濮嬮亶鍘 worker = (WorkerInfo)SHMQueueNext(&t_thrd.autovacuum_cxt.AutoVacuumShmem->av_runningWorkers, &t_thrd.autovacuum_cxt.AutoVacuumShmem->av_runningWorkers, offsetof(WorkerInfoData, wi_links)); - while (worker != NULL) { + while (worker != NULL) { // 閬嶅巻娲昏穬宸ヤ綔杩涚▼鍒楄〃 + // 妫鏌ュ綋鍓嶅伐浣滆繘绋嬫槸鍚︽湁鏁堜互鍙婃垚鏈弬鏁版槸鍚﹀悎娉 if (worker->wi_proc != NULL && worker->wi_cost_limit_base > 0 && worker->wi_cost_delay > 0) - cost_total += (double)worker->wi_cost_limit_base / worker->wi_cost_delay; + cost_total += (double)worker->wi_cost_limit_base / worker->wi_cost_delay; // 璁$畻褰撳墠宸ヤ綔杩涚▼鐨勬垚鏈紝灏嗗叾鍔犲埌鎬绘垚鏈腑 + // 鑾峰彇涓嬩竴涓椿璺冨伐浣滆繘绋嬶紝缁х画閬嶅巻 worker = (WorkerInfo)SHMQueueNext(&t_thrd.autovacuum_cxt.AutoVacuumShmem->av_runningWorkers, &worker->wi_links, offsetof(WorkerInfoData, wi_links)); } @@ -1522,6 +1607,7 @@ static void autovac_balance_cost(void) * Adjust cost limit of each active worker to balance the total of cost * limit to autovacuum_vacuum_cost_limit. */ + // 璋冩暣鍚勪釜宸ヤ綔杩涚▼鐨勬垚鏈檺鍒讹紝骞宠 鎬绘垚鏈檺鍒 cost_avail = (double)vac_cost_limit / vac_cost_delay; worker = (WorkerInfo)SHMQueueNext(&t_thrd.autovacuum_cxt.AutoVacuumShmem->av_runningWorkers, &t_thrd.autovacuum_cxt.AutoVacuumShmem->av_runningWorkers, offsetof(WorkerInfoData, wi_links)); @@ -1535,8 +1621,8 @@ static void autovac_balance_cost(void) * in these calculations, let's be sure we don't ever set * cost_limit to more than the base value. */ - worker->wi_cost_limit = Max(Min(limit, worker->wi_cost_limit_base), 1); - + worker->wi_cost_limit = Max(Min(limit, worker->wi_cost_limit_base), 1); // 纭繚鎴愭湰闄愬埗涓嶄綆浜 1锛屼篃涓嶉珮浜庡熀鍑嗗 + // 璁板綍鏃ュ織浠ヤ究璋冭瘯 AUTOVAC_LOG(LOG, "autovac_balance_cost(pid=%lu db=%u, rel=%u, parent=%u, cost_limit=%d, " "cost_limit_base=%d, cost_delay=%d)", worker->wi_proc->pid, worker->wi_dboid, worker->wi_tableoid, worker->wi_parentoid, @@ -1570,7 +1656,7 @@ static List* get_database_list(void) MemoryContext resultcxt; /* This is the context that we will allocate our output data in */ - resultcxt = CurrentMemoryContext; + resultcxt = CurrentMemoryContext;- // 鑾峰彇褰撳墠鍐呭瓨涓婁笅鏂 /* * Start a transaction so we can access pg_database, and get a snapshot. @@ -1579,15 +1665,17 @@ static List* get_database_list(void) * for anything that reads heap pages, because HOT may decide to prune * them even if the process doesn't attempt to modify any tuples.) */ - StartTransactionCommand(); - (void)GetTransactionSnapshot(); + StartTransactionCommand(); // 寮濮嬩竴涓簨鍔 + (void)GetTransactionSnapshot(); // 鑾峰彇浜嬪姟蹇収 - rel = heap_open(DatabaseRelationId, AccessShareLock); + // 鎵撳紑 pg_database 琛紝骞跺紑濮嬫壂鎻 + rel = heap_open(DatabaseRelationId, AccessShareLock); scan = tableam_scan_begin(rel, SnapshotNow, 0, NULL); + // 閬嶅巻 pg_database 琛ㄤ腑鐨勬瘡涓褰 while (HeapTupleIsValid(tup = (HeapTuple) tableam_scan_getnexttuple(scan, ForwardScanDirection))) { - Form_pg_database pgdatabase = (Form_pg_database)GETSTRUCT(tup); - avw_dbase* avdb = NULL; + Form_pg_database pgdatabase = (Form_pg_database)GETSTRUCT(tup); // 鑾峰彇鏁版嵁搴撹褰曠殑缁撴瀯浣 + avw_dbase* avdb = NULL; // 鍒嗛厤鍐呭瓨鏉ュ瓨鍌 avw_dbase 缁撴瀯浣 MemoryContext oldcxt; /* @@ -1596,13 +1684,15 @@ static List* get_database_list(void) * context at the end, so that leaky things like heap_getnext() are * not called in a potentially long-lived context. */ - oldcxt = MemoryContextSwitchTo(resultcxt); + oldcxt = MemoryContextSwitchTo(resultcxt); // 鍒囨崲鍒扮粨鏋滃唴瀛樹笂涓嬫枃 - avdb = (avw_dbase*)palloc(sizeof(avw_dbase)); + avdb = (avw_dbase*)palloc(sizeof(avw_dbase)); // 鍒嗛厤 avw_dbase 缁撴瀯浣撶殑鍐呭瓨 + // 灏嗘暟鎹簱鐨 OID 鍜屽悕绉颁繚瀛樺埌 avw_dbase 缁撴瀯浣 avdb->adw_datid = HeapTupleGetOid(tup); avdb->adw_name = pstrdup(NameStr(pgdatabase->datname)); + // 鑾峰彇鏁版嵁搴撶殑鍐荤粨浜嬪姟 ID bool isNull = false; TransactionId datfrozenxid; Datum xid64datum = heap_getattr(tup, Anum_pg_database_datfrozenxid64, RelationGetDescr(rel), &isNull); @@ -1615,34 +1705,41 @@ static List* get_database_list(void) } else datfrozenxid = DatumGetTransactionId(xid64datum); #ifndef ENABLE_MULTIPLE_NODES + // 鑾峰彇鏁版嵁搴撶殑鏈灏忓浜嬪姟 ID Datum mxidDatum = heap_getattr(tup, Anum_pg_database_datminmxid, RelationGetDescr(rel), &isNull); MultiXactId datminmxid = isNull ? FirstMultiXactId : DatumGetTransactionId(mxidDatum); avdb->adw_frozenmulti = datminmxid; #endif + // 灏嗗喕缁撲簨鍔 ID 鍜岀浉鍏充俊鎭繚瀛樺埌 avw_dbase 缁撴瀯浣 avdb->adw_frozenxid = datfrozenxid; /* this gets set later: */ avdb->adw_entry = NULL; + // 灏 avw_dbase 缁撴瀯浣撴坊鍔犲埌鏁版嵁搴撳垪琛ㄤ腑 dblist = lappend(dblist, avdb); - (void)MemoryContextSwitchTo(oldcxt); + (void)MemoryContextSwitchTo(oldcxt);// 鍒囨崲鍥炲師鏉ョ殑鍐呭瓨涓婁笅鏂 } - tableam_scan_end(scan); + // 缁撴潫鎵弿骞跺叧闂 pg_database 琛 + tableam_scan_end(scan); heap_close(rel, AccessShareLock); - CommitTransactionCommand(); + CommitTransactionCommand(); // 鎻愪氦浜嬪姟 - return dblist; + return dblist; // 杩斿洖鏋勫缓鐨勬暟鎹簱鍒楄〃 } +// 瀹忓畾涔 /* * 1. just support global statistic since local statistic is gradually abandoned * 2. just support traditional-sample analyze since percent-sample analyze is too inefficient */ +// 鍒ゆ柇鏄惁鎵ц鍒嗘瀽鎿嶄綔 #define DO_ANALYZE \ ((AUTOVACUUM_DO_ANALYZE_VACUUM == u_sess->attr.attr_storage.autovacuum_mode || \ AUTOVACUUM_DO_ANALYZE == u_sess->attr.attr_storage.autovacuum_mode) && \ u_sess->attr.attr_sql.enable_global_stats && 0 < default_statistics_target) +// 鍒ゆ柇鏄惁鎵ц娓呯悊鎿嶄綔 #define DO_VACUUM \ (AUTOVACUUM_DO_ANALYZE_VACUUM == u_sess->attr.attr_storage.autovacuum_mode || \ AUTOVACUUM_DO_VACUUM == u_sess->attr.attr_storage.autovacuum_mode) @@ -1650,19 +1747,21 @@ static List* get_database_list(void) /* * check if the relation can do auto-analyze or auto-vacuum */ +// 鍒ゆ柇涓涓叧绯绘槸鍚︽敮鎸佽嚜鍔ㄥ垎鏋愶紙ANALYZE锛夊拰鑷姩娓呯悊锛圴ACUUM锛夛紝浠ュ強鏄惁涓哄唴閮ㄥ叧绯 void relation_support_autoavac(HeapTuple tuple, bool* enable_analyze, bool* enable_vacuum, bool* is_internal_relation) { - bytea* relopts = NULL; - Form_pg_class classForm = (Form_pg_class)GETSTRUCT(tuple); + bytea* relopts = NULL; // 瀛樺偍鍏崇郴鐨勯夐」 + Form_pg_class classForm = (Form_pg_class)GETSTRUCT(tuple); // 鍏崇郴鐨勫厓缁勬暟鎹粨鏋 Assert(PointerIsValid(enable_analyze)); Assert(PointerIsValid(enable_vacuum)); - *enable_analyze = false; - *enable_vacuum = false; - *is_internal_relation = false; + *enable_analyze = false; // 榛樿绂佺敤 ANALYZE 鎿嶄綔 + *enable_vacuum = false; // 榛樿绂佺敤 VACUUM 鎿嶄綔 + *is_internal_relation = false; // 榛樿涓嶆槸鍐呴儴鍏崇郴 /* skip all autovac actions */ + // 濡傛灉涓嶅湪鍗忚皟鍣ㄤ笂鎴栬呰嚜鍔ㄦ竻鐞嗗畧鎶よ繘绋嬭绂佺敤锛屽垯璺宠繃鎵鏈夎嚜鍔ㄦ竻鐞嗘搷浣 if (IS_PGXC_COORDINATOR && !u_sess->attr.attr_storage.autovacuum_start_daemon) return; @@ -1670,27 +1769,31 @@ void relation_support_autoavac(HeapTuple tuple, bool* enable_analyze, bool* enab * 1. never analyze internal table since we never select them directly * 2. just analyze row/colume orientation table since analyze hdfs table is too inefficient */ + // 鏍规嵁鍏崇郴閫夐」鍜岀被鍨嬪垽鏂槸鍚﹀惎鐢 ANALYZE 鍜 VACUUM 鎿嶄綔 relopts = extractRelOptions(tuple, GetDefaultPgClassDesc(), InvalidOid); if (StdRelOptGetInternalMask(relopts)) { /* do nothing, but set is_internal_relation to be true */ - *is_internal_relation = true; + *is_internal_relation = true; //瀵逛簬鍐呴儴琛紝灏 is_internal_relation 璁剧疆涓 true /* if it is mlog or matmap then set it */ + // 濡傛灉鏄/鍒楀畾鍚戣〃涓旀槸 mlog 鎴 matmap锛屽垯鍚敤 ANALYZE 鍜 VACUUM 鎿嶄綔 if (StdRelOptIsRowStore(relopts) && (ISMATMAP(classForm->relname.data) || ISMLOG(classForm->relname.data))) { *enable_analyze = true; *enable_vacuum = true; } - } else if (StdRelOptIsColStore(relopts)) { + } else if (StdRelOptIsColStore(relopts)) { // 鍒楀畾鍚戣〃 *enable_analyze = true; - } else if (StdRelOptIsRowStore(relopts)) { + } else if (StdRelOptIsRowStore(relopts)) { //琛屽畾鍚戣〃 *enable_analyze = true; *enable_vacuum = true; } + // 瀵逛簬缁熻淇℃伅琛ㄣ乀OAST 琛紝鎴栧綋 DO_ANALYZE 涓 false 鏃讹紝绂佺敤 ANALYZE 鎿嶄綔 if (StatisticRelationId == HeapTupleGetOid(tuple) || RELKIND_TOASTVALUE == classForm->relkind || !DO_ANALYZE) { *enable_analyze = false; } + // 褰 DO_VACUUM 涓 false 鏃讹紝绂佺敤 VACUUM 鎿嶄綔 if (!DO_VACUUM) { *enable_vacuum = false; } @@ -1702,60 +1805,74 @@ void relation_support_autoavac(HeapTuple tuple, bool* enable_analyze, bool* enab * 1. data in temp/unlogged is short-lived, so do nothing for temp/unlogged table * 2. foreign table dose not have stat info, so just support ordinary table */ + // 鍒ゆ柇鍏崇郴鏄惁涓轰笉鏀寔鐨勭被鍨嬶紝鑻ユ槸鍒欑鐢ㄧ浉鍏虫搷浣 if (RELPERSISTENCE_PERMANENT != classForm->relpersistence || RELKIND_RELATION != classForm->relkind) { *enable_analyze = false; *is_internal_relation = false; } + // 瀵逛簬闈炴櫘閫氳〃锛岀鐢 VACUUM 鎿嶄綔 if (RELKIND_RELATION != classForm->relkind) { *enable_vacuum = false; } } +// 鍒ゆ柇鏄惁鍏佽鑷姩鎵ц ANALYZE 鎿嶄綔 bool allow_autoanalyze(HeapTuple tuple) { bool enable_analyze = false; bool enable_vacuum = false; bool is_internal_relation = false; + // 璋冪敤鍑芥暟鍒ゆ柇鏄惁鏀寔鑷姩鎵ц ANALYZE 鎿嶄綔 relation_support_autoavac(tuple, &enable_analyze, &enable_vacuum, &is_internal_relation); return enable_analyze; } +// 灏嗗簲鐢ㄧ▼搴忓悕绉版坊鍔犲埌杩炴帴姹犲弬鏁颁腑 static void AddApplicationNameToPoolerParams() { if (IS_PGXC_COORDINATOR && !IsConnFromCoord() && IsAutoVacuumWorkerProcess()) { StringInfoData str; + // 鍒濆鍖栦竴涓敤浜庢瀯寤哄瓧绗︿覆鐨勬暟鎹粨鏋 initStringInfo(&str); + // 鍚戝瓧绗︿覆涓坊鍔犺缃簲鐢ㄧ▼搴忓悕绉扮殑 SQL 璇彞 appendStringInfo(&str, "SET application_name = '%s';", AUTO_VACUUM_WORKER); + // 灏嗗簲鐢ㄧ▼搴忓悕绉版坊鍔犲埌杩炴帴姹犱細璇濆弬鏁颁腑 (void)register_pooler_session_param("application_name", str.data, POOL_CMD_GLOBAL_SET); - pfree_ext(str.data); + pfree_ext(str.data); // 閲婃斁瀛楃涓叉暟鎹粨鏋勬墍鍗犵敤鐨勫唴瀛 } } +// 浠庤繛鎺ユ睜鍙傛暟涓垹闄ゅ簲鐢ㄧ▼搴忓悕绉 static void DeleteApplicationNameFromPoolerParams() { if (IS_PGXC_COORDINATOR && !IsConnFromCoord() && IsAutoVacuumWorkerProcess()) { + // 浠庤繛鎺ユ睜浼氳瘽鍙傛暟涓垹闄ゅ簲鐢ㄧ▼搴忓悕绉 delete_pooler_session_params("application_name"); } } +// 浠庢墍鏈夋暟鎹妭鐐硅幏鍙栧叏灞鑷姩VACUUM淇℃伅 static void fetch_global_autovac_info() { - PgStat_StatTabKey tablekey; - bool connected = false; - StringInfoData buf; + PgStat_StatTabKey tablekey; // 鐢ㄤ簬缁熻淇℃伅琛ㄧ殑閿 + bool connected = false; // 琛ㄧず鏄惁宸茶繛鎺ュ埌SPI + StringInfoData buf; // 鐢ㄤ簬鏋勫缓SQL鏌ヨ璇彞鐨勫瓧绗︿覆缂撳啿鍖 /* * Dose not fetch global stat info from all datanodes if * 1. autovacuum = off * 2. autovacuum = on and u_sess->attr.attr_storage.autovacuum_mode = none */ + //濡傛灉autovacuum涓哄叧闂姸鎬侊紝鎴栬卆utovacuum涓烘墦寮浣唘_sess->attr.attr_storage.autovacuum_mode涓簄one妯″紡 if (!u_sess->attr.attr_storage.autovacuum_start_daemon || AUTOVACUUM_DO_NONE == u_sess->attr.attr_storage.autovacuum_mode) - return; + return; // 涓嶄粠鎵鏈夋暟鎹妭鐐硅幏鍙栧叏灞缁熻淇℃伅 - initStringInfo(&buf); + initStringInfo(&buf); // 鍒濆鍖栧瓧绗︿覆缂撳啿鍖 + // 鏍规嵁涓嶅悓鎯呭喌鏋勫缓SQL鏌ヨ璇彞 if (DO_VACUUM) { + // 鏋勫缓鎵цVACUUM鎿嶄綔鐨凷QL璇彞 appendStringInfo(&buf, "with f as (select nspname, relname, partname, sum(n_dead_tuples) as n_dead_tuples, " "sum(n_live_tuples) as n_live_tuples, sum(changes_since_analyze) as changes_since_analyze, " "count(1) as count from pg_total_autovac_tuples(%s) group by nspname, relname, partname), " @@ -1773,6 +1890,7 @@ static void fetch_global_autovac_info() "from t inner join f on (t.nspname = f.nspname and t.relname = f.relname " "and (t.partname = f.partname or (t.partname is null and f.partname is null))) ", "false"); } else { + // 鏋勫缓鎵цANALYZE鎿嶄綔鐨凷QL璇彞 appendStringInfo(&buf, "with f as (select nspname, relname, sum(n_dead_tuples) as n_dead_tuples, " "sum(changes_since_analyze) as changes_since_analyze, count(1) as count " "from pg_total_autovac_tuples(%s) group by nspname, relname), t as(SELECT c.oid as relid, " @@ -1786,29 +1904,36 @@ static void fetch_global_autovac_info() "end)::bigint as changes_since_analyze " "from t inner join f on (t.nspname = f.nspname and t.relname = f.relname) ", "true"); } - + // 鎵撳嵃鏋勫缓鐨凷QL璇彞锛岀敤浜庤皟璇 AUTOVAC_LOG(DEBUG2, "FETCH GLOABLE AUTOVAC INFO STRING: %s", buf.data); + // 寮鍚揩鐓э紝浠ヤ究鎵ц鏌ヨ PushActiveSnapshot(GetTransactionSnapshot()); + // 灏嗗簲鐢ㄧ▼搴忓悕绉版坊鍔犲埌杩炴帴姹犲弬鏁颁腑 AddApplicationNameToPoolerParams(); + // 寮傚父澶勭悊锛屾墽琛屾煡璇㈡搷浣 PG_TRY(); { DEBUG_MOD_START_TIMER(MOD_AUTOVAC); + // 灏濊瘯杩炴帴鍒癝PI SPI_STACK_LOG("connect", NULL, NULL); if (SPI_OK_CONNECT != SPI_connect()) { ereport(ERROR, (errcode(ERRCODE_OPERATE_FAILED), errmsg("Unable to connect to execute internal query."))); } connected = true; DEBUG_MOD_STOP_TIMER(MOD_AUTOVAC, "AUTOVAC TIMER: build SPI connect"); - + // 鎵цSQL鏌ヨ璇彞 if (SPI_OK_SELECT != SPI_execute(buf.data, true, 0)) { ereport(ERROR, (errcode(ERRCODE_DATA_EXCEPTION), errmsg("fail to execute query"))); } DEBUG_MOD_STOP_TIMER(MOD_AUTOVAC, "AUTOVAC TIMER: execte SQL to fetch global autovac info"); + // 閲婃斁瀛楃涓茬紦鍐插尯鐨勫唴瀛 pfree_ext(buf.data); + // 澶勭悊鏌ヨ缁撴灉锛屽皢缁撴灉瀛樺偍鍒拌嚜鍔╒ACUUM淇℃伅鍝堝笇琛ㄤ腑 for (uint32 i = 0; i < SPI_processed; i++) { + // 浠庢煡璇㈢粨鏋滀腑鎻愬彇淇℃伅 Oid relid; Oid partid; int64 n_dead_tuples = 0; @@ -1818,13 +1943,15 @@ static void fetch_global_autovac_info() bool partid_isnull = true; avw_info* entry = NULL; - relid = DatumGetObjectId(SPI_getbinval(SPI_tuptable->vals[i], SPI_tuptable->tupdesc, 1, &isnull)); - partid = DatumGetObjectId(SPI_getbinval(SPI_tuptable->vals[i], SPI_tuptable->tupdesc, 2, &partid_isnull)); - n_dead_tuples = DatumGetInt64(SPI_getbinval(SPI_tuptable->vals[i], SPI_tuptable->tupdesc, 3, &isnull)); - n_live_tuples = DatumGetInt64(SPI_getbinval(SPI_tuptable->vals[i], SPI_tuptable->tupdesc, 4, &isnull)); + // 鎻愬彇淇℃伅 + relid = DatumGetObjectId(SPI_getbinval(SPI_tuptable->vals[i], SPI_tuptable->tupdesc, 1, &isnull)); // 鍏崇郴鐨勫敮涓鏍囪瘑绗 + partid = DatumGetObjectId(SPI_getbinval(SPI_tuptable->vals[i], SPI_tuptable->tupdesc, 2, &partid_isnull)); // 鍒嗗尯鐨勫敮涓鏍囪瘑绗 + n_dead_tuples = DatumGetInt64(SPI_getbinval(SPI_tuptable->vals[i], SPI_tuptable->tupdesc, 3, &isnull)); // 鑷笂娆″垎鏋愪互鏉ユ鍏冪粍鐨勬暟閲 + n_live_tuples = DatumGetInt64(SPI_getbinval(SPI_tuptable->vals[i], SPI_tuptable->tupdesc, 4, &isnull)); // 娲诲厓缁勭殑鏁伴噺 changes_since_analyze = - DatumGetInt64(SPI_getbinval(SPI_tuptable->vals[i], SPI_tuptable->tupdesc, 5, &isnull)); + DatumGetInt64(SPI_getbinval(SPI_tuptable->vals[i], SPI_tuptable->tupdesc, 5, &isnull)); // 鑷笂娆″垎鏋愪互鏉ョ殑鍙樺寲娆℃暟 + // 鏋勫缓鑷姩VACUUM淇℃伅鐨勯敭 if (partid_isnull) { tablekey.tableid = relid; tablekey.statFlag = InvalidOid; @@ -1832,37 +1959,51 @@ static void fetch_global_autovac_info() tablekey.tableid = partid; tablekey.statFlag = relid; } - + // 鍦ㄨ嚜鍔ㄥ寲VACUUM缁熻淇℃伅鍝堝笇琛ㄤ腑鏌ユ壘鎴栨彃鍏ヤ竴涓潯鐩紝key鏄痶ablekey + // 杩斿洖鐨別ntry鏄壘鍒扮殑鐜版湁鏉$洰鎴栨柊鎻掑叆鐨勬潯鐩 entry = (avw_info*)hash_search(t_thrd.autovacuum_cxt.pgStatAutoVacInfo, (void*)(&tablekey), HASH_ENTER, NULL); + // 灏嗘彁鍙栫殑淇℃伅濉厖鍒癳ntry涓 entry->n_dead_tuples = n_dead_tuples; entry->n_live_tuples = n_live_tuples; entry->changes_since_analyze = changes_since_analyze; } + // 鍋滄AUTOVAC璁℃椂鍣ㄥ苟璁板綍澶勭悊鐨凷PI鍏冪粍鏁伴噺 DEBUG_MOD_STOP_TIMER(MOD_AUTOVAC, "AUTOVAC TIMER: process %u SPI tuples", SPI_processed); + // 鏂紑SPI杩炴帴锛屽皢connected鏍囪涓篺alse connected = false; + // 璁板綍SPI鎿嶄綔鐨勬棩蹇楋紝琛ㄧず鎿嶄綔宸插畬鎴 SPI_STACK_LOG("finish", NULL, NULL); + // 瀹屾垚SPI鎿嶄綔鍚庯紝鍏抽棴SPI杩炴帴骞舵鏌ユ槸鍚︽垚鍔熷叧闂 if (SPI_OK_FINISH != SPI_finish()) { ereport(ERROR, (errcode(ERRCODE_OPERATE_FAILED), errmsg("SPI_finish failed"))); } + // 寮瑰嚭蹇収锛屾仮澶嶄簨鍔$殑蹇収鐘舵 PopActiveSnapshot(); + // 娓呯┖浼氳瘽鐨勮皟璇曟煡璇D u_sess->debug_query_id = 0; } PG_CATCH(); /* Clean up in case of error. */ { - DeleteApplicationNameFromPoolerParams(); + DeleteApplicationNameFromPoolerParams(); // 鍙戠敓寮傚父鏃讹紝娓呴櫎杩炴帴姹犱腑鐨勫簲鐢ㄧ▼搴忓悕绉板弬鏁 + // 濡傛灉涔嬪墠寤虹珛浜哠PI杩炴帴锛屽嵆connected涓簍rue锛屽垯瀹屾垚SPI杩炴帴骞惰褰曟搷浣滄棩蹇 if (connected) { SPI_STACK_LOG("finish", NULL, NULL); SPI_finish(); } /* Carry on with error handling. */ + // 寮瑰嚭涔嬪墠蹇収锛屾仮澶嶄簨鍔$殑蹇収鐘舵 PopActiveSnapshot(); + // 閲嶆柊鎶涘嚭鎹曡幏鐨勫紓甯革紝灏嗗叾浼犻掔粰涓婂眰鐨勫紓甯稿鐞 PG_RE_THROW(); + // 娓呯┖浼氳瘽鐨勮皟璇曟煡璇D u_sess->debug_query_id = 0; } + // 缁撴潫寮傚父鎹曡幏鐨勪唬鐮佸潡锛岀‘淇濆紓甯稿鐞嗛昏緫鐨勫畬鎴 PG_END_TRY(); + // 鏃犺鏄惁鍙戠敓寮傚父锛屾渶缁堥兘瑕佸垹闄よ繛鎺ユ睜涓殑搴旂敤绋嬪簭鍚嶇О鍙傛暟 DeleteApplicationNameFromPoolerParams(); } @@ -1874,33 +2015,33 @@ static void fetch_global_autovac_info() */ static void do_autovacuum(void) { - Relation classRel = NULL; - HeapTuple tuple = NULL; - TableScanDesc relScan = NULL; - Form_pg_database dbForm = NULL; - List* table_oids = NIL; - HASHCTL partitioned_tables_ctl; - HTAB* partitioned_tables_map = NULL; - HASHCTL table_relopt_ctl; - HTAB* table_relopt_map = NULL; - HASHCTL toast_table_ctl; - HTAB* toast_table_map = NULL; - ListCell* volatile cell = NULL; - PgStat_StatDBEntry* shared = NULL; - PgStat_StatDBEntry* dbentry = NULL; - BufferAccessStrategy bstrategy; - HASHCTL avinfo_ctl; - bool datallowconn = true; - bool local_autovacuum = true; /* just do autovacuum in current instance */ - bool freeze_autovacuum = false; /* just do vacuum since need freeze the old tuple */ - bool is_internal_relation = false; /* whether current relation is an internal relation */ - ScanKeyData key[1]; - TableScanDesc partScan; - Relation partRel; - HeapTuple partTuple; - TupleDesc pg_class_desc; - vacuum_object* vacObj = NULL; - errno_t rc = EOK; + Relation classRel = NULL; // pg_class 绯荤粺鐩綍鐨 Relation + HeapTuple tuple = NULL; // 浠 pg_class 涓幏鍙栫殑鍏冪粍 + TableScanDesc relScan = NULL; // 琛ㄦ壂鎻忔弿杩扮 + Form_pg_database dbForm = NULL; // 浠 pg_database 绯荤粺鐩綍鑾峰彇鐨勬暟鎹簱淇℃伅 + List* table_oids = NIL; // 鏁版嵁搴撲腑琛ㄧ殑 OID 鍒楄〃 + HASHCTL partitioned_tables_ctl; // 鐢ㄤ簬鍒嗗尯琛ㄧ殑鍝堝笇琛ㄦ帶鍒剁粨鏋 + HTAB* partitioned_tables_map = NULL; // 鐢ㄤ簬璺熻釜鍒嗗尯琛ㄧ殑鍝堝笇琛 + HASHCTL table_relopt_ctl; // 鐢ㄤ簬瀛樺偍鍏崇郴閫夐」鐨勫搱甯岃〃鎺у埗缁撴瀯 + HTAB* table_relopt_map = NULL; // 鐢ㄤ簬瀛樺偍鍏崇郴閫夐」鐨勫搱甯岃〃 + HASHCTL toast_table_ctl; // 鐢ㄤ簬 TOAST 琛ㄧ殑鍝堝笇琛ㄦ帶鍒剁粨鏋 + HTAB* toast_table_map = NULL; // 鐢ㄤ簬璺熻釜 TOAST 琛ㄧ殑鍝堝笇琛 + ListCell* volatile cell = NULL; // 鐢ㄤ簬閬嶅巻琛 OID 鍒楄〃鐨勫崟鍏 + PgStat_StatDBEntry* shared = NULL; // 鍏变韩鏁版嵁搴撶粺璁′俊鎭潯鐩 + PgStat_StatDBEntry* dbentry = NULL; // 鏁版嵁搴撶粺璁′俊鎭潯鐩 + BufferAccessStrategy bstrategy; // 鐢ㄤ簬鍫嗘壂鎻忕殑缂撳啿鍖鸿闂瓥鐣 + HASHCTL avinfo_ctl; // 鐢ㄤ簬璺熻釜娓呯悊瀵硅薄鐨勫搱甯岃〃鎺у埗缁撴瀯 + bool datallowconn = true; // 琛ㄧず鏄惁鍏佽杩炴帴鍒版暟鎹簱 + bool local_autovacuum = true; // 琛ㄧず鏄惁浠呭湪褰撳墠瀹炰緥鎵ц鑷姩娓呯悊 + bool freeze_autovacuum = false; // 琛ㄧず鏄惁浠呮墽琛屽甫鍐荤粨鎿嶄綔鐨勬竻鐞 + bool is_internal_relation = false; // 琛ㄧず褰撳墠鍏崇郴鏄惁涓哄唴閮ㄧ郴缁熷叧绯 + ScanKeyData key[1]; // 琛ㄦ壂鎻忕殑鎵弿閿 + TableScanDesc partScan; // 鐢ㄤ簬鍒嗗尯琛ㄧ殑琛ㄦ壂鎻忔弿杩扮 + Relation partRel; // 鍒嗗尯琛ㄧ殑鍏崇郴 + HeapTuple partTuple; // 浠庡垎鍖鸿〃鎵弿涓幏鍙栫殑鍏冪粍 + TupleDesc pg_class_desc; // pg_class 绯荤粺鐩綍鐨勫厓缁勬弿杩 + vacuum_object* vacObj = NULL; // 鐢ㄤ簬璺熻釜娓呯悊淇℃伅鐨勭粨鏋勪綋 + errno_t rc = EOK; // 鐢ㄤ簬瀹夊叏 C 搴撳嚱鏁扮殑閿欒浠g爜 /* * StartTransactionCommand and CommitTransactionCommand will automatically @@ -1933,21 +2074,29 @@ static void do_autovacuum(void) * Find the pg_database entry and select the default freeze ages. We use * zero in template and nonconnectable databases, else the system-wide * default. - */ + */銆 + // 鍦ㄧ郴缁熺紦瀛樹腑鎼滅储鎸囧畾鏁版嵁搴撶殑鍏冪粍 tuple = SearchSysCache1(DATABASEOID, ObjectIdGetDatum(u_sess->proc_cxt.MyDatabaseId)); + // 濡傛灉鎵句笉鍒版湁鏁堢殑鍏冪粍锛屾姤鍛婇敊璇 if (!HeapTupleIsValid(tuple)) ereport(ERROR, (errcode(ERRCODE_CACHE_LOOKUP_FAILED), errmsg("cache lookup failed for database %u", u_sess->proc_cxt.MyDatabaseId))); + // 鑾峰彇 pg_database 鍏冪粍涓殑鏁版嵁缁撴瀯 dbForm = (Form_pg_database)GETSTRUCT(tuple); + // 鑾峰彇鏁版嵁搴撳睘鎬 datallowconn锛堟槸鍚﹀厑璁歌繛鎺ワ級 datallowconn = dbForm->datallowconn; + // 鏍规嵁鏁版嵁搴撴槸鍚︽槸妯℃澘鏁版嵁搴撴垨涓嶅彲杩炴帴鐨勬暟鎹簱鏉ヨ缃粯璁ょ殑鍐荤粨骞撮緞 if (dbForm->datistemplate || !dbForm->datallowconn) { + // 瀵逛簬妯℃澘鏁版嵁搴撴垨涓嶅彲杩炴帴鐨勬暟鎹簱锛屽皢榛樿鍐荤粨骞撮緞璁剧疆涓洪浂 t_thrd.autovacuum_cxt.default_freeze_min_age = 0; t_thrd.autovacuum_cxt.default_freeze_table_age = 0; } else { + // 鍚﹀垯锛屼娇鐢ㄧ郴缁熼厤缃殑榛樿鍊间綔涓洪粯璁ゅ喕缁撳勾榫 t_thrd.autovacuum_cxt.default_freeze_min_age = u_sess->attr.attr_storage.vacuum_freeze_min_age; t_thrd.autovacuum_cxt.default_freeze_table_age = u_sess->attr.attr_storage.vacuum_freeze_table_age; } + // 閲婃斁鏌ヨ鍒扮殑 pg_database 鍏冪粍 ReleaseSysCache(tuple); #ifdef PGXC @@ -1957,6 +2106,12 @@ static void do_autovacuum(void) return; } + /* + 鏍规嵁鏁版嵁搴撶殑灞炴у拰鐜锛屽喅瀹氫簡鑷姩`VACUUM`杩囩▼鐨勬墽琛岀瓥鐣: + - 濡傛灉鏁版嵁搴撲笉鍏佽杩炴帴鎴栬呮槸鍗曡妭鐐规ā寮忥紝鍒欒嚜鍔╒ACUUM鐨勬湰鍦版ā寮忓紑鍚紝鍐荤粨鎿嶄綔鐨勮嚜鍔╒ACUUM鍏抽棴 + - 濡傛灉鏄垎甯冨紡鍗忚皟鍣ㄤ笖鏄腑澶崗璋冨櫒锛屽垯鏈湴妯″紡鐨勮嚜鍔╒ACUUM鍏抽棴锛屽喕缁撴搷浣滅殑鑷姩VACUUM鍏抽棴 + - 瀵逛簬鍏朵粬鎯呭喌锛屾湰鍦版ā寮忕殑鑷姩VACUUM寮鍚紝鍐荤粨鎿嶄綔鐨勮嚜鍔╒ACUUM寮鍚 + */ if (false == datallowconn || IS_SINGLE_NODE) { /* for database that refuses to accpet connections, for single node mode, autovacuum remains the same as PG */ local_autovacuum = true; @@ -1973,40 +2128,52 @@ static void do_autovacuum(void) #endif /* StartTransactionCommand changed elsewhere */ + // 鍒囨崲鍒拌嚜鍔╒ACUUM鍐呭瓨涓婁笅鏂囦互渚夸簬鍐呭瓨鍒嗛厤 (void)MemoryContextSwitchTo(t_thrd.autovacuum_cxt.AutovacMemCxt); + // 鍒濆鍖栬嚜鍔╒ACUUM淇℃伅鍝堝笇琛 t_thrd.autovacuum_cxt.pgStatAutoVacInfo = NULL; + // 濡傛灉鏄垎甯冨紡鍗忚皟鍣ㄤ笖涓嶆槸鏈湴鑷姩VACUUM锛屽垯杩涜浠ヤ笅鎿嶄綔 if (IS_PGXC_COORDINATOR && false == local_autovacuum) { + // 鍒濆鍖 avinfo_ctl 鍙橀噺 rc = memset_s(&avinfo_ctl, sizeof(avinfo_ctl), 0, sizeof(avinfo_ctl)); securec_check(rc, "", ""); + // 璁剧疆鍝堝笇琛ㄧ殑閿ぇ灏忋佹潯鐩ぇ灏忋佸唴瀛樹笂涓嬫枃鍜屽搱甯屽嚱鏁 avinfo_ctl.keysize = sizeof(PgStat_StatTabKey); avinfo_ctl.entrysize = sizeof(avw_info); avinfo_ctl.hcxt = t_thrd.autovacuum_cxt.AutovacMemCxt; avinfo_ctl.hash = tag_hash; + // 鍒涘缓鑷姩VACUUM淇℃伅鐨勫搱甯岃〃 t_thrd.autovacuum_cxt.pgStatAutoVacInfo = hash_create( "autovac information of user-define table", 512, &avinfo_ctl, HASH_ELEM | HASH_FUNCTION | HASH_CONTEXT); + // 鑾峰彇鍏ㄥ眬鑷姩VACUUM淇℃伅 fetch_global_autovac_info(); } /* The database hash where pgstat keeps shared relations */ shared = pgstat_fetch_stat_dbentry(InvalidOid); + // 鎵撳紑 pg_class 鍏崇郴琛ㄥ苟鑾峰彇鍏舵弿杩扮 classRel = heap_open(RelationRelationId, AccessShareLock); /* create a copy so we can use it after closing pg_class */ + // 鍒涘缓鍓湰浠ヤ究鍦ㄥ叧闂 pg_class 鍚庣户缁娇鐢 pg_class_desc = CreateTupleDescCopy(RelationGetDescr(classRel)); /* create hash table for partitoned relid <-> autovac info mapping */ + // 涓哄垎鍖哄叧绯籌D <-> 鑷姩VACUUM 淇℃伅寤虹珛鍝堝笇琛 rc = memset_s(&partitioned_tables_ctl, sizeof(partitioned_tables_ctl), 0, sizeof(partitioned_tables_ctl)); securec_check(rc, "", ""); + // 璁剧疆鍝堝笇琛ㄧ殑閿ぇ灏忋佹潯鐩ぇ灏忓拰鍝堝笇鍑芥暟 partitioned_tables_ctl.keysize = sizeof(Oid); partitioned_tables_ctl.entrysize = sizeof(at_partitioned_table); partitioned_tables_ctl.hash = oid_hash; + // 鍒涘缓鍒嗗尯鍏崇郴ID <-> 鑷姩VACUUM 淇℃伅鐨勫搱甯岃〃 partitioned_tables_map = hash_create("partitioned relid to autovac info map", 10, &partitioned_tables_ctl, HASH_ELEM | HASH_FUNCTION); @@ -2014,20 +2181,24 @@ static void do_autovacuum(void) rc = memset_s(&toast_table_ctl, sizeof(toast_table_ctl), 0, sizeof(toast_table_ctl)); securec_check(rc, "", ""); + // 璁剧疆鍝堝笇琛ㄧ殑閿ぇ灏忋佹潯鐩ぇ灏忓拰鍝堝笇鍑芥暟 toast_table_ctl.keysize = sizeof(Oid); toast_table_ctl.entrysize = sizeof(av_toastid_mainid); toast_table_ctl.hash = oid_hash; + // 鍒涘缓 TOAST 鍏崇郴ID <-> 涓诲叧绯籌D 鐨勫搱甯岃〃 toast_table_map = hash_create("TOAST to main relid map", 100, &toast_table_ctl, HASH_ELEM | HASH_FUNCTION); /* create hash table for reloptions <-> main relid mapping */ rc = memset_s(&table_relopt_ctl, sizeof(table_relopt_ctl), 0, sizeof(table_relopt_ctl)); securec_check(rc, "", ""); + // 涓轰富鍏崇郴ID <-> 鍏崇郴閫夐」 寤虹珛鍝堝笇琛 table_relopt_ctl.keysize = sizeof(Oid); table_relopt_ctl.entrysize = sizeof(av_relation); table_relopt_ctl.hash = oid_hash; + // 鍒涘缓涓诲叧绯籌D <-> 鍏崇郴閫夐」 鐨勫搱甯岃〃 table_relopt_map = hash_create("main relid to rel options map", 100, &table_relopt_ctl, HASH_ELEM | HASH_FUNCTION); /* @@ -2049,6 +2220,7 @@ static void do_autovacuum(void) * On the first pass, we collect main tables to vacuum, and also the main * table relid to TOAST relid mapping. */ + // 绗竴閬嶆壂鎻- 涓昏〃/鍒嗗尯琛ㄧ殑澶勭悊锛氭敹闆嗕富琛ㄥ拰TOAST琛ㄤ箣闂寸殑鏄犲皠鍏崇郴浠ュ強闇瑕佽嚜鍔ㄦ竻鐞嗙殑涓昏〃锛 while ((tuple = (HeapTuple) tableam_scan_getnexttuple(relScan, ForwardScanDirection)) != NULL) { Form_pg_class classForm = (Form_pg_class)GETSTRUCT(tuple); PgStat_StatTabEntry* tabentry = NULL; @@ -2060,11 +2232,13 @@ static void do_autovacuum(void) bool enable_analyze = false; bool enable_vacuum = false; + // 濡傛灉鍏崇郴涓嶆槸鍏崇郴琛紙relations锛夋垨鐗╁寲瑙嗗浘锛坢aterialized views锛夛紝鍒欒烦杩 if (classForm->relkind != RELKIND_RELATION && classForm->relkind != RELKIND_MATVIEW) continue; /* We cannot safely process other backends' temp tables, so skip 'em. */ + // 璺宠繃鍏朵粬鍚庣浼氳瘽鐨勪复鏃惰〃 if (classForm->relpersistence == RELPERSISTENCE_TEMP || classForm->relpersistence == RELPERSISTENCE_GLOBAL_TEMP) { continue; @@ -2073,9 +2247,11 @@ static void do_autovacuum(void) /* Here we skipped relation_support_autoavac() and relation_needs_vacanalyze() checks * for Ustore partitioned tables */ + // 鍦 UStore 鍒嗗尯琛ㄧ殑鎯呭喌涓嬶紝璺宠繃 relation_support_autoavac() 鍜 relation_needs_vacanalyze() 妫鏌 bytea *rawRelopts = extractRelOptions(tuple, pg_class_desc, InvalidOid); if (rawRelopts != NULL && RelationIsTableAccessMethodUStoreType(rawRelopts) && isPartitionedRelation(classForm)) { + // 鍒涘缓涓涓 vacuum_object 缁撴瀯浣撳苟鍒濆鍖 vacObj = (vacuum_object*)palloc(sizeof(vacuum_object)); vacObj->tab_oid = relid; vacObj->parent_oid = InvalidOid; @@ -2085,6 +2261,7 @@ static void do_autovacuum(void) vacObj->need_freeze = false; vacObj->is_internal_relation = false; vacObj->flags = VACFLG_MAIN_PARTITION; + // 灏嗗綋鍓嶈〃娣诲姞鍒板緟澶勭悊琛ㄧ殑鍒楄〃涓 table_oids = lappend(table_oids, vacObj); continue; } @@ -2100,23 +2277,26 @@ static void do_autovacuum(void) relation_needs_vacanalyze(relid, relopts, classForm, tuple, tabentry, enable_analyze, enable_vacuum, false, &dovacuum, &doanalyze, &need_freeze); + // 濡傛灉澶勪簬鍐荤粨鑷姩VACUUM妯″紡锛屽垽鏂槸鍚﹂渶瑕佽繘琛孷ACUUM鎿嶄綔浠ュ強鏄惁闇瑕佸喕缁 if (freeze_autovacuum) { dovacuum = need_freeze; doanalyze = false; } /* relations that need work are added to table_oids */ + // 濡傛灉闇瑕佽繘琛孷ACUUM鎿嶄綔鎴栬呭垎鏋愭搷浣 if (dovacuum || doanalyze) { + // 鍒涘缓涓涓 vacuum_object 缁撴瀯浣撳苟鍒濆鍖 vacObj = (vacuum_object*)palloc(sizeof(vacuum_object)); - vacObj->tab_oid = relid; - vacObj->parent_oid = InvalidOid; - vacObj->dovacuum = dovacuum; - vacObj->dovacuum_toast = false; - vacObj->doanalyze = doanalyze; - vacObj->need_freeze = need_freeze; - vacObj->is_internal_relation = is_internal_relation; - vacObj->flags = (isPartitionedRelation(classForm) ? VACFLG_MAIN_PARTITION : VACFLG_SIMPLE_HEAP); - table_oids = lappend(table_oids, vacObj); + vacObj->tab_oid = relid; // 褰撳墠琛ㄧ殑瀵硅薄ID + vacObj->parent_oid = InvalidOid; // 鐖惰〃鐨勫璞D锛堝湪澶勭悊鍒嗗尯琛ㄦ椂鍙兘鏈夌敤锛 + vacObj->dovacuum = dovacuum; // 鏄惁闇瑕佽繘琛孷ACUUM鎿嶄綔 + vacObj->dovacuum_toast = false; // 鏄惁闇瑕佸 TOAST 琛ㄨ繘琛 VACUUM + vacObj->doanalyze = doanalyze; // 鏄惁闇瑕佽繘琛屽垎鏋愭搷浣 + vacObj->need_freeze = need_freeze; // 鏄惁闇瑕佸喕缁撴搷浣 + vacObj->is_internal_relation = is_internal_relation; // 褰撳墠鍏崇郴鏄惁鏄唴閮ㄥ叧绯 + vacObj->flags = (isPartitionedRelation(classForm) ? VACFLG_MAIN_PARTITION : VACFLG_SIMPLE_HEAP); // 琛ㄦ爣蹇 + table_oids = lappend(table_oids, vacObj); // 灏嗗綋鍓嶈〃娣诲姞鍒板緟澶勭悊琛ㄧ殑鍒楄〃涓 } /* @@ -2126,15 +2306,16 @@ static void do_autovacuum(void) * 2. to avoid recompute allowvacuum falg */ if (isPartitionedRelation(classForm)) { - bool found = false; - at_partitioned_table* ap_entry = NULL; + bool found = false; // 鏍囪鏄惁鍦ㄥ搱甯岃〃涓壘鍒版潯鐩 + at_partitioned_table* ap_entry = NULL; // 鎸囧悜鍒嗗尯琛ㄨ嚜鍔╒ACUUM淇℃伅鐨勬潯鐩 + // 鍦ㄥ垎鍖鸿〃鍒拌嚜鍔╒ACUUM淇℃伅鍝堝笇琛ㄤ腑鏌ユ壘鎴栨彃鍏ヤ竴涓潯鐩 ap_entry = (at_partitioned_table*)hash_search(partitioned_tables_map, &relid, HASH_ENTER, &found); - if (!found) { - ap_entry->at_allowvacuum = enable_vacuum; - ap_entry->at_doanalyze = doanalyze; - ap_entry->at_dovacuum = dovacuum; - ap_entry->at_needfreeze = need_freeze; + if (!found) { // 濡傛灉娌℃湁鎵惧埌宸插瓨鍦ㄧ殑鏉$洰锛岃鏄庢槸鏂版彃鍏ョ殑 + ap_entry->at_allowvacuum = enable_vacuum; // 璁板綍鏄惁鍏佽杩涜VACUUM鎿嶄綔鐨勬爣蹇 + ap_entry->at_doanalyze = doanalyze; // 璁板綍鏄惁闇瑕佽繘琛屽垎鏋愭搷浣滅殑鏍囧織 + ap_entry->at_dovacuum = dovacuum; // 璁板綍鏄惁闇瑕佽繘琛孷ACUUM鎿嶄綔鐨勬爣蹇 + ap_entry->at_needfreeze = need_freeze; // 璁板綍鏄惁闇瑕佽繘琛屽喕缁撴搷浣滅殑鏍囧織 } } @@ -2147,18 +2328,20 @@ static void do_autovacuum(void) * and save AutoVacOpts so we can use them when we deal with parttition */ if (OidIsValid(classForm->reltoastrelid) || isPartitionedRelation(classForm)) { - av_relation* ar_entry = NULL; - av_toastid_mainid* at_entry = NULL; - bool found = false; + av_relation* ar_entry = NULL; // 鎸囧悜淇濆瓨鍏宠仈淇℃伅鐨勬潯鐩 + av_toastid_mainid* at_entry = NULL; // 鎸囧悜淇濆瓨TOAST琛ㄤ笌涓昏〃鍏宠仈淇℃伅鐨勬潯鐩 + bool found = false; // 鏍囪鏄惁鍦ㄥ搱甯岃〃涓壘鍒版潯鐩 /* Skip partitioned table's toasttable, since partitioned table * is a logic table and has no data in physical files corresponding * to its relfilenode */ + // 濡傛灉涓嶆槸鍒嗗尯琛紝鍒欏鐞員OAST琛ㄧ殑鍏宠仈淇℃伅 if (!isPartitionedRelation(classForm)) { + // 鍦 toast_table_map 涓煡鎵炬垨鎻掑叆涓涓潯鐩 at_entry = (av_toastid_mainid*)hash_search(toast_table_map, &(classForm->reltoastrelid), HASH_ENTER, &found); - if (!found) { + if (!found) { // 濡傛灉娌℃湁鎵惧埌宸插瓨鍦ㄧ殑鏉$洰锛岃鏄庢槸鏂版彃鍏ョ殑 /* hash_search already filled in the key */ at_entry->at_relid = relid; at_entry->at_parentid = InvalidOid; @@ -2180,11 +2363,11 @@ static void do_autovacuum(void) * !!!Unlike PG, we pass relid instand of toastid to the hash table. */ ar_entry = (av_relation*)hash_search(table_relopt_map, &relid, HASH_ENTER, &found); - if (!found) { + if (!found) { // 濡傛灉娌℃湁鎵惧埌宸插瓨鍦ㄧ殑鏉$洰锛岃鏄庢槸鏂版彃鍏ョ殑 /* hash_search already filled in the key */ - ar_entry->ar_hasrelopts = false; + ar_entry->ar_hasrelopts = false; // 鏄惁鍏锋湁 reloptions 鐨勬爣蹇 if (relopts != NULL) { - ar_entry->ar_hasrelopts = true; + ar_entry->ar_hasrelopts = true; // 鏍囪鍏锋湁 reloptions rc = memcpy_s(&ar_entry->ar_reloptions, sizeof(AutoVacOpts), relopts, sizeof(AutoVacOpts)); securec_check(rc, "", ""); } @@ -2192,10 +2375,11 @@ static void do_autovacuum(void) } if (relopts != NULL) { - pfree_ext(relopts); + pfree_ext(relopts); // 閲婃斁涔嬪墠鎻愬彇鐨勮〃鐨 reloptions 鍐呭瓨 } } - tableam_scan_end(relScan); + tableam_scan_end(relScan); // 缁撴潫瀵 pg_class 鐨勬壂鎻忥紝閲婃斁鐩稿叧璧勬簮 + // 鍋滄璁℃椂鍣紝鍦ㄦ棩蹇椾腑璁板綍浠庡紑濮嬫壂鎻 pg_class 琛ㄥ埌缁撴潫鎵弿鐨勬椂闂达紝浠ュ府鍔╄皟璇曞拰鎬ц兘鍒嗘瀽銆 DEBUG_MOD_STOP_TIMER(MOD_AUTOVAC, "AUTOVAC TIMER: Scan pg_class to determine which tables to vacuum"); /* @@ -2203,54 +2387,58 @@ static void do_autovacuum(void) * and also the partitioned table relid to TOAST relid mapping. */ ScanKeyInit(&key[0], Anum_pg_partition_parttype, BTEqualStrategyNumber, F_CHAREQ, - CharGetDatum(PART_OBJ_TYPE_TABLE_PARTITION)); + CharGetDatum(PART_OBJ_TYPE_TABLE_PARTITION)); // 鍒濆鍖栨壂鎻忕殑鎼滅储閿紝鎸囧畾浜嗘悳绱 pg_partition 琛 - partRel = heap_open(PartitionRelationId, AccessShareLock); - partScan = tableam_scan_begin(partRel, SnapshotNow, 1, key); + partRel = heap_open(PartitionRelationId, AccessShareLock); // 鎵撳紑 pg_partition 琛 + partScan = tableam_scan_begin(partRel, SnapshotNow, 1, key); // 寮濮嬪 pg_partition 杩涜鎵弿 while (NULL != (partTuple = (HeapTuple) tableam_scan_getnexttuple(partScan, ForwardScanDirection))) { - Form_pg_partition partForm = (Form_pg_partition)GETSTRUCT(partTuple); - PgStat_StatTabEntry* tabentry = NULL; - AutoVacOpts* relopts = NULL; - bool dovacuum = false; - bool doanalyze = false; - bool need_freeze = false; - Oid partOid; - bool found = false; - av_relation* ar_hentry = NULL; - at_partitioned_table* ap_entry = NULL; + Form_pg_partition partForm = (Form_pg_partition)GETSTRUCT(partTuple); // 鑾峰彇 pg_partition 涓殑鏁版嵁 + PgStat_StatTabEntry* tabentry = NULL; // 鐢ㄤ簬缁熻淇℃伅 + AutoVacOpts* relopts = NULL; // 鑷姩娓呯悊閫夐」 + bool dovacuum = false; // 鏄惁闇瑕佹墽琛岃嚜鍔ㄦ竻鐞嗘搷浣 + bool doanalyze = false; // 鏄惁闇瑕佹墽琛岃嚜鍔ㄥ垎鏋愭搷浣 + bool need_freeze = false; // 鏄惁闇瑕佽繘琛屽喕缁撴搷浣 + Oid partOid; // 鍒嗗尯琛ㄧ殑 OID + bool found = false; // 鏍囪鏄惁鍦ㄥ搱甯岃〃涓壘鍒板搴旈」 + av_relation* ar_hentry = NULL; // 涓昏〃鐨勫叧鑱斿叧绯讳俊鎭 + at_partitioned_table* ap_entry = NULL; // 鍒嗗尯琛ㄧ殑鑷姩娓呯悊淇℃伅 /* * 'found = false' means partitioned table do autovac on other coordiantor * coordiantor that analyze table partition is consistent with the coordiantor * that analyze partition table. */ + // 閫氳繃涓昏〃鐨 parentid 鎵惧埌涓昏〃鐨勫叧鑱斿叧绯讳俊鎭 ar_hentry = (av_relation*)hash_search(table_relopt_map, &(partForm->parentid), HASH_FIND, &found); if (!found) - continue; + continue;// 鑻ユ湭鎵惧埌涓昏〃鐨勫叧鑱斿叧绯讳俊鎭紝缁х画涓嬩竴娆″惊鐜 - if (ar_hentry->ar_hasrelopts) + if (ar_hentry->ar_hasrelopts) // 濡傛灉涓昏〃鏈夊叧鑱旂殑 reloptions锛屽皢鍏惰祴鍊肩粰 relopts relopts = &ar_hentry->ar_reloptions; + // 閫氳繃 parentid 鍦ㄥ垎鍖鸿〃鍝堝笇琛ㄤ腑鏌ユ壘鍒嗗尯琛ㄧ殑鑷姩娓呯悊淇℃伅 ap_entry = (at_partitioned_table*)hash_search(partitioned_tables_map, &partForm->parentid, HASH_FIND, &found); if (!found) { + // 鑻ュ湪鍝堝笇琛ㄤ腑鏈壘鍒板搴旈」锛屾姏鍑洪敊璇 ereport(defence_errlevel(), (errcode(ERRCODE_DATA_CORRUPTED), errmsg("Oid: %u does not " "find in partitioned tables map.", partForm->parentid))); } /* Every partition table is local */ - partOid = HeapTupleGetOid(partTuple); - tabentry = get_pgstat_tabentry_relid(partOid, false, partForm->parentid, shared, dbentry); + partOid = HeapTupleGetOid(partTuple); // 鑾峰彇鍒嗗尯琛ㄧ殑 OID + tabentry = get_pgstat_tabentry_relid(partOid, false, partForm->parentid, shared, dbentry); // 鑾峰彇鍒嗗尯琛ㄧ殑缁熻淇℃伅 /* Check if it needs vacuum or analyze */ - partition_needs_vacanalyze( + partition_needs_vacanalyze( // 妫鏌ユ槸鍚﹂渶瑕佹墽琛岃嚜鍔ㄦ竻鐞嗘垨鑷姩鍒嗘瀽鎿嶄綔 partOid, relopts, partForm, partTuple, ap_entry, tabentry, false, &dovacuum, &doanalyze, &need_freeze); - Assert(false == doanalyze); - if (freeze_autovacuum) { + Assert(false == doanalyze); // 纭繚涓嶉渶瑕佹墽琛岃嚜鍔ㄥ垎鏋愭搷浣 + if (freeze_autovacuum) { // 濡傛灉闇瑕佽繘琛屽喕缁撴搷浣滐紝璁剧疆 dovacuum 涓 true dovacuum = need_freeze; } /* Partition that need work are added to table_oids */ if (dovacuum) { + // 灏嗛渶瑕佽繘琛岃嚜鍔ㄦ竻鐞嗙殑鍒嗗尯娣诲姞鍒 table_oids 鍒楄〃涓 vacObj = (vacuum_object*)palloc(sizeof(vacuum_object)); vacObj->tab_oid = partOid; vacObj->parent_oid = partForm->parentid; @@ -2264,11 +2452,12 @@ static void do_autovacuum(void) } /* just save partitioned tableis oid as mainid for partition */ - if (OidIsValid(partForm->reltoastrelid)) { + if (OidIsValid(partForm->reltoastrelid)) { // 淇濆瓨鍒嗗尯琛ㄧ殑 TOAST 琛ㄥ叧绯 av_toastid_mainid* at_entry = NULL; at_entry = (av_toastid_mainid*)hash_search(toast_table_map, &(partForm->reltoastrelid), HASH_ENTER, &found); if (!found) { + // 濡傛灉鏈壘鍒板搴旈」锛屽~鍏呯浉鍏充俊鎭 at_entry->at_relid = partOid; at_entry->at_parentid = partForm->parentid; at_entry->at_allowvacuum = ap_entry->at_allowvacuum; @@ -2283,26 +2472,36 @@ static void do_autovacuum(void) * (e.g. alter table exchange partition) * just skip it this time. */ + // 濡傛灉鍦 hash 琛ㄤ腑鎵惧埌瀵瑰簲椤癸紝骞朵笖 parentid 涓嶅尮閰 if (found && (at_entry->at_parentid != partForm->parentid)) { + // 鍦 toast_table_map 涓煡鎵惧搴旈」锛屽苟灏濊瘯绉婚櫎 if (hash_search(toast_table_map, &(partForm->reltoastrelid), HASH_REMOVE, NULL) != NULL) { + // 鑻ユ垚鍔熺Щ闄わ紝璁板綍鏃ュ織锛岃鏄 reltoastrelid 宸茶鏇存敼锛岃烦杩囪椤 ereport(LOG, (errmsg("reltoastrelid: %u toast table map " "has been changed, skip it.", partForm->reltoastrelid))); } else { + // 鑻ユ湭鎴愬姛绉婚櫎锛屾姤鍛婇敊璇紝琛ㄦ槑 toast_table_map 鍝堝笇琛ㄥ凡鎹熷潖 ereport(ERROR, (errcode(ERRCODE_DATA_CORRUPTED), errmsg("toast table map hash table corrupted."))); } } else { + // 濡傛灉娌℃湁鎵惧埌瀵瑰簲椤癸紝鎴栬 parentid 鍖归厤 纭繚 at_entry 鐨勫叧鑱斾俊鎭湁鏁 Assert(OidIsValid(at_entry->at_relid) && OidIsValid(at_entry->at_parentid)); } } } /* Close the pg_partition */ - tableam_scan_end(partScan); - heap_close(partRel, AccessShareLock); + tableam_scan_end(partScan); // 缁撴潫涔嬪墠寮濮嬬殑鍒嗗尯琛ㄦ壂鎻忥紝閲婃斁鐩稿叧璧勬簮 + heap_close(partRel, AccessShareLock); // 鍏抽棴涔嬪墠閫氳繃 heap_open 鍑芥暟鎵撳紑鐨刾g_partition琛 + // 鍋滄璁℃椂鍣紝鍦ㄦ棩蹇椾腑璁板綍浠庡紑濮嬫壂鎻 pg_partition 琛ㄥ埌缁撴潫鎵弿鐨勬椂闂达紝浠ュ府鍔╄皟璇曞拰鎬ц兘鍒嗘瀽銆 DEBUG_MOD_STOP_TIMER(MOD_AUTOVAC, "AUTOVAC TIMER: Scan pg_partition to determine which partitions to vacuum"); /* On the third pass: check TOAST tables */ + // 绗笁娆″惊鐜細妫鏌 TOAST 琛 + // 鍒濆鍖栨壂鎻忛敭锛岀敤浜庡湪鎵弿涓瓫閫夊嚭绗﹀悎鐗瑰畾鏉′欢鐨勮銆備互渚垮湪 pg_class 琛ㄤ腑鎵惧埌 relkind 瀛楁绛変簬 RELKIND_TOASTVALUE 鐨勮锛屼篃灏辨槸TOAST琛ㄧ殑琛 ScanKeyInit(&key[0], Anum_pg_class_relkind, BTEqualStrategyNumber, F_CHAREQ, CharGetDatum(RELKIND_TOASTVALUE)); + // 寮濮嬩竴涓柊鐨勮〃鎵弿銆傜敤浜庝粠 pg_class 琛ㄤ腑鑾峰彇婊¤冻鎵弿閿潯浠剁殑琛 relScan = tableam_scan_begin(classRel, SnapshotNow, 1, &key[0]); + // 閬嶅巻婊¤冻鏉′欢鐨 pg_class 琛ㄤ腑鐨勮褰曪紝鍗宠〃绀 TOAST 琛ㄧ殑璁板綍 while ((tuple = (HeapTuple) tableam_scan_getnexttuple(relScan, ForwardScanDirection)) != NULL) { Form_pg_class classForm = (Form_pg_class)GETSTRUCT(tuple); Oid relid = HeapTupleGetOid(tuple); @@ -2318,10 +2517,12 @@ static void do_autovacuum(void) av_toastid_mainid* at_entry = NULL; /* We cannot safely process other backends' temp tables, so skip 'em. */ + // 璺宠繃鍏朵粬鍚庡彴杩涚▼鐨勪复鏃惰〃 if (classForm->relpersistence == RELPERSISTENCE_TEMP || classForm->relpersistence == RELPERSISTENCE_GLOBAL_TEMP) continue; + // 鍦 toast_table_map 涓煡鎵惧搴旈」 at_entry = (av_toastid_mainid*)hash_search(toast_table_map, &(relid), HASH_FIND, &found); /* @@ -2336,15 +2537,18 @@ static void do_autovacuum(void) * fetch reloptions -- if this toast table does not have them, try the * main rel */ + // 鎻愬彇 reloptions - 濡傛灉璇 TOAST 琛ㄦ病鏈 reloptions锛屽垯灏濊瘯浣跨敤涓昏〃鐨 relopts = extract_autovac_opts(tuple, pg_class_desc); /* * we must get main table id first, and then get the * reloptions according to the main table id */ + // 濡傛灉 relopts 涓嶄负绌猴紝骞朵笖 relopts 寮曠敤鐨勬槸鍏朵粬琛ㄧ殑閫夐」 if (NULL == relopts && NULL != at_entry) { av_relation* ar_hentry = NULL; Oid MainId = at_entry->at_parentid > InvalidOid ? at_entry->at_parentid : at_entry->at_relid; + // 鍦 table_relopt_map 涓煡鎵句富琛/鍒嗗尯琛ㄧ殑 relopts ar_hentry = (av_relation*)hash_search(table_relopt_map, &MainId, HASH_FIND, &found); if (found && ar_hentry->ar_hasrelopts) { relopts = &ar_hentry->ar_reloptions; @@ -2353,56 +2557,67 @@ static void do_autovacuum(void) } /* Fetch the pgstat entry for this table */ + // 鑾峰彇璇ヨ〃鐨 pgstat 鏁版嵁 tabentry = get_pgstat_tabentry_relid(relid, classForm->relisshared, InvalidOid, shared, dbentry); + // 妫鏌ヨ〃鏄惁闇瑕 VACUUM 鎴 ANALYZE relation_support_autoavac(tuple, &enable_analyze, &enable_vacuum, &is_internal_relation); relation_needs_vacanalyze(relid, relopts, classForm, tuple, tabentry, enable_analyze, enable_vacuum, true, &dovacuum, &doanalyze, &need_freeze); + // 濡傛灉澶勪簬鍐荤粨鑷姩 VACUUM 妯″紡 if (freeze_autovacuum) { + // 瀵逛簬 MATMAP 琛ㄦ垨 MLOG 琛紝鎵ц VACUUM锛屼笉鎵ц ANALYZE if (ISMATMAP(classForm->relname.data) || ISMLOG(classForm->relname.data)) { dovacuum = true; doanalyze = false; } else { + // 鍚﹀垯锛屾墽琛 VACUUM 褰撲笖浠呭綋闇瑕佸喕缁 dovacuum = need_freeze; doanalyze = false; } } /* vacuum main table/partition instead if toast table */ - if (dovacuum) { + if (dovacuum) { // 娣诲姞涓昏〃/鍒嗗尯琛ㄥ埌 table_oids锛屾墽琛 VACUUM 鎴栬 VACUUM TOAST vacObj = (vacuum_object*)palloc(sizeof(vacuum_object)); if (local_autovacuum) { + // 瀵逛簬鏈湴鑷姩 VACUUM锛岃缃〃鐨 OID 浣滀负 tab_oid锛屾棤鐖惰〃 vacObj->tab_oid = relid; vacObj->parent_oid = InvalidOid; vacObj->flags = VACFLG_SIMPLE_HEAP; vacObj->dovacuum_toast = false; } else { + // 瀵逛簬鍏ㄥ眬鑷姩 VACUUM锛岃缃富琛/鍒嗗尯琛ㄧ殑 OID 浣滀负 tab_oid锛岀埗琛ㄧ殑 OID 浣滀负 parent_oid vacObj->tab_oid = at_entry->at_relid; vacObj->parent_oid = at_entry->at_parentid; + // 濡傛灉瀛樺湪鐖惰〃 OID锛屽垯璁剧疆 VACFLG_SUB_PARTITION 鏍囧織锛屽惁鍒欒缃 VACFLG_SIMPLE_HEAP 鏍囧織 vacObj->flags = OidIsValid(at_entry->at_parentid) ? VACFLG_SUB_PARTITION : VACFLG_SIMPLE_HEAP; vacObj->dovacuum_toast = true; vacObj->is_internal_relation = at_entry->at_internal; } + // 璁剧疆鏄惁鎵ц VACUUM銆佹槸鍚︽墽琛 ANALYZE銆佹槸鍚﹂渶瑕佸喕缁 vacObj->dovacuum = dovacuum; vacObj->doanalyze = doanalyze; vacObj->need_freeze = need_freeze; + // 灏嗗綋鍓 vacObj 娣诲姞鍒 table_oids 鍒楄〃涓 table_oids = lappend(table_oids, vacObj); } + // 濡傛灉 relopts 瀛樺湪涓斾笉鏄紩鐢ㄥ叾浠栬〃鐨勯夐」锛屽垯閲婃斁 relopts 鍐呭瓨 if (relopts && !isReloptsReferenceOther) { pfree_ext(relopts); } } - tableam_scan_end(relScan); - heap_close(classRel, AccessShareLock); + tableam_scan_end(relScan); // 缁撴潫瀵 pg_class 琛ㄧ殑鎵弿 + heap_close(classRel, AccessShareLock); // 鍏抽棴 pg_class 琛 + // 鍋滄璁℃椂锛岃褰曟壂鎻 pg_class 琛ㄤ互纭畾鍝簺 TOAST 琛ㄩ渶瑕佽繘琛 VACUUM 鐨勬椂闂 DEBUG_MOD_STOP_TIMER(MOD_AUTOVAC, "AUTOVAC TIMER: Scan pg_class to determine which toast tables to vacuum"); - /* * Create one buffer access strategy object per buffer pool for VACUUM to use. * We want to use the same one across all the vacuum operations we perform, * since the point is for VACUUM not to blow out the shared cache. */ - bstrategy = GetAccessStrategy(BAS_VACUUM); + bstrategy = GetAccessStrategy(BAS_VACUUM); // 涓 VACUUM 鍒涘缓姣忎釜缂撳啿姹犱竴涓紦鍐插尯璁块棶绛栫暐瀵硅薄 /* * create a memory context to act as fake t_thrd.mem_cxt.portal_mem_cxt, so that the @@ -2423,11 +2638,13 @@ static void do_autovacuum(void) int stdVacuumCostDelay; int stdVacuumCostLimit; + // 鑾峰彇褰撳墠寰呭鐞嗙殑琛ㄧ殑淇℃伅 vacObj = (vacuum_object*)lfirst(cell); relid = vacObj->tab_oid; parentid = vacObj->parent_oid; /* just skip all autovac actions quickly */ + // 濡傛灉鏈惎鐢ㄨ嚜鍔ㄥ寲娓呯悊瀹堟姢杩涚▼涓斾笉闇瑕佽繘琛屽喕缁撴搷浣滐紝鍒欏揩閫熻烦杩囨墍鏈夎嚜鍔ㄦ竻鐞嗘搷浣 if (!u_sess->attr.attr_storage.autovacuum_start_daemon && !vacObj->need_freeze) break; @@ -2438,6 +2655,7 @@ static void do_autovacuum(void) * needs vacuuming. We also need the AutovacuumLock to walk the * worker array, but we'll let go of that one quickly. */ + // 鑾峰緱 AutovacuumScheduleLock 鍜 AutovacuumLock 鐨勭嫭鍗犻攣锛岀敤浜庢鏌ユ槸鍚﹀彲浠ヨ繘琛屾竻鐞嗘搷浣 LWLockAcquire(AutovacuumScheduleLock, LW_EXCLUSIVE); LWLockAcquire(AutovacuumLock, LW_SHARED); @@ -2445,6 +2663,7 @@ static void do_autovacuum(void) * Check whether the table is being vacuumed concurrently by another * worker. */ + // 妫鏌ユ槸鍚︾敱鍏朵粬宸ヤ綔杩涚▼骞跺彂鍦板琛ㄨ繘琛屾竻鐞嗘搷浣 skipit = false; worker = (WorkerInfo)SHMQueueNext(&t_thrd.autovacuum_cxt.AutoVacuumShmem->av_runningWorkers, &t_thrd.autovacuum_cxt.AutoVacuumShmem->av_runningWorkers, offsetof(WorkerInfoData, wi_links)); @@ -2466,6 +2685,7 @@ static void do_autovacuum(void) * 1. other worker handle the main table, need check the worker's tableoid not equal the parentid; * 2. other worker handle the part table, need check the worker's parentoid not equal the parentid; */ + // 妫鏌ュ伐浣滆繘绋嬫鍦ㄥ鐞嗙殑琛ㄦ槸鍚﹀拰褰撳墠瑕佸鐞嗙殑琛ㄧ浉鍚岋紝濡傛灉鏄垯璺宠繃 if (parentid == InvalidOid && (worker->wi_tableoid == relid || worker->wi_parentoid == relid)) { AUTOVAC_LOG(DEBUG1, "parentoid = %u, tableoid = %u is on autovac, just skip it", parentid, relid); skipit = true; @@ -2482,6 +2702,7 @@ static void do_autovacuum(void) &worker->wi_links, offsetof(WorkerInfoData, wi_links)); } LWLockRelease(AutovacuumLock); + // 濡傛灉闇瑕佽烦杩囨竻鐞嗘搷浣滐紝缁х画澶勭悊涓嬩竴涓〃 if (skipit) { LWLockRelease(AutovacuumScheduleLock); continue; @@ -2497,8 +2718,10 @@ static void do_autovacuum(void) * that somebody just finished vacuuming this table. The window to * the race condition is not closed but it is very small. */ + // 鍒囨崲鍒版寚瀹氬唴瀛樹笂涓嬫枃浠ヨ繘琛屽悗缁搷浣 (void)MemoryContextSwitchTo(t_thrd.autovacuum_cxt.AutovacMemCxt); + // 妫鏌ユ槸鍚﹂渶瑕侀噸鏂版鏌ュ綋鍓嶈〃鐨勮嚜鍔ㄦ竻鐞嗚缃 if ((vacObj->flags & VACFLG_SIMPLE_HEAP) || (vacObj->flags & VACFLG_MAIN_PARTITION)) { tab = table_recheck_autovac(vacObj, table_relopt_map, toast_table_map, pg_class_desc); } else { @@ -2506,6 +2729,7 @@ static void do_autovacuum(void) tab = partition_recheck_autovac(vacObj, table_relopt_map, partitioned_tables_map, pg_class_desc); } + // 濡傛灉娌℃湁闇瑕佽繘琛岃嚜鍔ㄦ竻鐞嗙殑琛紝缁х画澶勭悊涓嬩竴涓〃 if (tab == NULL) { /* someone else vacuumed the table, or it went away */ LWLockRelease(AutovacuumScheduleLock); @@ -2518,6 +2742,7 @@ static void do_autovacuum(void) * Ok, good to go. Store the table in shared memory before releasing * the lock so that other workers don't vacuum it concurrently. */ + // 閲婃斁 AutovacuumScheduleLock 浠ュ厑璁稿叾浠栧伐浣滆繘绋嬫搷浣 t_thrd.autovacuum_cxt.MyWorkerInfo->wi_tableoid = relid; t_thrd.autovacuum_cxt.MyWorkerInfo->wi_parentoid = parentid; t_thrd.autovacuum_cxt.MyWorkerInfo->wi_sharedrel = tab->at_sharedrel; @@ -2529,26 +2754,26 @@ static void do_autovacuum(void) * restore these at the bottom of the loop, else we'll compute wrong * values in the next iteration of autovac_balance_cost(). */ + // 淇濆瓨褰撳墠 vacuum cost 鐩稿叧鍙傛暟鐨勫间互澶囧悗缁仮澶嶄娇鐢 stdVacuumCostDelay = u_sess->attr.attr_storage.VacuumCostDelay; stdVacuumCostLimit = u_sess->attr.attr_storage.VacuumCostLimit; - /* Must hold AutovacuumLock while mucking with cost balance info */ + // 淇濇寔 AutovacuumLock 鐘舵佷互澶勭悊鎴愭湰骞宠 淇℃伅 LWLockAcquire(AutovacuumLock, LW_EXCLUSIVE); - /* advertise my cost delay parameters for the balancing algorithm */ + // 璁剧疆鑷姩鍖栨竻鐞嗘搷浣滅殑鎴愭湰闄愬埗 t_thrd.autovacuum_cxt.MyWorkerInfo->wi_cost_delay = tab->at_vacuum_cost_delay; t_thrd.autovacuum_cxt.MyWorkerInfo->wi_cost_limit = tab->at_vacuum_cost_limit; t_thrd.autovacuum_cxt.MyWorkerInfo->wi_cost_limit_base = tab->at_vacuum_cost_limit; - /* do a balance */ + // 鎵ц鎴愭湰骞宠 鎿嶄綔锛屼互閬垮厤鏌愪簺宸ヤ綔杩涚▼杩囧害浣跨敤璧勬簮锛屽鑷存ц兘涓嬮檷銆 autovac_balance_cost(); - /* set the active cost parameters from the result of that */ + // 鏇存柊宸ヤ綔杩涚▼鐨勬垚鏈欢杩燂紝浠ラ傚簲绯荤粺鐨勮礋杞藉拰璧勬簮浣跨敤鎯呭喌 AutoVacuumUpdateDelay(); - /* done */ + // 閲婃斁 AutovacuumLock 閿 LWLockRelease(AutovacuumLock); - /* clean up memory before each iteration */ MemoryContextResetAndDeleteChildren(t_thrd.mem_cxt.portal_mem_cxt); (void)MemoryContextSwitchTo(t_thrd.mem_cxt.portal_mem_cxt); @@ -2560,20 +2785,22 @@ static void do_autovacuum(void) * Note: they must live in a long-lived memory context because we call * vacuum and analyze in different transactions. */ + // 濡傛灉褰撳墠琛ㄦ槸鍒嗗尯琛 if (vacuumPartition((uint32)(vacObj->flags))) { - Oid at_parentid = partid_get_parentid(tab->at_relid); + Oid at_parentid = partid_get_parentid(tab->at_relid); // 鑾峰彇鍒嗗尯琛ㄧ殑涓昏〃鐨凮id - tab->at_partname = getPartitionName(tab->at_relid, false); - tab->at_relname = get_rel_name(at_parentid); - tab->at_nspname = get_namespace_name(get_rel_namespace(at_parentid)); + tab->at_partname = getPartitionName(tab->at_relid, false); // 鑾峰彇鍒嗗尯琛ㄧ殑鍒嗗尯鍚嶇О + tab->at_relname = get_rel_name(at_parentid); // 鑾峰彇涓昏〃鐨勫叧绯诲悕 + tab->at_nspname = get_namespace_name(get_rel_namespace(at_parentid)); // 鑾峰彇涓昏〃鎵灞炵殑鍛藉悕绌洪棿鍚 } else { - tab->at_partname = NULL; - tab->at_relname = get_rel_name(tab->at_relid); - tab->at_nspname = get_namespace_name(get_rel_namespace(tab->at_relid)); + tab->at_partname = NULL; // 鍒嗗尯鍚嶇О璁剧疆涓虹┖ + tab->at_relname = get_rel_name(tab->at_relid); // 鑾峰彇鍏崇郴鍚 + tab->at_nspname = get_namespace_name(get_rel_namespace(tab->at_relid)); // 鑾峰彇鍛藉悕绌洪棿鍚 } - + // 鑾峰彇褰撳墠鏁版嵁搴撳悕 tab->at_datname = get_database_name(u_sess->proc_cxt.MyDatabaseId); + // 妫鏌ヨ幏鍙栫殑鍏崇郴鍚嶃佸懡鍚嶇┖闂村悕銆佹暟鎹簱鍚嶆槸鍚︿负绌 if ((NULL == tab->at_relname) || (NULL == tab->at_nspname) || (NULL == tab->at_datname)) goto deleted; @@ -2582,39 +2809,48 @@ static void do_autovacuum(void) * and continue with the next one in schedule; in particular, this * happens if we are interrupted with SIGINT. */ + /* + 璐熻矗鍦ㄦ墽琛岃嚜鍔ㄦ竻鐞嗗拰鍒嗘瀽鎿嶄綔鍓嶅仛蹇呰鐨勮缃紝鎵ц鎿嶄綔鍚庤繘琛屾竻鐞嗭紝浠ョ淮鎶ゆ暟鎹簱琛ㄧ殑鎬ц兘鍜岀┖闂淬 + 娑电洊浜嗘姤鍛婃椿鍔ㄣ佷簨鍔$鐞嗐侀攣瀹氭暟鎹簱銆佽缃椿鍔ㄥ揩鐓с佸垏鎹㈠唴瀛樹笂涓嬫枃銆佸鐞嗕俊鍙峰拰鎵ц娓呯悊鎿嶄綔绛夊叧閿楠ゃ + */ PG_TRY(); { /* * 1. Let pgstat know what we're doing * 2. in this function, statement_timestamp will be set to current time */ + // 閫氱煡 pgstat 姝e湪杩涜鐨勬椿鍔ㄧ被鍨嬶紙vacuum/analyze锛夊苟鏇存柊 statement_timestamp autovac_report_activity(tab); + // 濡傛灉鏈夋椿鍔ㄥ揩鐓э紝鍒欏脊鍑哄畠 if (ActiveSnapshotSet()) PopActiveSnapshot(); - CommitTransactionCommand(); + CommitTransactionCommand(); // 鎻愪氦褰撳墠浜嬪姟 - StartTransactionCommand(); + StartTransactionCommand(); // 寮濮嬫柊浜嬪姟 /* vacuum must hold RowExclusiveLock on db for a new transaction */ + // 鑾峰彇鏁版嵁搴撶殑 RowExclusiveLock 浠ユ墽琛屾竻鐞嗘搷浣 LockSharedObject(DatabaseRelationId, u_sess->proc_cxt.MyDatabaseId, 0, RowExclusiveLock); - PushActiveSnapshot(GetTransactionSnapshot()); + PushActiveSnapshot(GetTransactionSnapshot()); // 璁剧疆鏂颁簨鍔$殑娲诲姩蹇収 - (void)MemoryContextSwitchTo(t_thrd.mem_cxt.portal_mem_cxt); + (void)MemoryContextSwitchTo(t_thrd.mem_cxt.portal_mem_cxt); // 鍒囨崲鍒扮敤浜 portal 鐩稿叧鎿嶄綔鐨勫唴瀛樹笂涓嬫枃 + // 鍦ㄥ垎甯冨紡绯荤粺涓紝濡傛灉璁剧疆浜 autoanalyze 瓒呮椂涓旀弧瓒虫潯浠讹紝鍚敤淇″彿闂归挓 if ((IS_PGXC_COORDINATOR || IS_SINGLE_NODE) && u_sess->attr.attr_storage.autoanalyze_timeout > 0 && tab->at_doanalyze && !tab->at_dovacuum) { t_thrd.storage_cxt.timeIsPausing = false; enable_sig_alarm(u_sess->attr.attr_storage.autoanalyze_timeout * 1000, true); } + // 鏍规嵁琛ㄧ殑绫诲瀷鎵ц鏈湴鑷姩娓呯悊鎴栧垎甯冨紡 vacuum/analyze if (local_autovacuum || vacObj->is_internal_relation) autovacuum_local_vac_analyze(tab, bstrategy); else autovacuum_do_vac_analyze(tab, bstrategy); /* Cancel any active statement timeout before committing */ - disable_sig_alarm(true); + disable_sig_alarm(true); // 鍦ㄦ彁浜ゅ墠鍙栨秷浠讳綍娲昏穬鐨勮鍙ヨ秴鏃 /* * Clear a possible query-cancel signal, to avoid a late reaction @@ -2622,10 +2858,18 @@ static void do_autovacuum(void) * current table (we're done with it, so it would make no sense to * cancel at this point.) */ + // 娓呴櫎鍙兘鐨勬煡璇㈠彇娑堜俊鍙凤紝閬垮厤鍦ㄦ竻鐞嗗綋鍓嶈〃鏃剁敱浜庡彇娑堣屽紩璧疯繜閽濈殑鍙嶅簲 t_thrd.int_cxt.QueryCancelPending = false; } + /* + 鐢ㄤ簬鎹曡幏鍦ㄨ嚜鍔ㄦ竻鐞嗗拰鍒嗘瀽杩囩▼涓彲鑳藉彂鐢熺殑閿欒鎯呭喌锛屽苟鍦ㄥ嚭鐜伴敊璇椂鎵ц蹇呰鐨勬竻鐞嗗拰鎭㈠鎿嶄綔銆 + 浼氬彇娑堝綋鍓嶄簨鍔°侀噸缃浉鍏虫爣蹇楀拰涓婁笅鏂囷紝鍙戝嚭閿欒鎶ュ憡锛屾渶鍚庨噸鏂板惎鍔ㄤ簨鍔′互缁х画鍚庣画鎿嶄綔銆傝繖鏍峰仛鏄负浜嗕繚闅滅郴缁熺殑绋冲畾鎬у拰涓鑷存 + */ PG_CATCH(); { + // 鍦 PG_TRY 鍧椾腑鎹曡幏鍒伴敊璇悗鐨勫鐞 + + // 妫鏌ユ搷浣滆繃绋嬩腑鏄惁鍙戠敓浜嗚秴鏃 bool timeout_flag = (t_thrd.storage_cxt.cancel_from_timeout && u_sess->attr.attr_storage.autoanalyze_timeout); @@ -2633,6 +2877,7 @@ static void do_autovacuum(void) * Abort the transaction, start a new one, and proceed with the * next table in our list. */ + // 缁堟褰撳墠浜嬪姟骞堕噸缃繀瑕佺殑鏍囧織浣 HOLD_INTERRUPTS(); t_thrd.int_cxt.QueryCancelPending = false; @@ -2643,24 +2888,30 @@ static void do_autovacuum(void) t_thrd.storage_cxt.timeIsPausing = false; t_thrd.storage_cxt.restimems = -1; + // 鏍规嵁鎿嶄綔绫诲瀷锛坴acuum 鎴 analyze锛夌敓鎴愰敊璇笂涓嬫枃淇℃伅 if (tab->at_dovacuum) errcontext("automatic vacuum of table \"%s.%s.%s\"", tab->at_datname, tab->at_nspname, tab->at_relname); else errcontext( "automatic analyze of table \"%s.%s.%s\"", tab->at_datname, tab->at_nspname, tab->at_relname); + // 鍙戝嚭閿欒鎶ュ憡骞堕噸缃簨鍔$姸鎬 EmitErrorReport(); /* this resets the PGXACT flags too */ AbortCurrentTransaction(); FlushErrorState(); + + // 閲嶇疆鐢ㄤ簬娑堟伅鍜 portal 鎿嶄綔鐨勫唴瀛樹笂涓嬫枃 MemoryContextResetAndDeleteChildren(t_thrd.mem_cxt.msg_mem_cxt); MemoryContextResetAndDeleteChildren(t_thrd.mem_cxt.portal_mem_cxt); + // 濡傛灉鍙戠敓浜嗚秴鏃讹紝鍚 pgstat 鎶ュ憡浠ヨ繘琛岀洃鎺 if (timeout_flag) pgstat_report_autovac_timeout(vacObj->tab_oid, vacObj->parent_oid, tab->at_sharedrel); /* for some cases, we could not response any signal here, so we need unblock signals */ + // 瑙i櫎淇″彿灞忚斀骞堕噸鏂板紑濮嬩簨鍔′互杩涜鍚庣画鎿嶄綔 gs_signal_setmask(&t_thrd.libpq_cxt.UnBlockSig, NULL); (void)gs_signal_unblock_sigusr2(); @@ -2668,6 +2919,7 @@ static void do_autovacuum(void) StartTransactionCommand(); RESUME_INTERRUPTS(); /* vacuum must hold RowExclusiveLock on db for a new transaction */ + // 鑾峰彇鏁版嵁搴撶殑 RowExclusiveLock 浠ヨ繘琛屾柊浜嬪姟 LockSharedObject(DatabaseRelationId, u_sess->proc_cxt.MyDatabaseId, 0, RowExclusiveLock); } PG_END_TRY(); @@ -2682,6 +2934,7 @@ static void do_autovacuum(void) * settings, so we don't want to give up our share of I/O for a very * short interval and thereby thrash the global balance. */ + // 鑾峰彇 AutovacuumLock 骞堕噸缃綋鍓嶅伐浣滆繘绋嬬殑淇℃伅 LWLockAcquire(AutovacuumLock, LW_EXCLUSIVE); t_thrd.autovacuum_cxt.MyWorkerInfo->wi_tableoid = InvalidOid; t_thrd.autovacuum_cxt.MyWorkerInfo->wi_parentoid = InvalidOid; @@ -2690,12 +2943,15 @@ static void do_autovacuum(void) LWLockRelease(AutovacuumLock); /* restore vacuum cost GUCs for the next iteration */ + // 鎭㈠涓嬩竴娆¤凯浠f墍闇鐨 vacuum cost 鍙傛暟 u_sess->attr.attr_storage.VacuumCostDelay = stdVacuumCostDelay; u_sess->attr.attr_storage.VacuumCostLimit = stdVacuumCostLimit; + // 閲嶇疆娑堟伅鍜 portal 鍐呭瓨涓婁笅鏂 MemoryContextResetAndDeleteChildren(t_thrd.mem_cxt.msg_mem_cxt); MemoryContextResetAndDeleteChildren(t_thrd.mem_cxt.portal_mem_cxt); /* reset t_thrd.vacuum_cxt.vac_context in case that invalid t_thrd.vacuum_cxt.vac_context would be used */ + // 閲嶇疆 vacuum 涓婁笅鏂囷紝浠ュ厤鍦ㄦ棤鏁堢殑涓婁笅鏂囦笅杩涜鎿嶄綔 t_thrd.vacuum_cxt.vac_context = NULL; } /* @@ -2710,9 +2966,9 @@ static void do_autovacuum(void) vac_update_datfrozenxid(); /* Finally close out the last transaction. */ - if (ActiveSnapshotSet()) - PopActiveSnapshot(); - CommitTransactionCommand(); + if (ActiveSnapshotSet()) // 濡傛灉褰撳墠瀛樺湪娲昏穬鐨勫揩鐓 + PopActiveSnapshot(); // 寮瑰嚭娲昏穬蹇収 + CommitTransactionCommand(); // 鎻愪氦褰撳墠浜嬪姟 } /* @@ -2723,19 +2979,23 @@ static void do_autovacuum(void) */ AutoVacOpts* extract_autovac_opts(HeapTuple tup, TupleDesc pg_class_desc) { - bytea* relopts = NULL; - AutoVacOpts* av = NULL; - int rc = 0; + bytea* relopts = NULL; // 瀛樺偍鍏崇郴鐨 reloptions + AutoVacOpts* av = NULL; // 瀛樺偍鎻愬彇鐨 AutoVacOpts 缁撴瀯 + int rc = 0; // 鐢ㄤ簬瀛樺偍 memcpy_s 鍑芥暟鐨勮繑鍥炵爜 + // 鏂█锛氱‘淇濆叧绯荤被鍨嬫槸琛ㄣ佺墿鍖栬鍥炬垨 TOAST 鍊 Assert(((Form_pg_class)GETSTRUCT(tup))->relkind == RELKIND_RELATION || ((Form_pg_class) GETSTRUCT(tup))->relkind == RELKIND_MATVIEW || ((Form_pg_class)GETSTRUCT(tup))->relkind == RELKIND_TOASTVALUE); + // 鎻愬彇鍏崇郴鐨 reloptions relopts = extractRelOptions(tup, pg_class_desc, InvalidOid); if (relopts == NULL) return NULL; + // 鍒嗛厤鍐呭瓨浠ュ瓨鍌 AutoVacOpts 缁撴瀯 av = (AutoVacOpts*)palloc(sizeof(AutoVacOpts)); + // 灏嗘彁鍙栫殑 AutoVacOpts 澶嶅埗鍒 av 缁撴瀯涓 rc = memcpy_s(av, sizeof(AutoVacOpts), &(((StdRdOptions*)relopts)->autovacuum), sizeof(AutoVacOpts)); securec_check(rc, "\0", "\0"); @@ -2744,7 +3004,7 @@ AutoVacOpts* extract_autovac_opts(HeapTuple tup, TupleDesc pg_class_desc) av->enabled = isPartitionedRelation((Form_pg_class)GETSTRUCT(tup)); } - pfree_ext(relopts); + pfree_ext(relopts); // 閲婃斁 relopts 鐨勫唴瀛 return av; } @@ -2757,19 +3017,23 @@ AutoVacOpts* extract_autovac_opts(HeapTuple tup, TupleDesc pg_class_desc) static PgStat_StatTabEntry* get_pgstat_tabentry_relid( Oid relid, bool isshared, uint32 statFlag, PgStat_StatDBEntry* shared, PgStat_StatDBEntry* dbentry) { - PgStat_StatTabEntry* tabentry = NULL; - PgStat_StatDBEntry* dnentry = NULL; + PgStat_StatTabEntry* tabentry = NULL; // 瀛樺偍琛ㄧ殑 pgstat 缁熻淇℃伅椤 + PgStat_StatDBEntry* dnentry = NULL; // 瀛樺偍鏁版嵁搴撶殑 pgstat 缁熻淇℃伅椤 + // 鏍规嵁琛ㄦ槸鍚﹀叡浜紝閫夋嫨瑕佽闂殑鏁版嵁搴撶粺璁′俊鎭」 if (isshared) dnentry = shared; else dnentry = dbentry; + // 濡傛灉鏁版嵁搴撶粺璁′俊鎭」瀛樺湪 if (dnentry != NULL) { - PgStat_StatTabKey tabkey; + PgStat_StatTabKey tabkey; // 瀛樺偍琛ㄧ殑缁熻淇℃伅閿 - tabkey.statFlag = statFlag; - tabkey.tableid = relid; + // 璁剧疆琛ㄧ殑缁熻淇℃伅閿 + tabkey.statFlag = statFlag; // 缁熻淇℃伅鐨勬爣蹇椾綅 + tabkey.tableid = relid; // 琛ㄧ殑 OID + // 鍦ㄦ暟鎹簱缁熻淇℃伅椤圭殑鏁e垪琛ㄤ腑鏌ユ壘琛ㄧ殑缁熻淇℃伅椤 tabentry = (PgStat_StatTabEntry*)hash_search(dnentry->tables, (void*)(&tabkey), HASH_FIND, NULL); } @@ -2786,13 +3050,14 @@ static PgStat_StatTabEntry* get_pgstat_tabentry_relid( */ static autovac_table* calculate_vacuum_cost_and_freezeages(const AutoVacOpts* avopts, bool doanalyze, bool need_freeze) { - int64 freeze_min_age; - int64 freeze_table_age; - int vac_cost_limit; - int vac_cost_delay; - autovac_table* tab = NULL; + int64 freeze_min_age; // 鏈灏忓喕缁撳勾榫 + int64 freeze_table_age; // 琛ㄧ殑鍐荤粨骞撮緞 + int vac_cost_limit; // 娓呯悊鎴愭湰闄愬埗 + int vac_cost_delay; // 娓呯悊鎴愭湰寤惰繜 + autovac_table* tab = NULL; // 瀛樺偍鑷姩娓呯悊鐨勭浉鍏冲弬鏁板拰鍐荤粨淇℃伅 /* -1 in autovac setting means use plain vacuum_cost_delay */ + // 濡傛灉鍦ㄨ嚜鍔ㄦ竻鐞嗛夐」涓缃簡鍏蜂綋鐨勫硷紝灏变娇鐢ㄨ繖浜涘硷紱鍚﹀垯灏濊瘯浣跨敤 GUC 榛樿鍊 vac_cost_delay = (avopts && avopts->vacuum_cost_delay >= 0) ? avopts->vacuum_cost_delay : (u_sess->attr.attr_storage.autovacuum_vac_cost_delay >= 0) @@ -2807,21 +3072,23 @@ static autovac_table* calculate_vacuum_cost_and_freezeages(const AutoVacOpts* av : u_sess->attr.attr_storage.VacuumCostLimit; /* these do not have autovacuum-specific settings */ + // 杩欎簺鍙傛暟涓嶅叿鏈夎嚜鍔ㄦ竻鐞嗕笓鐢ㄧ殑璁剧疆锛屽洜姝ょ洿鎺ヤ娇鐢ㄩ粯璁ゅ兼垨涓婁笅鏂囦腑鐨勯粯璁ゅ freeze_min_age = (avopts && avopts->freeze_min_age >= 0) ? avopts->freeze_min_age : t_thrd.autovacuum_cxt.default_freeze_min_age; freeze_table_age = (avopts && avopts->freeze_table_age >= 0) ? avopts->freeze_table_age : t_thrd.autovacuum_cxt.default_freeze_table_age; + // 鍒涘缓瀛樺偍鑷姩娓呯悊鐨勭浉鍏冲弬鏁板拰鍐荤粨淇℃伅鐨勭粨鏋勪綋 tab = (autovac_table*)palloc(sizeof(autovac_table)); - tab->at_doanalyze = doanalyze; - tab->at_freeze_min_age = freeze_min_age; - tab->at_freeze_table_age = freeze_table_age; - tab->at_vacuum_cost_limit = vac_cost_limit; - tab->at_vacuum_cost_delay = vac_cost_delay; - tab->at_needfreeze = need_freeze; - tab->at_relname = NULL; - tab->at_nspname = NULL; - tab->at_datname = NULL; + tab->at_doanalyze = doanalyze; // 鏄惁鎵ц鍒嗘瀽鎿嶄綔 + tab->at_freeze_min_age = freeze_min_age; // 鏈灏忓喕缁撳勾榫 + tab->at_freeze_table_age = freeze_table_age; // 琛ㄧ殑鍐荤粨骞撮緞 + tab->at_vacuum_cost_limit = vac_cost_limit; // 娓呯悊鎴愭湰闄愬埗 + tab->at_vacuum_cost_delay = vac_cost_delay; // 娓呯悊鎴愭湰寤惰繜 + tab->at_needfreeze = need_freeze; // 鏄惁闇瑕佸喕缁 + tab->at_relname = NULL; // 琛ㄥ悕 + tab->at_nspname = NULL; // 鍛藉悕绌洪棿鍚 + tab->at_datname = NULL; // 鏁版嵁搴撳悕 return tab; } @@ -2836,46 +3103,47 @@ static autovac_table* calculate_vacuum_cost_and_freezeages(const AutoVacOpts* av static autovac_table* table_recheck_autovac( vacuum_object* vacObj, HTAB* table_relopt_map, HTAB* toast_table_map, TupleDesc pg_class_desc) { - Oid relid = vacObj->tab_oid; + Oid relid = vacObj->tab_oid; // 鑾峰彇寰呭鐞嗚〃鐨勫璞D Form_pg_class classForm; HeapTuple classTup; - bool dovacuum = false; - bool dovacuum_toast = vacObj->dovacuum_toast; - bool doanalyze = false; - bool need_freeze = false; - bool is_internal_relation = false; - bool enable_analyze = false; - bool enable_vacuum = false; - autovac_table* tab = NULL; - PgStat_StatDBEntry* shared = NULL; - PgStat_StatDBEntry* dbentry = NULL; - PgStat_StatTabEntry* tabentry = NULL; - AutoVacOpts* avopts = NULL; - bool isAvoptsRefereceOther = false; + bool dovacuum = false; // 鏄惁鎵ц娓呯悊鎿嶄綔鐨勬爣蹇 + bool dovacuum_toast = vacObj->dovacuum_toast; // 鏄惁鎵ц TOAST 琛ㄧ殑娓呯悊鎿嶄綔 + bool doanalyze = false; // 鏄惁鎵ц鍒嗘瀽鎿嶄綔鐨勬爣蹇 + bool need_freeze = false; // 鏄惁闇瑕佸喕缁撶殑鏍囧織 + bool is_internal_relation = false; // 鏄惁涓哄唴閮ㄥ叧绯荤殑鏍囧織 + bool enable_analyze = false; // 鏄惁鍚敤鍒嗘瀽鎿嶄綔鐨勬爣蹇 + bool enable_vacuum = false; // 鏄惁鍚敤娓呯悊鎿嶄綔鐨勬爣蹇 + autovac_table* tab = NULL; // 鑷姩鍨冨溇娓呯悊琛ㄤ俊鎭殑缁撴瀯浣撴寚閽 + PgStat_StatDBEntry* shared = NULL; // 鍏变韩鏁版嵁搴撶粺璁′俊鎭殑缁撴瀯浣撴寚閽 + PgStat_StatDBEntry* dbentry = NULL; // 褰撳墠鏁版嵁搴撶粺璁′俊鎭殑缁撴瀯浣撴寚閽 + PgStat_StatTabEntry* tabentry = NULL; // 琛ㄧ粺璁′俊鎭殑缁撴瀯浣撴寚閽 + AutoVacOpts* avopts = NULL; // 鑷姩鍨冨溇娓呯悊閰嶇疆閫夐」鐨勭粨鏋勪綋鎸囬拡 + bool isAvoptsRefereceOther = false; // 鏄惁寮曠敤浜嗗叾浠栫粨鏋勪綋鐨勬爣蹇 if (IS_SINGLE_NODE) { /* use fresh stats */ - autovac_refresh_stats(); + autovac_refresh_stats();// 鍒锋柊鏁版嵁搴撶粺璁′俊鎭 } - shared = pgstat_fetch_stat_dbentry(InvalidOid); - dbentry = pgstat_fetch_stat_dbentry(u_sess->proc_cxt.MyDatabaseId); + shared = pgstat_fetch_stat_dbentry(InvalidOid); // 鑾峰彇鍏变韩鏁版嵁搴撶粺璁′俊鎭 + dbentry = pgstat_fetch_stat_dbentry(u_sess->proc_cxt.MyDatabaseId); // 鑾峰彇褰撳墠鏁版嵁搴撶粺璁′俊鎭 /* fetch the relation's relcache entry */ - classTup = SearchSysCacheCopy1(RELOID, ObjectIdGetDatum(relid)); + classTup = SearchSysCacheCopy1(RELOID, ObjectIdGetDatum(relid)); // 浠庣郴缁熺紦瀛樹腑鑾峰彇琛ㄧ殑鍏冪粍 if (!HeapTupleIsValid(classTup)) return NULL; - classForm = (Form_pg_class)GETSTRUCT(classTup); + classForm = (Form_pg_class)GETSTRUCT(classTup); // 鑾峰彇琛ㄧ殑琛ㄥ崟鏁版嵁 bytea *rawRelopts = extractRelOptions(classTup, pg_class_desc, InvalidOid); /* this is Ustore partitioned table, use another bypass */ + // 鍒ゆ柇鏄惁澶勭悊鐨勬槸婊¤冻鐗瑰畾鏉′欢鐨 Ustore 瀛樺偍寮曟搸鐨勫垎鍖鸿〃 if (rawRelopts != NULL && RelationIsTableAccessMethodUStoreType(rawRelopts) && isPartitionedRelation(classForm)) { - avopts = extract_autovac_opts(classTup, pg_class_desc); - tab = calculate_vacuum_cost_and_freezeages(avopts, false, false); + avopts = extract_autovac_opts(classTup, pg_class_desc); // 鑾峰彇鑷姩鍨冨溇娓呯悊鐨勯厤缃夐」 + tab = calculate_vacuum_cost_and_freezeages(avopts, false, false); // 璁$畻娓呯悊鎴愭湰鍜屽喕缁撻槇鍊 if (tab != NULL) { - tab->at_relid = relid; - tab->at_sharedrel = classForm->relisshared; - tab->at_dovacuum = true; + tab->at_relid = relid; // 璁剧疆琛ㄧ殑瀵硅薄ID + tab->at_sharedrel = classForm->relisshared; // 璁剧疆琛ㄦ槸鍚︿负鍏变韩琛 + tab->at_dovacuum = true; // 璁剧疆鎵ц娓呯悊鎿嶄綔鐨勬爣蹇 } return tab; } @@ -2884,7 +3152,7 @@ static autovac_table* table_recheck_autovac( * Get the applicable reloptions. If it is a TOAST table, try to get the * main table reloptions if the toast table itself doesn't have. */ - avopts = extract_autovac_opts(classTup, pg_class_desc); + avopts = extract_autovac_opts(classTup, pg_class_desc); // 鎻愬彇琛ㄧ殑鑷姩娓呯悊閫夐」 if (RELKIND_TOASTVALUE == classForm->relkind && (NULL == avopts) && (NULL != table_relopt_map) && (NULL != toast_table_map)) { av_relation* hentry = NULL; @@ -2892,10 +3160,12 @@ static autovac_table* table_recheck_autovac( bool found = false; Oid MainId; + // 鍦╰oast_table_map涓煡鎵炬槸鍚︽湁涓昏〃鐨勬槧灏 tentry = (av_toastid_mainid*)hash_search(toast_table_map, &relid, HASH_FIND, &found); if (found) { MainId = tentry->at_relid; hentry = (av_relation*)hash_search(table_relopt_map, &MainId, HASH_FIND, &found); + // 鍦╰able_relopt_map涓煡鎵句富琛ㄧ殑reloptions if (found && hentry->ar_hasrelopts) { avopts = &hentry->ar_reloptions; isAvoptsRefereceOther = true; @@ -2929,10 +3199,10 @@ static autovac_table* table_recheck_autovac( } } - heap_freetuple(classTup); + heap_freetuple(classTup); // 閲婃斁classTup鎵鍗犵敤鐨勫唴瀛 - if (avopts && !isAvoptsRefereceOther) { - pfree_ext(avopts); + if (avopts && !isAvoptsRefereceOther) { // 濡傛灉涔嬪墠浠庤〃鐨勫厓缁勬暟鎹腑鎻愬彇鍒颁簡AutoVacOpts缁撴瀯浣揳vopts锛屽苟涓旀病鏈夎寮曠敤杩 + pfree_ext(avopts); // 閲婃斁avopts鍗犵敤鐨勫唴瀛 } return tab; @@ -2949,22 +3219,37 @@ static void determine_vacuum_params(float4& vac_scale_factor, int& vac_base_thre MultiXactId& multiForceLimit, const AutoVacOpts* relopts) { /* -1 in autovac setting means use plain vacuum_cost_delay */ + // 鍒ゆ柇鏄惁浼犲叆浜唕elopts缁撴瀯浣擄紝浠ュ強鍏朵腑鐨剉acuum_scale_factor灞炴у + // 濡傛灉鏈変紶鍏ヤ笖鍊煎ぇ浜庣瓑浜0锛屽垯浣跨敤浼犲叆鍊硷紱鍚﹀垯浣跨敤autovacuum_vac_scale鍙傛暟鐨勫 vac_scale_factor = (relopts && relopts->vacuum_scale_factor >= 0) ? relopts->vacuum_scale_factor : u_sess->attr.attr_storage.autovacuum_vac_scale; + // 鍒ゆ柇鏄惁浼犲叆浜唕elopts缁撴瀯浣擄紝浠ュ強鍏朵腑鐨剉acuum_threshold灞炴у + // 濡傛灉鏈変紶鍏ヤ笖鍊煎ぇ浜庣瓑浜0锛屽垯浣跨敤浼犲叆鍊硷紱鍚﹀垯浣跨敤autovacuum_vac_thresh鍙傛暟鐨勫 vac_base_thresh = (relopts && relopts->vacuum_threshold >= 0) ? relopts->vacuum_threshold : u_sess->attr.attr_storage.autovacuum_vac_thresh; + + // 鍒ゆ柇鏄惁浼犲叆浜唕elopts缁撴瀯浣擄紝浠ュ強鍏朵腑鐨刟nalyze_scale_factor灞炴у + // 濡傛灉鏈変紶鍏ヤ笖鍊煎ぇ浜庣瓑浜0锛屽垯浣跨敤浼犲叆鍊硷紱鍚﹀垯浣跨敤autovacuum_anl_scale鍙傛暟鐨勫 anl_scale_factor = (relopts && relopts->analyze_scale_factor >= 0) ? relopts->analyze_scale_factor : u_sess->attr.attr_storage.autovacuum_anl_scale; + + // 鍒ゆ柇鏄惁浼犲叆浜唕elopts缁撴瀯浣擄紝浠ュ強鍏朵腑鐨刟nalyze_threshold灞炴у + // 濡傛灉鏈変紶鍏ヤ笖鍊煎ぇ浜庣瓑浜0锛屽垯浣跨敤浼犲叆鍊硷紱鍚﹀垯浣跨敤autovacuum_anl_thresh鍙傛暟鐨勫 anl_base_thresh = (relopts && relopts->analyze_threshold >= 0) ? relopts->analyze_threshold : u_sess->attr.attr_storage.autovacuum_anl_thresh; + // 鍒ゆ柇鏄惁浼犲叆浜唕elopts缁撴瀯浣擄紝浠ュ強鍏朵腑鐨刦reeze_max_age灞炴у + // 濡傛灉鏈変紶鍏ヤ笖鍊煎ぇ浜庣瓑浜0锛屽垯浣跨敤浼犲叆鍊硷紱鍚﹀垯浣跨敤autovacuum_freeze_max_age鍙傛暟鐨勫 + // 浣嗕笉瓒呰繃鍏ㄥ眬鐨刟utovacuum_freeze_max_age鍙傛暟鍊 freeze_max_age = (relopts && relopts->freeze_max_age >= 0) ? Min(relopts->freeze_max_age, g_instance.attr.attr_storage.autovacuum_freeze_max_age) : g_instance.attr.attr_storage.autovacuum_freeze_max_age; + // 鍒ゆ柇鏄惁浼犲叆浜唕elopts缁撴瀯浣擄紝浠ュ強鍏朵腑鐨別nabled灞炴у + // 濡傛灉鏈変紶鍏ワ紝鍒欎娇鐢ㄤ紶鍏ュ硷紱鍚﹀垯榛樿涓哄惎鐢 av_enabled = (relopts ? relopts->enabled : true); /* Force vacuum if table need freeze the old tuple to recycle clog */ @@ -2974,6 +3259,7 @@ static void determine_vacuum_params(float4& vac_scale_factor, int& vac_base_thre xidForceLimit = FirstNormalTransactionId; #ifndef ENABLE_MULTIPLE_NODES + // 鍦ㄥ崟鑺傜偣妯″紡涓嬶紝鏍规嵁鏈杩戠殑澶氫簨鍔D鍜宖reeze_max_age璁$畻鍑哄己鍒舵墽琛屾竻鐞嗙殑澶氫簨鍔D鐨勪笅闄 if (t_thrd.autovacuum_cxt.recentMulti > FirstMultiXactId + (uint64)g_instance.attr.attr_storage.autovacuum_freeze_max_age) multiForceLimit = t_thrd.autovacuum_cxt.recentMulti - @@ -3027,17 +3313,17 @@ static void relation_needs_vacanalyze(Oid relid, AutoVacOpts* relopts, Form_pg_c PgStat_StatTabKey tablekey; avw_info* avwentry = NULL; bool found = false; - bool force_vacuum = false; - bool av_enabled = false; - bool userEnabled = true; + bool force_vacuum = false; // 鏄惁闇瑕佸己鍒舵墽琛孷ACUUM + bool av_enabled = false; // 鏄惁鍚敤浜嗚嚜鍔ㄦ竻鐞 + bool userEnabled = true; // 鐢ㄦ埛鏄惁鍚敤浜嗚嚜鍔ㄦ竻鐞 /* pg_class.reltuples */ float4 reltuples; /* constants from reloptions or GUC variables */ - int vac_base_thresh = 0; - int anl_base_thresh = 0; - float4 vac_scale_factor = 0.0; - float4 anl_scale_factor = 0.0; + int vac_base_thresh = 0; // VACUUM鐨勫熀纭闃堝 + int anl_base_thresh = 0; // ANALYZE鐨勫熀纭闃堝 + float4 vac_scale_factor = 0.0; // VACUUM闃堝肩殑缂╂斁鍥犲瓙 + float4 anl_scale_factor = 0.0; // ANALYZE闃堝肩殑缂╂斁鍥犲瓙 /* thresholds calculated from above constants */ float4 vacthresh; @@ -3048,24 +3334,30 @@ static void relation_needs_vacanalyze(Oid relid, AutoVacOpts* relopts, Form_pg_c int64 anltuples = 0; /* freeze parameters */ - int64 freeze_max_age = 0; - TransactionId xidForceLimit = InvalidTransactionId; - MultiXactId multiForceLimit = InvalidMultiXactId; + int64 freeze_max_age = 0; // 鏈澶т簨鍔D闂撮殧 + TransactionId xidForceLimit = InvalidTransactionId; // 寮哄埗VACUUM鐨勪簨鍔D闄愬埗 + MultiXactId multiForceLimit = InvalidMultiXactId; // 寮哄埗VACUUM鐨凪ultiXactId闄愬埗 + // 鏂█锛岀‘淇 classForm 鍜 relid 鏄湁鏁堢殑 AssertArg(classForm != NULL); AssertArg(OidIsValid(relid)); + // 浠庨厤缃腑鑾峰彇鑷姩娓呯悊鍙傛暟锛屽喅瀹氭槸鍚︽墽琛孷ACUUM鎿嶄綔 determine_vacuum_params(vac_scale_factor, vac_base_thresh, anl_scale_factor, anl_base_thresh, freeze_max_age, av_enabled, xidForceLimit, multiForceLimit, relopts); bool isNull = false; TransactionId relfrozenxid = InvalidTransactionId; + // 鎵撳紑 pg_class 琛ㄤ互鑾峰彇鍏抽敭灞炴 Relation rel = heap_open(RelationRelationId, AccessShareLock); + // 鑾峰彇琛ㄧ殑 relfrozenxid64 灞炴 Datum xid64datum = heap_getattr(tuple, Anum_pg_class_relfrozenxid64, RelationGetDescr(rel), &isNull); + // 濡傛灉灞炴т负绌猴紝鍒欎娇鐢ㄩ粯璁ゅ if (isNull) { relfrozenxid = classForm->relfrozenxid; + // 濡傛灉琛ㄧ殑 relfrozenxid 涓嶅湪鍚堢悊鑼冨洿鍐咃紝璁剧疆涓哄悎鐞嗙殑榛樿鍊 if (TransactionIdPrecedes(t_thrd.xact_cxt.ShmemVariableCache->nextXid, relfrozenxid) || !TransactionIdIsNormal(relfrozenxid)) { relfrozenxid = FirstNormalTransactionId; @@ -3074,23 +3366,30 @@ static void relation_needs_vacanalyze(Oid relid, AutoVacOpts* relopts, Form_pg_c relfrozenxid = DatumGetTransactionId(xid64datum); } + // 鍒ゆ柇鏄惁闇瑕佸己鍒舵墽琛 VACUUM force_vacuum = (TransactionIdIsNormal(relfrozenxid) && TransactionIdPrecedes(relfrozenxid, xidForceLimit)); #ifndef ENABLE_MULTIPLE_NODES + // 濡傛灉涓嶆槸寮哄埗鎵ц VACUUM锛屾鏌 MultiXactId 涔熸槸鍚﹂渶瑕 if (!force_vacuum) { + // 鑾峰彇琛ㄧ殑 relminmxid 灞炴 Datum mxidDatum = heap_getattr(tuple, Anum_pg_class_relminmxid, RelationGetDescr(rel), &isNull); MultiXactId relminmxid = isNull ? FirstMultiXactId : DatumGetTransactionId(mxidDatum); + // 鍒ゆ柇鏄惁闇瑕佸己鍒舵墽琛 VACUUM force_vacuum = (MultiXactIdIsValid(relminmxid) && MultiXactIdPrecedes(relminmxid, multiForceLimit)); } #endif heap_close(rel, AccessShareLock); - *need_freeze = force_vacuum; + *need_freeze = force_vacuum; // 鏇存柊鏄惁闇瑕佸己鍒舵墽琛屽喕缁撶殑鏍囧織 + // 璁板綍鏄惁闇瑕佸己鍒舵墽琛屽喕缁撶殑鎯呭喌 AUTOVAC_LOG(DEBUG2, "vac \"%s\": need freeze is %s", NameStr(classForm->relname), force_vacuum ? "true" : "false"); /* User disabled it in pg_class.reloptions? (But ignore if at risk) */ + // 濡傛灉鐢ㄦ埛宸茬鐢ㄨ嚜鍔ㄦ竻鐞嗘垨瀹堟姢杩涚▼锛屽垯涓嶆墽琛岃嚜鍔ㄦ竻鐞 if (!force_vacuum && (!av_enabled || !u_sess->attr.attr_storage.autovacuum_start_daemon)) { userEnabled = false; } + // 鑾峰彇缁熻淇℃伅鐨勯敭 if (NULL != t_thrd.autovacuum_cxt.pgStatAutoVacInfo) { tablekey.statFlag = InvalidOid; tablekey.tableid = relid; @@ -3098,42 +3397,54 @@ static void relation_needs_vacanalyze(Oid relid, AutoVacOpts* relopts, Form_pg_c (avw_info*)hash_search(t_thrd.autovacuum_cxt.pgStatAutoVacInfo, (void*)(&tablekey), HASH_FIND, &found); } + // 鑾峰彇琛ㄧ殑 reltuples 灞炴 reltuples = classForm->reltuples; vacthresh = (float4)vac_base_thresh + vac_scale_factor * reltuples; anlthresh = (float4)anl_base_thresh + anl_scale_factor * reltuples; + // 濡傛灉鏃㈡病鏈夊眬閮ㄧ粺璁′俊鎭篃娌℃湁鍏ㄥ眬缁熻淇℃伅锛屾牴鎹槸鍚﹂渶瑕佸己鍒舵墽琛孷ACUUM鏉ュ喅瀹氭槸鍚︽墽琛孷ACUUM鍜孉NALYZE if ((avwentry == NULL) && (tabentry == NULL)) { *dovacuum = force_vacuum; *doanalyze = false; } else { + // 濡傛灉鏈夊眬閮ㄧ粺璁′俊鎭 if (tabentry && (tabentry->changes_since_analyze || tabentry->n_dead_tuples)) { + // 鏇存柊鍙樺寲鐨勫厓缁勬暟鍜屾鍏冪粍鏁 anltuples = tabentry->changes_since_analyze; vactuples = tabentry->n_dead_tuples; + // 璁板綍灞閮ㄧ粺璁′俊鎭埌鏃ュ織涓 AUTOVAC_LOG(DEBUG2, "fetch local stat info: vac \"%s\" changes_since_analyze = %ld n_dead_tuples = %ld ", NameStr(classForm->relname), tabentry->changes_since_analyze, tabentry->n_dead_tuples); } + // 濡傛灉鏈夊叏灞缁熻淇℃伅 if (avwentry && (avwentry->changes_since_analyze || avwentry->n_dead_tuples)) { + // 鏇存柊鍙樺寲鐨勫厓缁勬暟鍜屾鍏冪粍鏁 anltuples = avwentry->changes_since_analyze; vactuples = avwentry->n_dead_tuples; + // 璁板綍鍏ㄥ眬缁熻淇℃伅鍒版棩蹇椾腑 AUTOVAC_LOG(DEBUG2, "fetch global stat info: vac \"%s\" changes_since_analyze = %ld n_dead_tuples = %ld ", NameStr(classForm->relname), avwentry->changes_since_analyze, avwentry->n_dead_tuples); } /* Determine if this table needs vacuum. */ + // 纭畾鏄惁闇瑕佹墽琛孷ACUUM *dovacuum = force_vacuum; *doanalyze = false; + // 濡傛灉鍏佽鑷姩娓呯悊锛屾牴鎹槇鍊煎垽鏂槸鍚﹂渶瑕佹墽琛孷ACUUM if (false == *dovacuum && allowVacuum) *dovacuum = ((float4)vactuples > vacthresh); /* Determine if this table needs analyze. */ + // 濡傛灉鍏佽鍒嗘瀽鎿嶄綔锛屾牴鎹槇鍊煎垽鏂槸鍚﹂渶瑕佹墽琛孉NALYZE if (allowAnalyze) *doanalyze = ((float4)anltuples > anlthresh); } - + // 濡傛灉鐢ㄦ埛鍚敤浜嗚嚜鍔ㄦ竻鐞嗭紝鍒欐牴鎹儏鍐垫洿鏂 dovacuum 鐨勫 *dovacuum = *dovacuum && userEnabled; + // 璁板綍鑷姩娓呯悊鍜屽垎鏋愮殑鍐崇瓥鏃ュ織 if (*dovacuum || *doanalyze) { AUTOVAC_LOG(DEBUG2, "vac \"%s\": recheck = %s need_freeze = %s dovacuum = %s (dead tuples %ld " "vacuum threshold %.0f) doanalyze = %s (changed tuples %ld analyze threshold %.0f)", @@ -3141,6 +3452,7 @@ static void relation_needs_vacanalyze(Oid relid, AutoVacOpts* relopts, Form_pg_c *dovacuum ? "true" : "false", vactuples, vacthresh, *doanalyze ? "true" : "false", anltuples, anlthresh); } + // 鎵撳嵃璇︾粏鐨勮嚜鍔ㄦ竻鐞嗘棩蹇 DEBUG_VACUUM_LOG(relid, classForm->relnamespace, LOG, "vac \"%s\": recheck = %s need_freeze = %s dovacuum = %s " "(dead tuples %ld vacuum threshold %.0f) doanalyze = %s (changed tuples %ld analyze threshold %.0f) reltuples " "= %.0f", NameStr(classForm->relname), is_recheck ? "true" : "false", *need_freeze ? "true" : "false", @@ -3153,19 +3465,27 @@ static void relation_needs_vacanalyze(Oid relid, AutoVacOpts* relopts, Form_pg_c * * fill in the vacuum statement. */ +// 濉厖 VACUUM 璇彞 static void fill_in_vac_stmt(VacuumStmt& vacstmt, const autovac_table& tab, RangeVar* rangevar) { + // 璁剧疆 VACUUM 璇彞鐨勭被鍨嬩负 T_VacuumStmt vacstmt.type = T_VacuumStmt; + // 鏍规嵁琛ㄧ殑闇瑕佹槸鍚﹀喕缁撹缃 VACUUM 閫夐」 if (!tab.at_needfreeze) vacstmt.options = VACOPT_NOWAIT; + // 鏍规嵁琛ㄧ殑闇瑕佹槸鍚︽墽琛 VACUUM 璁剧疆 VACUUM 閫夐」 if (tab.at_dovacuum) vacstmt.options = (unsigned int)vacstmt.options | VACOPT_VACUUM; + // 鏍规嵁琛ㄧ殑闇瑕佹槸鍚︽墽琛 ANALYZE 璁剧疆 VACUUM 閫夐」 if (tab.at_doanalyze) vacstmt.options = (unsigned int)vacstmt.options | VACOPT_ANALYZE; #ifdef ENABLE_MOT +// 濡傛灉鍚敤浜 MOT 瀛樺偍寮曟搸锛岃缃 VACUUM 閫夐」 vacstmt.options |= VACOPT_AUTOVAC; #endif + // 璁剧疆 VACUUM 璇彞鐨勬爣蹇 vacstmt.flags = tab.at_flags; + // 璁剧疆 VACUUM 璇彞鐨 rely_oid 涓烘棤鏁堝 vacstmt.rely_oid = InvalidOid; /* we just simple set it invalid, maybe change */ vacstmt.freeze_min_age = tab.at_freeze_min_age; vacstmt.freeze_table_age = tab.at_freeze_table_age; @@ -3178,83 +3498,85 @@ static void fill_in_vac_stmt(VacuumStmt& vacstmt, const autovac_table& tab, Rang * autovacuum_do_vac_analyze * Vacuum and/or analyze the specified table */ +// 鎵ц鑷姩娓呯悊涓殑 VACUUM 鍜 ANALYZE 鎿嶄綔 static void autovacuum_do_vac_analyze(autovac_table* tab, BufferAccessStrategy bstrategy) { - VacuumStmt vacstmt; - RangeVar rangevar; - const char* nspname = NULL; - const char* relname = NULL; - const char* partname = NULL; - StringInfoData str; - errno_t rc = EOK; + VacuumStmt vacstmt; // 鐢ㄤ簬瀛樺偍 VACUUM 璇彞淇℃伅 + RangeVar rangevar; // 鐢ㄤ簬瀛樺偍琛ㄧ殑鍚嶇О淇℃伅 + const char* nspname = NULL; // 琛ㄧ殑鍛藉悕绌洪棿鍚嶇О + const char* relname = NULL; // 琛ㄧ殑鍏崇郴鍚嶇О + const char* partname = NULL; // 鍒嗗尯琛ㄧ殑鍚嶇О + StringInfoData str; // 鐢ㄤ簬鏋勫缓 VACUUM 璇彞瀛楃涓茬殑缂撳啿鍖 + errno_t rc = EOK; // 鐢ㄤ簬瀛樺偍鍑芥暟璋冪敤鐨勮繑鍥炲 /* Set up command parameters --- use local variables instead of palloc */ - rc = memset_s(&vacstmt, sizeof(vacstmt), 0, sizeof(vacstmt)); + rc = memset_s(&vacstmt, sizeof(vacstmt), 0, sizeof(vacstmt));// 娓呯┖ vacstmt 缁撴瀯浣 securec_check(rc, "", ""); - rc = memset_s(&rangevar, sizeof(rangevar), 0, sizeof(rangevar)); + rc = memset_s(&rangevar, sizeof(rangevar), 0, sizeof(rangevar));// 娓呯┖ rangevar 缁撴瀯浣 securec_check(rc, "", ""); - rangevar.schemaname = tab->at_nspname; - rangevar.relname = tab->at_relname; - if (NULL != tab->at_partname) { - rangevar.ispartition = true; - rangevar.partitionname = tab->at_partname; + rangevar.schemaname = tab->at_nspname; // 璁剧疆鍛藉悕绌洪棿鍚嶇О + rangevar.relname = tab->at_relname; // 璁剧疆鍏崇郴鍚嶇О + if (NULL != tab->at_partname) { // 濡傛灉瀛樺湪鍒嗗尯鍚嶇О + rangevar.ispartition = true; // 鏍囪涓哄垎鍖鸿〃 + rangevar.partitionname = tab->at_partname; // 璁剧疆鍒嗗尯琛ㄥ悕绉 } - rangevar.location = -1; + rangevar.location = -1; // 璁剧疆浣嶇疆淇℃伅 - nspname = quote_identifier(tab->at_nspname); - relname = quote_identifier(tab->at_relname); + nspname = quote_identifier(tab->at_nspname); // 瀵瑰懡鍚嶇┖闂村悕绉拌繘琛屾爣璇嗙寮曠敤 + relname = quote_identifier(tab->at_relname); // 瀵瑰叧绯诲悕绉拌繘琛屾爣璇嗙寮曠敤 if (NULL != tab->at_partname) - partname = quote_identifier(tab->at_partname); + partname = quote_identifier(tab->at_partname); // 瀵瑰垎鍖鸿〃鍚嶇О杩涜鏍囪瘑绗﹀紩鐢 - fill_in_vac_stmt(vacstmt, *tab, &rangevar); - initStringInfo(&str); + fill_in_vac_stmt(vacstmt, *tab, &rangevar); // 濉厖 VACUUM 璇彞淇℃伅 + initStringInfo(&str); // 鍒濆鍖栫敤浜庢瀯寤鸿鍙ュ瓧绗︿覆鐨勭紦鍐插尯 if (tab->at_dovacuum) - appendStringInfo(&str, "VACUUM "); + appendStringInfo(&str, "VACUUM "); // 濡傛灉闇瑕佹墽琛 VACUUM锛屾坊鍔 VACUUM 鍏抽敭瀛 if (tab->at_doanalyze) - appendStringInfo(&str, "ANALYZE "); - appendStringInfo(&str, "%s.%s", nspname, relname); + appendStringInfo(&str, "ANALYZE "); // 濡傛灉闇瑕佹墽琛 ANALYZE锛屾坊鍔 ANALYZE 鍏抽敭瀛 + appendStringInfo(&str, "%s.%s", nspname, relname); // 娣诲姞琛ㄧ殑鍛藉悕绌洪棿鍜屽叧绯诲悕绉 if (NULL != tab->at_partname) - appendStringInfo(&str, " PARTITION (%s)", partname); + appendStringInfo(&str, " PARTITION (%s)", partname); // 濡傛灉鏄垎鍖鸿〃锛屾坊鍔犲垎鍖鸿〃鍚嶇О - WaitStatePhase oldPhase = pgstat_report_waitstatus_phase(PHASE_AUTOVACUUM); - DEBUG_MOD_START_TIMER(MOD_AUTOVAC); - DoVacuumMppTable(&vacstmt, str.data, true, false); - DEBUG_MOD_STOP_TIMER(MOD_AUTOVAC, "AUTOVAC TIMER: %s", str.data); - pgstat_report_waitstatus_phase(oldPhase); + WaitStatePhase oldPhase = pgstat_report_waitstatus_phase(PHASE_AUTOVACUUM); // 璁剧疆绛夊緟鐘舵侀樁娈典负鑷姩娓呯悊 + DEBUG_MOD_START_TIMER(MOD_AUTOVAC); // 鍚姩璁℃椂鍣ㄨ褰曡嚜鍔ㄦ竻鐞嗚楁椂 + DoVacuumMppTable(&vacstmt, str.data, true, false); // 鎵ц VACUUM 鎴 ANALYZE 鎿嶄綔 + DEBUG_MOD_STOP_TIMER(MOD_AUTOVAC, "AUTOVAC TIMER: %s", str.data); // 鍋滄璁℃椂鍣紝璁板綍鑷姩娓呯悊鑰楁椂 + pgstat_report_waitstatus_phase(oldPhase); // 鎭㈠绛夊緟鐘舵侀樁娈 } /* * autovacuum_do_vac_analyze * Vacuum and/or analyze the specified table */ +// 瀵规寚瀹氱殑琛ㄦ墽琛 VACUUM 鍜/鎴 ANALYZE 鎿嶄綔 static void autovacuum_local_vac_analyze(autovac_table* tab, BufferAccessStrategy bstrategy) { - VacuumStmt vacstmt; - RangeVar rangevar; - errno_t rc = EOK; + VacuumStmt vacstmt; // 鐢ㄤ簬瀛樺偍 VACUUM 璇彞淇℃伅 + RangeVar rangevar; // 鐢ㄤ簬瀛樺偍琛ㄧ殑鍚嶇О淇℃伅 + errno_t rc = EOK; // 鐢ㄤ簬瀛樺偍鍑芥暟璋冪敤鐨勮繑鍥炲 /* Set up command parameters --- use local variables instead of palloc */ - rc = memset_s(&vacstmt, sizeof(vacstmt), 0, sizeof(vacstmt)); + rc = memset_s(&vacstmt, sizeof(vacstmt), 0, sizeof(vacstmt)); // 娓呯┖ securec_check(rc, "", ""); - rc = memset_s(&rangevar, sizeof(rangevar), 0, sizeof(rangevar)); + rc = memset_s(&rangevar, sizeof(rangevar), 0, sizeof(rangevar)); // 娓呯┖ securec_check(rc, "", ""); - rangevar.schemaname = tab->at_nspname; - rangevar.relname = tab->at_relname; - rangevar.partitionname = tab->at_partname; - rangevar.location = -1; + rangevar.schemaname = tab->at_nspname; // 璁剧疆鍛藉悕绌洪棿鍚嶇О + rangevar.relname = tab->at_relname; // 璁剧疆鍏崇郴鍚嶇О + rangevar.partitionname = tab->at_partname; // 璁剧疆鍒嗗尯琛ㄥ悕绉 + rangevar.location = -1; // 璁剧疆浣嶇疆淇℃伅 - fill_in_vac_stmt(vacstmt, *tab, &rangevar); + fill_in_vac_stmt(vacstmt, *tab, &rangevar); // 濉厖 VACUUM 璇彞淇℃伅 /* Let pgstat know what we're doing */ autovac_report_activity(tab); - WaitStatePhase oldPhase = pgstat_report_waitstatus_phase(PHASE_AUTOVACUUM); - DEBUG_MOD_START_TIMER(MOD_AUTOVAC); - vacuum(&vacstmt, tab->at_relid, false, bstrategy, true); - DEBUG_MOD_STOP_TIMER(MOD_AUTOVAC, "AUTOVAC TIMER: %s", tab->at_relname); - pgstat_report_waitstatus_phase(oldPhase); + WaitStatePhase oldPhase = pgstat_report_waitstatus_phase(PHASE_AUTOVACUUM); // 璁剧疆绛夊緟鐘舵侀樁娈典负鑷姩娓呯悊 + DEBUG_MOD_START_TIMER(MOD_AUTOVAC); // 鍚姩璁℃椂鍣ㄨ褰曡嚜鍔ㄦ竻鐞嗚楁椂 + vacuum(&vacstmt, tab->at_relid, false, bstrategy, true); // 鎵ц VACUUM 鎴 ANALYZE 鎿嶄綔 + DEBUG_MOD_STOP_TIMER(MOD_AUTOVAC, "AUTOVAC TIMER: %s", tab->at_relname); // 鍋滄璁℃椂鍣紝璁板綍鑷姩娓呯悊鑰楁椂 + pgstat_report_waitstatus_phase(oldPhase); // 鎭㈠绛夊緟鐘舵侀樁娈 } /* @@ -3268,15 +3590,16 @@ static void autovacuum_local_vac_analyze(autovac_table* tab, BufferAccessStrateg * done with the current one, and exit right after the last one, so we don't * bother to report "" or some such. */ +// 鍚 pgstat 姹囨姤鑷姩娓呯悊姝e湪鎵ц鐨勬搷浣滅姸鎬佸拰娲诲姩淇℃伅 static void autovac_report_activity(autovac_table* tab) { #define MAX_AUTOVAC_ACTIV_LEN (NAMEDATALEN * 2 + 56) - char activity[MAX_AUTOVAC_ACTIV_LEN]; + char activity[MAX_AUTOVAC_ACTIV_LEN]; // 瀛樺偍瑕佹姤鍛婄殑瀛楃涓 int len; int rc = 0; /* Report the command and possible options */ - if (tab->at_dovacuum) + if (tab->at_dovacuum) // 濡傛灉闇瑕佹墽琛 VACUUM 鎿嶄綔 rc = snprintf_s(activity, MAX_AUTOVAC_ACTIV_LEN, MAX_AUTOVAC_ACTIV_LEN - 1, "autovacuum: VACUUM%s", tab->at_doanalyze ? " ANALYZE" : ""); else @@ -3295,7 +3618,7 @@ static void autovac_report_activity(autovac_table* tab) /* Set statement_timestamp() to current time for pg_stat_activity */ SetCurrentStatementStartTimestamp(); - pgstat_report_activity(STATE_RUNNING, activity); + pgstat_report_activity(STATE_RUNNING, activity); // 鍚 pgstat 姹囨姤鑷姩娓呯悊姝e湪鎵ц鐨勬搷浣滅姸鎬佸拰娲诲姩淇℃伅 } /* @@ -3305,6 +3628,7 @@ static void autovac_report_activity(autovac_table* tab) */ bool AutoVacuumingActive(void) { + // 妫鏌ユ槸鍚﹀惎鐢ㄤ簡鑷姩娓呯悊瀹堟姢杩涚▼鍜岀粺璁℃暟鎹窡韪 if (!u_sess->attr.attr_storage.autovacuum_start_daemon || !u_sess->attr.attr_common.pgstat_track_counts) return false; return true; @@ -3318,6 +3642,7 @@ bool AutoVacuumingActive(void) */ void autovac_init(void) { + // 濡傛灉鍚敤浜嗚嚜鍔ㄦ竻鐞嗗畧鎶よ繘绋嬩絾娌℃湁鍚敤缁熻鏁版嵁璺熻釜锛屽彂鍑鸿鍛 if (u_sess->attr.attr_storage.autovacuum_start_daemon && !u_sess->attr.attr_common.pgstat_track_counts) ereport(WARNING, (errmsg("autovacuum not started because of misconfiguration"), errhint("Enable the \"track_counts\" option."))); @@ -3328,20 +3653,25 @@ void autovac_init(void) * Return whether this is either a launcher autovacuum process or a worker * process. */ +// 妫鏌ユ槸鍚︿负鑷姩娓呯悊鍚姩鍣ㄨ繘绋 bool IsAutoVacuumLauncherProcess(void) { return t_thrd.role == AUTOVACUUM_LAUNCHER; } +// 妫鏌ユ槸鍚︿负鑷姩娓呯悊宸ヤ綔杩涚▼ bool IsAutoVacuumWorkerProcess(void) { return t_thrd.role == AUTOVACUUM_WORKER; } +// 瀹氫箟鑷姩娓呯悊宸ヤ綔杩涚▼鐨勫簲鐢ㄧ▼搴忓悕绉 const char* AUTO_VACUUM_WORKER = "AutoVacWorker"; +// 妫鏌ュ綋鍓嶄細璇濇槸鍚︽潵鑷嚜鍔ㄦ竻鐞嗗伐浣滆繘绋 bool IsFromAutoVacWoker(void) { + // 妫鏌ュ綋鍓嶄細璇濈殑搴旂敤绋嬪簭鍚嶇О鏄惁涓庤嚜鍔ㄦ竻鐞嗗伐浣滆繘绋嬬殑鍚嶇О鐩稿尮閰 return (u_sess->attr.attr_common.application_name != NULL && strcmp(u_sess->attr.attr_common.application_name, AUTO_VACUUM_WORKER) == 0); } @@ -3350,6 +3680,7 @@ bool IsFromAutoVacWoker(void) * AutoVacuumShmemSize * Compute space needed for autovacuum-related shared memory */ +// 璁$畻鐢ㄤ簬鑷姩娓呯悊鐩稿叧鍏变韩鍐呭瓨鎵闇鐨勭┖闂村ぇ灏 Size AutoVacuumShmemSize(void) { Size size; @@ -3357,8 +3688,8 @@ Size AutoVacuumShmemSize(void) /* * Need the fixed struct and the array of WorkerInfoData. */ - size = sizeof(AutoVacuumShmemStruct); - size = MAXALIGN(size); + size = sizeof(AutoVacuumShmemStruct); // 璁$畻闇瑕佺殑绌洪棿澶у皬 + size = MAXALIGN(size); // 瀵归綈鍒版渶澶у榻愭暟 size = add_size(size, mul_size(g_instance.attr.attr_storage.autovacuum_max_workers, sizeof(WorkerInfoData))); return size; } @@ -3371,9 +3702,11 @@ void AutoVacuumShmemInit(void) { bool found = false; + // 鍒嗛厤鑷姩娓呯悊鐩稿叧鐨勫叡浜唴瀛 t_thrd.autovacuum_cxt.AutoVacuumShmem = (AutoVacuumShmemStruct*)ShmemInitStruct("AutoVacuum Data", AutoVacuumShmemSize(), &found); + // 濡傛灉鎵惧埌鍏变韩鍐呭瓨鍧楋紝鎶ュ憡涓ラ噸閿欒锛屽洜涓轰笉搴旇鍐嶆鍒濆鍖 if (!IsUnderPostmaster) { WorkerInfo worker = NULL; int i = 0; @@ -3382,11 +3715,13 @@ void AutoVacuumShmemInit(void) ereport(PANIC, (errmsg("AutoVacuum Data share mem is already init"))); } + // 鍒濆鍖 AutoVacuumShmem 缁撴瀯鐨勫瓧娈 t_thrd.autovacuum_cxt.AutoVacuumShmem->av_launcherpid = 0; t_thrd.autovacuum_cxt.AutoVacuumShmem->av_freeWorkers = NULL; SHMQueueInit(&t_thrd.autovacuum_cxt.AutoVacuumShmem->av_runningWorkers); t_thrd.autovacuum_cxt.AutoVacuumShmem->av_startingWorker = NULL; + // 鍒濆鍖 WorkerInfo 鏁版嵁 worker = (WorkerInfo)((char*)t_thrd.autovacuum_cxt.AutoVacuumShmem + MAXALIGN(sizeof(AutoVacuumShmemStruct))); /* initialize the WorkerInfo free list */ @@ -3395,6 +3730,7 @@ void AutoVacuumShmemInit(void) t_thrd.autovacuum_cxt.AutoVacuumShmem->av_freeWorkers = &worker[i]; } } else { + // 濡傛灉娌℃湁鎵惧埌鍏变韩鍐呭瓨鍧楋紝鎶ュ憡涓ラ噸閿欒锛屽洜涓哄繀椤诲湪璇ユ儏鍐典笅鍒濆鍖 if (unlikely(!found)) { ereport(PANIC, (errmsg("AutoVacuum Data share mem is not init"))); } @@ -3413,26 +3749,30 @@ void AutoVacuumShmemInit(void) * Note: we avoid throttling in the autovac worker, as it would be * counterproductive in the recheck logic. */ +// 鍒锋柊鑷姩娓呯悊杩涚▼鐨 pgstats 鏁版嵁 static void autovac_refresh_stats(void) { if (IsAutoVacuumLauncherProcess()) { TimestampTz current_time; - current_time = GetCurrentTimestamp(); + current_time = GetCurrentTimestamp(); // 鑾峰彇褰撳墠鏃堕棿鎴 + // 濡傛灉涓庝笂娆¤鍙栨椂闂撮棿闅斾笉瓒呰繃 STATS_READ_DELAY锛屽垯涓嶅埛鏂 if (!TimestampDifferenceExceeds(t_thrd.autovacuum_cxt.last_read, current_time, STATS_READ_DELAY)) return; + // 鏇存柊涓婃璇诲彇鏃堕棿 t_thrd.autovacuum_cxt.last_read = current_time; } - pgstat_clear_snapshot(); + pgstat_clear_snapshot(); // 娓呴櫎 pgstats 蹇収鏁版嵁 } - +// 鐢ㄤ簬纭畾鍒嗗尯琛ㄦ槸鍚﹂渶瑕佹墽琛岃嚜鍔ㄧ殑VACUUM鍜孉NALYZE鎿嶄綔锛屽苟鏍规嵁鍚勭鍙傛暟鍜岄槇鍊兼潵鍐冲畾鏄惁鎵ц杩欎簺鎿嶄綔銆傚悓鏃讹紝璁板綍鐩稿叧淇℃伅浠ヤ究浜庤皟璇曞拰鐩戞帶 static void partition_needs_vacanalyze(Oid partid, AutoVacOpts* relopts, Form_pg_partition partForm, HeapTuple partTuple, at_partitioned_table* ap_entry, PgStat_StatTabEntry* tabentry, bool is_recheck, bool* dovacuum, bool* doanalyze, bool* need_freeze) { + // 鍒濆鍖栧拰鍙傛暟璁剧疆 PgStat_StatTabKey tablekey; avw_info* avwentry = NULL; bool found = false; @@ -3462,10 +3802,13 @@ static void partition_needs_vacanalyze(Oid partid, AutoVacOpts* relopts, Form_pg Oid nameSpaceOid = InvalidOid; char* partname = NULL; + // 鏂█纭繚 partForm 涓嶄负 NULL 骞朵笖 partid 涓烘湁鏁堢殑 Oid AssertArg(partForm != NULL && OidIsValid(partid)); + // 鑾峰彇鑷姩VACUUM鍜孉NALYZE鎿嶄綔鎵闇鐨勫弬鏁 determine_vacuum_params(vac_scale_factor, vac_base_thresh, anl_scale_factor, anl_base_thresh, freeze_max_age, av_enabled, xidForceLimit, multiForceLimit, relopts); /* Force vacuum if table need freeze the old tuple to recycle clog */ + // 濡傛灉闇瑕佸喕缁撴棫鐨勫厓缁勪互鍥炴敹CLOG锛屽己鍒惰繘琛孷ACUUM鎿嶄綔 if (t_thrd.autovacuum_cxt.recentXid > FirstNormalTransactionId + freeze_max_age) xidForceLimit = t_thrd.autovacuum_cxt.recentXid - freeze_max_age; else @@ -3473,17 +3816,21 @@ static void partition_needs_vacanalyze(Oid partid, AutoVacOpts* relopts, Form_pg bool isNull = false; TransactionId relfrozenxid = InvalidTransactionId; + // 鎵撳紑 pg_partition 鍏崇郴锛屼娇鐢 AccessShareLock 妯″紡 Relation rel = heap_open(PartitionRelationId, AccessShareLock); + // 鑾峰彇 pg_partition.relfrozenxid64 瀛楁鐨勫 Datum xid64datum = heap_getattr(partTuple, Anum_pg_partition_relfrozenxid64, RelationGetDescr(rel), &isNull); - if (isNull) { + if (isNull) {// 濡傛灉 xid64datum 鐨勫间负 NULL锛岃鏄 pg_partition.relfrozenxid64 瀛楁涓虹┖ relfrozenxid = partForm->relfrozenxid; + // 濡傛灉褰撳墠鐨 nextXid 姣 relfrozenxid 灏忥紝鎴栬 relfrozenxid 涓嶆槸姝e父浜嬪姟ID if (TransactionIdPrecedes(t_thrd.xact_cxt.ShmemVariableCache->nextXid, relfrozenxid) || !TransactionIdIsNormal(relfrozenxid)) { relfrozenxid = FirstNormalTransactionId; } } else { + // 濡傛灉 xid64datum 鐨勫间笉涓 NULL锛屽皢鍏朵綔涓 relfrozenxid 鐨勫 relfrozenxid = DatumGetTransactionId(xid64datum); } @@ -3491,21 +3838,26 @@ static void partition_needs_vacanalyze(Oid partid, AutoVacOpts* relopts, Form_pg if (!force_vacuum) { Datum mxidDatum = heap_getattr(partTuple, Anum_pg_partition_relminmxid, RelationGetDescr(rel), &isNull); MultiXactId relminmxid = isNull ? FirstMultiXactId : DatumGetTransactionId(mxidDatum); + // 妫鏌 relminmxid 鏄惁鏈夋晥涓旀棭浜 multiForceLimit force_vacuum = (MultiXactIdIsValid(relminmxid) && MultiXactIdPrecedes(relminmxid, multiForceLimit)); } #endif - heap_close(rel, AccessShareLock); + heap_close(rel, AccessShareLock); // 鍏抽棴鍏宠仈鐨勫叧绯 + // 妫鏌 relfrozenxid 鏄惁涓烘甯镐簨鍔D涓旀棭浜 xidForceLimit force_vacuum = (TransactionIdIsNormal(relfrozenxid) && TransactionIdPrecedes(relfrozenxid, xidForceLimit)); + // 璁剧疆 need_freeze 鏍囧織锛岃〃绀烘槸鍚﹂渶瑕佹墽琛屽喕缁撴搷浣 *need_freeze = force_vacuum; /* User disabled it in pg_class.reloptions? (But ignore if at risk) */ + // 濡傛灉鐢ㄦ埛绂佺敤浜嗚嚜鍔╒ACUUM锛屾垨鑰呯鐢ㄤ簡autovacuum_start_daemon GUC閫夐」 if (!force_vacuum && (!av_enabled || !u_sess->attr.attr_storage.autovacuum_start_daemon)) { + // 涓嶆墽琛孉NALYZE鍜孷ACUUM鎿嶄綔 *doanalyze = false; *dovacuum = false; return; } - + // 濡傛灉涓嶉渶瑕佸己鍒惰繘琛孷ACUUM鎿嶄綔锛屼笖涓嶅厑璁告墽琛孷ACUUM鎿嶄綔鎴栬呭凡缁忔墽琛岃繃VACUUM鎿嶄綔 if (!force_vacuum && (!ap_entry->at_allowvacuum || ap_entry->at_dovacuum)) { *doanalyze = false; *dovacuum = false; @@ -3517,16 +3869,21 @@ static void partition_needs_vacanalyze(Oid partid, AutoVacOpts* relopts, Form_pg partname = NameStr(partForm->relname); reltuples = partForm->reltuples; + // 璁$畻ANALYZE鎿嶄綔鐨勯槇鍊 anlthresh = (float4)anl_base_thresh + anl_scale_factor * reltuples; + // 璁$畻VACUUM鎿嶄綔鐨勯槇鍊 vacthresh = (float4)vac_base_thresh + vac_scale_factor * reltuples; if (NULL != t_thrd.autovacuum_cxt.pgStatAutoVacInfo) { + // 璁剧疆琛ㄩ敭鐨勭粺璁℃爣蹇楀拰琛↖D tablekey.statFlag = partForm->parentid; tablekey.tableid = partid; + // 鍦 pgStatAutoVacInfo 涓煡鎵句笌琛ㄩ敭鍖归厤鐨 avw_info 璁板綍 avwentry = (avw_info*)hash_search(t_thrd.autovacuum_cxt.pgStatAutoVacInfo, (void*)(&tablekey), HASH_FIND, &found); } + // 鏍规嵁涓嶅悓鎯呭喌璁$畻鍙樺寲鍜屾鍏冪粍鐨勬暟閲忥紝骞舵牴鎹槇鍊煎拰缁熻淇℃伅鍒ゆ柇鏄惁闇瑕佹墽琛孷ACUUM鍜孉NALYZE鎿嶄綔 if ((avwentry == NULL) && (tabentry == NULL)) { *doanalyze = false; *dovacuum = force_vacuum; @@ -3568,6 +3925,7 @@ static void partition_needs_vacanalyze(Oid partid, AutoVacOpts* relopts, Form_pg *doanalyze = (anltuples > anlthresh) && false; } + // 鍦ㄩ渶瑕佹墽琛岃嚜鍔╒ACUUM鍜孉NALYZE鎿嶄綔鐨勬儏鍐典笅锛岃褰曞拰杈撳嚭鐩稿簲鐨勮皟璇曟棩蹇椼 if (!is_recheck && (*dovacuum || *doanalyze)) { AUTOVAC_LOG(DEBUG2, "vac table \"%s\" partition(\"%s\"): recheck = %s need_freeze = %s " "dovacuum = %s (dead tuples %ld vacuum threshold %.0f)", @@ -3581,60 +3939,68 @@ static void partition_needs_vacanalyze(Oid partid, AutoVacOpts* relopts, Form_pg *dovacuum ? "true" : "false", vactuples, vacthresh, reltuples); } +// 鐢ㄤ簬閲嶆柊妫鏌ュ垎鍖鸿〃鏄惁闇瑕佽繘琛岃嚜鍔╒ACUUM鎿嶄綔锛屽苟璁$畻闇瑕佹墽琛岀殑鎿嶄綔鍙婂弬鏁伴厤缃 static autovac_table* partition_recheck_autovac( vacuum_object* vacObj, HTAB* table_relopt_map, HTAB* partitioned_tables_map, TupleDesc pg_class_desc) { - Oid partid = vacObj->tab_oid; - bool dovacuum = false; - bool doanalyze = false; - bool dovacuum_toast = vacObj->dovacuum_toast; - bool need_freeze = false; - autovac_table* tab = NULL; - PgStat_StatTabEntry* tabentry = NULL; - PgStat_StatDBEntry* shared = NULL; - PgStat_StatDBEntry* dbentry = NULL; - at_partitioned_table* ap_entry = NULL; - AutoVacOpts* avopts = NULL; - av_relation* hentry = NULL; - bool found = false; - Form_pg_partition partForm; - HeapTuple partTuple; - Oid relid; + Oid partid = vacObj->tab_oid; // 鍒嗗尯琛ㄧ殑OID + bool dovacuum = false; // 鏄惁闇瑕佽繘琛孷ACUUM鎿嶄綔 + bool doanalyze = false; // 鏄惁闇瑕佽繘琛孉NALYZE鎿嶄綔 + bool dovacuum_toast = vacObj->dovacuum_toast; // 鏄惁闇瑕佸TOAST琛ㄨ繘琛孷ACUUM鎿嶄綔 + bool need_freeze = false; // 鏄惁闇瑕佸喕缁撴棫鍏冪粍浠ュ洖鏀禖LOG + autovac_table* tab = NULL; // 瀛樺偍鑷姩VACUUM鎿嶄綔鐨勪俊鎭 + PgStat_StatTabEntry* tabentry = NULL; // 缁熻淇℃伅涓殑琛ㄧ骇鍒叆鍙 + PgStat_StatDBEntry* shared = NULL; // 鍏ㄥ眬缁熻淇℃伅鍏ュ彛 + PgStat_StatDBEntry* dbentry = NULL; // 褰撳墠鏁版嵁搴撶殑缁熻淇℃伅鍏ュ彛 + at_partitioned_table* ap_entry = NULL; // 鍒嗗尯琛ㄧ殑淇℃伅鍏ュ彛 + AutoVacOpts* avopts = NULL; // 鑷姩VACUUM鐨勯夐」 + av_relation* hentry = NULL; // 琛ㄥ叧绯荤殑淇℃伅鍏ュ彛 + bool found = false; // 鏍囪鏄惁鎵惧埌鐩稿叧淇℃伅 + Form_pg_partition partForm; // 鍒嗗尯琛ㄧ殑琛ㄥ崟淇℃伅 + HeapTuple partTuple; // 鍒嗗尯琛ㄧ殑鍏冪粍 + Oid relid; // 鍏宠仈鐨勮〃鐨凮ID + // 鍦ㄥ崟鑺傜偣妯″紡涓嬪埛鏂扮粺璁′俊鎭 if (IS_SINGLE_NODE) { /* use fresh stats */ autovac_refresh_stats(); } /* fetch the partition's syscache entry */ + // 鑾峰彇鍒嗗尯琛ㄧ殑syscache鏉$洰 partTuple = SearchSysCacheCopy1(PARTRELID, ObjectIdGetDatum(partid)); if (!HeapTupleIsValid(partTuple)) return NULL; - partForm = (Form_pg_partition)GETSTRUCT(partTuple); - relid = partForm->parentid; - shared = pgstat_fetch_stat_dbentry(InvalidOid); - dbentry = pgstat_fetch_stat_dbentry(u_sess->proc_cxt.MyDatabaseId); + partForm = (Form_pg_partition)GETSTRUCT(partTuple); // 鑾峰彇鍒嗗尯琛ㄧ殑琛ㄥ崟淇℃伅 + relid = partForm->parentid; // 鑾峰彇鍏宠仈琛ㄧ殑OID + shared = pgstat_fetch_stat_dbentry(InvalidOid); // 鑾峰彇鍏ㄥ眬缁熻淇℃伅鍏ュ彛 + dbentry = pgstat_fetch_stat_dbentry(u_sess->proc_cxt.MyDatabaseId); // 鑾峰彇褰撳墠鏁版嵁搴撶殑缁熻淇℃伅鍏ュ彛 /* fetch the relation's syscache entry */ + // 浠庤〃鍏崇郴閫夐」鏄犲皠涓幏鍙栧叧鑱旇〃鐨剆yscache鏉$洰 hentry = (av_relation*)hash_search(table_relopt_map, &relid, HASH_FIND, &found); + // 濡傛灉鏈壘鍒板叧鑱旇〃鐨勯夐」淇℃伅鎴栭夐」淇℃伅涓嶅瓨鍦紝鍒欐姤鍛婃暟鎹崯鍧忛敊璇 if (!(found && hentry->ar_hasrelopts)) { ereport(defence_errlevel(), (errcode(ERRCODE_DATA_CORRUPTED), errmsg("Oid: %u does not " "find in rel options map.", relid))); } - avopts = &(hentry->ar_reloptions); + avopts = &(hentry->ar_reloptions); // 鑾峰彇鍏宠仈琛ㄧ殑閫夐」淇℃伅鎸囬拡 /* fetch the pgstat table entry */ + // 浠庡垎鍖鸿〃鏄犲皠涓幏鍙杙gstat琛ㄧ骇鍒殑鏉$洰 ap_entry = (at_partitioned_table*)hash_search(partitioned_tables_map, &partForm->parentid, HASH_FIND, &found); if (!found) { ereport(defence_errlevel(), (errcode(ERRCODE_DATA_CORRUPTED), errmsg("Oid: %u does not " "find in partitioned tables map.", partForm->parentid))); } tabentry = get_pgstat_tabentry_relid(partid, false, relid, shared, dbentry); + // 纭畾鍒嗗尯琛ㄦ槸鍚﹂渶瑕佽繘琛孷ACUUM鎴朅NALYZE partition_needs_vacanalyze( partid, avopts, partForm, partTuple, ap_entry, tabentry, true, &dovacuum, &doanalyze, &need_freeze); Assert(false == doanalyze); /* OK, it needs something done */ + // 濡傛灉闇瑕佽繘琛孷ACUUM鎴朅NALYZE锛岃绠楁墍闇鐨勬搷浣滃拰鍙傛暟 if (dovacuum || dovacuum_toast) { tab = calculate_vacuum_cost_and_freezeages(avopts, doanalyze, need_freeze); if (tab != NULL) { @@ -3644,7 +4010,7 @@ static autovac_table* partition_recheck_autovac( } } - heap_freetuple(partTuple); + heap_freetuple(partTuple); // 閲婃斁缂撳瓨涓殑鍏崇郴鍏冪粍 return tab; } diff --git a/src/gausskernel/process/postmaster/barrier_arch.cpp b/src/gausskernel/process/postmaster/barrier_arch.cpp index 51bfbaa7d..0167a0427 100755 --- a/src/gausskernel/process/postmaster/barrier_arch.cpp +++ b/src/gausskernel/process/postmaster/barrier_arch.cpp @@ -52,60 +52,72 @@ #define atolsn(x) ((XLogRecPtr)strtoul((x), NULL, 0)) +// 灏哹arrier_id 鍐欏叆鍒癘BS锛堝崕涓轰簯瀵硅薄瀛樺偍锛変腑锛岀敤浜庡疄鐜版暟鎹瓨妗 static void write_barrier_id_to_obs(const char* barrier_name, ArchiveConfig *archive_obs) { - errno_t rc = 0; - ArchiveConfig obsConfig; - char pathPrefix[MAXPGPATH] = {0}; + errno_t rc = 0; // 鐢ㄤ簬瀛樺偍鍑芥暟璋冪敤鐨勮繑鍥炲硷紝浠ヤ究妫鏌ラ敊璇 + ArchiveConfig obsConfig; // 瀛樺偍OBS閰嶇疆鐨勪复鏃跺彉閲 + char pathPrefix[MAXPGPATH] = {0}; // 鐢ㄤ簬瀛樺偍OBS璺緞鍓嶇紑鐨勪复鏃跺彉閲 - ereport(LOG, (errmsg("Write barrierId <%s> to obs start", barrier_name))); + ereport(LOG, (errmsg("Write barrierId <%s> to obs start", barrier_name))); // 杈撳嚭鏃ュ織锛岃〃绀哄紑濮嬪啓鍏arrierID鍒癘BS /* copy OBS configs to temporary variable for customising file path */ - rc = memcpy_s(&obsConfig, sizeof(ArchiveConfig), archive_obs, sizeof(ArchiveConfig)); + rc = memcpy_s(&obsConfig, sizeof(ArchiveConfig), archive_obs, sizeof(ArchiveConfig)); // 灏哋BS閰嶇疆澶嶅埗鍒颁复鏃跺彉閲忥紝浠ヤ究鑷畾涔夋枃浠惰矾寰 securec_check(rc, "", ""); - if (!IS_PGXC_COORDINATOR) { - rc = strcpy_s(pathPrefix, MAXPGPATH, obsConfig.archive_prefix); + if (!IS_PGXC_COORDINATOR) { // 濡傛灉涓嶆槸PGXC鍗忚皟鍣 + rc = strcpy_s(pathPrefix, MAXPGPATH, obsConfig.archive_prefix); // 灏哋BS璺緞鍓嶇紑澶嶅埗鍒皃athPrefix涓 securec_check(rc, "\0", "\0"); - char *p = strrchr(pathPrefix, '/'); + // 鏌ユ壘璺緞涓殑鏈鍚庝竴涓 '/' + char *p = strrchr(pathPrefix, '/'); if (p == NULL) { + // 濡傛灉鎵句笉鍒版渶鍚庝竴涓 '/'锛屽垯杈撳嚭閿欒骞剁粓姝 ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("Obs path prefix is invalid"))); } + // 灏嗘壘鍒扮殑鏈鍚庝竴涓 '/' 鏇挎崲涓哄瓧绗︿覆缁撴潫绗︼紝浠ユ埅鍙栬矾寰勫墠缂 *p = '\0'; + // 灏嗕慨鏀瑰悗鐨勮矾寰勫墠缂璧嬪煎洖obsConfig obsConfig.archive_prefix = pathPrefix; } + // 璋冪敤ArchiveWrite鍑芥暟锛屽皢BarrierID鍐欏叆OBS ArchiveWrite(BARRIER_FILE, barrier_name, MAX_BARRIER_ID_LENGTH - 1, &obsConfig); } +// 绛夊緟Barrier褰掓。鎿嶄綔锛岀洿鍒拌揪鍒版寚瀹氱殑LSN static void WaitBarrierArch(XLogRecPtr barrierLsn, const char *slotName) { + // 杈撳嚭鏃ュ織锛岃〃绀哄紑濮嬬瓑寰匓arrier褰掓。鎿嶄綔 ereport(LOG, (errmsg("WaitBarrierArch start: 0x%lx", barrierLsn))); - int cnt = 0; - const int interval = 100; + int cnt = 0; // 鐢ㄤ簬璁℃暟绛夊緟娆℃暟 + const int interval = 100; // 瀹氫箟璁℃暟闂撮殧 do { - ArchiveTaskStatus *archive_task_status = NULL; - archive_task_status = find_archive_task_status(slotName); + ArchiveTaskStatus *archive_task_status = NULL; // 鐢ㄤ簬瀛樺偍褰掓。浠诲姟鐘舵佺殑鎸囬拡 + archive_task_status = find_archive_task_status(slotName); // 鏍规嵁slotName鏌ユ壘褰掓。浠诲姟鐘舵 if (NULL == archive_task_status) { + // 濡傛灉鎵句笉鍒板綊妗d换鍔$姸鎬侊紝杈撳嚭閿欒淇℃伅骞剁粓姝 ereport(ERROR, (errcode(ERRCODE_OPERATE_NOT_SUPPORTED), errmsg("Obs slot <%s> not exist.", slotName))); } + // 姣旇緝barrierLsn鍜屽綋鍓嶅凡褰掓。鐨凩SN锛屽鏋滆揪鍒颁簡瑕佹眰鍒欒烦鍑哄惊鐜 if (XLByteLE(pg_atomic_read_u64(&barrierLsn), pg_atomic_read_u64(&archive_task_status->archived_lsn))) { break; } - CHECK_FOR_INTERRUPTS(); + CHECK_FOR_INTERRUPTS(); // 妫鏌ユ槸鍚︽湁涓柇璇锋眰 /* Also check stop flag */ if (t_thrd.barrier_arch.ready_to_stop) { + // 濡傛灉宸茬粡鍑嗗鍋滄锛屽垯杈撳嚭閿欒淇℃伅骞剁粓姝 ereport(ERROR, (errcode(ERRCODE_ADMIN_SHUTDOWN), errmsg("[BarrierArch] terminating barrier arch" " due to administrator command"))); } - pg_usleep(100000L); + pg_usleep(100000L); // 绛夊緟100000寰锛0.1绉掞級 if (t_thrd.barrier_arch.lastArchiveLoc == pg_atomic_read_u64(&archive_task_status->archived_lsn)) { + // 濡傛灉褰掓。浣嶇疆娌℃湁鍙戠敓鍙樺寲锛岃鏁板姞涓锛屽苟鍦ㄤ竴瀹氶棿闅旇緭鍑鸿鍛婁俊鎭 cnt++; if ((cnt % interval) == 0) { ereport(WARNING, (errmsg("[WaitBarrierArch] arch thread now archived" @@ -113,23 +125,27 @@ static void WaitBarrierArch(XLogRecPtr barrierLsn, const char *slotName) (uint32)t_thrd.barrier_arch.lastArchiveLoc, cnt))); } } else { - cnt = 0; + cnt = 0; // 濡傛灉褰掓。浣嶇疆鍙戠敓鍙樺寲锛岃鏁版竻闆 } + // 鏇存柊褰掓。浣嶇疆锛屽苟妫鏌ユ槸鍚﹁秴杩囦簡绛夊緟瓒呮椂 t_thrd.barrier_arch.lastArchiveLoc = pg_atomic_read_u64(&archive_task_status->archived_lsn); if (cnt > WAIT_ARCHIVE_TIMEOUT) { + // 濡傛灉绛夊緟娆℃暟瓒呰繃浜嗚瀹氱殑瓒呮椂娆℃暟锛岃緭鍑洪敊璇俊鎭苟缁堟 ereport(ERROR, (errcode(ERRCODE_OPERATE_NOT_SUPPORTED), errmsg("Wait archived timeout."))); } - } while (1); + } while (1); // 鏃犻檺寰幆锛岀洿鍒拌揪鍒拌姹傜殑LSN - ereport(LOG, (errmsg("WaitBarrierArch archive lsn end"))); + ereport(LOG, (errmsg("WaitBarrierArch archive lsn end"))); // 杈撳嚭鏃ュ織锛岃〃绀虹瓑寰呭綊妗f搷浣滅粨鏉 } /* * Make sure the current BARRIER WAL record has been archived.If not, wait until * the BARRIER WAL record has been archived. */ +// 纭繚褰撳墠鐨凚ARRIER WAL璁板綍宸茶褰掓。 void ProcessBarrierQueryArchive(char* id) { + // 杈撳嚭鏃ュ織锛岃〃绀烘敹鍒癇ARRIER QUERY娑堟伅 ereport(LOG, (errmsg("Receive BARRIER <%s> QUERY message on Coordinator or Datanode", id))); @@ -137,84 +153,99 @@ void ProcessBarrierQueryArchive(char* id) char *slotName; char *lsn; - lsn = strtok_r(id, ":", &slotName); + lsn = strtok_r(id, ":", &slotName); // 浣跨敤":"鍒嗗壊id锛岃幏鍙朙SN鍜宻lotName if (lsn == NULL) { + // 濡傛灉LSN涓虹┖锛岃緭鍑洪敊璇俊鎭苟缁堟 ereport(ERROR, (errcode(ERRCODE_OPERATE_NOT_SUPPORTED), errmsg("The BARRIER QUERY ARCHIVE target lsn is null"))); } + // 灏哃SN杞崲涓篨LogRecPtr绫诲瀷 XLogRecPtr barrierTargetLsn = atolsn(lsn); + // 杈撳嚭鏃ュ織锛岃〃绀烘敹鍒版寚瀹歀SN娑堟伅 ereport(LOG, (errmsg("Receive LSN <%lx> message on Coordinator or Datanode", barrierTargetLsn))); + // 杈撳嚭鏃ュ織锛岃〃绀烘敹鍒癇ARRIER QUERY娑堟伅鐨剆lotName ereport(LOG, (errmsg("Receive BARRIER QUERY message slotname: %s", slotName))); + // 濡傛灉涓嶆槸浠庡崗璋冨櫒杩炴帴锛岃緭鍑洪敊璇俊鎭苟缁堟 if (!IsConnFromCoord()) ereport(ERROR, (errcode(ERRCODE_OPERATE_NOT_SUPPORTED), errmsg("The BARRIER QUERY ARCHIVE message is expected to " "arrive from a Coordinator"))); - if (!IS_PGXC_COORDINATOR) { - WaitBarrierArch(barrierTargetLsn, slotName); + if (!IS_PGXC_COORDINATOR) { // 濡傛灉涓嶆槸PGXC鍗忚皟鍣 + WaitBarrierArch(barrierTargetLsn, slotName); // 绛夊緟杈惧埌鎸囧畾鐨凩SN } - pq_beginmessage(&buf, 'b'); - pq_sendstring(&buf, id); - pq_endmessage(&buf); - pq_flush(); + pq_beginmessage(&buf, 'b'); // 鍚姩涓涓'b'绫诲瀷鐨勬秷鎭 + pq_sendstring(&buf, id); // 鍚戞秷鎭腑娣诲姞id瀛楃涓 + pq_endmessage(&buf); // 缁撴潫娑堟伅鏋勫缓 + pq_flush(); // 鍒锋柊娑堟伅 鍙戦佺粰瀹㈡埛绔 } +// 澶勭悊鐢ㄤ簬缁堟Barrier褰掓。鐨勪俊鍙 static void BarrierArchWakenStop(SIGNAL_ARGS) { - t_thrd.barrier_arch.ready_to_stop = true; + t_thrd.barrier_arch.ready_to_stop = true; // 璁剧疆鏍囧織锛屽噯澶囩粓姝㈠綊妗 } +// 澶勭悊鏀跺埌SIGHUP淇″彿鐨勬儏鍐 static void BarrierArchSighupHandler(SIGNAL_ARGS) { - int save_errno = errno; - t_thrd.barrier_arch.got_SIGHUP = true; - errno = save_errno; + int save_errno = errno; // 淇濆瓨褰撳墠鐨勯敊璇爜 + t_thrd.barrier_arch.got_SIGHUP = true; // 璁剧疆鏍囧織锛岃〃绀烘敹鍒颁簡SIGHUP淇″彿 + errno = save_errno; // 鎭㈠涔嬪墠淇濆瓨鐨勯敊璇爜 } /* Reset some signals that are accepted by postmaster but not here */ +// 璁剧疆涓嶅悓淇″彿鐨勫鐞嗘柟寮忥紝纭繚绋嬪簭鍦ㄦ敹鍒颁笉鍚岀殑淇″彿鏃惰兘澶熸纭湴澶勭悊 static void BarrierArchSetupSignalHook(void) { - (void)gspqsignal(SIGHUP, BarrierArchSighupHandler); - (void)gspqsignal(SIGINT, SIG_IGN); - (void)gspqsignal(SIGTERM, die); - (void)gspqsignal(SIGQUIT, quickdie); - (void)gspqsignal(SIGALRM, SIG_IGN); - (void)gspqsignal(SIGPIPE, SIG_IGN); - (void)gspqsignal(SIGUSR1, procsignal_sigusr1_handler); - (void)gspqsignal(SIGUSR2, BarrierArchWakenStop); + (void)gspqsignal(SIGHUP, BarrierArchSighupHandler); // 璁剧疆SIGHUP鐨勫鐞嗗嚱鏁颁负BarrierArchSighupHandler + (void)gspqsignal(SIGINT, SIG_IGN); // 蹇界暐SIGINT淇″彿 + (void)gspqsignal(SIGTERM, die); // 璁剧疆SIGTERM鐨勫鐞嗗嚱鏁颁负die + (void)gspqsignal(SIGQUIT, quickdie); // 璁剧疆SIGQUIT鐨勫鐞嗗嚱鏁颁负quickdie + (void)gspqsignal(SIGALRM, SIG_IGN); // 蹇界暐SIGALRM淇″彿 + (void)gspqsignal(SIGPIPE, SIG_IGN); // 蹇界暐SIGPIPE淇″彿 + (void)gspqsignal(SIGUSR1, procsignal_sigusr1_handler); // 璁剧疆SIGUSR1鐨勫鐞嗗嚱鏁颁负procsignal_sigusr1_handler + (void)gspqsignal(SIGUSR2, BarrierArchWakenStop); // 璁剧疆SIGUSR2鐨勫鐞嗗嚱鏁颁负BarrierArchWakenStop - (void)gspqsignal(SIGCHLD, SIG_DFL); - (void)gspqsignal(SIGTTIN, SIG_DFL); - (void)gspqsignal(SIGTTOU, SIG_DFL); - (void)gspqsignal(SIGCONT, SIG_DFL); - (void)gspqsignal(SIGWINCH, SIG_DFL); + (void)gspqsignal(SIGCHLD, SIG_DFL); // 灏哠IGCHLD鐨勫鐞嗗嚱鏁拌缃负榛樿鍊 + (void)gspqsignal(SIGTTIN, SIG_DFL); // 灏哠IGTTIN鐨勫鐞嗗嚱鏁拌缃负榛樿鍊 + (void)gspqsignal(SIGTTOU, SIG_DFL); // 灏哠IGTTOU鐨勫鐞嗗嚱鏁拌缃负榛樿鍊 + (void)gspqsignal(SIGCONT, SIG_DFL); // 灏哠IGCONT鐨勫鐞嗗嚱鏁拌缃负榛樿鍊 + (void)gspqsignal(SIGWINCH, SIG_DFL); // 灏哠IGWINCH鐨勫鐞嗗嚱鏁拌缃负榛樿鍊 /* We allow SIGQUIT (quickdie) at all times */ - (void)sigdelset(&t_thrd.libpq_cxt.BlockSig, SIGQUIT); + (void)sigdelset(&t_thrd.libpq_cxt.BlockSig, SIGQUIT); // 浠庨樆濉炰俊鍙烽泦涓Щ闄IGQUIT淇″彿 } #ifdef ENABLE_MULTIPLE_NODES +// 褰撳畯 ENABLE_MULTIPLE_NODES 琚畾涔夋椂锛岀紪璇戜互涓嬩唬鐮佸潡 + +// 鑾峰彇鎵鏈夎妭鐐圭殑杩炴帴鍙ユ焺 static PGXCNodeAllHandles* GetAllNodesHandles() { + // 鑾峰彇鎵鏈夋暟鎹妭鐐瑰拰鍗忚皟鑺傜偣鐨勫垪琛 List* barrierDataNodeList = GetAllDataNodes(); List* barrierCoordList = GetAllCoordNodes(); PGXCNodeAllHandles* conn_handles = NULL; + // 鑾峰彇杩炴帴鍙ユ焺 conn_handles = get_handles(barrierDataNodeList, barrierCoordList, false); + // 閲婃斁鑺傜偣鍒楄〃鍐呭瓨 list_free(barrierCoordList); list_free(barrierDataNodeList); - return conn_handles; + return conn_handles; // 杩斿洖杩炴帴鍙ユ焺 } +// 鍚戞墍鏈夎妭鐐瑰彂閫丅arrier褰掓。璇锋眰 static void SendBarrierArchRequest(const PGXCNodeAllHandles* handles, int count, ArchiveBarrierLsnInfo *barrierLsnInfo) { int conn; @@ -223,23 +254,26 @@ static void SendBarrierArchRequest(const PGXCNodeAllHandles* handles, int count, errno_t rc; char barrierInfo[BARRIER_ARCH_INFO_LEN]; + // 杈撳嚭鏃ュ織锛岃〃绀哄紑濮嬪悜鎵鏈夎妭鐐瑰彂閫丅arrier褰掓。璇锋眰 ereport(LOG, (errmsg("Start to send barrier arch request to all nodes."))); - for (conn = 0; conn < count; conn++) { + for (conn = 0; conn < count; conn++) { // 寰幆閬嶅巻鎵鏈夎繛鎺ワ紝鍚戞瘡涓繛鎺ュ彂閫佽姹 PGXCNodeHandle* handle = NULL; + // 鏍规嵁杩炴帴绫诲瀷鑾峰彇杩炴帴鍙ユ焺 if (conn < handles->co_conn_count) handle = handles->coord_handles[conn]; else handle = handles->datanode_handles[conn - handles->co_conn_count]; /* Invalid connection state, return error */ - if (handle->state != DN_CONNECTION_STATE_IDLE) { + if (handle->state != DN_CONNECTION_STATE_IDLE) { // 濡傛灉杩炴帴鐘舵佹棤鏁堬紝杈撳嚭閿欒淇℃伅骞剁粓姝 ereport(ERROR, (errcode(ERRCODE_OPERATE_FAILED), errmsg("Failed to send BARRIER request to the node"))); } + // 閬嶅巻鎵鏈塨arrierLsnInfo锛屾壘鍒板尮閰嶈妭鐐圭殑淇℃伅 for (int i = 0; i < count; i++) { if (barrierLsnInfo[i].nodeoid == handle->nodeoid) { rc = snprintf_s(barrierInfo, BARRIER_ARCH_INFO_LEN, BARRIER_ARCH_INFO_LEN - 1, "0x%lx:%s", @@ -249,13 +283,15 @@ static void SendBarrierArchRequest(const PGXCNodeAllHandles* handles, int count, barrier_idlen = strlen(barrierInfo) + 1; + // 璁$畻娑堟伅鐨勬婚暱搴 msglen = 4; /* for the length itself */ msglen += barrier_idlen; msglen += 1; /* for barrier command itself */ /* msgType + msgLen */ - ensure_out_buffer_capacity(1 + msglen, handle); + ensure_out_buffer_capacity(1 + msglen, handle); // 纭繚杈撳嚭缂撳啿鍖鸿冻澶熷绾虫秷鎭 + // 娣诲姞娑堟伅绫诲瀷 'b' Assert(handle->outBuffer != NULL); handle->outBuffer[handle->outEnd++] = 'b'; msglen = htonl(msglen); @@ -263,123 +299,147 @@ static void SendBarrierArchRequest(const PGXCNodeAllHandles* handles, int count, securec_check(rc, "\0", "\0"); handle->outEnd += 4; + // 娣诲姞Barrier褰掓。鍛戒护 BARRIER_QUERY_ARCHIVE handle->outBuffer[handle->outEnd++] = BARRIER_QUERY_ARCHIVE; + // 娣诲姞Barrier淇℃伅 rc = memcpy_s(handle->outBuffer + handle->outEnd, handle->outSize - handle->outEnd, barrierInfo, barrier_idlen); securec_check(rc, "\0", "\0"); handle->outEnd += barrier_idlen; + // 璁剧疆杩炴帴鐘舵佷负鏌ヨ鐘舵 handle->state = DN_CONNECTION_STATE_QUERY; + // 鍒锋柊杩炴帴鐨勮緭鍑虹紦鍐插尯 pgxc_node_flush(handle); } } +// 妫鏌ュ湪鎵鏈夎妭鐐逛笂鎵цBARRIER ARCH鏌ヨ鍛戒护鐨勭姸鎬 static void CheckBarrierArchCommandStatus(const PGXCNodeAllHandles* conn_handles, int count, const char *id) { int conn; RemoteQueryState* combiner = NULL; + // 杈撳嚭璋冭瘯鏃ュ織锛岃〃绀烘鍦ㄦ鏌ARRIER ARCH鏌ヨ鍛戒护鐘舵 ereport(DEBUG1, (errmsg("Check BARRIER ARCH QUERY <%s> command status", id))); + // 鍒涘缓涓涓搷搴旂粍鍚堝櫒锛岀敤浜庡悎骞舵潵鑷涓妭鐐圭殑鍝嶅簲 combiner = CreateResponseCombiner(count, COMBINE_TYPE_NONE); + // 寰幆閬嶅巻鎵鏈夎繛鎺ワ紝妫鏌ユ瘡涓繛鎺ョ殑鍝嶅簲 for (conn = 0; conn < count; conn++) { PGXCNodeHandle* handle = NULL; + // 鏍规嵁杩炴帴绫诲瀷鑾峰彇杩炴帴鍙ユ焺 if (conn < conn_handles->co_conn_count) handle = conn_handles->coord_handles[conn]; else handle = conn_handles->datanode_handles[conn - conn_handles->co_conn_count]; + // 鎺ユ敹鏉ヨ嚜鑺傜偣鐨勫搷搴 if (pgxc_node_receive(1, &handle, NULL)) ereport( ERROR, (errcode(ERRCODE_OPERATE_FAILED), errmsg("Failed to receive response from the remote side"))); + // 澶勭悊鍝嶅簲骞舵鏌ユ墽琛岀姸鎬 if (handle_response(handle, combiner) != RESPONSE_BARRIER_OK) ereport(ERROR, (errcode(ERRCODE_OPERATE_FAILED), errmsg("BARRIER ARCH QUERY failed with error %s", handle->error))); } + // 鍏抽棴鍝嶅簲缁勫悎鍣 CloseCombiner(combiner); + // 杈撳嚭鏃ュ織锛岃〃绀哄湪鎵鏈夎妭鐐逛笂鎴愬姛瀹屾垚浜咮ARRIER ARCH鏌ヨ鍛戒护 ereport(LOG, (errmsg("Successfully completed BARRIER ARCH QUERY <%s> command on " "all nodes", id))); } +// 鎵ц褰掓。鐩稿叧鐨勪换鍔 static void QueryBarrierArch(PGXCNodeAllHandles* handles, ArchiveConfig *archive_obs) { int connCnt = handles->co_conn_count + handles->dn_conn_count; SpinLockAcquire(&g_instance.archive_obs_cxt.barrier_lock); + // 鑾峰彇鏈澶ц妭鐐规暟閲 int archivMaxNodeCnt = g_instance.archive_obs_cxt.max_node_cnt; + // 濡傛灉杩炴帴鏁拌秴杩囦簡鏈澶ц妭鐐规暟 if (connCnt >= archivMaxNodeCnt) { + // 閲婃斁鍏ㄥ眬閿 SpinLockRelease(&g_instance.archive_obs_cxt.barrier_lock); + // 杈撳嚭璋冭瘯淇℃伅锛岃〃绀哄綋鍓嶈繛鎺ユ暟澶т簬鏈澶ц妭鐐规暟 ereport(DEBUG2, (errmsg("current cn get connCnt: <%d> max than cluster connCnt: <%d>", connCnt, archivMaxNodeCnt))); return; } ArchiveBarrierLsnInfo barrierLsnInfo[g_instance.archive_obs_cxt.max_node_cnt]; - + // 濡傛灉褰撳墠鐨凚arrier鍚嶇О鍜屽凡瀛樺偍鐨勫悕绉扮浉鍚岋紝鐩存帴杩斿洖 if (strncmp(t_thrd.barrier_arch.barrierName, g_instance.archive_obs_cxt.barrierName, strlen(g_instance.archive_obs_cxt.barrierName)) == 0) { SpinLockRelease(&g_instance.archive_obs_cxt.barrier_lock); return; } - + // 澶嶅埗褰撳墠鐨凚arrier鍚嶇О鍒板叏灞鍙橀噺 errno_t errorno = memcpy_s(t_thrd.barrier_arch.barrierName, MAX_BARRIER_ID_LENGTH, g_instance.archive_obs_cxt.barrierName, sizeof(g_instance.archive_obs_cxt.barrierName)); securec_check(errorno, "\0", "\0"); + // 妫鏌ユ槸鍚︽墍鏈夎妭鐐圭殑barrierLsn閮戒笉涓0锛屽鏋滄湁涓涓负0锛岀洿鎺ヨ繑鍥 for (int i = 0; i < connCnt + 1; i++) { if (g_instance.archive_obs_cxt.barrier_lsn_info[i].barrierLsn == 0x0) { SpinLockRelease(&g_instance.archive_obs_cxt.barrier_lock); return; } } + // 澶嶅埗barrierLsn淇℃伅鍒板眬閮ㄥ彉閲 errorno = memcpy_s(&barrierLsnInfo, sizeof(ArchiveBarrierLsnInfo) * g_instance.archive_obs_cxt.max_node_cnt, g_instance.archive_obs_cxt.barrier_lsn_info, sizeof(ArchiveBarrierLsnInfo) * g_instance.archive_obs_cxt.max_node_cnt); SpinLockRelease(&g_instance.archive_obs_cxt.barrier_lock); securec_check(errorno, "\0", "\0"); - + // 鍙戦丅arrier褰掓。璇锋眰 SendBarrierArchRequest(handles, connCnt, barrierLsnInfo); - + // 妫鏌arrier褰掓。鍛戒护鐨勭姸鎬 CheckBarrierArchCommandStatus(handles, connCnt, t_thrd.barrier_arch.barrierName); - + // 绛夊緟Barrier褰掓。瀹屾垚 WaitBarrierArch(barrierLsnInfo[connCnt].barrierLsn, t_thrd.barrier_arch.slot_name); - + // 灏咮arrier鍚嶇О鍐欏叆褰掓。瀛樺偍 write_barrier_id_to_obs(t_thrd.barrier_arch.barrierName, archive_obs); } - +// 濡傛灉鏈畾涔塃NABLE_MULTIPLE_NODES锛屽垯鎵ц浠ヤ笅浠g爜鍧 #else +// 鐢ㄤ簬鍦ㄥ崟涓妭鐐逛笂鎵цBarrier褰掓。鎿嶄綔锛岀瓑寰呯壒瀹氱殑LSN瀹屾垚鍚庡皢Barrier鍚嶇О鍐欏叆褰掓。瀛樺偍 static void SingleBarrierArch(ArchiveConfig *archive_obs) { XLogRecPtr barrierLsn; - SpinLockAcquire(&g_instance.archive_obs_cxt.barrier_lock); + SpinLockAcquire(&g_instance.archive_obs_cxt.barrier_lock); // 鑾峰彇鍏ㄥ眬閿 + // 妫鏌ュ綋鍓嶇殑Barrier鍚嶇О鏄惁鍜屽凡瀛樺偍鐨勫悕绉扮浉鍚岋紝濡傛灉鐩稿悓鍒欓噴鏀鹃攣骞惰繑鍥 if (strncmp(t_thrd.barrier_arch.barrierName, g_instance.archive_obs_cxt.barrierName, strlen(g_instance.archive_obs_cxt.barrierName)) == 0) { SpinLockRelease(&g_instance.archive_obs_cxt.barrier_lock); return; } - + // 澶嶅埗褰撳墠鐨凚arrier鍚嶇О鍒扮嚎绋嬪眬閮ㄥ彉閲 errno_t errorno = memcpy_s(t_thrd.barrier_arch.barrierName, MAX_BARRIER_ID_LENGTH, g_instance.archive_obs_cxt.barrierName, sizeof(g_instance.archive_obs_cxt.barrierName)); securec_check(errorno, "\0", "\0"); - + // 澶嶅埗BarrierLSN鍒板眬閮ㄥ彉閲 barrierLsn = g_instance.archive_obs_cxt.barrierLsn; + // 閲婃斁鍏ㄥ眬閿 SpinLockRelease(&g_instance.archive_obs_cxt.barrier_lock); - + // 绛夊緟Barrier褰掓。瀹屾垚 WaitBarrierArch(barrierLsn, t_thrd.barrier_arch.slot_name); - + // 灏咮arrier鍚嶇О鍐欏叆褰掓。瀛樺偍 write_barrier_id_to_obs(t_thrd.barrier_arch.barrierName, archive_obs); } #endif +// 褰掓。Barrier绾跨▼鐨勫叆鍙e嚱鏁 NON_EXEC_STATIC void BarrierArchMain(knl_thread_arg* arg) { ArchiveSlotConfig *obsArchiveSlot = NULL; @@ -388,25 +448,30 @@ NON_EXEC_STATIC void BarrierArchMain(knl_thread_arg* arg) char username[NAMEDATALEN]; char *dbname = (char *)pstrdup(DEFAULT_DATABASE); - SetProcessingMode(InitProcessing); + SetProcessingMode(InitProcessing); // 璁剧疆褰撳墠绾跨▼鐨勫鐞嗘ā寮忎负鍒濆鍖栨ā寮 + // 璁剧疆绾跨▼鐨勭浉鍏充俊鎭厤缃 t_thrd.role = BARRIER_ARCH; t_thrd.proc_cxt.MyProgName = "BarrierArch"; t_thrd.proc_cxt.MyProcPid = gs_thread_self(); t_thrd.barrier_arch.slot_name = pstrdup((char *)arg->payload); u_sess->attr.attr_common.application_name = pstrdup("BarrierArch"); + // 杈撳嚭鏃ュ織锛岃〃绀哄綊妗arrier绾跨▼鍚姩 ereport(LOG, (errmsg("[BarrierArch] barrier arch thread starts. slot name: %s", t_thrd.barrier_arch.slot_name))); - + + // 鍦ㄨ繘绋嬮鍑烘椂璋冪敤 PGXCNodeCleanAndRelease 鍑芥暟 on_shmem_exit(PGXCNodeCleanAndRelease, 0); + // 璁剧疆淇″彿澶勭悊鍑芥暟 BarrierArchSetupSignalHook(); - + + // 鍒濆鍖 BaseInit(); - + // 璁剧疆鏁版嵁搴撳拰鐢ㄦ埛淇℃伅 t_thrd.proc_cxt.PostInit->SetDatabaseAndUser(dbname, InvalidOid, username); t_thrd.proc_cxt.PostInit->InitBarrierCreator(); - + // 鍒涘缓涓涓唴瀛樹笂涓嬫枃鐢ㄤ簬鎵ц宸ヤ綔 t_thrd.utils_cxt.CurrentResourceOwner = ResourceOwnerCreate(NULL, "BarrierArch", THREAD_GET_MEM_CXT_GROUP(MEMORY_CONTEXT_STORAGE)); @@ -427,119 +492,139 @@ NON_EXEC_STATIC void BarrierArchMain(knl_thread_arg* arg) * If an exception is encountered, processing resumes here. * See notes in postgres.c about the design of this coding. */ + // 鎹曡幏寮傚父 浠ュ強杩涜寮傚父澶勭悊 int curTryCounter; int* oldTryCounter = NULL; if (sigsetjmp(localSigjmpBuf, 1) != 0) { gstrace_tryblock_exit(true, oldTryCounter); /* Since not using PG_TRY, must reset error stack by hand */ - t_thrd.log_cxt.error_context_stack = NULL; + t_thrd.log_cxt.error_context_stack = NULL; // 娓呯悊閿欒涓婁笅鏂 /* Prevent interrupts while cleaning up */ - HOLD_INTERRUPTS(); + HOLD_INTERRUPTS(); // 闃绘涓柇淇″彿 /* Report the error to the server log */ - EmitErrorReport(); + EmitErrorReport(); // 灏嗛敊璇俊鎭啓鍏ユ棩蹇 + // 閲婃斁璧勬簮 /* release resource held by lsc */ - AtEOXact_SysDBCache(false); - + AtEOXact_SysDBCache(false); /* release resource */ - LWLockReleaseAll(); + LWLockReleaseAll(); /* * Now return to normal top-level context and clear ErrorContext for * next time. */ + // 鍒囨崲鍥炲垵濮嬪唴瀛樹笂涓嬫枃锛屾竻绌洪敊璇姸鎬 MemoryContextSwitchTo(barrierArchContext); FlushErrorState(); MemoryContextResetAndDeleteChildren(barrierArchContext); /* Now we can allow interrupts again */ - RESUME_INTERRUPTS(); + RESUME_INTERRUPTS(); // 鎭㈠涓柇澶勭悊 /* * Sleep at least 1 second after any error. A write error is likely * to be repeated, and we don't want to be filling the error logs as * fast as we can. */ + // 绛夊緟涓绉掞紝浠ラ槻姝㈤敊璇俊鎭绻佸啓鍏ユ棩蹇 pg_usleep(1000000L); } - destroy_handles(); - oldTryCounter = gstrace_tryblock_entry(&curTryCounter); + destroy_handles(); // 閿姣佽繛鎺ュ彞鏌 + oldTryCounter = gstrace_tryblock_entry(&curTryCounter); // 璁剧疆鎹曡幏寮傚父鐨勮鏁板櫒锛屼互渚垮悗缁紓甯稿鐞 /* We can now handle ereport(ERROR) */ - t_thrd.log_cxt.PG_exception_stack = &localSigjmpBuf; + t_thrd.log_cxt.PG_exception_stack = &localSigjmpBuf; // 灏嗗綋鍓嶇殑寮傚父鎹曡幏鐘舵佷繚瀛樺埌绾跨▼鐨勫紓甯稿爢鏍堜笂 /* * Unblock signals (they were blocked when the postmaster forked us) */ + // 瑙i櫎鍦 BarrierArchSetupSignalHook 鍑芥暟涓樆濉炵殑涓浜涗俊鍙 gs_signal_setmask(&t_thrd.libpq_cxt.UnBlockSig, NULL); (void)gs_signal_unblock_sigusr2(); - + // 灏嗗鐞嗘ā寮忚缃负姝e父澶勭悊妯″紡锛岃〃鏄庣嚎绋嬫鍦ㄦ甯歌繍琛屽苟澶勭悊浠诲姟 SetProcessingMode(NormalProcessing); - + // 绛夊緟1 绉 pg_usleep_retry(1000000L, 0); - obsArchiveSlot = getArchiveReplicationSlotWithName(t_thrd.barrier_arch.slot_name); - if (obsArchiveSlot == NULL) { - t_thrd.barrier_arch.ready_to_stop = true; - ereport(WARNING, (errmsg("[BarrierArch] obs slot not created."))); + obsArchiveSlot = getArchiveReplicationSlotWithName(t_thrd.barrier_arch.slot_name); // 鑾峰彇涓庣粰瀹氬悕绉板尮閰嶇殑褰掓。澶嶅埗妲 + if (obsArchiveSlot == NULL) { // 濡傛灉鎵句笉鍒板尮閰嶇殑妲 + t_thrd.barrier_arch.ready_to_stop = true; // 鍑嗗鍋滄绾跨▼ + ereport(WARNING, (errmsg("[BarrierArch] obs slot not created."))); // 杈撳嚭璀﹀憡娑堟伅 return; } - exec_init_poolhandles(); + exec_init_poolhandles(); // 鍒濆鍖栬繛鎺ユ睜鍙ユ焺 #ifdef ENABLE_MULTIPLE_NODES +// 寮鍚鑺傜偣缂栬瘧閫夐」鏃舵墽琛屼互涓嬩唬鐮佸潡 do { + // 濡傛灉褰撳墠鑺傜偣涓嶆槸绗竴涓崗璋冨櫒鑺傜偣锛岃烦鍑哄惊鐜 if (IsFirstCn()) break; - + // 杈撳嚭鏃ュ織锛屾樉绀哄綋鍓嶈妭鐐逛笉鏄涓涓崗璋冨櫒鑺傜偣 ereport(DEBUG1, (errmsg("[BarrierArch] Current node is not first node: %s", g_instance.attr.attr_common.PGXCNodeName))); if (IsGotPoolReload()) { + // 濡傛灉鏀跺埌浜嗚繛鎺ユ睜閲嶈浇鏍囧織锛屾墽琛岃繛鎺ユ睜閲嶈浇鎿嶄綔 processPoolerReload(); + // 閲嶇疆杩炴帴姹犻噸杞芥爣蹇椾负 false ResetGotPoolReload(false); } + // 妫鏌ユ槸鍚︽湁涓柇璇锋眰 CHECK_FOR_INTERRUPTS(); + // 鏆傚仠 10 绉 pg_usleep(10000000L); } while (1); - + // 鑾峰彇涓涓悕涓 barrier_lock 鐨勮嚜鏃嬮攣锛岀敤浜庝繚鎶ゅ叧閿祫婧 SpinLockAcquire(&g_instance.archive_obs_cxt.barrier_lock); + // 濡傛灉 barrier_lsn_info 涓虹┖锛屾垨鑰 max_node_cnt 涓 0 if (g_instance.archive_obs_cxt.barrier_lsn_info == NULL || g_instance.archive_obs_cxt.max_node_cnt == 0) { - SpinLockRelease(&g_instance.archive_obs_cxt.barrier_lock); - ereport(WARNING, (errmsg("[BarrierArch] barrier_lsn_info not alloc."))); + SpinLockRelease(&g_instance.archive_obs_cxt.barrier_lock); // 閲婃斁鑷棆閿 + // 杈撳嚭璀﹀憡娑堟伅锛屾彁绀 barrier_lsn_info 鏈垎閰 + ereport(WARNING, (errmsg("[BarrierArch] barrier_lsn_info not alloc."))); return; } - SpinLockRelease(&g_instance.archive_obs_cxt.barrier_lock); + SpinLockRelease(&g_instance.archive_obs_cxt.barrier_lock); // 閲婃斁鑷棆閿 #endif +// 缁撴潫澶氳妭鐐圭紪璇戦夐」鐨勬潯浠剁紪璇 + // 杈撳嚭鏃ュ織锛屾樉绀烘鍦ㄥ垵濮嬪寲涓庡崗璋冨櫒鍜屾暟鎹妭鐐圭殑杩炴帴锛屼互鍙婃暟鎹妭鐐瑰拰鍗忚皟鍣ㄧ殑鏁伴噺 ereport(DEBUG1, (errmsg("[BarrierArch] Init connections with CN/DN, dn count : %d, cn count : %d", u_sess->pgxc_cxt.NumDataNodes, u_sess->pgxc_cxt.NumCoords))); + // 杩涘叆寰幆锛屽彧瑕 ready_to_stop 鏍囧織涓嶄负鐪燂紝灏变竴鐩存墽琛屽惊鐜綋 while (!t_thrd.barrier_arch.ready_to_stop) { - CHECK_FOR_INTERRUPTS(); - + CHECK_FOR_INTERRUPTS(); // 妫鏌ユ槸鍚︽湁涓柇璇锋眰 + // 濡傛灉 barrierName 涓虹┖鎴栭暱搴︿负 0 if (g_instance.archive_obs_cxt.barrierName == NULL || strlen(g_instance.archive_obs_cxt.barrierName) == 0) { - ereport(WARNING, (errmsg("[BarrierArch] barrierName is null."))); + ereport(WARNING, (errmsg("[BarrierArch] barrierName is null."))); // 杈撳嚭璀﹀憡娑堟伅锛屾彁绀 barrierName 涓虹┖ break; } #ifdef ENABLE_MULTIPLE_NODES + // 寮鍚簡澶氳妭鐐圭紪璇戦夐」鏃舵墽琛屼互涓嬩唬鐮佸潡 + // 濡傛灉鏀跺埌浜嗚繛鎺ユ睜閲嶈浇鏍囧織 if (IsGotPoolReload()) { - processPoolerReload(); - ResetGotPoolReload(false); - if (!IsFirstCn()) + processPoolerReload(); // 鎵ц杩炴帴姹犻噸杞芥搷浣 + ResetGotPoolReload(false); // 閲嶇疆杩炴帴姹犻噸杞芥爣蹇椾负 false + if (!IsFirstCn()) // 濡傛灉褰撳墠鑺傜偣涓嶆槸绗竴涓崗璋冨櫒鑺傜偣锛岃烦鍑哄惊鐜 break; } - - PGXCNodeAllHandles* handles = GetAllNodesHandles(); - + // 鑾峰彇鎵鏈夎妭鐐圭殑杩炴帴鍙ユ焺 + PGXCNodeAllHandles* handles = GetAllNodesHandles(); + // 璋冪敤 QueryBarrierArch 鍑芥暟澶勭悊Barrier褰掓。 QueryBarrierArch(handles, &obsArchiveSlot->archive_config); - + // 閲婃斁鎵鏈夎妭鐐圭殑杩炴帴鍙ユ焺鍐呭瓨 pfree_pgxc_all_handles(handles); #else +// 娌℃湁寮鍚鑺傜偣缂栬瘧閫夐」鏃舵墽琛屼互涓嬩唬鐮佸潡 + // 璋冪敤 SingleBarrierArch 鍑芥暟澶勭悊Barrie褰掓。 SingleBarrierArch(&obsArchiveSlot->archive_config); #endif } + // 杈撳嚭鏃ュ織锛屾樉绀洪殰纰嶅綊妗g嚎绋嬪凡閫鍑 ereport(LOG, (errmsg("[BarrierArch] barrier arch thread exits."))); } diff --git a/src/gausskernel/process/postmaster/barrier_creator.cpp b/src/gausskernel/process/postmaster/barrier_creator.cpp index 3715ee3c8..a7eedfe61 100755 --- a/src/gausskernel/process/postmaster/barrier_creator.cpp +++ b/src/gausskernel/process/postmaster/barrier_creator.cpp @@ -52,100 +52,116 @@ const int BARRIER_NAME_LEN = 40; const char* CSN_BARRIER_PATTREN_STR = "csn_%021lu_%013ld"; const char* CSN_SWITCHOVER_BARRIER_PATTREN_STR = "csn_%021lu_dr_switchover"; +/* +浣滅敤锛 鐢熸垚鐢ㄤ簬Barrier褰掓。鐨勫悕绉 +鍙傛暟锛 barrierRet:瀛楃鏁扮粍鎸囬拡锛屽瓨鍌ㄧ敓鎴愮殑 Barrier 鍚嶇О + isSwitchoverBarrier:琛ㄧず鏄惁涓哄垏鎹 Barrier +*/ void GetCsnBarrierName(char* barrierRet, bool isSwitchoverBarrier) { - struct timeval tv; - int rc; - CommitSeqNo csn; + struct timeval tv; // 鐢ㄤ簬瀛樺偍鏃堕棿鐨勭粨鏋勪綋鍙橀噺 + int rc; // 鐢ㄤ簬瀛樺偍鍑芥暟杩斿洖鍊肩殑鍙橀噺 + CommitSeqNo csn; // 鐢ㄤ簬瀛樺偍浜嬪姟鎻愪氦搴忓垪鍙风殑鍙橀噺 + // 濡傛灉澶勪簬GTM妯″紡锛岃幏鍙栧叏灞浜嬪姟绠$悊鍣ㄧ殑浜嬪姟鎻愪氦搴忓垪鍙 if (GTM_MODE) csn = GetCSNGTM(); else - csn = CommitCSNGTM(false); + csn = CommitCSNGTM(false); // 鍚﹀垯鑾峰彇鏈湴浜嬪姟鎻愪氦搴忓垪鍙 - gettimeofday(&tv, NULL); + gettimeofday(&tv, NULL); // 鑾峰彇褰撳墠鏃堕棿淇℃伅 - if (isSwitchoverBarrier) { + if (isSwitchoverBarrier) { // 濡傛灉瑕佸垏鎹arrier + // 鏋勯犵敤浜庡垏鎹arrier鐨勫悕绉帮紝灏咰SN鎻掑叆鍒扮壒瀹氱殑鏍煎紡瀛楃涓蹭腑 rc = snprintf_s(barrierRet, BARRIER_NAME_LEN, BARRIER_NAME_LEN - 1, CSN_SWITCHOVER_BARRIER_PATTREN_STR, csn); } else { + // 鏋勯犳櫘閫欱arrier鐨勫悕绉帮紝灏咰SN鍜屾椂闂存埑淇℃伅鎻掑叆鍒版牸寮忓瓧绗︿覆涓 rc = snprintf_s(barrierRet, BARRIER_NAME_LEN, BARRIER_NAME_LEN - 1, CSN_BARRIER_PATTREN_STR, csn, TIME_GET_MILLISEC(tv)); } - securec_check_ss_c(rc, "\0", "\0"); + securec_check_ss_c(rc, "\0", "\0"); // 妫鏌ユ牸寮忓寲鎿嶄綔鐨勮繑鍥炲硷紝纭繚鎿嶄綔鎴愬姛 + // 璁板綍璋冭瘯鏃ュ織锛岃緭鍑虹敓鎴愮殑Barrier鍚嶇О鍜屽搴旂殑CSN elog(DEBUG1, "GetCsnBarrierName csn = %lu, barrier_name = %s", csn, barrierRet); } - +/* 鏍规嵁浼犲叆鐨凜SN Barrier鍚嶇О锛岃В鏋愬嚭鍏朵腑鐨凜SN鍊硷紝骞惰繑鍥 + 鍙傛暟: csnBarrier 琛ㄧず CSN Barrier 鐨勫悕绉 + 杩斿洖鍊硷細瑙f瀽鍑虹殑 CSN 鍊硷紙瑙f瀽鎴愬姛锛 +*/ CommitSeqNo CsnBarrierNameGetCsn(const char *csnBarrier) { CommitSeqNo csn; long ts = 0; + // 浣跨敤鏍煎紡鍖栧瓧绗︿覆瑙f瀽CSN Barrier鍚嶇О锛屾彁鍙栧叾涓殑CSN鍊煎拰鏃堕棿鎴筹紙濡傛灉鏈夛級 if ((strstr(csnBarrier, "_dr_switchover") != NULL && sscanf_s(csnBarrier, CSN_SWITCHOVER_BARRIER_PATTREN_STR, &csn) == 1) || sscanf_s(csnBarrier, CSN_BARRIER_PATTREN_STR, &csn, &ts) == 2) { return csn; } - return 0; + return 0; // 瑙f瀽澶辫触鏃惰繑鍥0 } - +// 鏍规嵁浼犲叆鐨凜SN Barrier鍚嶇О锛岃В鏋愬嚭鍏朵腑鐨勬椂闂存埑鍊硷紝骞惰繑鍥 int64 CsnBarrierNameGetTimeStamp(const char *csnBarrier) { CommitSeqNo csn; int64 ts = 0; + // 浣跨敤鏍煎紡鍖栧瓧绗︿覆瑙f瀽CSN Barrier鍚嶇О锛屾彁鍙栧叾涓殑CSN鍊煎拰鏃堕棿鎴筹紙濡傛灉鏈夛級 if (sscanf_s(csnBarrier, CSN_BARRIER_PATTREN_STR, &csn, &ts) == 2) { return ts; } - return 0; + return 0; // 瑙f瀽澶辫触鏃惰繑鍥0 } - +// 鍒ゆ柇浼犲叆鐨凜SN Barrier鍚嶇О鏄惁涓哄垏鎹arrier bool IsSwitchoverBarrier(const char *csnBarrier) { + // 鍒ゆ柇CSN Barrier鍚嶇О鏄惁绗﹀悎瑕佹眰锛屼笖鏄惁鍖呭惈 "_dr_switchover" 瀛愪覆 if (!IS_CSN_BARRIER(csnBarrier) || (strstr(csnBarrier, "_dr_switchover") == NULL)) { return false; } - return true; + return true; // 濡傛灉绗﹀悎瑕佹眰锛屽垯璁や负鏄垏鎹arrier } - +// 鍒ゆ柇褰撳墠鑺傜偣鏄惁涓虹涓涓墽琛岀殑鍗忚皟鍣ㄨ妭鐐 bool IsFirstCn() { - char *firstExecNode = find_first_exec_cn(); + char *firstExecNode = find_first_exec_cn(); // 鏌ユ壘绗竴涓墽琛岀殑鍗忚皟鍣ㄨ妭鐐 + // 灏嗗綋鍓嶈妭鐐圭殑鍚嶇О涓巉irstExecNode杩涜姣旇緝锛屽鏋滀袱鑰呯浉鍚岋紝鍒欒繑鍥瀟rue锛岃〃绀哄綋鍓嶈妭鐐规槸绗竴涓墽琛岀殑鍗忚皟鍣ㄨ妭鐐癸紱鍚﹀垯杩斿洖false return (strcmp(firstExecNode, g_instance.attr.attr_common.PGXCNodeName) == 0); } - +// 鍏抽棴Barrier鍒涘缓绾跨▼ void barrier_creator_thread_shutdown(void) { - g_instance.barrier_creator_cxt.stop = true; - ereport(LOG, (errmsg("[BarrierCreator] barrier creator thread shutting down."))); + g_instance.barrier_creator_cxt.stop = true; // 璁剧疆鏍囧織锛岃〃绀哄仠姝㈢嚎绋 + ereport(LOG, (errmsg("[BarrierCreator] barrier creator thread shutting down."))); // 杈撳嚭鏃ュ織 } - +// SIGHUP淇″彿澶勭悊鍑芥暟锛岀敤浜庨噸鏂板姞杞介厤缃 static void barrier_creator_sighup_handler(SIGNAL_ARGS) { - int save_errno = errno; - t_thrd.barrier_creator_cxt.got_SIGHUP = true; - errno = save_errno; -} + int save_errno = errno; // 淇濆瓨褰撳墠errno + t_thrd.barrier_creator_cxt.got_SIGHUP = true; // 璁剧疆鏍囧織锛岃〃绀烘敹鍒癝IGHUP淇″彿 + errno = save_errno; // 鎭㈠errno +} /* Reset some signals that are accepted by postmaster but not here */ static void barrier_creator_setup_signal_hook(void) { - (void)gspqsignal(SIGHUP, barrier_creator_sighup_handler); - (void)gspqsignal(SIGINT, SIG_IGN); - (void)gspqsignal(SIGTERM, die); - (void)gspqsignal(SIGQUIT, quickdie); - (void)gspqsignal(SIGALRM, SIG_IGN); - (void)gspqsignal(SIGPIPE, SIG_IGN); - (void)gspqsignal(SIGUSR1, procsignal_sigusr1_handler); - (void)gspqsignal(SIGUSR2, SIG_IGN); + (void)gspqsignal(SIGHUP, barrier_creator_sighup_handler); // 璁剧疆SIGHUP淇″彿澶勭悊鍑芥暟 + (void)gspqsignal(SIGINT, SIG_IGN); // 蹇界暐SIGINT淇″彿 + (void)gspqsignal(SIGTERM, die); // 璁剧疆SIGTERM淇″彿澶勭悊鍑芥暟涓篸ie + (void)gspqsignal(SIGQUIT, quickdie); // 璁剧疆SIGQUIT淇″彿澶勭悊鍑芥暟涓簈uickdie + (void)gspqsignal(SIGALRM, SIG_IGN); // 蹇界暐SIGALRM淇″彿 + (void)gspqsignal(SIGPIPE, SIG_IGN); // 蹇界暐SIGPIPE淇″彿 + (void)gspqsignal(SIGUSR1, procsignal_sigusr1_handler); // 璁剧疆SIGUSR1淇″彿澶勭悊鍑芥暟涓簆rocsignal_sigusr1_handler + (void)gspqsignal(SIGUSR2, SIG_IGN); // 蹇界暐SIGUSR2淇″彿 - (void)gspqsignal(SIGCHLD, SIG_DFL); - (void)gspqsignal(SIGTTIN, SIG_DFL); - (void)gspqsignal(SIGTTOU, SIG_DFL); - (void)gspqsignal(SIGCONT, SIG_DFL); - (void)gspqsignal(SIGWINCH, SIG_DFL); + (void)gspqsignal(SIGCHLD, SIG_DFL); // 璁剧疆SIGCHLD淇″彿澶勭悊鍑芥暟涓洪粯璁 + (void)gspqsignal(SIGTTIN, SIG_DFL); // 璁剧疆SIGTTIN淇″彿澶勭悊鍑芥暟涓洪粯璁 + (void)gspqsignal(SIGTTOU, SIG_DFL); // 璁剧疆SIGTTOU淇″彿澶勭悊鍑芥暟涓洪粯璁 + (void)gspqsignal(SIGCONT, SIG_DFL); // 璁剧疆SIGCONT淇″彿澶勭悊鍑芥暟涓洪粯璁 + (void)gspqsignal(SIGWINCH, SIG_DFL); // 璁剧疆SIGWINCH淇″彿澶勭悊鍑芥暟涓洪粯璁 /* We allow SIGQUIT (quickdie) at all times */ - (void)sigdelset(&t_thrd.libpq_cxt.BlockSig, SIGQUIT); + (void)sigdelset(&t_thrd.libpq_cxt.BlockSig, SIGQUIT); // 鍏佽闅忔椂澶勭悊SIGQUIT锛坬uickdie锛変俊鍙 } - +// 浠嶰BS涓鍙朆arrier鏍囪瘑 static uint64_t read_barrier_id_from_obs(const char *slotName, long *currBarrierTime) { char barrier_name[BARRIER_NAME_LEN]; @@ -153,146 +169,153 @@ static uint64_t read_barrier_id_from_obs(const char *slotName, long *currBarrier uint64_t barrier_id; if (ArchiveReplicationReadFile(BARRIER_FILE, (char *)barrier_name, MAX_BARRIER_ID_LENGTH, slotName)) { - barrier_name[BARRIER_NAME_LEN - 1] = '\0'; + barrier_name[BARRIER_NAME_LEN - 1] = '\0'; // 灏嗚鍙栫殑鏁版嵁鏈熬璁剧疆涓哄瓧绗︿覆缁撴潫绗 + // 杈撳嚭鏃ュ織锛岃〃绀轰粠褰掓。瀛樺偍涓鍙栦簡barrier ID ereport(LOG, (errmsg("[BarrierCreator] read barrier id from obs %s", barrier_name))); } else { + // 杈撳嚭鏃ュ織锛岃〃绀轰粠褰掓。瀛樺偍涓鍙朾arrier ID澶辫触锛屽皢浠0寮濮 ereport(LOG, (errmsg("[BarrierCreator] failed to read barrier id from obs, start barrier from 0"))); return 0; } #ifdef ENABLE_MULTIPLE_NODES + // 鏍规嵁涓嶅悓鐨勭紪璇戦夐」瑙f瀽Barrier鍚嶇О锛屾洿鏂癰arrier_id鍜宑urrBarrierTime ret = sscanf_s(barrier_name, "csn_%021" PRIu64 "_%013ld", &barrier_id, currBarrierTime); #else ret = sscanf_s(barrier_name, "hadr_%020" PRIu64 "_%013ld", &barrier_id, currBarrierTime); #endif - + // 濡傛灉瑙f瀽鎴愬姛锛屾洿鏂癰arrier_id骞惰繑鍥 if (ret == 2) { barrier_id++; return barrier_id; } - return 0; + return 0; // 瑙f瀽澶辫触锛岃繑鍥0 } - +// 鑾峰彇褰掓。妲戒腑鐨勬渶澶arrier绱㈠紩鍜屾渶鏂扮殑barrier鏃堕棿 uint64_t GetObsBarrierIndex(const List *archiveSlotNames, long *last_barrier_time) { - uint64_t maxIndex = 0; - long maxBarrierTime = 0; - foreach_cell(cell, archiveSlotNames) { - long currBarrierTime = 0; - char* slotName = (char*)lfirst(cell); - if (slotName == NULL || strlen(slotName) == 0) { + uint64_t maxIndex = 0; // 鏈澶arrier绱㈠紩 + long maxBarrierTime = 0; // 鏈澶arrier鏃堕棿 + foreach_cell(cell, archiveSlotNames) { // 閬嶅巻褰掓。妲藉悕绉板垪琛 + long currBarrierTime = 0; // 褰撳墠barrier鏃堕棿 + char* slotName = (char*)lfirst(cell); // 鑾峰彇褰掓。妲藉悕绉 + if (slotName == NULL || strlen(slotName) == 0) { // 濡傛灉褰掓。妲藉悕绉颁负绌猴紝璺宠繃鏈寰幆 continue; } - uint64_t readIndex = read_barrier_id_from_obs(slotName, &currBarrierTime); - maxIndex = (readIndex > maxIndex) ? readIndex : maxIndex; - maxBarrierTime = (currBarrierTime > maxBarrierTime) ? currBarrierTime : maxBarrierTime; + uint64_t readIndex = read_barrier_id_from_obs(slotName, &currBarrierTime); // 浠庡綊妗e瓨鍌ㄤ腑璇诲彇barrier绱㈠紩鍜屾椂闂 + maxIndex = (readIndex > maxIndex) ? readIndex : maxIndex; // 鏇存柊鏈澶arrier绱㈠紩 + maxBarrierTime = (currBarrierTime > maxBarrierTime) ? currBarrierTime : maxBarrierTime; // 鏇存柊鏈澶arrier鏃堕棿 } - *last_barrier_time = maxBarrierTime; + *last_barrier_time = maxBarrierTime; // 灏嗘渶澶arrier鏃堕棿璧嬪肩粰鎸囬拡鍙傛暟 - return maxIndex; + return maxIndex; // 杩斿洖鏈澶arrier绱㈠紩 } - +// 鑾峰彇褰掓。妲戒腑绗竴涓崗璋冨櫒鑺傜偣鐨刡arrier鏃堕棿绾 uint64 GetObsFirstCNBarrierTimeline(const List *archiveSlotNames) { - uint64 timeline = 0; + uint64 timeline = 0; // 鏃堕棿绾垮垵濮嬪间负0 - foreach_cell(cell, archiveSlotNames) { - char* slotName = (char*)lfirst(cell); - if (slotName == NULL || strlen(slotName) == 0) { + foreach_cell(cell, archiveSlotNames) { // 閬嶅巻褰掓。妲藉悕绉板垪琛 + char* slotName = (char*)lfirst(cell); // 鑾峰彇褰掓。妲藉悕绉 + if (slotName == NULL || strlen(slotName) == 0) { // 濡傛灉褰掓。妲藉悕绉颁负绌猴紝璺宠繃鏈寰幆 continue; } - timeline = ReadBarrierTimelineRecordFromObs(slotName); - break; + timeline = ReadBarrierTimelineRecordFromObs(slotName); // 浠庡綊妗e瓨鍌ㄤ腑璇诲彇鍗忚皟鍣ㄨ妭鐐圭殑barrier鏃堕棿绾 + break; // 璺冲嚭寰幆锛屽彧鑾峰彇绗竴涓綊妗fЫ鐨勬椂闂寸嚎 } - return timeline; + return timeline; // 杩斿洖鑾峰彇鐨勬椂闂寸嚎 } #ifdef ENABLE_MULTIPLE_NODES +// 鍒嗛厤鍜屽垵濮嬪寲BarrierLsnInfo鏁扮粍 static void AllocBarrierLsnInfo(int nodeSize) { int rc; g_instance.archive_obs_cxt.barrier_lsn_info = (ArchiveBarrierLsnInfo *)palloc0( - sizeof(ArchiveBarrierLsnInfo) * nodeSize); + sizeof(ArchiveBarrierLsnInfo) * nodeSize); // 鍒嗛厤鍐呭瓨 rc = memset_s(g_instance.archive_obs_cxt.barrier_lsn_info, sizeof(ArchiveBarrierLsnInfo) * nodeSize, 0, - sizeof(ArchiveBarrierLsnInfo) * nodeSize); - securec_check(rc, "", ""); + sizeof(ArchiveBarrierLsnInfo) * nodeSize); // 灏嗗垎閰嶇殑鍐呭瓨鍐呭鍒濆鍖栦负0 + securec_check(rc, "", ""); // 妫鏌ュ唴瀛樻搷浣滄槸鍚︽垚鍔燂紝濡傛灉涓嶆垚鍔燂紝杈撳嚭閿欒淇℃伅 } #endif #ifdef ENABLE_MULTIPLE_NODES +// BarrierCreator杩炴帴姹犻噸鏂板姞杞 static void BarrierCreatorPoolerReload(void) { - destroy_handles(); - processPoolerReload(); + destroy_handles(); // 閿姣佽繛鎺ュ彞鏌 + processPoolerReload(); // 閲嶆柊鍔犺浇杩炴帴姹 ereport(LOG, (errmsg("[BarrierCreatorPoolerReload] Reload connections with CN/DN, dn count : %d, cn count : %d", u_sess->pgxc_cxt.NumDataNodes, u_sess->pgxc_cxt.NumCoords))); if (g_instance.archive_obs_cxt.archive_slot_num == 0) { - return; + return; // 濡傛灉娌℃湁褰掓。妲斤紝鐩存帴杩斿洖 } int maxNodeCnt = *t_thrd.pgxc_cxt.shmemNumCoords + *t_thrd.pgxc_cxt.shmemNumDataNodes; - if (maxNodeCnt > g_instance.archive_obs_cxt.max_node_cnt) { + if (maxNodeCnt > g_instance.archive_obs_cxt.max_node_cnt) { // 濡傛灉鑺傜偣鏁伴噺瓒呰繃鏈澶у SpinLockAcquire(&g_instance.archive_obs_cxt.barrier_lock); - g_instance.archive_obs_cxt.max_node_cnt = 0; + g_instance.archive_obs_cxt.max_node_cnt = 0; // 娓呴浂鏈澶ц妭鐐规暟閲 SpinLockRelease(&g_instance.archive_obs_cxt.barrier_lock); int nodeSize = maxNodeCnt; if (g_instance.archive_obs_cxt.barrier_lsn_info != NULL) { - pfree_ext(g_instance.archive_obs_cxt.barrier_lsn_info); + pfree_ext(g_instance.archive_obs_cxt.barrier_lsn_info); // 閲婃斁鏃х殑BarrierLsnInfo鏁扮粍鍐呭瓨 } - AllocBarrierLsnInfo(nodeSize); + AllocBarrierLsnInfo(nodeSize); // 閲嶆柊鍒嗛厤鍜屽垵濮嬪寲BarrierLsnInfo鏁扮粍 SpinLockAcquire(&g_instance.archive_obs_cxt.barrier_lock); - g_instance.archive_obs_cxt.max_node_cnt = nodeSize; + g_instance.archive_obs_cxt.max_node_cnt = nodeSize; // 鏇存柊鏈澶ц妭鐐规暟閲 SpinLockRelease(&g_instance.archive_obs_cxt.barrier_lock); } } #endif - +// 鐢ㄤ簬閲婃斁涔嬪墠鍒嗛厤鐨勫瓨鍌ㄥ綊妗f搷浣滅殑Barrier LSN淇℃伅鐨勫唴瀛 static void FreeBarrierLsnInfo() { - SpinLockAcquire(&g_instance.archive_obs_cxt.barrier_lock); - g_instance.archive_obs_cxt.max_node_cnt = 0; - SpinLockRelease(&g_instance.archive_obs_cxt.barrier_lock); - pfree_ext(g_instance.archive_obs_cxt.barrier_lsn_info); + SpinLockAcquire(&g_instance.archive_obs_cxt.barrier_lock); // 鑾峰彇鍏ㄥ眬閿 + g_instance.archive_obs_cxt.max_node_cnt = 0; // 灏嗘渶澶ц妭鐐规暟璁剧疆涓0 + SpinLockRelease(&g_instance.archive_obs_cxt.barrier_lock); // 閲婃斁鍏ㄥ眬閿 + pfree_ext(g_instance.archive_obs_cxt.barrier_lsn_info); // 閲婃斁鍒嗛厤鐨勫唴瀛 } - +// 鍒涘缓涓嶅悓绫诲瀷鐨 Barrier锛屼互瀹炵幇鏁版嵁涓鑷存у拰鐏惧闇姹 void barrier_creator_main(void) { - uint64_t index = 0; - long last_barrier_time = 0; - struct timeval tv; - int rc; - char barrier_name[BARRIER_NAME_LEN]; - List* archiveSlotNames; - MemoryContext barrier_creator_context; - sigjmp_buf local_sigjmp_buf; - t_thrd.barrier_creator_cxt.is_first_barrier = true; - char username[NAMEDATALEN]; - char *dbname = (char *)pstrdup(DEFAULT_DATABASE); - bool startCsnBarrier = g_instance.attr.attr_storage.auto_csn_barrier; + uint64_t index = 0; // 鍒濆鍖栫敤浜庤褰曞垱寤築arrier鐨勭储寮 + long last_barrier_time = 0; // 鍒濆鍖栦笂涓涓狟arrier鐨勬椂闂 + struct timeval tv; // 鐢ㄤ簬鑾峰彇褰撳墠鏃堕棿 + int rc; // 鐢ㄤ簬璁板綍鍑芥暟杩斿洖鍊 + char barrier_name[BARRIER_NAME_LEN]; // 鐢ㄤ簬瀛樺偍Barrier鍚嶇О鐨勫瓧绗︽暟缁 + List* archiveSlotNames; // 瀛樺偍褰掓。妲藉悕鐨勫垪琛 + MemoryContext barrier_creator_context; // 鐢ㄤ簬瀛樺偍Barrier Creator绾跨▼鐨勫唴瀛樹笂涓嬫枃 + sigjmp_buf local_sigjmp_buf; // 鐢ㄤ簬瀹炵幇寮傚父澶勭悊璺宠浆 + t_thrd.barrier_creator_cxt.is_first_barrier = true; // 鏍囪瘑鏄惁鏄娆″垱寤築arrier + char username[NAMEDATALEN]; // 瀛樺偍鐢ㄦ埛鍚嶇殑瀛楃鏁扮粍 + char *dbname = (char *)pstrdup(DEFAULT_DATABASE); // 瀛樺偍榛樿鏁版嵁搴撳悕绉扮殑鎸囬拡 + bool startCsnBarrier = g_instance.attr.attr_storage.auto_csn_barrier; // 琛ㄧず鏄惁鍚敤鑷姩CSN Barrier鐨勬爣蹇 // use InnerMaintenanceTools mode to avoid deadlock with thread pool - u_sess->proc_cxt.IsInnerMaintenanceTools = true; - ereport(LOG, (errmsg("[BarrierCreator] barrier creator started"))); - g_instance.archive_obs_cxt.max_node_cnt = 0; - SetProcessingMode(InitProcessing); + u_sess->proc_cxt.IsInnerMaintenanceTools = true; // 浣跨敤InnerMaintenanceTools妯″紡锛屼互閬垮厤涓庣嚎绋嬫睜浜х敓姝婚攣 + ereport(LOG, (errmsg("[BarrierCreator] barrier creator started"))); // 杈撳嚭鏃ュ織锛岃〃绀築arrier Creator绾跨▼宸插惎鍔 + g_instance.archive_obs_cxt.max_node_cnt = 0; // 鍒濆鍖栨渶澶ц妭鐐规暟涓0 + SetProcessingMode(InitProcessing); // 璁剧疆澶勭悊妯″紡涓篒nitProcessing - t_thrd.role = BARRIER_CREATOR; - t_thrd.proc_cxt.MyProgName = "BarrierCreator"; - t_thrd.proc_cxt.MyProcPid = gs_thread_self(); - u_sess->attr.attr_common.application_name = pstrdup("BarrierCreator"); - g_instance.barrier_creator_cxt.stop = false; + t_thrd.role = BARRIER_CREATOR; // 璁剧疆绾跨▼鐨勮鑹蹭负BARRIER_CREATOR + t_thrd.proc_cxt.MyProgName = "BarrierCreator"; // 璁剧疆绾跨▼鐨勭▼搴忓悕绉颁负"BarrierCreator" + t_thrd.proc_cxt.MyProcPid = gs_thread_self(); // 璁剧疆绾跨▼鐨勮繘绋婭D涓哄綋鍓嶇嚎绋婭D + u_sess->attr.attr_common.application_name = pstrdup("BarrierCreator"); // 璁剧疆搴旂敤绋嬪簭鍚嶇О涓"BarrierCreator" + g_instance.barrier_creator_cxt.stop = false; // 鍒濆鍖栧仠姝㈡爣蹇椾负false锛岃〃绀築arrier Creator绾跨▼涓嶅仠姝 - on_shmem_exit(PGXCNodeCleanAndRelease, 0); + on_shmem_exit(PGXCNodeCleanAndRelease, 0); // 娉ㄥ唽涓涓湪杩涚▼閫鍑烘椂鎵ц鐨勫洖璋冨嚱鏁帮紝鐢ㄤ簬娓呯悊PGXC鑺傜偣璧勬簮 - barrier_creator_setup_signal_hook(); + barrier_creator_setup_signal_hook(); // 璁剧疆淇″彿澶勭悊鍑芥暟 - BaseInit(); + BaseInit(); // 鍒濆鍖 + // 璁剧疆褰撳墠绾跨▼鐨勬暟鎹簱鍜岀敤鎴蜂俊鎭 t_thrd.proc_cxt.PostInit->SetDatabaseAndUser(dbname, InvalidOid, username); + // 鍒濆鍖朆arrier Creator妯″潡鐨勪笂涓嬫枃 t_thrd.proc_cxt.PostInit->InitBarrierCreator(); - + // 鍒涘缓涓涓柊鐨勮祫婧愭嫢鏈夎咃紝鐢ㄤ簬绠$悊Barrier Creator绾跨▼鐨勮祫婧 t_thrd.utils_cxt.CurrentResourceOwner = ResourceOwnerCreate(NULL, "BarrierCreator", THREAD_GET_MEM_CXT_GROUP(MEMORY_CONTEXT_STORAGE)); @@ -302,6 +325,7 @@ void barrier_creator_main(void) * possible memory leaks. Formerly this code just ran in * t_thrd.top_mem_cxt, but resetting that would be a really bad idea. */ + // 鍒涘缓鍐呭瓨涓婁笅鏂 barrier_creator_context = AllocSetContextCreate(t_thrd.top_mem_cxt, "BarrierCreator", ALLOCSET_DEFAULT_MINSIZE, @@ -313,83 +337,92 @@ void barrier_creator_main(void) * If an exception is encountered, processing resumes here. * See notes in postgres.c about the design of this coding. */ + // 濡傛灉閬囧埌寮傚父锛屽皢浠庤繖閲屾仮澶 int curTryCounter; int *oldTryCounter = NULL; if (sigsetjmp(local_sigjmp_buf, 1) != 0) { - destroy_handles(); + destroy_handles(); // 閿姣佸彞鏌 gstrace_tryblock_exit(true, oldTryCounter); /* Since not using PG_TRY, must reset error stack by hand */ + // 閲嶇疆閿欒鍫嗘爤 t_thrd.log_cxt.error_context_stack = NULL; t_thrd.log_cxt.call_stack = NULL; /* Prevent interrupts while cleaning up */ - HOLD_INTERRUPTS(); + HOLD_INTERRUPTS(); // 鍦ㄦ竻鐞嗘湡闂撮樆姝腑鏂 /* Report the error to the server log */ - EmitErrorReport(); + EmitErrorReport(); // 灏嗛敊璇姤鍛婅褰曞埌鏈嶅姟鍣ㄦ棩蹇椾腑 /* release resource held by lsc */ - AtEOXact_SysDBCache(false); + AtEOXact_SysDBCache(false); // 閲婃斁lsc鎸佹湁鐨勮祫婧 /* release resource */ - LWLockReleaseAll(); + // 閲婃斁璧勬簮 + LWLockReleaseAll(); // 閲婃斁鎵鏈夌殑杞婚噺绾ч攣 - FreeBarrierLsnInfo(); + FreeBarrierLsnInfo(); // 閲婃斁Barrier淇℃伅缁撴瀯浣撶殑鍐呭瓨 /* * Now return to normal top-level context and clear ErrorContext for * next time. */ - MemoryContextSwitchTo(barrier_creator_context); - FlushErrorState(); - MemoryContextResetAndDeleteChildren(barrier_creator_context); + MemoryContextSwitchTo(barrier_creator_context); // 鍒囨崲鍒 barrier_creator_context 鍐呭瓨涓婁笅鏂 + FlushErrorState(); // 娓呴櫎閿欒鐘舵佷俊鎭 + MemoryContextResetAndDeleteChildren(barrier_creator_context); // 閲嶇疆骞跺垹闄 barrier_creator_context 鍐呭瓨涓婁笅鏂囩殑瀛愯妭鐐 /* Now we can allow interrupts again */ - RESUME_INTERRUPTS(); + RESUME_INTERRUPTS(); // 鎭㈠涓柇澶勭悊 return; } + // 杩涘叆寮傚父澶勭悊灏濊瘯鍧楋紝淇濆瓨鏃х殑寮傚父澶勭悊璁℃暟鍣ㄥ苟鑾峰彇褰撳墠璁℃暟鍣 oldTryCounter = gstrace_tryblock_entry(&curTryCounter); /* We can now handle ereport(ERROR) */ - t_thrd.log_cxt.PG_exception_stack = &local_sigjmp_buf; + t_thrd.log_cxt.PG_exception_stack = &local_sigjmp_buf; // 灏嗘湰鍦扮殑璺宠浆缂撳啿鍖鸿缃负寮傚父澶勭悊鐨勮烦杞紦鍐插尯 /* * Unblock signals (they were blocked when the postmaster forked us) */ - gs_signal_setmask(&t_thrd.libpq_cxt.UnBlockSig, NULL); - (void)gs_signal_unblock_sigusr2(); - SetProcessingMode(NormalProcessing); - exec_init_poolhandles(); + gs_signal_setmask(&t_thrd.libpq_cxt.UnBlockSig, NULL); // 瑙i櫎鍏堝墠闃诲鐨勪俊鍙 + (void)gs_signal_unblock_sigusr2(); // 瑙i櫎瀵 SIGUSR2 淇″彿鐨勯樆濉 + SetProcessingMode(NormalProcessing); // 璁剧疆澶勭悊妯″紡涓烘甯稿鐞嗘ā寮 + exec_init_poolhandles(); // 鍒濆鍖栬繛鎺ユ睜鍙ユ焺 #ifdef ENABLE_MULTIPLE_NODES /* * Ensure all barrier commond execuet on first coordinator */ do { - if (IsFirstCn()) + if (IsFirstCn()) // 濡傛灉褰撳墠鑺傜偣鏄涓涓崗璋冨櫒鑺傜偣 break; - + // 杈撳嚭璋冭瘯淇℃伅锛屾寚绀哄綋鍓嶈妭鐐逛笉鏄涓涓崗璋冨櫒鑺傜偣 ereport(DEBUG1, (errmsg("[BarrierCreator] Current node is not first node: %s", g_instance.attr.attr_common.PGXCNodeName))); + // 濡傛灉鏀跺埌閲嶆柊鍔犺浇杩炴帴姹犵殑淇″彿锛岄噸鏂板姞杞借繛鎺ユ睜骞堕噸缃爣蹇 if (IsGotPoolReload()) { - BarrierCreatorPoolerReload(); - ResetGotPoolReload(false); + BarrierCreatorPoolerReload(); // 閲嶆柊鍔犺浇杩炴帴姹 + ResetGotPoolReload(false); // 閲嶇疆鏍囧織锛岃〃绀哄凡澶勭悊杩炴帴姹犻噸鏂板姞杞 } - CHECK_FOR_INTERRUPTS(); - pg_usleep(1000000L); + CHECK_FOR_INTERRUPTS(); // 妫鏌ユ槸鍚︽敹鍒颁腑鏂俊鍙凤紝濡傛灉鏄垯澶勭悊涓柇 + pg_usleep(1000000L); // 浼戠湢1绉掗挓 } while (1); #endif ereport(DEBUG1, (errmsg("[BarrierCreator] Init connections with CN/DN, dn count : %d, cn count : %d", u_sess->pgxc_cxt.NumDataNodes, u_sess->pgxc_cxt.NumCoords))); + // 杈撳嚭鏃ュ織锛屾寚鏄庡綋鍓嶈妭鐐规槸 barrier creator ereport(LOG, (errmsg("[BarrierCreator] %s is barrier creator", g_instance.attr.attr_common.PGXCNodeName))); + // 璁剧疆鍋滄鏍囧織涓 false锛岃〃绀轰笉鍋滄 barrier creator 绾跨▼ g_instance.barrier_creator_cxt.stop = false; - if (g_instance.archive_obs_cxt.archive_slot_num != 0) { + if (g_instance.archive_obs_cxt.archive_slot_num != 0) { // 濡傛灉瀛樺湪褰掓。妲戒綅 t_thrd.barrier_creator_cxt.archive_slot_names = GetAllArchiveSlotsName(); if (t_thrd.barrier_creator_cxt.archive_slot_names == NIL || t_thrd.barrier_creator_cxt.archive_slot_names->length == 0) { - return; + return; // 娌℃湁鑾峰彇鍒板綊妗fЫ浣嶅悕绉帮紝鐩存帴杩斿洖 } + // 鑾峰彇褰掓。妲戒綅鐨 barrier 绱㈠紩鍜宭ast barrier 鏃堕棿 index = GetObsBarrierIndex(t_thrd.barrier_creator_cxt.archive_slot_names, &last_barrier_time); + // 鑾峰彇褰掓。妲戒綅鐨 barrier 绱㈠紩鍜屾渶鍚庣殑 barrier 鏃堕棿 t_thrd.barrier_creator_cxt.first_cn_timeline = GetObsFirstCNBarrierTimeline(t_thrd.barrier_creator_cxt.archive_slot_names); /* @@ -397,83 +430,94 @@ void barrier_creator_main(void) * wait for a while to prevent barrier time rollback. */ do { - gettimeofday(&tv, NULL); + gettimeofday(&tv, NULL); // 鑾峰彇褰撳墠鏃堕棿 long current_time = TIME_GET_MILLISEC(tv); - if (last_barrier_time < current_time) { + if (last_barrier_time < current_time) { // 濡傛灉鏈鍚庝竴涓猙arrier鏃堕棿姣斿綋鍓嶆椂闂村皬锛屽垯璺冲嚭寰幆 break; } + // 璁$畻鏃堕棿宸苟鎵撳嵃鏃ュ織淇℃伅 long time_diff = last_barrier_time - current_time; ereport(LOG, (errmsg("[BarrierCreator] current time %ld is smaller than barrier time %ld, and sleep %ld ms", current_time, last_barrier_time, time_diff))); - CHECK_FOR_INTERRUPTS(); - pg_usleep(time_diff * 1000L); + CHECK_FOR_INTERRUPTS(); // 妫鏌ユ槸鍚︽敹鍒颁腑鏂俊鍙凤紝濡傛灉鏈夛紝鍒欏鐞嗕腑鏂 + pg_usleep(time_diff * 1000L); // 浼戠湢鎸囧畾鐨勬椂闂村樊 } while (1); + // 濡傛灉鏄涓涓猙arrier锛岃褰曞叏灞barrier鍒楄〃鐨勫紑濮嬫椂闂 if (t_thrd.barrier_creator_cxt.is_first_barrier) { gettimeofday(&tv, NULL); WriteGlobalBarrierListStartTimeOnMedia(TIME_GET_MILLISEC(tv)); } #ifdef ENABLE_MULTIPLE_NODES +// 濡傛灉鍚敤浜嗗鑺傜偣妯″紡 while (!START_AUTO_CSN_BARRIER) { - CHECK_FOR_INTERRUPTS(); - pg_usleep(1000000L); + // 鍦ㄦ湭鏀跺埌 START_AUTO_CSN_BARRIER 淇″彿涔嬪墠锛屽惊鐜瓑寰 + CHECK_FOR_INTERRUPTS(); // 妫鏌ユ槸鍚︽敹鍒颁腑鏂俊鍙凤紝濡傛灉鏈夛紝鍒欏鐞嗕腑鏂 + pg_usleep(1000000L); // 绛夊緟1绉 } #endif } #ifdef ENABLE_MULTIPLE_NODES - CleanupBarrierLock(); +// 濡傛灉鍚敤浜嗗鑺傜偣妯″紡 + CleanupBarrierLock(); // 娓呯悊barrier閿 #endif while (!g_instance.barrier_creator_cxt.stop) { if (t_thrd.barrier_creator_cxt.got_SIGHUP) { + // 濡傛灉鏀跺埌 SIGHUP 淇″彿锛屾墽琛岄厤缃枃浠跺鐞 t_thrd.barrier_preparse_cxt.got_SIGHUP = false; ProcessConfigFile(PGC_SIGHUP); startCsnBarrier = g_instance.attr.attr_storage.auto_csn_barrier; } /* in hadr switchover, barrier creator thread stop creating new barriers during service truncate.*/ + // 濡傛灉褰掓。妲芥暟閲忎笉涓0涓旀湇鍔℃埅鏂爣蹇椾负true if (g_instance.archive_obs_cxt.archive_slot_num != 0 && g_instance.archive_obs_cxt.in_service_truncate == true) { - continue; + continue; // 鍦ㄦ湇鍔℃埅鏂湡闂寸户缁惊鐜笅涓娆¤凯浠 } - if (g_instance.archive_obs_cxt.archive_slot_num != 0) { + if (g_instance.archive_obs_cxt.archive_slot_num != 0) { // 濡傛灉瀛樺湪褰掓。妲 if (t_thrd.barrier_creator_cxt.barrier_update_last_time_info == NULL) { + // 濡傛灉barrier鏇存柊鐨勬椂闂翠俊鎭负绌猴紝鍒欏垎閰嶅唴瀛樺苟鍒濆鍖栦负0 t_thrd.barrier_creator_cxt.barrier_update_last_time_info = (BarrierUpdateLastTimeInfo*)palloc0( sizeof(BarrierUpdateLastTimeInfo) * g_instance.attr.attr_storage.max_replication_slots); } #ifdef ENABLE_MULTIPLE_NODES - if (g_instance.archive_obs_cxt.barrier_lsn_info == NULL) { + if (g_instance.archive_obs_cxt.barrier_lsn_info == NULL) { // 濡傛灉barrier LSN 淇℃伅涓虹┖ int nodeSize = *t_thrd.pgxc_cxt.shmemNumCoords + *t_thrd.pgxc_cxt.shmemNumDataNodes; - AllocBarrierLsnInfo(nodeSize); - SpinLockAcquire(&g_instance.archive_obs_cxt.barrier_lock); - g_instance.archive_obs_cxt.max_node_cnt = nodeSize; - SpinLockRelease(&g_instance.archive_obs_cxt.barrier_lock); + AllocBarrierLsnInfo(nodeSize); // 鍒嗛厤barrier LSN 淇℃伅鐨勫唴瀛 + SpinLockAcquire(&g_instance.archive_obs_cxt.barrier_lock); // 鑾峰彇鍏ㄥ眬barrier閿 + g_instance.archive_obs_cxt.max_node_cnt = nodeSize; // 璁剧疆鏈澶ц妭鐐规暟涓烘寚瀹氬 + SpinLockRelease(&g_instance.archive_obs_cxt.barrier_lock); // 閲婃斁鍏ㄥ眬barrier閿 } #endif - archiveSlotNames = GetAllArchiveSlotsName(); - if (archiveSlotNames == NIL || archiveSlotNames->length == 0) { + archiveSlotNames = GetAllArchiveSlotsName(); // 鑾峰彇鎵鏈夊綊妗fЫ鐨勫悕绉 + if (archiveSlotNames == NIL || archiveSlotNames->length == 0) { // 濡傛灉鏃犳硶鑾峰彇褰掓。妲藉悕绉帮紝鍙戝嚭璀﹀憡骞惰繑鍥 ereport(WARNING, (errmsg("[BarrierCreator] could not get archive slot name when barrier start"))); return; } - if (t_thrd.barrier_creator_cxt.archive_slot_names == NULL) { - t_thrd.barrier_creator_cxt.archive_slot_names = archiveSlotNames; + if (t_thrd.barrier_creator_cxt.archive_slot_names == NULL) { // 濡傛灉褰掓。妲藉悕绉板皻鏈垵濮嬪寲 + t_thrd.barrier_creator_cxt.archive_slot_names = archiveSlotNames; // 鑾峰彇绗竴涓崗璋冨櫒鑺傜偣鐨勬椂闂寸嚎淇℃伅 t_thrd.barrier_creator_cxt.first_cn_timeline = GetObsFirstCNBarrierTimeline(t_thrd.barrier_creator_cxt.archive_slot_names); } - if (archiveSlotNames->length > t_thrd.barrier_creator_cxt.archive_slot_names->length) { + if (archiveSlotNames->length > t_thrd.barrier_creator_cxt.archive_slot_names->length) { // 濡傛灉褰撳墠褰掓。妲芥暟閲忓ぇ浜庝箣鍓嶈褰曠殑鏁伴噺 t_thrd.barrier_creator_cxt.archive_slot_names = archiveSlotNames; - t_thrd.barrier_creator_cxt.is_first_barrier = true; - gettimeofday(&tv, NULL); - WriteGlobalBarrierListStartTimeOnMedia(TIME_GET_MILLISEC(tv)); + t_thrd.barrier_creator_cxt.is_first_barrier = true; // 灏嗘爣蹇椾綅璁句负true锛岃〃绀烘槸绗竴娆″垱寤哄睆闅 + gettimeofday(&tv, NULL); // 鑾峰彇褰撳墠鏃堕棿 + WriteGlobalBarrierListStartTimeOnMedia(TIME_GET_MILLISEC(tv)); // 璁板綍鍏ㄥ眬灞忛殰鍒楄〃鐨勫紑濮嬫椂闂 } else if (archiveSlotNames->length < t_thrd.barrier_creator_cxt.archive_slot_names->length) { + // 濡傛灉褰撳墠褰掓。妲芥暟閲忓皬浜庝箣鍓嶈褰曠殑鏁伴噺 t_thrd.barrier_creator_cxt.archive_slot_names = archiveSlotNames; } } - pg_usleep_retry(500000L, 0); + pg_usleep_retry(500000L, 0); if (!startCsnBarrier && g_instance.archive_obs_cxt.archive_slot_num == 0) { + // 濡傛灉涓嶉渶瑕佸惎鍔–SN barrier涓斿綊妗fЫ鏁伴噺涓0 g_instance.barrier_creator_cxt.stop = true; for (int i = 0; i < g_instance.attr.attr_storage.max_replication_slots; i++) { if (g_instance.archive_thread_info.obsBarrierArchPID[i] != 0) { + // 鍚戝瓙杩涚▼鍙戦侀鍑轰俊鍙 signal_child(g_instance.archive_thread_info.obsBarrierArchPID[i], SIGUSR2, -1); } } @@ -483,41 +527,47 @@ void barrier_creator_main(void) /* create barrier with increasing index */ #ifdef ENABLE_MULTIPLE_NODES - if (IsGotPoolReload()) { + if (IsGotPoolReload()) { // 濡傛灉鏀跺埌閲嶆柊鍔犺浇鐨勪俊鍙 BarrierCreatorPoolerReload(); ResetGotPoolReload(false); - if (!IsFirstCn()) + if (!IsFirstCn()) // 濡傛灉褰撳墠鑺傜偣涓嶆槸绗竴涓崗璋冨櫒鑺傜偣 break; } ereport(DEBUG1, (errmsg("[BarrierCreator] auto_csn_barrier: %d", startCsnBarrier))); - if (startCsnBarrier) { - rc = snprintf_s(barrier_name, BARRIER_NAME_LEN, BARRIER_NAME_LEN - 1, CSN_BARRIER_NAME); + if (startCsnBarrier) { // 濡傛灉鍚敤浜嗚嚜鍔–SN barrier + rc = snprintf_s(barrier_name, BARRIER_NAME_LEN, BARRIER_NAME_LEN - 1, CSN_BARRIER_NAME); //鏋勯燙SN barrier鍚嶇О securec_check_ss_c(rc, "\0", "\0"); - RequestBarrier(barrier_name, NULL); - ereport(LOG, (errmsg("[BarrierCreator]barrier %s created", barrier_name))); + RequestBarrier(barrier_name, NULL); // 璇锋眰鍒涘缓CSN barrier + ereport(LOG, (errmsg("[BarrierCreator]barrier %s created", barrier_name))); // 鏃ュ織涓褰昩arrier鐨勫垱寤 } #else + //鏋勯燙SN barrier鍚嶇О rc = snprintf_s(barrier_name, BARRIER_NAME_LEN, BARRIER_NAME_LEN - 1, "hadr_%020" PRIu64 "_%013ld", index, TIME_GET_MILLISEC(tv)); securec_check_ss_c(rc, "\0", "\0"); - DisasterRecoveryRequestBarrier(barrier_name); - ereport(LOG, (errmsg("[BarrierCreator] barrier %s created", barrier_name))); + DisasterRecoveryRequestBarrier(barrier_name); // 璇锋眰鍒涘缓鐏惧 barrier + ereport(LOG, (errmsg("[BarrierCreator] barrier %s created", barrier_name))); // 鏃ュ織涓褰昩arrier鐨勫垱寤 #endif index++; } - ereport(LOG, (errmsg("[BarrierCreator] barrier creator thread exits."))); - if (t_thrd.barrier_creator_cxt.barrier_update_last_time_info != 0) { + ereport(LOG, (errmsg("[BarrierCreator] barrier creator thread exits."))); // 璁板綍鏃ュ織锛屾寚绀築arrier Creator绾跨▼鍗冲皢閫鍑 + if (t_thrd.barrier_creator_cxt.barrier_update_last_time_info != 0) { // 妫鏌ユ槸鍚﹀垎閰嶄簡barrier_update_last_time_info缁撴瀯鐨勫唴瀛 + // 寰幆閬嶅巻barrier_update_last_time_info缁撴瀯鏁扮粍浠ラ噴鏀捐祫婧 for (int i = 0; i < g_instance.attr.attr_storage.max_replication_slots; i++) { + // 妫鏌ュ綋鍓嶇储寮曞鐨刟rchiveSlotName鏄惁涓嶄负NULL if (t_thrd.barrier_creator_cxt.barrier_update_last_time_info[i].archiveSlotName != NULL) { + // 閲婃斁涓巃rchiveSlotName鐩稿叧鑱旂殑鍐呭瓨 pfree_ext(t_thrd.barrier_creator_cxt.barrier_update_last_time_info[i].archiveSlotName); } } + // 閲婃斁涓巄arrier_update_last_time_info缁撴瀯鏁扮粍鐩稿叧鑱旂殑鍐呭瓨 pfree_ext(t_thrd.barrier_creator_cxt.barrier_update_last_time_info); } - destroy_handles(); - FreeBarrierLsnInfo(); + // 鎵ц娓呯悊鎿嶄綔 + destroy_handles(); // 閿姣佸彞鏌 + FreeBarrierLsnInfo(); // 閲婃斁Barrier LSN淇℃伅 proc_exit(0); } diff --git a/src/gausskernel/process/postmaster/barrier_preparse.cpp b/src/gausskernel/process/postmaster/barrier_preparse.cpp index 7ab25c93a..69c13a759 100644 --- a/src/gausskernel/process/postmaster/barrier_preparse.cpp +++ b/src/gausskernel/process/postmaster/barrier_preparse.cpp @@ -40,17 +40,27 @@ #include "postmaster/barrier_preparse.h" typedef struct XLogPageReadPrivate { - const char *datadir; - TimeLineID tli; + const char *datadir; // 瀛樺偍鏁版嵁搴撶殑鏁版嵁鐩綍璺緞 + TimeLineID tli; // 瀛樺偍 WAL 鏃ュ織鎵鍦ㄧ殑鏃堕棿绾挎爣璇嗙 } XLogPageReadPrivate; +/* + * 瀹忥紝鐢ㄤ簬纭畾鏄惁闇瑕佸皢鏉$洰鎻掑叆鍝堝笇琛ㄣ傞氳繃妫鏌ヨ褰曠被鍨嬶紙xl_rmid锛夊拰鏌愪簺鏉′欢鏉ュ喅瀹氭槸鍚︽彃鍏ャ + * - 濡傛灉璁板綍绫诲瀷涓篟M_BARRIER_ID锛屽苟涓攊nfo涓篨LOG_BARRIER_SWITCHOVER锛 + * 鎴栬呰妭鐐规槸鍗忚皟鍣ㄤ笖info涓篨LOG_BARRIER_COMMIT锛 + * 鎴栬呰妭鐐规槸鏁版嵁鑺傜偣涓攊nfo涓篨LOG_BARRIER_CREATE + * 閭d箞锛岄渶瑕佸皢鏉$洰鎻掑叆鍝堝笇琛ㄣ + */ #define NEED_INSERT_INTO_HASH \ ((record->xl_rmid == RM_BARRIER_ID) && ((info == XLOG_BARRIER_SWITCHOVER) || \ (IS_PGXC_COORDINATOR && info == XLOG_BARRIER_COMMIT) || (IS_PGXC_DATANODE && info == XLOG_BARRIER_CREATE))) +//鍒濆鍖栦笌barrier鐩稿叧鐨勫搱甯岃〃鐨勫嚱鏁 static void InitBarrierHash() { + // 妫鏌ユ槸鍚﹀凡缁忓垱寤轰簡barrier涓婁笅鏂囷紝濡傛灉娌℃湁鍒欏垱寤轰竴涓 if (g_instance.csn_barrier_cxt.barrier_context == NULL) { + // 鍒涘缓涓涓柊鐨勫唴瀛樹笂涓嬫枃锛屽懡鍚嶄负CsnBarrierContext锛岀敤浜庡瓨鍌ㄤ笌barrier鐩稿叧淇℃伅 g_instance.csn_barrier_cxt.barrier_context = AllocSetContextCreate(g_instance.instance_context, "CsnBarrierContext", ALLOCSET_DEFAULT_MINSIZE, @@ -58,66 +68,72 @@ static void InitBarrierHash() ALLOCSET_DEFAULT_MAXSIZE, SHARED_CONTEXT); } - + // 瀹氫箟HASHCTL缁撴瀯锛岀敤浜庡垵濮嬪寲鍝堝笇琛ㄧ殑灞炴 HASHCTL ctl; errno_t rc = 0; /* Init hash table */ - rc = memset_s(&ctl, sizeof(HASHCTL), 0, sizeof(HASHCTL)); + rc = memset_s(&ctl, sizeof(HASHCTL), 0, sizeof(HASHCTL)); // 灏哻tl缁撴瀯娓呴浂锛岀‘淇濈粨鏋勪腑鐨勫悇瀛楁姝g‘鍒濆鍖 securec_check(rc, "", ""); + // 璁剧疆鍝堝笇琛ㄧ殑閿ぇ灏忓拰姣忎釜鏉$洰鐨勫ぇ灏 ctl.keysize = MAX_BARRIER_ID_LENGTH * sizeof(char); ctl.entrysize = MAX_BARRIER_ID_LENGTH * sizeof(char); - ctl.hash = string_hash; + ctl.hash = string_hash; // 璁剧疆鍝堝笇鍑芥暟涓簊tring_hash锛岀敤浜庤绠楅敭鐨勫搱甯屽 + // 璁剧疆鍝堝笇琛ㄤ娇鐢ㄧ殑涓婁笅鏂囦负涔嬪墠鍒涘缓鐨凜snBarrierContext涓婁笅鏂 ctl.hcxt = g_instance.csn_barrier_cxt.barrier_context; + // 鍒涘缓灞忛殰鍝堝笇琛紝鎸囧畾涓婅堪鍝堝笇琛ㄧ殑鍚嶇О銆佸垵濮嬪ぇ灏忓拰灞炴 g_instance.csn_barrier_cxt.barrier_hash_table = hash_create("Barrier Id Storage Table", INIBARRIERCACHESIZE, &ctl, HASH_ELEM | HASH_FUNCTION | HASH_SHRCTX); + // 涓哄睆闅滃搱甯岃〃鍒嗛厤杞婚噺绾ч攣锛岀敤浜庡苟鍙戣闂帶鍒 g_instance.csn_barrier_cxt.barrier_hashtbl_lock = LWLockAssign(LWTRANCHE_BARRIER_TBL); } - +// 璁剧疆barrier ID static void SetBarrieID(const char *barrierId, XLogRecPtr lsn) { errno_t rc = EOK; const uint32 shiftSize = 32; volatile WalRcvData *walrcv = t_thrd.walreceiverfuncs_cxt.WalRcv; - SpinLockAcquire(&walrcv->mutex); + SpinLockAcquire(&walrcv->mutex); // 鑾峰彇浜掓枼閿侊紝纭繚鏁版嵁涓鑷存 + // 浣跨敤strncpy_s鍑芥暟灏哹arrierId澶嶅埗鍒發astReceivedBarrierId涓紝纭繚瀛楃涓插畨鍏ㄦ rc = strncpy_s((char *)walrcv->lastReceivedBarrierId, MAX_BARRIER_ID_LENGTH, barrierId, MAX_BARRIER_ID_LENGTH - 1); securec_check(rc, "\0", "\0"); - walrcv->lastReceivedBarrierId[MAX_BARRIER_ID_LENGTH - 1] = '\0'; - walrcv->lastReceivedBarrierLSN = lsn; - SpinLockRelease(&walrcv->mutex); + walrcv->lastReceivedBarrierId[MAX_BARRIER_ID_LENGTH - 1] = '\0'; // 鍦ㄦ湯灏炬坊鍔犲瓧绗︿覆缁撴潫绗 + walrcv->lastReceivedBarrierLSN = lsn; // 璁剧疆鏈鍚庢帴鏀跺埌鐨刡arrier LSN + SpinLockRelease(&walrcv->mutex); // 閲婃斁浜掓枼閿 + // 杈撳嚭鏃ュ織锛岃褰曡缃殑barrier ID鍜宐arrier LSN ereport(LOG, (errmsg("SetBarrieID set the barrier ID is %s, the barrier LSN is %08X/%08X", barrierId, (uint32)(lsn >> shiftSize), (uint32)lsn))); } - +// 澶勭悊SIGHUP淇″彿 static void BarrierPreParseSigHupHandler(SIGNAL_ARGS) { int save_errno = errno; - t_thrd.barrier_preparse_cxt.got_SIGHUP = true; + t_thrd.barrier_preparse_cxt.got_SIGHUP = true; // 璁剧疆鏍囧織浣嶏紝琛ㄧず鏀跺埌SIGHUP淇″彿 if (t_thrd.proc) { - SetLatch(&t_thrd.proc->procLatch); + SetLatch(&t_thrd.proc->procLatch); // 璁剧疆杩涚▼鐨凩atch锛岀敤浜庡敜閱掕繘绋嬪鐞哠IGHUP淇″彿 } errno = save_errno; } - +// 澶勭悊鍏抽棴璇锋眰淇″彿 static void BarrierPreParseShutdownHandler(SIGNAL_ARGS) { int save_errno = errno; - t_thrd.barrier_preparse_cxt.shutdown_requested = true; + t_thrd.barrier_preparse_cxt.shutdown_requested = true; // 璁剧疆鍏抽棴璇锋眰鏍囧織涓簍rue锛岃〃绀烘敹鍒颁簡鍏抽棴璇锋眰淇″彿 if (t_thrd.proc) - SetLatch(&t_thrd.proc->procLatch); + SetLatch(&t_thrd.proc->procLatch); // 璁剧疆绾跨▼鐨凩atch锛岀敤浜庡敜閱掔嚎绋嬪鐞嗗叧闂姹備俊鍙 errno = save_errno; } - +// 澶勭悊蹇熺粓姝俊鍙 鐢ㄤ簬鍦ㄥ嚭鐜颁弗閲嶉棶棰樻椂寮哄埗缁堟杩涚▼ static void BarrierPreParseQuickDie(SIGNAL_ARGS) { - gs_signal_setmask(&t_thrd.libpq_cxt.BlockSig, NULL); + gs_signal_setmask(&t_thrd.libpq_cxt.BlockSig, NULL); // 瑙i櫎瀵逛俊鍙风殑闃诲锛屼互渚胯繘琛屽揩閫熺粓姝 /* * We DO NOT want to run proc_exit() callbacks -- we're here because @@ -127,7 +143,7 @@ static void BarrierPreParseQuickDie(SIGNAL_ARGS) * things by calling exit() directly, we have to reset the callbacks * explicitly to make this work as intended. */ - on_exit_reset(); + on_exit_reset(); // 閲嶇疆閫鍑哄洖璋冨嚱鏁 /* * Note we do exit(2) not exit(0). This is to force the postmaster into a @@ -137,105 +153,108 @@ static void BarrierPreParseQuickDie(SIGNAL_ARGS) * should ensure the postmaster sees this as a crash, too, but no harm in * being doubly sure.) */ - exit(2); + exit(2); //浠ヤ唬鐮2 閫鍑鸿繘绋 } - +// 澶勭悊SIGUSR1淇″彿 static void BarrierPreParseSigUsr1Handler(SIGNAL_ARGS) { - int saveErrno = errno; + int saveErrno = errno; // 淇濆瓨褰撳墠閿欒鐮佺殑鍊 - latch_sigusr1_handler(); + latch_sigusr1_handler(); // 澶勭悊SIGUSR1淇″彿鐨勫洖璋冨嚱鏁 - errno = saveErrno; + errno = saveErrno; // 鎭㈠涔嬪墠淇濆瓨鐨勯敊璇爜 } /* * Called when the BarrierPreParseMain is ending. */ +// 鍦˙arrierPreParseMain缁撴潫鏃惰皟鐢 static void ShutdownBarrierPreParse(int code, Datum arg) { + // 灏咮arrierPreParseLatch璁句负NULL锛岃〃绀哄叧闂瑽arrierPreParse绾跨▼ g_instance.proc_base->BarrierPreParseLatch = NULL; } - +// 璁剧疆BarrierPreParse绾跨▼鐨凩SN void SetBarrierPreParseLsn(XLogRecPtr startptr) { - volatile WalRcvData *walrcv = t_thrd.walreceiverfuncs_cxt.WalRcv; - SpinLockAcquire(&walrcv->mutex); - walrcv->lastReceivedBarrierLSN = startptr; - SpinLockRelease(&walrcv->mutex); + volatile WalRcvData *walrcv = t_thrd.walreceiverfuncs_cxt.WalRcv; // 鑾峰彇WalRcvData缁撴瀯浣撶殑鎸囬拡 + SpinLockAcquire(&walrcv->mutex); // 鑾峰彇浜掓枼閿侊紝淇濊瘉鎿嶄綔鐨勫師瀛愭 + walrcv->lastReceivedBarrierLSN = startptr; // 璁剧疆lastReceivedBarrierLSN涓烘寚瀹氱殑LSN + SpinLockRelease(&walrcv->mutex); // 閲婃斁浜掓枼閿 } void BarrierPreParseMain(void) { - volatile WalRcvData *walrcv = t_thrd.walreceiverfuncs_cxt.WalRcv; - MemoryContext preParseContext; - XLogRecord *record = NULL; - XLogReaderState *xlogreader = NULL; - char *errormsg = NULL; - XLogPageReadPrivate readprivate; - XLogRecPtr startLSN = InvalidXLogRecPtr; - XLogRecPtr preStartLSN = InvalidXLogRecPtr; - XLogRecPtr lastReadLSN = InvalidXLogRecPtr; - bool found = false; - XLogRecPtr barrierLSN = InvalidXLogRecPtr; - char *xLogBarrierId = NULL; - char barrierId[MAX_BARRIER_ID_LENGTH] = {0}; - const uint32 shiftSize = 32; - int rc; + volatile WalRcvData *walrcv = t_thrd.walreceiverfuncs_cxt.WalRcv; // 鑾峰彇WalRcvData缁撴瀯浣撶殑鎸囬拡 + MemoryContext preParseContext; // 鍐呭瓨涓婁笅鏂囷紝鐢ㄤ簬鍒嗛厤鍐呭瓨 + XLogRecord *record = NULL; // XLog璁板綍鎸囬拡 + XLogReaderState *xlogreader = NULL; // XLog璇诲彇鍣ㄧ殑鐘舵佺粨鏋勪綋鎸囬拡 + char *errormsg = NULL; // 閿欒娑堟伅 + XLogPageReadPrivate readprivate; // XLog椤佃鍙栫殑绉佹湁鏁版嵁 + XLogRecPtr startLSN = InvalidXLogRecPtr; // 璧峰LSN + XLogRecPtr preStartLSN = InvalidXLogRecPtr; // 鍓嶄竴涓捣濮婰SN + XLogRecPtr lastReadLSN = InvalidXLogRecPtr; // 涓婁竴娆¤鍙栫殑LSN + bool found = false; // 鏄惁鎵惧埌寰呭鐞嗙殑璁板綍 + XLogRecPtr barrierLSN = InvalidXLogRecPtr; // barrier璁板綍鐨凩SN + char *xLogBarrierId = NULL; // XLog涓殑barrierID + char barrierId[MAX_BARRIER_ID_LENGTH] = {0}; // barrier ID瀛楃涓 + const uint32 shiftSize = 32; // 浣嶇Щ澶у皬 + int rc; // 鍑芥暟杩斿洖鍊 - ereport(LOG, (errmsg("[BarrierPreParse] barrier preparse thread started"))); + ereport(LOG, (errmsg("[BarrierPreParse] barrier preparse thread started"))); // 璁板綍鏃ュ織锛屾爣璁扮嚎绋嬪紑濮 /* * Reset some signals that are accepted by postmaster but not here */ - (void)gspqsignal(SIGHUP, BarrierPreParseSigHupHandler); - (void)gspqsignal(SIGINT, SIG_IGN); - (void)gspqsignal(SIGTERM, BarrierPreParseShutdownHandler); - (void)gspqsignal(SIGQUIT, BarrierPreParseQuickDie); /* hard crash time */ - (void)gspqsignal(SIGALRM, SIG_IGN); - (void)gspqsignal(SIGPIPE, SIG_IGN); - (void)gspqsignal(SIGUSR1, BarrierPreParseSigUsr1Handler); - (void)gspqsignal(SIGUSR2, SIG_IGN); + (void)gspqsignal(SIGHUP, BarrierPreParseSigHupHandler); // 澶勭悊SIGHUP淇″彿鐨勫洖璋冨嚱鏁 + (void)gspqsignal(SIGINT, SIG_IGN); // 蹇界暐SIGINT淇″彿 + (void)gspqsignal(SIGTERM, BarrierPreParseShutdownHandler); // 澶勭悊SIGTERM淇″彿鐨勫洖璋冨嚱鏁 + (void)gspqsignal(SIGQUIT, BarrierPreParseQuickDie); /* hard crash time */ // 澶勭悊SIGQUIT淇″彿鐨勫洖璋冨嚱鏁帮紝鐢ㄤ簬蹇熺粓姝 + (void)gspqsignal(SIGALRM, SIG_IGN); // 蹇界暐SIGALRM淇″彿 + (void)gspqsignal(SIGPIPE, SIG_IGN); // 蹇界暐SIGPIPE淇″彿 + (void)gspqsignal(SIGUSR1, BarrierPreParseSigUsr1Handler); // 澶勭悊SIGUSR1淇″彿鐨勫洖璋冨嚱鏁 + (void)gspqsignal(SIGUSR2, SIG_IGN); // 蹇界暐SIGUSR2淇″彿 /* * Reset some signals that are accepted by postmaster but not here */ - (void)gspqsignal(SIGCHLD, SIG_DFL); - (void)gspqsignal(SIGTTIN, SIG_DFL); - (void)gspqsignal(SIGTTOU, SIG_DFL); - (void)gspqsignal(SIGCONT, SIG_DFL); - (void)gspqsignal(SIGWINCH, SIG_DFL); + (void)gspqsignal(SIGCHLD, SIG_DFL); // 鎭㈠SIGCHLD淇″彿鐨勯粯璁ゅ鐞 + (void)gspqsignal(SIGTTIN, SIG_DFL); // 鎭㈠SIGTTIN淇″彿鐨勯粯璁ゅ鐞 + (void)gspqsignal(SIGTTOU, SIG_DFL); // 鎭㈠SIGTTOU淇″彿鐨勯粯璁ゅ鐞 + (void)gspqsignal(SIGCONT, SIG_DFL); // 鎭㈠SIGCONT淇″彿鐨勯粯璁ゅ鐞 + (void)gspqsignal(SIGWINCH, SIG_DFL); // 鎭㈠SIGWINCH淇″彿鐨勯粯璁ゅ鐞 /* We allow SIGQUIT (quickdie) at all times */ - (void)sigdelset(&t_thrd.libpq_cxt.BlockSig, SIGQUIT); + (void)sigdelset(&t_thrd.libpq_cxt.BlockSig, SIGQUIT); // 鍏佽鍦ㄤ换浣曟椂闂存帴鏀禨IGQUIT 淇″彿 - on_shmem_exit(ShutdownBarrierPreParse, 0); + on_shmem_exit(ShutdownBarrierPreParse, 0); // 鍦ㄨ繘绋嬮鍑烘椂璋冪敤ShutdownBarrierPreParse鍑芥暟 preParseContext = AllocSetContextCreate(t_thrd.top_mem_cxt, "Barrier PreParse", ALLOCSET_DEFAULT_MINSIZE, - ALLOCSET_DEFAULT_INITSIZE, ALLOCSET_DEFAULT_MAXSIZE); - (void)MemoryContextSwitchTo(preParseContext); + ALLOCSET_DEFAULT_INITSIZE, ALLOCSET_DEFAULT_MAXSIZE); // 鍒涘缓鍐呭瓨涓婁笅鏂 + (void)MemoryContextSwitchTo(preParseContext); // 鍒囨崲鍒皃reParseContext涓婁笅鏂 /* * Unblock signals (they were blocked when the postmaster forked us) */ - gs_signal_setmask(&t_thrd.libpq_cxt.UnBlockSig, NULL); - (void)gs_signal_unblock_sigusr2(); + gs_signal_setmask(&t_thrd.libpq_cxt.UnBlockSig, NULL); // 瑙i櫎瀵逛俊鍙风殑闃诲 + (void)gs_signal_unblock_sigusr2(); // 瑙i櫎瀵筍IGUSR2淇″彿鐨勯樆濉 - g_instance.proc_base->BarrierPreParseLatch = &t_thrd.proc->procLatch; + g_instance.proc_base->BarrierPreParseLatch = &t_thrd.proc->procLatch; // 璁剧疆BarrierPreParseLatch - startLSN = walrcv->lastReceivedBarrierLSN; + startLSN = walrcv->lastReceivedBarrierLSN; // 鑾峰彇涓婃鎺ユ敹鐨刡arrier LSN ereport(LOG, (errmsg("[BarrierPreParse] preparse thread start at %08X/%08X", (uint32)(startLSN >> shiftSize), - (uint32)startLSN))); + (uint32)startLSN))); // 璁板綍鏃ュ織锛屾爣璁扮嚎绋嬭捣濮嬩綅缃 - if (g_instance.csn_barrier_cxt.barrier_hash_table == NULL) { + if (g_instance.csn_barrier_cxt.barrier_hash_table == NULL) {// 濡傛灉barrier鍝堝笇琛ㄤ负绌猴紝鍒濆鍖 InitBarrierHash(); } - readprivate.datadir = t_thrd.proc_cxt.DataDir; - readprivate.tli = GetRecoveryTargetTLI(); + readprivate.datadir = t_thrd.proc_cxt.DataDir; // 璁剧疆璇诲彇绉佹湁鏁版嵁鐨勬暟鎹洰褰 + readprivate.tli = GetRecoveryTargetTLI(); // 鑾峰彇鎭㈠鐩爣鐨勬椂闂寸嚎ID - xlogreader = XLogReaderAllocate(&SimpleXLogPageRead, &readprivate); + xlogreader = XLogReaderAllocate(&SimpleXLogPageRead, &readprivate); // 鍒嗛厤XLog璇诲彇鍣 if (xlogreader == NULL) + // 濡傛灉鍒嗛厤澶辫触锛屾姤閿 ereport(ERROR, (errcode(ERRCODE_INSUFFICIENT_RESOURCES), errmsg("memory is temporarily unavailable while allocate xlog reader"))); @@ -244,91 +263,98 @@ void BarrierPreParseMain(void) */ for (;;) { /* Clear any already-pending wakeups */ - ResetLatch(&t_thrd.proc->procLatch); + ResetLatch(&t_thrd.proc->procLatch); //娓呴櫎宸叉寕璧风殑鍞ら啋 - if (t_thrd.barrier_preparse_cxt.got_SIGHUP) { - t_thrd.barrier_preparse_cxt.got_SIGHUP = false; - ProcessConfigFile(PGC_SIGHUP); + if (t_thrd.barrier_preparse_cxt.got_SIGHUP) { // 濡傛灉鏀跺埌SIGHUP淇″彿锛岄噸鏂拌鍙栭厤缃枃浠 + t_thrd.barrier_preparse_cxt.got_SIGHUP = false; // 閲嶇疆淇″彿鏍囧織 + ProcessConfigFile(PGC_SIGHUP); // 澶勭悊SIGHUP淇″彿锛岄噸鏂拌鍙栭厤缃枃浠 } - if (t_thrd.barrier_preparse_cxt.shutdown_requested) { + if (t_thrd.barrier_preparse_cxt.shutdown_requested) { // 濡傛灉鏀跺埌鍏抽棴璇锋眰锛岀粨鏉熺嚎绋 ereport(LOG, (errmsg("[BarrierPreParse] preparse thread shut down"))); - XLogReaderFree(xlogreader); + XLogReaderFree(xlogreader); // 閲婃斁XLog璇诲彇鍣ㄧ殑璧勬簮 proc_exit(0); /* done */ } - found = false; - preStartLSN = startLSN; + found = false; // 鍒濆鍖杅ound鏍囧織涓篺alse + preStartLSN = startLSN; // 淇濆瓨涓婁竴娆$殑璧峰LSN + // 璁板綍鏃ュ織锛屾爣璁伴瑙f瀽寮濮嬩綅缃 ereport(DEBUG1, (errmsg("[BarrierPreParse] start to preparse at: %08X/%08X", (uint32)(startLSN >> shiftSize), (uint32)startLSN))); - startLSN = XLogFindNextRecord(xlogreader, startLSN); - if (XLogRecPtrIsInvalid(startLSN)) { - startLSN = preStartLSN; + startLSN = XLogFindNextRecord(xlogreader, startLSN); // 鏌ユ壘涓嬩竴涓猉Log璁板綍鐨凩SN + if (XLogRecPtrIsInvalid(startLSN)) { // 濡傛灉鎵句笉鍒帮紝鍥炲埌涓婁竴涓捣濮婰SN + startLSN = preStartLSN; // 浣跨敤涔嬪墠璁板綍鐨勮捣濮婰SN if (!XLByteEQ(walrcv->receiver_flush_location, startLSN) && !XLByteEQ(walrcv->lastRecoveredBarrierLSN, startLSN)) { /* reset startLSN */ - startLSN = walrcv->lastRecoveredBarrierLSN; + startLSN = walrcv->lastRecoveredBarrierLSN; // 浣跨敤涓婃鎭㈠鐨凚arrier LSN ereport(LOG, (errmsg("[BarrierPreParse] reset startLSN with lastRecoveredBarrierLSN: %08X/%08X", - (uint32)(startLSN >> shiftSize), (uint32)startLSN))); + (uint32)(startLSN >> shiftSize), (uint32)startLSN))); // 璁板綍鏃ュ織锛屾爣璁伴噸缃畇tartLSN } continue; } do { + // 浠嶺Log涓鍙栬褰曪紝浠巗tartLSN寮濮 record = XLogReadRecord(xlogreader, startLSN, &errormsg); - if (record == NULL) { + if (record == NULL) { // 濡傛灉璇诲彇鍒颁簡NULL璁板綍锛屽嵆鏃犳硶缁х画璇诲彇锛岃烦鍑哄惊鐜 break; } - lastReadLSN = xlogreader->EndRecPtr; - uint8 info = XLogRecGetInfo(xlogreader) & ~XLR_INFO_MASK; + lastReadLSN = xlogreader->EndRecPtr; // 璁板綍鏈鍚庤鍙栫殑LSN + // 鑾峰彇XLog璁板綍鐨勪俊鎭綅锛屽幓闄LR_INFO_MASK鏍囧織浣 + uint8 info = XLogRecGetInfo(xlogreader) & ~XLR_INFO_MASK; if (NEED_INSERT_INTO_HASH) { - xLogBarrierId = XLogRecGetData(xlogreader); - if (!IS_CSN_BARRIER(xLogBarrierId)) { + // 濡傛灉闇瑕佸皢璁板綍鎻掑叆鍒板搱甯岃〃涓 + xLogBarrierId = XLogRecGetData(xlogreader); // 鑾峰彇XLog璁板綍鐨勬暟鎹儴鍒 + if (!IS_CSN_BARRIER(xLogBarrierId)) { // 濡傛灉涓嶆槸鐢ㄤ簬澶囨満闆嗙兢鐨刡arrier璁板綍 ereport(WARNING, (errmsg("[BarrierPreParse] %s is not for standby cluster", xLogBarrierId))); } else { // insert into hash table - found = true; - barrierLSN = xlogreader->EndRecPtr; + // 鎻掑叆鍒板搱甯岃〃涓 + found = true; // 鏍囪鎵惧埌閫傜敤浜庡鐢ㄩ泦缇ょ殑barrier璁板綍 + barrierLSN = xlogreader->EndRecPtr; // 璁板綍barrier鐨凩SN rc = strncpy_s((char *)barrierId, MAX_BARRIER_ID_LENGTH, xLogBarrierId, MAX_BARRIER_ID_LENGTH - 1); securec_check(rc, "\0", "\0"); - barrierId[MAX_BARRIER_ID_LENGTH - 1] = '\0'; + barrierId[MAX_BARRIER_ID_LENGTH - 1] = '\0'; // 纭繚barrierId瀛楃涓叉湁鏁堟 + // 鑾峰彇鍝堝笇琛ㄩ攣锛屾彃鍏arrierId LWLockAcquire(g_instance.csn_barrier_cxt.barrier_hashtbl_lock, LW_EXCLUSIVE); - BarrierCacheInsertBarrierId(barrierId); - LWLockRelease(g_instance.csn_barrier_cxt.barrier_hashtbl_lock); + BarrierCacheInsertBarrierId(barrierId); // 灏哹arrierId鎻掑叆鍝堝笇琛 + LWLockRelease(g_instance.csn_barrier_cxt.barrier_hashtbl_lock); // 閲婃斁鍝堝笇琛ㄩ攣 + // 璁板綍鏃ュ織锛岃鏄庢彃鍏ヤ簡barrierId鍒板搱甯岃〃涓 ereport(LOG, (errmsg("[BarrierPreParse] insert barrierID %s to the hash table, rmid: %d, crc: %d.", barrierId, record->xl_rmid, record->xl_crc))); } } - startLSN = InvalidXLogRecPtr; - } while (!t_thrd.barrier_preparse_cxt.shutdown_requested); + startLSN = InvalidXLogRecPtr; // 灏唖tartLSN閲嶇疆涓篒nvalidXLogRecPtr锛屼互渚夸笅娆″惊鐜鐞嗕笅涓涓猉Log璁板綍 + } while (!t_thrd.barrier_preparse_cxt.shutdown_requested); // 鏀跺埌鍏抽棴璇锋眰閫鍑哄惊鐜紝鍚﹀垯缁х画 /* close xlogreadfd after circulation */ - CloseXlogFile(); + CloseXlogFile(); // 鍏抽棴褰撳墠浣跨敤鐨刋LOG鏂囦欢 - if (found) { + if (found) { // 濡傛灉鎵惧埌浜嗛渶瑕佹彃鍏ュ埌鍝堝笇琛ㄧ殑barrier锛屽皢鍏舵彃鍏 SetBarrieID(barrierId, barrierLSN); } - startLSN = XLogRecPtrIsInvalid(lastReadLSN) ? preStartLSN : lastReadLSN; + startLSN = XLogRecPtrIsInvalid(lastReadLSN) ? preStartLSN : lastReadLSN; // 鏇存柊璧峰LSN - if (XLogRecPtrIsInvalid(xlogreader->ReadRecPtr) && errormsg) { + if (XLogRecPtrIsInvalid(xlogreader->ReadRecPtr) && errormsg) { // 濡傛灉鍦ㄨВ鏋愯繃绋嬩腑鍑虹幇閿欒锛岃褰曢敊璇俊鎭 ereport(LOG, (errmsg("[BarrierPreParse] preparse thread get an error info %s", errormsg))); } - const long sleepTime = 1000; - rc = WaitLatch(&t_thrd.proc->procLatch, WL_LATCH_SET | WL_TIMEOUT | WL_POSTMASTER_DEATH, sleepTime); + const long sleepTime = 1000; // 瀹氫箟浼戠湢鏃堕棿涓1000姣 + rc = WaitLatch(&t_thrd.proc->procLatch, WL_LATCH_SET | WL_TIMEOUT | WL_POSTMASTER_DEATH, sleepTime); // 绛夊緟淇″彿閲忔垨瓒呮椂 if (((unsigned int)rc) & WL_POSTMASTER_DEATH) { - XLogReaderFree(xlogreader); - ereport(LOG, (errmsg("[BarrierPreParse] preparse thread shut down with code 1"))); - gs_thread_exit(1); + XLogReaderFree(xlogreader); // 閲婃斁XLogReader璧勬簮 + ereport(LOG, (errmsg("[BarrierPreParse] preparse thread shut down with code 1"))); // 璁板綍绾跨▼浠ヤ唬鐮1鍏抽棴鐨勬棩蹇 + gs_thread_exit(1);// 浠ヤ唬鐮1閫鍑虹嚎绋 } } } - +// 鐢ㄤ簬鍞ら啋 BarrierPreParse 鍚庡彴杩涚▼ void WakeUpBarrierPreParseBackend() { - if (g_instance.pid_cxt.BarrierPreParsePID != 0) { - if (g_instance.proc_base->BarrierPreParseLatch != NULL) { - SetLatch(g_instance.proc_base->BarrierPreParseLatch); + if (g_instance.pid_cxt.BarrierPreParsePID != 0) { // 濡傛灉瀛樺湪BarrierPreParse杩涚▼ + if (g_instance.proc_base->BarrierPreParseLatch != NULL) { // 濡傛灉瀛樺湪BarrierPreParse杩涚▼鐨凩atch + SetLatch(g_instance.proc_base->BarrierPreParseLatch); // 瑙﹀彂Latch锛屽敜閱払arrierPreParse杩涚▼ } } } diff --git a/src/gausskernel/process/postmaster/bgworker.cpp b/src/gausskernel/process/postmaster/bgworker.cpp index f30e94618..2a29edb1d 100644 --- a/src/gausskernel/process/postmaster/bgworker.cpp +++ b/src/gausskernel/process/postmaster/bgworker.cpp @@ -25,119 +25,163 @@ #include "utils/snapmgr.h" #include "commands/dbcommands.h" #include "pgstat.h" - +// 澶栭儴鍑芥暟澹版槑锛 +// 鍑芥暟澹版槑锛歋treamSaveTxnContext锛岀敤浜庝繚瀛樻祦澶嶅埗浜嬪姟涓婁笅鏂 extern void StreamSaveTxnContext(StreamTxnContext* stc); +// 鍑芥暟澹版槑锛歋treamRestoreTxnContext锛岀敤浜庢仮澶嶆祦澶嶅埗浜嬪姟涓婁笅鏂 extern void StreamRestoreTxnContext(StreamTxnContext* stc); +// 鍑芥暟澹版槑锛欳opySnapshotByCurrentMcxt锛岄氳繃褰撳墠鍐呭瓨涓婁笅鏂囧鍒跺揩鐓 extern Snapshot CopySnapshotByCurrentMcxt(Snapshot snapshot); +// 鍑芥暟澹版槑锛歋etGlobalSnapshotData锛岃缃叏灞蹇収鏁版嵁 extern void SetGlobalSnapshotData( TransactionId xmin, TransactionId xmax, uint64 csn, GTM_Timeline timeline, bool ssNeedSyncWaitAll); +// 鍏ㄥ眬鍙橀噺锛氭渶澶у悗鍙板伐浣滆繘绋嬫暟锛屽垵濮嬪间负 64 int g_max_worker_processes = 64; /* * Return true if the thread is bgworker. */ +// 鍒ゆ柇褰撳墠杩涚▼鏄惁涓哄悗鍙板伐浣滆繘绋 +// 杩斿洖鍊硷細鑻ヤ负鍚庡彴宸ヤ綔杩涚▼锛岃繑鍥 true锛涘惁鍒欒繑鍥 false bool IsBgWorkerProcess(void) { - return t_thrd.role == BGWORKER; + return t_thrd.role == BGWORKER; // 杩斿洖褰撳墠绾跨▼鏄惁涓 BGWORKER锛堝悗鍙板伐浣滆繘绋嬶級 } +// 鍐呰仈鍑芥暟瀹氫箟锛欱gworkerPutBackToFreeList +// 鍔熻兘锛氬皢鍚庡彴宸ヤ綔杩涚▼鏀惧洖绌洪棽鍒楄〃 +// 鍙傛暟锛歜gworker - 鍚庡彴宸ヤ綔杩涚▼鎸囬拡 static inline void BgworkerPutBackToFreeList(BackgroundWorker* bgworker) { - BGW_HDR* bgworker_base = (BGW_HDR *)g_instance.bgw_base; + BGW_HDR* bgworker_base = (BGW_HDR *)g_instance.bgw_base;// 鑾峰彇鍚庡彴宸ヤ綔杩涚▼澶存寚閽 + // 浣跨敤 memset_s 娓呯┖ bgworker 缁撴瀯浣撶殑鍐呭锛岀‘淇濋殣绉佷俊鎭娓呴櫎 errno_t rc = memset_s(bgworker, sizeof(BackgroundWorker), 0, sizeof(BackgroundWorker)); - securec_check(rc, "", ""); + securec_check(rc, "", ""); // 妫鏌ユ纭 + // 灏 bgworker 鏀惧洖绌洪棽鍚庡彴宸ヤ綔杩涚▼閾捐〃 bgworker->links.next = (SHM_QUEUE *)bgworker_base->free_bgws; bgworker_base->free_bgws = bgworker; } +// 鍐呰仈鍑芥暟瀹氫箟锛欸etFreeBgworker +// 鍔熻兘锛氳幏鍙栫┖闂插悗鍙板伐浣滆繘绋 +// 杩斿洖鍊硷細鑾峰彇鐨勭┖闂插悗鍙板伐浣滆繘绋嬫寚閽堬紝鑻ユ病鏈夊彲鐢ㄧ殑杩斿洖 NULL static inline BackgroundWorker* GetFreeBgworker() { + // 鑾峰彇鍚庡彴宸ヤ綔杩涚▼澶存寚閽 BGW_HDR* bgworker_base = (BGW_HDR *)g_instance.bgw_base; + // 鑻ョ┖闂插悗鍙板伐浣滆繘绋嬮摼琛ㄤ负绌猴紝鍒欒繑鍥 NULL if (!bgworker_base->free_bgws) { return NULL; } + // 浠庣┖闂插悗鍙板伐浣滆繘绋嬮摼琛ㄤ腑鑾峰彇涓涓悗鍙板伐浣滆繘绋 BackgroundWorker* bgworker = bgworker_base->free_bgws; bgworker_base->free_bgws = (BackgroundWorker *)bgworker->links.next; return bgworker; } +// 鍒濆鍖栧悗鍙板伐浣滆繘绋嬪叏灞鏁版嵁 void InitBgworkerGlobal(void) { - BGW_HDR* bgworker_base = NULL; - BackgroundWorker* bgws = NULL; - bool needPalloc = false; - + BGW_HDR* bgworker_base = NULL; // 鍚庡彴宸ヤ綔杩涚▼澶存寚閽 + BackgroundWorker* bgws = NULL; // 鍚庡彴宸ヤ綔杩涚▼鎸囬拡 + bool needPalloc = false; // 鏄惁闇瑕佽繘琛 palloc 鍐呭瓨鍒嗛厤 + // 鍒囨崲鍐呭瓨涓婁笅鏂囧埌 MEMORY_CONTEXT_CBB 缁勪腑 MemoryContext oldContext = MemoryContextSwitchTo(INSTANCE_GET_MEM_CXT_GROUP(MEMORY_CONTEXT_CBB)); + // 鑻 g_instance.bgw_base 涓虹┖锛岃〃绀哄皻鏈垱寤哄悗鍙板伐浣滆繘绋嬪叡浜粨鏋 if (g_instance.bgw_base == NULL) { /* Create the g_instance.proc_base shared structure */ + // 鍒涘缓 g_instance.bgw_base 鍏变韩缁撴瀯锛屼负鍏跺垎閰嶅唴瀛橈紝纭繚鍦板潃瀵归綈 bgworker_base = (BGW_HDR *)CACHELINEALIGN(palloc(sizeof(BGW_HDR) + PG_CACHE_LINE_SIZE)); + // 灏嗗垎閰嶇殑鍐呭瓨璁剧疆涓哄悗鍙板伐浣滆繘绋嬪叡浜粨鏋 g_instance.bgw_base = (void *)bgworker_base; - needPalloc = true; + needPalloc = true;// 鏍囪闇瑕佽繘琛屽唴瀛樺垎閰 } else { + // 灏 g_instance.bgw_base 杞崲涓 BGW_HDR 鎸囬拡锛岃〃绀哄悗鍙板伐浣滆繘绋嬪叡浜ご閮 bgworker_base = (BGW_HDR *)g_instance.bgw_base; + // 鏂█纭繚 bgworker_base 鐨 bgws 鎸囬拡涓嶄负绌猴紝鍗冲悗鍙板伐浣滆繘绋嬫暟缁勫凡瀛樺湪 Assert(bgworker_base->bgws != NULL); } + // 鍒濆鍖 bgworker_base 鐨 bgw_id_seq 璁℃暟涓 1锛岀敤浜庤窡韪悗鍙板伐浣滆繘绋嬬殑鍞竴鏍囪瘑绗 pg_atomic_init_u64(&bgworker_base->bgw_id_seq, 1); - + // 濡傛灉闇瑕佽繘琛屽唴瀛樺垎閰 if (needPalloc) { + // 鍒嗛厤瓒冲澶у皬鐨勫唴瀛樼敤浜庡瓨鍌ㄥ悗鍙板伐浣滆繘绋嬫暟缁勶紝纭繚鍦板潃瀵归綈 bgws = (BackgroundWorker*)CACHELINEALIGN( palloc0(g_max_worker_processes * sizeof(BackgroundWorker) + PG_CACHE_LINE_SIZE)); - bgworker_base->bgws = bgws; - } else { - bgws = bgworker_base->bgws; + bgworker_base->bgws = bgws; // 灏嗗垎閰嶇殑鍐呭瓨璁剧疆涓哄悗鍙板伐浣滆繘绋嬫暟缁 + } else { // 濡傛灉涓嶉渶瑕佽繘琛屽唴瀛樺垎閰 + bgws = bgworker_base->bgws; // 鐩存帴鑾峰彇宸插瓨鍦ㄧ殑鍚庡彴宸ヤ綔杩涚▼鏁扮粍鎸囬拡 } - + // 灏嗘墍鏈夊悗鍙板伐浣滆繘绋嬫斁鍥炵┖闂插垪琛 for (int i = 0; i < g_max_worker_processes; i++) { BgworkerPutBackToFreeList(&bgws[i]); } - + // 鍒濆鍖栧悗鍙板伐浣滆繘绋嬫暟鎹攣 pthread_mutex_init(&g_instance.bgw_base_lock, NULL); + // 鍒囨崲鍥炲師鏉ョ殑鍐呭瓨涓婁笅鏂 MemoryContextSwitchTo(oldContext); } +// 璁剧疆鍚庡彴宸ヤ綔杩涚▼鐨勪簨鍔$幆澧 void SetUpBgWorkerTxnEnvironment() { /* resotre transaction context. */ + // 鑾峰彇鍚庡彴宸ヤ綔杩涚▼涓婁笅鏂 BgWorkerContext *bwc = (BgWorkerContext *)t_thrd.bgworker_cxt.bgwcontext; - + // 鎭㈠浜嬪姟涓婁笅鏂 StreamRestoreTxnContext(&bwc->transactionCxt); /* transaction id. */ + // SetNextTransactionId 鍑芥暟鐨勭浜屼釜鍙傛暟鐢ㄤ簬鎺у埗鏄惁鑷姩澧炲姞浜嬪姟ID銆 + // 褰撹涓 false 鏃讹紝鍑芥暟涓嶄細鑷姩澧炲姞浜嬪姟ID锛岃屾槸浣跨敤浼犻掔殑 txnId 鍙傛暟浣滀负涓嬩竴涓簨鍔D + // 纭繚鍚庣画鐨勪簨鍔′娇鐢ㄦ寚瀹氱殑浜嬪姟ID锛屼繚鎸佷竴鑷存 SetNextTransactionId(bwc->transactionCxt.txnId, false); - StreamTxnContextSetTransactionState(&bwc->transactionCxt); + StreamTxnContextSetTransactionState(&bwc->transactionCxt); // 璁剧疆浜嬪姟鐘舵佷负褰撳墠鐘舵 /* snapshot. */ - Snapshot snapshot = CopySnapshotByCurrentMcxt(bwc->transactionCxt.snapshot); - SetGlobalSnapshotData(snapshot->xmin, snapshot->xmax, snapshot->snapshotcsn, snapshot->timeline, false); - StreamTxnContextSetSnapShot(snapshot); - StreamTxnContextSetMyPgXactXmin(snapshot->xmin); + Snapshot snapshot = CopySnapshotByCurrentMcxt(bwc->transactionCxt.snapshot); // 澶嶅埗褰撳墠鍐呭瓨涓婁笅鏂囦腑鐨勫揩鐓 + // SetGlobalSnapshotData 鍑芥暟鐨勬渶鍚庝竴涓弬鏁扮敤浜庢帶鍒舵槸鍚﹂渶瑕佺瓑寰呮墍鏈変簨鍔″悓姝ュ畬鎴愩 + // 褰撹涓 false 鏃讹紝鍑芥暟灏嗕笉浼氱瓑寰呮墍鏈変簨鍔″悓姝ュ畬鎴愶紝鑰屾槸绔嬪嵆杩斿洖锛屼互鎻愰珮鍝嶅簲閫熷害鍜屾晥鐜 + SetGlobalSnapshotData(snapshot->xmin, snapshot->xmax, snapshot->snapshotcsn, snapshot->timeline, false); // 璁剧疆鍏ㄥ眬蹇収鏁版嵁 + StreamTxnContextSetSnapShot(snapshot); // 灏嗗揩鐓т俊鎭缃埌娴佸鍒朵簨鍔′笂涓嬫枃涓 + StreamTxnContextSetMyPgXactXmin(snapshot->xmin); // 璁剧疆 PGXACT 鐨 xmin /* command id. */ - SaveReceivedCommandId(bwc->transactionCxt.currentCommandId); + SaveReceivedCommandId(bwc->transactionCxt.currentCommandId); // 淇濆瓨鎺ユ敹鍒扮殑鍛戒护ID /* timestamp. */ - SetCurrentGTMDeltaTimestamp(); + SetCurrentGTMDeltaTimestamp(); // 璁剧疆褰撳墠鐨 GTM Delta 鏃堕棿鎴 } +// 淇濆瓨鍚庡彴宸ヤ綔杩涚▼鐨勯敊璇俊鎭 static void BgWorkerSaveError() { + // 鑾峰彇褰撳墠鍚庡彴宸ヤ綔杩涚▼鐨勬寚閽 BackgroundWorker *bgw = (BackgroundWorker *)t_thrd.bgworker_cxt.bgworker; + // 鑾峰彇褰撳墠閿欒淇℃伅鐨勬寚閽 ErrorData *edata = &t_thrd.log_cxt.errordata[t_thrd.log_cxt.errordata_stack_depth]; errno_t rc = EOK; int len; + // 璁剧疆閿欒淇℃伅鍜岃鎯呯殑榛樿瀛楃涓 char *failmsg = "Worker failed during parallel build index."; char *nulldetail = "N/A"; + // 灏嗛敊璇骇鍒拰 SQL 閿欒鐮佷繚瀛樺埌 bgw_edata 缁撴瀯 bgw->bgw_edata.elevel = edata->elevel; bgw->bgw_edata.sqlerrcode = edata->sqlerrcode; + // 鑾峰彇閿欒娑堟伅锛屽鏋滀负绌哄垯浣跨敤榛樿娑堟伅 char *message = (edata->message != NULL ? edata->message : failmsg); + // 闄愬埗娑堟伅闀垮害锛屽苟澶嶅埗鍒 bgw_edata 鐨 message 瀛楁 len = Min(strlen(message), BGWORKER_MAX_ERROR_LEN - 1); rc = strncpy_s(bgw->bgw_edata.message, BGWORKER_MAX_ERROR_LEN, message, len); + // 纭繚瀛楃涓茬殑澶嶅埗鎿嶄綔涓嶄細閫犳垚缂撳啿鍖烘孩鍑猴紝澧炲姞浠g爜鐨勫仴澹 securec_check_c(rc, "", ""); - bgw->bgw_edata.message[len] = '\0'; + bgw->bgw_edata.message[len] = '\0'; // 纭繚瀛楃涓蹭互 C 瀛楃涓茬殑褰㈠紡缁撴潫 + // 鑾峰彇閿欒璇︽儏锛屽鏋滀负绌哄垯浣跨敤榛樿璇︽儏 char *detail = (edata->detail != NULL ? edata->detail : nulldetail); + // 闄愬埗璇︽儏闀垮害锛屽苟澶嶅埗鍒 bgw_edata 鐨 detail 瀛楁 len = Min(strlen(detail), BGWORKER_MAX_ERROR_LEN - 1); rc = strncpy_s(bgw->bgw_edata.detail, BGWORKER_MAX_ERROR_LEN, detail, len); securec_check_c(rc, "", ""); @@ -147,43 +191,55 @@ static void BgWorkerSaveError() /* * Called when the Bgworker thread is ending. */ +/* + * BgworkerQuitAndClean + * 鍔熻兘锛氬綋鍚庡彴宸ヤ綔杩涚▼绾跨▼鍗冲皢缁撴潫鏃惰皟鐢 + * 鍙傛暟: + * code: 閫鍑轰唬鐮 + * arg: 鐢ㄦ埛瀹氫箟鐨勫弬鏁 + */ static void BgworkerQuitAndClean(int code, Datum arg) { + // 鑾峰彇褰撳墠鍚庡彴宸ヤ綔杩涚▼鐨勬寚閽 BackgroundWorker *bgw = (BackgroundWorker *)t_thrd.bgworker_cxt.bgworker; + // 鏍规嵁鍚庡彴宸ヤ綔杩涚▼鐨勭姸鎬佽缃浉搴旂姸鎬 if (bgw->bgw_status == BGW_STOPPED) { - bgw->bgw_status = BGW_TERMINATED; + bgw->bgw_status = BGW_TERMINATED; // 灏嗙姸鎬佹洿鏂颁负 BGW_TERMINATED锛岃〃绀鸿繘绋嬪凡姝e父缁堟 } else { - bgw->bgw_status = BGW_FAILED; + bgw->bgw_status = BGW_FAILED; // 灏嗙姸鎬佹洿鏂颁负 BGW_FAILED锛岃〃绀鸿繘绋嬪洜鏌愮鍘熷洜澶辫触 } } +// 鍚庡彴宸ヤ綔杩涚▼鐨勫垵濮嬪寲鍑芥暟 static void BackgroundWorkerInit(void) { /* we are a postmaster subprocess now */ - IsUnderPostmaster = true; - t_thrd.role = BGWORKER; + IsUnderPostmaster = true; // 灏 IsUnderPostmaster 鏍囧織璁剧疆涓 true锛岃〃绀哄綋鍓嶈繘绋嬫槸鍦ㄥ悗鍙拌繍琛 + t_thrd.role = BGWORKER; // 璁剧疆褰撳墠绾跨▼鐨勮鑹蹭负 BGWORKER锛岃〃绀哄綋鍓嶇嚎绋嬫槸涓涓悗鍙板伐浣滆繘绋 /* reset t_thrd.proc_cxt.MyProcPid */ - t_thrd.proc_cxt.MyProcPid = gs_thread_self(); + t_thrd.proc_cxt.MyProcPid = gs_thread_self(); // 閲嶇疆褰撳墠绾跨▼鐨勮繘绋婭D锛屽皢鍏惰缃负褰撳墠绾跨▼鐨勫疄闄呯嚎绋婭D - t_thrd.proc_cxt.MyProgName = "BgWorker"; + t_thrd.proc_cxt.MyProgName = "BgWorker"; // 璁剧疆褰撳墠绾跨▼鐨勮繘绋嬪悕绉颁负 "BgWorker" /* record Start Time for logging */ - t_thrd.proc_cxt.MyStartTime = time(NULL); + t_thrd.proc_cxt.MyStartTime = time(NULL); // 璁板綍褰撳墠绾跨▼鐨勫紑濮嬫椂闂达紝鐢ㄤ簬鏃ュ織璁板綍 - init_ps_display("Bgworker process", "", "", ""); + init_ps_display("Bgworker process", "", "", ""); // 鍒濆鍖栨樉绀鸿繘绋嬬姸鎬 - SetProcessingMode(InitProcessing); + SetProcessingMode(InitProcessing); // 璁剧疆褰撳墠鐨勫鐞嗘ā寮忎负鍒濆鍖栭樁娈 - on_proc_exit(BgworkerQuitAndClean, 0); + on_proc_exit(BgworkerQuitAndClean, 0); // 鍦ㄨ繘绋嬮鍑烘椂璋冪敤 BgworkerQuitAndClean 鍑芥暟锛屾墽琛屾竻鐞嗘搷浣 /* * SIGINT is used to signal canceling the current action */ + // 涓 SIGINT銆丼IGTERM 鍜 SIGALRM 淇″彿璁剧疆鐩稿簲鐨勫鐞嗗嚱鏁 (void)gspqsignal(SIGINT, StatementCancelHandler); (void)gspqsignal(SIGTERM, die); (void)gspqsignal(SIGALRM, handle_sig_alarm); + // 瀵逛簬 SIGQUIT銆丼IGPIPE銆丼IGUSR1 銆丼IGUSR2 鍜 SIGHUP 淇″彿锛岃缃拷鐣ュ鐞 (void)gspqsignal(SIGQUIT, SIG_IGN); (void)gspqsignal(SIGPIPE, SIG_IGN); (void)gspqsignal(SIGUSR1, SIG_IGN); @@ -191,6 +247,7 @@ static void BackgroundWorkerInit(void) (void)gspqsignal(SIGHUP, SIG_IGN); /* Reset some signals that are accepted by postmaster but not here */ + // 閲嶇疆涓浜涘湪 postmaster 涓帴鍙椾絾鍦ㄨ繖閲屼笉鎺ュ彈鐨勪俊鍙风殑澶勭悊鏂瑰紡 (void)gspqsignal(SIGCHLD, SIG_DFL); (void)gspqsignal(SIGTTIN, SIG_DFL); (void)gspqsignal(SIGTTOU, SIG_DFL); @@ -198,11 +255,11 @@ static void BackgroundWorkerInit(void) (void)gspqsignal(SIGWINCH, SIG_DFL); /* Early initialization */ - BaseInit(); + BaseInit(); // 鎵ц鏃╂湡鍒濆鍖栨搷浣 #ifndef EXEC_BACKEND - InitProcess(); -#endif + InitProcess(); // 鍒濆鍖栬繘绋嬫暟鎹粨鏋勫拰鐘舵 +#endif } /* @@ -211,6 +268,7 @@ static void BackgroundWorkerInit(void) * This is the main entry point for background worker, to be called from * postmaster. */ +// 鍚庡彴宸ヤ綔杩涚▼鐨勪富瑕佸叆鍙e嚱鏁帮紝浠 postmaster 琚皟鐢 void BackgroundWorkerMain(void) { BgWorkerContext *bwc = (BgWorkerContext *)t_thrd.bgworker_cxt.bgwcontext; @@ -222,57 +280,67 @@ void BackgroundWorkerMain(void) int *oldTryCounter = NULL; int curTryCounter; + // 鑾峰彇鍚庡彴宸ヤ綔杩涚▼涓婁笅鏂囬攣锛岀敤浜庣‘淇濆畨鍏ㄨ闂 bgworker 鏁版嵁缁撴瀯 pthread_mutex_lock(&g_instance.bgw_base_lock); + // 濡傛灉 bgwId 涓 bgw->bgw_id 涓嶅尮閰嶏紝鎴栬呭凡缁忚绂佺敤锛屽垯閫鍑 if (bgwId != bgw->bgw_id || pg_atomic_fetch_add_u32(&bgw->disable_count, 1) > 0) { /* The leader disallowed this worker to do index build due to startup time longer than 5s. */ ereport(WARNING, (errmsg("BgWorker thread %lu was disabled for long startup time.", - t_thrd.proc_cxt.MyProcPid))); + t_thrd.proc_cxt.MyProcPid))); // 鎶ュ憡璀﹀憡淇℃伅 /* Note that we are in the state BGW_NOT_YET_STARTED. */ - pthread_mutex_unlock(&g_instance.bgw_base_lock); + // 瑙i攣骞惰烦杞埌 out 鏍囩锛岄鍑哄嚱鏁 + pthread_mutex_unlock(&g_instance.bgw_base_lock); goto out; } - pthread_mutex_unlock(&g_instance.bgw_base_lock); + pthread_mutex_unlock(&g_instance.bgw_base_lock); // 瑙i攣 - BackgroundWorkerInit(); + BackgroundWorkerInit(); // 鍒濆鍖栧悗鍙板伐浣滆繘绋 + // 鍒涘缓涓涓唴瀛樹笂涓嬫枃鏉ョ鐞嗗悗鍙板伐浣滆繘绋嬬殑鍐呭瓨 workerContext = AllocSetContextCreate(t_thrd.top_mem_cxt, "BgWorker", ALLOCSET_DEFAULT_MINSIZE, ALLOCSET_DEFAULT_INITSIZE, ALLOCSET_DEFAULT_MAXSIZE); - (void)MemoryContextSwitchTo(workerContext); + (void)MemoryContextSwitchTo(workerContext); // 鍒囨崲鍒板伐浣滃唴瀛樹笂涓嬫枃 /* Unblock signals (they were blocked when the postmaster forked us) */ + // 瑙i櫎瀵逛俊鍙风殑闃诲锛堝湪 postmaster fork 鏃朵細闃诲淇″彿锛 gs_signal_setmask(&t_thrd.libpq_cxt.UnBlockSig, NULL); (void)gs_signal_unblock_sigusr2(); /* If an exception is encountered, processing resumes here. */ + // 濡傛灉閬囧埌寮傚父锛屽鐞嗗皢浼氳烦杞埌姝ゅ if (sigsetjmp(local_sigjmp_buf, 1) != 0) { - gstrace_tryblock_exit(true, oldTryCounter); + gstrace_tryblock_exit(true, oldTryCounter); // 閫鍑哄紓甯稿鐞嗗潡锛屾仮澶嶄箣鍓嶇殑 try counter /* Since not using PG_TRY, must reset error stack by hand */ + // 鎵嬪姩閲嶇疆閿欒鍫嗘爤鍜岃皟鐢ㄥ爢鏍 t_thrd.log_cxt.error_context_stack = NULL; - t_thrd.log_cxt.call_stack = NULL; /* Prevent interrupts while cleaning up */ - HOLD_INTERRUPTS(); + HOLD_INTERRUPTS(); // 鍦ㄦ竻鐞嗘湡闂撮樆姝腑鏂 /* save bgworker error data for leader reporting */ - BgWorkerSaveError(); + BgWorkerSaveError(); // 淇濆瓨 bgworker 閿欒淇℃伅 /* Report the error to the parallel leader and the server log */ - EmitErrorReport(); + EmitErrorReport(); // 鎶ュ憡閿欒缁欎富杩涚▼鍜屾棩蹇 /* release resource held by lsc */ - AtEOXact_SysDBCache(false); + AtEOXact_SysDBCache(false); // 閲婃斁绯荤粺缂撳瓨涓殑璧勬簮 /* * These operations are really just a minimal subset of * AbortTransaction(). We don't have very many resources to worry * about in bgwriter, but we do have LWLocks, buffers, and temp files. */ - LWLockReleaseAll(); - AbortBufferIO(); - UnlockBuffers(); + LWLockReleaseAll(); // 閲婃斁鎵鏈夌殑杞婚噺绾ч攣 + AbortBufferIO(); // 涓鎵鏈夌殑缂撳啿鍖鸿緭鍏/杈撳嚭鎿嶄綔 + UnlockBuffers(); // 瑙i攣鎵鏈夌紦鍐插尯 /* buffer pins are released here */ + // 濡傛灉褰撳墠璧勬簮鎷ユ湁鑰呭瓨鍦紝杩涜璧勬簮閲婃斁 if (t_thrd.utils_cxt.CurrentResourceOwner != NULL) { + // 閲婃斁璧勬簮鎷ユ湁鑰呯殑璧勬簮锛屽苟鎸囧畾 RESOURCE_RELEASE_BEFORE_LOCKS 妯″紡 + // 绗笁涓弬鏁颁负 false锛岃〃绀轰笉閲婃斁杩炴帴绾у埆鐨勮祫婧 + // 绗洓涓弬鏁颁负 true锛岃〃绀哄湪閲婃斁璧勬簮鍚庝篃鎵ц閿佺殑閲婃斁 ResourceOwnerRelease(t_thrd.utils_cxt.CurrentResourceOwner, RESOURCE_RELEASE_BEFORE_LOCKS, false, true); } @@ -280,6 +348,7 @@ void BackgroundWorkerMain(void) * Now return to normal top-level context and clear ErrorContext for * next time. */ + // 鍒囨崲鍥炲師濮嬬殑鍐呭瓨涓婁笅鏂囷紝鍒锋柊閿欒鐘舵佸苟娓呯悊鍐呭瓨 (void)MemoryContextSwitchTo(workerContext); FlushErrorState(); @@ -287,35 +356,44 @@ void BackgroundWorkerMain(void) MemoryContextResetAndDeleteChildren(workerContext); /* and go away */ - proc_exit(1); + proc_exit(1); // 閫鍑鸿繘绋 } + // 鑾峰彇鏃х殑 try 璁℃暟鍣ㄧ殑鍊硷紝浠ヤ究鍦ㄥ紓甯告仮澶嶆椂杩涜鎭㈠ oldTryCounter = gstrace_tryblock_entry(&curTryCounter); /* We can now handle ereport(ERROR) */ + // 璁剧疆寮傚父澶勭悊鏈哄埗鐨勮烦杞偣锛屼互渚垮湪鍙戠敓閿欒鏃惰繘琛屽鐞 t_thrd.log_cxt.PG_exception_stack = &local_sigjmp_buf; + // 璁剧疆浼氳瘽鐨勫紑濮嬫椂闂存埑 u_sess->proc_cxt.MyProcPort->SessionStartTime = GetCurrentTimestamp(); - bgw->bgw_status = BGW_STARTED; + bgw->bgw_status = BGW_STARTED; // 璁剧疆 bgworker 鐘舵 /* General initialization. */ /* user_name and database_name in u_sess->proc_cxt.MyProcPort is under t_thrd.top_mem_cxt */ + // 鍒囨崲鍒板瓨鍌ㄤ笂涓嬫枃锛屽 MyProcPort 鐨勬暟鎹簱鍚嶅拰鐢ㄦ埛鍚嶈繘琛岄噸缃 oldcontext = MemoryContextSwitchTo(SESS_GET_MEM_CXT_GROUP(MEMORY_CONTEXT_STORAGE)); + // 濡傛灉褰撳墠 MyProcPort 鐨勬暟鎹簱鍚嶄笉涓 NULL锛屽垯閲婃斁鍏跺唴瀛 if (u_sess->proc_cxt.MyProcPort->database_name != NULL) { pfree_ext(u_sess->proc_cxt.MyProcPort->database_name); } + // 濡傛灉褰撳墠 MyProcPort 鐨勭敤鎴峰悕涓嶄负 NULL锛屽垯閲婃斁鍏跺唴瀛 if (u_sess->proc_cxt.MyProcPort->user_name != NULL) { pfree_ext(u_sess->proc_cxt.MyProcPort->user_name); } + // 璁剧疆 MyProcPort 鐨勬暟鎹簱鍚嶅拰鐢ㄦ埛鍚 u_sess->proc_cxt.MyProcPort->database_name = pstrdup(bwc->databaseName); u_sess->proc_cxt.MyProcPort->user_name = pstrdup(bwc->userName); + // 鍒囨崲鍥炰箣鍓嶇殑涓婁笅鏂 (void)MemoryContextSwitchTo(oldcontext); - + // 璁剧疆鏁版嵁搴撳拰鐢ㄦ埛锛屽垵濮嬪寲鍚庡彴宸ヤ綔 t_thrd.proc_cxt.PostInit->SetDatabaseAndUser(bwc->databaseName, InvalidOid, bwc->userName); t_thrd.proc_cxt.PostInit->InitBgWorker(); t_thrd.proc_cxt.PostInit->GetDatabaseName(u_sess->proc_cxt.MyProcPort->database_name); + // 璁板綍鏃ュ織锛岃〃绀 bgworker 鐨勭嚎绋 ID ereport(LOG, (errmsg("bgworker threadId is %lu.", t_thrd.proc_cxt.MyProcPid))); - StartTransactionCommand(); - SetUpBgWorkerTxnEnvironment(); + StartTransactionCommand(); // 寮鍚簨鍔 + SetUpBgWorkerTxnEnvironment(); // 璁剧疆鍚庡彴宸ヤ綔鐨勪簨鍔$幆澧 /* * Join locking group. We must do this before anything that could try to @@ -326,21 +404,28 @@ void BackgroundWorkerMain(void) * deadlock. (If we can't join the lock group, the leader has gone away, * so just exit quietly.) */ - BecomeLockGroupMember(bwc->leader); + /* + 鍔犲叆閿佸畾缁勭殑鐩殑鏄伩鍏嶆閿佺殑鍙戠敓銆 + 鍦ㄥ苟琛屽鐞嗕腑锛屽鏋滀竴涓繘绋嬭幏鍙栦簡閲嶉噺绾ч攣锛岃屽彟涓涓繘绋嬪張璇曞浘鑾峰彇涓庝箣鍐茬獊鐨勯攣锛屽氨鍙兘寮曞彂姝婚攣銆 + 閫氳繃鍔犲叆閿佸畾缁勶紝鍙互纭繚鎵鏈夊苟琛岃繘绋嬮兘鍦ㄥ悓涓涓攣瀹氱粍鍐咃紝浠庤岄伩鍏嶆閿佺殑鍙戠敓銆 + 濡傛灉鏃犳硶鍔犲叆閿佸畾缁勶紝閭d箞鍙兘鏄洜涓哄苟琛岀粍鐨勯瀵艰呭凡缁忛鍑猴紝杩欐椂鍚庡彴宸ヤ綔杩涚▼浼氬畨闈欏湴閫鍑猴紝鑰屼笉鍋氬叾浠栨搷浣溿 + */ + BecomeLockGroupMember(bwc->leader); // 鍔犲叆閿佸畾缁勶紝閬垮厤姝婚攣 - u_sess->attr.attr_sql.enable_cluster_resize = bwc->enable_cluster_resize; + u_sess->attr.attr_sql.enable_cluster_resize = bwc->enable_cluster_resize; // 璁剧疆鏄惁鍚敤闆嗙兢璋冩暣澶у皬 /* * Now invoke the user-defined worker code */ - bwc->main_entry(bwc); + bwc->main_entry(bwc); // 璋冪敤鐢ㄦ埛瀹氫箟鐨勫悗鍙板伐浣滃嚱鏁 + // 缁撴潫骞堕噸缃悗鍙板伐浣滅殑浜嬪姟 EndParallelWorkerTransaction(); ResetTransactionInfo(); /* ... and if it returns, we're done */ - bgw->bgw_status = BGW_STOPPED; + bgw->bgw_status = BGW_STOPPED; // 璁剧疆 bgworker 鐘舵佷负宸插仠姝 out: - proc_exit(0); + proc_exit(0); // 閫鍑鸿繘绋 } /* @@ -349,27 +434,46 @@ out: * This can only be called in the _PG_init function of a module library * that's loaded by shared_preload_libraries; otherwise it has no effect. */ +/* + * 鍦ㄥ鐞 shared_preload_libraries 鏈熼棿娉ㄥ唽涓涓柊鐨勫悗鍙板伐浣滆繘绋嬨 + * + * 璇ュ嚱鏁扮敤浜庡湪 _PG_init 鍑芥暟涓璋冪敤锛屼粎鍦ㄨ shared_preload_libraries 鍔犺浇鐨 + * 妯″潡搴撲腑鏈夋晥銆傚畠鐨勪綔鐢ㄦ槸涓哄悗鍙板伐浣滆繘绋嬫敞鍐屾彁渚涗簡涓涓帴鍙o紝鐢ㄤ簬鍑嗗骞跺惎鍔ㄦ柊鐨 + * 鍚庡彴宸ヤ綔杩涚▼銆 + * + * 鍙傛暟: + * bwc - 鍚庡彴宸ヤ綔涓婁笅鏂囷紝鍖呭惈浜嗗悗鍙板伐浣滆繘绋嬬殑鐩稿叧淇℃伅 + * + * 杩斿洖鍊: + * 濡傛灉鎴愬姛娉ㄥ唽浜嗘柊鐨勫悗鍙板伐浣滆繘绋嬶紝杩斿洖 true锛涘惁鍒欙紝杩斿洖 false銆 + */ bool RegisterBackgroundWorker(BgWorkerContext *bwc) { - BGW_HDR* bgworker_base = (BGW_HDR *)g_instance.bgw_base; + BGW_HDR* bgworker_base = (BGW_HDR *)g_instance.bgw_base; // 鑾峰彇鎸囧悜鍚庡彴宸ヤ綔杩涚▼姹犵殑鎸囬拡 + // 澹版槑鍚庡彴宸ヤ綔杩涚▼缁撴瀯鍜屽悗鍙板伐浣滆繘绋嬪弬鏁扮粨鏋勭殑鎸囬拡 BackgroundWorker *bgw = NULL; BackgroundWorkerArgs *bwa = NULL; + // 鍔犻攣锛屼互渚垮湪鎿嶄綔鍚庡彴宸ヤ綔杩涚▼姹犳椂淇濇寔鍚屾 pthread_mutex_lock(&g_instance.bgw_base_lock); - bgw = GetFreeBgworker(); - if (bgw == NULL) { - pthread_mutex_unlock(&g_instance.bgw_base_lock); + bgw = GetFreeBgworker(); // 鑾峰彇涓涓┖闂茬殑鍚庡彴宸ヤ綔杩涚▼ + if (bgw == NULL) { // 濡傛灉娌℃湁绌洪棽鐨勫悗鍙板伐浣滆繘绋嬪彲鐢 + pthread_mutex_unlock(&g_instance.bgw_base_lock); // 瑙i攣鍚庡彴宸ヤ綔杩涚▼姹 + // 杈撳嚭璀﹀憡淇℃伅锛岃〃绀烘病鏈夌┖闂茬殑鍚庡彴宸ヤ綔杩涚▼鍙敤 ereport(WARNING, (errmsg("There are no more free background workers available"))); - return false; + return false; // 杩斿洖 false锛岃〃绀烘敞鍐屽け璐 } + // 涓鸿鍚庡彴宸ヤ綔杩涚▼鍒嗛厤鍞竴鐨 ID bgw->bgw_id = pg_atomic_fetch_add_u64(&bgworker_base->bgw_id_seq, 1); - pthread_mutex_unlock(&g_instance.bgw_base_lock); + pthread_mutex_unlock(&g_instance.bgw_base_lock); // 瑙i攣鍚庡彴宸ヤ綔杩涚▼姹 + // 璁剧疆鍚庡彴宸ヤ綔杩涚▼鐨勭姸鎬佷负灏氭湭鍚姩锛屼互鍙婄浉鍏崇殑鐘舵佹寔缁椂闂村拰绂佺敤璁℃暟 bgw->bgw_status = BGW_NOT_YET_STARTED; bgw->bgw_status_dur = 0; bgw->disable_count = 0; /* Construct bgworker thread args */ + // 鏋勯犲悗鍙板伐浣滅嚎绋嬪弬鏁 bwa = (BackgroundWorkerArgs*)MemoryContextAllocZero( INSTANCE_GET_MEM_CXT_GROUP(MEMORY_CONTEXT_STORAGE), sizeof(BackgroundWorkerArgs)); bwa->bgwcontext = bwc; @@ -377,153 +481,221 @@ bool RegisterBackgroundWorker(BgWorkerContext *bwc) bwa->bgworkerId = bgw->bgw_id; /* Fork a new worker thread */ + // 鍒涘缓涓涓柊鐨勫伐浣滅嚎绋 bgw->bgw_notify_pid = initialize_util_thread(BGWORKER, bwa); /* failed to fork a new thread */ + // 濡傛灉鍒涘缓绾跨▼澶辫触 if (bgw->bgw_notify_pid == 0) { - pfree_ext(bwa); - return false; + pfree_ext(bwa); // 閲婃斁鍒嗛厤鐨勫弬鏁板唴瀛 + return false; // 杩斿洖娉ㄥ唽澶辫触 } /* Copy the registration data into the registered workers list. */ - slist_push_head(&t_thrd.bgworker_cxt.bgwlist, &bgw->rw_lnode); - return true; + slist_push_head(&t_thrd.bgworker_cxt.bgwlist, &bgw->rw_lnode); // 灏嗘敞鍐屾暟鎹鍒跺埌宸叉敞鍐屽伐浣滅嚎绋嬪垪琛ㄤ腑 + return true; // 杩斿洖娉ㄥ唽鎴愬姛 } +// 鍔熻兘锛氭竻鐞嗗悗鍙板伐浣滆繘绋嬬殑鍏变韩涓婁笅鏂 static void BgworkerCleanupSharedContext() { - Assert(!IsBgWorkerProcess()); + Assert(!IsBgWorkerProcess()); // 纭繚涓嶆槸鍚庡彴宸ヤ綔杩涚▼璋冪敤璇ュ嚱鏁 /* clean up backgroud shared context */ - if (t_thrd.bgworker_cxt.bgwcontext) { + if (t_thrd.bgworker_cxt.bgwcontext) { // 濡傛灉瀛樺湪鍚庡彴宸ヤ綔涓婁笅鏂 BgWorkerContext *bwc = (BgWorkerContext*)t_thrd.bgworker_cxt.bgwcontext; - if (bwc->exit_entry) { - bwc->exit_entry(bwc); + if (bwc->exit_entry) { // 濡傛灉鏈夐鍑哄嚱鏁帮紝鍗崇▼搴忛鍑烘椂鎵ц鎿嶄綔 + bwc->exit_entry(bwc); // 璋冪敤 } - pfree_ext(bwc->bgshared); - pfree_ext(t_thrd.bgworker_cxt.bgwcontext); + pfree_ext(bwc->bgshared); // 閲婃斁鍒嗛厤鐨勫悗鍙板伐浣滃叡浜唴瀛 + pfree_ext(t_thrd.bgworker_cxt.bgwcontext); // 閲婃斁鍒嗛厤鐨勫悗鍙板伐浣滀笂涓嬫枃鍐呭瓨 } - slist_init(&t_thrd.bgworker_cxt.bgwlist); + slist_init(&t_thrd.bgworker_cxt.bgwlist); // 鍒濆鍖栧悗鍙板伐浣滃垪琛 } +/* + * 鍔熻兘锛 鍚屾閬嶅巻鍚庡彴宸ヤ綔杩涚▼鍒楄〃锛屾墽琛岀粓姝㈡垨绠$悊鎿嶄綔 + * + * 鍙傛暟锛 鏃 + * + * 杩斿洖鍊硷細 鏃 + */ void BgworkerListSyncQuit() { slist_mutable_iter iter; bool alldone = false; bool sigsent = false; - + // 濡傛灉鍚庡彴宸ヤ綔杩涚▼鍒楄〃涓虹┖锛岀洿鎺ヨ繑鍥 if (slist_is_empty(&t_thrd.bgworker_cxt.bgwlist)) { return; } loop: alldone = true; + // 閬嶅巻鍚庡彴宸ヤ綔杩涚▼鍒楄〃 slist_foreach_modify(iter, &t_thrd.bgworker_cxt.bgwlist) { + // 鑾峰彇褰撳墠閬嶅巻鍒扮殑鍚庡彴宸ヤ綔杩涚▼ BackgroundWorker *bgw = slist_container(BackgroundWorker, rw_lnode, iter.cur); + // 濡傛灉鍚庡彴宸ヤ綔杩涚▼鐘舵佷负 BGW_FAILED 鎴 BGW_TERMINATED if (bgw->bgw_status == BGW_FAILED || bgw->bgw_status == BGW_TERMINATED) { - slist_delete_current(&iter); + slist_delete_current(&iter); // 浠庡垪琛ㄤ腑鍒犻櫎鍚庡彴宸ヤ綔杩涚▼ + // 鑾峰彇鍏ㄥ眬鍚庡彴宸ヤ綔杩涚▼鍒楄〃浜掓枼閿侊紝闃叉澶氫釜绾跨▼鍚屾椂璁块棶鍒楄〃 pthread_mutex_lock(&g_instance.bgw_base_lock); + // 灏嗗綋鍓嶅悗鍙板伐浣滆繘绋嬫斁鍥炵┖闂插垪琛 BgworkerPutBackToFreeList(bgw); + // 閲婃斁鍏ㄥ眬鍚庡彴宸ヤ綔杩涚▼鍒楄〃浜掓枼閿侊紝鍏佽鍏朵粬绾跨▼璁块棶鍒楄〃 pthread_mutex_unlock(&g_instance.bgw_base_lock); - } else if (bgw->bgw_status == BGW_NOT_YET_STARTED) { + } else if (bgw->bgw_status == BGW_NOT_YET_STARTED) { // 濡傛灉鍚庡彴宸ヤ綔杩涚▼鐘舵佷负 BGW_NOT_YET_STARTED alldone = false; + // 澧炲姞鐘舵佹寔缁椂闂达紝濡傛灉瓒呰繃闄愬埗涓斿皻鏈鐢紝鍒欐爣璁颁负澶辫触 if (++bgw->bgw_status_dur > BGWORKER_STATUS_DURLIMIT && (pg_atomic_fetch_add_u32(&bgw->disable_count, 1) == 0)) { bgw->bgw_status = BGW_FAILED; } } else { + // 濡傛灉鍚庡彴宸ヤ綔杩涚▼鐘舵佷负鍏朵粬鍊 + // 濡傛灉涔嬪墠娌℃湁鍙戦佽繃淇″彿涓旀垚鍔熷湴鍙戦佷簡 SIGINT 淇″彿缁欐寚瀹氱殑杩涚▼ if (!sigsent && gs_signal_send(bgw->bgw_notify_pid, SIGINT) != 0) { ereport(WARNING, (errmsg("BgworkerListSyncQuit kill(pid %lu, stat %d) failed: %m", - bgw->bgw_notify_pid, bgw->bgw_status))); + bgw->bgw_notify_pid, bgw->bgw_status))); // 璀﹀憡娑堟伅璁板綍鍒版棩蹇 } - alldone = false; + alldone = false; // 琛ㄧず灏氭湭瀹屾垚鎵鏈夊悗鍙板伐浣滆繘绋嬬殑澶勭悊銆 } } + // 濡傛灉鏈畬鎴愰亶鍘嗭紝绛夊緟涓娈垫椂闂村苟缁х画 if (!alldone) { usleep(BGWORKER_LOOP_SLEEP_TIME); sigsent = true; goto loop; } + // 娓呯悊鍚庡彴宸ヤ綔杩涚▼鐨勫叡浜笂涓嬫枃 BgworkerCleanupSharedContext(); } +/* + * 娓呯悊鏈兘鎴愬姛鍚姩鐨勫悗鍙板伐浣滆繘绋 + * + * 璇ュ嚱鏁扮敤浜庨亶鍘嗗悗鍙板伐浣滆繘绋嬪垪琛紝濡傛灉鍙戠幇鏌愪釜鍚庡彴宸ヤ綔杩涚▼鐨勭姸鎬佷负 BGW_NOT_YET_STARTED锛 + * 鍗虫湭鑳芥垚鍔熷惎鍔紝灏卞皢鍏朵粠鍒楄〃涓垹闄わ紝骞跺皢鍏惰繑鍥炲埌绌洪棽鍒楄〃涓傝繖鏍峰仛鏄负浜嗙‘淇濇湭鑳芥垚鍔熷惎鍔ㄧ殑 + * 鍚庡彴宸ヤ綔杩涚▼涓嶄細褰卞搷鍚庣画澶勭悊銆 + * + * 鍙傛暟锛 nunstarts 鏈兘鎴愬姛鍚姩鐨勫悗鍙板伐浣滆繘绋嬬殑鏁伴噺 + */ static inline void CleanupUnstartBgworkers(int nunstarts) { slist_mutable_iter iter; + // 濡傛灉瀛樺湪鏈兘鎴愬姛鍚姩鐨勫悗鍙板伐浣滆繘绋 if (nunstarts > 0) { + // 閬嶅巻鍚庡彴宸ヤ綔杩涚▼鍒楄〃 slist_foreach_modify(iter, &t_thrd.bgworker_cxt.bgwlist) { + // 鑾峰彇褰撳墠杩唬鍣ㄦ寚鍚戠殑鍚庡彴宸ヤ綔杩涚▼缁撴瀯 BackgroundWorker *bgw = slist_container(BackgroundWorker, rw_lnode, iter.cur); + // 濡傛灉褰撳墠鍚庡彴宸ヤ綔杩涚▼鐨勭姸鎬佷负 BGW_NOT_YET_STARTED锛屽嵆鏈兘鎴愬姛鍚姩 if (bgw->bgw_status == BGW_NOT_YET_STARTED) { /* the bgworker thread is unable to start, remove it from the waiting list */ - slist_delete_current(&iter); - pthread_mutex_lock(&g_instance.bgw_base_lock); - BgworkerPutBackToFreeList(bgw); - pthread_mutex_unlock(&g_instance.bgw_base_lock); + slist_delete_current(&iter); // 浠庡垪琛ㄤ腑鍒犻櫎褰撳墠杩唬鍣ㄦ寚鍚戠殑鍏冪礌 + pthread_mutex_lock(&g_instance.bgw_base_lock); // 鑾峰彇鍏ㄥ眬浜掓枼閿侊紝浠ヤ究瀵瑰叏灞鏁版嵁杩涜淇敼 + BgworkerPutBackToFreeList(bgw); // 灏嗘湭鑳芥垚鍔熷惎鍔ㄧ殑鍚庡彴宸ヤ綔杩涚▼杩斿洖鍒扮┖闂插垪琛ㄤ腑 + pthread_mutex_unlock(&g_instance.bgw_base_lock); // 閲婃斁鍏ㄥ眬浜掓枼閿 } } } } +/* + * BgworkerListWaitFinish + * + * 鍔熻兘锛氱敤浜庣瓑寰呭悗鍙板伐浣滆呯殑瀹屾垚鐘舵侊紝鐩村埌鎵鏈夌殑鍚庡彴宸ヤ綔鑰呴兘瀹屾垚浜嗕换鍔′负姝 + * + * 鍙傛暟锛 + * nparticipants锛氳〃绀哄弬涓庝换鍔$殑鍚庡彴宸ヤ綔鑰呯殑鏁伴噺 + */ void BgworkerListWaitFinish(int *nparticipants) { slist_iter iter; - bool alldone = false; - uint32 disable_count; - int nfinished; - int nunstarts = 0; + bool alldone = false; // 琛ㄧず鏄惁鎵鏈夊悗鍙板伐浣滆呴兘宸插畬鎴愪换鍔 + uint32 disable_count; // 鐢ㄤ簬瀛樺偍绂佺敤璁℃暟鐨勫彉閲 + int nfinished; // 璁板綍宸插畬鎴愪换鍔$殑鍚庡彴宸ヤ綔鑰呮暟閲 + int nunstarts = 0; // 璁板綍鏈兘鍚姩鐨勫悗鍙板伐浣滆呮暟閲 - Assert(nparticipants != NULL); + Assert(nparticipants != NULL); // 鏂█锛岀‘淇濅紶鍏ョ殑鍙傛暟 nparticipants 涓嶄负绌 + // 鍦ㄧ瓑寰呯姸鎬佹姤鍛婁腑璁剧疆褰撳墠鐘舵佷负绛夊緟鍚屾鐨勫悗鍙板伐浣滆 WaitState oldStatus = pgstat_report_waitstatus(STATE_WAIT_SYNC_BGWORKERS); + // 寰幆锛岀洿鍒版墍鏈夊悗鍙板伐浣滆呴兘瀹屾垚浜嗕换鍔 while (!alldone) { nfinished = 0; + // 閬嶅巻鍚庡彴宸ヤ綔鑰呭垪琛 slist_foreach(iter, &t_thrd.bgworker_cxt.bgwlist) { + // 鑾峰彇褰撳墠杩唬涓殑鍚庡彴宸ヤ綔鑰 BackgroundWorker *bgw = slist_container(BackgroundWorker, rw_lnode, iter.cur); + // 濡傛灉鍚庡彴宸ヤ綔鑰呯姸鎬佷负 BGW_NOT_YET_STARTED锛屼笖瓒呰繃浜嗙姸鎬佹寔缁椂闂撮檺鍒 if (bgw->bgw_status == BGW_NOT_YET_STARTED && ++bgw->bgw_status_dur > BGWORKER_STATUS_DURLIMIT) { - disable_count = pg_atomic_fetch_add_u32(&bgw->disable_count, 1); + disable_count = pg_atomic_fetch_add_u32(&bgw->disable_count, 1); // 鍘熷瓙鎿嶄綔鍦板鍔犲悗鍙板伐浣滆呯殑绂佺敤璁℃暟 + // 濡傛灉绂佺敤璁℃暟涓 0锛岃〃绀鸿鍚庡彴宸ヤ綔鑰呴渶瑕佽绂佺敤 if (disable_count == 0) { + // 杈撳嚭璀﹀憡淇℃伅锛岃〃绀鸿鍚庡彴宸ヤ綔鑰呭湪 5 绉掑唴鏈兘鍚姩锛岃绂佺敤 ereport(WARNING, (errmsg("The bgworker thread %lu hasn't started in 5 seconds, disable it.", bgw->bgw_notify_pid))); - (*nparticipants)--; - nunstarts++; - } - } else if (bgw->bgw_status == BGW_FAILED) { + (*nparticipants)--; // 鍑忓皯鍙備笌浠诲姟鐨勫悗鍙板伐浣滆呮暟閲 + nunstarts++; // 澧炲姞鏈惎鍔ㄧ殑鍚庡彴宸ヤ綔鑰呮暟閲 + } + } else if (bgw->bgw_status == BGW_FAILED) { // 濡傛灉鍚庡彴宸ヤ綔鑰呯姸鎬佷负 BGW_FAILED + // 妫鏌ュ悗鍙板伐浣滆呯殑閿欒绾у埆鏄惁澶т簬鎴栫瓑浜 ERROR if (bgw->bgw_edata.elevel >= ERROR) { + // 杈撳嚭閿欒淇℃伅锛屽寘鎷敊璇爜銆侀敊璇秷鎭拰閿欒璇︽儏 ereport(bgw->bgw_edata.elevel, (errcode(bgw->bgw_edata.sqlerrcode), errmsg("%s", bgw->bgw_edata.message), errdetail("%s", bgw->bgw_edata.detail))); } else { + // 杈撳嚭閿欒淇℃伅锛岃〃绀哄悗鍙板伐浣滆呭湪骞惰绱㈠紩鏋勫缓杩囩▼涓け璐ヤ簡 ereport(ERROR, (errcode(ERRCODE_IN_FAILED_SQL_TRANSACTION), errmsg("Background worker failed during parallel index building."))); } - } else if (bgw->bgw_status == BGW_TERMINATED) { - nfinished++; + } else if (bgw->bgw_status == BGW_TERMINATED) { // 濡傛灉鍚庡彴宸ヤ綔鑰呯姸鎬佷负 BGW_TERMINATED + nfinished++; // 宸插畬鎴愪换鍔$殑鍚庡彴宸ヤ綔鑰呮暟閲+1 } } - alldone = (nfinished >= *nparticipants); + alldone = (nfinished >= *nparticipants); // 鍒ゆ柇鏄惁鎵鏈夊悗鍙板伐浣滆呴兘宸插畬鎴愪换鍔 + // 濡傛灉鎵鏈夊悗鍙板伐浣滆呴兘宸插畬鎴愪换鍔★紝杩涜娓呯悊鏈惎鍔ㄧ殑鍚庡彴宸ヤ綔鑰 if (alldone) { CleanupUnstartBgworkers(nunstarts); } else { + // 鍦ㄧ瓑寰呮湡闂存鏌ユ槸鍚︽湁涓柇璇锋眰锛岀劧鍚庤繘琛岀煭鏆傜殑绛夊緟 CHECK_FOR_INTERRUPTS(); usleep(BGWORKER_LOOP_SLEEP_TIME); } } - pgstat_report_waitstatus(oldStatus); + pgstat_report_waitstatus(oldStatus); // 鎭㈠涔嬪墠鐨勭瓑寰呯姸鎬佹姤鍛 } +/* + * LaunchBackgroundWorkers + * + * 鍔熻兘锛氬惎鍔ㄦ寚瀹氭暟閲忕殑鍚庡彴宸ヤ綔鑰呰繘绋嬶紝鐢ㄤ簬骞惰澶勭悊浠诲姟 + * + * 鍙傛暟锛 + * nworkers: 瑕佸惎鍔ㄧ殑鍚庡彴宸ヤ綔鑰呮暟閲 + * bgshared: 鍏变韩缁欏悗鍙板伐浣滆呯殑鏁版嵁缁撴瀯 + * bgmain: 鍚庡彴宸ヤ綔鑰呯殑涓诲叆鍙e嚱鏁 + * bgexit: 鍚庡彴宸ヤ綔鑰呯殑閫鍑哄叆鍙e嚱鏁 + * + * 杩斿洖鍊硷細 + * 杩斿洖瀹為檯鎴愬姛鍚姩鐨勫悗鍙板伐浣滆呮暟閲 + */ int LaunchBackgroundWorkers(int nworkers, void *bgshared, bgworker_main bgmain, bgworker_exit bgexit) { int actualWorkers = 0; MemoryContext oldcontext; BgWorkerContext *bwc; - Assert(nworkers > 0); + Assert(nworkers > 0); // 纭繚瑕佸惎鍔ㄧ殑鍚庡彴宸ヤ綔鑰呮暟閲忓ぇ浜 0 /* We need to be a lock group leader. */ - BecomeLockGroupLeader(); + BecomeLockGroupLeader(); // 鎴愪负閿佺粍鐨勯瀵艰 /* We might be running in a short-lived memory context. */ - oldcontext = MemoryContextSwitchTo(u_sess->top_transaction_mem_cxt); + oldcontext = MemoryContextSwitchTo(u_sess->top_transaction_mem_cxt); // 淇濆瓨鏃х殑鍐呭瓨涓婁笅鏂 /* * Start workers. @@ -533,30 +705,34 @@ int LaunchBackgroundWorkers(int nworkers, void *bgshared, bgworker_main bgmain, * fails. It wouldn't help much anyway, because registering the worker in * no way guarantees that it will start up and initialize successfully. */ + // 寮濮嬪垱寤哄伐浣滆 + // 鍒嗛厤涓涓悗鍙板伐浣滆呬笂涓嬫枃鍐呭瓨锛屽苟灏嗗叾鍒濆鍖栦负闆 bwc = (BgWorkerContext*)MemoryContextAllocZero( INSTANCE_GET_MEM_CXT_GROUP(MEMORY_CONTEXT_STORAGE), sizeof(BgWorkerContext)); - bwc->transactionCxt.txnId = GetCurrentTransactionIdIfAny(); - bwc->transactionCxt.snapshot = GetActiveSnapshot(); - bwc->bgshared = bgshared; - bwc->databaseName = get_database_name(u_sess->proc_cxt.MyDatabaseId); - bwc->userName = u_sess->proc_cxt.MyProcPort->user_name; + bwc->transactionCxt.txnId = GetCurrentTransactionIdIfAny(); // 璁剧疆浜嬪姟涓婁笅鏂囩殑浜嬪姟ID + bwc->transactionCxt.snapshot = GetActiveSnapshot(); // 璁剧疆浜嬪姟涓婁笅鏂囩殑蹇収 + bwc->bgshared = bgshared; // 灏嗗叡浜殑鏁版嵁缁撴瀯鎸囬拡瀛樺偍鍦ㄤ笂涓嬫枃涓 + bwc->databaseName = get_database_name(u_sess->proc_cxt.MyDatabaseId); // 鑾峰彇褰撳墠鏁版嵁搴撶殑鍚嶇О骞跺瓨鍌ㄥ湪涓婁笅鏂囦腑 + bwc->userName = u_sess->proc_cxt.MyProcPort->user_name; // 鑾峰彇褰撳墠浼氳瘽鐢ㄦ埛鐨勭敤鎴峰悕骞跺瓨鍌ㄥ湪涓婁笅鏂囦腑 /* pass enable_cluster_resize to bgwokers to optimize parallel index building performance during redistribution */ - bwc->enable_cluster_resize = u_sess->attr.attr_sql.enable_cluster_resize; - bwc->leader = t_thrd.proc; - bwc->main_entry = bgmain; - bwc->exit_entry = bgexit; + bwc->enable_cluster_resize = u_sess->attr.attr_sql.enable_cluster_resize; // 灏嗛泦缇よ皟鏁存爣蹇椾紶閫掔粰鍚庡彴宸ヤ綔鑰呬互浼樺寲骞惰绱㈠紩鏋勫缓鎬ц兘 + bwc->leader = t_thrd.proc; // 璁剧疆鍚庡彴宸ヤ綔鑰呯殑棰嗗鑰呬负褰撳墠绾跨▼ + bwc->main_entry = bgmain; // 璁剧疆鍚庡彴宸ヤ綔鑰呯殑涓昏鍏ュ彛鐐 + bwc->exit_entry = bgexit; // 璁剧疆鍚庡彴宸ヤ綔鑰呯殑閫鍑哄叆鍙g偣 - t_thrd.bgworker_cxt.bgwcontext = bwc; + t_thrd.bgworker_cxt.bgwcontext = bwc; // 灏嗗垰鍒氬垵濮嬪寲鐨勫悗鍙板伐浣滆呬笂涓嬫枃璁剧疆鍒板叏灞涓婁笅鏂囦腑 - StreamSaveTxnContext(&bwc->transactionCxt); + StreamSaveTxnContext(&bwc->transactionCxt); // 灏嗕簨鍔′笂涓嬫枃淇濆瓨鍒版祦澶嶅埗涓婁笅鏂囦腑锛屼互渚垮湪鍚庣画娴佸鍒惰繘绋嬩腑浣跨敤 - for (int i = 0; i < nworkers; ++i) { + for (int i = 0; i < nworkers; ++i) { // 閬嶅巻娉ㄥ唽鎸囧畾鏁伴噺鐨勫悗鍙板伐浣滆 + // 璋冪敤 RegisterBackgroundWorker 鍑芥暟娉ㄥ唽鍚庡彴宸ヤ綔鑰 + // 濡傛灉娉ㄥ唽鎴愬姛锛屽垯澧炲姞 actualWorkers 璁℃暟 if (RegisterBackgroundWorker(bwc)) { actualWorkers++; } } /* Restore previous memory context. */ - MemoryContextSwitchTo(oldcontext); - return actualWorkers; + MemoryContextSwitchTo(oldcontext); // 鎭㈠涔嬪墠鐨勫唴瀛樹笂涓嬫枃 + return actualWorkers; // 杩斿洖瀹為檯娉ㄥ唽鐨勫悗鍙板伐浣滆呮暟閲 } diff --git a/src/gausskernel/process/postmaster/bgwriter.cpp b/src/gausskernel/process/postmaster/bgwriter.cpp index e5b67dacf..a96269c70 100755 --- a/src/gausskernel/process/postmaster/bgwriter.cpp +++ b/src/gausskernel/process/postmaster/bgwriter.cpp @@ -88,33 +88,50 @@ const int MAX_THREAD_NAME_LEN = 128; static void drop_rel_all_forks_buffers(); static void drop_rel_one_fork_buffers(); +/* + * 鍔熻兘锛氱敤浜庝负 bgwriter 杩涚▼璁剧疆淇″彿澶勭悊鍑芥暟鎴栦俊鍙峰鐞嗘柟寮忥紝浠ラ傚簲鍏堕渶姹傘 + * 瀹冨拷鐣ヤ簡鏌愪簺淇″彿锛岃缃簡涓浜涗俊鍙风殑澶勭悊鏂瑰紡涓洪粯璁ゅ硷紝骞舵寚瀹氫簡涓浜涗俊鍙风殑澶勭悊鍑芥暟銆 + * + * 鍙傛暟锛氭棤 + * + * 杩斿洖鍊硷細鏃 + */ static void setup_bgwriter_signalhook(void) { /* * Reset some signals that are accepted by postmaster but not here */ - (void)gspqsignal(SIGHUP, bgwriter_sighup_handler); /* set flag to read config file */ - (void)gspqsignal(SIGINT, SIG_IGN); - (void)gspqsignal(SIGTERM, bgwriter_request_shutdown_handler); /* shutdown */ - (void)gspqsignal(SIGQUIT, bgwriter_quickdie); /* hard crash time */ - (void)gspqsignal(SIGALRM, SIG_IGN); - (void)gspqsignal(SIGPIPE, SIG_IGN); - (void)gspqsignal(SIGUSR1, bgwriter_sigusr1_handler); - (void)gspqsignal(SIGUSR2, SIG_IGN); + (void)gspqsignal(SIGHUP, bgwriter_sighup_handler); // 褰撴敹鍒癝IGHUP淇″彿鏃讹紝璁剧疆鏍囧織浠ラ噸鏂拌鍙栭厤缃枃浠 + (void)gspqsignal(SIGINT, SIG_IGN); // 蹇界暐SIGINT淇″彿锛堜腑鏂俊鍙凤級 + (void)gspqsignal(SIGTERM, bgwriter_request_shutdown_handler); // 褰撴敹鍒癝IGTERM淇″彿鏃讹紝璇锋眰鍏抽棴杩涚▼ + (void)gspqsignal(SIGQUIT, bgwriter_quickdie); // 褰撴敹鍒癝IGQUIT淇″彿鏃讹紝鎵ц蹇熷穿婧 + (void)gspqsignal(SIGALRM, SIG_IGN); // 蹇界暐SIGALRM淇″彿锛堝畾鏃跺櫒淇″彿锛 + (void)gspqsignal(SIGPIPE, SIG_IGN); // SIGPIPE淇″彿鐨勯粯璁よ涓烘槸缁堟杩涚▼锛屽皢SIGPIPE淇″彿鐨勫鐞嗘柟寮忚缃负蹇界暐锛屼笉浼氬鑷磋繘绋嬬粓姝紝鑰屾槸鍏佽绋嬪簭缁х画鎵ц + (void)gspqsignal(SIGUSR1, bgwriter_sigusr1_handler); // 褰撴敹鍒癝IGUSR1淇″彿鏃讹紝璋冪敤鐩稿簲鐨勫鐞嗗嚱鏁 + (void)gspqsignal(SIGUSR2, SIG_IGN); // 蹇界暐SIGUSR2淇″彿 /* * Reset some signals that are accepted by postmaster but not here */ - (void)gspqsignal(SIGCHLD, SIG_DFL); + (void)gspqsignal(SIGCHLD, SIG_DFL); // 璁剧疆SIGCHLD淇″彿鐨勯粯璁ゅ鐞嗘柟寮 (void)gspqsignal(SIGTTIN, SIG_DFL); (void)gspqsignal(SIGTTOU, SIG_DFL); (void)gspqsignal(SIGCONT, SIG_DFL); (void)gspqsignal(SIGWINCH, SIG_DFL); /* We allow SIGQUIT (quickdie) at all times */ - sigdelset(&t_thrd.libpq_cxt.BlockSig, SIGQUIT); + sigdelset(&t_thrd.libpq_cxt.BlockSig, SIGQUIT); // 浠庝俊鍙峰睆钄介泦涓Щ闄 SIGQUIT 淇″彿 } +/* + * 鍔熻兘锛氱敤浜庡湪鍚庡彴鍐欏叆杩涚▼閬囧埌寮傚父鎯呭喌鏃舵墽琛屼竴绯诲垪娓呯悊鎿嶄綔锛屼互灏介噺淇濊瘉杩涚▼鑳藉缁х画姝e父杩愯銆 + * + * 鍙傛暟: + * - wb_context: 鍐欏洖涓婁笅鏂囷紝鐢ㄤ簬鎺у埗鍚庡彴鍐欏叆杩涚▼鐨勮涓恒 + * - bgwriter_cxt: 鍚庡彴鍐欏叆杩涚▼鐨勫唴瀛樹笂涓嬫枃銆 + * + * 杩斿洖鍊: 鏃 + */ static void bgwriter_handle_exceptions(WritebackContext wb_context, MemoryContext bgwriter_cxt) { /* @@ -187,90 +204,102 @@ static void bgwriter_handle_exceptions(WritebackContext wb_context, MemoryContex * This is invoked from AuxiliaryProcessMain, which has already created the * basic execution environment, but not enabled signals yet. */ + +/* + * 鍔熻兘锛氬悗鍙板啓鍏ヨ繘绋 (bgwriter) 鐨勪富瑕佸叆鍙g偣銆 + * 鍏朵粠 AuxiliaryProcessMain 琚皟鐢ㄧ殑锛孉uxiliaryProcessMain 宸茬粡鍒涘缓浜嗗熀鏈殑鎵ц鐜锛 + * 浣嗚繕娌℃湁鍚敤淇″彿銆 + * + * 鍙傛暟: 鏃 + * + * 杩斿洖鍊: 鏃 + */ void BackgroundWriterMain(void) { - sigjmp_buf local_sigjmp_buf; - MemoryContext bgwriter_context; - bool prev_hibernate = false; - WritebackContext wb_context; + sigjmp_buf local_sigjmp_buf; // 澹版槑鐢ㄤ簬淇濆瓨璺宠浆浣嶇疆鐨勭紦鍐插尯 + MemoryContext bgwriter_context; // 澹版槑鍚庡彴鍐欏叆杩涚▼鐨勫唴瀛樹笂涓嬫枃 + bool prev_hibernate = false; // 澹版槑鍓嶄竴涓紤鐪犵姸鎬侊紝鐢ㄤ簬鎺у埗浼戠湢 + WritebackContext wb_context; // 鍐欏洖涓婁笅鏂囷紝鐢ㄤ簬鎺у埗鍚庡彴鍐欏叆杩涚▼鐨勮涓 - t_thrd.role = BGWRITER; + t_thrd.role = BGWRITER; // 璁剧疆褰撳墠绾跨▼瑙掕壊涓哄悗鍙板啓鍏ヨ繘绋 - ereport(LOG, (errmsg("bgwriter started"))); + ereport(LOG, (errmsg("bgwriter started"))); // 璁板綍鏃ュ織锛屾爣璁 bgwriter 寮濮嬭繍琛 - setup_bgwriter_signalhook(); + setup_bgwriter_signalhook(); // 璁剧疆淇″彿澶勭悊鍑芥暟 /* * We just started, assume there has been either a shutdown or * end-of-recovery snapshot. */ - last_snapshot_ts = GetCurrentTimestamp(); + last_snapshot_ts = GetCurrentTimestamp(); // 鑾峰彇褰撳墠鏃堕棿鎴充綔涓烘渶鍚庡揩鐓ф椂闂存埑 /* * Create a resource owner to keep track of our resources (currently only * buffer pins). */ t_thrd.utils_cxt.CurrentResourceOwner = ResourceOwnerCreate(NULL, "Background Writer", - THREAD_GET_MEM_CXT_GROUP(MEMORY_CONTEXT_STORAGE)); + THREAD_GET_MEM_CXT_GROUP(MEMORY_CONTEXT_STORAGE)); // 鍒涘缓璧勬簮鎵鏈夎呭苟璁剧疆鍚嶇О /* * Create a memory context that we will do all our work in. We do this so * that we can reset the context during error recovery and thereby avoid * possible memory leaks. Formerly this code just ran in * t_thrd.top_mem_cxt, but resetting that would be a really bad idea. */ + // 鍒涘缓鍐呭瓨涓婁笅鏂囷紝鍦ㄥ叾涓墽琛屾墍鏈夊伐浣溿備究浜庡湪閿欒鎭㈠鏈熼棿鑳藉閲嶇疆涓婁笅鏂囷紝閬垮厤鍙兘鐨勫唴瀛樻硠婕 bgwriter_context = AllocSetContextCreate(t_thrd.top_mem_cxt, "Background Writer", ALLOCSET_DEFAULT_MINSIZE, ALLOCSET_DEFAULT_INITSIZE, - ALLOCSET_DEFAULT_MAXSIZE); - MemoryContextSwitchTo(bgwriter_context); + ALLOCSET_DEFAULT_MAXSIZE); // 鍒涘缓鍚庡彴鍐欏叆杩涚▼鐨勫唴瀛樹笂涓嬫枃 + MemoryContextSwitchTo(bgwriter_context); // 鍒囨崲鍒版柊鍒涘缓鐨勫唴瀛樹笂涓嬫枃 - WritebackContextInit(&wb_context, &u_sess->attr.attr_storage.bgwriter_flush_after); + WritebackContextInit(&wb_context, &u_sess->attr.attr_storage.bgwriter_flush_after); // 鍒濆鍖栧啓鍥炰笂涓嬫枃 /* * If an exception is encountered, processing resumes here. * * See notes in postgres.c about the design of this coding. */ - int curTryCounter; - int* oldTryCounter = NULL; - if (sigsetjmp(local_sigjmp_buf, 1) != 0) { - gstrace_tryblock_exit(true, oldTryCounter); - bgwriter_handle_exceptions(wb_context, bgwriter_context); + // 閬囧埌寮傚父锛屼粠姝ゅ紑濮嬫墽琛 + int curTryCounter; // 鐢ㄤ簬淇濆瓨褰撳墠鐨勯敊璇皾璇曡鏁板櫒 + int* oldTryCounter = NULL; // 鐢ㄤ簬淇濆瓨鏃х殑閿欒灏濊瘯璁℃暟鍣ㄦ寚閽 + if (sigsetjmp(local_sigjmp_buf, 1) != 0) { // 璁剧疆璺宠浆鐐逛互澶勭悊寮傚父 + gstrace_tryblock_exit(true, oldTryCounter); // 閫鍑洪敊璇皾璇曞潡 + bgwriter_handle_exceptions(wb_context, bgwriter_context); // 澶勭悊寮傚父 /* Report wait end here, when there is no further possibility of wait */ - pgstat_report_waitevent(WAIT_EVENT_END); + pgstat_report_waitevent(WAIT_EVENT_END); // 鎶ュ憡绛夊緟浜嬩欢缁撴潫 } - oldTryCounter = gstrace_tryblock_entry(&curTryCounter); + oldTryCounter = gstrace_tryblock_entry(&curTryCounter); // 杩涘叆閿欒灏濊瘯鍧楋紝骞惰幏鍙栨棫鐨勯敊璇皾璇曡鏁板櫒 /* We can now handle ereport(ERROR) */ - t_thrd.log_cxt.PG_exception_stack = &local_sigjmp_buf; + t_thrd.log_cxt.PG_exception_stack = &local_sigjmp_buf; // 璁剧疆寮傚父鍫嗘爤 /* * Unblock signals (they were blocked when the postmaster forked us) */ - gs_signal_setmask(&t_thrd.libpq_cxt.UnBlockSig, NULL); - (void)gs_signal_unblock_sigusr2(); + gs_signal_setmask(&t_thrd.libpq_cxt.UnBlockSig, NULL); // 瑙i櫎淇″彿鎺╃爜 + (void)gs_signal_unblock_sigusr2(); // 瑙i櫎 SIGUSR2 淇″彿鐨勯樆濉 /* * Use the recovery target timeline ID during recovery */ - if (RecoveryInProgress()) - t_thrd.xlog_cxt.ThisTimeLineID = GetRecoveryTargetTLI(); + if (RecoveryInProgress()) // 濡傛灉姝e湪杩涜鎭㈠鎿嶄綔 + t_thrd.xlog_cxt.ThisTimeLineID = GetRecoveryTargetTLI(); // 鑾峰彇鎭㈠鐩爣鏃堕棿绾 ID /* * Reset hibernation state after any error. */ - prev_hibernate = false; + prev_hibernate = false; // 璁剧疆鍒濆鍖栦紤鐪犵姸鎬 - pgstat_report_appname("Background writer"); - pgstat_report_activity(STATE_IDLE, NULL); + pgstat_report_appname("Background writer"); // 鎶ュ憡搴旂敤绋嬪簭鍚嶇О鍒扮粺璁′俊鎭 + pgstat_report_activity(STATE_IDLE, NULL); // 鎶ュ憡娲诲姩鐘舵佷负绌洪棽 /* * Loop forever */ for (;;) { - bool can_hibernate = false; + bool can_hibernate = false; // 鏄惁鍙互浼戠湢鐨勬爣蹇 int rc; /* @@ -279,25 +308,25 @@ void BackgroundWriterMain(void) */ if (pg_atomic_read_u32(&g_instance.dw_batch_cxt.dw_version) < DW_SUPPORT_REABLE_DOUBLE_WRITE && t_thrd.proc->workingVersionNum >= DW_SUPPORT_REABLE_DOUBLE_WRITE) { - dw_upgrade_renable_double_write(); + dw_upgrade_renable_double_write(); // 鎵ц鍙屽啓鍗囩骇鎿嶄綔 } /* Clear any already-pending wakeups */ - ResetLatch(&t_thrd.proc->procLatch); + ResetLatch(&t_thrd.proc->procLatch); // 閲嶇疆杩涚▼鐨 latch - pgstat_report_activity(STATE_RUNNING, NULL); + pgstat_report_activity(STATE_RUNNING, NULL); // 鎶ュ憡娲诲姩鐘舵佷负杩愯涓 - if (t_thrd.bgwriter_cxt.got_SIGHUP) { - t_thrd.bgwriter_cxt.got_SIGHUP = false; - ProcessConfigFile(PGC_SIGHUP); + if (t_thrd.bgwriter_cxt.got_SIGHUP) { // 濡傛灉鏀跺埌浜 SIGHUP 淇″彿 + t_thrd.bgwriter_cxt.got_SIGHUP = false; // 娓呴櫎 SIGHUP 淇″彿鏍囧織 + ProcessConfigFile(PGC_SIGHUP); // 澶勭悊閰嶇疆鏂囦欢鍙樻洿 } - if (t_thrd.bgwriter_cxt.shutdown_requested) { - /* + if (t_thrd.bgwriter_cxt.shutdown_requested) { // 濡傛灉璇锋眰浜嗗叧闂 + /* * From here on, elog(ERROR) should end with exit(1), not send * control back to the sigsetjmp block above */ - u_sess->attr.attr_common.ExitOnAnyError = true; + u_sess->attr.attr_common.ExitOnAnyError = true; // 璁剧疆鍦ㄤ换浣曢敊璇椂閫鍑 /* Normal exit from the bgwriter is here */ proc_exit(0); /* done */ } @@ -310,16 +339,24 @@ void BackgroundWriterMain(void) /* * Send off activity statistics to the stats collector */ - pgstat_send_bgwriter(); + pgstat_send_bgwriter(); // 鍙戦佸悗鍙板啓鍏ヨ繘绋嬬殑缁熻淇℃伅 - if (FirstCallSinceLastCheckpoint()) { + if (FirstCallSinceLastCheckpoint()) { // 濡傛灉鑷笂娆℃鏌ョ偣浠ユ潵鏄娆¤皟鐢 /* * After any checkpoint, close all smgr files. This is so we * won't hang onto smgr references to deleted files indefinitely. */ - smgrcloseall(); + smgrcloseall(); // 鍏抽棴鎵鏈 smgr 鏂囦欢 } + // 鎻忚堪鍦ㄥ悗鍙板啓鍏ヨ繘绋嬶紙bgwriter锛変腑瀹氭湡璁板綍 xl_running_xacts 鐨勭洰鐨勫拰鍘熷洜 /* + *1.缁存姢澶嶅埗涓鑷存: 閫氳繃璁板綍 xl_running_xacts锛屽府鍔╂暟鎹簱澶嶅埗杩涚▼鏇村揩鍦拌揪鍒颁竴鑷寸姸鎬併傝繖瀵逛簬纭繚涓绘暟鎹簱鍜屽浠芥暟鎹簱鐨勬暟鎹竴鑷存ч潪甯搁噸瑕侊紝灏ゅ叾鏄湪澶勭悊瀛愭孩鍑虹殑蹇収鏃躲 + *2.璧勬簮娓呯悊: 瀹氭湡璁板綍鏈夊姪浜庢洿棰戠箒鍦版竻鐞嗚祫婧愶紝濡傞攣鍜 KnownXids* 缁撴瀯銆傝繖鏈夊姪浜庡噺灏戣祫婧愬崰鐢紝鎻愰珮鏁版嵁搴撴ц兘鍜岀ǔ瀹氭с + *3.浣庢垚鏈: 璁板綍 xl_running_xacts 鐨勬垚鏈浉瀵硅緝浣庯紝鍥犳鍙互瀹氭湡鎵ц鑰屼笉浼氬绯荤粺鎬ц兘浜х敓鏄捐憲褰卞搷銆 + *4.閫傚綋鐨勬墽琛岄鐜: 璁板綍鎿嶄綔姣忓垎閽熸墽琛 4 娆★紝杩欎釜棰戠巼瓒充互缁存姢澶嶅埗涓鑷存э紝鍚屾椂涔熶笉浼氬绯荤粺鐨勮秴鏃跺鐞嗛犳垚涓嶅繀瑕佺殑澶嶆潅鎬с + *5.閫夋嫨鍚庡彴鍐欏叆杩涚▼鎵ц: 鐢变簬鍚庡彴鍐欏叆杩涚▼鏄敮涓瀹氭湡鎵ц骞朵笖浼氫竴鐩磋繑鍥炲埌鍏朵富寰幆鐨勮繘绋嬶紝鍥犳鍦ㄦ澶勬墽琛岃褰曟搷浣滄槸鍚堥傜殑銆 + 鍏朵粬杩涚▼锛屽妫鏌ョ偣杩涚▼锛岄氬父涓嶄細棰戠箒鎵ц鍏朵富寰幆锛屼笉閫傚悎鐢ㄤ簬瀹氭湡璁板綍 xl_running_xacts銆 + * Log a new xl_running_xacts every now and then so replication can get * into a consistent state faster (think of suboverflowed snapshots) * and clean up resources (locks, KnownXids*) more frequently. The @@ -340,21 +377,21 @@ void BackgroundWriterMain(void) * time. E.g. Checkpointer, when active, is barely ever in its * mainloop and thus makes it hard to log regularly. */ - if (XLogStandbyInfoActive() && !RecoveryInProgress()) { + if (XLogStandbyInfoActive() && !RecoveryInProgress()) { // 濡傛灉姝e湪杩愯鐑锛屼笖涓嶅湪鎭㈠杩囩▼涓 TimestampTz timeout = 0; - TimestampTz now = GetCurrentTimestamp(); - timeout = TimestampTzPlusMilliseconds(last_snapshot_ts, LOG_SNAPSHOT_INTERVAL_MS); + TimestampTz now = GetCurrentTimestamp(); // 鑾峰彇褰撳墠鏃堕棿鎴 + timeout = TimestampTzPlusMilliseconds(last_snapshot_ts, LOG_SNAPSHOT_INTERVAL_MS); // 璁$畻涓嬫璁板綍鏃堕棿 /* * only log if enough time has passed and some xlog record has been * inserted. */ - if (now >= timeout && !XLByteEQ(last_snapshot_lsn, GetXLogInsertRecPtr())) { - last_snapshot_lsn = LogStandbySnapshot(); - last_snapshot_ts = now; + if (now >= timeout && !XLByteEQ(last_snapshot_lsn, GetXLogInsertRecPtr())) { // 妫鏌ユ槸鍚﹀簲璁板綍 + last_snapshot_lsn = LogStandbySnapshot(); // 璁板綍鐑蹇収 + last_snapshot_ts = now; // 鏇存柊鏈鍚庡揩鐓ф椂闂 } if (now >= timeout) { - LogCheckSlot(); + LogCheckSlot(); // 璁板綍妫鏌ユЫ淇℃伅 } } @@ -368,12 +405,16 @@ void BackgroundWriterMain(void) * down with latch events that are likely to happen frequently during * normal operation. */ - pgstat_report_activity(STATE_IDLE, NULL); + pgstat_report_activity(STATE_IDLE, NULL); // 鎶ュ憡娲诲姩鐘舵佷负绌洪棽 rc = WaitLatch(&t_thrd.proc->procLatch, WL_LATCH_SET | WL_TIMEOUT | WL_POSTMASTER_DEATH, - u_sess->attr.attr_storage.BgWriterDelay /* ms */); + u_sess->attr.attr_storage.BgWriterDelay /* ms */); // 绛夊緟淇″彿鎴栬秴鏃 /* + *1.浼戠湢妯″紡寤堕暱锛氬綋娌℃湁鏍囧織浜嬩欢瑙﹀彂骞朵笖 BgBufferSync 琛ㄧず绯荤粺褰撳墠娌℃湁娲诲姩鏃讹紝浼氳繘鍏 "浼戠湢" 妯″紡锛 + 浼戠湢鏃堕棿姣 bgwriter_delay 瑙勫畾鐨勬椂闂存洿闀匡紝浠ヨ妭鐪佽兘婧愩 + *2.娼滃湪鐨勭珵浜夋潯浠讹細瀛樺湪娼滃湪鐨勭珵浜夋潯浠讹紝鍗冲悗鍙拌繘绋嬪彲鑳藉湪 BgBufferSync 瑙傚療鍒版棤缂撳啿鍖哄垎閰嶈鏁板悗鍒嗛厤缂撳啿鍖恒 + 涓哄噺灏戦敊杩囧敜閱掔殑鍙兘鎬э紝鍙湁鍦ㄨ繛缁袱涓懆鏈熸病鏈夋椿鍔ㄦ椂鎵嶄細杩涘叆浼戠湢锛屽苟涓斾笉浼氭案涔呬紤鐪犮 * If no latch event and BgBufferSync says nothing's happening, extend * the sleep in "hibernation" mode, where we sleep for much longer * than bgwriter_delay says. Fewer wakeups save electricity. When a @@ -406,10 +447,10 @@ void BackgroundWriterMain(void) * Emergency bailout if postmaster has died. This is to avoid the * necessity for manual cleanup of all postmaster children. */ - if (rc & WL_POSTMASTER_DEATH) - gs_thread_exit(1); + if (rc & WL_POSTMASTER_DEATH) // 濡傛灉 postmaster 宸茬粡姝讳骸 + gs_thread_exit(1); // 绱фラ鍑 - prev_hibernate = can_hibernate; + prev_hibernate = can_hibernate; // 鏇存柊鍓嶄竴涓紤鐪犵姸鎬 } } @@ -423,9 +464,23 @@ void BackgroundWriterMain(void) * Some backend has bought the farm, * so we need to stop what we're doing and exit. */ + +/* + *鍔熻兘锛 + * 鍦ㄦ敹鍒 postmaster 鍙戦佺殑 SIGQUIT 淇″彿鏃惰Е鍙戯紝鐢ㄤ簬澶勭悊淇″彿銆 + * 鎰忓懗鐫鏌愪釜鍚庣杩涚▼鍙戠敓浜嗕弗閲嶉敊璇紝闇瑕佺珛鍗冲仠姝㈠綋鍓嶆搷浣滃苟閫鍑恒傚嚱鏁颁細鍏抽棴鎵鏈夊彲鑳界殑璧勬簮骞堕鍑鸿繘绋嬨 + * 杩欓噷涓嶆墽琛 proc_exit() 鍥炶皟鍑芥暟锛屽洜涓哄叡浜唴瀛樺彲鑳藉凡缁忔崯鍧忥紝鎵浠ヤ笉灏濊瘯娓呯悊浜嬪姟銆 + * 涓轰簡纭繚 postmaster 杩涘叆绯荤粺澶嶄綅鍛ㄦ湡锛屼娇鐢 exit(2) 浠ヤ唬鐮2閫鍑 + * + * 鍙傛暟锛 + * SIGNAL_ARGS: 淇″彿澶勭悊鍣ㄧ殑鍙傛暟瀹忥紝鐢ㄤ簬鎺ユ敹淇″彿淇℃伅銆 + * + * 杩斿洖鍊硷細 + * 鏃 + */ static void bgwriter_quickdie(SIGNAL_ARGS) { - gs_signal_setmask(&t_thrd.libpq_cxt.BlockSig, NULL); + gs_signal_setmask(&t_thrd.libpq_cxt.BlockSig, NULL); // 瑙i櫎淇″彿灞忚斀 /* * We DO NOT want to run proc_exit() callbacks -- we're here because @@ -435,7 +490,7 @@ static void bgwriter_quickdie(SIGNAL_ARGS) * things by calling exit() directly, we have to reset the callbacks * explicitly to make this work as intended. */ - on_exit_reset(); + on_exit_reset(); // 閲嶇疆 exit() 鍥炶皟鍑芥暟 /* * Note we do exit(2) not exit(0). This is to force the postmaster into a @@ -445,88 +500,139 @@ static void bgwriter_quickdie(SIGNAL_ARGS) * should ensure the postmaster sees this as a crash, too, but no harm in * being doubly sure.) */ - exit(2); + exit(2); // 浣跨敤 exit(2) 閫鍑鸿繘绋嬶紝寮哄埗 postmaster 杩涘叆绯荤粺澶嶄綅鍛ㄦ湡 } /* SIGHUP: set flag to re-read config file at next convenient time */ +// 鍔熻兘锛氬綋鏀跺埌 SIGHUP 淇″彿鏃讹紝璁剧疆鏍囧織浠ュ湪涓嬩竴涓悎閫傜殑鏃舵満閲嶆柊璇诲彇閰嶇疆鏂囦欢 static void bgwriter_sighup_handler(SIGNAL_ARGS) { - int save_errno = errno; + int save_errno = errno; // 淇濆瓨褰撳墠鐨 errno 鍊 - t_thrd.bgwriter_cxt.got_SIGHUP = true; + t_thrd.bgwriter_cxt.got_SIGHUP = true; // 璁剧疆鏀跺埌 SIGHUP 淇″彿鐨勬爣蹇 if (t_thrd.proc) - SetLatch(&t_thrd.proc->procLatch); + SetLatch(&t_thrd.proc->procLatch); // 璁剧疆杩涚▼鐨勬爣蹇椾簨浠讹紝浠ヤ究閲嶆柊璇诲彇閰嶇疆鏂囦欢 - errno = save_errno; + errno = save_errno; // 鎭㈠涔嬪墠淇濆瓨鐨 errno 鍊 } /* SIGTERM: set flag to shutdown and exit */ +// 鍔熻兘锛氬綋鏀跺埌 SIGTERM 淇″彿鏃讹紝璁剧疆鏍囧織浠ヨ姹傚叧闂苟閫鍑 static void bgwriter_request_shutdown_handler(SIGNAL_ARGS) { - int save_errno = errno; + int save_errno = errno; // 淇濆瓨褰撳墠鐨 errno 鍊 - t_thrd.bgwriter_cxt.shutdown_requested = true; + t_thrd.bgwriter_cxt.shutdown_requested = true; // 璁剧疆璇锋眰鍏抽棴鐨勬爣蹇 if (t_thrd.proc) - SetLatch(&t_thrd.proc->procLatch); + SetLatch(&t_thrd.proc->procLatch);// 璁剧疆杩涚▼鐨勬爣蹇椾簨浠讹紝浠ヤ究璇锋眰鍏抽棴骞堕鍑 - errno = save_errno; + errno = save_errno; // 鎭㈠涔嬪墠淇濆瓨鐨 errno 鍊 } /* SIGUSR1: used for latch wakeups */ +// 鍔熻兘锛氱敤浜庢爣蹇椾簨浠跺敜閱 static void bgwriter_sigusr1_handler(SIGNAL_ARGS) { - int save_errno = errno; + int save_errno = errno; // 淇濆瓨褰撳墠鐨 errno 鍊 - latch_sigusr1_handler(); + latch_sigusr1_handler(); // 澶勭悊 SIGUSR1 淇″彿锛岄氬父鐢ㄤ簬鍞ら啋鏍囧織浜嬩欢 - errno = save_errno; + errno = save_errno; // 鎭㈠涔嬪墠淇濆瓨鐨 errno 鍊 } +// 妫鏌ュ綋鍓嶈繘绋嬫槸鍚︿负鍚庡彴鍐欏叆杩涚▼ +// 鍙傛暟锛 鏃 +// 杩斿洖鍊硷細bool绫诲瀷 [濡傛灉褰撳墠杩涚▼鐨勮鑹叉槸鍚庡彴鍐欏叆杩涚▼锛屽垯杩斿洖 true] bool IsBgwriterProcess(void) { - return (t_thrd.role == BGWRITER); + return (t_thrd.role == BGWRITER); // 濡傛灉褰撳墠杩涚▼鐨勮鑹叉槸鍚庡彴鍐欏叆杩涚▼锛屽垯杩斿洖 true } /* bgwriter view function */ +/* + * 鍔熻兘锛氳幏鍙栧綋鍓嶅疄渚嬬殑鑺傜偣鍚嶇О銆 + * + * 鍙傛暟锛氭棤 + * + * 杩斿洖鍊: + * 濡傛灉鑺傜偣鍚嶇О鏈畾涔夛紝鍒欒繑鍥 "not define" 鐨勬枃鏈暟鎹 + * 鍚﹀垯杩斿洖鑺傜偣鍚嶇О鐨勬枃鏈暟鎹 + */ Datum bgwriter_view_get_node_name() { if (g_instance.attr.attr_common.PGXCNodeName == NULL || g_instance.attr.attr_common.PGXCNodeName[0] == '\0') { - return CStringGetTextDatum("not define"); + return CStringGetTextDatum("not define");// 濡傛灉鑺傜偣鍚嶇О鏈畾涔夛紝鍒欒繑鍥 "not define" 鐨勬枃鏈暟鎹 } else { - return CStringGetTextDatum(g_instance.attr.attr_common.PGXCNodeName); + return CStringGetTextDatum(g_instance.attr.attr_common.PGXCNodeName); // 鍚﹀垯杩斿洖鑺傜偣鍚嶇О鐨勬枃鏈暟鎹 } } +/* + * 鍔熻兘锛氳幏鍙栧悗鍙板啓鍏ヨ繘绋嬫墽琛岀殑瀹為檯鍒锋柊娆℃暟銆 + * + * 鍙傛暟锛氭棤 + * + * 杩斿洖鍊: 杩斿洖鏁存暟 0锛岃〃绀哄疄闄呭埛鏂版鏁般 + */ Datum bgwriter_view_get_actual_flush_num() { - return Int64GetDatum(0); + return Int64GetDatum(0); // 杩斿洖鏁存暟 0锛岃〃绀哄疄闄呭埛鏂版鏁 } - +/* + * 鍔熻兘锛氳幏鍙栦笂涓娆″悗鍙板啓鍏ヨ繘绋嬫墽琛岀殑鍒锋柊娆℃暟銆 + * + * 鍙傛暟锛氭棤 + * + * 杩斿洖鍊: 杩斿洖鏁存暟 0锛岃〃绀轰笂娆″埛鏂版鏁般 + */ Datum bgwriter_view_get_last_flush_num() { - return Int32GetDatum(0); + return Int32GetDatum(0); // 杩斿洖鏁存暟 0锛岃〃绀轰笂娆″埛鏂版鏁 } +/* + * 鍔熻兘锛氳幏鍙栫敤浜庡埛鏂扮殑鍊欓夌紦鍐插尯鎬绘暟銆 + * + * 鍙傛暟锛氭棤 + * + * 杩斿洖鍊: 杩斿洖鍊欓夌紦鍐插尯鏁伴噺鐨勬暣鏁般 + */ Datum bgwriter_view_get_candidate_nums() { int candidate_num = get_curr_candidate_nums(true) + get_curr_candidate_nums(false); - return Int32GetDatum(candidate_num); + return Int32GetDatum(candidate_num); // 杩斿洖鍊欓夌紦鍐插尯鏁伴噺 } +/* + * 鍔熻兘锛氳幏鍙栫敤浜庡埛鏂扮殑缂撳啿鍖哄欓夊垪琛ㄧ殑鏁伴噺銆 + * + * 鍙傛暟锛氭棤 + * + * 杩斿洖鍊: 杩斿洖缂撳啿鍖哄欓夊垪琛ㄦ暟閲忕殑鏁存暟銆 + */ Datum bgwriter_view_get_num_candidate_list() { - return Int64GetDatum(g_instance.ckpt_cxt_ctl->get_buf_num_candidate_list); + return Int64GetDatum(g_instance.ckpt_cxt_ctl->get_buf_num_candidate_list); // 杩斿洖缂撳啿鍖哄欓夊垪琛ㄦ暟閲 } +/* + * 鍔熻兘锛氳幏鍙栧悗鍙板啓鍏ヨ繘绋嬫墽琛岀殑缂撳啿鍖烘椂閽熸壂鎻忚凯浠f鏁般 + * + * 鍙傛暟锛氭棤 + * + * 杩斿洖鍊: 杩斿洖缂撳啿鍖烘椂閽熸壂鎻忔鏁扮殑鏁存暟銆 + */ Datum bgwriter_view_get_num_clock_sweep() { - return Int64GetDatum(g_instance.ckpt_cxt_ctl->get_buf_num_clock_sweep); + return Int64GetDatum(g_instance.ckpt_cxt_ctl->get_buf_num_clock_sweep); // 杩斿洖缂撳啿鍖烘椂閽熸壂鎻忔鏁 } +// 瀹氫箟浜嗗悗鍙板啓鍏ヨ繘绋嬭鍥剧殑鍒椾俊鎭 const incre_ckpt_view_col g_bgwriter_view_col[INCRE_CKPT_BGWRITER_VIEW_COL_NUM] = { +// 鍒楀悕 鏁版嵁绫诲瀷 鑾峰彇鏁版嵁闇瑕佽皟鐢ㄧ殑鍑芥暟 {"node_name", TEXTOID, bgwriter_view_get_node_name}, {"bgwr_actual_flush_total_num", INT8OID, bgwriter_view_get_actual_flush_num}, {"bgwr_last_flush_num", INT4OID, bgwriter_view_get_last_flush_num}, @@ -535,17 +641,24 @@ const incre_ckpt_view_col g_bgwriter_view_col[INCRE_CKPT_BGWRITER_VIEW_COL_NUM] {"get_buf_clock_sweep", INT8OID, bgwriter_view_get_num_clock_sweep}}; -const uint THREAD_SLEEP_TIME = 10 * 60 * 1000; +const uint THREAD_SLEEP_TIME = 10 * 60 * 1000; // 鍚庡彴鍐欏叆杩涚▼鐫$湢鏃堕棿锛堜互姣涓哄崟浣嶏級 +/* + * 鍔熻兘锛氬悗鍙版棤鏁堢紦鍐插尯鍐欏叆杩涚▼鐨勪富瑕佹墽琛屽嚱鏁帮紝璐熻矗绠$悊鏃犳晥缂撳啿鍖虹殑娓呯悊宸ヤ綔銆 + * + * 鍙傛暟锛氭棤 + * + * 杩斿洖鍊: 鏃 + */ void invalid_buffer_bgwriter_main() { - sigjmp_buf localSigjmpBuf; - MemoryContext bgwriter_context; - char name[MAX_THREAD_NAME_LEN] = {0}; - WritebackContext wb_context; - t_thrd.role = SPBGWRITER; + sigjmp_buf localSigjmpBuf; // 鐢ㄤ簬澶勭悊寮傚父鐨勮烦杞爣璁 + MemoryContext bgwriter_context; // 鍐呭瓨涓婁笅鏂囷紝鐢ㄤ簬鎵ц宸ヤ綔骞跺鐞嗛敊璇仮澶 + char name[MAX_THREAD_NAME_LEN] = {0}; // 绾跨▼鍚嶇О + WritebackContext wb_context; // 鍐欏叆涓婁笅鏂囷紝鐢ㄤ簬閰嶇疆鍐欏叆琛屼负 + t_thrd.role = SPBGWRITER; // 璁剧疆绾跨▼瑙掕壊涓 SPBGWRITER - setup_bgwriter_signalhook(); - ereport(LOG, (errmsg("invalidate buffer bgwriter started"))); + setup_bgwriter_signalhook(); // 璁剧疆淇″彿澶勭悊鍑芥暟 + ereport(LOG, (errmsg("invalidate buffer bgwriter started"))); // 璁板綍鏃ュ織锛岃〃绀哄悗鍙版棤鏁堢紦鍐插尯鍐欏叆杩涚▼宸插惎鍔 errno_t err_rc = snprintf_s(name, MAX_THREAD_NAME_LEN, MAX_THREAD_NAME_LEN - 1, "%s", "spbgwriter"); securec_check_ss(err_rc, "", ""); @@ -564,10 +677,10 @@ void invalid_buffer_bgwriter_main() ALLOCSET_DEFAULT_INITSIZE, ALLOCSET_DEFAULT_MAXSIZE); MemoryContextSwitchTo(bgwriter_context); - WritebackContextInit(&wb_context, &u_sess->attr.attr_storage.bgwriter_flush_after); + WritebackContextInit(&wb_context, &u_sess->attr.attr_storage.bgwriter_flush_after); // 鍒濆鍖栧啓鍏ヤ笂涓嬫枃 if (sigsetjmp(localSigjmpBuf, 1) != 0) { - ereport(WARNING, (errmsg("invalidate buffer bgwriter exception occured."))); + ereport(WARNING, (errmsg("invalidate buffer bgwriter exception occured."))); // 澶勭悊寮傚父鎯呭喌 bgwriter_handle_exceptions(wb_context, bgwriter_context); } @@ -575,7 +688,7 @@ void invalid_buffer_bgwriter_main() t_thrd.log_cxt.PG_exception_stack = &localSigjmpBuf; /* Unblock signals (they were blocked when the postmaster forked us) */ - gs_signal_setmask(&t_thrd.libpq_cxt.UnBlockSig, NULL); + gs_signal_setmask(&t_thrd.libpq_cxt.UnBlockSig, NULL); (void)gs_signal_unblock_sigusr2(); /* Use the recovery target timeline ID during recovery */ @@ -583,187 +696,230 @@ void invalid_buffer_bgwriter_main() t_thrd.xlog_cxt.ThisTimeLineID = GetRecoveryTargetTLI(); } - pgstat_report_appname("InvalidBufferBgWriter"); - pgstat_report_activity(STATE_IDLE, NULL); - g_instance.bgwriter_cxt.invalid_buf_proc_latch = &t_thrd.proc->procLatch; + pgstat_report_appname("InvalidBufferBgWriter"); // 璁剧疆搴旂敤绋嬪簭鍚嶇О浠ヨ繘琛岀粺璁 + pgstat_report_activity(STATE_IDLE, NULL); // 鎶ュ憡杩涚▼鐘舵佷负绌洪棽 + g_instance.bgwriter_cxt.invalid_buf_proc_latch = &t_thrd.proc->procLatch; // 璁剧疆 Latch 鐢ㄤ簬绛夊緟浜嬩欢瑙﹀彂 /* Loop forever */ for (;;) { int rc; if (t_thrd.bgwriter_cxt.got_SIGHUP) { t_thrd.bgwriter_cxt.got_SIGHUP = false; - ProcessConfigFile(PGC_SIGHUP); + ProcessConfigFile(PGC_SIGHUP); // 澶勭悊 SIGHUP 淇″彿锛岄噸鏂板姞杞介厤缃枃浠 } if (t_thrd.bgwriter_cxt.shutdown_requested) { - ereport(LOG, (errmsg("invalidate buffer bgwriter thread shut down"))); - u_sess->attr.attr_common.ExitOnAnyError = true; - proc_exit(0); + ereport(LOG, (errmsg("invalidate buffer bgwriter thread shut down"))); // 璁板綍鏃ュ織锛岃〃绀虹嚎绋嬪嵆灏嗗叧闂 + u_sess->attr.attr_common.ExitOnAnyError = true; + proc_exit(0); // 閫鍑虹嚎绋 } - rc = WaitLatch(&t_thrd.proc->procLatch, WL_LATCH_SET | WL_TIMEOUT | WL_POSTMASTER_DEATH, THREAD_SLEEP_TIME); + rc = WaitLatch(&t_thrd.proc->procLatch, WL_LATCH_SET | WL_TIMEOUT | WL_POSTMASTER_DEATH, THREAD_SLEEP_TIME); // 绛夊緟浜嬩欢瑙﹀彂 if (rc & WL_POSTMASTER_DEATH) { - gs_thread_exit(1); + gs_thread_exit(1); // 濡傛灉 Postmaster 宸茬粡鍏抽棴锛岀嚎绋嬮鍑 } /* Clear any already-pending wakeups */ - ResetLatch(&t_thrd.proc->procLatch); - drop_rel_all_forks_buffers(); - drop_rel_one_fork_buffers(); + ResetLatch(&t_thrd.proc->procLatch); // 娓呴櫎宸茬粡瑙﹀彂鐨勪簨浠 + drop_rel_all_forks_buffers(); // 鎵ц閲婃斁鎵鏈夊叧绯荤殑缂撳啿鍖虹殑鎿嶄綔 + drop_rel_one_fork_buffers(); // 鎵ц閲婃斁涓涓叧绯荤殑缂撳啿鍖虹殑鎿嶄綔 } } const int HASH_TABLE_ELEMENT_MIN_NUM = 512; + +/* + * 鍔熻兘锛氬垱寤哄叧绯绘枃浠惰妭鐐瑰搱甯岃〃锛岀敤浜庡瓨鍌ㄥ叧浜庡垹闄ょ殑鍏崇郴鏂囦欢鐨勪俊鎭 + * + * 鍙傛暟锛 + * name - 鍝堝笇琛ㄧ殑鍚嶇О + * use_heap_mem - 鏄惁浣跨敤鍫嗗唴瀛 + * + * 杩斿洖鍊硷細 + * 杩斿洖鍒涘缓鐨勫搱甯岃〃 + */ HTAB *relfilenode_hashtbl_create(const char *name, bool use_heap_mem) { - HASHCTL hashCtrl; - HTAB *hashtbl = NULL; - errno_t rc; + HASHCTL hashCtrl; // 鍝堝笇琛ㄦ帶鍒朵俊鎭粨鏋勪綋 + HTAB *hashtbl = NULL; // 鍝堝笇琛ㄦ寚閽堬紝鍒濆鍖栦负绌 + errno_t rc; // 鐢ㄤ簬閿欒澶勭悊鐨勮繑鍥炵爜 - rc = memset_s(&hashCtrl, sizeof(hashCtrl), 0, sizeof(hashCtrl)); - securec_check(rc, "", ""); - hashCtrl.hcxt = (MemoryContext)CurrentMemoryContext; - hashCtrl.hash = tag_hash; - hashCtrl.keysize = sizeof(RelFileNode); + rc = memset_s(&hashCtrl, sizeof(hashCtrl), 0, sizeof(hashCtrl)); // 鍒濆鍖 hashCtrl 缁撴瀯浣撲负 0 + securec_check(rc, "", ""); // 妫鏌 memset_s 鐨勮繑鍥炲 + hashCtrl.hcxt = (MemoryContext)CurrentMemoryContext; // 璁剧疆鍝堝笇琛ㄧ殑鍐呭瓨涓婁笅鏂 + hashCtrl.hash = tag_hash; // 璁剧疆鍝堝笇鍑芥暟 + hashCtrl.keysize = sizeof(RelFileNode); // 璁剧疆閿殑澶у皬 /* keep entrysize >= keysize, stupid limits */ - hashCtrl.entrysize = sizeof(DelFileTag); + hashCtrl.entrysize = sizeof(DelFileTag); // 璁剧疆鍝堝笇琛ㄤ腑姣忎釜鏉$洰鐨勫ぇ灏 - if (use_heap_mem) { + if (use_heap_mem) { // 鏍规嵁 use_heap_mem 鍙傛暟鍒ゆ柇鏄惁浣跨敤鍫嗗唴瀛 hashtbl = HeapMemInitHash(name, HASH_TABLE_ELEMENT_MIN_NUM, Max(g_instance.attr.attr_common.max_files_per_process, t_thrd.storage_cxt.max_userdatafiles), &hashCtrl, - (HASH_FUNCTION | HASH_ELEM)); + (HASH_FUNCTION | HASH_ELEM)); // 鍦ㄥ爢鍐呭瓨涓婂垱寤哄搱甯岃〃 if (hashtbl == NULL) { - ereport(FATAL, (errmsg("could not initialize unlinik relation hash table"))); + ereport(FATAL, (errmsg("could not initialize unlinik relation hash table"))); // 濡傛灉鍒涘缓澶辫触锛屾姤鑷村懡閿欒 } } else { + // 鍦ㄥ綋鍓嶅唴瀛樹笂涓嬫枃涓垱寤哄搱甯岃〃 hashtbl = hash_create(name, HASH_TABLE_ELEMENT_MIN_NUM, &hashCtrl, (HASH_CONTEXT | HASH_FUNCTION | HASH_ELEM)); } - return hashtbl; + return hashtbl; // 杩斿洖鍒涘缓鐨勫搱甯岃〃鎸囬拡 } +/* + * 鍔熻兘锛氬垱寤哄叧绯绘枃浠惰妭鐐瑰垎鏀搱甯岃〃锛岀敤浜庡瓨鍌ㄥ叧浜庡垹闄ょ殑鍏崇郴鏂囦欢鍒嗘敮鐨勪俊鎭 + * + * 鍙傛暟锛 + * name - 鍝堝笇琛ㄧ殑鍚嶇О + * use_heap_mem - 鏄惁浣跨敤鍫嗗唴瀛 + * + * 杩斿洖鍊硷細 + * 杩斿洖鍒涘缓鐨勫搱甯岃〃 + */ HTAB *relfilenode_fork_hashtbl_create(const char* name, bool use_heap_mem) { - HASHCTL hashCtrl; - HTAB *hashtbl = NULL; - errno_t rc; + HASHCTL hashCtrl; // 鍝堝笇琛ㄦ帶鍒朵俊鎭粨鏋勪綋 + HTAB *hashtbl = NULL; // 鍝堝笇琛ㄦ寚閽堬紝鍒濆鍖栦负绌 + errno_t rc; // 鐢ㄤ簬閿欒澶勭悊鐨勮繑鍥炵爜 - rc = memset_s(&hashCtrl, sizeof(hashCtrl), 0, sizeof(hashCtrl)); - securec_check(rc, "", ""); - hashCtrl.hcxt = (MemoryContext)CurrentMemoryContext; - hashCtrl.hash = tag_hash; - hashCtrl.keysize = sizeof(ForkRelFileNode); + rc = memset_s(&hashCtrl, sizeof(hashCtrl), 0, sizeof(hashCtrl)); // 鍒濆鍖 hashCtrl 缁撴瀯浣撲负 0 + securec_check(rc, "", ""); // 妫鏌 memset_s 鐨勮繑鍥炲 + hashCtrl.hcxt = (MemoryContext)CurrentMemoryContext; // 璁剧疆鍝堝笇琛ㄧ殑鍐呭瓨涓婁笅鏂 + hashCtrl.hash = tag_hash; // 璁剧疆鍝堝笇鍑芥暟 + hashCtrl.keysize = sizeof(ForkRelFileNode); // 璁剧疆閿殑澶у皬 /* keep entrysize >= keysize, stupid limits */ - hashCtrl.entrysize = sizeof(DelForkFileTag); + hashCtrl.entrysize = sizeof(DelForkFileTag); // 璁剧疆鍝堝笇琛ㄤ腑姣忎釜鏉$洰鐨勫ぇ灏 - if (use_heap_mem) { + if (use_heap_mem) { // 鏍规嵁 use_heap_mem 鍙傛暟鍒ゆ柇鏄惁浣跨敤鍫嗗唴瀛 hashtbl = HeapMemInitHash(name, HASH_TABLE_ELEMENT_MIN_NUM, Max(g_instance.attr.attr_common.max_files_per_process, t_thrd.storage_cxt.max_userdatafiles), - &hashCtrl, (HASH_FUNCTION | HASH_ELEM)); + &hashCtrl, (HASH_FUNCTION | HASH_ELEM)); // 鍦ㄥ爢鍐呭瓨涓婂垱寤哄搱甯岃〃 if (hashtbl == NULL) { ereport(FATAL, (errmsg("could not initialize unlinik relation hash table"))); } } else { hashtbl = hash_create(name, HASH_TABLE_ELEMENT_MIN_NUM, &hashCtrl, (HASH_CONTEXT | HASH_FUNCTION | HASH_ELEM)); } - return hashtbl; + return hashtbl; // 杩斿洖鍒涘缓鐨勫搱甯岃〃鎸囬拡 } +/* + * 鍔熻兘锛 + * 涓㈠純鎵鏈夎〃鐨勬墍鏈夊垎鏀殑缂撳啿鍖猴紝骞舵敞鍐岀浉鍏崇殑蹇樿璇锋眰 + * + * 鍙傛暟锛 鏃 + * + * 杩斿洖鍊硷細鏃 + */ static void drop_rel_all_forks_buffers() { - HASH_SEQ_STATUS status; - DelFileTag *entry = NULL; - DelFileTag *temp_entry = NULL; - bool found = false; - uint rel_num = 0; - HTAB *unlink_rel_hashtbl = g_instance.bgwriter_cxt.unlink_rel_hashtbl; - HTAB *rel_bak = relfilenode_hashtbl_create("unlink_rel_bak", false); + HASH_SEQ_STATUS status; // 鍝堝笇琛ㄩ亶鍘嗙姸鎬 + DelFileTag *entry = NULL; // 鍝堝笇琛ㄤ腑鐨勬潯鐩寚閽 + DelFileTag *temp_entry = NULL; // 涓存椂鏉$洰鎸囬拡 + bool found = false; // 鏄惁鎵惧埌鏍囧織 + uint rel_num = 0; // 鍏崇郴鏁伴噺 + HTAB *unlink_rel_hashtbl = g_instance.bgwriter_cxt.unlink_rel_hashtbl; // 鑾峰彇鍝堝笇琛ㄦ寚閽 + HTAB *rel_bak = relfilenode_hashtbl_create("unlink_rel_bak", false); // 鍒涘缓涓存椂鍝堝笇琛 /* Obtains the entry in hashtable. */ - LWLockAcquire(g_instance.bgwriter_cxt.rel_hashtbl_lock, LW_SHARED); - hash_seq_init(&status, unlink_rel_hashtbl); + LWLockAcquire(g_instance.bgwriter_cxt.rel_hashtbl_lock, LW_SHARED); // 鑾峰彇鍏变韩閿 + hash_seq_init(&status, unlink_rel_hashtbl); // 鍒濆鍖栧搱甯岃〃閬嶅巻鐘舵 while ((temp_entry = (DelFileTag *)hash_seq_search(&status)) != NULL) { - entry = (DelFileTag*)hash_search(rel_bak, (void *)&temp_entry->rnode, HASH_ENTER, &found); + entry = (DelFileTag*)hash_search(rel_bak, (void *)&temp_entry->rnode, HASH_ENTER, &found); // 灏嗗搱甯岃〃涓殑鏁版嵁澶嶅埗鍒颁复鏃跺搱甯岃〃 if (!found) { entry->rnode = temp_entry->rnode; entry->maxSegNo = temp_entry->maxSegNo; rel_num++; } } - LWLockRelease(g_instance.bgwriter_cxt.rel_hashtbl_lock); + LWLockRelease(g_instance.bgwriter_cxt.rel_hashtbl_lock); // 閲婃斁鍏变韩閿 if (rel_num > 0) { - DropRelFileNodeAllBuffersUsingHash(rel_bak); + DropRelFileNodeAllBuffersUsingHash(rel_bak); // 閲婃斁鍝堝笇琛ㄤ腑鎵鏈夊叧绯荤殑缂撳啿鍖 - hash_seq_init(&status, rel_bak); - while ((temp_entry = (DelFileTag *)hash_seq_search(&status)) != NULL) { - if (temp_entry->maxSegNo == -1) { + hash_seq_init(&status, rel_bak); // 鍒濆鍖栧搱甯岃〃閬嶅巻鐘舵 + while ((temp_entry = (DelFileTag *)hash_seq_search(&status)) != NULL) { // 寰幆閬嶅巻鍝堝笇琛ㄤ腑鐨勬瘡涓潯鐩 + if (temp_entry->maxSegNo == -1) { // 濡傛灉maxSegNo涓-1锛岃〃绀轰笉澶勭悊璇ュ叧绯 ereport(DEBUG1, (errmodule(MOD_INCRE_BG), errmsg("the max segno is -1, skip forget this rel %u/%u/%u, bucketNode is %d", temp_entry->rnode.spcNode, temp_entry->rnode.dbNode, temp_entry->rnode.relNode, temp_entry->rnode.bucketNode))); - continue; + continue; // 璺宠繃涓嶅鐞嗙殑鍏崇郴 } - for (int32 i = 0; i < temp_entry->maxSegNo; i++) { - for (int fork_num = 0; fork_num <= (int)MAX_FORKNUM; fork_num++) { - md_register_forget_request(temp_entry->rnode, fork_num, i); + for (int32 i = 0; i < temp_entry->maxSegNo; i++) { // 寰幆澶勭悊鍏崇郴鐨勬瘡涓 + for (int fork_num = 0; fork_num <= (int)MAX_FORKNUM; fork_num++) { // 寰幆澶勭悊鍏崇郴鐨勬瘡涓垎鏀 + md_register_forget_request(temp_entry->rnode, fork_num, i); // 娉ㄥ唽蹇樿璇锋眰 } } - LWLockAcquire(g_instance.bgwriter_cxt.rel_hashtbl_lock, LW_EXCLUSIVE); + LWLockAcquire(g_instance.bgwriter_cxt.rel_hashtbl_lock, LW_EXCLUSIVE); // 鑾峰彇閿佷互鎿嶄綔鍏崇郴鍝堝笇琛 + // 濡傛灉鍦ㄥ搱甯岃〃涓病鏈夋壘鍒板叧绯伙紝鎶ュ憡鏁版嵁鎹熷潖閿欒 if (hash_search(unlink_rel_hashtbl, (void *)&temp_entry->rnode, HASH_REMOVE, NULL) == NULL) { LWLockRelease(g_instance.bgwriter_cxt.rel_hashtbl_lock); hash_destroy(rel_bak); ereport(ERROR, (errcode(ERRCODE_DATA_CORRUPTED), errmsg("unlink rel hash table corrupted"))); } else { + // 鍏崇郴澶勭悊瀹屾垚锛岃褰曟棩蹇 ereport(DEBUG1, (errmodule(MOD_INCRE_BG), errmsg("invalidate buffer has been finished for rel %u/%u/%u, bucketNode is %d", temp_entry->rnode.spcNode, temp_entry->rnode.dbNode, temp_entry->rnode.relNode, temp_entry->rnode.bucketNode))); } - LWLockRelease(g_instance.bgwriter_cxt.rel_hashtbl_lock); + LWLockRelease(g_instance.bgwriter_cxt.rel_hashtbl_lock); // 閲婃斁鍏崇郴鍝堝笇琛ㄩ攣 } } - hash_destroy(rel_bak); + hash_destroy(rel_bak); // 閿姣佷复鏃跺搱甯岃〃 } +/* + * 鍔熻兘锛 + * 閲婃斁涓庝竴涓壒瀹氬叧绯荤殑鍗曚釜鍒嗗弶鏂囦欢鐩稿叧鐨勬墍鏈夌紦鍐插尯锛屽苟灏嗗叾浠庡搱甯岃〃涓Щ闄 + * + * 鍙傛暟锛氭棤 + * + * 杩斿洖鍊硷細鏃 + */ static void drop_rel_one_fork_buffers() { - HASH_SEQ_STATUS status; - DelForkFileTag *entry = NULL; - DelForkFileTag *temp_entry = NULL; - bool found = false; - uint rel_num = 0; - HTAB *unlink_rel_fork_hashtbl = g_instance.bgwriter_cxt.unlink_rel_fork_hashtbl; - HTAB *rel_bak = relfilenode_fork_hashtbl_create("unlink_rel_one_fork_bak", false); + HASH_SEQ_STATUS status; // 鍝堝笇琛ㄩ亶鍘嗙姸鎬 + DelForkFileTag *entry = NULL; // 鍝堝笇琛ㄤ腑鐨勬潯鐩寚閽 + DelForkFileTag *temp_entry = NULL; // 涓存椂鏉$洰鎸囬拡 + bool found = false; // 鏄惁鎵惧埌鏍囧織 + uint rel_num = 0; // 鍏崇郴鏁伴噺 + HTAB *unlink_rel_fork_hashtbl = g_instance.bgwriter_cxt.unlink_rel_fork_hashtbl; // 鑾峰彇鍝堝笇琛ㄦ寚閽 + HTAB *rel_bak = relfilenode_fork_hashtbl_create("unlink_rel_one_fork_bak", false); // 鍒涘缓涓存椂鍝堝笇琛 /* Obtains the entry in hashtable. */ - LWLockAcquire(g_instance.bgwriter_cxt.rel_one_fork_hashtbl_lock, LW_SHARED); - hash_seq_init(&status, unlink_rel_fork_hashtbl); - while ((temp_entry = (DelForkFileTag *)hash_seq_search(&status)) != NULL) { - entry = (DelForkFileTag*)hash_search(rel_bak, temp_entry, HASH_ENTER, &found); + LWLockAcquire(g_instance.bgwriter_cxt.rel_one_fork_hashtbl_lock, LW_SHARED); // 鑾峰彇鍝堝笇琛ㄩ攣锛堝叡浜ā寮忥級 + hash_seq_init(&status, unlink_rel_fork_hashtbl); // 鍒濆鍖栧搱甯岃〃閬嶅巻鐘舵 + while ((temp_entry = (DelForkFileTag *)hash_seq_search(&status)) != NULL) { // 寰幆閬嶅巻鍝堝笇琛ㄤ腑鐨勬瘡涓潯鐩 + entry = (DelForkFileTag*)hash_search(rel_bak, temp_entry, HASH_ENTER, &found); // 鍦ㄤ复鏃跺搱甯岃〃涓煡鎵炬垨鎻掑叆鏉$洰 if (!found) { + // 濡傛灉娌℃湁鎵惧埌锛屽垵濮嬪寲鏉$洰鏁版嵁 entry->forkrnode.rnode.spcNode = temp_entry->forkrnode.rnode.spcNode; entry->forkrnode.rnode.dbNode = temp_entry->forkrnode.rnode.dbNode; entry->forkrnode.rnode.relNode = temp_entry->forkrnode.rnode.relNode; entry->forkrnode.rnode.bucketNode = temp_entry->forkrnode.rnode.bucketNode; entry->forkrnode.forkNum = temp_entry->forkrnode.forkNum; entry->maxSegNo = temp_entry->maxSegNo; - rel_num++; + rel_num++; // 澧炲姞鍏崇郴鏁伴噺 } } - LWLockRelease(g_instance.bgwriter_cxt.rel_one_fork_hashtbl_lock); + LWLockRelease(g_instance.bgwriter_cxt.rel_one_fork_hashtbl_lock); // 閲婃斁鍝堝笇琛ㄩ攣 - if (rel_num > 0) { - DropRelFileNodeOneForkAllBuffersUsingHash(rel_bak); - hash_seq_init(&status, rel_bak); + if (rel_num > 0) { // 濡傛灉鏈夎澶勭悊鐨勫叧绯 + DropRelFileNodeOneForkAllBuffersUsingHash(rel_bak); // 閲婃斁涓存椂鍝堝笇琛ㄤ腑鎵鏈夊叧绯荤殑缂撳啿鍖 + hash_seq_init(&status, rel_bak); // 閲嶆柊鍒濆鍖栧搱甯岃〃閬嶅巻鐘舵 while ((temp_entry = (DelForkFileTag *)hash_seq_search(&status)) != NULL) { + // 鍐嶆閬嶅巻涓存椂鍝堝笇琛ㄤ腑鐨勬瘡涓潯鐩 if (temp_entry->maxSegNo == -1) { + // 濡傛灉maxSegNo涓-1锛岃〃绀轰笉澶勭悊璇ュ叧绯 ereport(DEBUG1, (errmodule(MOD_INCRE_BG), errmsg("the max segno is -1, skip forget this rel %u/%u/%u, bucketNode is %d", temp_entry->forkrnode.rnode.spcNode, temp_entry->forkrnode.rnode.dbNode, temp_entry->forkrnode.rnode.relNode, temp_entry->forkrnode.rnode.bucketNode))); - continue; + continue; // 璺宠繃涓嶅鐞嗙殑鍏崇郴 } - for (int32 i = 0; i < temp_entry->maxSegNo; i++) { + for (int32 i = 0; i < temp_entry->maxSegNo; i++) { // 寰幆澶勭悊鍏崇郴鐨勬瘡涓 md_register_forget_request(temp_entry->forkrnode.rnode, temp_entry->forkrnode.forkNum, i); } LWLockAcquire(g_instance.bgwriter_cxt.rel_one_fork_hashtbl_lock, LW_EXCLUSIVE); diff --git a/src/gausskernel/process/postmaster/cbmwriter.cpp b/src/gausskernel/process/postmaster/cbmwriter.cpp index c82192c3b..ad9977aee 100755 --- a/src/gausskernel/process/postmaster/cbmwriter.cpp +++ b/src/gausskernel/process/postmaster/cbmwriter.cpp @@ -56,12 +56,23 @@ static void CBMwriter_sigusr1_handler(SIGNAL_ARGS); * This is invoked from AuxiliaryProcessMain, which has already created the * basic execution environment, but not enabled signals yet. */ +/* + * 鍔熻兘锛 + * cbmwriter 杩涚▼鐨勪富瑕佸叆鍙g偣銆傝礋璐g鐞嗘彁浜や綅鍥撅紙CBM锛夌殑鎸佷箙鍖栧啓鍏ワ紝浠ュ強澶勭悊閰嶇疆鏂囦欢銆佷俊鍙峰拰寮傚父銆 + * + * 鍙傛暟锛 + * 鏃 + * + * 杩斿洖鍊硷細 + * 鏃 + */ void CBMWriterMain(void) { - sigjmp_buf local_sigjmp_buf; - ResourceOwner cbmwriter_resourceOwner; + sigjmp_buf local_sigjmp_buf; // 鐢ㄤ簬閿欒澶勭悊鐨勮烦杞偣 + ResourceOwner cbmwriter_resourceOwner; // 鐢ㄤ簬璺熻釜 CBM Writer 杩涚▼鐨勮祫婧 ereport(LOG, (errmsg("cbm writer started"))); + // 鏍规嵁閰嶇疆鍐冲畾妫鏌ョ偣瓒呮椂鏃堕棿 u_sess->attr.attr_storage.CheckPointTimeout = ENABLE_INCRE_CKPT ? u_sess->attr.attr_storage.incrCheckPointTimeout : u_sess->attr.attr_storage.fullCheckPointTimeout; @@ -75,31 +86,33 @@ void CBMWriterMain(void) /* * Reset some signals that are accepted by postmaster but not here */ - (void)gspqsignal(SIGHUP, CBMSigHupHandler); /* set flag to read config file */ - (void)gspqsignal(SIGINT, CBMShutdownHandler); /* request shutdown */ - (void)gspqsignal(SIGTERM, CBMShutdownHandler); /* request shutdown */ - (void)gspqsignal(SIGQUIT, CBM_quickdie); /* hard crash time */ - (void)gspqsignal(SIGALRM, SIG_IGN); - (void)gspqsignal(SIGPIPE, SIG_IGN); - (void)gspqsignal(SIGUSR1, CBMwriter_sigusr1_handler); - (void)gspqsignal(SIGUSR2, SIG_IGN); /* not used */ + (void)gspqsignal(SIGHUP, CBMSigHupHandler); /* set flag to read config file */ // 鏀跺埌 SIGHUP 淇″彿鏃堕噸鏂拌鍙栭厤缃枃浠 + (void)gspqsignal(SIGINT, CBMShutdownHandler); /* request shutdown */ // 鏀跺埌 SIGINT 淇″彿鏃惰姹傛甯稿叧闂 + (void)gspqsignal(SIGTERM, CBMShutdownHandler); /* request shutdown */ // 鏀跺埌 SIGTERM 淇″彿鏃惰姹傛甯稿叧闂 + (void)gspqsignal(SIGQUIT, CBM_quickdie); /* hard crash time */ // 鏀跺埌 SIGQUIT 淇″彿鏃舵墽琛岀‖宕╂簝鎿嶄綔 + (void)gspqsignal(SIGALRM, SIG_IGN); // 蹇界暐 SIGALRM 淇″彿 + (void)gspqsignal(SIGPIPE, SIG_IGN); // 蹇界暐 SIGPIPE 淇″彿 + (void)gspqsignal(SIGUSR1, CBMwriter_sigusr1_handler); // 鎵ц鑷畾涔夋搷浣滀互鍝嶅簲 SIGUSR1 淇″彿 + (void)gspqsignal(SIGUSR2, SIG_IGN); /* not used */ // 蹇界暐 SIGUSR2 淇″彿 /* * Reset some signals that are accepted by postmaster but not here */ - (void)gspqsignal(SIGCHLD, SIG_DFL); - (void)gspqsignal(SIGTTIN, SIG_DFL); - (void)gspqsignal(SIGTTOU, SIG_DFL); - (void)gspqsignal(SIGCONT, SIG_DFL); - (void)gspqsignal(SIGWINCH, SIG_DFL); + // 鎭㈠鍚勪俊鍙峰鐞嗙▼搴忎负绯荤粺榛樿琛屼负 + (void)gspqsignal(SIGCHLD, SIG_DFL); // SIGCHLD 淇″彿鍦ㄥ瓙杩涚▼缁堟鎴栧仠姝㈡椂鍙戝嚭 + (void)gspqsignal(SIGTTIN, SIG_DFL); // SIGTTIN 淇″彿鍦ㄥ悗鍙拌繘绋嬪皾璇曚粠缁堢璇诲彇鏃跺彂鍑 + (void)gspqsignal(SIGTTOU, SIG_DFL); // SIGTTOU 淇″彿鍦ㄥ悗鍙拌繘绋嬪皾璇曞悜缁堢鍐欏叆鏃跺彂鍑 + (void)gspqsignal(SIGCONT, SIG_DFL); // SIGCONT 淇″彿鐢ㄤ簬缁х画宸插仠姝㈢殑杩涚▼ + (void)gspqsignal(SIGWINCH, SIG_DFL); // SIGWINCH 淇″彿鍦ㄧ粓绔獥鍙eぇ灏忓彉鍖栨椂鍙戝嚭 /* We allow SIGQUIT (quickdie) at all times */ - sigdelset(&t_thrd.libpq_cxt.BlockSig, SIGQUIT); + sigdelset(&t_thrd.libpq_cxt.BlockSig, SIGQUIT); // 鍏佽 SIGQUIT淇″彿鍦ㄤ换浣曟椂鍊欓兘鍙互瑙﹀彂 /* * Create a resource owner to keep track of our resources (not clear that * we need this, but may as well have one). */ + // 鍒涘缓 ResourceOwner 鐢ㄤ簬璺熻釜绠$悊璧勬簮 cbmwriter_resourceOwner = ResourceOwnerCreate(NULL, "CBM Writer", THREAD_GET_MEM_CXT_GROUP(MEMORY_CONTEXT_STORAGE)); t_thrd.utils_cxt.CurrentResourceOwner = cbmwriter_resourceOwner; @@ -109,6 +122,7 @@ void CBMWriterMain(void) * that we can reset the context during error recovery and thereby avoid * possible memory leaks. */ + // 鍒涘缓鍐呭瓨涓婁笅鏂囷紝浠ヤ究鍦ㄩ敊璇仮澶嶆湡闂撮噸缃笂涓嬫枃锛岄伩鍏嶅唴瀛樻硠婕 t_thrd.cbm_cxt.cbmwriter_context = AllocSetContextCreate(t_thrd.top_mem_cxt, "CBM Writer", ALLOCSET_DEFAULT_MINSIZE, @@ -124,24 +138,26 @@ void CBMWriterMain(void) /* * If an exception is encountered, processing resumes here. */ + // 鍙戠敓寮傚父璺宠浆鍒版澶 int curTryCounter; int* oldTryCounter = NULL; if (sigsetjmp(local_sigjmp_buf, 1) != 0) { gstrace_tryblock_exit(true, oldTryCounter); /* Since not using PG_TRY, must reset error stack by hand */ + // 鎵嬪姩閲嶇疆閿欒鏍 t_thrd.log_cxt.error_context_stack = NULL; t_thrd.log_cxt.call_stack = NULL; /* Prevent interrupts while cleaning up */ - HOLD_INTERRUPTS(); + HOLD_INTERRUPTS(); // 闃叉鍦ㄦ竻鐞嗘湡闂村彂鐢熶腑鏂 /* Report the error to the server log */ - EmitErrorReport(); + EmitErrorReport(); // 鎶ュ憡閿欒鍒版湇鍔″櫒鏃ュ織 /* release resource held by lsc */ - AtEOXact_SysDBCache(false); + AtEOXact_SysDBCache(false); // 閲婃斁鐢 lsc 鎸佹湁鐨勮祫婧 /* * These operations are really just a minimal subset of * AbortTransaction(). We don't have very many resources to worry @@ -200,7 +216,7 @@ void CBMWriterMain(void) int rc; /* Clear any already-pending wakeups */ - ResetLatch(&t_thrd.proc->procLatch); + ResetLatch(&t_thrd.proc->procLatch); // 娓呴櫎鎸傝捣鐨勫敜閱掕姹 pgstat_report_activity(STATE_RUNNING, NULL); @@ -209,12 +225,12 @@ void CBMWriterMain(void) */ if (t_thrd.cbm_cxt.got_SIGHUP) { t_thrd.cbm_cxt.got_SIGHUP = false; - ProcessConfigFile(PGC_SIGHUP); + ProcessConfigFile(PGC_SIGHUP); // 閰嶇疆鏂囦欢 u_sess->attr.attr_storage.CheckPointTimeout = ENABLE_INCRE_CKPT ? u_sess->attr.attr_storage.incrCheckPointTimeout : u_sess->attr.attr_storage.fullCheckPointTimeout; } - + // 濡傛灉鏀跺埌鍏抽棴璇锋眰锛屽垯閫鍑哄惊鐜 if (t_thrd.cbm_cxt.shutdown_requested) { g_instance.proc_base->cbmwriterLatch = NULL; /* Normal exit from the walwriter is here */ @@ -223,7 +239,8 @@ void CBMWriterMain(void) CBMFollowXlog(); - pgstat_report_activity(STATE_IDLE, NULL); + pgstat_report_activity(STATE_IDLE, NULL); // 鎶ュ憡娲诲姩鐘舵 + // 绛夊緟浜嬩欢鐨勫彂鐢燂紝鍖呮嫭淇″彿閲忚缃佽秴鏃躲乸ostmaster 姝讳骸 rc = WaitLatch(&t_thrd.proc->procLatch, WL_LATCH_SET | WL_TIMEOUT | WL_POSTMASTER_DEATH, (long)u_sess->attr.attr_storage.CheckPointTimeout * 1000); @@ -231,6 +248,7 @@ void CBMWriterMain(void) /* Emergency bailout if postmaster has died. This is to avoid the * necessity for manual cleanup of all postmaster children. */ + // postmaster 閫鍑烘椂搴旀ラ鍑轰互閬垮厤鎵嬪姩娓呯悊鎵鏈 postmaster 瀛愯繘绋 if (rc & WL_POSTMASTER_DEATH) { g_instance.proc_base->cbmwriterLatch = NULL; gs_thread_exit(1); @@ -248,11 +266,21 @@ void CBMWriterMain(void) * Some backend has bought the farm, * so we need to stop what we're doing and exit. */ +/* + * 鍔熻兘锛氬鐞咰BM Writer杩涚▼鐨勭揣鎬ラ鍑恒 + * + * 鍙傛暟锛 SIGNAL_ARGS 淇″彿澶勭悊鍑芥暟鐨勫弬鏁 + * 杩斿洖鍊硷細 鏃 + */ static void CBM_quickdie(SIGNAL_ARGS) { - g_instance.proc_base->cbmwriterLatch = NULL; - gs_signal_setmask(&t_thrd.libpq_cxt.BlockSig, NULL); + g_instance.proc_base->cbmwriterLatch = NULL; // 璁剧疆 cbmwriterLatch 涓 NULL锛岄槻姝㈠悗缁殑鍞ら啋 + gs_signal_setmask(&t_thrd.libpq_cxt.BlockSig, NULL); // 瑙i櫎淇″彿鐨勯樆濉炵姸鎬 + /* + 褰撳叡浜唴瀛樺彲鑳藉凡缁忓彈鍒版崯鍧忔垨鍑虹幇鍏朵粬涓ラ噸闂鏃讹紝cbmwriter杩涚▼浼氱珛鍗崇粓姝紝鑰屼笉浼氭墽琛屾甯哥殑娓呯悊鎿嶄綔鎴栬皟鐢╜proc_exit()`娉ㄥ唽鐨勫洖璋冨嚱鏁般 + 纭繚杩呴熺粓姝㈣繘绋嬶紝浠ラ槻姝㈣繘涓姝ョ殑鏁版嵁鎹熷潖鎴栧叾浠栨綔鍦ㄧ殑椋庨櫓銆 + */ /* * We DO NOT want to run proc_exit() callbacks -- we're here because * shared memory may be corrupted, so we don't want to try to clean up our @@ -263,6 +291,10 @@ static void CBM_quickdie(SIGNAL_ARGS) */ on_exit_reset(); + /* + 浠xit(2)閫鍑猴紝寮哄埗 postmaster 杩涘叆绯荤粺澶嶄綅寰幆 + 纭繚濡傛灉鏈変汉涓嶅皬蹇冪粓姝簡cbmwriter杩涚▼锛岀郴缁熶細璁や负鍙戠敓浜嗕弗閲嶉棶棰橈紝閲囧彇棰濆鎺柦纭繚绯荤粺绋冲畾鎬с + */ /* * Note we do exit(2) not exit(0). This is to force the postmaster into a * system reset cycle if some idiot DBA sends a manual SIGQUIT to a random @@ -275,37 +307,64 @@ static void CBM_quickdie(SIGNAL_ARGS) } /* SIGHUP: set flag to re-read config file at next convenient time */ +/* + * 鍔熻兘锛歋IGHUP 淇″彿澶勭悊绋嬪簭锛屽湪涓嬩竴涓柟渚跨殑鏃堕棿閲嶆柊璇诲彇閰嶇疆鏂囦欢 + * + * 鍙傛暟: + * SIGNAL_ARGS: 淇″彿澶勭悊绋嬪簭鐨勫弬鏁板垪琛紝鎻愪緵鍏充簬瑙﹀彂淇″彿鐨勪笂涓嬫枃淇℃伅 + * + * 杩斿洖鍊: + * 鏃 + */ static void CBMSigHupHandler(SIGNAL_ARGS) { - int save_errno = errno; + int save_errno = errno; // 淇濆瓨褰撳墠鐨勯敊璇爜 - t_thrd.cbm_cxt.got_SIGHUP = true; + t_thrd.cbm_cxt.got_SIGHUP = true; // 璁剧疆鏍囧織浠ユ寚绀洪渶瑕佸湪涓嬩竴涓柟渚跨殑鏃堕棿閲嶆柊璇诲彇閰嶇疆鏂囦欢 if (t_thrd.proc) - SetLatch(&t_thrd.proc->procLatch); + SetLatch(&t_thrd.proc->procLatch); // 濡傛灉杩涚▼瀛樺湪锛屽垯璁剧疆杩涚▼鐨凩atch浠ュ敜閱掕繘绋 - errno = save_errno; + errno = save_errno; // 鎭㈠涔嬪墠淇濆瓨鐨勯敊璇爜 } /* SIGTERM: set flag to exit normally */ +/* + * 鍔熻兘锛歋IGTERM 淇″彿澶勭悊绋嬪簭锛岃姹傛甯搁鍑 + * + * 鍙傛暟: + * SIGNAL_ARGS: 淇″彿澶勭悊绋嬪簭鐨勫弬鏁板垪琛紝鎻愪緵鍏充簬瑙﹀彂淇″彿鐨勪笂涓嬫枃淇℃伅 + * + * 杩斿洖鍊: + * 鏃 + */ static void CBMShutdownHandler(SIGNAL_ARGS) { - int save_errno = errno; + int save_errno = errno; // 淇濆瓨褰撳墠鐨勯敊璇爜 - t_thrd.cbm_cxt.shutdown_requested = true; + t_thrd.cbm_cxt.shutdown_requested = true; // 璁剧疆鏍囧織浠ユ寚绀洪渶瑕佹甯搁鍑 if (t_thrd.proc) - SetLatch(&t_thrd.proc->procLatch); + SetLatch(&t_thrd.proc->procLatch); // 濡傛灉杩涚▼瀛樺湪锛屽垯璁剧疆杩涚▼鐨凩atch浠ュ敜閱掕繘绋 - errno = save_errno; + errno = save_errno; // 鎭㈠涔嬪墠淇濆瓨鐨勯敊璇爜 } /* SIGUSR1: used for latch wakeups */ +/* + * 鍔熻兘锛歋IGUSR1 淇″彿澶勭悊绋嬪簭锛岀敤浜庡鐞哃atch鍞ら啋 + * + * 鍙傛暟: + * SIGNAL_ARGS: 淇″彿澶勭悊绋嬪簭鐨勫弬鏁板垪琛紝鎻愪緵鍏充簬瑙﹀彂淇″彿鐨勪笂涓嬫枃淇℃伅 + * + * 杩斿洖鍊: + * 鏃 + */ static void CBMwriter_sigusr1_handler(SIGNAL_ARGS) { - int save_errno = errno; + int save_errno = errno; // 淇濆瓨褰撳墠鐨勯敊璇爜 - latch_sigusr1_handler(); + latch_sigusr1_handler(); // 澶勭悊SIGUSR1淇″彿锛屽敜閱掕繘绋 - errno = save_errno; + errno = save_errno; // 鎭㈠涔嬪墠淇濆瓨鐨勯敊璇爜 } diff --git a/src/gausskernel/process/postmaster/checkpointer.cpp b/src/gausskernel/process/postmaster/checkpointer.cpp index c45b702ee..61b1b1f3a 100755 --- a/src/gausskernel/process/postmaster/checkpointer.cpp +++ b/src/gausskernel/process/postmaster/checkpointer.cpp @@ -115,32 +115,35 @@ * ---------- */ +// 鏁版嵁缁撴瀯锛岀敤浜庡湪鍏变韩鍐呭瓨涓瓨鍌ㄤ笌 checkpointer 杩涚▼鐩稿叧鐨勬暟鎹 typedef struct CheckpointerShmemStruct { - ThreadId checkpointer_pid; /* PID (0 if not started) */ - slock_t ckpt_lck; /* protects all the ckpt_* fields */ - int64 fsync_start; - int64 fsync_done; - int64 fsync_request; + ThreadId checkpointer_pid; /* PID (0 if not started) */ // 瀛樺偍 checkpointer 杩涚▼鐨勭嚎绋嬫爣璇嗙 + slock_t ckpt_lck; /* protects all the ckpt_* fields */ // 鐢ㄤ簬淇濇姢鎵鏈変笌妫鏌ョ偣澶勭悊鐩稿叧瀛楁鐨勫叡浜攣 + int64 fsync_start; // 璁板綍鏂囦欢鍚屾锛坒sync锛夌殑寮濮嬫椂闂 + int64 fsync_done; // 璁板綍鏂囦欢鍚屾锛坒sync锛夌殑缁撴潫鏃堕棿 + int64 fsync_request; // 璁板綍鏂囦欢鍚屾锛坒sync锛夌殑璇锋眰鏃堕棿 - int ckpt_started; /* advances when checkpoint starts */ - int ckpt_done; /* advances when checkpoint done */ - int ckpt_failed; /* advances when checkpoint fails */ + // 璁板綍妫鏌ョ偣鐨勭姸鎬 + int ckpt_started; /* advances when checkpoint starts */ // 鍦ㄦ鏌ョ偣寮濮嬫椂閫掑 + int ckpt_done; /* advances when checkpoint done */ // 鍦ㄦ鏌ョ偣瀹屾垚鏃堕掑 + int ckpt_failed; /* advances when checkpoint fails */ // 鍦ㄦ鏌ョ偣澶辫触鏃堕掑 int ckpt_flags; /* checkpoint flags, as defined in xlog.h */ - uint32 num_backend_writes; /* counts user backend buffer writes */ - uint32 num_backend_fsync; /* counts user backend fsync calls */ + uint32 num_backend_writes; /* counts user backend buffer writes */ // 璁℃暟鐢ㄦ埛鍚庣杩涚▼鎵ц鐨勭紦鍐插尯鍐欏叆鐨勬暟閲 + uint32 num_backend_fsync; /* counts user backend fsync calls */ // 璁℃暟鐢ㄦ埛鍚庣杩涚▼鑷鎵ц鐨勬枃浠跺悓姝ヨ皟鐢ㄧ殑鏁伴噺 - int num_requests; /* current # of requests */ - int max_requests; /* allocated array size */ - CheckpointerRequest requests[1]; /* VARIABLE LENGTH ARRAY */ + int num_requests; /* current # of requests */ // 褰撳墠鎸傝捣鐨勬鏌ョ偣璇锋眰鐨勬暟閲 + int max_requests; /* allocated array size */ // 宸插垎閰嶇殑妫鏌ョ偣璇锋眰鏁扮粍鐨勬渶澶уぇ灏 + CheckpointerRequest requests[1]; /* VARIABLE LENGTH ARRAY */ // 瀛樺偍妫鏌ョ偣璇锋眰鐨勪俊鎭 } CheckpointerShmemStruct; #ifdef ENABLE_MOT +// 缁撴瀯浣擄紝鍚敤MOT锛圡emSQL寮曟搸锛夋椂锛岀敤浜庡瓨鍌ㄦ鏌ョ偣鍥炶皟鍑芥暟鐨勪俊鎭 typedef struct CheckpointCallbackItem { - struct CheckpointCallbackItem* next; - CheckpointCallback callback; - void* arg; + struct CheckpointCallbackItem* next; // 鎸囧悜涓嬩竴涓 CheckpointCallbackItem 缁撴瀯浣撶殑鎸囬拡锛岀敤浜庡垱寤洪摼琛 + CheckpointCallback callback; // 鍥炶皟鍑芥暟鎸囬拡锛屾寚鍚戜竴涓壒瀹氱殑鍑芥暟锛屽湪妫鏌ョ偣鎿嶄綔鏈熼棿琚皟鐢紝鐢ㄤ簬鍦ㄦ鏌ョ偣鍓嶅悗鎵ц涓浜涜嚜瀹氫箟鎿嶄綔 + void* arg; // 浼犻掔粰鍥炶皟鍑芥暟鐨勯澶栧弬鏁帮紝鍥炶皟鍑芥暟鍙互浣跨敤杩欎釜鍙傛暟鏉ヨ闂拰鎿嶄綔鐗瑰畾鐨勬暟鎹垨涓婁笅鏂囦俊鎭 } CheckpointCallbackItem; #endif @@ -169,14 +172,21 @@ static void ReqShutdownHandler(SIGNAL_ARGS); * This is invoked from AuxiliaryProcessMain, which has already created the * basic execution environment, but not enabled signals yet. */ +/* + * 鍔熻兘锛歝heckpointer杩涚▼鐨勪富瑕佸叆鍙g偣锛岃礋璐g鐞嗘鏌ョ偣杩涚▼鐨勬牳蹇冮昏緫锛岃礋璐e鐞嗘暟鎹簱绯荤粺鐨勬鏌ョ偣鎿嶄綔 + * + * 鍙傛暟: 鏃 + * + * 杩斿洖鍊: 鏃 + */ void CheckpointerMain(void) { - sigjmp_buf local_sigjmp_buf; - MemoryContext checkpointer_context; - bool bgwriter_first_startup = true; - + sigjmp_buf local_sigjmp_buf; // 鐢ㄤ簬璺宠浆鍥炶繖閲岀殑淇″彿澶勭悊 + MemoryContext checkpointer_context; // 妫鏌ョ偣杩涚▼鐨勫唴瀛樹笂涓嬫枃 + bool bgwriter_first_startup = true; // 鏍囪鏄惁鏄悗鍙板啓鍏ヨ繘绋嬬殑绗竴娆″惎鍔 + // 璁剧疆checkpointer杩涚▼鐨凱ID t_thrd.checkpoint_cxt.CheckpointerShmem->checkpointer_pid = t_thrd.proc_cxt.MyProcPid; - + // 鏍规嵁鏄惁鍚敤澧為噺妫鏌ョ偣鏉ヨ缃鏌ョ偣瓒呮椂鏃堕棿 u_sess->attr.attr_storage.CheckPointTimeout = ENABLE_INCRE_CKPT ? u_sess->attr.attr_storage.incrCheckPointTimeout : u_sess->attr.attr_storage.fullCheckPointTimeout; @@ -191,15 +201,15 @@ void CheckpointerMain(void) * want to wait for the backends to exit, whereupon the postmaster will * tell us it's okay to shut down (via SIGUSR2). */ - (void)gspqsignal(SIGHUP, ChkptSigHupHandler); /* set flag to read config + (void)gspqsignal(SIGHUP, ChkptSigHupHandler); /* set flag to read config // 鐢ㄤ簬閲嶆柊鍔犺浇閰嶇疆鏂囦欢 * file */ - (void)gspqsignal(SIGINT, ReqCheckpointHandler); /* request checkpoint */ - (void)gspqsignal(SIGTERM, SIG_IGN); /* ignore SIGTERM */ - (void)gspqsignal(SIGQUIT, chkpt_quickdie); /* hard crash time */ - (void)gspqsignal(SIGALRM, SIG_IGN); - (void)gspqsignal(SIGPIPE, SIG_IGN); - (void)gspqsignal(SIGUSR1, chkpt_sigusr1_handler); - (void)gspqsignal(SIGUSR2, ReqShutdownHandler); /* request shutdown */ + (void)gspqsignal(SIGINT, ReqCheckpointHandler); /* request checkpoint */ // 璇锋眰鎵ц妫鏌ョ偣 + (void)gspqsignal(SIGTERM, SIG_IGN); /* ignore SIGTERM */ // 蹇界暐SIGTERM + (void)gspqsignal(SIGQUIT, chkpt_quickdie); /* hard crash time */ // 寮哄埗缁堟 + (void)gspqsignal(SIGALRM, SIG_IGN); // 蹇界暐SIGALRM淇″彿 + (void)gspqsignal(SIGPIPE, SIG_IGN); // 蹇界暐SIGPIPE淇″彿 + (void)gspqsignal(SIGUSR1, chkpt_sigusr1_handler); // 璁剧疆SIGUSR1淇″彿澶勭悊绋嬪簭涓篶hkpt_sigusr1_handler + (void)gspqsignal(SIGUSR2, ReqShutdownHandler); /* request shutdown */ // 璇锋眰鍏抽棴 /* * Reset some signals that are accepted by postmaster but not here @@ -211,11 +221,12 @@ void CheckpointerMain(void) (void)gspqsignal(SIGWINCH, SIG_DFL); /* We allow SIGQUIT (quickdie) at all times */ - sigdelset(&t_thrd.libpq_cxt.BlockSig, SIGQUIT); + sigdelset(&t_thrd.libpq_cxt.BlockSig, SIGQUIT); // 鍏佽闅忔椂鍝嶅簲 SIGQUIT 淇″彿锛堢敤浜庡揩閫熺粓姝㈣繘绋嬶級 /* * Initialize so that first time-driven event happens at the correct time. */ + // 鍒濆鍖栨椂闂寸浉鍏崇殑鍙橀噺 t_thrd.checkpoint_cxt.last_checkpoint_time = t_thrd.checkpoint_cxt.last_truncate_log_time = t_thrd.checkpoint_cxt.last_xlog_switch_time = (pg_time_t)time(NULL); @@ -223,6 +234,7 @@ void CheckpointerMain(void) * Create a resource owner to keep track of our resources (currently only * buffer pins). */ + // 鍒涘缓璧勬簮鎵鏈夎咃紝鐢ㄤ簬璺熻釜杩涚▼鎵浣跨敤鐨勮祫婧 t_thrd.utils_cxt.CurrentResourceOwner = ResourceOwnerCreate(NULL, "Checkpointer", THREAD_GET_MEM_CXT_GROUP(MEMORY_CONTEXT_STORAGE)); @@ -232,6 +244,7 @@ void CheckpointerMain(void) * possible memory leaks. Formerly this code just ran in * t_thrd.top_mem_cxt, but resetting that would be a really bad idea. */ + // 鍒涘缓鍐呭瓨涓婁笅鏂囷紝鐢ㄤ簬鎵ц杩涚▼鐨勬墍鏈夊伐浣溿備互渚垮湪閿欒鎭㈠鏈熼棿閲嶇疆鍐呭瓨涓婁笅鏂囷紝閬垮厤鍙兘鐨勫唴瀛樻硠婕 checkpointer_context = AllocSetContextCreate(t_thrd.top_mem_cxt, "Checkpointer", ALLOCSET_DEFAULT_MINSIZE, @@ -244,9 +257,10 @@ void CheckpointerMain(void) * * See notes in postgres.c about the design of this coding. */ + // 閬囧埌寮傚父锛屼粠杩欓噷缁х画鎵ц int curTryCounter; int* oldTryCounter = NULL; - if (sigsetjmp(local_sigjmp_buf, 1) != 0) { + if (sigsetjmp(local_sigjmp_buf, 1) != 0) { // 濡傛灉寮傚父琚姏鍑 gstrace_tryblock_exit(true, oldTryCounter); /* * Close all open files after any error. This is helpful on Windows, @@ -255,69 +269,69 @@ void CheckpointerMain(void) */ /* Since not using PG_TRY, must reset error stack by hand */ - t_thrd.log_cxt.error_context_stack = NULL; + t_thrd.log_cxt.error_context_stack = NULL; // 鎵嬪姩閲嶇疆閿欒鏍 - t_thrd.log_cxt.call_stack = NULL; + t_thrd.log_cxt.call_stack = NULL; // 娓呴櫎鍑芥暟璋冪敤鍫嗘爤淇℃伅 /* Prevent interrupts while cleaning up */ - HOLD_INTERRUPTS(); + HOLD_INTERRUPTS(); //闃绘涓柇锛屼互纭繚鍦ㄦ竻鐞嗘湡闂翠笉浼氳涓柇 /* Report the error to the server log */ - EmitErrorReport(); + EmitErrorReport(); // 灏嗛敊璇俊鎭姤鍛婂埌鏈嶅姟鍣ㄦ棩蹇椾腑 /* abort async io, must before LWlock release */ - AbortAsyncListIO(); + AbortAsyncListIO(); // 涓寮傛I/O鎿嶄綔 #ifdef ENABLE_MOT /* cleanups any leftovers in other storage engines (release MOT snapshot lock if taken) */ - CallCheckpointCallback(EVENT_CHECKPOINT_ABORT, 0); + CallCheckpointCallback(EVENT_CHECKPOINT_ABORT, 0); // 娓呯悊鍏朵粬瀛樺偍寮曟搸鐨勯仐鐣欐暟鎹 #endif /* release resource held by lsc */ - AtEOXact_SysDBCache(false); + AtEOXact_SysDBCache(false); // 閲婃斁浜嗙敱 lsc鎸佹湁鐨勮祫婧 /* * These operations are really just a minimal subset of * AbortTransaction(). We don't have very many resources to worry * about in checkpointer, but we do have LWLocks, buffers, and temp * files. */ - LWLockReleaseAll(); - pgstat_report_waitevent(WAIT_EVENT_END); - AbortBufferIO(); - UnlockBuffers(); + LWLockReleaseAll(); // 閲婃斁褰撳墠杩涚▼鎸佹湁鐨勬墍鏈夎交閲忕骇閿 + pgstat_report_waitevent(WAIT_EVENT_END); // 鎶ュ憡绛夊緟浜嬩欢锛岀敤浜庤窡韪瓑寰呬簨浠剁殑缁熻淇℃伅 + AbortBufferIO(); // 涓姝e湪杩涜鐨勭紦鍐插尯I/O 鎿嶄綔锛屼互纭繚鍦ㄥ紓甯告儏鍐典笅涓嶄細缁х画杩涜鏈畬鎴愮殑 I/O 鎿嶄綔 + UnlockBuffers(); // 瑙i攣鎵鏈夌殑缂撳啿鍖 /* buffer pins are released here: */ - ResourceOwnerRelease(t_thrd.utils_cxt.CurrentResourceOwner, RESOURCE_RELEASE_BEFORE_LOCKS, false, true); + ResourceOwnerRelease(t_thrd.utils_cxt.CurrentResourceOwner, RESOURCE_RELEASE_BEFORE_LOCKS, false, true); // 閲婃斁璧勬簮鎵鏈夎呮寔鏈夌殑璧勬簮 /* we needn't bother with the other ResourceOwnerRelease phases */ - AtEOXact_Buffers(false); - AtEOXact_SMgr(); - AtEOXact_Files(); - AtEOXact_HashTables(false); + AtEOXact_Buffers(false); // 鎵ц涓庣紦鍐插尯鐩稿叧鐨勪簨鍔$粨鏉熸搷浣滐紝涓嶅簲璇ュ己鍒跺埛鏂拌剰椤 + AtEOXact_SMgr(); // 鎵ц涓庡瓨鍌ㄧ鐞嗗櫒鐩稿叧鐨勪簨鍔$粨鏉熸搷浣 + AtEOXact_Files(); // 鎵ц涓庢枃浠舵搷浣滅浉鍏崇殑浜嬪姟缁撴潫鎿嶄綔 + AtEOXact_HashTables(false); // 鎵ц涓庡搱甯岃〃鐩稿叧鐨勪簨鍔$粨鏉熸搷浣滐紝涓嶆竻绌哄搱甯岃〃 /* Warn any waiting backends that the checkpoint failed. */ - if (t_thrd.checkpoint_cxt.ckpt_active) { + if (t_thrd.checkpoint_cxt.ckpt_active) { // 濡傛灉妫鏌ョ偣鎿嶄綔姝e湪杩涜涓 /* use volatile pointer to prevent code rearrangement */ volatile CheckpointerShmemStruct* cps = t_thrd.checkpoint_cxt.CheckpointerShmem; - SpinLockAcquire(&cps->ckpt_lck); - cps->ckpt_failed++; - cps->ckpt_done = cps->ckpt_started; - SpinLockRelease(&cps->ckpt_lck); + SpinLockAcquire(&cps->ckpt_lck); //鑾峰彇閿 + cps->ckpt_failed++; // 閫掑锛岃〃绀烘鏌ョ偣澶辫触 + cps->ckpt_done = cps->ckpt_started; // 灏 ckpt_done 璁剧疆涓 ckpt_started + SpinLockRelease(&cps->ckpt_lck); // 閲婃斁閿 - t_thrd.checkpoint_cxt.ckpt_active = false; + t_thrd.checkpoint_cxt.ckpt_active = false; // 琛ㄧず妫鏌ョ偣鎿嶄綔涓嶅啀娲昏穬 } /* * Now return to normal top-level context and clear ErrorContext for * next time. */ - MemoryContextSwitchTo(checkpointer_context); - FlushErrorState(); + MemoryContextSwitchTo(checkpointer_context); // 灏嗗唴瀛樹笂涓嬫枃鍒囨崲鍥炴甯哥殑椤剁骇涓婁笅鏂 + FlushErrorState(); // 娓呴櫎閿欒涓婁笅鏂囷紝浠ュ噯澶囧鐞嗕笅涓涓紓甯 /* Flush any leaked data in the top-level context */ - MemoryContextResetAndDeleteChildren(checkpointer_context); + MemoryContextResetAndDeleteChildren(checkpointer_context); // 鍒锋柊椤剁骇涓婁笅鏂囦腑鍙兘瀛樺湪鐨勬硠婕忔暟鎹 /* Now we can allow interrupts again */ - RESUME_INTERRUPTS(); + RESUME_INTERRUPTS(); // 閲嶆柊鍏佽涓柇澶勭悊 /* * Sleep at least 1 second after any error. A write error is likely @@ -326,7 +340,7 @@ void CheckpointerMain(void) */ pg_usleep(1000000L); } - oldTryCounter = gstrace_tryblock_entry(&curTryCounter); + oldTryCounter = gstrace_tryblock_entry(&curTryCounter); // 璁板綍浜嗚繘鍏ュ紓甯稿鐞嗗潡鐨勪俊鎭 /* We can now handle ereport(ERROR) */ t_thrd.log_cxt.PG_exception_stack = &local_sigjmp_buf; @@ -334,13 +348,14 @@ void CheckpointerMain(void) /* * Unblock signals (they were blocked when the postmaster forked us) */ + // 瑙i櫎淇″彿鐨勯樆濉 gs_signal_setmask(&t_thrd.libpq_cxt.UnBlockSig, NULL); (void)gs_signal_unblock_sigusr2(); /* * Use the recovery target timeline ID during recovery */ - if (RecoveryInProgress()) + if (RecoveryInProgress()) // 濡傛灉鍑轰簬鎭㈠妯″紡涓 t_thrd.xlog_cxt.ThisTimeLineID = GetRecoveryTargetTLI(); /* @@ -354,7 +369,7 @@ void CheckpointerMain(void) * sleeping. */ g_instance.proc_base->checkpointerLatch = &t_thrd.proc->procLatch; - + // 鎶ュ憡妫鏌ョ偣杩涚▼鐨勫簲鐢ㄧ▼搴忓悕绉板拰娲诲姩鐘舵侊紝鐢ㄤ簬鎬ц兘鐩戣鍜岀粺璁 pgstat_report_appname("CheckPointer"); pgstat_report_activity(STATE_IDLE, NULL); @@ -362,27 +377,28 @@ void CheckpointerMain(void) * Loop forever */ for (;;) { - bool do_checkpoint = false; - bool do_dirty_flush = false; - int flags = 0; - pg_time_t now; - int elapsed_secs; - int cur_timeout; - int rc; + bool do_checkpoint = false; // 琛ㄧず鏄惁闇瑕佹墽琛屾鏌ョ偣 + bool do_dirty_flush = false; // 琛ㄧず鏄惁闇瑕佹墽琛岃剰椤靛埛鏂 + int flags = 0; // 瀛樺偍妫鏌ョ偣鐨勬爣蹇 + pg_time_t now; // 璁板綍褰撳墠鏃堕棿 + int elapsed_secs; // 璁板綍璺濈涓婃妫鏌ョ偣宸茬粡杩囧幓鐨勭鏁 + int cur_timeout; // 璁板綍褰撳墠绛夊緟鐨勮秴鏃舵椂闂 + int rc; // 瀛樺偍绛夊緟缁撴灉鐨勮繑鍥炲 /* Clear any already-pending wakeups */ - ResetLatch(&t_thrd.proc->procLatch); + ResetLatch(&t_thrd.proc->procLatch); // 娓呴櫎褰撳墠杩涚▼鐨勪簨浠舵爣蹇楋紝浠ヤ究绛夊緟鏂颁簨浠 - pgstat_report_activity(STATE_RUNNING, NULL); + pgstat_report_activity(STATE_RUNNING, NULL); // 鎶ュ憡褰撳墠妫鏌ョ偣杩涚▼鐨勬椿鍔ㄧ姸鎬侊紝鐢ㄤ簬缁熻鍜岃瘖鏂殑淇℃伅 /* * Process any requests or signals received recently. */ - CkptAbsorbFsyncRequests(); + CkptAbsorbFsyncRequests(); // 澶勭悊鏈杩戞帴鏀跺埌鐨勬枃浠跺悓姝ヨ姹 - if (t_thrd.checkpoint_cxt.got_SIGHUP) { - t_thrd.checkpoint_cxt.got_SIGHUP = false; - ProcessConfigFile(PGC_SIGHUP); + if (t_thrd.checkpoint_cxt.got_SIGHUP) { // 濡傛灉鏀跺埌浜哠IGHUP淇″彿锛岃〃绀洪厤缃枃浠跺凡鏇存敼锛岄渶瑕侀噸鏂板姞杞介厤缃 + t_thrd.checkpoint_cxt.got_SIGHUP = false; // 琛ㄧず宸茬粡澶勭悊浜 SIGHUP 淇″彿 + ProcessConfigFile(PGC_SIGHUP); // 閲嶆柊鍔犺浇閰嶇疆鏂囦欢 + // 璁剧疆鍙傛暟 澧為噺妫鏌ョ偣瓒呮椂鏃堕棿 鎴 瀹屾暣妫鏌ョ偣瓒呮椂鏃堕棿 u_sess->attr.attr_storage.CheckPointTimeout = ENABLE_INCRE_CKPT ? u_sess->attr.attr_storage.incrCheckPointTimeout : u_sess->attr.attr_storage.fullCheckPointTimeout; @@ -398,20 +414,21 @@ void CheckpointerMain(void) * responsible for updating the shared memory copy if the * parameter setting changes because of SIGHUP. */ - UpdateSharedMemoryConfig(); + UpdateSharedMemoryConfig(); // 鏇存柊鍏变韩鍐呭瓨涓殑閰嶇疆鍙傛暟 } - + // 妫鏌ユ槸鍚︽槸鏁版嵁搴撶殑棣栨鍚姩涓斾笉澶勪簬鎭㈠鐘舵 if (bgwriter_first_startup && !RecoveryInProgress()) { - t_thrd.checkpoint_cxt.checkpoint_requested = true; - flags = CHECKPOINT_IMMEDIATE; - bgwriter_first_startup = false; + t_thrd.checkpoint_cxt.checkpoint_requested = true; // 琛ㄧず闇瑕佹墽琛屾鏌ョ偣 + flags = CHECKPOINT_IMMEDIATE; // 琛ㄧず鎵ц涓涓珛鍗虫鏌ョ偣 + bgwriter_first_startup = false; // 琛ㄧず涓嶅啀鏄娆″惎鍔 + //璁板綍鏃ュ織娑堟伅锛屾寚绀烘暟鎹簱棣栨鍚姩骞跺畬鎴愭仮澶 ereport(LOG, (errmsg("database first startup and recovery finish,so do checkpointer"))); } if (t_thrd.checkpoint_cxt.checkpoint_requested) { - t_thrd.checkpoint_cxt.checkpoint_requested = false; - do_checkpoint = true; - u_sess->stat_cxt.BgWriterStats->m_requested_checkpoints++; + t_thrd.checkpoint_cxt.checkpoint_requested = false; // 琛ㄧず宸茬粡澶勭悊浜嗘鏌ョ偣璇锋眰 + do_checkpoint = true; // 琛ㄧず闇瑕佹墽琛屾鏌ョ偣 + u_sess->stat_cxt.BgWriterStats->m_requested_checkpoints++; // 澧炲姞璇锋眰妫鏌ョ偣璁℃暟鍣 } if (t_thrd.checkpoint_cxt.shutdown_requested) { @@ -419,12 +436,14 @@ void CheckpointerMain(void) * From here on, elog(ERROR) should end with exit(1), not send * control back to the sigsetjmp block above */ + // 琛ㄧず濡傛灉鍑虹幇閿欒锛屽垯缁堟杩涚▼鑰屼笉鏄户缁鐞 u_sess->attr.attr_common.ExitOnAnyError = true; /* Close down the database */ + // 姝e父閫鍑轰箣鍓嶆墽琛屽叧闂暟鎹簱 ShutdownXLOG(0, 0); /* Normal exit from the checkpointer is here */ - proc_exit(0); /* done */ + proc_exit(0); /* done */ // 姝e父閫鍑烘鏌ョ偣杩涚▼ } /* @@ -435,13 +454,14 @@ void CheckpointerMain(void) */ now = (pg_time_t)time(NULL); elapsed_secs = now - t_thrd.checkpoint_cxt.last_checkpoint_time; - + // 妫鏌ヨ嚜涓婃妫鏌ョ偣浠ユ潵鏄惁宸茬粡杩囧幓浜嗚冻澶熼暱鐨勬椂闂 if (elapsed_secs >= u_sess->attr.attr_storage.CheckPointTimeout) { - if (!do_checkpoint) + if (!do_checkpoint) // 濡傛灉鍦ㄥ閮ㄦ病鏈夎姹傛鏌ョ偣 + // 澧炲姞缁熻淇℃伅璁℃暟鍣 琛ㄧず宸叉墽琛屼簡涓涓熀浜庢椂闂寸殑妫鏌ョ偣 u_sess->stat_cxt.BgWriterStats->m_timed_checkpoints++; - do_checkpoint = true; - flags |= CHECKPOINT_CAUSE_TIME; + do_checkpoint = true; // 琛ㄧず闇瑕佹墽琛屾鏌ョ偣 + flags |= CHECKPOINT_CAUSE_TIME; // 琛ㄧず妫鏌ョ偣鐨勮Е鍙戝師鍥犳槸鏃堕棿瓒呮椂 } /* @@ -466,11 +486,11 @@ void CheckpointerMain(void) * checkpoint we should perform, and increase the started-counter * to acknowledge that we've started a new checkpoint. */ - SpinLockAcquire(&cps->ckpt_lck); + SpinLockAcquire(&cps->ckpt_lck); // 鑾峰彇鑷棆閿 flags |= cps->ckpt_flags; cps->ckpt_flags = 0; - cps->ckpt_started++; - SpinLockRelease(&cps->ckpt_lck); + cps->ckpt_started++; // 璁板綍浜嗗凡缁忓紑濮嬬殑妫鏌ョ偣鏁伴噺 + SpinLockRelease(&cps->ckpt_lck); // 閲婃斁鑷棆閿 /* * The end-of-recovery checkpoint is a real checkpoint that's @@ -487,8 +507,10 @@ void CheckpointerMain(void) * implementation will not generate warnings caused by * CheckPointTimeout < CheckPointWarning. */ + // 濡傛灉涓嶆槸閲嶅惎鐐逛笖瑙﹀彂鍘熷洜鏄 XLOG 璁板綍锛屽苟涓旇窛绂讳笂娆℃鏌ョ偣鏃堕棿涓嶈冻 if (!do_restartpoint && (flags & CHECKPOINT_CAUSE_XLOG) && elapsed_secs < u_sess->attr.attr_storage.CheckPointWarning) + // 鍙戝嚭璀﹀憡娑堟伅 ereport(LOG, (errmsg_plural("checkpoints are occurring too frequently (%d second apart)", "checkpoints are occurring too frequently (%d seconds apart)", @@ -500,38 +522,42 @@ void CheckpointerMain(void) * Initialize checkpointer-private variables used during * checkpoint */ - t_thrd.checkpoint_cxt.ckpt_active = true; + t_thrd.checkpoint_cxt.ckpt_active = true; // 琛ㄧず妫鏌ョ偣杩涚▼姝e湪鎵ц妫鏌ョ偣鎿嶄綔 - if (!do_restartpoint) - t_thrd.checkpoint_cxt.ckpt_start_recptr = GetInsertRecPtr(); + if (!do_restartpoint) // 妫鏌ユ槸鍚︽鍦ㄦ墽琛岄噸鍚偣 + t_thrd.checkpoint_cxt.ckpt_start_recptr = GetInsertRecPtr(); // 鑾峰彇骞惰褰曞綋鍓嶆彃鍏ヨ褰曟寚閽 - t_thrd.checkpoint_cxt.ckpt_start_time = now; - t_thrd.checkpoint_cxt.ckpt_cached_elapsed = 0; + t_thrd.checkpoint_cxt.ckpt_start_time = now; // 璁板綍妫鏌ョ偣鎿嶄綔鐨勫紑濮嬫椂闂 + t_thrd.checkpoint_cxt.ckpt_cached_elapsed = 0; // 璁板綍妫鏌ョ偣鎿嶄綔宸茬粡鎵ц鐨勬椂闂 if (flags & CHECKPOINT_FLUSH_DIRTY) { - do_dirty_flush = true; + do_dirty_flush = true; // 琛ㄧず闇瑕佹墽琛岃剰椤靛埛鏂版搷浣 } /* * Do a normal checkpoint/restartpoint. */ - if (do_dirty_flush) { + if (do_dirty_flush) { // 濡傛灉闇瑕佹墽琛岃剰椤靛埛鏂版搷浣 + // 鐢熸垚鏃ュ織娑堟伅锛屾寚绀烘鍦ㄦ墽琛屾枃浠朵慨澶嶏紝闇瑕佸埛鏂版墍鏈夎剰椤 ereport(LOG, (errmsg("[file repair] request checkpoint, flush all dirty page."))); - Assert(RecoveryInProgress()); - if (ENABLE_INCRE_CKPT) { + Assert(RecoveryInProgress()); // 鏂█褰撳墠绯荤粺澶勪簬宕╂簝鎭㈠鐘舵 + if (ENABLE_INCRE_CKPT) { // 妫鏌ユ槸鍚﹀惎鐢ㄤ簡澧為噺妫鏌ョ偣 + // 璁剧疆鑴忛〉闃熷熬 g_instance.ckpt_cxt_ctl->full_ckpt_expected_flush_loc = get_dirty_page_queue_tail(); - pg_memory_barrier(); - if (get_dirty_page_num() > 0) { - g_instance.ckpt_cxt_ctl->flush_all_dirty_page = true; + pg_memory_barrier(); // 鎵ц鍐呭瓨灞忛殰鎿嶄綔锛岀‘淇濆鍐呭瓨鐨勪慨鏀瑰湪澶氱嚎绋嬬幆澧冧笅姝g‘鍚屾 + if (get_dirty_page_num() > 0) { // 妫鏌ユ槸鍚﹀瓨鍦ㄨ剰椤 + g_instance.ckpt_cxt_ctl->flush_all_dirty_page = true; // 琛ㄧず闇瑕佸埛鏂版墍鏈夎剰椤点 + // 鐢熸垚鏃ュ織娑堟伅锛屾寚绀洪渶瑕佸埛鏂颁竴瀹氭暟閲忕殑鑴忛〉 ereport(LOG, (errmsg("[file repair] need flush %ld pages.", get_dirty_page_num()))); - CheckPointBuffers(flags, true); + CheckPointBuffers(flags, true); // 鎵ц妫鏌ョ偣鎿嶄綔锛屽皢鑴忛〉鍒锋柊鍒扮鐩樹笂 } } else { CheckPointBuffers(flags, true); } - } else if (!do_restartpoint) { - CreateCheckPoint(flags); - ckpt_performed = true; - if (!bgwriter_first_startup && CheckFpwBeforeFirstCkpt()) { + } else if (!do_restartpoint) { // 鎵ц甯歌妫鏌ョ偣 + CreateCheckPoint(flags); // 鎵ц鍒涘缓妫鏌ョ偣鐨勬搷浣 + ckpt_performed = true; // 琛ㄧず宸茬粡鎵ц浜嗘鏌ョ偣鎿嶄綔 + // 妫鏌ユ槸鍚﹂渶瑕佺鐢ㄥ悗鍙板啓鍏ヨ繘绋嬮儴鍒嗘搷浣 + if (!bgwriter_first_startup && CheckFpwBeforeFirstCkpt()) { DisableFpwBeforeFirstCkpt(); } } else { @@ -542,36 +568,39 @@ void CheckpointerMain(void) * After any checkpoint, close all smgr files. This is so we * won't hang onto smgr references to deleted files indefinitely. */ - smgrcloseall(); + smgrcloseall(); // 鍏抽棴瀛樺偍绠$悊鍣ㄧ殑鎵鏈夋枃浠跺彞鏌勶紝纭繚涓嶅啀鎸佹湁宸插垹闄ゆ枃浠剁殑寮曠敤 /* * Indicate checkpoint completion to any waiting backends. */ - SpinLockAcquire(&cps->ckpt_lck); - cps->ckpt_done = cps->ckpt_started; - SpinLockRelease(&cps->ckpt_lck); + SpinLockAcquire(&cps->ckpt_lck); // 鑾峰彇鑷棆閿 + cps->ckpt_done = cps->ckpt_started; // 琛ㄧず妫鏌ョ偣宸茬粡瀹屾垚 + SpinLockRelease(&cps->ckpt_lck); // 閲婃斁 - if (ckpt_performed) { + if (ckpt_performed) { // 濡傛灉妫鏌ョ偣鎵ц鎴愬姛 /* * Note we record the checkpoint start time not end time as * t_thrd.checkpoint_cxt.last_checkpoint_time. This is so that time-driven * checkpoints happen at a predictable spacing. */ + // 璁剧疆涓哄綋鍓嶆椂闂达紝浠ヤ究涓嬩竴涓熀浜庢椂闂寸殑妫鏌ョ偣鍦ㄥ彲棰勬祴鐨勬椂闂撮棿闅斿唴瑙﹀彂 t_thrd.checkpoint_cxt.last_checkpoint_time = now; - } else if (!do_dirty_flush) { + } else if (!do_dirty_flush) { // 濡傛灉妫鏌ョ偣娌℃湁鎵ц鎴愬姛锛屼笖涓嶉渶瑕佹墽琛岃剰椤靛埛鏂 /* * We were not able to perform the restartpoint (checkpoints * throw an ERROR in case of error). Most likely because we * have not received any new checkpoint WAL records since the * last restartpoint. Try again in 15 s. */ + // 绛夊緟 15 绉掑悗鍐嶆灏濊瘯妫鏌ョ偣 t_thrd.checkpoint_cxt.last_checkpoint_time = now - u_sess->attr.attr_storage.CheckPointTimeout + 15; } - t_thrd.checkpoint_cxt.ckpt_active = false; + t_thrd.checkpoint_cxt.ckpt_active = false; // 琛ㄧず妫鏌ョ偣杩涚▼涓嶅啀澶勪簬娲诲姩鐘舵 } /* Check for archive_timeout and switch xlog files if necessary. */ + // 妫鏌ユ槸鍚﹂渶瑕佹墽琛屽綊妗h秴鏃舵搷浣滐紝濡傛灉闇瑕佸垏鎹 WAL 鏃ュ織鏂囦欢鎵ц CheckArchiveTimeout(); /* @@ -581,30 +610,36 @@ void CheckpointerMain(void) * worth the trouble to split the stats support into two independent * stats message types.) */ + // 灏嗘鏌ョ偣杩涚▼鐨勬椿鍔ㄧ粺璁′俊鎭彂閫佸埌缁熻鏀堕泦鍣紝浠ヤ究鐩戞帶绯荤粺鎬ц兘 pgstat_send_bgwriter(); /* * Sleep until we are signaled or it's time for another checkpoint or * xlog file switch. */ - now = (pg_time_t)time(NULL); + now = (pg_time_t)time(NULL); // 鑾峰彇褰撳墠鏃堕棿 + // 璁$畻鑷笂涓娆℃鏌ョ偣瀹屾垚浠ユ潵缁忚繃鐨勭鏁 elapsed_secs = now - t_thrd.checkpoint_cxt.last_checkpoint_time; + // 纭繚 elapsed_secs 涓嶄細涓鸿礋鏁 elapsed_secs = (elapsed_secs < 0) ? 0 : elapsed_secs; + // 妫鏌ユ槸鍚﹀凡缁忚繃浜嗘墽琛屾鏌ョ偣鐨勬椂闂撮槇鍊 if (elapsed_secs >= u_sess->attr.attr_storage.CheckPointTimeout) - continue; /* no sleep for us ... */ - + continue; /* no sleep for us ... */ // 涓嶉渶瑕佷紤鐪狅紝鐩存帴璺冲埌涓嬩竴娆″惊鐜 + // 璁$畻浼戠湢鐨勫墿浣欐椂闂达紝鍗宠窛绂讳笅涓娆℃鏌ョ偣鐨勬椂闂 cur_timeout = u_sess->attr.attr_storage.CheckPointTimeout - elapsed_secs; - + // 妫鏌ユ槸鍚﹀惎鐢ㄤ簡褰掓。瓒呮椂锛屽苟涓斿綋鍓嶄笉鍦ㄦ暟鎹簱鎭㈠鐘舵佷笅 if (u_sess->attr.attr_common.XLogArchiveTimeout > 0 && !RecoveryInProgress()) { + // 璁$畻鑷笂涓娆 WAL 鏃ュ織鏂囦欢鍒囨崲浠ユ潵缁忚繃鐨勭鏁 elapsed_secs = now - t_thrd.checkpoint_cxt.last_xlog_switch_time; - + // 濡傛灉瓒呰繃浜嗗綊妗h秴鏃舵椂闂撮槇鍊 if (elapsed_secs >= u_sess->attr.attr_common.XLogArchiveTimeout) continue; /* no sleep for us ... */ - + // 鏇存柊 cur_timeout 锛岀‘淇濅紤鐪犵殑鏃堕棿涓嶈秴杩囨渶灏忓 cur_timeout = Min(cur_timeout, u_sess->attr.attr_common.XLogArchiveTimeout - elapsed_secs); } - + // 鍚戠粺璁℃敹闆嗗櫒鎶ュ憡褰撳墠杩涚▼鐘舵佷负闂茬疆锛屼互渚跨洃瑙嗙郴缁熸ц兘 pgstat_report_activity(STATE_IDLE, NULL); + // 浼戠湢鎸囧畾鐨勬椂闂达紝绛夊緟淇″彿鎴栬秴鏃朵簨浠跺彂鐢 rc = WaitLatch(&t_thrd.proc->procLatch, WL_LATCH_SET | WL_TIMEOUT | WL_POSTMASTER_DEATH, cur_timeout * 1000L /* convert to ms */); @@ -613,8 +648,8 @@ void CheckpointerMain(void) * Emergency bailout if postmaster has died. This is to avoid the * necessity for manual cleanup of all postmaster children. */ - if (rc & WL_POSTMASTER_DEATH) - gs_thread_exit(1); + if (rc & WL_POSTMASTER_DEATH) // postmaster 杩涚▼宸茬粓姝 + gs_thread_exit(1); // 绱фラ鍑哄綋鍓嶇嚎绋嬶紝浠ラ伩鍏嶆墜鍔ㄦ竻鐞唒ostmaster鎵鏈夊瓙杩涚▼ } } @@ -625,40 +660,51 @@ void CheckpointerMain(void) * if any activity is recorded in the current WAL file, including just * a single checkpoint record. */ +/* + *鍔熻兘锛 妫鏌ュ綊妗h秴鏃跺苟瑙﹀彂 WAL 鏂囦欢鍒囨崲 + * + * 鍙傛暟锛氭棤 + * + * 杩斿洖鍊硷細鏃 + */ static void CheckArchiveTimeout(void) { pg_time_t now; pg_time_t last_time; - + // 棣栧厛妫鏌ユ槸鍚﹀惎鐢ㄤ簡褰掓。瓒呮椂锛屽苟涓斿綋鍓嶆槸鍚﹀浜庢暟鎹簱鎭㈠妯″紡 if (u_sess->attr.attr_common.XLogArchiveTimeout <= 0 || RecoveryInProgress()) - return; + return; // 涓嶉渶瑕佹墽琛屽綊妗h秴鏃舵搷浣 - now = (pg_time_t)time(NULL); + now = (pg_time_t)time(NULL); // 鑾峰彇褰撳墠鏃堕棿 /* First we do a quick check using possibly-stale local state. */ + // 浣跨敤杩囨椂鐨勬湰鍦扮姸鎬佷俊鎭墽琛屽揩閫熸鏌 + // 妫鏌ヤ粠涓婁竴娆 WAL 鏂囦欢鍒囨崲鍒扮幇鍦ㄧ粡杩囩殑鏃堕棿鏄惁灏忎簬褰掓。瓒呮椂鐨勯槇鍊 if ((int)(now - t_thrd.checkpoint_cxt.last_xlog_switch_time) < u_sess->attr.attr_common.XLogArchiveTimeout) - return; + return; // 涓嶉渶瑕佹墽琛屽綊妗h秴鏃舵搷浣 /* * Update local state ... note that t_thrd.checkpoint_cxt.last_xlog_switch_time is the last time * a switch was performed *or requested*. */ - last_time = GetLastSegSwitchTime(); - + last_time = GetLastSegSwitchTime(); // 鑾峰彇涓婁竴娆 WAL 鏂囦欢鍒囨崲鐨勬椂闂 + // 璁板綍鐨勬槸鏈杩戜竴娆 WAL 鏂囦欢鍒囨崲鎴栬姹傚垏鎹㈢殑鏃堕棿 t_thrd.checkpoint_cxt.last_xlog_switch_time = Max(t_thrd.checkpoint_cxt.last_xlog_switch_time, last_time); /* Now we can do the real check */ + // 鍐嶆妫鏌ヤ粠涓婁竴娆 WAL 鏂囦欢鍒囨崲鍒扮幇鍦ㄧ粡杩囩殑鏃堕棿鏄惁澶т簬鎴栫瓑浜庡綊妗h秴鏃剁殑闃堝 if ((int)(now - t_thrd.checkpoint_cxt.last_xlog_switch_time) >= u_sess->attr.attr_common.XLogArchiveTimeout) { XLogRecPtr switchpoint; /* OK, it's time to switch */ - switchpoint = RequestXLogSwitch(); + switchpoint = RequestXLogSwitch(); // 璇锋眰 WAL 鏂囦欢鍒囨崲锛屽苟杩斿洖鍒囨崲鐐 /* * If the returned pointer points exactly to a segment boundary, * assume nothing happened. */ - if ((switchpoint % XLogSegSize) != 0) + if ((switchpoint % XLogSegSize) != 0) // 妫鏌ュ垏鎹㈢偣鏄惁姝eソ鍦ㄤ竴涓 WAL 娈佃竟鐣屼笂 + // 濡傛灉涓嶆槸锛岀敓鎴愯皟璇曟棩蹇楋紝鎸囩ず WAL 鏂囦欢鍒囨崲鏄敱浜庡綊妗h秴鏃惰Е鍙戠殑 ereport(DEBUG1, (errmsg("transaction log switch forced (archive_timeout=%d)", u_sess->attr.attr_common.XLogArchiveTimeout))); @@ -667,6 +713,7 @@ static void CheckArchiveTimeout(void) * Update state in any case, so we don't retry constantly when the * system is idle. */ + // 鏇存柊鏃堕棿 璁板綍鏈杩戜竴娆 WAL 鏂囦欢鍒囨崲鐨勬椂闂 t_thrd.checkpoint_cxt.last_xlog_switch_time = now; } } @@ -676,16 +723,24 @@ static void CheckArchiveTimeout(void) * this does not check the *current* checkpoint's IMMEDIATE flag, but whether * there is one pending behind it.) */ +/* + *鍔熻兘锛 鐢ㄤ簬妫鏌ユ槸鍚﹁姹傜珛鍗虫墽琛屾鏌ョ偣 + * + * 鍙傛暟锛 鏃 + * + * 杩斿洖鍊硷細濡傛灉瀛樺湪璇锋眰绔嬪嵆鎵ц妫鏌ョ偣锛屽嚱鏁拌繑鍥 true锛涘惁鍒欙紝杩斿洖 false + */ static bool ImmediateCheckpointRequested(void) { - if (t_thrd.checkpoint_cxt.checkpoint_requested) { + if (t_thrd.checkpoint_cxt.checkpoint_requested) { // 濡傛灉鏈夋鏌ョ偣璇锋眰 + // 鍒濆鍖栦负鍏ㄥ眬鍙橀噺 鐢ㄤ簬鍦ㄥ涓繘绋嬩箣闂村叡浜鏌ョ偣鐩稿叧鐨勭姸鎬佷俊鎭 volatile CheckpointerShmemStruct* cps = t_thrd.checkpoint_cxt.CheckpointerShmem; /* * We don't need to acquire the ckpt_lck in this case because we're * only looking at a single flag bit. */ - if (cps->ckpt_flags & CHECKPOINT_IMMEDIATE) + if (cps->ckpt_flags & CHECKPOINT_IMMEDIATE) // 濡傛灉宸茬粡璇锋眰浜嗙珛鍗虫鏌ョ偣 return true; } @@ -705,34 +760,46 @@ static bool ImmediateCheckpointRequested(void) * 'progress' is an estimate of how much of the work has been done, as a * fraction between 0.0 meaning none, and 1.0 meaning all done. */ +/* + *鍔熻兘锛氭帶鍒舵鏌ョ偣鐨勯熺巼锛 + * 浠ュ疄鐜颁笌 checkpoint_completion_target 閰嶇疆椤圭殑鐩爣鎬ц兘涓鑷淬 + * + * 鍙傛暟锛 + * flags锛氭暣鏁帮紝琛ㄧず妫鏌ョ偣璇锋眰鏍囧織 + * progress锛氬弻绮惧害娴偣鏁帮紝琛ㄧず妫鏌ョ偣杩涘害鐨勪及璁★紝鑼冨洿鍦 0.0~1.0涔嬮棿 + */ void CheckpointWriteDelay(int flags, double progress) { /* Do nothing if checkpoint is being executed by non-checkpointer process */ - if (!AmCheckpointerProcess()) - return; + if (!AmCheckpointerProcess()) // 妫鏌ュ綋鍓嶆槸鍚︽槸妫鏌ョ偣杩涚▼鍦ㄦ墽琛 + return; // 濡傛灉涓嶆槸锛岀珛鍗宠繑鍥 /* * Perform the usual duties and take a nap, unless we're behind schedule, * in which case we just try to catch up as quickly as possible. */ + // 閫氳繃妫鏌ユ槸鍚︿笉闇瑕佺珛鍗虫墽琛屾鏌ョ偣锛屾槸鍚︽病鏈夋鏌ョ偣鐨勫叧闂姹傦紝 + // 鏄惁娌℃湁绔嬪嵆妫鏌ョ偣璇锋眰锛屾鏌ョ偣鐨勮繘搴︽槸鍚︽寜璁″垝鎵ц锛 + // 浠ョ‘瀹氭槸鍚﹂渶瑕佹墽琛屾鏌ョ偣鐨勫啓鍏ユ搷浣 if (!((uint32)flags & CHECKPOINT_IMMEDIATE) && !t_thrd.checkpoint_cxt.shutdown_requested && !ImmediateCheckpointRequested() && IsCheckpointOnSchedule(progress)) { - if (t_thrd.checkpoint_cxt.got_SIGHUP) { + if (t_thrd.checkpoint_cxt.got_SIGHUP) { // 妫鏌ユ槸鍚︽敹鍒 SIGHUP 淇″彿 t_thrd.checkpoint_cxt.got_SIGHUP = false; - ProcessConfigFile(PGC_SIGHUP); + ProcessConfigFile(PGC_SIGHUP); // 閲嶆柊鍔犺浇閰嶇疆鏂囦欢 /* update shmem copies of config variables */ - UpdateSharedMemoryConfig(); + UpdateSharedMemoryConfig(); // 鏇存柊鍏变韩鍐呭瓨涓殑閰嶇疆鍙橀噺 } - CkptAbsorbFsyncRequests(); + CkptAbsorbFsyncRequests(); // 澶勭悊鎸傝捣鐨 fsync 璇锋眰 + // 灏 absorbCounter 璁℃暟鍣ㄨ缃负 WRITES_PER_ABSORB锛岄檺鍒堕绻佸鐞 fsync 璇锋眰 t_thrd.checkpoint_cxt.absorbCounter = WRITES_PER_ABSORB; - CheckArchiveTimeout(); + CheckArchiveTimeout(); // 妫鏌ユ槸鍚﹂渶瑕佹墽琛屾棩蹇楁枃浠跺垏鎹 /* * Report interim activity statistics to the stats collector. */ - pgstat_send_bgwriter(); + pgstat_send_bgwriter(); // 灏嗗綋鍓嶇殑娲诲姩缁熻淇℃伅鍙戦佺粰缁熻淇℃伅鏀堕泦鍣 /* * This sleep used to be connected to bgwriter_delay, typically 200ms. @@ -740,14 +807,17 @@ void CheckpointWriteDelay(int flags, double progress) * Checkpointer and bgwriter are no longer related so take the Big * Sleep. */ - pg_usleep(100000L); - } else if (--t_thrd.checkpoint_cxt.absorbCounter <= 0) { + pg_usleep(100000L); // 鎵ц鐭殏鐨勪紤鐪狅紝浠ユ帶鍒跺啓鍏ラ熺巼 + } else if (--t_thrd.checkpoint_cxt.absorbCounter <= 0) { // 妫鏌ユ槸鍚﹂渶瑕佸鐞嗘寕璧风殑 fsync 璇锋眰 /* * Absorb pending fsync requests after each WRITES_PER_ABSORB write * operations even when we don't sleep, to prevent overflow of the * fsync request queue. */ + // 澶勭悊鎸傝捣鐨 fsync 璇锋眰 CkptAbsorbFsyncRequests(); + //灏 absorbCounter 璁℃暟鍣ㄩ噸缃负 WRITES_PER_ABSORB锛屼互闄愬埗棰戠箒澶勭悊 fsync 璇锋眰 + t_thrd.checkpoint_cxt.absorbCounter = WRITES_PER_ABSORB; } } @@ -760,18 +830,31 @@ void CheckpointWriteDelay(int flags, double progress) * checkpoint, and returns true if the progress we've made this far is greater * than the elapsed time/segments. */ +/* + *鍔熻兘锛氭鏌ュ綋鍓嶆槸鍚﹀湪绗﹀悎璁″垝鐨勬椂闂村唴瀹屾垚妫鏌ョ偣 + * + * 鍙傛暟锛 + * progress 鍙岀簿搴︽诞鐐规暟锛岃〃绀哄綋鍓嶅凡瀹屾垚鐨勫伐浣滆繘搴 + * + * 杩斿洖鍊硷細 + * bool绫诲瀷锛岃〃绀哄綋鍓嶆鏌ョ偣鏄惁鎸夌収棰勫畾璁″垝杩涜銆 + * 濡傛灉妫鏌ョ偣鐨勮繘搴﹀凡缁忚秴杩囦簡鏃堕棿鎴栨鏁扮殑璁$畻缁撴灉锛岃繑鍥 true锛岃〃绀烘鏌ョ偣鎸夎鍒掕繘琛屻 + * 鍚﹀垯锛岃繑鍥 false锛岃〃绀烘鏌ョ偣娌℃湁鎸夎鍒掕繘琛屻 + */ static bool IsCheckpointOnSchedule(double progress) { - XLogRecPtr recptr; - struct timeval now; - double elapsed_xlogs, elapsed_time; + XLogRecPtr recptr; // 鐢ㄤ簬瀛樺偍 WAL 鎻掑叆浣嶇疆 + struct timeval now; // 鐢ㄤ簬鑾峰彇褰撳墠鏃堕棿 + double elapsed_xlogs, elapsed_time; // 鐢ㄤ簬璁$畻宸茬粡杩囧幓鐨 WAL 娈垫暟鍜屾椂闂 - Assert(t_thrd.checkpoint_cxt.ckpt_active); + Assert(t_thrd.checkpoint_cxt.ckpt_active); // 纭繚褰撳墠妫鏌ョ偣姝e湪娲诲姩鐘舵 + // 鎹厤缃弬鏁 ENABLE_INCRE_CKPT 鏉ヨ缃 CheckPointTimeout锛岀敤浜庡悗缁殑璁$畻 u_sess->attr.attr_storage.CheckPointTimeout = ENABLE_INCRE_CKPT ? u_sess->attr.attr_storage.incrCheckPointTimeout : u_sess->attr.attr_storage.fullCheckPointTimeout; /* Scale progress according to checkpoint_completion_target. */ + // 鏍规嵁閰嶇疆鍙傛暟 checkpoint_completion_target 瀵硅繘搴 progress 杩涜缂╂斁 progress *= u_sess->attr.attr_storage.CheckPointCompletionTarget; /* @@ -780,6 +863,7 @@ static bool IsCheckpointOnSchedule(double progress) * neither time or WAL insert pointer moves backwards, a freshly * calculated value can only be greater than or equal to the cached value. */ + // 妫鏌ユ槸鍚﹀凡缁忚绠楄繃褰撳墠鐨勮繘搴 progress if (progress < t_thrd.checkpoint_cxt.ckpt_cached_elapsed) return false; @@ -793,12 +877,14 @@ static bool IsCheckpointOnSchedule(double progress) * However, it's good enough for our purposes, we're only calculating an * estimate anyway. */ - if (!RecoveryInProgress()) { - recptr = GetInsertRecPtr(); + if (!RecoveryInProgress()) { // 濡傛灉娌℃湁鍦ㄦ仮澶嶆ā寮忎笅鎵ц + recptr = GetInsertRecPtr(); // 鑾峰彇褰撳墠鐨 WAL 鎻掑叆浣嶇疆 recptr + // 璁$畻宸茬粡杩囧幓鐨 WAL 娈垫暟 elapsed_xlogs锛屽苟涓 checkpoint_segments 閰嶇疆椤硅繘琛屾瘮杈 elapsed_xlogs = (((double)(recptr - t_thrd.checkpoint_cxt.ckpt_start_recptr)) / XLogSegSize) / u_sess->attr.attr_storage.CheckPointSegments; - if (progress < elapsed_xlogs) { + if (progress < elapsed_xlogs) { // 妫鏌ヨ繘搴 progress 鏄惁宸茬粡瓒呰繃 + // 濡傛灉鏈秴杩囷紝鏇存柊缂撳瓨鐨勮绠楃粨鏋 t_thrd.checkpoint_cxt.ckpt_cached_elapsed = elapsed_xlogs; return false; } @@ -807,11 +893,13 @@ static bool IsCheckpointOnSchedule(double progress) /* * Check progress against time elapsed and checkpoint_timeout. */ - gettimeofday(&now, NULL); + gettimeofday(&now, NULL); // 鑾峰彇褰撳墠鏃堕棿 + // 璁$畻宸茬粡杩囧幓鐨勬椂闂 elapsed_time锛屽苟涓 checkpoint_timeout 閰嶇疆椤硅繘琛屾瘮杈 elapsed_time = ((double)((pg_time_t)now.tv_sec - t_thrd.checkpoint_cxt.ckpt_start_time) + now.tv_usec / 1000000.0) / u_sess->attr.attr_storage.CheckPointTimeout; - if (progress < elapsed_time) { + if (progress < elapsed_time) { // 妫鏌ヨ繘搴 progress 鏄惁宸茬粡瓒呰繃 + // 濡傛灉鏈秴杩囷紝鏇存柊缂撳瓨鐨勮绠楃粨鏋 t_thrd.checkpoint_cxt.ckpt_cached_elapsed = elapsed_time; return false; } @@ -830,9 +918,19 @@ static bool IsCheckpointOnSchedule(double progress) * Some backend has bought the farm, * so we need to stop what we're doing and exit. */ +/* + *鍔熻兘锛氬鐞嗗揩閫熺粓姝俊鍙 + * 绱фラ鍑烘搷浣滐紝涓嶄細瑙﹀彂姝e父鐨勬竻鐞嗗拰鍏抽棴姝ラ锛屽洜涓哄叡浜唴瀛樺彲鑳藉凡鎹熷潖 + * + * 鍙傛暟: + * SIGNAL_ARGS: 淇″彿澶勭悊绋嬪簭鐨勫弬鏁板垪琛紝鎻愪緵鍏充簬瑙﹀彂淇″彿鐨勪笂涓嬫枃淇℃伅 + * + * 杩斿洖鍊: + * 鏃 + */ static void chkpt_quickdie(SIGNAL_ARGS) { - gs_signal_setmask(&t_thrd.libpq_cxt.BlockSig, NULL); + gs_signal_setmask(&t_thrd.libpq_cxt.BlockSig, NULL); // 瑙i櫎瀵逛俊鍙风殑闃诲 /* * We DO NOT want to run proc_exit() callbacks -- we're here because @@ -842,7 +940,7 @@ static void chkpt_quickdie(SIGNAL_ARGS) * things by calling exit() directly, we have to reset the callbacks * explicitly to make this work as intended. */ - on_exit_reset(); + on_exit_reset(); // 閲嶇疆閫鍑哄鐞嗗洖璋 /* * Note we do exit(2) not exit(0). This is to force the postmaster into a @@ -852,56 +950,92 @@ static void chkpt_quickdie(SIGNAL_ARGS) * should ensure the postmaster sees this as a crash, too, but no harm in * being doubly sure.) */ - exit(2); + exit(2); // 寮哄埗 postmaster 杩涘叆绯荤粺閲嶇疆鍛ㄦ湡锛岀‘淇 postmaster 灏嗚繖涓俊鍙疯涓哄穿婧 } /* SIGHUP: set flag to re-read config file at next convenient time */ +/* + *鍔熻兘锛氬鐞 SIGHUP 淇″彿锛岀敤浜庨噸鏂拌鍙栭厤缃枃浠 + * + * 鍙傛暟: + * SIGNAL_ARGS: 淇″彿澶勭悊绋嬪簭鐨勫弬鏁板垪琛紝鎻愪緵鍏充簬瑙﹀彂淇″彿鐨勪笂涓嬫枃淇℃伅 + * + * 杩斿洖鍊: + * 鏃 + */ static void ChkptSigHupHandler(SIGNAL_ARGS) { int save_errno = errno; - + // 琛ㄧず闇瑕佸湪涓嬩竴涓柟渚跨殑鏃堕棿閲嶆柊璇诲彇閰嶇疆鏂囦欢 t_thrd.checkpoint_cxt.got_SIGHUP = true; - if (t_thrd.proc) - SetLatch(&t_thrd.proc->procLatch); + if (t_thrd.proc) // 濡傛灉褰撳墠杩涚▼瀛樺湪 + SetLatch(&t_thrd.proc->procLatch); // 璁剧疆璇ヨ繘绋嬬殑浜嬩欢鏍囧織锛屼互澶勭悊 SIGHUP 淇″彿 - errno = save_errno; + errno = save_errno; // 淇濆瓨骞惰繕鍘熷綋鍓嶇殑 errno 鍊硷紝浠ラ槻骞叉壈鍏朵粬浠g爜 } /* SIGINT: set flag to run a normal checkpoint right away */ +/* + *鍔熻兘锛 澶勭悊 SIGINT 淇″彿锛堜腑鏂繘绋嬩俊鍙凤級锛岀敤浜庤姹傜珛鍗虫墽琛屾甯哥殑妫鏌ョ偣 + * + * 鍙傛暟: + * SIGNAL_ARGS: 淇″彿澶勭悊绋嬪簭鐨勫弬鏁板垪琛紝鎻愪緵鍏充簬瑙﹀彂淇″彿鐨勪笂涓嬫枃淇℃伅 + * + * 杩斿洖鍊: + * 鏃 + */ static void ReqCheckpointHandler(SIGNAL_ARGS) { int save_errno = errno; - + // 琛ㄧず闇瑕佺珛鍗虫墽琛屾甯哥殑妫鏌ョ偣 t_thrd.checkpoint_cxt.checkpoint_requested = true; - if (t_thrd.proc) - SetLatch(&t_thrd.proc->procLatch); + if (t_thrd.proc) // 濡傛灉褰撳墠杩涚▼瀛樺湪 + SetLatch(&t_thrd.proc->procLatch); // 璁剧疆璇ヨ繘绋嬩簨浠舵爣蹇楋紝浠ュ鐞 SIGINT 淇″彿 - errno = save_errno; + errno = save_errno; // 淇濆瓨骞惰繕鍘熷綋鍓嶇殑 errno 鍊硷紝浠ラ槻骞叉壈鍏朵粬浠g爜 } /* SIGUSR1: used for latch wakeups */ +/* + *鍔熻兘锛 澶勭悊 SIGUSR1 淇″彿锛岀敤浜庡敜閱掕繘绋嬩腑鐨勭瓑寰呮搷浣 + * + * 鍙傛暟: + * SIGNAL_ARGS: 淇″彿澶勭悊绋嬪簭鐨勫弬鏁板垪琛紝鎻愪緵鍏充簬瑙﹀彂淇″彿鐨勪笂涓嬫枃淇℃伅 + * + * 杩斿洖鍊: + * 鏃 + */ static void chkpt_sigusr1_handler(SIGNAL_ARGS) { int save_errno = errno; - latch_sigusr1_handler(); + latch_sigusr1_handler(); // 澶勭悊涓 latch 鐩稿叧鐨 SIGUSR1 淇″彿鎿嶄綔 - errno = save_errno; + errno = save_errno; // 淇濆瓨骞惰繕鍘熷綋鍓嶇殑 errno 鍊硷紝浠ラ槻骞叉壈鍏朵粬浠g爜 } /* SIGUSR2: set flag to run a shutdown checkpoint and exit */ +/* + *鍔熻兘锛氬鐞 SIGUSR2 淇″彿锛岀敤浜庤姹傛墽琛屽叧闂鏌ョ偣骞堕鍑鸿繘绋 + * + * 鍙傛暟: + * SIGNAL_ARGS: 淇″彿澶勭悊绋嬪簭鐨勫弬鏁板垪琛紝鎻愪緵鍏充簬瑙﹀彂淇″彿鐨勪笂涓嬫枃淇℃伅 + * + * 杩斿洖鍊: + * 鏃 + */ static void ReqShutdownHandler(SIGNAL_ARGS) { int save_errno = errno; - + // 琛ㄧず闇瑕佹墽琛屽叧闂鏌ョ偣骞堕鍑鸿繘绋 t_thrd.checkpoint_cxt.shutdown_requested = true; - if (t_thrd.proc) - SetLatch(&t_thrd.proc->procLatch); + if (t_thrd.proc) // 濡傛灉褰撳墠杩涚▼瀛樺湪 + SetLatch(&t_thrd.proc->procLatch); // 璁剧疆璇ヨ繘绋嬬殑浜嬩欢鏍囧織锛屼互澶勭悊 SIGUSR2 淇″彿 - errno = save_errno; + errno = save_errno; // 淇濆瓨骞惰繕鍘熷綋鍓嶇殑 errno 鍊硷紝浠ラ槻骞叉壈鍏朵粬浠g爜 } /* -------------------------------- @@ -912,7 +1046,14 @@ static void ReqShutdownHandler(SIGNAL_ARGS) * CheckpointerShmemSize * Compute space needed for checkpointer-related shared memory */ -const uint DDL_REQUEST_MAX = 100000; +const uint DDL_REQUEST_MAX = 100000; // 琛ㄧずDDL璇锋眰鐨勬渶澶ф暟閲 +/* + *鍔熻兘锛氳绠楃敤浜庢鏌ョ偣杩涚▼鐨勫叡浜唴瀛樻墍闇鐨勭┖闂村ぇ灏 + * + * 鍙傛暟锛 鏃 + * + * 杩斿洖鍊硷細Size 绫诲瀷锛岃〃绀烘墍闇鐨勭┖闂村ぇ灏 + */ Size CheckpointerShmemSize(void) { Size size; @@ -921,11 +1062,14 @@ Size CheckpointerShmemSize(void) * Currently, the size of the requests[] array is arbitrarily set equal to * NBuffers. This may prove too large or small ... */ + // 璁$畻 CheckpointerShmemStruct 缁撴瀯浣擄紙鍖呭惈妫鏌ョ偣杩涚▼鎵闇鐨勫悇绉嶄俊鎭級鐨勫亸绉婚噺 size = offsetof(CheckpointerShmemStruct, requests); - if (ENABLE_INCRE_CKPT) { + if (ENABLE_INCRE_CKPT) { // 濡傛灉鍚敤澧為噺妫鏌ョ偣 /* incremental checkpoint, the checkpoint thread only handle the drop table request and drop db request */ + // 鏇存柊size锛岃〃绀哄湪澧為噺妫鏌ョ偣妯″紡涓嬶紝鍏变韩鍐呭瓨闇瑕佸瓨鍌ㄤ竴瀹氭暟閲忕殑DDL璇锋眰 size = add_size(size, mul_size(DDL_REQUEST_MAX, sizeof(CheckpointerRequest))); } else { + // 鏇存柊size锛岃〃绀哄湪闈炲閲忔鏌ョ偣妯″紡涓嬶紝鍏变韩鍐呭瓨闇瑕佸瓨鍌ㄤ竴瀹氭暟閲忕殑妫鏌ョ偣璇锋眰 size = add_size(size, mul_size(TOTAL_BUFFER_NUM, sizeof(CheckpointerRequest))); } @@ -936,23 +1080,34 @@ Size CheckpointerShmemSize(void) * CheckpointerShmemInit * Allocate and initialize checkpointer-related shared memory */ +/* + *鍔熻兘锛氬垎閰嶅拰鍒濆鍖栦笌妫鏌ョ偣杩涚▼鐩稿叧鐨勫叡浜唴瀛 + * + * 鍙傛暟锛氭棤 + * + * 杩斿洖鍊硷細鏃 + */ void CheckpointerShmemInit(void) { - Size size = CheckpointerShmemSize(); + Size size = CheckpointerShmemSize(); // 璁$畻鎵闇鐨勫叡浜唴瀛樺ぇ灏 bool found = false; - + // 鍒嗛厤鍏变韩鍐呭瓨 t_thrd.checkpoint_cxt.CheckpointerShmem = (CheckpointerShmemStruct*)ShmemInitStruct("Checkpointer Data", size, &found); - if (!found) { + if (!found) { // 妫鏌ユ槸鍚︽壘鍒颁簡宸插瓨鍦ㄧ殑鍏变韩鍐呭瓨 /* * First time through, so initialize. Note that we zero the whole * requests array; this is so that CompactCheckpointerRequestQueue * can assume that any pad bytes in the request structs are zeroes. */ /* The memory of the memset sometimes exceeds 2 GB. so, memset_s cannot be used. */ + // 濡傛灉娌℃湁鎵惧埌锛岃〃绀鸿繖鏄涓娆″垱寤哄叡浜唴瀛橈紝闇瑕佽繘琛屽垵濮嬪寲 + // 灏嗘暣涓叡浜唴瀛樺尯鍩熷垵濮嬪寲涓洪浂 MemSet((char*)t_thrd.checkpoint_cxt.CheckpointerShmem, 0, size); + // 瀵瑰叡浜唴瀛樹腑鐨勮嚜鏃嬮攣杩涜鍒濆鍖栵紝鐢ㄤ簬鍦ㄥ涓繘绋嬩箣闂村悓姝ュ鍏变韩鍐呭瓨鐨勮闂 SpinLockInit(&t_thrd.checkpoint_cxt.CheckpointerShmem->ckpt_lck); + // 鏍规嵁鏄惁鍚敤浜嗗閲忔鏌ョ偣璁剧疆 max_requests 瀛楁鐨勫 t_thrd.checkpoint_cxt.CheckpointerShmem->max_requests = ENABLE_INCRE_CKPT ? DDL_REQUEST_MAX : TOTAL_BUFFER_NUM; } } @@ -960,9 +1115,19 @@ void CheckpointerShmemInit(void) /* * Check wheter checkpoint proc is running while waiting request checkpoint to finish. */ +/* + *鍔熻兘锛 妫鏌ユ鏌ョ偣杩涚▼鏄惁姝e湪杩愯 纭繚鍙湁鍦ㄦ鏌ョ偣杩涚▼姝e湪杩愯鏃舵墠鑳藉彂鍑鸿姹 + * + * 鍙傛暟锛氭棤 + * + * 杩斿洖鍊硷細鏃 + */ static void CheckPointProcRunning(void) { + // 妫鏌ュ叏灞鍙橀噺 g_instance.pid_cxt.CheckpointerPID 鏄惁涓0 + // 濡傛灉涓0锛岃〃绀烘鏌ョ偣杩涚▼娌℃湁鍦ㄨ繍琛 if (g_instance.pid_cxt.CheckpointerPID == 0) { + // 鍙戝嚭璀﹀憡 璇存槑鏃犳硶璇锋眰妫鏌ョ偣 ereport(FATAL, (errcode(ERRCODE_WITH_CHECK_OPTION_VIOLATION), errmsg("could not request checkpoint because checkpointer not running"))); @@ -986,6 +1151,21 @@ static void CheckPointProcRunning(void) * CHECKPOINT_CAUSE_XLOG: checkpoint is requested due to xlog filling. * (This affects logging, and in particular enables CheckPointWarning.) */ +/* + *鍔熻兘锛氳姹傛墽琛屾鏌ョ偣鎿嶄綔 + * + * 鍙傛暟锛 + * flags-浣嶆帺鐮 锛屼笉鍚屼簩杩涘埗浣嶅叿鏈変笉鍚屽惈涔 + * 鍖呭惈浠ヤ笅鏍囧織鐨勬寜浣嶆垨鎿嶄綔 + * - CHECKPOINT_IS_SHUTDOWN锛氳〃绀烘鏌ョ偣鏄负浜嗘暟鎹簱鍏抽棴鑰屾墽琛岀殑 + * - CHECKPOINT_END_OF_RECOVERY锛氳〃绀烘鏌ョ偣鏄负浜哤AL鎭㈠缁撴潫鑰屾墽琛岀殑 + * - CHECKPOINT_IMMEDIATE锛氳〃绀虹珛鍗冲畬鎴愭鏌ョ偣锛屽拷鐣 checkpoint_completion_target 鍙傛暟 + * - CHECKPOINT_FORCE锛氳〃绀哄嵆浣垮湪涓婃妫鏌ョ偣涔嬪悗娌℃湁鍙戠敓浠讳綍XLOG娲诲姩锛屼篃瑕佸己鍒舵墽琛屾鏌ョ偣 + * - CHECKPOINT_WAIT锛氳〃绀虹瓑寰呮鏌ョ偣瀹屾垚鍚庡啀杩斿洖 + * - CHECKPOINT_CAUSE_XLOG锛氳〃绀虹敱浜嶺LOG濉厖鑰岃姹傛鏌ョ偣 + * + *杩斿洖鍊硷細鏃 + */ void RequestCheckpoint(int flags) { /* use volatile pointer to prevent code rearrangement */ @@ -995,17 +1175,23 @@ void RequestCheckpoint(int flags) /* * If in a standalone backend, just do it ourselves. */ + // 妫鏌ュ綋鍓嶆槸鍚﹀湪鐙珛鍚庡彴杩涚▼涓繍琛 + // 濡傛灉鏄垯鐩存帴鎵ц妫鏌ョ偣鎿嶄綔锛屼互闃插叾浠栧悗鍙拌繘绋嬪共鎵版鏌ョ偣 if (!IsPostmasterEnvironment) { + // 濡傛灉涓嶅湪鐙珛鍚庡彴杩涚▼涓繍琛 /* * There's no point in doing slow checkpoints in a standalone backend, * because there's no other backends the checkpoint could disrupt. */ + // 璋冪敤 CreateCheckPoint 鍑芥暟鎵ц妫鏌ョ偣鎿嶄綔 CreateCheckPoint(flags | CHECKPOINT_IMMEDIATE); /* * After any checkpoint, close all smgr files. This is so we won't * hang onto smgr references to deleted files indefinitely. */ + // 鍦ㄤ换浣曟鏌ョ偣涔嬪悗鍏抽棴鎵鏈夌殑 smgr 鏂囦欢 + // 閬垮厤鎸佺画寮曠敤宸插垹闄ゆ枃浠剁殑 smgr 寮曠敤 smgrcloseall(); return; @@ -1020,11 +1206,12 @@ void RequestCheckpoint(int flags) * a "stronger" request by another backend. The flag senses must be * chosen to make this work! */ - SpinLockAcquire(&cps->ckpt_lck); + SpinLockAcquire(&cps->ckpt_lck); // 鑾峰彇鑷棆閿 + // 鑾峰彇妫鏌ョ偣杩涘害鍊 old_failed = cps->ckpt_failed; old_started = cps->ckpt_started; cps->ckpt_flags |= flags; - SpinLockRelease(&cps->ckpt_lck); + SpinLockRelease(&cps->ckpt_lck); // 閲婃斁鑷棆閿 /* * Send signal to request checkpoint. It's possible that the checkpointer @@ -1033,11 +1220,15 @@ void RequestCheckpoint(int flags) * occur, we consider failure to send the signal to be nonfatal and merely * LOG it. */ + // 寰幆灏濊瘯鍚戞鏌ョ偣杩涚▼鍙戝嚭淇″彿锛岀洿鑷虫鏌ョ偣杩涚▼鍚姩 for (ntries = 0;; ntries++) { + // 妫鏌ユ鏌ョ偣杩涚▼鐨凱ID鏄惁涓0锛屽鏋滀负0锛屽垯琛ㄧず妫鏌ョ偣杩涚▼灏氭湭鍚姩 if (t_thrd.checkpoint_cxt.CheckpointerShmem->checkpointer_pid == 0) { /* max wait CheckPointWaitTime secs */ + // 濡傛灉绛夊緟鏃堕棿瓒呰繃闃堝兼垨绯荤粺姝e湪鍏抽棴 if (ntries >= (u_sess->attr.attr_storage.CheckPointWaitTimeOut * 10) || pmState == PM_SHUTDOWN_2) { if (flags & CHECKPOINT_WAIT) { + // 鐢熸垚閿欒鎶ュ憡 ereport(ERROR, (errcode(ERRCODE_WITH_CHECK_OPTION_VIOLATION), errmsg("could not request checkpoint because checkpointer not running"))); @@ -1046,10 +1237,13 @@ void RequestCheckpoint(int flags) } break; } + // 鍚戞鏌ョ偣杩涚▼鍙戦 SIGINT 淇″彿锛岃姹傛墽琛屾鏌ョ偣 } else if (gs_signal_send(t_thrd.checkpoint_cxt.CheckpointerShmem->checkpointer_pid, SIGINT) != 0) { /* max wait CheckPointWaitTime secs */ + // 濡傛灉绛夊緟鏃堕棿瓒呰繃闃堝 if (ntries >= (u_sess->attr.attr_storage.CheckPointWaitTimeOut * 10)) { if (flags & CHECKPOINT_WAIT) { + // 鐢熸垚閿欒鎶ュ憡 ereport(ERROR, (errcode(ERRCODE_WITH_CHECK_OPTION_VIOLATION), errmsg("could not signal for checkpoint: %m"))); } else { @@ -1060,8 +1254,9 @@ void RequestCheckpoint(int flags) } else { break; /* signal sent successfully */ } - - CHECK_FOR_INTERRUPTS(); + // 妫鏌ユ槸鍚︽敹鍒颁簡涓柇淇″彿锛屽鏋滄敹鍒颁腑鏂俊鍙凤紝鍒欎腑鏂綋鍓嶆搷浣 + CHECK_FOR_INTERRUPTS(); + // 浣垮綋鍓嶈繘绋嬩紤鐪0.1绉掞紝鐒跺悗閲嶈瘯鍚戞鏌ョ偣杩涚▼鍙戦佷俊鍙 pg_usleep(100000L); /* wait 0.1 sec, then retry */ } @@ -1069,19 +1264,20 @@ void RequestCheckpoint(int flags) * If requested, wait for completion. We detect completion according to * the algorithm given above. */ - if (flags & CHECKPOINT_WAIT) { - int new_started, new_failed; + if (flags & CHECKPOINT_WAIT) { // 濡傛灉闇瑕佺瓑寰呮鏌ョ偣鎿嶄綔瀹屾垚 + int new_started, new_failed; // 鐢ㄤ簬璁板綍鏂扮殑妫鏌ョ偣寮濮嬪拰澶辫触鐨勮鏁 /* Wait for a new checkpoint to start. */ - for (;;) { - SpinLockAcquire(&cps->ckpt_lck); - new_started = cps->ckpt_started; - SpinLockRelease(&cps->ckpt_lck); + // 寰幆绛夊緟鏂扮殑妫鏌ョ偣寮濮 + for (;;) { + SpinLockAcquire(&cps->ckpt_lck); // 鑾峰彇鑷棆閿 + new_started = cps->ckpt_started; // 鑾峰彇妫鏌ョ偣鏃х殑璁℃暟 + SpinLockRelease(&cps->ckpt_lck); // 閲婃斁閿 - if (new_started != old_started) { - break; + if (new_started != old_started) { // 妫鏌ユ柊鐨勬鏌ョ偣寮濮嬭鏁版槸鍚︿笌鏃х殑璁℃暟涓嶅悓 + break; // 濡傛灉涓嶅悓锛屽垯琛ㄧず鏂扮殑妫鏌ョ偣宸茬粡寮濮嬶紝璺冲嚭寰幆 } - + // 妫鏌ユ槸鍚︽敹鍒颁簡涓柇淇″彿锛屽鏋滄敹鍒颁腑鏂俊鍙凤紝鍒欎腑鏂綋鍓嶆搷浣 CHECK_FOR_INTERRUPTS(); CheckPointProcRunning(); pg_usleep(100000L); @@ -1090,24 +1286,27 @@ void RequestCheckpoint(int flags) /* * We are waiting for ckpt_done >= new_started, in a modulo sense. */ + // 寰幆绛夊緟妫鏌ョ偣鎿嶄綔鐨勫畬鎴 for (;;) { int new_done; - SpinLockAcquire(&cps->ckpt_lck); + SpinLockAcquire(&cps->ckpt_lck); // 鑾峰彇鑷棆閿 + // 鑾峰彇鏃х殑妫鏌ョ偣淇℃伅 new_done = cps->ckpt_done; new_failed = cps->ckpt_failed; - SpinLockRelease(&cps->ckpt_lck); - + SpinLockRelease(&cps->ckpt_lck); // 閲婃斁閿 + // 濡傛灉鏂扮殑妫鏌ョ偣瀹屾垚璁℃暟澶т簬绛変簬鏂扮殑妫鏌ョ偣寮濮嬭鏁 if (new_done - new_started >= 0) { - break; + break; // 琛ㄧず妫鏌ョ偣鎿嶄綔瀹屾垚锛岃烦鍑哄惊鐜 } - + // 妫鏌ユ槸鍚︽敹鍒颁簡涓柇淇″彿锛屽鏋滄敹鍒颁腑鏂俊鍙凤紝鍒欎腑鏂綋鍓嶆搷浣 CHECK_FOR_INTERRUPTS(); CheckPointProcRunning(); pg_usleep(100000L); } - if (new_failed != old_failed) + if (new_failed != old_failed) // 濡傛灉妫鏌ョ偣鎿嶄綔澶辫触 + // 鐢熸垚閿欒鎶ュ憡锛屾寚绀烘鏌ョ偣璇锋眰澶辫触 ereport(ERROR, (errcode(ERRCODE_WITH_CHECK_OPTION_VIOLATION), errmsg("checkpoint request failed"), @@ -1135,25 +1334,42 @@ void RequestCheckpoint(int flags) * the queue is full and contains no duplicate entries. In that case, we * let the backend know by returning false. */ +/* + * 鍔熻兘锛 + * 灏嗘枃浠跺悓姝ヨ姹備粠鍚庡彴杩涚▼浼犻掔粰妫鏌ョ偣杩涚▼ + * 浠ョ‘淇濆湪涓嬩竴娆℃鏌ョ偣涔嬪墠灏嗚繖浜涙枃浠跺悓姝ュ埌纾佺洏 + * + * 鍙傛暟锛 + * ftag 琛ㄧず鏂囦欢鏍囩锛堟寚瀹氳鍚屾鐨勬枃浠讹級 + * type 琛ㄧず鍚屾璇锋眰鐨勭被鍨 + * + * 杩斿洖鍊硷細 + * bool绫诲瀷锛屽鏋滄垚鍔熷皢鏂囦欢鍚屾璇锋眰娣诲姞鍒板悗鍙版鏌ョ偣杩涚▼鐨勮姹傞槦鍒椾腑锛岃繑鍥瀟rue + * 鍚﹀垯锛岃繑鍥瀎alse + */ bool CkptForwardSyncRequest(const FileTag *ftag, SyncRequestType type) { CheckpointerRequest* request = NULL; bool too_full = false; - if (!IsUnderPostmaster) { + if (!IsUnderPostmaster) { // 妫鏌ュ綋鍓嶈繘绋嬫槸鍚﹀湪 Postmaster 鐜涓繍琛 + // 濡傛灉涓嶆槸锛屽垯杩斿洖 false return false; /* probably shouldn't even get here */ } - if (AmCheckpointerProcess()) { + if (AmCheckpointerProcess()) { // 妫鏌ュ綋鍓嶈繘绋嬫槸鍚︿负妫鏌ョ偣杩涚▼ + // 濡傛灉鏄紝鍒欐姤鍛婇敊璇紝鍥犱负妫鏌ョ偣杩涚▼涓嶅簲璇ヨ皟鐢ㄦ鍑芥暟 ereport(ERROR, (errcode(ERRCODE_WITH_CHECK_OPTION_VIOLATION), errmsg("ForwardFsyncRequest must not be called in checkpointer"))); } - + // 鑾峰彇杞婚噺绾ч攣锛岀‘淇濆涓繘绋嬩箣闂翠笉浼氬悓鏃朵慨鏀瑰叡浜暟鎹粨鏋 LWLockAcquire(CheckpointerCommLock, LW_EXCLUSIVE); /* Count all backend writes regardless of if they fit in the queue */ + // 妫鏌ュ綋鍓嶈繘绋嬫槸鍚︿负鍚庡彴鍐欏叆杩涚▼鎴栭〉闈㈠啓鍏ヨ繘绋 if (!AmBackgroundWriterProcess() && !AmPageWriterProcess()) { + // 濡傛灉涓嶆槸杩欎袱绉嶈繘绋嬶紝澧炲姞璁℃暟鍣紝琛ㄧず鍚庡彴鍐欏叆鎿嶄綔鐨勬暟閲 t_thrd.checkpoint_cxt.CheckpointerShmem->num_backend_writes++; } @@ -1162,6 +1378,7 @@ bool CkptForwardSyncRequest(const FileTag *ftag, SyncRequestType type) * backend will have to perform its own fsync request. But before forcing * that to happen, we can try to compact the request queue. */ + // 妫鏌ユ鏌ョ偣杩涚▼鏄惁鏈繍琛岋紝鎴栬呰姹傞槦鍒楁槸鍚﹀凡婊★紝鎴栬呮槸鍚﹀彲鍘嬬缉妫鏌ョ偣璇锋眰闃熷垪 if (t_thrd.checkpoint_cxt.CheckpointerShmem->checkpointer_pid == 0 || (t_thrd.checkpoint_cxt.CheckpointerShmem->num_requests >= t_thrd.checkpoint_cxt.CheckpointerShmem->max_requests && @@ -1170,54 +1387,71 @@ bool CkptForwardSyncRequest(const FileTag *ftag, SyncRequestType type) * Count the subset of writes where backends have to do their own * fsync */ + // 妫鏌ュ綋鍓嶈繘绋嬫槸鍚︿负鍚庡彴鍐欏叆杩涚▼鎴栭〉闈㈠啓鍏ヨ繘绋 if (!AmBackgroundWriterProcess() && !AmPageWriterProcess()) { + // 濡傛灉涓嶆槸杩欎袱绉嶈繘绋嬶紝澧炲姞璁℃暟鍣紝琛ㄧず鍚庡彴鍐欏叆鎿嶄綔鐨勬暟閲 t_thrd.checkpoint_cxt.CheckpointerShmem->num_backend_fsync++; } - LWLockRelease(CheckpointerCommLock); + LWLockRelease(CheckpointerCommLock); // 閲婃斁閿 return false; } /* OK, insert request */ - request = + // 濡傛灉鍙互灏嗚姹傛彃鍏ラ槦鍒楋紝灏嗚姹傛坊鍔犲埌妫鏌ョ偣璇锋眰闃熷垪涓紝骞舵洿鏂伴槦鍒楄鏁板櫒 + request = &t_thrd.checkpoint_cxt.CheckpointerShmem->requests[t_thrd.checkpoint_cxt.CheckpointerShmem->num_requests++]; request->ftag = *ftag; request->type = type; /* If queue is more than half full, nudge the checkpointer to empty it */ + // 妫鏌ヨ姹傞槦鍒楁槸鍚﹀凡缁忚秴杩囦竴鍗婃弧 too_full = (t_thrd.checkpoint_cxt.CheckpointerShmem->num_requests >= t_thrd.checkpoint_cxt.CheckpointerShmem->max_requests / 2); - - LWLockRelease(CheckpointerCommLock); + + LWLockRelease(CheckpointerCommLock); // 閲婃斁杞婚噺绾ч攣锛屽厑璁稿叾浠栬繘绋嬭闂叡浜暟鎹 /* ... but not till after we release the lock */ + // 濡傛灉璇锋眰闃熷垪宸茬粡瓒呰繃涓鍗婃弧锛屽苟涓斿瓨鍦ㄦ鏌ョ偣杩涚▼鐨勭瓑寰呬俊鍙烽噺 if (too_full && g_instance.proc_base->checkpointerLatch) { - SetLatch(g_instance.proc_base->checkpointerLatch); + SetLatch(g_instance.proc_base->checkpointerLatch); // 閱掓鏌ョ偣杩涚▼ } return true; } +/* + * 鍔熻兘锛氬湪涓缁勬枃浠跺悓姝ヨ姹備腑鏌ユ壘閲嶅鐨勮姹傚苟鏍囪 + * + * 鍙傛暟锛 + * requests锛氭枃浠跺悓姝ヨ姹傛暟缁 + * num_requests锛氳姹傛暟閲 鏁扮粍闀垮害 + * + * 杩斿洖鍊硷細 + * int绫诲瀷锛岃繑鍥為噸澶嶈姹傛暟閲 + */ int getDuplicateRequest(CheckpointerRequest *requests, int num_requests, bool *skip_slot) { + // 鐢ㄤ簬灏嗘枃浠跺悓姝ヨ姹傛槧灏勫埌涓涓Ы浣 锛岀敤浜庢爣璁伴噸澶嶇殑璇锋眰 struct CheckpointerSlotMapping { CheckpointerRequest request; int slot; }; int n; - int num_skipped = 0; - HASHCTL ctl; - HTAB* htab = NULL; + int num_skipped = 0; // 璁℃暟鍣紝鐢ㄤ簬璁板綍璺宠繃鐨勯噸澶嶈姹傜殑鏁伴噺 + HASHCTL ctl; // 鐢ㄤ簬璁剧疆鍝堝笇琛ㄧ殑鎺у埗鍙傛暟 + HTAB* htab = NULL; // 鐢ㄤ簬瀛樺偍璇锋眰骞舵煡鎵鹃噸澶嶇殑璇锋眰 /* Initialize temporary hash table */ - errno_t rc = memset_s(&ctl, sizeof(ctl), 0, sizeof(ctl)); + // 鍒濆鍖栫粨鏋勪綋 璁剧疆鍙傛暟 + errno_t rc = memset_s(&ctl, sizeof(ctl), 0, sizeof(ctl)); securec_check(rc, "\0", "\0"); ctl.keysize = sizeof(CheckpointerRequest); ctl.entrysize = sizeof(struct CheckpointerSlotMapping); ctl.hash = tag_hash; ctl.hcxt = CurrentMemoryContext; - + // 鍒涘缓鍝堝笇琛 htab = hash_create("CompactRequestQueue", num_requests, &ctl, HASH_ELEM | HASH_FUNCTION | HASH_CONTEXT); @@ -1234,7 +1468,7 @@ int getDuplicateRequest(CheckpointerRequest *requests, int num_requests, bool *s * anyhow), but it's not clear that the extra complexity would buy us * anything. */ - + // 閬嶅巻缁欏畾鐨勬枃浠跺悓姝ヨ姹傛暟缁 for (n = 0; n < num_requests; n++) { CheckpointerRequest* request = NULL; struct CheckpointerSlotMapping* slotmap; @@ -1247,28 +1481,34 @@ int getDuplicateRequest(CheckpointerRequest *requests, int num_requests, bool *s * CheckpointerShmemInit. Note also that RelFileNode had better * contain no pad bytes. */ - request = &requests[n]; + request = &requests[n]; // 鑾峰彇褰撳墠璇锋眰 + // 鐢ㄥ搱甯岃〃 htab 鏌ユ壘褰撳墠璇锋眰鏄惁宸茬粡瀛樺湪 slotmap = (CheckpointerSlotMapping*)hash_search(htab, request, HASH_ENTER, &found); if (found) { /* Duplicate, so mark the previous occurrence as skippable */ + // 濡傛灉鎵惧埌鐩稿悓鐨勮姹 + // 鏍囪鍓嶄竴涓姹傜殑妲戒綅涓哄彲璺宠繃 skip_slot[slotmap->slot] = true; - num_skipped++; + num_skipped++; // 澧炲姞璁℃暟 } /* Remember slot containing latest occurrence of this request value */ + // 濡傛灉娌℃湁鎵惧埌鐩稿悓鐨勮姹傦紝灏嗗綋鍓嶈姹傛彃鍏ュ搱甯岃〃涓紝鍚屾椂璁板綍璇ヨ姹傜殑妲戒綅 slotmap->slot = n; } /* Done with the hash table. */ + // 閬嶅巻瀹屾墍鏈夎姹傚悗锛岄攢姣佸搱甯岃〃 hash_destroy(htab); /* If no duplicates, we're out of luck. */ if (!num_skipped) { + // 濡傛灉娌℃湁璺宠繃鐨勮姹傦紙鍗虫病鏈夐噸澶嶇殑璇锋眰锛 return 0; } - return num_skipped; + return num_skipped; // 鍚﹀垯锛岃繑鍥炶烦杩囩殑璇锋眰鏁伴噺 } /* @@ -1287,47 +1527,61 @@ int getDuplicateRequest(CheckpointerRequest *requests, int num_requests, bool *s * aren't any removable entries. But that should be vanishingly rare in * practice: there's one queue entry per shared buffer. */ +/* + * 鍔熻兘锛氱鐞嗘鏌ョ偣杩涚▼涓敤浜巉sync鎿嶄綔鐨勮姹傞槦鍒 + * + * 鍙傛暟锛氭棤 + * + * 杩斿洖鍊硷細 + * bool绫诲瀷锛屾寚绀烘槸鍚︿粠璇锋眰闃熷垪涓垹闄や簡浠讳綍閲嶅鐨勬潯鐩 + */ static bool CompactCheckpointerRequestQueue(void) { - int preserve_count; + int preserve_count; // 鐢ㄤ簬璁$畻鍦ㄥ垹闄ら噸澶嶉」鍚庤姹傞槦鍒椾腑搴斾繚鐣欑殑鏉$洰鏁 bool* skip_slot = NULL; - int num_skipped = 0; + int num_skipped = 0; // 璺熻釜鎵惧埌鐨勯噸澶嶉」鏁伴噺 /* must hold CheckpointerCommLock in exclusive mode */ + // 浠ョ嫭鍗犳ā寮忔寔鏈塁heckpointerCommLock閿侊紝鐢ㄤ簬鍚屾瀵瑰叡浜唴瀛樼粨鏋勭殑璁块棶 Assert(LWLockHeldByMe(CheckpointerCommLock)); /* Initialize skip_slot array */ + // 鍒濆鍖栨暟缁勶紝bool绫诲瀷锛岄暱搴︾瓑浜庤姹傞槦鍒椾腑鐨勮姹傛暟 skip_slot = (bool*)palloc0(sizeof(bool) * t_thrd.checkpoint_cxt.CheckpointerShmem->num_requests); + // 璇嗗埆闃熷垪涓殑閲嶅璇锋眰骞舵爣璁帮紝浠ヨ繘琛屽垹闄 + // 鎵惧埌鐨勯噸澶嶉」鏁伴噺瀛樺偍鍦╪um_skipped涓 num_skipped = getDuplicateRequest(t_thrd.checkpoint_cxt.CheckpointerShmem->requests, t_thrd.checkpoint_cxt.CheckpointerShmem->num_requests, skip_slot); /* If no duplicates, we're out of luck. */ - if (num_skipped == 0) { - pfree(skip_slot); - return false; + if (num_skipped == 0) { // 濡傛灉鏈壘鍒伴噸澶嶈姹 + pfree(skip_slot); // 閲婃斁鏁扮粍鍐呭瓨 + return false; // 杩斿洖false锛岃〃绀烘湭鍒犻櫎浠讳綍鏉$洰 } /* We found some duplicates; remove them. */ - preserve_count = 0; - + // 濡傛灉鎵惧埌閲嶅椤癸紝鍒欏垹闄 + preserve_count = 0; // 鐢ㄤ簬璁$畻鍒犻櫎閲嶅椤瑰悗搴斾繚鐣欑殑鏉$洰鏁 + // 寰幆閬嶅巻璇锋眰闃熷垪 for (int n = 0; n < t_thrd.checkpoint_cxt.CheckpointerShmem->num_requests; n++) { - if (skip_slot[n]) + if (skip_slot[n]) // 濡傛灉璇ユ潯鐩簲璺宠繃锛堝嵆涓洪噸澶嶉」锛 continue; - + // 闈為噸澶嶉」锛屽皢璇ユ潯鐩繚鐣欏湪闃熷垪涓 t_thrd.checkpoint_cxt.CheckpointerShmem->requests[preserve_count++] = t_thrd.checkpoint_cxt.CheckpointerShmem->requests[n]; } - + // 鐢熸垚涓涓皟璇曟秷鎭紝鎶ュ憡鍦ㄥ帇缂╁墠鍚庣殑鏉$洰鏁伴噺 ereport(DEBUG1, (errmsg("compacted fsync request queue from %d entries to %d entries", t_thrd.checkpoint_cxt.CheckpointerShmem->num_requests, preserve_count))); + // 鏇存柊璇锋眰闃熷垪涓殑璇锋眰鏁 t_thrd.checkpoint_cxt.CheckpointerShmem->num_requests = preserve_count; /* Cleanup. */ - pfree(skip_slot); - return true; + pfree(skip_slot); // 閲婃斁鏁扮粍鍐呭瓨 + return true; // 杩斿洖true锛岃〃绀哄凡浠庤姹傞槦鍒椾腑鍒犻櫎浜嗛噸澶嶆潯鐩 } /* @@ -1339,14 +1593,23 @@ static bool CompactCheckpointerRequestQueue(void) * we start fsync'ing. Since CreateCheckPoint sometimes runs in * non-checkpointer processes, do nothing if not checkpointer. */ +/* + * 鍔熻兘锛 + * 妫鏌ユ鏌ョ偣杩涚▼鏄惁闇瑕佸惛鏀舵帓闃熺殑鏂囦欢鍚屾璇锋眰 + * 骞跺皢杩欎簺璇锋眰浼犻掔粰鏈湴鐨剆mgr锛堝瓨鍌ㄧ鐞嗗櫒锛夎繘琛屽鐞 + * + * 鍙傛暟锛氭棤 + * + * 杩斿洖鍊硷細鏃 + */ void CkptAbsorbFsyncRequests(void) { - CheckpointerRequest* requests = NULL; - CheckpointerRequest* request = NULL; - int n; + CheckpointerRequest* requests = NULL; // 鐢ㄤ簬瀛樺偍鎺掗槦鐨勫悓姝ヨ姹 + CheckpointerRequest* request = NULL; // 鐢ㄤ簬杩唬澶勭悊杩欎簺璇锋眰 + int n; // 鐢ㄤ簬琛ㄧず鎺掗槦璇锋眰鐨勬暟閲 - if (!AmCheckpointerProcess()) - return; + if (!AmCheckpointerProcess()) // 濡傛灉涓嶆槸妫鏌ョ偣杩涚▼ + return; // 杩斿洖 /* * We have to PANIC if we fail to absorb all the pending requests (eg, @@ -1355,61 +1618,79 @@ void CkptAbsorbFsyncRequests(void) * fsync. Fortunately, the hashtable is so small that the problem is * quite unlikely to arise in practice. */ + // 寮濮嬩竴涓复鐣屽尯锛岀‘淇濅互涓嬫搷浣滆兘澶熶互鍘熷瓙鏂瑰紡鎵ц锛岄伩鍏嶅苟鍙戦棶棰 START_CRIT_SECTION(); /* * We try to avoid holding the lock for a long time by copying the request * array. */ + // 浠ョ嫭鍗犳ā寮忚幏鍙栭攣 LWLockAcquire(CheckpointerCommLock, LW_EXCLUSIVE); /* Transfer stats counts into pending pgstats message */ + // 璺熻釜鍚庡彴鍐欏叆鍜屽悗鍙版枃浠跺悓姝ョ殑缁熻鏁版嵁 + // 灏唍um_backend_writes鍜宯um_backend_fsync鐨勫肩疮鍔犲埌缁熻淇℃伅涓 u_sess->stat_cxt.BgWriterStats->m_buf_written_backend += t_thrd.checkpoint_cxt.CheckpointerShmem->num_backend_writes; u_sess->stat_cxt.BgWriterStats->m_buf_fsync_backend += t_thrd.checkpoint_cxt.CheckpointerShmem->num_backend_fsync; t_thrd.checkpoint_cxt.CheckpointerShmem->num_backend_writes = 0; t_thrd.checkpoint_cxt.CheckpointerShmem->num_backend_fsync = 0; - + // 鑾峰彇鎺掗槦璇锋眰鐨勬暟閲 n = t_thrd.checkpoint_cxt.CheckpointerShmem->num_requests; if (n > 0) { errno_t rc; + // 澶嶅埗鏂囦欢鍚屾璇锋眰鏁版嵁 requests = (CheckpointerRequest*)palloc(n * sizeof(CheckpointerRequest)); + // 灏嗘枃浠跺悓姝ヨ姹備粠鍏变韩鍐呭瓨涓鍒跺埌鏈湴鍐呭瓨涓 rc = memcpy_s(requests, n * sizeof(CheckpointerRequest), t_thrd.checkpoint_cxt.CheckpointerShmem->requests, n * sizeof(CheckpointerRequest)); - securec_check(rc, "\0", "\0"); + securec_check(rc, "\0", "\0"); // 妫鏌ュ嚱鏁版槸鍚︽墽琛屾垚鍔 } - + // 閲嶇疆璇锋眰闃熷垪涓殑璇锋眰鏁伴噺涓洪浂锛屼互娓呴櫎鎺掗槦鐨勮姹 t_thrd.checkpoint_cxt.CheckpointerShmem->num_requests = 0; - + // 閲婃斁閿 LWLockRelease(CheckpointerCommLock); - + // 杩唬澶勭悊鎺掗槦鐨勮姹 for (request = requests; n > 0; request++, n--) { + // 璁板綍闇瑕佽繘琛屽悓姝ョ殑鏂囦欢淇℃伅鍜屾搷浣滅被鍨 RememberSyncRequest(&request->ftag, request->type); } - if (requests != NULL) { - pfree(requests); + // 濡傛灉闈炵┖锛屽嵆涔嬪墠鍒嗛厤浜嗗唴瀛樼敤浜庡瓨鍌ㄦ枃浠跺悓姝ヨ姹傛暟鎹 + if (requests != NULL) { + pfree(requests); // 閲婃斁鍐呭瓨 } - END_CRIT_SECTION(); + END_CRIT_SECTION(); // 缁撴潫涓寸晫鍖 } /* * Update any shared memory configurations based on config parameters */ +/* + * 鍔熻兘锛氭洿鏂板叡浜唴瀛樹腑鐨勯厤缃弬鏁 + * + * 鍙傛暟锛氭棤 + * + * 杩斿洖鍊硷細鏃 + */ static void UpdateSharedMemoryConfig(void) { /* update global shmem state for sync rep */ + // 鏇存柊鍏变韩鍐呭瓨涓殑鍏充簬鍚屾澶嶅埗鐨勯厤缃弬鏁 SyncRepUpdateSyncStandbysDefined(); /* * If full_page_writes has been changed by SIGHUP, we update it in shared * memory and write an XLOG_FPW_CHANGE record. */ + // 妫鏌ュ苟鏇存柊 full_page_writes 閰嶇疆鍙傛暟鐨勫 + // 骞跺湪闇瑕佹椂璁板綍涓涓 XLOG_FPW_CHANGE WAL 璁板綍 UpdateFullPageWrites(); - + // 璁板綍璋冭瘯鏃ュ織娑堟伅锛屾寚绀烘鏌ョ偣杩涚▼宸茬粡鏇存柊浜嗗叡浜唴瀛樹腑鐨勯厤缃弬鏁板 ereport(DEBUG2, (errmsg("checkpointer updated shared memory configuration values"))); } @@ -1417,43 +1698,74 @@ static void UpdateSharedMemoryConfig(void) * FirstCallSinceLastCheckpoint allows a process to take an action once * per checkpoint cycle by asynchronously checking for checkpoint completion. */ +/* + * 鍔熻兘锛氭鏌ユ槸鍚︽槸鑷笂娆℃鏌ョ偣浠ユ潵鐨勭涓娆¤皟鐢 + * + * 鍙傛暟锛氭棤 + * + * 杩斿洖鍊硷細 + * bool绫诲瀷锛岃繑鍥炴槸鍚︾涓娆¤皟鐢ㄨ鍑芥暟 + * 濡傛灉鏄涓娆¤皟鐢ㄥ垯杩斿洖true锛屽惁鍒欒繑鍥瀎alse + */ bool FirstCallSinceLastCheckpoint(void) { /* use volatile pointer to prevent code rearrangement */ volatile CheckpointerShmemStruct* cps = t_thrd.checkpoint_cxt.CheckpointerShmem; - int new_done; - bool FirstCall = false; - - SpinLockAcquire(&cps->ckpt_lck); - new_done = cps->ckpt_done; - SpinLockRelease(&cps->ckpt_lck); + int new_done; // 鐢ㄤ簬瀛樺偍鏂扮殑妫鏌ョ偣瀹屾垚璁℃暟鍊 + bool FirstCall = false; // 鐢ㄤ簬琛ㄧず鏄惁鏄嚜涓婃妫鏌ョ偣浠ユ潵鐨勭涓娆¤皟鐢 + SpinLockAcquire(&cps->ckpt_lck); // 鑾峰彇鑷棆閿 + new_done = cps->ckpt_done; // 鑾峰緱妫鏌ョ偣瀹屾垚鐨勪俊鎭 + SpinLockRelease(&cps->ckpt_lck); // 閲婃斁閿 + // 姣旇緝鏂版棫鏁板硷紝濡傛灉涓嶇浉绛夛紝璇存槑鍙戠敓浜嗘柊鐨勬鏌ョ偣 if (new_done != t_thrd.checkpoint_cxt.ckpt_done) - FirstCall = true; + FirstCall = true; // 琛ㄧず杩欐槸绗竴娆¤皟鐢 - t_thrd.checkpoint_cxt.ckpt_done = new_done; + t_thrd.checkpoint_cxt.ckpt_done = new_done; // 鏇存柊璁℃暟鍣ㄤ俊鎭 return FirstCall; } #ifdef ENABLE_MOT +/* + * 鍔熻兘锛 娉ㄥ唽妫鏌ョ偣鍥炶皟鍑芥暟 + * + * 鍙傛暟锛 + * callback-鍑芥暟鎸囬拡锛屾寚鍚戣娉ㄥ唽鐨勫洖璋冨嚱鏁 + * arg-鍥炶皟鍑芥暟鐨勫弬鏁帮紝鐢ㄤ簬浼犻掗澶栫殑鏁版嵁缁欏洖璋冨嚱鏁 + * + * 杩斿洖鍊硷細鏃 + */ void RegisterCheckpointCallback(CheckpointCallback callback, void* arg) { CheckpointCallbackItem *item; - + // 鍒嗛厤缁撴瀯浣撳唴瀛 item = (CheckpointCallbackItem*)MemoryContextAlloc( INSTANCE_GET_MEM_CXT_GROUP(MEMORY_CONTEXT_STORAGE), sizeof(CheckpointCallbackItem)); - item->callback = callback; - item->arg = arg; - item->next = g_instance.ckpt_cxt_ctl->ckptCallback; + // 鍙傛暟璧嬪 + item->callback = callback; // 娉ㄥ唽鐨勫洖璋冨嚱鏁扮殑鍑芥暟鎸囬拡 + item->arg = arg; // 鍥炶皟鍑芥暟鐨勫弬鏁 + // 褰撳墠鍥炶皟鍑芥暟閾捐〃鐨勫ご閮紝琛ㄧず鏂版敞鍐岀殑鍥炶皟鍑芥暟浼氳娣诲姞鍒伴摼琛ㄧ殑澶撮儴 + item->next = g_instance.ckpt_cxt_ctl->ckptCallback; + // 鏇存柊鍏ㄥ眬鍥炶皟鍑芥暟閾捐〃 g_instance.ckpt_cxt_ctl->ckptCallback = item; } +/* + * 鍔熻兘锛 鍦ㄦ鏌ョ偣浜嬩欢鍙戠敓鏃惰皟鐢ㄥ凡娉ㄥ唽鐨勬鏌ョ偣鍥炶皟鍑芥暟 + * + * 鍙傛暟锛 + * checkpointEvent-琛ㄧず妫鏌ョ偣浜嬩欢鐨勭被鍨 + * lsn-琛ㄧず涓庢鏌ョ偣浜嬩欢鐩稿叧鐨勯昏緫鏃ュ織搴忓垪鍙 + * + * 杩斿洖鍊硷細鏃 + */ void CallCheckpointCallback(CheckpointEvent checkpointEvent, XLogRecPtr lsn) { CheckpointCallbackItem* item; - + // 閬嶅巻鍥炶皟鍑芥暟閾捐〃 for (item = g_instance.ckpt_cxt_ctl->ckptCallback; item; item = item->next) { + // 璋冪敤姣忎釜娉ㄥ唽鐨勫洖璋冨嚱鏁帮紝浼犻掔浉搴旂殑鍙傛暟 (*item->callback) (checkpointEvent, lsn, item->arg); } } diff --git a/src/gausskernel/process/postmaster/fencedudf.cpp b/src/gausskernel/process/postmaster/fencedudf.cpp index cc95b5c00..10108431a 100644 --- a/src/gausskernel/process/postmaster/fencedudf.cpp +++ b/src/gausskernel/process/postmaster/fencedudf.cpp @@ -80,7 +80,7 @@ typedef enum { UDF_INFO = 5, UDF_ARGS, UDF_RESULT, UDF_ERROR } UDFMsgType; typedef enum { UDF_SEND_ARGS = 0, UDF_RECV_ARGS = 1, UDF_SEND_RESULT = 2, UDF_RECV_RESULT = 3 } UDFArgHandlerType; -typedef enum { C_UDF, JAVA_UDF, PYTHON_UDF} UDF_LANG; +typedef enum { C_UDF, JAVA_UDF, PYTHON_UDF } UDF_LANG; typedef enum { MASTER_PROCESS = 1, WORK_PROCESS, KILL_WORK } UDF_Process; @@ -105,21 +105,21 @@ typedef enum { typedef enum { OPTION_ADDJAR = 0, OPTION_LS, OPTION_RMJAR } LibraryOptType; typedef struct OBSInfo { - char* accesskey; - char* secretkey; - char* region; - char* bucket; - char* path; + char *accesskey; + char *secretkey; + char *region; + char *bucket; + char *path; } OBSInfo; typedef struct LibraryInfo { - char* option; - char* operation; + char *option; + char *operation; LibraryOptType optionType; - char* destpath; + char *destpath; bool isSourceLocal; - char* localpath; - OBSInfo* obsInfo; + char *localpath; + OBSInfo *obsInfo; } LibraryInfo; #define KB 1024 @@ -133,17 +133,17 @@ THR_LOCAL Oid lastUDFOid = InvalidOid; static MemoryContext UDFWorkMemContext = NULL; static int listenUDFSocket = -1; static bool UDFMasterQuitFlag = false; -static HTAB* UDFFuncHash = NULL; +static HTAB *UDFFuncHash = NULL; /* PRC Server Declaration */ static void UDFMasterServerLoop(); static void UDFWorkerMain(int socket); static pid_t StartUDFWorker(int socket); static void SIGQUITUDFMaster(SIGNAL_ARGS); -static void RecvUDFInformation(int socket, FunctionCallInfoData* fcinfo); -static void FindOrInsertUDFHashTab(FunctionCallInfoData* fcinfo); +static void RecvUDFInformation(int socket, FunctionCallInfoData *fcinfo); +static void FindOrInsertUDFHashTab(FunctionCallInfoData *fcinfo); static void UDFCreateHashTab(); -void SetUDFUnixSocketPath(struct sockaddr_un* unAddrPtr); +void SetUDFUnixSocketPath(struct sockaddr_un *unAddrPtr); /* RPC Client Declaration */ template @@ -152,40 +152,51 @@ static void SendUDFInformation(FunctionCallInfo fcinfo); template extern Datum RPCFencedUDF(FunctionCallInfo fcinfo); -bool RPCInitFencedUDFIfNeed(Oid functionId, FmgrInfo* finfo, HeapTuple procedureTuple); -void InitFuncCallUDFInfo(FunctionCallInfoData* fcinfo, int argN, bool setFuncPtr); -void InitUDFInfo(UDFInfoType* udfInfo, int argN, int batchRows); -void FencedUDFMasterMain(int argc, char* argv[]); +bool RPCInitFencedUDFIfNeed(Oid functionId, FmgrInfo *finfo, HeapTuple procedureTuple); +void InitFuncCallUDFInfo(FunctionCallInfoData *fcinfo, int argN, bool setFuncPtr); +void InitUDFInfo(UDFInfoType *udfInfo, int argN, int batchRows); +void FencedUDFMasterMain(int argc, char *argv[]); /* Extern Enterface Declaration */ -extern void* internal_load_library(const char* libname); - +extern void *internal_load_library(const char *libname); +/* + * 鍔熻兘锛氬惎鍔║DF涓昏繘绋 + * + * 鍙傛暟鍒楄〃锛氭棤 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庡垱寤哄苟鍚姩涓涓柊鐨勮繘绋嬶紝鍏朵腑瀛愯繘绋嬫墽琛屼簡 FencedUDFMasterMain() 鍑芥暟锛岃岀埗杩涚▼缁х画鎵ц鍚庣画閫昏緫銆 + */ void StartUDFMaster() { + // 鍒涘缓鍙橀噺浠ュ瓨鍌ㄦ柊杩涚▼鐨凱ID pid_t fencedWorkPid = 0; + // 浣跨敤 switch-case 璇彞澶勭悊 fork_process() 鐨勮繑鍥炲 switch ((fencedWorkPid = fork_process())) { case -1: { + // 瀛愯繘绋嬪垱寤哄け璐ユ椂鐨勫鐞嗛昏緫 int errsv = errno; ereport(WARNING, - (errmodule(MOD_UDF), - errcode(ERRCODE_INVALID_STATUS), - errmsg("could not fork gaussDB process, errno:%d, error reason:%s", - errsv, - strerror(errsv)))); + (errmodule(MOD_UDF), errcode(ERRCODE_INVALID_STATUS), + errmsg("could not fork gaussDB process, errno:%d, error reason:%s", errsv, strerror(errsv)))); break; } case 0: { - + // 瀛愯繘绋嬬殑澶勭悊閫昏緫 + // 璋冪敤 FencedUDFMasterMain() 鍑芥暟锛屽瓙杩涚▼浼氬湪杩欎釜鍑芥暟涓墽琛 FencedUDFMasterMain(0, NULL); + // 瀛愯繘绋嬫墽琛屽畬姣曞悗閫鍑 exit(0); break; } default: { + // 鐖惰繘绋嬬殑澶勭悊閫昏緫锛屼笉鎵ц鍏蜂綋鎿嶄綔 break; } } } + /* * @Description: The main function of UDF RPC server. * It will initialize envrionment, create listen socket and startup @@ -193,7 +204,7 @@ void StartUDFMaster() * @IN argc: the number of argment value * @IN argv: the argment values */ -void FencedUDFMasterMain(int argc, char* argv[]) +void FencedUDFMasterMain(int argc, char *argv[]) { SetProcessingMode(FencedProcessing); @@ -229,8 +240,8 @@ void FencedUDFMasterMain(int argc, char* argv[]) #if ((defined ENABLE_PYTHON2) || (defined ENABLE_PYTHON3)) BaseInit(); InitProcess(); - t_thrd.utils_cxt.CurrentResourceOwner = ResourceOwnerCreate(NULL, "fencedMaster", - THREAD_GET_MEM_CXT_GROUP(MEMORY_CONTEXT_AI)); + t_thrd.utils_cxt.CurrentResourceOwner = + ResourceOwnerCreate(NULL, "fencedMaster", THREAD_GET_MEM_CXT_GROUP(MEMORY_CONTEXT_AI)); #endif /* @@ -249,7 +260,7 @@ void FencedUDFMasterMain(int argc, char* argv[]) SetUDFUnixSocketPath(&unAddr); unlink(unAddr.sun_path); - if (bind(listenUDFSocket, (struct sockaddr*)&unAddr, sizeof(unAddr)) < 0) { + if (bind(listenUDFSocket, (struct sockaddr *)&unAddr, sizeof(unAddr)) < 0) { ereport(FATAL, (errmodule(MOD_UDF), errmsg("bind socket path %s failed:%m", unAddr.sun_path))); } if (listen(listenUDFSocket, 65536) < 0) { @@ -309,12 +320,9 @@ void UDFMasterServerLoop() if (selres < 0) { if (errno != EINTR && errno != EWOULDBLOCK) { int errsv = errno; - ereport(ERROR, - (errmodule(MOD_UDF), - errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("poll() failed in UDFMasterServerLoop, errno:%d, error reason:%s", - errsv, - strerror(errsv)))); + ereport(ERROR, (errmodule(MOD_UDF), errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("poll() failed in UDFMasterServerLoop, errno:%d, error reason:%s", errsv, + strerror(errsv)))); return; } } @@ -325,24 +333,19 @@ void UDFMasterServerLoop() */ if (selres > 0) { if (ufds[0].fd == PGINVALID_SOCKET) { - ereport(WARNING, - (errmodule(MOD_UDF), - errcode(ERRCODE_CONNECTION_EXCEPTION), - errmsg("poll() returned %d, but the first file descriptor is invalid.", selres))); + ereport(WARNING, (errmodule(MOD_UDF), errcode(ERRCODE_CONNECTION_EXCEPTION), + errmsg("poll() returned %d, but the first file descriptor is invalid.", selres))); break; } if (ufds[0].fd != listenUDFSocket) { ereport(WARNING, - (errmodule(MOD_UDF), - errcode(ERRCODE_CONNECTION_EXCEPTION), - errmsg("poll() returned %d, but the first file descriptor is not listenUDFSocket.", selres))); + (errmodule(MOD_UDF), errcode(ERRCODE_CONNECTION_EXCEPTION), + errmsg("poll() returned %d, but the first file descriptor is not listenUDFSocket.", selres))); break; } if (((unsigned int)ufds[0].revents) & POLLERR) { - ereport(WARNING, - (errmodule(MOD_UDF), - errcode(ERRCODE_CONNECTION_EXCEPTION), - errmsg("poll() returned %d, but ufds[0].revents returned with POLLERR", selres))); + ereport(WARNING, (errmodule(MOD_UDF), errcode(ERRCODE_CONNECTION_EXCEPTION), + errmsg("poll() returned %d, but ufds[0].revents returned with POLLERR", selres))); } if (((unsigned int)ufds[0].revents) & POLLIN) { @@ -352,28 +355,21 @@ void UDFMasterServerLoop() if (socket < 0) { int errsv = errno; - ereport(WARNING, - (errmodule(MOD_UDF), - errcode(ERRCODE_CONNECTION_EXCEPTION), - errmsg("accept failed, errno:%d, error reason:%s", errsv, strerror(errsv)))); + ereport(WARNING, (errmodule(MOD_UDF), errcode(ERRCODE_CONNECTION_EXCEPTION), + errmsg("accept failed, errno:%d, error reason:%s", errsv, strerror(errsv)))); } else { int res; if (StartUDFWorker(socket) < 0) { - ereport(WARNING, - (errmodule(MOD_UDF), - errcode(ERRCODE_INVALID_STATUS), - errmsg("failed to fork fencedWorker porcess"))); + ereport(WARNING, (errmodule(MOD_UDF), errcode(ERRCODE_INVALID_STATUS), + errmsg("failed to fork fencedWorker porcess"))); } /* we must close socket because worker process have inherit it */ res = close(socket); if (res != 0) { int errsv = errno; - ereport(WARNING, - (errmodule(MOD_UDF), - errcode(ERRCODE_CONNECTION_EXCEPTION), - errmsg("UDF master close client socket failed, errno:%d, error reason:%s", - errsv, - strerror(errsv)))); + ereport(WARNING, (errmodule(MOD_UDF), errcode(ERRCODE_CONNECTION_EXCEPTION), + errmsg("UDF master close client socket failed, errno:%d, error reason:%s", + errsv, strerror(errsv)))); } } } @@ -392,16 +388,13 @@ pid_t StartUDFWorker(int socket) switch ((fencedWorkPid = fork_process())) { case -1: { int errsv = errno; - ereport(WARNING, - (errmodule(MOD_UDF), - errcode(ERRCODE_INVALID_STATUS), - errmsg("could not fork fenced UDF master process, errno:%d, error reason:%s", - errsv, - strerror(errsv)))); + ereport(WARNING, (errmodule(MOD_UDF), errcode(ERRCODE_INVALID_STATUS), + errmsg("could not fork fenced UDF master process, errno:%d, error reason:%s", errsv, + strerror(errsv)))); break; } case 0: { - /* Child process */ + /* Child process */ /* Just make set_ps_dispaly ok */ IsUnderPostmaster = true; @@ -410,10 +403,8 @@ pid_t StartUDFWorker(int socket) close(listenUDFSocket); listenUDFSocket = -1; } else { - ereport(WARNING, - (errmodule(MOD_UDF), - errcode(ERRCODE_INVALID_STATUS), - errmsg("Unexpected error occurs, listenUDFSocket <= -1"))); + ereport(WARNING, (errmodule(MOD_UDF), errcode(ERRCODE_INVALID_STATUS), + errmsg("Unexpected error occurs, listenUDFSocket <= -1"))); } set_ps_display("gaussdb fenced UDF worker process", true); UDFWorkerMain(socket); @@ -429,33 +420,76 @@ pid_t StartUDFWorker(int socket) return fencedWorkPid; } -static inline void SendMsg(int socket, char* val, int len) +/* + * 鍔熻兘锛氬悜鎸囧畾鐨勫鎺ュ瓧鍙戦佹秷鎭 + * + * 鍙傛暟鍒楄〃锛 + * socket锛氱洰鏍囧鎺ュ瓧鐨勬枃浠舵弿杩扮 + * val锛氳鍙戦佺殑娑堟伅鐨勮捣濮嬪湴鍧 + * len锛氳鍙戦佺殑娑堟伅鐨勯暱搴 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庡悜鎸囧畾鐨勫鎺ュ瓧鍙戦佹秷鎭紝纭繚娑堟伅鐨勯暱搴﹀ぇ浜0銆 + */ +static inline void SendMsg(int socket, char *val, int len) { + // 纭繚娑堟伅鐨勯暱搴﹀ぇ浜0锛屽惁鍒欐姤閿 AssertEreport(len > 0, MOD_UDF, "Msg's length should be greater than 0 when it's being sent."); - char* startPtr = val; - char* endPtr = val + len; + + // 鍒濆鍖栨寚閽堬紝鎸囧悜娑堟伅鐨勮捣濮嬪湴鍧鍜岀粨鏉熷湴鍧 + char *startPtr = val; + char *endPtr = val + len; + + // 寰幆鍙戦佹秷鎭紝鐩村埌鎵鏈夋秷鎭兘琚彂閫佸畬姣 while (startPtr < endPtr) { + // 浣跨敤 write() 鍑芥暟鍚戝鎺ュ瓧鍙戦佹秷鎭 int nbytes = write(socket, startPtr, endPtr - startPtr); + + // 澶勭悊鍙戦侀敊璇 if (nbytes < 0) { if (errno == EINTR) - continue; /* Ok if interrupted */ - ereport(ERROR, - (errmodule(MOD_UDF), errcode(ERRCODE_CONNECTION_FAILURE), errmsg("Socket send %d bytes: %m", nbytes))); + continue; /* 濡傛灉鍙戦佽涓柇锛岀户缁彂閫 */ + // 鍙戦佸け璐ワ紝鎶ラ敊 + ereport(ERROR, (errmodule(MOD_UDF), errcode(ERRCODE_CONNECTION_FAILURE), + errmsg("Socket send %d bytes: %m", nbytes))); } + // 鏇存柊鎸囬拡锛屾寚鍚戝皻鏈彂閫佺殑娑堟伅閮ㄥ垎 startPtr += nbytes; } } -static inline void RecvMsg(int socket, char* buffer, int len, bool isIdle = false) +/* + * 鍔熻兘锛氫粠鎸囧畾鐨勫鎺ュ瓧鎺ユ敹娑堟伅 + * + * 鍙傛暟鍒楄〃锛 + * socket锛氱洰鏍囧鎺ュ瓧鐨勬枃浠舵弿杩扮 + * buffer锛氱敤浜庡瓨鍌ㄦ帴鏀舵秷鎭殑缂撳啿鍖 + * len锛氭湡鏈涙帴鏀剁殑娑堟伅闀垮害 + * isIdle锛氭爣蹇楋紝鎸囩ず鏄惁澶勪簬绌洪棽鐘舵 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庝粠鎸囧畾鐨勫鎺ュ瓧鎺ユ敹娑堟伅锛岀‘淇濇帴鏀剁殑瀛楄妭鏁扮瓑浜庢湡鏈涚殑娑堟伅闀垮害銆 + * 濡傛灉鎺ユ敹杩囩▼涓嚭鐜伴敊璇紝灏嗙敓鎴愮浉搴旂殑閿欒鎶ュ憡骞舵牴鎹儏鍐甸鍑恒 + */ +static inline void RecvMsg(int socket, char *buffer, int len, bool isIdle = false) { + // 鍒濆鍖栨帴鏀跺瓧鑺傛暟 int recvBytes = 0; + + // 鍒濆鍖栫敤浜庢彁绀烘秷鎭殑瀛楃涓 StringInfoData hintMsgStr; + + // 寰幆鎺ユ敹娑堟伅锛岀洿鍒版帴鏀跺埌鏈熸湜鐨勫瓧鑺傛暟 while (recvBytes < len) { + // 浣跨敤 read() 鍑芥暟浠庡鎺ュ瓧鎺ユ敹娑堟伅 int bytes = read(socket, buffer + recvBytes, len - recvBytes); + + // 澶勭悊鎺ユ敹閿欒 if (bytes <= 0) { if (errno == EINTR) continue; /* Ok if interrupted */ - char* err_reason = strerror(errno); + // 鑾峰彇閿欒鍘熷洜瀛楃涓 + char *err_reason = strerror(errno); /* The udf worker process is finished. */ if (!IS_PGXC_COORDINATOR && !IS_PGXC_DATANODE && isIdle) { @@ -466,8 +500,8 @@ static inline void RecvMsg(int socket, char* buffer, int len, bool isIdle = fals * function is called from UDF master/worker, myName should be * "UDF Master/Worker". */ - char* myName = "UDF Master/Worker"; - char* peerName = "GaussDB Kernel(CN/DN)"; + char *myName = "UDF Master/Worker"; + char *peerName = "GaussDB Kernel(CN/DN)"; if (IS_PGXC_COORDINATOR || IS_PGXC_DATANODE) { #ifdef PGXC myName = g_instance.attr.attr_common.PGXCNodeName; @@ -477,20 +511,18 @@ static inline void RecvMsg(int socket, char* buffer, int len, bool isIdle = fals peerName = "UDF Master/Worker"; } + // 鍒濆鍖栭敊璇秷鎭瓧绗︿覆 StringInfoData errMsgStr; initStringInfo(&errMsgStr); appendStringInfo(&errMsgStr, - "The connection between '%s' and '%s' maybe closed. '%s' recv %d bytes. Error: %s", - myName, - peerName, - myName, - bytes, - err_reason); + "The connection between '%s' and '%s' maybe closed. '%s' recv %d bytes. Error: %s", myName, + peerName, myName, bytes, err_reason); if (IS_PGXC_COORDINATOR || IS_PGXC_DATANODE) { initStringInfo(&hintMsgStr); if (u_sess->attr.attr_sql.FencedUDFMemoryLimit) { - appendStringInfo(&hintMsgStr, + appendStringInfo( + &hintMsgStr, "FencedUDFMemoryLimit is set to %dKB. Please check if it is too small, or you can just set " "FencedUDFMemoryLimit to 0KB, which will not limit visual memory usage.", u_sess->attr.attr_sql.FencedUDFMemoryLimit); @@ -498,7 +530,8 @@ static inline void RecvMsg(int socket, char* buffer, int len, bool isIdle = fals if (strlen(u_sess->attr.attr_sql.pljava_vmoptions) > 0) { if (strlen(hintMsgStr.data) > 0) appendStringInfo(&hintMsgStr, "\n"); - appendStringInfo(&hintMsgStr, + appendStringInfo( + &hintMsgStr, "pljava_vmoptions is set to '%s', please check every parameter in it, e.g., if -Xmx or " "-XX:MaxMetaspaceSize are set, please check if they are too large compared to " "FencedUDFMemoryLimit", @@ -511,57 +544,75 @@ static inline void RecvMsg(int socket, char* buffer, int len, bool isIdle = fals pfree_ext(hintMsgStr.data); } + // 鐢熸垚閿欒鎶ュ憡骞堕鍑 ereport(ERROR, (errmodule(MOD_UDF), errcode(ERRCODE_DATA_EXCEPTION), errmsg("%s", errMsgStr.data))); - pfree_ext(errMsgStr.data); - exit(0); } + // 鏇存柊鎺ユ敹瀛楄妭鏁 recvBytes += bytes; } + + // 纭繚鎺ユ敹鐨勫瓧鑺傛暟绛変簬鏈熸湜鐨勫瓧鑺傛暟 AssertEreport(recvBytes == len, MOD_UDF, "Bytes received is not the same as expected."); } -static char* GetBasicUDFInformation(FunctionCallInfoData* fcinfo) +/* + * 鍔熻兘锛氫粠鍑芥暟璋冪敤淇℃伅涓幏鍙栧熀鏈殑UDF淇℃伅 + * + * 鍙傛暟鍒楄〃锛 + * fcinfo锛氬嚱鏁拌皟鐢ㄤ俊鎭殑鎸囬拡 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁颁粠鍑芥暟璋冪敤淇℃伅涓彁鍙栦簡鍩烘湰鐨刄DF淇℃伅锛屽寘鎷嚱鏁癘ID銆佸唴瀛橀檺鍒躲丳L/Java铏氭嫙鏈洪夐」銆佽瑷OID銆 + * 鍑芥暟鐨剉olatile灞炴с佸嚱鏁板悕銆佸簱璺緞銆佸弬鏁版暟閲忋佸弬鏁扮被鍨嬪拰缁撴灉绫诲瀷銆 + * 鑾峰彇鐨勪俊鎭敤浜嶶DF鎵ц鐨勫垵濮嬪寲銆 + */ +static char *GetBasicUDFInformation(FunctionCallInfoData *fcinfo) { + // 鍒濆鍖栭暱搴︺佸嚱鏁癘ID銆佽瑷OID鍜屽嚱鏁扮殑volatile灞炴 uint len = 0; Oid fnOid = 0; Oid lagOid = 0; char fnVolatile; - FmgrInfo* flinfo = fcinfo->flinfo; - char* readPtr = fcinfo->udfInfo.udfMsgBuf->data; + + // 鑾峰彇鍑芥暟淇℃伅绠$悊鍣 + FmgrInfo *flinfo = fcinfo->flinfo; + + // 鍒濆鍖栬鍙栨寚閽堛佸墿浣欓暱搴 + char *readPtr = fcinfo->udfInfo.udfMsgBuf->data; uint remainLen = fcinfo->udfInfo.udfMsgBuf->len; /* Get Message type */ short msgType; - GetFixedMsgValSafe(readPtr, (char*)&msgType, sizeof(msgType), sizeof(msgType), remainLen); + GetFixedMsgValSafe(readPtr, (char *)&msgType, sizeof(msgType), sizeof(msgType), remainLen); if (msgType == UDF_ARGS) { /* Get Function Oid */ - GetFixedMsgValSafe(readPtr, (char*)&fnOid, sizeof(fnOid), sizeof(fnOid), remainLen); + GetFixedMsgValSafe(readPtr, (char *)&fnOid, sizeof(fnOid), sizeof(fnOid), remainLen); flinfo->fn_oid = fnOid; } else { /* Get memory limit size */ - GetFixedMsgValSafe(readPtr, (char*)&u_sess->attr.attr_sql.FencedUDFMemoryLimit, - sizeof(u_sess->attr.attr_sql.FencedUDFMemoryLimit), - sizeof(u_sess->attr.attr_sql.FencedUDFMemoryLimit), remainLen); + GetFixedMsgValSafe(readPtr, (char *)&u_sess->attr.attr_sql.FencedUDFMemoryLimit, + sizeof(u_sess->attr.attr_sql.FencedUDFMemoryLimit), + sizeof(u_sess->attr.attr_sql.FencedUDFMemoryLimit), remainLen); /* Get pljava_vmoptions */ - GetFixedMsgValSafe(readPtr, (char*)&len, sizeof(len), sizeof(len), remainLen); - u_sess->attr.attr_sql.pljava_vmoptions = (char*)palloc(len + 1); + GetFixedMsgValSafe(readPtr, (char *)&len, sizeof(len), sizeof(len), remainLen); + u_sess->attr.attr_sql.pljava_vmoptions = (char *)palloc(len + 1); GetFixedMsgValSafe(readPtr, u_sess->attr.attr_sql.pljava_vmoptions, len, len + 1, remainLen); u_sess->attr.attr_sql.pljava_vmoptions[len] = 0; /* Get Function Oid */ - GetFixedMsgValSafe(readPtr, (char*)&fnOid, sizeof(fnOid), sizeof(fnOid), remainLen); + GetFixedMsgValSafe(readPtr, (char *)&fnOid, sizeof(fnOid), sizeof(fnOid), remainLen); flinfo->fn_oid = fnOid; /* Get Language Oid */ - GetFixedMsgValSafe(readPtr, (char*)&lagOid, sizeof(lagOid), sizeof(lagOid), remainLen); + GetFixedMsgValSafe(readPtr, (char *)&lagOid, sizeof(lagOid), sizeof(lagOid), remainLen); flinfo->fn_languageId = lagOid; /* Get func volatile propertie */ - GetFixedMsgValSafe(readPtr, (char*)&fnVolatile, sizeof(fnVolatile), sizeof(fnVolatile), remainLen); + GetFixedMsgValSafe(readPtr, (char *)&fnVolatile, sizeof(fnVolatile), sizeof(fnVolatile), remainLen); flinfo->fn_volatile = fnVolatile; /* Get UDF name */ @@ -569,37 +620,46 @@ static char* GetBasicUDFInformation(FunctionCallInfoData* fcinfo) flinfo->fnName[len] = 0; /* Get Library path */ - GetFixedMsgValSafe(readPtr, (char*)&len, sizeof(len), sizeof(len), remainLen); - flinfo->fnLibPath = (char*)palloc(len + 1); + GetFixedMsgValSafe(readPtr, (char *)&len, sizeof(len), sizeof(len), remainLen); + flinfo->fnLibPath = (char *)palloc(len + 1); GetFixedMsgValSafe(readPtr, flinfo->fnLibPath, len, len + 1, remainLen); flinfo->fnLibPath[len] = 0; /* Get Argument number */ - GetFixedMsgValSafe(readPtr, (char*)&flinfo->fn_nargs, sizeof(flinfo->fn_nargs), sizeof(flinfo->fn_nargs), - remainLen); + GetFixedMsgValSafe(readPtr, (char *)&flinfo->fn_nargs, sizeof(flinfo->fn_nargs), sizeof(flinfo->fn_nargs), + remainLen); /* Macro is OK */ InitFunctionCallInfoArgs(*fcinfo, flinfo->fn_nargs, BatchMaxSize); if (flinfo->fn_nargs > 0) { /* Get Argument type */ - GetFixedMsgValSafe(readPtr, (char*)fcinfo->argTypes, sizeof(Oid) * flinfo->fn_nargs, - sizeof(Oid) * flinfo->fn_nargs, remainLen); + GetFixedMsgValSafe(readPtr, (char *)fcinfo->argTypes, sizeof(Oid) * flinfo->fn_nargs, + sizeof(Oid) * flinfo->fn_nargs, remainLen); } /* Get Result Type */ - GetFixedMsgValSafe(readPtr, (char*)&flinfo->fn_rettype, sizeof(flinfo->fn_rettype), sizeof(flinfo->fn_rettype), - remainLen); + GetFixedMsgValSafe(readPtr, (char *)&flinfo->fn_rettype, sizeof(flinfo->fn_rettype), sizeof(flinfo->fn_rettype), + remainLen); } return readPtr; } -static void GetUDFArguments(FunctionCallInfoData* fcinfo) +/* + * 鍔熻兘锛氫粠鍑芥暟璋冪敤淇℃伅涓幏鍙朥DF鍙傛暟 + * + * 鍙傛暟鍒楄〃锛 + * fcinfo锛氬嚱鏁拌皟鐢ㄤ俊鎭殑鎸囬拡 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁颁粠鍑芥暟璋冪敤淇℃伅涓彁鍙栦簡UDF鍙傛暟锛屽寘鎷弬鏁扮殑鎵规琛屾暟銆佸弬鏁板煎拰绌哄间俊鎭 + * 鍙傛暟淇℃伅灏嗙敤浜嶶DF鐨勬墽琛屻 + */ +static void GetUDFArguments(FunctionCallInfoData *fcinfo) { - GetFixedMsgVal(fcinfo->udfInfo.msgReadPtr, - (char*)&fcinfo->udfInfo.argBatchRows, - sizeof(fcinfo->udfInfo.argBatchRows), - sizeof(fcinfo->udfInfo.argBatchRows)); + // 浠庢秷鎭腑鑾峰彇鍙傛暟鐨勬壒娆¤鏁 + GetFixedMsgVal(fcinfo->udfInfo.msgReadPtr, (char *)&fcinfo->udfInfo.argBatchRows, + sizeof(fcinfo->udfInfo.argBatchRows), sizeof(fcinfo->udfInfo.argBatchRows)); /* Argument Values Handler */ for (int row = 0; row < fcinfo->udfInfo.argBatchRows; row++) { @@ -610,17 +670,30 @@ static void GetUDFArguments(FunctionCallInfoData* fcinfo) } } } -static void RecvUDFInformation(int socket, FunctionCallInfoData* fcinfo) + +/* + * 鍔熻兘锛氫粠濂楁帴瀛楁帴鏀禪DF淇℃伅骞跺~鍏呭嚱鏁拌皟鐢ㄤ俊鎭粨鏋 + * + * 鍙傛暟鍒楄〃锛 + * socket锛氬鎺ュ瓧鏂囦欢鎻忚堪绗︼紝鐢ㄤ簬鎺ユ敹UDF淇℃伅 + * fcinfo锛氬嚱鏁拌皟鐢ㄤ俊鎭殑鎸囬拡锛屽皢鍦ㄥ嚱鏁板唴閮ㄥ~鍏 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁拌礋璐d粠濂楁帴瀛楁帴鏀禪DF淇℃伅锛屽苟灏嗗叾鐢ㄤ簬濉厖鍑芥暟璋冪敤淇℃伅缁撴瀯锛團unctionCallInfoData锛夈 + * 杩欏寘鎷帴鏀舵秷鎭ご鍜屾秷鎭綋锛岃幏鍙栧熀鏈琔DF淇℃伅锛圤ID銆佸悕绉般佸簱璺緞绛夛級浠ュ強鑾峰彇UDF鍙傛暟銆 + * 鏈鍚庯紝瀹冩煡鎵炬垨鎻掑叆UDF鍝堝笇琛ㄣ + */ +static void RecvUDFInformation(int socket, FunctionCallInfoData *fcinfo) { - uint len = 0; - char* allocPtr = NULL; + uint len = 0; + char *allocPtr = NULL; char buffer[UDF_MSG_BUFLEN]; - char* readPtr = buffer; + char *readPtr = buffer; /* * Step 1: Initialize function call structure and recv message header and body */ - FmgrInfo* flinfo = (FmgrInfo*)palloc0(sizeof(FmgrInfo)); + FmgrInfo *flinfo = (FmgrInfo *)palloc0(sizeof(FmgrInfo)); fcinfo->flinfo = flinfo; flinfo->fn_fenced = true; @@ -628,14 +701,14 @@ static void RecvUDFInformation(int socket, FunctionCallInfoData* fcinfo) /* Get message length */ RecvMsg(socket, buffer, 4, true); - len = *(uint*)buffer; + len = *(uint *)buffer; if (unlikely(len >= MaxAllocSize)) { ereport(ERROR, (errmodule(MOD_UDF), errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("Invalid udf message len:%u", len))); + errmsg("Invalid udf message len:%u", len))); } readPtr = buffer; if (unlikely(len >= UDF_MSG_BUFLEN)) { - allocPtr = readPtr = (char*)palloc(len); + allocPtr = readPtr = (char *)palloc(len); } /* Get message body */ RecvMsg(socket, readPtr, len); @@ -664,34 +737,68 @@ static void RecvUDFInformation(int socket, FunctionCallInfoData* fcinfo) return; } +/* + * 鍔熻兘锛氳繍琛岀敤鎴峰畾涔夊嚱鏁帮紙UDF锛夊苟杩斿洖缁撴灉 + * + * 鍙傛暟鍒楄〃锛 + * fcinfo锛氬嚱鏁拌皟鐢ㄤ俊鎭殑鎸囬拡锛屽寘鍚玌DF鐩稿叧淇℃伅 + * + * 杩斿洖鍊硷細 + * 杩斿洖UDF鐨勭粨鏋滐紙Datum绫诲瀷锛 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庢墽琛岀敤鎴峰畾涔夊嚱鏁帮紙UDF锛夛紝瀹冨皢鍑芥暟璋冪敤淇℃伅缁撴瀯涓殑isnull鏍囧織璁剧疆涓篺alse锛 + * 鐒跺悗閫氳繃璋冪敤FunctionCallInvoke鏉ユ墽琛孶DF锛屽苟杩斿洖缁撴灉銆 + */ template -static inline Datum RunUDF(FunctionCallInfoData* fcinfo) +static inline Datum RunUDF(FunctionCallInfoData *fcinfo) { - fcinfo->isnull = false; + fcinfo->isnull = false; // 璁剧疆isnull鏍囧織涓篺alse Datum result = 0; - result = FunctionCallInvoke(fcinfo); - return result; + result = FunctionCallInvoke(fcinfo); // 璋冪敤FunctionCallInvoke鎵цUDF + return result; // 杩斿洖UDF鐨勭粨鏋 } +/* + * 鍔熻兘锛氳缃敤鎴峰畾涔夊嚱鏁帮紙UDF锛夌殑鍐呭瓨闄愬埗 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庢牴鎹厤缃缃甎DF鐨勫唴瀛橀檺鍒躲傚鏋渦_sess->attr.attr_sql.FencedUDFMemoryLimit澶т簬0锛 + * 鍒欏皢RLIMIT_AS锛堝湴鍧绌洪棿闄愬埗锛夎缃负鎸囧畾鍊硷紝浠ラ檺鍒禪DF鐨勫唴瀛樹娇鐢ㄣ + * 濡傛灉璁剧疆澶辫触锛屽皢鍙戝嚭璀﹀憡娑堟伅銆 + */ void SetUDFMemoryLimit() { - struct rlimit memory_limit; + struct rlimit memory_limit; // 鐢ㄤ簬瀛樺偍鍐呭瓨闄愬埗鐨勭粨鏋勪綋 if (u_sess->attr.attr_sql.FencedUDFMemoryLimit > 0) { - /* baseVirtualMemSize is 200MB */ - const int64 baseVirtualMemSize = 200 * KB * KB; + const int64 baseVirtualMemSize = 200 * KB * KB; // 鍩虹铏氭嫙鍐呭瓨澶у皬涓200MB + + // 璁剧疆鍐呭瓨闄愬埗鐨勮蒋闄愬埗鍜岀‖闄愬埗涓烘寚瀹氬 memory_limit.rlim_cur = memory_limit.rlim_max = (int64)u_sess->attr.attr_sql.FencedUDFMemoryLimit * KB + baseVirtualMemSize; + + // 浣跨敤setrlimit鍑芥暟璁剧疆RLIMIT_AS闄愬埗 if (setrlimit(RLIMIT_AS, &memory_limit)) - ereport(WARNING, (errmodule(MOD_UDF), errmsg("setrlimit error: %m"))); + ereport(WARNING, (errmodule(MOD_UDF), errmsg("setrlimit error: %m"))); // 璁剧疆澶辫触鏃跺彂鍑鸿鍛 } } +/* + * 鍔熻兘锛氬垏鎹㈠綋鍓嶄細璇濈殑鏁版嵁搴撲笂涓嬫枃 + * + * 鍙傛暟鍒楄〃锛 + * currentDatabaseId锛氳鍒囨崲鍒扮殑鏁版嵁搴撶殑鍞竴鏍囪瘑绗 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庡垏鎹㈠綋鍓嶄細璇濈殑鏁版嵁搴撲笂涓嬫枃銆傚鏋滀紶鍏ョ殑currentDatabaseId涓嶄负0涓斾笌u_sess->proc_cxt.MyDatabaseId涓嶇浉绛夛紝 + * 鍒欐洿鏂皍_sess->proc_cxt.MyDatabaseId锛屽苟閲嶆柊鍒濆鍖朏enced绯荤粺缂撳瓨锛圛nitFencedSysCache锛夈 + */ void changeDatabase(unsigned int currentDatabaseId) { - if (currentDatabaseId!= 0 && currentDatabaseId != u_sess->proc_cxt.MyDatabaseId){ - u_sess->proc_cxt.MyDatabaseId = currentDatabaseId; - t_thrd.proc_cxt.PostInit->InitFencedSysCache(); + if (currentDatabaseId != 0 && currentDatabaseId != u_sess->proc_cxt.MyDatabaseId) { + u_sess->proc_cxt.MyDatabaseId = currentDatabaseId; // 鏇存柊褰撳墠浼氳瘽鐨勬暟鎹簱鏍囪瘑绗 + t_thrd.proc_cxt.PostInit->InitFencedSysCache(); // 閲嶆柊鍒濆鍖朏enced绯荤粺缂撳瓨 } } @@ -699,14 +806,22 @@ void changeDatabase(unsigned int currentDatabaseId) * @Description: The main function which run UDF * @IN socket: argument values is socket communication with RPC client */ +/* + * 鍔熻兘锛歎DF宸ヤ綔杩涚▼鐨勪富瑕佸嚱鏁帮紝鐢ㄤ簬鎵ц鐢ㄦ埛瀹氫箟鍑芥暟锛圲DF锛 + * + * 鍙傛暟鍒楄〃锛 + * socket锛歎DF宸ヤ綔杩涚▼涓庡鎴风涔嬮棿鐨勯氫俊濂楁帴瀛 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁版槸UDF宸ヤ綔杩涚▼鐨勪富瑕佸叆鍙g偣锛岀敤浜庢帴鏀禪DF淇℃伅銆佽缃唴瀛橀檺鍒躲佽繍琛孶DF骞惰繑鍥炵粨鏋溿 + * 鍦ㄥ惊鐜腑锛屼笉鏂湴鎺ユ敹瀹㈡埛绔彂閫佺殑UDF淇℃伅锛屾墽琛孶DF鍑芥暟锛岀劧鍚庡皢缁撴灉鍙戦佸洖瀹㈡埛绔 + * 濡傛灉鍦ㄦ墽琛孶DF杩囩▼涓亣鍒伴敊璇紝灏嗘崟鑾烽敊璇俊鎭苟鍙戦佸洖瀹㈡埛绔 + */ static void UDFWorkerMain(int socket) { - bool hasSetMemLimit = false; - UDFWorkMemContext = AllocSetContextCreate(t_thrd.top_mem_cxt, - "UDF_Work_MemContext", - ALLOCSET_DEFAULT_MINSIZE, - ALLOCSET_DEFAULT_INITSIZE, - ALLOCSET_DEFAULT_MAXSIZE); + bool hasSetMemLimit = false; // 鏍囧織鏄惁宸茶缃唴瀛橀檺鍒 + UDFWorkMemContext = AllocSetContextCreate(t_thrd.top_mem_cxt, "UDF_Work_MemContext", ALLOCSET_DEFAULT_MINSIZE, + ALLOCSET_DEFAULT_INITSIZE, ALLOCSET_DEFAULT_MAXSIZE); if (!UDFWorkMemContext) ereport(FATAL, (errmodule(MOD_UDF), errmsg("create UDFWorkMemContext failed"))); @@ -733,7 +848,7 @@ static void UDFWorkerMain(int socket) resetStringInfo(fcinfo.udfInfo.udfMsgBuf); Reserve4BytesMsgHeader(fcinfo.udfInfo.udfMsgBuf); short msgType = (short)UDF_RESULT; - AppendBufFixedMsgVal(fcinfo.udfInfo.udfMsgBuf, (char*)&msgType, sizeof(msgType)); + AppendBufFixedMsgVal(fcinfo.udfInfo.udfMsgBuf, (char *)&msgType, sizeof(msgType)); for (int row = 0; row < fcinfo.udfInfo.argBatchRows; ++row) { for (int idx = 0; idx < fcinfo.nargs; idx++) { @@ -749,7 +864,7 @@ static void UDFWorkerMain(int socket) result = RunUDF(&fcinfo); break; default: - if(fcinfo.flinfo->fnLibPath != NULL) { + if (fcinfo.flinfo->fnLibPath != NULL) { changeDatabase(atoi(fcinfo.flinfo->fnLibPath)); } result = RunUDF(&fcinfo); @@ -767,14 +882,14 @@ static void UDFWorkerMain(int socket) resetStringInfo(fcinfo.udfInfo.udfMsgBuf); Reserve4BytesMsgHeader(fcinfo.udfInfo.udfMsgBuf); short msgType = (short)UDF_ERROR; - AppendBufFixedMsgVal(fcinfo.udfInfo.udfMsgBuf, (char*)&msgType, sizeof(msgType)); + AppendBufFixedMsgVal(fcinfo.udfInfo.udfMsgBuf, (char *)&msgType, sizeof(msgType)); MemoryContext ecxt = MemoryContextSwitchTo(current_context); - ErrorData* edata = CopyErrorData(); + ErrorData *edata = CopyErrorData(); int len = strlen(edata->message); - AppendBufVarMsgVal(fcinfo.udfInfo.udfMsgBuf, (char*)edata->message, len); + AppendBufVarMsgVal(fcinfo.udfInfo.udfMsgBuf, (char *)edata->message, len); Fill4BytesMsgHeader(fcinfo.udfInfo.udfMsgBuf); SendMsg(socket, fcinfo.udfInfo.udfMsgBuf->data, fcinfo.udfInfo.udfMsgBuf->len); @@ -802,16 +917,33 @@ static void UDFWorkerMain(int socket) * 1 byte | fixed bytes values | * ------------------------------------------------------------------- */ +/* + * 鍔熻兘锛氱敤浜庡鐞嗕笉鍚屾暟鎹被鍨嬬殑鍑芥暟鍙傛暟鍜岀粨鏋滃 + * + * 鍙傛暟鍒楄〃锛 + * fcinfo锛欶unctionCallInfoData缁撴瀯浣撴寚閽堬紝鍖呭惈浜嗗嚱鏁拌皟鐢ㄧ殑淇℃伅 + * idx锛氬弬鏁扮储寮曪紝鎸囩ず瑕佸鐞嗙殑鍙傛暟鐨勪綅缃 + * val锛氫紶鍏ョ殑鍙傛暟鍊 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁版牴鎹弬鏁扮殑鏁版嵁绫诲瀷鍜屽鐞嗙被鍨嬫墽琛屼笉鍚岀殑鎿嶄綔锛屽寘鎷弬鏁扮殑搴忓垪鍖栧拰鍙嶅簭鍒楀寲锛 + * 浠ュ強璁剧疆鍑芥暟璋冪敤淇℃伅涓殑鍙傛暟鍊煎拰缁撴灉鍊笺傚嚱鏁伴氳繃娑堟伅缂撳啿鍖轰笌澶栭儴閫氫俊锛岀敤浜 + * 鐢ㄦ埛瀹氫箟鍑芥暟锛圲DF锛夌殑鍙傛暟浼犻掑拰缁撴灉杩斿洖銆 + */ template -Datum UDFArgumentHandler(FunctionCallInfoData* fcinfo, int idx, Datum val) +Datum UDFArgumentHandler(FunctionCallInfoData *fcinfo, int idx, Datum val) { + // 鑾峰彇涓庡綋鍓嶅嚱鏁拌皟鐢ㄧ浉鍏崇殑娑堟伅缂撳啿鍖哄拰鍏朵粬鍒濆鍖栦俊鎭 StringInfo udfMsgBuf = fcinfo->udfInfo.udfMsgBuf; + // 鍒濆鍖栫粨鏋滀负浼犲叆鐨勫 Datum result = val; + // 鍒濆鍖栧彉閲忕敤浜庡瓨鍌ㄥ肩殑闀垮害銆佹槸鍚︿负NULL銆佷互鍙婃秷鎭鍙栨寚閽 int valLen = 0; char isNull = 0; - char* readPtr = fcinfo->udfInfo.msgReadPtr; - + char *readPtr = fcinfo->udfInfo.msgReadPtr; + // 鏍规嵁鏁版嵁绫诲瀷杩涜涓嶅悓鐨勫鐞 switch (type) { + // 澶勭悊鍥哄畾闀垮害鐨勬暟鎹被鍨 case BOOLOID: case INT8OID: case INT2OID: @@ -839,46 +971,49 @@ Datum UDFArgumentHandler(FunctionCallInfoData* fcinfo, int idx, Datum val) /* typlen: 4 */ case RELTIMEOID: { if (handlerType == UDF_SEND_ARGS) { + // 濡傛灉鏄彂閫佸弬鏁帮紝鑾峰彇鍙傛暟鍊煎拰鏄惁涓篘ULL锛岀劧鍚庡皢瀹冧滑闄勫姞鍒版秷鎭紦鍐插尯涓 Datum v = fcinfo->arg[idx]; isNull = fcinfo->argnull[idx] ? 1 : 0; - AppendBufFixedMsgVal(udfMsgBuf, (char*)&isNull, sizeof(isNull)); + AppendBufFixedMsgVal(udfMsgBuf, (char *)&isNull, sizeof(isNull)); if (!isNull) { - AppendBufFixedMsgVal(udfMsgBuf, (char*)&v, sizeof(v)); + AppendBufFixedMsgVal(udfMsgBuf, (char *)&v, sizeof(v)); } } else if (handlerType == UDF_RECV_ARGS) { /* is NULL ? */ - GetFixedMsgVal(readPtr, (char*)&isNull, sizeof(isNull), sizeof(isNull)); + // 濡傛灉鏄帴鏀跺弬鏁帮紝妫鏌ユ槸鍚︿负NULL锛岀劧鍚庢帴鏀跺弬鏁板煎苟璁剧疆瀵瑰簲鐨勫嚱鏁拌皟鐢ㄤ俊鎭 + GetFixedMsgVal(readPtr, (char *)&isNull, sizeof(isNull), sizeof(isNull)); if (!isNull) { /* Keep Always Send Datum, So Recv Datum */ Datum value = 0; - GetFixedMsgVal(readPtr, (char*)&value, sizeof(value), sizeof(value)); + GetFixedMsgVal(readPtr, (char *)&value, sizeof(value), sizeof(value)); fcinfo->arg[idx] = value; fcinfo->argnull[idx] = false; } else { fcinfo->argnull[idx] = true; } } else if (handlerType == UDF_SEND_RESULT) { + // 濡傛灉鏄彂閫佺粨鏋滐紝澶勭悊缁撴灉鍊肩殑NULL鏍囧織鍜屽兼湰韬紝骞堕檮鍔犲埌娑堟伅缂撳啿鍖轰腑 valLen = 0; isNull = fcinfo->isnull ? 1 : 0; - AppendBufFixedMsgVal(udfMsgBuf, (char*)&isNull, sizeof(isNull)); + AppendBufFixedMsgVal(udfMsgBuf, (char *)&isNull, sizeof(isNull)); if (isNull == 0) { - AppendBufFixedMsgVal(udfMsgBuf, (char*)&result, sizeof(result)); + AppendBufFixedMsgVal(udfMsgBuf, (char *)&result, sizeof(result)); } } else { Assert(handlerType == UDF_RECV_RESULT); if (handlerType != UDF_RECV_RESULT) { - ereport(ERROR, - (errmodule(MOD_UDF), - errcode(ERRORCODE_ASSERT_FAILED), - errmsg("Otherwise, handlerType can only be UDF_RECV_RESULT"))); + // 濡傛灉澶勭悊绫诲瀷涓嶆槸棰勬湡鐨勬帴鏀剁粨鏋滅被鍨嬶紝鎶ュ憡閿欒 + ereport(ERROR, (errmodule(MOD_UDF), errcode(ERRORCODE_ASSERT_FAILED), + errmsg("Otherwise, handlerType can only be UDF_RECV_RESULT"))); } /* Get null flag */ - GetFixedMsgVal(readPtr, (char*)&isNull, sizeof(isNull), sizeof(isNull)); + // 濡傛灉鏄帴鏀剁粨鏋滐紝鑾峰彇缁撴灉鐨凬ULL鏍囧織鍜屽硷紝骞惰缃搴旂殑鍑芥暟璋冪敤淇℃伅 + GetFixedMsgVal(readPtr, (char *)&isNull, sizeof(isNull), sizeof(isNull)); /* Get result if not null */ if (isNull == 0) { - GetFixedMsgVal(readPtr, (char*)&result, sizeof(result), sizeof(result)); + GetFixedMsgVal(readPtr, (char *)&result, sizeof(result), sizeof(result)); fcinfo->isnull = false; } else { fcinfo->isnull = true; @@ -886,6 +1021,7 @@ Datum UDFArgumentHandler(FunctionCallInfoData* fcinfo, int idx, Datum val) } break; } + // 澶勭悊鍙彉闀垮害鐨勬暟鎹被鍨 case BOOLARRAYOID: case INT2ARRAYOID: case INT4ARRAYOID: @@ -921,27 +1057,27 @@ Datum UDFArgumentHandler(FunctionCallInfoData* fcinfo, int idx, Datum val) case CIDROID: case VARBITOID: { if (handlerType == UDF_SEND_ARGS) { + // 濡傛灉鏄彂閫佸弬鏁帮紝鑾峰彇鍙傛暟鍊煎拰鏄惁涓篘ULL锛岀劧鍚庡皢瀹冧滑闄勫姞鍒版秷鎭紦鍐插尯涓 Datum v = fcinfo->arg[idx]; isNull = fcinfo->argnull[idx] ? 1 : 0; - AppendBufFixedMsgVal(udfMsgBuf, (char*)&isNull, sizeof(isNull)); + AppendBufFixedMsgVal(udfMsgBuf, (char *)&isNull, sizeof(isNull)); if (!isNull) { - struct varlena* value = PG_DETOAST_DATUM(v); + struct varlena *value = PG_DETOAST_DATUM(v); valLen = VARSIZE_ANY(value); - AppendBufVarMsgVal(udfMsgBuf, (char*)value, valLen); + AppendBufVarMsgVal(udfMsgBuf, (char *)value, valLen); } } else if (handlerType == UDF_RECV_ARGS) { valLen = 0; - GetFixedMsgVal(readPtr, (char*)&isNull, sizeof(isNull), sizeof(isNull)); + GetFixedMsgVal(readPtr, (char *)&isNull, sizeof(isNull), sizeof(isNull)); if (!isNull) { - GetFixedMsgVal(readPtr, (char*)&valLen, sizeof(valLen), sizeof(valLen)); + GetFixedMsgVal(readPtr, (char *)&valLen, sizeof(valLen), sizeof(valLen)); if (valLen < 0) { - ereport(ERROR, - (errmodule(MOD_UDF), - errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("Variable length %d cannot be negative", valLen))); + // 闀垮害涓嶈兘涓鸿礋鏁帮紝鎶ュ憡閿欒 + ereport(ERROR, (errmodule(MOD_UDF), errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("Variable length %d cannot be negative", valLen))); } - char* buffer = (char*)palloc0(valLen + 1); + char *buffer = (char *)palloc0(valLen + 1); GetFixedMsgVal(readPtr, buffer, valLen, valLen + 1); /* memory should free */ @@ -952,38 +1088,34 @@ Datum UDFArgumentHandler(FunctionCallInfoData* fcinfo, int idx, Datum val) } } else if (handlerType == UDF_SEND_RESULT) { valLen = 0; - varlena* resultVar = NULL; + varlena *resultVar = NULL; isNull = fcinfo->isnull ? 1 : 0; - AppendBufFixedMsgVal(udfMsgBuf, (char*)&isNull, sizeof(isNull)); + AppendBufFixedMsgVal(udfMsgBuf, (char *)&isNull, sizeof(isNull)); if (!isNull) { resultVar = PG_DETOAST_DATUM(result); valLen = VARSIZE_ANY(resultVar); - AppendBufVarMsgVal(udfMsgBuf, (char*)resultVar, valLen); + AppendBufVarMsgVal(udfMsgBuf, (char *)resultVar, valLen); } } else { Assert(handlerType == UDF_RECV_RESULT); if (handlerType != UDF_RECV_RESULT) { - ereport(ERROR, - (errmodule(MOD_UDF), - errcode(ERRORCODE_ASSERT_FAILED), - errmsg("Otherwise, handlerType can only be UDF_RECV_RESULT"))); + ereport(ERROR, (errmodule(MOD_UDF), errcode(ERRORCODE_ASSERT_FAILED), + errmsg("Otherwise, handlerType can only be UDF_RECV_RESULT"))); } /* Get null falg */ - GetFixedMsgVal(readPtr, (char*)&isNull, sizeof(isNull), sizeof(isNull)); + GetFixedMsgVal(readPtr, (char *)&isNull, sizeof(isNull), sizeof(isNull)); /* Get result if not null */ if (isNull == 0) { valLen = 0; - GetFixedMsgVal(readPtr, (char*)&valLen, sizeof(valLen), sizeof(valLen)); + GetFixedMsgVal(readPtr, (char *)&valLen, sizeof(valLen), sizeof(valLen)); if (valLen < 0) { - ereport(ERROR, - (errmodule(MOD_UDF), - errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("Variable length %d cannot be negative", valLen))); + ereport(ERROR, (errmodule(MOD_UDF), errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("Variable length %d cannot be negative", valLen))); } - char* ptr = (char*)palloc0(valLen + 1); - GetFixedMsgVal(readPtr, (char*)ptr, valLen, valLen + 1); + char *ptr = (char *)palloc0(valLen + 1); + GetFixedMsgVal(readPtr, (char *)ptr, valLen, valLen + 1); result = PointerGetDatum(ptr); fcinfo->isnull = false; } else { @@ -1055,22 +1187,20 @@ Datum UDFArgumentHandler(FunctionCallInfoData* fcinfo, int idx, Datum val) if (handlerType == UDF_SEND_ARGS) { Datum v = fcinfo->arg[idx]; isNull = fcinfo->argnull[idx] ? 1 : 0; - AppendBufFixedMsgVal(udfMsgBuf, (char*)&isNull, sizeof(isNull)); + AppendBufFixedMsgVal(udfMsgBuf, (char *)&isNull, sizeof(isNull)); if (!isNull) { - char* value = DatumGetPointer(v); - AppendBufVarMsgVal(udfMsgBuf, (char*)value, valLen); + char *value = DatumGetPointer(v); + AppendBufVarMsgVal(udfMsgBuf, (char *)value, valLen); } } else if (handlerType == UDF_RECV_ARGS) { - GetFixedMsgVal(readPtr, (char*)&isNull, sizeof(isNull), sizeof(isNull)); + GetFixedMsgVal(readPtr, (char *)&isNull, sizeof(isNull), sizeof(isNull)); if (!isNull) { - GetFixedMsgVal(readPtr, (char*)&valLen, sizeof(valLen), sizeof(valLen)); + GetFixedMsgVal(readPtr, (char *)&valLen, sizeof(valLen), sizeof(valLen)); if (valLen < 0) { - ereport(ERROR, - (errmodule(MOD_UDF), - errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("Variable length %d cannot be negative", valLen))); + ereport(ERROR, (errmodule(MOD_UDF), errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("Variable length %d cannot be negative", valLen))); } - char* buffer = (char*)palloc0(valLen + 1); + char *buffer = (char *)palloc0(valLen + 1); GetFixedMsgVal(readPtr, buffer, valLen, valLen + 1); fcinfo->argnull[idx] = false; /* memory should free */ @@ -1079,32 +1209,30 @@ Datum UDFArgumentHandler(FunctionCallInfoData* fcinfo, int idx, Datum val) fcinfo->argnull[idx] = true; } } else if (handlerType == UDF_SEND_RESULT) { - char* resultVar = NULL; + char *resultVar = NULL; char isNull = fcinfo->isnull ? 1 : 0; /* Fill NULL flag 1 byte */ - AppendBufFixedMsgVal(udfMsgBuf, (char*)&isNull, sizeof(isNull)); + AppendBufFixedMsgVal(udfMsgBuf, (char *)&isNull, sizeof(isNull)); /* Fill fixed-length value if not null */ if (!isNull) { resultVar = DatumGetPointer(result); - AppendBufFixedMsgVal(udfMsgBuf, (char*)resultVar, valLen); + AppendBufFixedMsgVal(udfMsgBuf, (char *)resultVar, valLen); } } else { Assert(handlerType == UDF_RECV_RESULT); if (handlerType != UDF_RECV_RESULT) { - ereport(ERROR, - (errmodule(MOD_UDF), - errcode(ERRORCODE_ASSERT_FAILED), - errmsg("Otherwise, handlerType can only be UDF_RECV_RESULT"))); + ereport(ERROR, (errmodule(MOD_UDF), errcode(ERRORCODE_ASSERT_FAILED), + errmsg("Otherwise, handlerType can only be UDF_RECV_RESULT"))); } /* Get null flag */ - GetFixedMsgVal(readPtr, (char*)&isNull, sizeof(isNull), sizeof(isNull)); + GetFixedMsgVal(readPtr, (char *)&isNull, sizeof(isNull), sizeof(isNull)); /* Get result if not null */ if (isNull == 0) { - char* ptr = (char*)palloc0(valLen + 1); - GetFixedMsgVal(readPtr, (char*)ptr, valLen, valLen + 1); + char *ptr = (char *)palloc0(valLen + 1); + GetFixedMsgVal(readPtr, (char *)ptr, valLen, valLen + 1); result = PointerGetDatum(ptr); fcinfo->isnull = false; } else { @@ -1115,10 +1243,8 @@ Datum UDFArgumentHandler(FunctionCallInfoData* fcinfo, int idx, Datum val) } default: { HANDLE_UNSOPPORTED_VAL: - ereport(ERROR, - (errmodule(MOD_UDF), - errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("Recv Unsupported argument type: %u", type))); + ereport(ERROR, (errmodule(MOD_UDF), errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("Recv Unsupported argument type: %u", type))); break; } } @@ -1127,7 +1253,18 @@ Datum UDFArgumentHandler(FunctionCallInfoData* fcinfo, int idx, Datum val) fcinfo->udfInfo.msgReadPtr = readPtr; return result; } - +/* + * 鍔熻兘锛氭牴鎹鐞嗙被鍨嬪垵濮嬪寲UDF鍙傛暟澶勭悊鍣ㄥ嚱鏁版寚閽 + * + * 鍙傛暟鍒楄〃锛 + * handlerType锛歎DFArgHandlerType绫诲瀷锛屾寚绀哄弬鏁板鐞嗙殑绫诲瀷 + * fcinfo锛欶unctionCallInfo缁撴瀯浣撴寚閽堬紝鍖呭惈浜嗗嚱鏁拌皟鐢ㄧ殑淇℃伅 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庡垵濮嬪寲UDF鍙傛暟澶勭悊鍣ㄥ嚱鏁版寚閽堬紝鏍规嵁涓嶅悓鐨勬暟鎹被鍨嬪拰澶勭悊绫诲瀷锛 + * 鍒嗛厤鍚堥傜殑鍑芥暟鎸囬拡浠ヨ繘琛屽弬鏁板鐞嗐傚嚱鏁版寚閽堝皢鍦ㄥ悗缁殑鍑芥暟璋冪敤涓敤浜 + * 澶勭悊涓嶅悓鏁版嵁绫诲瀷鐨勫弬鏁版垨缁撴灉鍊笺 + */ template void InitUDFArgsHandler(FunctionCallInfo fcinfo) { @@ -1137,14 +1274,13 @@ void InitUDFArgsHandler(FunctionCallInfo fcinfo) for (int i = 0; i < n; ++i) { Oid type = 0; - UDFArgsFuncType* funcPPtr = NULL; + UDFArgsFuncType *funcPPtr = NULL; if (handlerType == UDF_SEND_RESULT || handlerType == UDF_RECV_RESULT) { type = fcinfo->flinfo->fn_rettype; funcPPtr = &fcinfo->udfInfo.UDFResultHandlerPtr; } else { - AssertEreport(handlerType == UDF_SEND_ARGS || handlerType == UDF_RECV_ARGS, - MOD_UDF, - "Otherwise, handlerType can only be UDF_SEND_ARGS or UDF_RECV_ARGS"); + AssertEreport(handlerType == UDF_SEND_ARGS || handlerType == UDF_RECV_ARGS, MOD_UDF, + "Otherwise, handlerType can only be UDF_SEND_ARGS or UDF_RECV_ARGS"); type = fcinfo->argTypes[i]; funcPPtr = fcinfo->udfInfo.UDFArgsHandlerPtr + i; @@ -1392,13 +1528,25 @@ void InitUDFArgsHandler(FunctionCallInfo fcinfo) } default: { ereport(ERROR, - (errmodule(MOD_UDF), errcode(ERRCODE_DATATYPE_MISMATCH), errmsg("Unsupport type: %u", type))); + (errmodule(MOD_UDF), errcode(ERRCODE_DATATYPE_MISMATCH), errmsg("Unsupport type: %u", type))); break; } } } } - +/* + * 鍔熻兘锛氬~鍏呭熀鏈殑UDF淇℃伅 + * + * 鍙傛暟鍒楄〃锛 + * fcinfo锛欶unctionCallInfo缁撴瀯浣撴寚閽堬紝鍖呭惈浜嗗嚱鏁拌皟鐢ㄧ殑淇℃伅 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庡~鍏匲DF娑堟伅缂撳啿鍖猴紙udfMsgBuf锛変腑鐨勫熀鏈俊鎭傛牴鎹嚱鏁版槸鍚 + * 鏄浉鍚岀殑UDF鍑芥暟璋冪敤锛屽嚱鏁板皢濉厖涓嶅悓鐨勪俊鎭傚鏋滄槸鐩稿悓鐨刄DF鍑芥暟璋冪敤锛 + * 鍒欏~鍏匲DF_ARGS绫诲瀷鐨勪俊鎭紝鍚﹀垯濉厖UDF_INFO绫诲瀷鐨勪俊鎭傚嚱鏁颁細濉厖 + * UDF鍑芥暟鐨勫悇绉嶅睘鎬э紝濡傚嚱鏁癘ID銆佽瑷OID銆佸嚱鏁板悕绉般佸嚱鏁板簱璺緞銆佸弬鏁扮被鍨 + * 鏁扮粍绛夈 + */ static void FillBasicUDFInformation(FunctionCallInfo fcinfo) { StringInfo udfMsgBuf = fcinfo->udfInfo.udfMsgBuf; @@ -1410,114 +1558,151 @@ static void FillBasicUDFInformation(FunctionCallInfo fcinfo) msgType = (short)UDF_ARGS; Oid oid = fcinfo->flinfo->fn_oid; - AppendBufFixedMsgVal(udfMsgBuf, (char*)&msgType, sizeof(msgType)); - AppendBufFixedMsgVal(udfMsgBuf, (char*)&oid, sizeof(oid)); + AppendBufFixedMsgVal(udfMsgBuf, (char *)&msgType, sizeof(msgType)); + AppendBufFixedMsgVal(udfMsgBuf, (char *)&oid, sizeof(oid)); } else { /* Message Type */ msgType = (short)UDF_INFO; - AppendBufFixedMsgVal(udfMsgBuf, (char*)&msgType, sizeof(msgType)); + AppendBufFixedMsgVal(udfMsgBuf, (char *)&msgType, sizeof(msgType)); /* memory limit of udf worker process */ - AppendBufFixedMsgVal(udfMsgBuf, - (char*)&u_sess->attr.attr_sql.FencedUDFMemoryLimit, - sizeof(u_sess->attr.attr_sql.FencedUDFMemoryLimit)); + AppendBufFixedMsgVal(udfMsgBuf, (char *)&u_sess->attr.attr_sql.FencedUDFMemoryLimit, + sizeof(u_sess->attr.attr_sql.FencedUDFMemoryLimit)); /* pljava_vmoptions */ len = strlen(u_sess->attr.attr_sql.pljava_vmoptions); - AppendBufVarMsgVal(udfMsgBuf, (char*)u_sess->attr.attr_sql.pljava_vmoptions, len); + AppendBufVarMsgVal(udfMsgBuf, (char *)u_sess->attr.attr_sql.pljava_vmoptions, len); /* UDF OID */ - AppendBufFixedMsgVal(udfMsgBuf, (char*)&fcinfo->flinfo->fn_oid, sizeof(Oid)); + AppendBufFixedMsgVal(udfMsgBuf, (char *)&fcinfo->flinfo->fn_oid, sizeof(Oid)); /* UDF language OID */ - AppendBufFixedMsgVal(udfMsgBuf, (char*)&fcinfo->flinfo->fn_languageId, sizeof(Oid)); + AppendBufFixedMsgVal(udfMsgBuf, (char *)&fcinfo->flinfo->fn_languageId, sizeof(Oid)); /* UDF volatile property */ - AppendBufFixedMsgVal(udfMsgBuf, (char*)&fcinfo->flinfo->fn_volatile, sizeof(char)); + AppendBufFixedMsgVal(udfMsgBuf, (char *)&fcinfo->flinfo->fn_volatile, sizeof(char)); /* UDF Name */ len = strlen(fcinfo->flinfo->fnName); - AppendBufVarMsgVal(udfMsgBuf, (char*)fcinfo->flinfo->fnName, len); + AppendBufVarMsgVal(udfMsgBuf, (char *)fcinfo->flinfo->fnName, len); /* UDF Library */ len = strlen(fcinfo->flinfo->fnLibPath); - AppendBufVarMsgVal(udfMsgBuf, (char*)fcinfo->flinfo->fnLibPath, len); + AppendBufVarMsgVal(udfMsgBuf, (char *)fcinfo->flinfo->fnLibPath, len); /* UDF Number of Argument */ - AppendBufFixedMsgVal(udfMsgBuf, (char*)&fcinfo->nargs, sizeof(fcinfo->nargs)); + AppendBufFixedMsgVal(udfMsgBuf, (char *)&fcinfo->nargs, sizeof(fcinfo->nargs)); if (fcinfo->nargs > 0) { /* the type of arguments */ - Oid* argTypes = fcinfo->argTypes; - AppendBufFixedMsgVal(udfMsgBuf, (char*)argTypes, sizeof(Oid) * fcinfo->nargs); + Oid *argTypes = fcinfo->argTypes; + AppendBufFixedMsgVal(udfMsgBuf, (char *)argTypes, sizeof(Oid) * fcinfo->nargs); } /* The type of result */ resultType = fcinfo->flinfo->fn_rettype; - AppendBufFixedMsgVal(udfMsgBuf, (char*)&resultType, sizeof(resultType)); + AppendBufFixedMsgVal(udfMsgBuf, (char *)&resultType, sizeof(resultType)); } } +/* + * 鍔熻兘锛氬~鍏匲DF鍑芥暟鐨勫弬鏁颁俊鎭 + * + * 鍙傛暟鍒楄〃锛 + * fcinfo锛欶unctionCallInfo缁撴瀯浣撴寚閽堬紝鍖呭惈浜嗗嚱鏁拌皟鐢ㄧ殑淇℃伅 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庡~鍏匲DF娑堟伅缂撳啿鍖猴紙udfMsgBuf锛変腑鐨勫弬鏁颁俊鎭傛牴鎹槸鍚﹀浜 + * 鎵瑰鐞嗘ā寮忥紙batchMode锛夛紝鍑芥暟浼氬~鍏呬笉鍚屾暟閲忕殑鍙傛暟琛屻傚嚱鏁拌繕浼氭鏌ユ槸鍚 + * 闇瑕佸垵濮嬪寲UDF鍙傛暟澶勭悊鍣紙UDFArgsHandler锛夛紝濡傛灉闇瑕侊紝鍒欒繘琛屽垵濮嬪寲銆 + * 鐒跺悗锛屽嚱鏁颁細閬嶅巻姣忎竴琛岀殑鍙傛暟锛屽苟鏍规嵁鍙傛暟澶勭悊鍣ㄥ鐞嗗弬鏁板笺 + */ template static void FillUDFArguments(FunctionCallInfo fcinfo) { - StringInfo udfMsgBuf = fcinfo->udfInfo.udfMsgBuf; - int batchRows = batchMode ? fcinfo->udfInfo.argBatchRows : 1; - AppendBufFixedMsgVal(udfMsgBuf, (char*)&batchRows, sizeof(batchRows)); + StringInfo udfMsgBuf = fcinfo->udfInfo.udfMsgBuf; // 鑾峰彇UDF娑堟伅缂撳啿鍖 + int batchRows = batchMode ? fcinfo->udfInfo.argBatchRows : 1; // 鎵瑰鐞嗘ā寮忎笅鐨勮鏁帮紝榛樿涓1 + AppendBufFixedMsgVal(udfMsgBuf, (char *)&batchRows, sizeof(batchRows)); // 濉厖琛屾暟淇℃伅鍒版秷鎭紦鍐插尯 if (unlikely(!fcinfo->udfInfo.valid_UDFArgsHandlerPtr)) { - InitUDFArgsHandler(fcinfo); - InitUDFArgsHandler(fcinfo); - fcinfo->udfInfo.valid_UDFArgsHandlerPtr = true; + InitUDFArgsHandler(fcinfo); // 鍒濆鍖朥DF鍙傛暟澶勭悊鍣紙鍙戦佸弬鏁帮級 + InitUDFArgsHandler(fcinfo); // 鍒濆鍖朥DF鍙傛暟澶勭悊鍣紙鎺ユ敹缁撴灉锛 + fcinfo->udfInfo.valid_UDFArgsHandlerPtr = true; // 鏍囪鍙傛暟澶勭悊鍣ㄥ凡鍒濆鍖 } /* Fill UDF Argument Values */ for (int row = 0; row < batchRows; row++) { for (int idx = 0; idx < fcinfo->nargs; idx++) { if (batchMode) { - fcinfo->arg[idx] = fcinfo->udfInfo.arg[row][idx]; - fcinfo->argnull[idx] = fcinfo->udfInfo.null[row][idx]; + fcinfo->arg[idx] = fcinfo->udfInfo.arg[row][idx]; // 浠庢壒澶勭悊涓幏鍙栧弬鏁板 + fcinfo->argnull[idx] = fcinfo->udfInfo.null[row][idx]; // 鑾峰彇鍙傛暟鏄惁涓虹┖鐨勬爣蹇 } - (*(fcinfo->udfInfo.UDFArgsHandlerPtr + idx))(fcinfo, idx, 0); + (*(fcinfo->udfInfo.UDFArgsHandlerPtr + idx))(fcinfo, idx, 0); // 璋冪敤鍙傛暟澶勭悊鍣ㄥ鐞嗗弬鏁板 } } } +/* + * 鍔熻兘锛氬彂閫乁DF鍑芥暟淇℃伅 + * + * 鍙傛暟鍒楄〃锛 + * fcinfo锛欶unctionCallInfo缁撴瀯浣撴寚閽堬紝鍖呭惈浜嗗嚱鏁拌皟鐢ㄧ殑淇℃伅 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庡彂閫乁DF鍑芥暟鐨勪俊鎭紝鍖呮嫭鍑芥暟鐨勫熀鏈俊鎭佸弬鏁颁俊鎭瓑銆傚叿浣撶殑 + * 姝ラ鍖呮嫭鍒濆鍖栨秷鎭紦鍐插尯銆佸~鍏呭熀鏈琔DF淇℃伅銆佸~鍏匲DF鍙傛暟淇℃伅銆佸彂閫佹秷鎭瓑銆 + * 鍑芥暟涓殑鎵瑰鐞嗘ā寮忥紙batchMode锛変細褰卞搷鍙傛暟鐨勬暟閲忋 + */ template static void SendUDFInformation(FunctionCallInfo fcinfo) { - StringInfo udfMsgBuf = fcinfo->udfInfo.udfMsgBuf; + StringInfo udfMsgBuf = fcinfo->udfInfo.udfMsgBuf; // 鑾峰彇UDF娑堟伅缂撳啿鍖 /* Step 1: Initialize and Reset the udfMsgBuf */ - resetStringInfo(fcinfo->udfInfo.udfMsgBuf); - Reserve4BytesMsgHeader(udfMsgBuf); + resetStringInfo(fcinfo->udfInfo.udfMsgBuf); // 閲嶇疆娑堟伅缂撳啿鍖 + Reserve4BytesMsgHeader(udfMsgBuf); // 涓烘秷鎭ご棰勭暀4瀛楄妭绌洪棿 /* * Step 2: Fill the basic UDF information (OID, NAME, * LIBPATH and so on) */ - FillBasicUDFInformation(fcinfo); + FillBasicUDFInformation(fcinfo); // 濉厖鍩烘湰UDF淇℃伅 /* * Step 3: Fill UDF arguments * the number of batch argument values */ - FillUDFArguments(fcinfo); + FillUDFArguments(fcinfo); // 濉厖UDF鍙傛暟淇℃伅锛屾牴鎹壒澶勭悊妯″紡纭畾鍙傛暟鏁伴噺 /* * Step 4: Fill the length of body msg and send msg */ - Fill4BytesMsgHeader(udfMsgBuf); - SendMsg(UDFRPCSocket, udfMsgBuf->data, udfMsgBuf->len); + Fill4BytesMsgHeader(udfMsgBuf); // 濉厖娑堟伅浣撻暱搴 + SendMsg(UDFRPCSocket, udfMsgBuf->data, udfMsgBuf->len); // 鍙戦佹秷鎭 - lastUDFOid = fcinfo->flinfo->fn_oid; + lastUDFOid = fcinfo->flinfo->fn_oid; // 鏇存柊鏈鍚庝竴涓猆DF鍑芥暟鐨凮ID } - -bool RPCInitFencedUDFIfNeed(Oid functionId, FmgrInfo* finfo, HeapTuple procedureTuple) +/* + * 鍔熻兘锛氬鏋滈渶瑕佺殑璇濓紝鍒濆鍖朏enced UDF锛堢敤鎴峰畾涔夊嚱鏁帮級 + * + * 鍙傛暟鍒楄〃锛 + * functionId锛歎DF鍑芥暟鐨凮ID锛堝璞℃爣璇嗙锛 + * finfo锛欶mgrInfo缁撴瀯浣撴寚閽堬紝鍖呭惈浜嗗嚱鏁扮鐞嗙殑淇℃伅 + * procedureTuple锛氬嚱鏁板搴旂殑杩囩▼鍏冪粍锛圚eapTuple锛 + * + * 杩斿洖鍊硷細 + * 濡傛灉鍑芥暟浠enced妯″紡杩愯锛屽垯杩斿洖true锛屽惁鍒欒繑鍥瀎alse + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庡垵濮嬪寲Fenced UDF锛堢敤鎴峰畾涔夊嚱鏁帮級锛屼富瑕佸寘鎷幏鍙栧嚱鏁扮殑鐩稿叧淇℃伅锛 + * 鐗瑰埆鏄拡瀵笴璇█鍜孞ava璇█鐨勪笉鍚屽鐞嗘柟寮忋傚鏋滃嚱鏁颁互Fenced妯″紡杩愯锛屼細璁剧疆 + * 鐩稿叧鐨勫嚱鏁颁俊鎭紝鍚﹀垯淇濇寔榛樿鍊笺 + */ +bool RPCInitFencedUDFIfNeed(Oid functionId, FmgrInfo *finfo, HeapTuple procedureTuple) { Datum prosrcattr; Datum probinattr; - char* udfName = NULL; - char* udfLibPath = NULL; + char *udfName = NULL; + char *udfLibPath = NULL; bool isnull = false; Oid languageId = finfo->fn_languageId; bool fencedMode = false; @@ -1528,10 +1713,8 @@ bool RPCInitFencedUDFIfNeed(Oid functionId, FmgrInfo* finfo, HeapTuple procedure probinattr = SysCacheGetAttr(PROCOID, procedureTuple, Anum_pg_proc_probin, &isnull); if (languageId == ClanguageId && isnull) - ereport(ERROR, - (errmodule(MOD_UDF), - errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED), - errmsg("null probin for C function %u", functionId))); + ereport(ERROR, (errmodule(MOD_UDF), errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED), + errmsg("null probin for C function %u", functionId))); if (fencedMode) { if (languageId == ClanguageId) { @@ -1543,18 +1726,16 @@ bool RPCInitFencedUDFIfNeed(Oid functionId, FmgrInfo* finfo, HeapTuple procedure prosrcattr = SysCacheGetAttr(PROCOID, procedureTuple, Anum_pg_proc_prosrc, &isnull); if (isnull) - ereport(ERROR, - (errmodule(MOD_UDF), - errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED), - errmsg("null prosrc for C function %u", functionId))); + ereport(ERROR, (errmodule(MOD_UDF), errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED), + errmsg("null prosrc for C function %u", functionId))); udfName = TextDatumGetCString(prosrcattr); udfLibPath = TextDatumGetCString(probinattr); - char* udfLibFullPath = expand_dynamic_library_name(udfLibPath); + char *udfLibFullPath = expand_dynamic_library_name(udfLibPath); errno_t errorno = memcpy_s(finfo->fnName, sizeof(finfo->fnName), udfName, strlen(udfName) + 1); securec_check_c(errorno, "\0", "\0"); - finfo->fnLibPath = (char*)MemoryContextAllocZero(finfo->fn_mcxt, strlen(udfLibFullPath) + 1); + finfo->fnLibPath = (char *)MemoryContextAllocZero(finfo->fn_mcxt, strlen(udfLibFullPath) + 1); errorno = memcpy_s(finfo->fnLibPath, strlen(udfLibFullPath) + 1, udfLibFullPath, strlen(udfLibFullPath)); securec_check_c(errorno, "\0", "\0"); pfree_ext(udfLibFullPath); @@ -1566,10 +1747,8 @@ bool RPCInitFencedUDFIfNeed(Oid functionId, FmgrInfo* finfo, HeapTuple procedure */ prosrcattr = SysCacheGetAttr(PROCOID, procedureTuple, Anum_pg_proc_prosrc, &isnull); if (isnull) - ereport(ERROR, - (errmodule(MOD_UDF), - errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED), - errmsg("null prosrc for Java function %u", functionId))); + ereport(ERROR, (errmodule(MOD_UDF), errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED), + errmsg("null prosrc for Java function %u", functionId))); if (languageId == JavalanguageId) { udfLibPath = TextDatumGetCString(prosrcattr); } else { @@ -1577,7 +1756,7 @@ bool RPCInitFencedUDFIfNeed(Oid functionId, FmgrInfo* finfo, HeapTuple procedure udfLibPath = (char *)palloc0(dbinLen * sizeof(char)); pg_itoa(u_sess->proc_cxt.MyDatabaseId, udfLibPath); } - finfo->fnLibPath = (char*)MemoryContextAllocZero(finfo->fn_mcxt, strlen(udfLibPath) + 1); + finfo->fnLibPath = (char *)MemoryContextAllocZero(finfo->fn_mcxt, strlen(udfLibPath) + 1); errno_t errorno = memcpy_s(finfo->fnLibPath, strlen(udfLibPath) + 1, udfLibPath, strlen(udfLibPath)); securec_check_c(errorno, "\0", "\0"); } @@ -1602,7 +1781,7 @@ Datum RPCFencedUDF(FunctionCallInfo fcinfo) /* Step 1: Build UDF RPC connection if need */ if (unlikely((-1 == UDFRPCSocket))) { struct sockaddr_un addrUnix; - errno_t rc = memset_s((void*)&addrUnix, sizeof(addrUnix), 0, sizeof(addrUnix)); + errno_t rc = memset_s((void *)&addrUnix, sizeof(addrUnix), 0, sizeof(addrUnix)); securec_check(rc, "\0", "\0"); addrUnix.sun_family = AF_UNIX; @@ -1610,13 +1789,13 @@ Datum RPCFencedUDF(FunctionCallInfo fcinfo) UDFRPCSocket = socket(AF_UNIX, SOCK_STREAM, 0); if (UDFRPCSocket < 0) { - ereport( - ERROR, (errmodule(MOD_UDF), errcode(ERRCODE_CONNECTION_FAILURE), errmsg("create socket failed: %m"))); + ereport(ERROR, + (errmodule(MOD_UDF), errcode(ERRCODE_CONNECTION_FAILURE), errmsg("create socket failed: %m"))); } - if (connect(UDFRPCSocket, (struct sockaddr*)&addrUnix, sizeof(addrUnix)) < 0) { - ereport(ERROR, - (errmodule(MOD_UDF), errcode(ERRCODE_CONNECTION_FAILURE), errmsg("Run udf RPC connect failed: %m"))); + if (connect(UDFRPCSocket, (struct sockaddr *)&addrUnix, sizeof(addrUnix)) < 0) { + ereport(ERROR, (errmodule(MOD_UDF), errcode(ERRCODE_CONNECTION_FAILURE), + errmsg("Run udf RPC connect failed: %m"))); } } @@ -1626,14 +1805,12 @@ Datum RPCFencedUDF(FunctionCallInfo fcinfo) /* Step 3: Get UDF result */ int len = 0; resetStringInfo(fcinfo->udfInfo.udfMsgBuf); - RecvMsg(UDFRPCSocket, (char*)&len, sizeof(len)); + RecvMsg(UDFRPCSocket, (char *)&len, sizeof(len)); if (len < 0) { - ereport(ERROR, - (errmodule(MOD_UDF), - errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("Variable length %d cannot be negative", len))); + ereport(ERROR, (errmodule(MOD_UDF), errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("Variable length %d cannot be negative", len))); } - char* ptr = (char*)palloc(len + 1); + char *ptr = (char *)palloc(len + 1); RecvMsg(UDFRPCSocket, ptr, len); AppendBufFixedMsgVal(fcinfo->udfInfo.udfMsgBuf, ptr, len); fcinfo->udfInfo.msgReadPtr = fcinfo->udfInfo.udfMsgBuf->data; @@ -1641,7 +1818,7 @@ Datum RPCFencedUDF(FunctionCallInfo fcinfo) /* Get Message type */ short msgType; - GetFixedMsgVal(fcinfo->udfInfo.msgReadPtr, (char*)&msgType, sizeof(msgType), sizeof(msgType)); + GetFixedMsgVal(fcinfo->udfInfo.msgReadPtr, (char *)&msgType, sizeof(msgType), sizeof(msgType)); if (msgType == UDF_RESULT) { int batchRows = batchMode ? fcinfo->udfInfo.argBatchRows : 1; @@ -1654,20 +1831,26 @@ Datum RPCFencedUDF(FunctionCallInfo fcinfo) } } else if (msgType == UDF_ERROR) { int valLen = 0; - GetFixedMsgVal(fcinfo->udfInfo.msgReadPtr, (char*)&valLen, sizeof(valLen), sizeof(valLen)); + GetFixedMsgVal(fcinfo->udfInfo.msgReadPtr, (char *)&valLen, sizeof(valLen), sizeof(valLen)); if (valLen < 0) { - ereport(ERROR, - (errmodule(MOD_UDF), - errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("Variable length %d cannot be negative", valLen))); + ereport(ERROR, (errmodule(MOD_UDF), errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("Variable length %d cannot be negative", valLen))); } - char* errMsg = (char*)palloc0(valLen + 1); - GetFixedMsgVal(fcinfo->udfInfo.msgReadPtr, (char*)errMsg, valLen, valLen + 1); + char *errMsg = (char *)palloc0(valLen + 1); + GetFixedMsgVal(fcinfo->udfInfo.msgReadPtr, (char *)errMsg, valLen, valLen + 1); ereport(ERROR, (errmodule(MOD_UDF), errcode(ERRCODE_DATA_EXCEPTION), errmsg("UDF Error:%s", errMsg))); } return result; } +/* + * 鍔熻兘锛氬垱寤虹敤鎴峰畾涔夊嚱鏁帮紙UDF锛夊搱甯岃〃 + * + * 璇存槑锛 + * 濡傛灉UDFFuncHash涓篘ULL锛屽垯鍒涘缓涓涓搱甯岃〃鐢ㄤ簬瀛樺偍鐢ㄦ埛瀹氫箟鍑芥暟鐨勪俊鎭 + * 璇ュ搱甯岃〃浠ュ嚱鏁扮殑OID锛堝璞℃爣璇嗙锛変綔涓洪敭锛屽苟鍖呭惈UDFFuncHashTabEntry绫诲瀷鐨勫笺 + * 濡傛灉鍝堝笇琛ㄥ凡瀛樺湪锛屽垯涓嶆墽琛屼换浣曟搷浣溿 + */ static void UDFCreateHashTab() { if (NULL == UDFFuncHash) { @@ -1682,14 +1865,21 @@ static void UDFCreateHashTab() UDFFuncHash = hash_create("UDFFuncHash", 100, &hash_ctl, HASH_ELEM | HASH_FUNCTION); } } - -static void FindOrInsertUDFHashTab(FunctionCallInfoData* fcinfo) +/* + * 鍔熻兘锛氭煡鎵炬垨鎻掑叆鐢ㄦ埛瀹氫箟鍑芥暟锛圲DF锛夊搱甯岃〃 + * + * 璇存槑锛 + * 姝ゅ嚱鏁扮敤浜庢煡鎵炬垨鎻掑叆UDF鍝堝笇琛ㄤ腑鐨勬潯鐩紝浠ヤ究鑾峰彇鎴栬缃湁鍏砋DF鐨勪俊鎭 + * 濡傛灉鍦ㄥ搱甯岃〃涓壘鍒颁簡鍑芥暟鐨凮ID锛屽垯灏嗙浉鍏充俊鎭缃埌FunctionCallInfoData涓 + * 濡傛灉娌℃湁鎵惧埌锛屽垯灏嗗嚱鏁颁俊鎭姞杞藉埌鍐呭瓨涓紝骞舵彃鍏ュ搱甯岃〃涓 + */ +static void FindOrInsertUDFHashTab(FunctionCallInfoData *fcinfo) { AssertEreport(UDFFuncHash, MOD_UDF, "Hash table is not initialized in UDF."); Oid oid = fcinfo->flinfo->fn_oid; - UDFFuncHashTabEntry* entry = NULL; - entry = (UDFFuncHashTabEntry*)hash_search(UDFFuncHash, &oid, HASH_FIND, NULL); + UDFFuncHashTabEntry *entry = NULL; + entry = (UDFFuncHashTabEntry *)hash_search(UDFFuncHash, &oid, HASH_FIND, NULL); if (NULL != entry) { @@ -1705,43 +1895,38 @@ static void FindOrInsertUDFHashTab(FunctionCallInfoData* fcinfo) fcinfo->udfInfo = entry->udfInfo; } else { AutoContextSwitch contextSwitcher(THREAD_GET_MEM_CXT_GROUP(MEMORY_CONTEXT_EXECUTOR)); - entry = (UDFFuncHashTabEntry*)hash_search(UDFFuncHash, &oid, HASH_ENTER, NULL); + entry = (UDFFuncHashTabEntry *)hash_search(UDFFuncHash, &oid, HASH_ENTER, NULL); if (NULL != entry) { - FmgrInfo* flinfo = fcinfo->flinfo; + FmgrInfo *flinfo = fcinfo->flinfo; /* Load the shared library, unless we already did */ if (flinfo->fn_languageId == ClanguageId) { - void* libHandle = internal_load_library(flinfo->fnLibPath); + void *libHandle = internal_load_library(flinfo->fnLibPath); if (NULL == libHandle) - ereport(ERROR, - (errmodule(MOD_UDF), - errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED), - errmsg("internal_load_library %s failed: %m", flinfo->fnLibPath))); + ereport(ERROR, (errmodule(MOD_UDF), errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED), + errmsg("internal_load_library %s failed: %m", flinfo->fnLibPath))); /* Look up the function within the library */ flinfo->fn_addr = (PGFunction)pg_dlsym(libHandle, flinfo->fnName); - } else if (flinfo->fn_languageId == JavalanguageId){ + } else if (flinfo->fn_languageId == JavalanguageId) { #ifndef ENABLE_LITE_MODE /* Load libpljava.so to support Java UDF */ char pathbuf[MAXPGPATH]; get_lib_path(my_exec_path, pathbuf); join_path_components(pathbuf, pathbuf, "libpljava.so"); - char* libpljava_location = strdup(pathbuf); - void* libpljava_handler = internal_load_library(libpljava_location); + char *libpljava_location = strdup(pathbuf); + void *libpljava_handler = internal_load_library(libpljava_location); if (NULL == libpljava_handler) - ereport(ERROR, - (errmodule(MOD_UDF), - errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED), - errmsg("internal_load_library %s failed: %m", libpljava_location))); + ereport(ERROR, (errmodule(MOD_UDF), errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED), + errmsg("internal_load_library %s failed: %m", libpljava_location))); free(libpljava_location); /* Look up the java_call_handler function within libpljava.so */ - Datum (*pljava_call_handler)(FunctionCallInfoData*); - pljava_call_handler = (Datum(*)(FunctionCallInfoData*))pg_dlsym(libpljava_handler, "java_call_handler"); + Datum (*pljava_call_handler)(FunctionCallInfoData *); + pljava_call_handler = + (Datum(*)(FunctionCallInfoData *))pg_dlsym(libpljava_handler, "java_call_handler"); if (NULL == pljava_call_handler) - ereport(ERROR, - (errmodule(MOD_UDF), - errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED), - errmsg("load java_call_handler failed."))); + ereport(ERROR, (errmodule(MOD_UDF), errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED), + errmsg("load java_call_handler failed."))); flinfo->fn_addr = pljava_call_handler; #else FEATURE_ON_LITE_MODE_NOT_SUPPORTED(); @@ -1762,10 +1947,11 @@ static void FindOrInsertUDFHashTab(FunctionCallInfoData* fcinfo) free(libpl_location); Datum (*plpython_call_handler)(FunctionCallInfoData *); #ifdef ENABLE_PYTHON2 - plpython_call_handler = (Datum(*)(FunctionCallInfoData *))pg_dlsym(libpl_handler, "plpython_call_handler"); + plpython_call_handler = + (Datum(*)(FunctionCallInfoData *))pg_dlsym(libpl_handler, "plpython_call_handler"); #else - plpython_call_handler = - (Datum(*)(FunctionCallInfoData *))pg_dlsym(libpl_handler, "plpython3_call_handler"); + plpython_call_handler = + (Datum(*)(FunctionCallInfoData *))pg_dlsym(libpl_handler, "plpython3_call_handler"); #endif if (NULL == plpython_call_handler) { ereport(ERROR, (errmodule(MOD_UDF), errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED), @@ -1795,49 +1981,75 @@ void SIGQUITUDFMaster(SIGNAL_ARGS) { UDFMasterQuitFlag = true; } - -void inline SetUDFUnixSocketPath(struct sockaddr_un* unAddrPtr) +/* + * 鍔熻兘锛氳缃瓼enced UDF锛堢敤鎴峰畾涔夊嚱鏁帮級鐨刄nix鍩熷鎺ュ瓧璺緞 + * + * 鍙傛暟鍒楄〃锛 + * unAddrPtr锛氭寚鍚憇truct sockaddr_un鐨勬寚閽堬紝鐢ㄤ簬瀛樺偍Unix鍩熷鎺ュ瓧璺緞 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庢鏌ュ苟璁剧疆Unix鍩熷鎺ュ瓧鐨勮矾寰勩傞鍏堣绠楁墍闇鐨勮矾寰勯暱搴︼紝 + * 鐒跺悗涓庡鎺ュ瓧璺緞鐨勫ぇ灏忚繘琛屾瘮杈冿紝濡傛灉瓒呭嚭鑼冨洿鍒欐姤閿欍 + * 鏈鍚庝娇鐢╯nprintf_s鍑芥暟璁剧疆濂楁帴瀛楄矾寰勩 + */ +void inline SetUDFUnixSocketPath(struct sockaddr_un *unAddrPtr) { /* Check and set unix domain socket path */ uint32 socketPathLen = strlen(g_instance.attr.attr_network.UnixSocketDir) + 1 + strlen(FENCED_UDF_UNIXSOCKET) + 1; if (socketPathLen > sizeof(unAddrPtr->sun_path)) - ereport(FATAL, - (errmodule(MOD_UDF), - errmsg("UnixSocketDir is not valid, length is between 1 and %lu: %s/%s", - sizeof(unAddrPtr->sun_path) - sizeof(FENCED_UDF_UNIXSOCKET) - 2, - g_instance.attr.attr_network.UnixSocketDir, - FENCED_UDF_UNIXSOCKET))); + ereport(FATAL, (errmodule(MOD_UDF), errmsg("UnixSocketDir is not valid, length is between 1 and %lu: %s/%s", + sizeof(unAddrPtr->sun_path) - sizeof(FENCED_UDF_UNIXSOCKET) - 2, + g_instance.attr.attr_network.UnixSocketDir, FENCED_UDF_UNIXSOCKET))); - errno_t rc = snprintf_s(unAddrPtr->sun_path, - sizeof(unAddrPtr->sun_path), - sizeof(unAddrPtr->sun_path) - 1, - "%s/%s", - g_instance.attr.attr_network.UnixSocketDir, - FENCED_UDF_UNIXSOCKET); + errno_t rc = snprintf_s(unAddrPtr->sun_path, sizeof(unAddrPtr->sun_path), sizeof(unAddrPtr->sun_path) - 1, "%s/%s", + g_instance.attr.attr_network.UnixSocketDir, FENCED_UDF_UNIXSOCKET); securec_check_ss(rc, "\0", "\0"); } -void InitUDFInfo(UDFInfoType* udfInfo, int argN, int batchRows) +/* + * 鍔熻兘锛氬垵濮嬪寲UDF淇℃伅缁撴瀯浣 + * + * 鍙傛暟鍒楄〃锛 + * udfInfo锛氭寚鍚慤DF淇℃伅缁撴瀯浣撶殑鎸囬拡锛岀敤浜庡瓨鍌║DF鐨勭浉鍏充俊鎭 + * argN锛歎DF鐨勫弬鏁颁釜鏁 + * batchRows锛氭壒澶勭悊琛屾暟 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庡垵濮嬪寲UDF淇℃伅缁撴瀯浣擄紝鍖呮嫭鍒嗛厤鍐呭瓨绌洪棿鍜岃缃粯璁ゅ笺 + * 涓昏鍒嗛厤鍐呭瓨鏉ュ瓨鍌║DF鐨勬秷鎭紦鍐插尯銆佸弬鏁般佺┖鍊兼爣蹇椼佺粨鏋滅瓑淇℃伅锛屽苟鍒濆鍖栧叾浠栧瓧娈点 + */ +void InitUDFInfo(UDFInfoType *udfInfo, int argN, int batchRows) { + // 涓烘秷鎭紦鍐插尯鍒嗛厤鍐呭瓨 udfInfo->udfMsgBuf = makeStringInfo(); - udfInfo->arg = (Datum**)palloc(sizeof(Datum*) * batchRows); - udfInfo->null = (bool**)palloc(sizeof(bool*) * batchRows); - udfInfo->result = (Datum*)palloc(sizeof(Datum) * batchRows); - udfInfo->resultIsNull = (bool*)palloc(sizeof(bool) * batchRows); + // 涓哄弬鏁版暟缁勫垎閰嶅唴瀛 + udfInfo->arg = (Datum **)palloc(sizeof(Datum *) * batchRows); + // 涓虹┖鍊兼爣蹇楁暟缁勫垎閰嶅唴瀛 + udfInfo->null = (bool **)palloc(sizeof(bool *) * batchRows); + // 涓虹粨鏋滄暟缁勫垎閰嶅唴瀛 + udfInfo->result = (Datum *)palloc(sizeof(Datum) * batchRows); + // 涓虹粨鏋滄槸鍚︿负绌虹殑鏍囧織鏁扮粍鍒嗛厤鍐呭瓨 + udfInfo->resultIsNull = (bool *)palloc(sizeof(bool) * batchRows); + // 鍒濆鍖栨壒澶勭悊琛屾暟 udfInfo->argBatchRows = 0; + // 鍒濆鍖栨秷鎭鍙栨寚閽堜负NULL udfInfo->msgReadPtr = NULL; + // 鍒濆鍖栨湁鏁堢殑UDF鍙傛暟澶勭悊鍣ㄤ负false udfInfo->valid_UDFArgsHandlerPtr = false; + // 鍒濆鍖朥DF缁撴灉澶勭悊鍣ㄤ负NULL udfInfo->UDFResultHandlerPtr = NULL; + // 璁剧疆鍒嗛厤鐨勮鏁 udfInfo->allocRows = batchRows; - + // 涓烘瘡琛屽弬鏁板垎閰嶅唴瀛 for (int i = 0; i < batchRows; ++i) { - udfInfo->arg[i] = (Datum*)palloc(sizeof(Datum) * argN); - udfInfo->null[i] = (bool*)palloc(sizeof(bool) * argN); + udfInfo->arg[i] = (Datum *)palloc(sizeof(Datum) * argN); + udfInfo->null[i] = (bool *)palloc(sizeof(bool) * argN); } - udfInfo->UDFArgsHandlerPtr = (UDFArgsFuncType*)palloc0((argN) * sizeof(UDFArgsFuncType)); + // 涓篣DF鍙傛暟澶勭悊鍣ㄥ垎閰嶅唴瀛 + udfInfo->UDFArgsHandlerPtr = (UDFArgsFuncType *)palloc0((argN) * sizeof(UDFArgsFuncType)); } -void InitFunctionCallUDFArgs(FunctionCallInfoData* fcinfo, int argN, int batchRows) +void InitFunctionCallUDFArgs(FunctionCallInfoData *fcinfo, int argN, int batchRows) { /* For UDF, FmgrInfo must be valid, if not invalid, don't need init the following */ if (argN > 0) { @@ -1845,7 +2057,20 @@ void InitFunctionCallUDFArgs(FunctionCallInfoData* fcinfo, int argN, int batchRo } } -void InitFuncCallUDFInfo(FunctionCallInfoData* fcinfo, int argN, bool setFuncPtr = true) +/* + * 鍔熻兘锛氬垵濮嬪寲鍑芥暟璋冪敤鐨刄DF淇℃伅 + * + * 鍙傛暟鍒楄〃锛 + * fcinfo锛氬嚱鏁拌皟鐢ㄤ俊鎭粨鏋勪綋鎸囬拡 + * argN锛歎DF鐨勫弬鏁颁釜鏁 + * setFuncPtr锛氭槸鍚﹁缃嚱鏁版寚閽堬紝榛樿涓簍rue + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庡垵濮嬪寲鍑芥暟璋冪敤鏃剁殑UDF淇℃伅锛屼富瑕佺敤浜嶧enced UDF鐨勮缃拰鍙傛暟鍒濆鍖栥 + * 濡傛灉鍑芥暟浠enced妯″紡杩愯锛屼細璁剧疆鐩稿叧鐨勫嚱鏁版寚閽堬紝濡傛灉鏈夊弬鏁帮紝涔熶細鍒濆鍖栧弬鏁颁俊鎭 + * 鍚﹀垯锛屼細鍒濆鍖栨秷鎭紦鍐插尯绛夌浉鍏充俊鎭 + */ +void InitFuncCallUDFInfo(FunctionCallInfoData *fcinfo, int argN, bool setFuncPtr = true) { if (unlikely(fcinfo->flinfo && fcinfo->flinfo->fn_fenced)) { if (setFuncPtr) @@ -1859,7 +2084,20 @@ void InitFuncCallUDFInfo(FunctionCallInfoData* fcinfo, int argN, bool setFuncPtr } } } - +/* + * 鍔熻兘锛氬鐞咶enced UDF鐩稿叧鎿嶄綔 + * + * 鍙傛暟鍒楄〃锛 + * PG_FUNCTION_ARGS锛歅ostgreSQL鍑芥暟鍙傛暟鍒楄〃 + * + * 杩斿洖鍊硷細 + * 杩斿洖鏂囨湰绫诲瀷鎴朜ULL + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庡鐞咶enced UDF鐨勭浉鍏虫搷浣滐紝鏍规嵁浼犲叆鐨勫弬鏁颁笉鍚屾墽琛屼笉鍚岀殑鎿嶄綔锛 + * 鍖呮嫭鏌ヨ鍜屾搷浣淔enced UDF鐨勪富杩涚▼鍜屽伐浣滆繘绋嬨傚鏋滀紶鍏ユ棤鏁堢殑鍙傛暟锛 + * 浼氭姏鍑洪敊璇 + */ Datum fenced_udf_process(PG_FUNCTION_ARGS) { int32 arg = PG_GETARG_INT32(0); @@ -1875,17 +2113,18 @@ Datum fenced_udf_process(PG_FUNCTION_ARGS) appendStringInfo(&strinfo, "ps ux | grep 'gaussdb fenced UDF worker process' | grep -v grep | wc -l"); } else if (KILL_WORK == arg) { /* kill UDF work process */ - appendStringInfo(&strinfo, + appendStringInfo( + &strinfo, "ps ux | grep 'gaussdb fenced UDF worker process' | grep -v grep | awk '{print $2}' | xargs kill -9"); } else { ereport(ERROR, (errmodule(MOD_UDF), errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("Invalid parameter."))); } - FILE* fp = popen(strinfo.data, "r"); + FILE *fp = popen(strinfo.data, "r"); if (fp == NULL) { - ereport(ERROR, - (errmodule(MOD_UDF), errcode(ERRCODE_UNEXPECTED_NULL_VALUE), errmsg("execute cmd %s fail.", strinfo.data))); + ereport(ERROR, (errmodule(MOD_UDF), errcode(ERRCODE_UNEXPECTED_NULL_VALUE), + errmsg("execute cmd %s fail.", strinfo.data))); } /* Get process num. */ @@ -1894,7 +2133,7 @@ Datum fenced_udf_process(PG_FUNCTION_ARGS) pfree_ext(strinfo.data); pclose(fp); ereport(ERROR, - (errmodule(MOD_UDF), errcode(ERRCODE_UNEXPECTED_NULL_VALUE), errmsg("Can not read process num."))); + (errmodule(MOD_UDF), errcode(ERRCODE_UNEXPECTED_NULL_VALUE), errmsg("Can not read process num."))); } int len = strlen(result); @@ -1911,69 +2150,75 @@ Datum fenced_udf_process(PG_FUNCTION_ARGS) PG_RETURN_NULL(); } } - -static char* parse_value(char* p_start) +/* + * 鍔熻兘锛氳В鏋愬瓧绗︿覆涓殑鍊硷紝杩斿洖瑙f瀽鍚庣殑瀛愬瓧绗︿覆 + * + * 鍙傛暟鍒楄〃锛 + * p_start锛氬緟瑙f瀽鐨勫瓧绗︿覆鐨勮捣濮嬩綅缃 + * + * 杩斿洖鍊硷細 + * 杩斿洖瑙f瀽鍚庣殑瀛愬瓧绗︿覆锛岃嫢鏃犳硶瑙f瀽鍒欒繑鍥濶ULL + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庤В鏋愬瓧绗︿覆涓殑鍊硷紝浠庣粰瀹氱殑璧峰浣嶇疆寮濮嬭В鏋愶紝鐩村埌閬囧埌绗竴涓┖鏍兼垨'\0'瀛楃涓烘銆 + * 濡傛灉鎴愬姛瑙f瀽锛岃繑鍥炶В鏋愬悗鐨勫瓙瀛楃涓诧紱濡傛灉鏃犳硶瑙f瀽锛岃繑鍥濶ULL銆 + */ +static char *parse_value(char *p_start) { - char* value = NULL; - char* p_end = p_start; + char *value = NULL; + char *p_end = p_start; // seek for the first whitespace or '\0' while (*p_end != '\0' && *p_end != ' ') { p_end++; } if (p_end != p_start) { - value = (char*)palloc((p_end - p_start + 1) * sizeof(char)); + value = (char *)palloc((p_end - p_start + 1) * sizeof(char)); errno_t errorno = strncpy_s(value, p_end - p_start + 1, p_start, p_end - p_start); securec_check_c(errorno, "\0", "\0"); } return value; } - -static void check_input_for_security_s(const char* input) +/* + * 鍔熻兘锛氭鏌ヨ緭鍏ュ瓧绗︿覆鏄惁鍖呭惈娼滃湪鐨勫畨鍏ㄩ闄╁瓧绗 + * + * 鍙傛暟鍒楄〃锛 + * input锛氬緟妫鏌ョ殑杈撳叆瀛楃涓 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庢鏌ヨ緭鍏ュ瓧绗︿覆鏄惁鍖呭惈娼滃湪鐨勫畨鍏ㄩ闄╁瓧绗︼紝濡"|", ";", "&", "$"绛夈 + * 濡傛灉杈撳叆瀛楃涓插寘鍚换浣曡繖浜涘瓧绗︿箣涓锛屽皢寮曞彂閿欒骞剁粓姝㈢▼搴忋 + */ +static void check_input_for_security_s(const char *input) { - char* danger_token[] = {"|", - ";", - "&", - "$", - "<", - ">", - "`", - "\\", - "'", - "\"", - "{", - "}", - "(", - ")", - "[", - "]", - "~", - "*", - "?", - "!", - "\n", - NULL}; + char *danger_token[] = {"|", ";", "&", "$", "<", ">", "`", "\\", "'", "\"", "{", + "}", "(", ")", "[", "]", "~", "*", "?", "!", "\n", NULL}; for (int i = 0; danger_token[i] != NULL; ++i) { if (strstr(input, danger_token[i])) { - ereport(ERROR, - (errmodule(MOD_UDF), - errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("Contains invaid character: \"%s\"", danger_token[i]))); + ereport(ERROR, (errmodule(MOD_UDF), errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("Contains invaid character: \"%s\"", danger_token[i]))); } } } - -static void check_extend_library_option(LibraryInfo* libInfo) +/* + * 鍔熻兘锛氭鏌ユ墿灞曞簱閫夐」鏄惁鍚堟硶 + * + * 鍙傛暟鍒楄〃锛 + * libInfo锛歀ibraryInfo缁撴瀯浣撴寚閽堬紝鍖呭惈浜嗘墿灞曞簱淇℃伅鍜岄夐」 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庢鏌ユ墿灞曞簱閫夐」鏄惁鍚堟硶锛岄夐」搴旇鏄"ls"銆"addjar"鎴"rmjar"涔嬩竴锛 + * 鍚﹀垯灏嗗紩鍙戦敊璇苟缁堟绋嬪簭銆 + */ +static void check_extend_library_option(LibraryInfo *libInfo) { - const char* option = libInfo->option; + const char *option = libInfo->option; int len = 0; /* check option which should not be null */ if (option == NULL || (len = strlen(option)) == 0) { - ereport(ERROR, - (errmodule(MOD_UDF), - errcode(ERRCODE_UNEXPECTED_NULL_VALUE), - errmsg("Invalid argument: should appoint an option of ls, addjar or rmjar."))); + ereport(ERROR, (errmodule(MOD_UDF), errcode(ERRCODE_UNEXPECTED_NULL_VALUE), + errmsg("Invalid argument: should appoint an option of ls, addjar or rmjar."))); } /* check option which should be ls, addjar or rmjar */ @@ -1984,10 +2229,8 @@ static void check_extend_library_option(LibraryInfo* libInfo) } else if ((len == 5) && (strncmp(option, "rmjar", len) == 0)) { libInfo->optionType = OPTION_RMJAR; } else { - ereport(ERROR, - (errmodule(MOD_UDF), - errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("Invalid argument: only support ls, addjar, rmjar options."))); + ereport(ERROR, (errmodule(MOD_UDF), errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("Invalid argument: only support ls, addjar, rmjar options."))); } } @@ -1997,21 +2240,21 @@ static void check_extend_library_option(LibraryInfo* libInfo) * @in filepath: another palloc string of the file path behind "obs://" in obsinfo * @out: OBSInfo structure */ -static OBSInfo* parse_obsinfo(char* obsinfo, char* filepath) +static OBSInfo *parse_obsinfo(char *obsinfo, char *filepath) { - OBSInfo* obsInfo = (OBSInfo*)palloc0(sizeof(OBSInfo)); + OBSInfo *obsInfo = (OBSInfo *)palloc0(sizeof(OBSInfo)); if (filepath == NULL) { ereport(ERROR, (errcode(ERRCODE_UNEXPECTED_NULL_VALUE), errmsg("filepath should not be NULL"))); } - char* p = filepath; + char *p = filepath; while (*p != '\0') { if (*p == '/' && p != filepath) { - obsInfo->bucket = (char*)palloc((p - filepath + 1) * sizeof(char)); + obsInfo->bucket = (char *)palloc((p - filepath + 1) * sizeof(char)); errno_t errorno = strncpy_s(obsInfo->bucket, p - filepath + 1, filepath, p - filepath); securec_check_c(errorno, "\0", "\0"); p++; - obsInfo->path = (char*)palloc((strlen(p) + 1) * sizeof(char)); + obsInfo->path = (char *)palloc((strlen(p) + 1) * sizeof(char)); errorno = strncpy_s(obsInfo->path, strlen(p) + 1, p, strlen(p)); securec_check_c(errorno, "\0", "\0"); break; @@ -2021,13 +2264,13 @@ static OBSInfo* parse_obsinfo(char* obsinfo, char* filepath) } if (obsInfo->bucket == NULL) { - ereport( - ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("Invalid argument: must set correct bucket."))); + ereport(ERROR, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("Invalid argument: must set correct bucket."))); } if (obsInfo->path == NULL) { - ereport(ERROR, - (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("Invalid argument: must set correct obs file path."))); + ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("Invalid argument: must set correct obs file path."))); } if ((p = strstr(obsinfo, "accesskey=")) != NULL) { @@ -2057,7 +2300,7 @@ static OBSInfo* parse_obsinfo(char* obsinfo, char* filepath) return obsInfo; } -static void parse_extend_library_operation(LibraryInfo* libInfo) +static void parse_extend_library_operation(LibraryInfo *libInfo) { /* parse libInfo->operation * the operation format should be like either: @@ -2076,8 +2319,8 @@ static void parse_extend_library_operation(LibraryInfo* libInfo) * and in all cases except OPTION_LS, the 'libraryname' key can not be omitted. */ - char* operation = libInfo->operation; - char* tmp = NULL; + char *operation = libInfo->operation; + char *tmp = NULL; /* Check if there is "libraryname=", and it cannot be omitted except OPTION_LS */ if ((tmp = strstr(operation, "libraryname=")) != NULL) { @@ -2086,11 +2329,12 @@ static void parse_extend_library_operation(LibraryInfo* libInfo) if (libInfo->destpath == NULL) { if (libInfo->optionType != OPTION_LS) ereport(ERROR, (errmodule(MOD_UDF), errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("Invalid argument: must set a \"libraryname\"."))); + errmsg("Invalid argument: must set a \"libraryname\"."))); } else { if ((strstr(libInfo->destpath, "/") != NULL) || libInfo->destpath[0] == '.') - ereport(ERROR, (errmodule(MOD_UDF), errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("Invalid argument: \"libraryname\" should not contain \"/\" or starting with \".\"."))); + ereport(ERROR, + (errmodule(MOD_UDF), errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("Invalid argument: \"libraryname\" should not contain \"/\" or starting with \".\"."))); } if (libInfo->optionType != OPTION_ADDJAR) { @@ -2105,12 +2349,12 @@ static void parse_extend_library_operation(LibraryInfo* libInfo) tmp = operation + strlen("file://"); if ((libInfo->localpath = parse_value(tmp)) == NULL || libInfo->localpath[0] != '/') { ereport(ERROR, (errmodule(MOD_UDF), errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("Invalid argument: must set an absolute path followed by \"file:///\"."))); + errmsg("Invalid argument: must set an absolute path followed by \"file:///\"."))); } if (strlen(libInfo->localpath) < 4 || - (strncmp(libInfo->localpath + strlen(libInfo->localpath) - 4, ".jar", 4) != 0 )) { + (strncmp(libInfo->localpath + strlen(libInfo->localpath) - 4, ".jar", 4) != 0)) { ereport(ERROR, (errmodule(MOD_UDF), errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("Invalid argument: the source file must be .jar file."))); + errmsg("Invalid argument: the source file must be .jar file."))); } } else if (strncmp(operation, "obs://", strlen("obs://")) == 0) { /* Check if there is "obs://". @@ -2119,18 +2363,18 @@ static void parse_extend_library_operation(LibraryInfo* libInfo) */ if (!isSecurityMode) { ereport(ERROR, (errmodule(MOD_UDF), errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("Invalid argument: must set an absolute path followed by \"file:///\"."))); + errmsg("Invalid argument: must set an absolute path followed by \"file:///\"."))); } libInfo->isSourceLocal = false; tmp = operation + strlen("obs://"); if ((tmp = parse_value(tmp)) == NULL) { ereport(ERROR, (errmodule(MOD_UDF), errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("Invalid argument: must set bucket and filepath followed by \"obs://\"."))); + errmsg("Invalid argument: must set bucket and filepath followed by \"obs://\"."))); } if (strlen(tmp) < 4 || (strncmp(tmp + strlen(tmp) - 4, ".jar", 4) != 0)) { ereport(ERROR, (errmodule(MOD_UDF), errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("Invalid argument: the source file must be .jar file."))); + errmsg("Invalid argument: the source file must be .jar file."))); } libInfo->obsInfo = parse_obsinfo(operation, tmp); @@ -2138,7 +2382,7 @@ static void parse_extend_library_operation(LibraryInfo* libInfo) } else { /* must set "file://" or "obs://" when OPTION_ADDJAR */ ereport(ERROR, (errmodule(MOD_UDF), errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("must set correct source file path."))); + errmsg("must set correct source file path."))); } char pathbuf[MAXPGPATH]; @@ -2147,7 +2391,7 @@ static void parse_extend_library_operation(LibraryInfo* libInfo) join_path_components(pathbuf, pathbuf, libInfo->destpath); if (access(pathbuf, F_OK) == 0) { ereport(ERROR, (errmodule(MOD_UDF), errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("Invalid argument: the library already existed, please remove it first using rmjar."))); + errmsg("Invalid argument: the library already existed, please remove it first using rmjar."))); } } @@ -2158,7 +2402,7 @@ static void parse_extend_library_operation(LibraryInfo* libInfo) * @in tmp_path: $GAUSSHOME/share/postgresql/tmp * @out: void */ -static void get_obsfile(OBSInfo* obsInfo, const char* tmp_path) +static void get_obsfile(OBSInfo *obsInfo, const char *tmp_path) { #ifndef ENABLE_MULTIPLE_NODES DISTRIBUTED_FEATURE_NOT_SUPPORTED(); @@ -2170,26 +2414,19 @@ static void get_obsfile(OBSInfo* obsInfo, const char* tmp_path) check_backend_env(tmp_path); - appendStringInfo(&cmd, - "python %s/udstools.py %s %s %s %s %s %s", - tmp_path, obsInfo->accesskey, obsInfo->secretkey, obsInfo->path, - obsInfo->region, obsInfo->bucket, tmp_path); + appendStringInfo(&cmd, "python %s/udstools.py %s %s %s %s %s %s", tmp_path, obsInfo->accesskey, obsInfo->secretkey, + obsInfo->path, obsInfo->region, obsInfo->bucket, tmp_path); /* reset key buffer to avoid private info leak */ errno_t ret = memset_s(obsInfo->accesskey, strlen(obsInfo->accesskey) + 1, 0, strlen(obsInfo->accesskey) + 1); securec_check(ret, "\0", "\0"); ret = memset_s(obsInfo->secretkey, strlen(obsInfo->secretkey) + 1, 0, strlen(obsInfo->secretkey) + 1); securec_check(ret, "\0", "\0"); - ereport(DEBUG1, - (errmodule(MOD_UDF), - errmsg("[udstools]:%s/udstools.py\n" - "[path]:%s\n" - "[region]:%s\n" - "[bucket]:%s\n", - tmp_path, - obsInfo->path, - obsInfo->region, - obsInfo->bucket))); + ereport(DEBUG1, (errmodule(MOD_UDF), errmsg("[udstools]:%s/udstools.py\n" + "[path]:%s\n" + "[region]:%s\n" + "[bucket]:%s\n", + tmp_path, obsInfo->path, obsInfo->region, obsInfo->bucket))); /* execute downloading from obs */ check_input_for_security_s(cmd.data); @@ -2199,19 +2436,13 @@ static void get_obsfile(OBSInfo* obsInfo, const char* tmp_path) ret = memset_s(cmd.data, cmd.len, 0, cmd.len); securec_check(ret, "\0", "\0"); resetStringInfo(&cmd); - appendStringInfo(&cmd, - "python %s/udstools.py * * %s %s %s %s", - tmp_path, - obsInfo->path, - obsInfo->region, - obsInfo->bucket, - tmp_path); + appendStringInfo(&cmd, "python %s/udstools.py * * %s %s %s %s", tmp_path, obsInfo->path, obsInfo->region, + obsInfo->bucket, tmp_path); if (rc == -1 || WIFEXITED(rc) == 0) { - ereport(LOG, - (errcode(ERRCODE_SYSTEM_ERROR), errmsg("[status]:%d %d System error. \"%s\"", rc, WIFEXITED(rc), cmd.data))); - ereport(ERROR, - (errcode(ERRCODE_SYSTEM_ERROR), errmsg("%d %d: System error.", rc, WIFEXITED(rc)))); + ereport(LOG, (errcode(ERRCODE_SYSTEM_ERROR), + errmsg("[status]:%d %d System error. \"%s\"", rc, WIFEXITED(rc), cmd.data))); + ereport(ERROR, (errcode(ERRCODE_SYSTEM_ERROR), errmsg("%d %d: System error.", rc, WIFEXITED(rc)))); } ereport(LOG, (errmsg("[status]:%d %d %d [command]:\"%s\"", rc, WIFEXITED(rc), WEXITSTATUS(rc), cmd.data))); @@ -2225,42 +2456,34 @@ static void get_obsfile(OBSInfo* obsInfo, const char* tmp_path) case OBS_FAILED_IO_ERROR: ereport(ERROR, - ((errcode(ERRCODE_SQL_ROUTINE_EXCEPTION), - errmsg("%d: Failed to access system files.", rc)))); + ((errcode(ERRCODE_SQL_ROUTINE_EXCEPTION), errmsg("%d: Failed to access system files.", rc)))); break; case OBS_FAILED_INCORRECT_REGION: - ereport(ERROR, - ((errcode(ERRCODE_SQL_ROUTINE_EXCEPTION), - errmsg("%d: Invalid argument, must set correct region.", rc)))); + ereport(ERROR, ((errcode(ERRCODE_SQL_ROUTINE_EXCEPTION), + errmsg("%d: Invalid argument, must set correct region.", rc)))); break; case OBS_FAILED_INVALID_ARGUMENT: - ereport(ERROR, - ((errcode(ERRCODE_SQL_ROUTINE_EXCEPTION), errmsg("%d: Parameters error.", rc)))); + ereport(ERROR, ((errcode(ERRCODE_SQL_ROUTINE_EXCEPTION), errmsg("%d: Parameters error.", rc)))); break; case OBS_FAILED_BASE_EXCEPTION: - ereport( - ERROR, ((errcode(ERRCODE_SQL_ROUTINE_EXCEPTION), errmsg("%d: System error.", rc)))); + ereport(ERROR, ((errcode(ERRCODE_SQL_ROUTINE_EXCEPTION), errmsg("%d: System error.", rc)))); break; case OBS_FAILED_CONNECT_TO_UDS_SERVER: - ereport(ERROR, - ((errcode(ERRCODE_CONNECTION_FAILURE), - errmsg("%d: Failed to connect to obs server.", rc)))); + ereport(ERROR, ((errcode(ERRCODE_CONNECTION_FAILURE), errmsg("%d: Failed to connect to obs server.", rc)))); break; case OBS_FAILED_DOWNLOAD_FROM_UDS_SERVER: ereport(ERROR, - ((errcode(ERRCODE_SQL_ROUTINE_EXCEPTION), - errmsg("%d: Failed to download from obs server.", rc)))); + ((errcode(ERRCODE_SQL_ROUTINE_EXCEPTION), errmsg("%d: Failed to download from obs server.", rc)))); break; case OBS_FAILED_TRY_AGAIN: ereport(ERROR, - ((errcode(ERRCODE_CONNECTION_FAILURE), - errmsg("%d: Obs server is busy. Try again later.", rc)))); + ((errcode(ERRCODE_CONNECTION_FAILURE), errmsg("%d: Obs server is busy. Try again later.", rc)))); break; default: @@ -2272,7 +2495,7 @@ static void get_obsfile(OBSInfo* obsInfo, const char* tmp_path) #endif } -static void execute_udstools_commnd(LibraryInfo* libInfo) +static void execute_udstools_commnd(LibraryInfo *libInfo) { /* As gs_om addjar command can only distrubte local file, * so we have to download obs file using udstools.py into $GAUSSHOME/share/postgresql/tmp/ first, @@ -2283,20 +2506,20 @@ static void execute_udstools_commnd(LibraryInfo* libInfo) char pathbuf[MAXPGPATH]; get_share_path(my_exec_path, pathbuf); join_path_components(pathbuf, pathbuf, "tmp"); - char* tmp_path = pstrdup(pathbuf); + char *tmp_path = pstrdup(pathbuf); get_obsfile(libInfo->obsInfo, tmp_path); - join_path_components(pathbuf, - pathbuf, - (last_dir_separator(libInfo->obsInfo->path) == NULL) ? libInfo->obsInfo->path - : (last_dir_separator(libInfo->obsInfo->path) + 1)); + join_path_components(pathbuf, pathbuf, + (last_dir_separator(libInfo->obsInfo->path) == NULL) + ? libInfo->obsInfo->path + : (last_dir_separator(libInfo->obsInfo->path) + 1)); libInfo->localpath = pstrdup(pathbuf); pfree_ext(tmp_path); } -static char* execute_gsom_javaudf_command(LibraryInfo* libInfo) +static char *execute_gsom_javaudf_command(LibraryInfo *libInfo) { StringInfoData cmd; initStringInfo(&cmd); @@ -2309,7 +2532,7 @@ static char* execute_gsom_javaudf_command(LibraryInfo* libInfo) } ereport(DEBUG1, (errmodule(MOD_UDF), errmsg("[gs_om]: %s", cmd.data))); - FILE* fp = NULL; + FILE *fp = NULL; char results[MAXPGPATH]; /* handle the gs_om command return message per line. */ StringInfoData ret; initStringInfo(&ret); @@ -2328,7 +2551,7 @@ static char* execute_gsom_javaudf_command(LibraryInfo* libInfo) * or parse the expected results and stored in 'ret'. */ while (fgets(results, sizeof(results), fp) != NULL) { - char* tmp = NULL; + char *tmp = NULL; if ((tmp = strstr(results, "command not found")) != NULL) { /* get rid of the last \n */ tmp[strlen(tmp) - 1] = '\0'; @@ -2402,21 +2625,22 @@ static char* execute_gsom_javaudf_command(LibraryInfo* libInfo) ereport(DEBUG1, (errmodule(MOD_UDF), errmsg("[rm_tmp]: %s", cmd.data))); int rc = system(cmd.data); if (rc != 0) { - ereport(LOG, - (errcode(ERRCODE_SYSTEM_ERROR), - errmsg("[WARNING] remove the tmp file downloaded from the OBS Server failed, [command] %s", cmd.data))); + ereport(LOG, (errcode(ERRCODE_SYSTEM_ERROR), + errmsg("[WARNING] remove the tmp file downloaded from the OBS Server failed, [command] %s", + cmd.data))); } } if (isFailed) { - ereport(LOG, (errcode(ERRCODE_SQL_ROUTINE_EXCEPTION), errmsg("execute command failed, [command] %s", cmd.data))); - ereport(ERROR, (errmodule(MOD_UDF), - (errcode(ERRCODE_SQL_ROUTINE_EXCEPTION), errmsg("execute command failed")))); + ereport(LOG, + (errcode(ERRCODE_SQL_ROUTINE_EXCEPTION), errmsg("execute command failed, [command] %s", cmd.data))); + ereport(ERROR, + (errmodule(MOD_UDF), (errcode(ERRCODE_SQL_ROUTINE_EXCEPTION), errmsg("execute command failed")))); } if (isError) { ereport(ERROR, (errmodule(MOD_UDF), errcode(ERRCODE_SQL_ROUTINE_EXCEPTION), - errmsg("%s", (ret.len > 0) ? ret.data : "Cannot get detailed execution results."))); + errmsg("%s", (ret.len > 0) ? ret.data : "Cannot get detailed execution results."))); } /* the execution succeed, we return \"t\" as a successful operation */ @@ -2439,17 +2663,18 @@ PG_FUNCTION_INFO_V1(gs_extend_library); Datum gs_extend_library(PG_FUNCTION_ARGS) { #ifndef ENABLE_MULTIPLE_NODES - ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), (errmsg("Unsupport feature"), - errdetail("gs_extend_library is not supported for centralize deployment"), - errcause("The function is not implemented."), erraction("Do not use this function.")))); + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + (errmsg("Unsupport feature"), errdetail("gs_extend_library is not supported for centralize deployment"), + errcause("The function is not implemented."), erraction("Do not use this function.")))); #endif if (!superuser()) { ereport(ERROR, (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), - (errmsg("must be system admin to use the gs_extend_library function")))); + (errmsg("must be system admin to use the gs_extend_library function")))); } - LibraryInfo* libInfo = (LibraryInfo*)palloc0(sizeof(LibraryInfo)); + LibraryInfo *libInfo = (LibraryInfo *)palloc0(sizeof(LibraryInfo)); libInfo->option = PG_GETARG_CSTRING(0); libInfo->operation = PG_GETARG_CSTRING(1); libInfo->destpath = NULL; @@ -2457,7 +2682,7 @@ Datum gs_extend_library(PG_FUNCTION_ARGS) libInfo->isSourceLocal = true; libInfo->obsInfo = NULL; - char* result = NULL; + char *result = NULL; ExtendLibraryStatus status = EXTENDLIB_CHECK_OPTION; bool done = false; while (!done) { @@ -2474,9 +2699,8 @@ Datum gs_extend_library(PG_FUNCTION_ARGS) break; } - ereport(ERROR, (errmodule(MOD_UDF), - errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("Invaid argument: must at least set libraryname"))); + ereport(ERROR, (errmodule(MOD_UDF), errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("Invaid argument: must at least set libraryname"))); } parse_extend_library_operation(libInfo); @@ -2533,11 +2757,11 @@ Datum gs_extend_library(PG_FUNCTION_ARGS) * @in extension: user-defined obs file name extension * @out: $GAUSSHOME/share/postgresql/tmp/ */ -char* get_obsfile_local(char* pathname, const char* basename, const char* extension) +char *get_obsfile_local(char *pathname, const char *basename, const char *extension) { - char* fullname = NULL; - char* tmp_path = NULL; - OBSInfo* obsinfo = NULL; + char *fullname = NULL; + char *tmp_path = NULL; + OBSInfo *obsinfo = NULL; StringInfoData tmp; initStringInfo(&tmp); @@ -2550,7 +2774,7 @@ char* get_obsfile_local(char* pathname, const char* basename, const char* extens tmp_path = parse_value(pathname); if (tmp_path == NULL) ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("Invalid argument: must set correct bucket and obs file path."))); + errmsg("Invalid argument: must set correct bucket and obs file path."))); appendStringInfo(&tmp, "%s", tmp_path); if (tmp_path[strlen(tmp_path) - 1] != '/') diff --git a/src/gausskernel/process/postmaster/fork_process.cpp b/src/gausskernel/process/postmaster/fork_process.cpp index 45bafed55..54f0b9551 100644 --- a/src/gausskernel/process/postmaster/fork_process.cpp +++ b/src/gausskernel/process/postmaster/fork_process.cpp @@ -43,6 +43,7 @@ pid_t fork_process(void) * Presently stdout and stderr are the only stdio output channels used by * the postmaster, so fflush'ing them should be sufficient. */ + // 鍒锋柊鏍囧噯杈撳嚭鍜屾爣鍑嗛敊璇祦锛岄伩鍏嶈緭鍑洪棶棰 fflush(stdout); fflush(stderr); @@ -57,15 +58,16 @@ pid_t fork_process(void) getitimer(ITIMER_PROF, &prof_itimer); #endif - result = fork(); + result = fork(); // 鍒涘缓瀛愯繘绋 - if (result == 0) { + if (result == 0) { // fork鎴愬姛 /* fork succeeded, in child */ #ifdef LINUX_PROFILE - setitimer(ITIMER_PROF, &prof_itimer, NULL); + setitimer(ITIMER_PROF, &prof_itimer, NULL); // 璁剧疆鎬ц兘鍒嗘瀽璁℃椂鍣紝浠ヤ繚璇佸瓙杩涚▼涔熻兘杩涜鎬ц兘鍒嗘瀽 #endif /* + * 寮鸿皟浜嗗湪Linux绯荤粺涓繚鎶ostmaster杩涚▼鍏嶅彈OOM鏉姝荤殑闂锛屽苟鎻愪緵浜嗕竴浜涜В鍐虫柟娉曞拰寤鸿 * By default, Linux tends to kill the postmaster in out-of-memory * situations, because it blames the postmaster for the sum of child * process sizes *including shared memory*. (This is unbelievably @@ -84,19 +86,19 @@ pid_t fork_process(void) * Use open() not stdio, to ensure we control the open flags. Some * Linux security environments reject anything but O_WRONLY. */ - int fd = open("/proc/self/oom_score_adj", O_WRONLY, 0); + int fd = open("/proc/self/oom_score_adj", O_WRONLY, 0); // 鎵撳紑OOM鍒嗘暟璋冩暣鏂囦欢 /* We ignore all errors */ if (fd >= 0) { - char buf[16]; - int rc; + char buf[16]; // 鐢ㄤ簬瀛樺偍瑕佸啓鍏ユ枃浠剁殑瀛楃涓 + int rc; // 鐢ㄤ簬瀛樺偍write()鍑芥暟鐨勮繑鍥炲 - errno_t rcs = snprintf_s(buf, sizeof(buf), sizeof(buf) - 1, "%d\n", LINUX_OOM_SCORE_ADJ); - securec_check_intval(rcs, ); + errno_t rcs = snprintf_s(buf, sizeof(buf), sizeof(buf) - 1, "%d\n", LINUX_OOM_SCORE_ADJ); // 鏍煎紡鍖朞OM鍒嗘暟璋冩暣鍊间负瀛楃涓 + securec_check_intval(rcs, ); // 妫鏌nprintf_s鍑芥暟鐨勮繑鍥炲 - rc = write(fd, buf, strlen(buf)); - (void)rc; - close(fd); + rc = write(fd, buf, strlen(buf)); // 灏哋OM鍒嗘暟璋冩暣鍊煎啓鍏ユ枃浠 + (void)rc; // 闃叉缂栬瘧鍣ㄨ鍛 + close(fd); // 鍏抽棴鏂囦欢 } } #endif /* LINUX_OOM_SCORE_ADJ */ @@ -113,25 +115,25 @@ pid_t fork_process(void) * Use open() not stdio, to ensure we control the open flags. Some * Linux security environments reject anything but O_WRONLY. */ - int fd = open("/proc/self/oom_adj", O_WRONLY, 0); + int fd = open("/proc/self/oom_adj", O_WRONLY, 0); // 鎵撳紑OOM璋冩暣鏂囦欢 /* We ignore all errors */ if (fd >= 0) { - char buf[16]; - int rc; + char buf[16];// 鐢ㄤ簬瀛樺偍瑕佸啓鍏ユ枃浠剁殑瀛楃涓 + int rc; // 鐢ㄤ簬瀛樺偍write()鍑芥暟鐨勮繑鍥炲 errno_t rcs = snprintf_s(buf, sizeof(buf), sizeof(buf) - 1, "%d\n", LINUX_OOM_ADJ); - securec_check_intval(rcs, ); + securec_check_intval(rcs, ); // 妫鏌nprintf_s鍑芥暟鐨勮繑鍥炲 - rc = write(fd, buf, strlen(buf)); - (void)rc; - close(fd); + rc = write(fd, buf, strlen(buf)); // 灏哋OM璋冩暣鍊煎啓鍏ユ枃浠 + (void)rc; // 闃叉缂栬瘧鍣ㄨ鍛 + close(fd); // 鍏抽棴鏂囦欢 } } #endif /* LINUX_OOM_ADJ */ /* Binding static TLS variables for current thread */ - EarlyBindingTLSVariables(); + EarlyBindingTLSVariables(); // 缁戝畾褰撳墠绾跨▼鐨勯潤鎬乀LS鍙橀噺 } return result; diff --git a/src/gausskernel/process/postmaster/globalstats.cpp b/src/gausskernel/process/postmaster/globalstats.cpp index 921c87dc7..69c92b4f6 100644 --- a/src/gausskernel/process/postmaster/globalstats.cpp +++ b/src/gausskernel/process/postmaster/globalstats.cpp @@ -60,52 +60,94 @@ static void GlobalstatsSigusr2Handler(SIGNAL_ARGS); static void GlobalstatsSigtermHandler(SIGNAL_ARGS); /* SIGHUP: set flag to re-read config file at next convenient time */ +/* + * 鍔熻兘锛歋IGHUP 淇″彿澶勭悊绋嬪簭锛屽湪涓嬩竴涓柟渚跨殑鏃堕棿閲嶆柊璇诲彇閰嶇疆鏂囦欢 + * + * 鍙傛暟: + * SIGNAL_ARGS: 淇″彿澶勭悊绋嬪簭鐨勫弬鏁板垪琛紝鎻愪緵鍏充簬瑙﹀彂淇″彿鐨勪笂涓嬫枃淇℃伅 + * + * 杩斿洖鍊: + * 鏃 + */ static void GlobalstatsSighupHandler(SIGNAL_ARGS) { - int saveErrno = errno; + int saveErrno = errno; // 淇濆瓨褰撳墠鐨勯敊璇爜 - t_thrd.gstat_cxt.got_SIGHUP = true; + t_thrd.gstat_cxt.got_SIGHUP = true; // 璁剧疆鏍囧織浠ユ寚绀洪渶瑕佸湪涓嬩竴涓柟渚跨殑鏃堕棿閲嶆柊璇诲彇閰嶇疆鏂囦欢 if (t_thrd.proc) - SetLatch(&t_thrd.proc->procLatch); + SetLatch(&t_thrd.proc->procLatch);// 濡傛灉杩涚▼瀛樺湪锛屽垯璁剧疆杩涚▼鐨凩atch浠ュ敜閱掕繘绋 - errno = saveErrno; + errno = saveErrno;// 鎭㈠涔嬪墠淇濆瓨鐨勯敊璇爜 } /* SIGUSR2: a worker is up and running, or just finished, or failed to fork */ +/* + * 鍔熻兘锛歋IGUSR2 淇″彿澶勭悊绋嬪簭锛岃〃绀轰竴涓伐浣滆繘绋嬪凡鍚姩銆佽繍琛屽畬鎴愭垨鏃犳硶 fork銆 + * + * 鍙傛暟: + * SIGNAL_ARGS: 淇″彿澶勭悊绋嬪簭鐨勫弬鏁板垪琛紝鎻愪緵鍏充簬瑙﹀彂淇″彿鐨勪笂涓嬫枃淇℃伅 + * + * 杩斿洖鍊: + * 鏃 + */ static void GlobalstatsSigusr2Handler(SIGNAL_ARGS) { - int saveErrno = errno; + int saveErrno = errno; // 淇濆瓨褰撳墠鐨勯敊璇爜 - t_thrd.gstat_cxt.got_SIGUSR2 = true; + t_thrd.gstat_cxt.got_SIGUSR2 = true; // 璁剧疆鏍囧織浠ユ寚绀烘帴鏀跺埌SIGUSR2淇″彿 if (t_thrd.proc) - SetLatch(&t_thrd.proc->procLatch); + SetLatch(&t_thrd.proc->procLatch); // 濡傛灉杩涚▼瀛樺湪锛屽垯璁剧疆杩涚▼鐨凩atch浠ュ敜閱掕繘绋 - errno = saveErrno; + errno = saveErrno; // 鎭㈠涔嬪墠淇濆瓨鐨勯敊璇爜 } /* SIGTERM: time to die */ +/* + * 鍔熻兘锛歋IGTERM 淇″彿澶勭悊绋嬪簭锛岃姹傛甯搁鍑 + * + * 鍙傛暟: + * SIGNAL_ARGS: 淇″彿澶勭悊绋嬪簭鐨勫弬鏁板垪琛紝鎻愪緵鍏充簬瑙﹀彂淇″彿鐨勪笂涓嬫枃淇℃伅 + * + * 杩斿洖鍊: + * 鏃 + */ static void GlobalstatsSigtermHandler(SIGNAL_ARGS) { - int saveErrno = errno; + int saveErrno = errno;// 淇濆瓨褰撳墠鐨勯敊璇爜 - t_thrd.gstat_cxt.got_SIGTERM = true; + t_thrd.gstat_cxt.got_SIGTERM = true; // 璁剧疆鏍囧織浠ユ寚绀洪渶瑕佹甯搁鍑 if (t_thrd.proc) - SetLatch(&t_thrd.proc->procLatch); + SetLatch(&t_thrd.proc->procLatch); // 濡傛灉杩涚▼瀛樺湪锛屽垯璁剧疆杩涚▼鐨凩atch浠ュ敜閱掕繘绋 - errno = saveErrno; + errno = saveErrno;// 鎭㈠涔嬪墠淇濆瓨鐨勯敊璇爜 } +/* + * 鍔熻兘锛氬噯澶囧垏鎹㈠叏灞缁熻淇℃伅鍝堝笇琛ㄧ殑鐘舵 + * + * 鍦ㄥ垏鎹㈠叏灞缁熻淇℃伅鍝堝笇琛ㄤ箣鍓嶏紝闇瑕佺‘淇濇病鏈夊叾浠栫嚎绋嬫鍦ㄨ鍙栧搱甯岃〃銆 + * 璇ュ嚱鏁颁細鍏堣缃竴涓 quiesce 鏍囧織锛岀劧鍚庣瓑寰呮墍鏈夎鍙栧搱甯岃〃鐨勭嚎绋嬪畬鎴愩 + * 鍙湁褰 quiesce 鏍囧織涓 0 鏃讹紝鎵嶈兘瀹夊叏鍦拌繘琛屽垏鎹€ + * + * 鍙傛暟: 鏃 + * + * 杩斿洖鍊: 鏃 + */ static void PrepareStatsHashForSwitch() { + // 鏂█ quiesce 鏍囧織涓 0锛岀‘淇濇病鏈夊叾浠栫嚎绋嬫鍦ㄥ垏鎹 Assert(pg_atomic_read_u64(&g_instance.stat_cxt.tableStat->quiesce) == 0); + // 灏 quiesce 鏍囧織璁剧疆涓 1锛岃〃绀烘鍦ㄥ垏鎹 pg_atomic_exchange_u64(&g_instance.stat_cxt.tableStat->quiesce, 1); - + // 鑾峰彇褰撳墠璇诲彇鍝堝笇琛ㄧ殑绾跨▼鏁 uint64 readers = pg_atomic_read_u64(&g_instance.stat_cxt.tableStat->readers); + // 鏂█璇诲彇绾跨▼鏁板皬浜庢荤嚎绋嬫暟 Assert(readers < (uint64) GLOBAL_ALL_PROCS); /* Wait until all readers are done */ - while (readers > 0) { - pg_usleep(10000L); + while (readers > 0) { // 绛夊緟鎵鏈夎鍙栫嚎绋嬪畬鎴 + pg_usleep(10000L); // 绛夊緟涓娈垫椂闂达紝浠ュ厤杩囦簬棰戠箒鍦版鏌 + // 閲嶆柊鑾峰彇璇诲彇绾跨▼鏁 readers = pg_atomic_read_u64(&g_instance.stat_cxt.tableStat->readers); } } @@ -118,16 +160,31 @@ static void CompleteStatsHashSwitch() pg_atomic_exchange_u64(&g_instance.stat_cxt.tableStat->quiesce, 0); } +/* + * 鍔熻兘锛氬尮閰嶅叏灞缁熻淇℃伅鍝堝笇琛ㄧ殑閿 + * + * 鐢ㄤ簬姣旇緝涓や釜鍝堝笇琛ㄩ敭鏄惁鍖归厤銆傚湪鍏ㄥ眬缁熻淇℃伅鍝堝笇琛ㄤ腑锛岄敭鐨勭被鍨嬩负 PgStat_StartBlockTableKey銆 + * 濡傛灉涓や釜閿殑 relid銆乸arentid 鍜 dbid 閮界浉绛夛紝閭d箞璁や负瀹冧滑鍖归厤銆 + * + * 鍙傛暟: + * - left: 宸﹁竟鐨勯敭 + * - right: 鍙宠竟鐨勯敭 + * - keysize: 閿殑澶у皬 + * + * 杩斿洖鍊: 0 琛ㄧず鍖归厤锛岄潪 0 琛ㄧず涓嶅尮閰 + */ static int MatchDictItem(const void* left, const void* right, Size keysize) { + // 灏嗗乏鍙充袱涓敭杞崲涓 PgStat_StartBlockTableKey 绫诲瀷 const PgStat_StartBlockTableKey* leftItem = (PgStat_StartBlockTableKey*)left; const PgStat_StartBlockTableKey* rightItem = (PgStat_StartBlockTableKey*)right; - Assert(leftItem != NULL && rightItem != NULL); + Assert(leftItem != NULL && rightItem != NULL); // 鏂█宸﹀彸閿兘涓嶄负绌 /* we just care whether the result is 0 or not. */ + // 濡傛灉 relid銆乸arentid 鍜 dbid 閮界浉绛夛紝鍒欒繑鍥 0锛岃〃绀哄尮閰 if (leftItem->relid != rightItem->relid || leftItem->parentid != rightItem->parentid || leftItem->dbid != rightItem->dbid) { - return 1; + return 1; // 涓嶅尮閰嶏紝杩斿洖闈 0 鍊 } return 0; @@ -138,26 +195,39 @@ static uint32 HashDictItem(const void* key, Size keysize) return DatumGetUInt32(hash_any((const unsigned char*)key, sizeof(PgStat_StartBlockTableKey))); } +/* + * 鍔熻兘锛氬垵濮嬪寲鍏ㄥ眬缁熻淇℃伅杩借釜鍣 + * + * 鍙傛暟: 鏃 + * + * 杩斿洖鍊: 鏃 + */ void GlobalStatsTrackerInit() { /* Setup a shared memory context that other backends can access. * This will hold the Global Statistics Hash */ + // 璁剧疆涓涓叾浠栧悗绔繘绋嬪彲浠ヨ闂殑鍏变韩鍐呭瓨涓婁笅鏂 g_instance.stat_cxt.tableStat->global_stats_cxt = AllocSetContextCreate((MemoryContext)g_instance.instance_context, "GlobalStatisticsContext", ALLOCSET_DEFAULT_MINSIZE, ALLOCSET_DEFAULT_INITSIZE, ALLOCSET_DEFAULT_MAXSIZE, SHARED_CONTEXT); - + // 鍒濆鍖栧搱甯岃〃鎺у埗缁撴瀯 HASHCTL hashCtrl; errno_t rc = memset_s(&hashCtrl, sizeof(hashCtrl), 0, sizeof(hashCtrl)); securec_check(rc, "", ""); + // 璁剧疆鍝堝笇琛ㄧ殑鍝堝笇鍑芥暟鍜屾瘮杈冨嚱鏁 hashCtrl.hash = (HashValueFunc)HashDictItem; hashCtrl.match = (HashCompareFunc)MatchDictItem; + // 璁剧疆鍝堝笇琛ㄩ敭鐨勫ぇ灏忓拰鏉$洰鐨勫ぇ灏 hashCtrl.keysize = (Size)sizeof(PgStat_StartBlockTableKey); hashCtrl.entrysize = (Size)sizeof(PgStat_StartBlockTableEntry); + // 璁剧疆鍝堝笇琛ㄧ殑涓婁笅鏂囦负鍏ㄥ眬缁熻淇℃伅涓婁笅鏂 hashCtrl.hcxt = g_instance.stat_cxt.tableStat->global_stats_cxt; + // 璁剧疆鍝堝笇琛ㄧ殑鍒嗗尯鏁 hashCtrl.num_partitions = NUM_STARTBLOCK_PARTITIONS; int flags = (HASH_FUNCTION | HASH_COMPARE | HASH_ELEM | HASH_SHRCTX | HASH_PARTITION); + // 鍒涘缓鍏ㄥ眬缁熻淇℃伅鍝堝笇琛 g_instance.stat_cxt.tableStat->blocks_map = hash_create("Candidate Blocks for Pruning Hash", NUM_STARTBLOCK_PARTITIONS, &hashCtrl, flags); } @@ -167,9 +237,17 @@ bool IsGlobalStatsTrackerProcess() return t_thrd.role == GLOBALSTATS_THREAD; } +/* + * 鍔熻兘锛氬叏灞缁熻淇℃伅杩借釜鍣ㄧ殑涓昏鍏ュ彛鐐癸紝杩涜涓绯诲垪鐨勫垵濮嬪寲鎿嶄綔锛 + * 璁剧疆淇″彿澶勭悊鍑芥暟锛屽鐞嗗紓甯告儏鍐碉紝浠ュ強鍛ㄦ湡鎬у湴鏀堕泦鍏ㄥ眬缁熻淇℃伅銆 + * + * 鍙傛暟: 鏃 + * + * 杩斿洖鍊: 鏃 + */ NON_EXEC_STATIC void GlobalStatsTrackerMain() { - sigjmp_buf localSigjmpBuf; + sigjmp_buf localSigjmpBuf; // 鐢ㄤ簬淇濆瓨寮傚父璺宠浆鐨勪笂涓嬫枃淇℃伅 /* we are a postmaster subprocess now */ IsUnderPostmaster = true; @@ -181,29 +259,31 @@ NON_EXEC_STATIC void GlobalStatsTrackerMain() t_thrd.proc_cxt.MyProgName = "StatsTracker"; - Assert(t_thrd.proc->pid == t_thrd.proc_cxt.MyProcPid); - init_ps_display("global stats process", "", "", ""); + Assert(t_thrd.proc->pid == t_thrd.proc_cxt.MyProcPid); // 鏂█褰撳墠杩涚▼鐨 PID 涓 t_thrd 涓褰曠殑涓鑷 + init_ps_display("global stats process", "", "", ""); // 鍒濆鍖栬繘绋嬬姸鎬佺殑鏄剧ず + // 杈撳嚭鏃ュ織锛岃〃绀哄叏灞缁熻淇℃伅鏀堕泦鍣ㄥ凡鍚姩 ereport(LOG, (errmsg("global stats collector started"))); - SetProcessingMode(InitProcessing); + SetProcessingMode(InitProcessing); // 璁剧疆褰撳墠杩涚▼鐨勫鐞嗘ā寮忎负鍒濆鍖栨ā寮忥紝鐢ㄤ簬鎵ц涓浜涘垵濮嬪寲鎿嶄綔 /* * Set up signal handlers. We operate on databases much like a regular * backend, so we use the same signal handling. See equivalent code in * tcop/postgres.c. */ - gspqsignal(SIGHUP, GlobalstatsSighupHandler); - gspqsignal(SIGINT, StatementCancelHandler); - gspqsignal(SIGTERM, GlobalstatsSigtermHandler); + // 璁剧疆淇″彿澶勭悊绋嬪簭 + gspqsignal(SIGHUP, GlobalstatsSighupHandler); // 鐢ㄤ簬閲嶆柊璇诲彇閰嶇疆鏂囦欢 + gspqsignal(SIGINT, StatementCancelHandler); // 鐢ㄤ簬鍙栨秷姝e湪鎵ц鐨勮鍙 + gspqsignal(SIGTERM, GlobalstatsSigtermHandler); // 鐢ㄤ簬缁堟杩涚▼ - gspqsignal(SIGQUIT, quickdie); - gspqsignal(SIGALRM, handle_sig_alarm); + gspqsignal(SIGQUIT, quickdie); // 鐢ㄤ簬蹇熺粓姝㈣繘绋 + gspqsignal(SIGALRM, handle_sig_alarm); // 鐢ㄤ簬澶勭悊瀹氭椂鍣ㄤ俊鍙 - gspqsignal(SIGPIPE, SIG_IGN); - gspqsignal(SIGUSR1, procsignal_sigusr1_handler); - gspqsignal(SIGUSR2, GlobalstatsSigusr2Handler); - gspqsignal(SIGFPE, FloatExceptionHandler); - gspqsignal(SIGCHLD, SIG_DFL); + gspqsignal(SIGPIPE, SIG_IGN); // 鐢ㄤ簬閬垮厤杩涚▼鍦ㄥ啓鍏ュ凡鍏抽棴鐨勭閬撴椂缁堟 + gspqsignal(SIGUSR1, procsignal_sigusr1_handler); // 鐢ㄤ簬鐢ㄦ埛鑷畾涔夌殑淇″彿澶勭悊 + gspqsignal(SIGUSR2, GlobalstatsSigusr2Handler); // 鐢ㄤ簬鎸囩ず涓涓伐浣滆繘绋嬫鍦ㄨ繍琛屻佸垰鍒氬畬鎴愭垨鑰呭湪 fork 澶辫触 + gspqsignal(SIGFPE, FloatExceptionHandler); // 鐢ㄤ簬澶勭悊娴偣寮傚父 + gspqsignal(SIGCHLD, SIG_DFL); // 鐢ㄤ簬澶勭悊瀛愯繘绋嬬殑鐘舵佸彉鍖 /* Early initialization */ BaseInit(); @@ -215,74 +295,75 @@ NON_EXEC_STATIC void GlobalStatsTrackerMain() * had to do some stuff with LWLocks). */ #ifndef EXEC_BACKEND - InitProcess(); + InitProcess(); // 鍒濆鍖栬繘绋嬩笂涓嬫枃 #endif - SetProcessingMode(NormalProcessing); + SetProcessingMode(NormalProcessing); // 璁剧疆褰撳墠杩涚▼鐨勫鐞嗘ā寮忎负姝e父澶勭悊妯″紡锛岀敤浜庢甯哥殑鏁版嵁搴撴搷浣 /* Unblock signals (they were blocked when the postmaster forked us) */ - gs_signal_setmask(&t_thrd.libpq_cxt.UnBlockSig, NULL); - (void)gs_signal_unblock_sigusr2(); + gs_signal_setmask(&t_thrd.libpq_cxt.UnBlockSig, NULL); // 鍙栨秷浜嗗睆钄戒互鍏佽淇″彿琚鐞 + (void)gs_signal_unblock_sigusr2(); // 鍙栨秷瀵 SIGUSR2 淇″彿[鐢ㄤ簬鍚庡彴杩涚▼鐨勭姸鎬佹洿鏂癩鐨勫睆钄 /* * If an exception is encountered, processing resumes here. * * This code is a stripped down version of PostgresMain error recovery. */ - if (sigsetjmp(localSigjmpBuf, 1) != 0) { + // 閿欒鎭㈠澶勭悊 + if (sigsetjmp(localSigjmpBuf, 1) != 0) { // 濡傛灉鍦ㄦ墽琛岃繃绋嬩腑鍑虹幇閿欒锛屽皢浼氳烦杞埌姝ゅ /* since not using PG_TRY, must reset error stack by hand */ t_thrd.log_cxt.error_context_stack = NULL; t_thrd.log_cxt.call_stack = NULL; /* Prevents interrupts while cleaning up */ - HOLD_INTERRUPTS(); + HOLD_INTERRUPTS(); // 绂佹涓柇锛屼互纭繚鍦ㄦ竻鐞嗘搷浣滄湡闂翠笉浼氳涓柇 /* Report the error to the server log */ - EmitErrorReport(); + EmitErrorReport(); // 灏嗛敊璇俊鎭褰曞埌鏈嶅姟鍣ㄦ棩蹇椾腑 /* release resource held by lsc */ - AtEOXact_SysDBCache(false); + AtEOXact_SysDBCache(false); // 閲婃斁绯荤粺鏁版嵁搴撶紦瀛橈紝浠ョ‘淇濇竻鐞嗘搷浣 - FlushErrorState(); + FlushErrorState(); // 鍒锋柊閿欒鐘舵侊紝浠ユ竻闄ら敊璇俊鎭 /* Now we can allow interrupts again */ - RESUME_INTERRUPTS(); + RESUME_INTERRUPTS(); // 鍏佽涓柇锛屼互渚跨户缁甯稿鐞 /* if in shutdown mode, no need for anything further; just go away */ - if (t_thrd.gstat_cxt.got_SIGTERM) + if (t_thrd.gstat_cxt.got_SIGTERM) // 濡傛灉鏀跺埌浜 SIGTERM 淇″彿锛屽氨璺宠浆鍒板叧闂搷浣 goto shutdown; /* * Sleep at least 1 second after any error. We don't want to be * filling the error logs as fast as we can. */ - pg_usleep(1000000L); + pg_usleep(1000000L); // 濡傛灉鍑虹幇閿欒锛岀瓑寰呰嚦灏1绉掑悗鍐嶇户缁紝浠ラ伩鍏嶆棩蹇楀~鍏呰繃蹇 } - while (!t_thrd.gstat_cxt.got_SIGTERM) { + while (!t_thrd.gstat_cxt.got_SIGTERM) { // 寰幆锛岀洿鍒版敹鍒 SIGTERM 淇″彿 /* backup the old one so we can delete it when nobody needs it anymore */ - MemoryContext oldStatLocalContext = u_sess->stat_cxt.pgStatLocalContext; - + MemoryContext oldStatLocalContext = u_sess->stat_cxt.pgStatLocalContext; // 淇濆瓨鏃х殑缁熻淇℃伅鍐呭瓨涓婁笅鏂囷紝浠ヤ究绋嶅悗杩涜娓呯悊鎿嶄綔 + // 鍒涘缓涓涓柊鐨勫唴瀛樹笂涓嬫枃鐢ㄤ簬瀛樺偍鍏ㄥ眬缁熻淇℃伅鐨勫揩鐓ф暟鎹 u_sess->stat_cxt.pgStatLocalContext = AllocSetContextCreate(u_sess->top_mem_cxt, "Global Statistics snapshot", ALLOCSET_SMALL_MINSIZE, ALLOCSET_SMALL_INITSIZE, ALLOCSET_SMALL_MAXSIZE); - pgstat_fetch_global(); + pgstat_fetch_global(); // 浠庡叏灞缁熻淇℃伅涓姄鍙栨暟鎹苟瀛樺偍鍦ㄦ柊鐨勫唴瀛樹笂涓嬫枃涓 /* switch global_stats_map to point to the newly loaded statistics */ - PrepareStatsHashForSwitch(); - g_instance.stat_cxt.tableStat->global_stats_map = u_sess->stat_cxt.pgStatDBHash; - CompleteStatsHashSwitch(); + PrepareStatsHashForSwitch(); // 鎵ц鍑嗗鍒囨崲鎿嶄綔锛岀‘淇濆叏灞缁熻淇℃伅鐨勫畨鍏ㄥ垏鎹 + g_instance.stat_cxt.tableStat->global_stats_map = u_sess->stat_cxt.pgStatDBHash; // 灏嗗叏灞缁熻淇℃伅鐨勬槧灏勬寚閽堝垏鎹㈠埌鏂扮殑鏁版嵁 + CompleteStatsHashSwitch(); // 瀹屾垚鍒囨崲鎿嶄綔锛岀‘淇濇柊鐨勬暟鎹粨鏋勫凡鐢熸晥 /* Now destroy the old one */ - if (oldStatLocalContext) { - MemoryContextDelete(oldStatLocalContext); + if (oldStatLocalContext) { // 妫鏌ユ棫鐨勭粺璁′俊鎭唴瀛樹笂涓嬫枃鏄惁瀛樺湪 + MemoryContextDelete(oldStatLocalContext); // 瀛樺湪鍒欓噴鏀 } - u_sess->stat_cxt.pgStatDBHash = NULL; + u_sess->stat_cxt.pgStatDBHash = NULL; // 璁句负NULL锛岀‘淇濅笉鍐嶅紩鐢ㄦ棫鐨勬暟鎹 - pg_usleep(u_sess->attr.attr_storage.ustats_tracker_naptime * 1000000L); + pg_usleep(u_sess->attr.attr_storage.ustats_tracker_naptime * 1000000L); // 浣胯繘绋嬩紤鐪狅紝绛夊緟涓嬩竴娆¤幏鍙栧叏灞缁熻淇℃伅鐨勬椂闂 } shutdown: @@ -290,11 +371,11 @@ shutdown: * Before the thread exits, set global_stats_map to NULL to prevent core dump when the * backend thread accesses the released memory during the prune operation. */ - PrepareStatsHashForSwitch(); - g_instance.stat_cxt.tableStat->global_stats_map = NULL; - CompleteStatsHashSwitch(); - ereport(LOG, (errmsg("global stats shutting down"))); - proc_exit(0); + PrepareStatsHashForSwitch(); // 鍑嗗鍒囨崲鎿嶄綔锛岀‘淇濆湪鍏抽棴涔嬪墠瀵瑰叏灞缁熻淇℃伅杩涜鏈鍚庣殑澶勭悊 + g_instance.stat_cxt.tableStat->global_stats_map = NULL; // 纭繚鍦ㄥ叧闂椂涓嶅啀璁块棶閲婃斁鐨勫唴瀛 + CompleteStatsHashSwitch(); // 瀹屾垚鍒囨崲鎿嶄綔锛岀‘淇濇柊鐨勭姸鎬佸凡鐢熸晥 + ereport(LOG, (errmsg("global stats shutting down"))); // 鐢熸垚鏃ュ織锛岃〃绀哄叏灞缁熻淇℃伅杩借釜鍣ㄦ鍦ㄥ叧闂 + proc_exit(0); // 姝e父閫鍑哄綋鍓嶈繘绋 } @@ -303,24 +384,41 @@ shutdown: * relid is the partition id for a Partitioned table, otherwise it's the Relation id. * parentid is the actual Relation id for a Partitioned table, otherwise it's InvalidOid. */ +/* + *鍔熻兘锛氳幏鍙栬〃鐨勫叏灞缁熻淇℃伅 + * + * 鍙傛暟锛 + * Oid dbid锛氭暟鎹簱鐨勫敮涓鏍囪瘑绗 + * Oid relid锛氳〃鐨勫敮涓鏍囪瘑绗 + * Oid parentid锛氳〃鐨勭埗琛ㄧ殑鍞竴鏍囪瘑绗 + * PgStat_StatTabEntry *tableentry锛氫簬瀛樺偍鑾峰彇鍒扮殑缁熻淇℃伅 + * + * 杩斿洖鍊硷細 + * bool绫诲瀷 濡傛灉鎴愬姛鑾峰彇浜嗚〃鐨勫叏灞缁熻淇℃伅锛屽垯杩斿洖 true锛 + * 濡傛灉鏃犳硶鑾峰彇锛屽垯杩斿洖 false + * + */ bool GetTableGstats(Oid dbid, Oid relid, Oid parentid, PgStat_StatTabEntry *tableentry) { /* return if stats is not ready */ + // 妫鏌ュ叏灞缁熻淇℃伅鐨勬槧灏勬槸鍚︿负 NULL锛屼互鍙婃槸鍚﹀浜 "quiesce" 鐘舵併傚鏋滄槸锛岃鏄庣粺璁′俊鎭皻鏈噯澶囧ソ锛岃繑鍥 false if (g_instance.stat_cxt.tableStat->global_stats_map == NULL || pg_atomic_read_u64(&g_instance.stat_cxt.tableStat->quiesce) == 1) { return false; } - uint64 readers PG_USED_FOR_ASSERTS_ONLY = pg_atomic_add_fetch_u64(&g_instance.stat_cxt.tableStat->readers, 1); - Assert(readers < (uint64) GLOBAL_ALL_PROCS); + uint64 readers PG_USED_FOR_ASSERTS_ONLY = pg_atomic_add_fetch_u64(&g_instance.stat_cxt.tableStat->readers, 1); // 澧炲姞鍏ㄥ眬缁熻淇℃伅璇诲彇鑰呯殑璁℃暟 + Assert(readers < (uint64) GLOBAL_ALL_PROCS); // 鏂█妫鏌 readers 鏄惁灏忎簬 GLOBAL_ALL_PROCS锛岀敤浜庨檺鍒跺苟鍙戣闂叏灞缁熻淇℃伅鐨勮繘绋嬫暟閲 /* recheck in case quiesce is updated between first check and increment readers */ + // 鍐嶆妫鏌 "quiesce" 鐘舵侊紝浠ョ‘淇濆湪澧炲姞璇诲彇鑰呰鏁版湡闂存湭鏇存敼鐘舵併傚鏋滅姸鎬佸凡鏇存敼锛屽垯鍑忓皯璇诲彇鑰呰鏁板苟杩斿洖 false if (pg_atomic_read_u64(&g_instance.stat_cxt.tableStat->quiesce) == 1) { pg_atomic_sub_fetch_u64(&g_instance.stat_cxt.tableStat->readers, 1); return false; } - Assert(g_instance.stat_cxt.tableStat->global_stats_map != NULL); + Assert(g_instance.stat_cxt.tableStat->global_stats_map != NULL); // 纭繚鍏ㄥ眬缁熻淇℃伅鐨勬槧灏勪笉涓 NULL + // 瀹氫箟鎸囧悜鏁版嵁搴撳拰琛ㄧ粺璁′俊鎭潯鐩殑鎸囬拡 PgStat_StatDBEntry *dbentry = NULL; PgStat_StatTabEntry *tabentry = NULL; errno_t rc = 0; @@ -329,87 +427,129 @@ bool GetTableGstats(Oid dbid, Oid relid, Oid parentid, PgStat_StatTabEntry *tabl PgStat_StatTabKey tabkey; tabkey.statFlag = parentid; tabkey.tableid = relid; - + // 閫氳繃鏁版嵁搴撴爣璇嗕粠鍏ㄥ眬缁熻淇℃伅鏄犲皠涓煡鎵炬暟鎹簱缁熻淇℃伅鏉$洰銆傚鏋滄病鏈夋壘鍒帮紝dbentry 灏嗕负 NULL dbentry = (PgStat_StatDBEntry*)hash_search(g_instance.stat_cxt.tableStat->global_stats_map, (void*)&dbid, HASH_FIND, NULL); if (dbentry == NULL) { goto done; } - + // 閫氳繃鏋勫缓鐨勯敭浠庢暟鎹簱缁熻淇℃伅涓煡鎵捐〃鐨勭粺璁′俊鎭潯鐩傚鏋滄病鏈夋壘鍒帮紝tabentry 灏嗕负 NULL tabentry = (PgStat_StatTabEntry*)hash_search(dbentry->tables, (void*)(&tabkey), HASH_FIND, NULL); if (tabentry == NULL) { goto done; } - + // 濡傛灉鎵惧埌浜嗙粺璁′俊鎭潯鐩紝鍑芥暟灏嗗叾澶嶅埗鍒 tableentry 涓紝浠ヤ究杩斿洖缁欒皟鐢ㄨ rc = memcpy_s(tableentry, sizeof(PgStat_StatTabEntry), tabentry, sizeof(PgStat_StatTabEntry)); securec_check(rc, "", ""); - result = true; + result = true; // 琛ㄧず鎴愬姛鑾峰彇浜嗙粺璁′俊鎭 done: - readers = pg_atomic_sub_fetch_u64(&g_instance.stat_cxt.tableStat->readers, 1); + readers = pg_atomic_sub_fetch_u64(&g_instance.stat_cxt.tableStat->readers, 1); // 鍑忓皯璇诲彇鑰呰鏁 Assert(readers < (uint64) GLOBAL_ALL_PROCS); return result; } +/* + *鍔熻兘锛氳幏鍙栫敤浜庤闂叏灞缁熻淇℃伅涓 "StartBlock" 鍝堝笇琛ㄧ壒瀹氬垎鍖虹殑浜掓枼閿 + * + * 鍙傛暟锛 + * PgStat_StartBlockTableKey *tabkey锛氬敮涓鏍囪瘑瑕佽闂殑鍝堝笇琛ㄥ垎鍖 + * LWLockMode mode锛氱敤浜庢寚瀹氶攣鐨勬ā寮忥紝鍙互鏄叡浜攣锛圫HARED锛夋垨鐙崰閿侊紙EXCLUSIVE锛 + * + * 杩斿洖鍊硷細 + * LWLock * 绫诲瀷锛岋紝鐢ㄤ簬琛ㄧず鑾峰彇鐨勯攣 + * + */ static LWLock *LockStartBlockHashTablePartition(PgStat_StartBlockTableKey *tabkey, LWLockMode mode) { - uint32 hashValue = get_hash_value(g_instance.stat_cxt.tableStat->blocks_map, tabkey); - uint32 partition = hashValue % (NUM_STARTBLOCK_PARTITIONS); - uint32 lockid = (uint32)(FirstStartBlockMappingLock + partition); - LWLock* lock = &t_thrd.shemem_ptr_cxt.mainLWLockArray[lockid].lock; + uint32 hashValue = get_hash_value(g_instance.stat_cxt.tableStat->blocks_map, tabkey); // 璁$畻鍝堝笇鍊 + uint32 partition = hashValue % (NUM_STARTBLOCK_PARTITIONS); // 璁$畻鍒嗗尯鍙凤紝鐢ㄤ簬纭畾鍝堝笇琛ㄤ腑鐨勫摢涓垎鍖哄皢鐢ㄤ簬閿佸畾 + uint32 lockid = (uint32)(FirstStartBlockMappingLock + partition); // 璁$畻閿佹爣璇嗭紝鐢ㄤ簬纭畾瑕侀攣瀹氱殑閿 + LWLock* lock = &t_thrd.shemem_ptr_cxt.mainLWLockArray[lockid].lock; // 浣跨敤鐨勬槸鍝堝笇鍒嗗尯鐨勯攣鏉ユ帶鍒跺鍝堝笇琛ㄥ垎鍖虹殑璁块棶 - LWLockAcquire(lock, mode); + LWLockAcquire(lock, mode); // 鑾峰彇閿 return lock; } +/* + *鍔熻兘锛氱敤浜庡湪鍏ㄥ眬缁熻淇℃伅鐨 "StartBlock" 鍝堝笇琛ㄤ腑鏌ユ壘缁欏畾鐨 PgStat_StartBlockTableKey锛屽苟杩斿洖鐩稿簲鐨 PgStat_StartBlockTableEntry 鏉$洰 + * + * 鍙傛暟锛 + * PgStat_StartBlockTableKey *tabkey锛氱敤浜庡敮涓鏍囪瘑瑕佹煡鎵剧殑鍝堝笇琛ㄦ潯鐩 + * + * 杩斿洖鍊硷細 + * PgStat_StartBlockTableEntry * 绫诲瀷锛岃〃绀烘煡鎵惧埌鐨勫搱甯岃〃鏉$洰銆傚鏋滄病鏈夋壘鍒板尮閰嶇殑鏉$洰锛岃繑鍥炲间负 NULL + */ PgStat_StartBlockTableEntry * StartBlockHashTableLookup(PgStat_StartBlockTableKey *tabkey) { - PgStat_StartBlockTableEntry *result = NULL; - bool found = false; + PgStat_StartBlockTableEntry *result = NULL; // 鐢ㄤ簬瀛樺偍鏌ユ壘缁撴灉 + bool found = false; // 鐢ㄤ簬琛ㄧず鏄惁鎵惧埌浜嗗尮閰嶇殑鏉$洰 - LWLock* lock = LockStartBlockHashTablePartition(tabkey, LW_SHARED); + LWLock* lock = LockStartBlockHashTablePartition(tabkey, LW_SHARED); // 鑾峰彇鍏变韩閿 + // 鏌ユ壘鍖归厤鐨勬潯鐩紝濡傛灉鎵惧埌浜嗭紝灏卞皢瀹冪殑鍦板潃璧嬬粰 result 锛屽苟灏 found 璁剧疆涓 true锛涘惁鍒欙紝result 淇濇寔涓 NULL锛宖ound 淇濇寔涓 false銆 result = (PgStat_StartBlockTableEntry *) hash_search(g_instance.stat_cxt.tableStat->blocks_map, tabkey, HASH_FIND, &found); - LWLockRelease(lock); + LWLockRelease(lock); // 閲婃斁涔嬪墠鑾峰彇鐨勫叡浜攣 return result; } +/* + *鍔熻兘锛氱敤浜庡悜鍏ㄥ眬缁熻淇℃伅鐨 "StartBlock" 鍝堝笇琛ㄤ腑娣诲姞鎴栨洿鏂版潯鐩紝浠ヨ褰曞紑濮嬪潡鐨勭粺璁′俊鎭 + * + * 鍙傛暟锛 + * PgStat_StartBlockTableKey *tabkey锛氱敤浜庡敮涓鏍囪瘑瑕佹坊鍔犳垨鏇存柊鐨勫搱甯岃〃鏉$洰 + * + * 杩斿洖鍊硷細 + * PgStat_StartBlockTableEntry * 绫诲瀷锛岃〃绀哄凡娣诲姞鎴栨洿鏂扮殑鍝堝笇琛ㄦ潯鐩 + * + */ PgStat_StartBlockTableEntry * StartBlockHashTableAdd(PgStat_StartBlockTableKey *tabkey) { - bool found = true; - PgStat_StartBlockTableEntry *result = NULL; - - LWLock* lock = LockStartBlockHashTablePartition(tabkey, LW_EXCLUSIVE); + bool found = true; // 鐢ㄤ簬鎸囩ず鍦ㄦ坊鍔犳潯鐩椂鏄惁鎵惧埌浜嗗凡瀛樺湪鐨勫尮閰嶆潯鐩 + PgStat_StartBlockTableEntry *result = NULL; // 鐢ㄤ簬瀛樺偍娣诲姞鐨勬潯鐩垨鑰呭凡瀛樺湪鐨勫尮閰嶆潯鐩 + LWLock* lock = LockStartBlockHashTablePartition(tabkey, LW_EXCLUSIVE); // 鑾峰彇鐙崰閿 + // 鏌ユ壘鍖归厤鐨勬潯鐩紝濡傛灉鎵惧埌浜嗭紝灏卞皢瀹冪殑鍦板潃璧嬬粰 result 锛屽苟灏 found 璁剧疆涓 true锛涘惁鍒欙紝result 淇濇寔涓 NULL锛宖ound 淇濇寔涓 false銆 result = (PgStat_StartBlockTableEntry *)hash_search(g_instance.stat_cxt.tableStat->blocks_map, tabkey, HASH_ENTER, &found); - if (!found) { + if (!found) { // 濡傛灉鏈夋壘鍒板尮閰嶇殑鏉$洰 + // 鐢ㄤ簬鍒濆鍖 result 鏉$洰涓殑 starting_blocks 鏁扮粍銆傚畠灏嗘暟缁勪腑鐨勫厓绱犺缃负浠 0 鍒 START_BLOCK_ARRAY_SIZE - 1 鐨勮繛缁暣鏁板 for (int i = 0; i < START_BLOCK_ARRAY_SIZE; i++) { result->starting_blocks[i] = i; } } - LWLockRelease(lock); + LWLockRelease(lock); // 閲婃斁鑾峰彇鐨勭嫭鍗犻攣 return result; } +/* + *鍔熻兘锛氱敤浜庤幏鍙 "StartBlock" 鍝堝笇琛ㄤ腑鐨勬潯鐩傚鏋滃搱甯岃〃涓笉瀛樺湪鍖归厤鐨勬潯鐩紝鍒欎細娣诲姞涓涓柊鐨勬潯鐩苟杩斿洖 + * + * 鍙傛暟锛 + * PgStat_StartBlockTableKey *tabkey锛氱敤浜庡敮涓鏍囪瘑瑕佽幏鍙栨垨娣诲姞鐨勫搱甯岃〃鏉$洰 + * + * 杩斿洖鍊硷細 + * PgStat_StartBlockTableEntry * 绫诲瀷锛岃〃绀哄凡鑾峰彇鎴栨坊鍔犵殑鍝堝笇琛ㄦ潯鐩 + * + */ PgStat_StartBlockTableEntry * GetStartBlockHashEntry(PgStat_StartBlockTableKey *tabkey) { - PgStat_StartBlockTableEntry *result = NULL; - result = StartBlockHashTableLookup(tabkey); + PgStat_StartBlockTableEntry *result = NULL; // 鐢ㄤ簬瀛樺偍鑾峰彇鐨勬潯鐩 + result = StartBlockHashTableLookup(tabkey); // 鐢ㄤ簬鏌ユ壘鍝堝笇琛ㄤ腑鏄惁瀛樺湪涓庣粰瀹氶敭鍖归厤鐨勬潯鐩 /* not found, add it */ - if (result == NULL) { - result = StartBlockHashTableAdd(tabkey); + if (result == NULL) { // 濡傛灉娌℃湁鎵惧埌鍖归厤鐨勬潯鐩 + result = StartBlockHashTableAdd(tabkey); // 娣诲姞鏂扮殑鏉$洰 } - Assert(result); + Assert(result); // 纭繚 result 鍙橀噺涓嶄负 NULL return result; } diff --git a/src/gausskernel/process/postmaster/lwlockmonitor.cpp b/src/gausskernel/process/postmaster/lwlockmonitor.cpp index a7a7005bc..ea7c74a21 100644 --- a/src/gausskernel/process/postmaster/lwlockmonitor.cpp +++ b/src/gausskernel/process/postmaster/lwlockmonitor.cpp @@ -37,44 +37,45 @@ #include "utils/memutils.h" #include "utils/timestamp.h" -#define DEFAULT_HOLDERS_NUM 8 +#define DEFAULT_HOLDERS_NUM 8 // 瀹氫箟榛樿鐨勬寔鏈夎呮暟鐩 +// 鐢ㄤ簬琛ㄧず閿佺殑鏉$洰 typedef struct { - LWLockAddr lock_addr; // Use LWLockAddr instead of LWLock* to avoid misuse during key hash - int holders_curnum; - int holders_maxnum; - int waiters_curnum; - int waiters_maxnum; - holding_lockmode* holders; - lock_entry_id* waiters; + LWLockAddr lock_addr; // 琛ㄧず閿佺殑鍦板潃 // Use LWLockAddr instead of LWLock* to avoid misuse during key hash + int holders_curnum; // 琛ㄧず褰撳墠鎸佹湁閿佺殑绾跨▼鏁 + int holders_maxnum; // 琛ㄧず鏈澶у厑璁哥殑鎸佹湁閿佺殑绾跨▼鏁 + int waiters_curnum; // 琛ㄧず褰撳墠绛夊緟閿佺殑绾跨▼鏁 + int waiters_maxnum; // 琛ㄧず鏈澶у厑璁哥殑绛夊緟閿佺殑绾跨▼鏁 + holding_lockmode* holders; // 鎸囧悜褰撳墠鎸佹湁閿佺殑绾跨▼鐨勬暟缁 + lock_entry_id* waiters; // 鎸囧悜褰撳墠绛夊緟閿佺殑绾跨▼鐨勬暟缁 } lock_entry; - +// 鐢ㄤ簬琛ㄧず绾跨▼鐨勬潯鐩 typedef struct { - lock_entry_id be_tid; - int be_idx; - LWLockAddr want_lwlock; + lock_entry_id be_tid; // 琛ㄧず绾跨▼鐨処D + int be_idx; // 琛ㄧず绾跨▼鐨勭储寮 + LWLockAddr want_lwlock; // 琛ㄧず绾跨▼鎯宠鑾峰彇鐨刲wlock } thread_entry; - +// 鐢ㄤ簬琛ㄧずlwlock姝婚攣鐨勪俊鎭 typedef struct { - LWLock *lock; - lock_entry_id waiter; - lock_entry_id blocker; - int waiter_index; + LWLock *lock; // 鎸囧悜鐩稿叧lwlock鐨勬寚閽 + lock_entry_id waiter; // 琛ㄧず鍦ㄧ瓑寰呴攣鐨勭嚎绋嬬殑ID + lock_entry_id blocker; // 琛ㄧず鍦ㄩ樆姝㈠叾浠栫嚎绋嬭幏鍙栭攣鐨勭嚎绋嬬殑ID + int waiter_index; // 琛ㄧず鍦ㄧ瓑寰呯嚎绋嬫暟缁勪腑鐨勭储寮 /* whether blocker is holding in X mode */ - LWLockMode block_xmode; + LWLockMode block_xmode; // 琛ㄧず闃绘绾跨▼鏄惁浠妯″紡鎸佹湁閿 } lw_deadlock_info; - +// 鐢ㄤ簬琛ㄧず宸茶闂殑绾跨▼淇℃伅 typedef struct { - lock_entry_id* entry_ids; - int cur_num; - int max_num; + lock_entry_id* entry_ids; // 鎸囧悜宸茶闂嚎绋嬬殑ID鏁扮粍 + int cur_num; // 琛ㄧず褰撳墠宸茶闂嚎绋嬬殑鏁伴噺 + int max_num; // 琛ㄧず鏈澶у厑璁哥殑宸茶闂嚎绋嬫暟閲 } lwm_visited_thread; - +// 鐢ㄤ簬琛ㄧずlwlock姝婚攣淇℃伅 typedef struct { - lw_deadlock_info* info; - int max_num; - int start; /* range [start, end) */ - int end; + lw_deadlock_info* info; // 鎸囧悜姝婚攣淇℃伅鐨勬寚閽堟暟缁 + int max_num; // 琛ㄧず鏈澶у厑璁哥殑姝婚攣淇℃伅鏁伴噺 + int start; /* range [start, end) */ // 琛ㄧず鑼冨洿鐨勫紑濮嬩綅缃紙鍖呭惈锛 + int end; // 琛ㄧず鑼冨洿鐨勭粨鏉熶綅缃紙涓嶅寘鍚級 } lwm_deadlock; /* Signal handlers */ @@ -90,8 +91,22 @@ static void ut_test_find_deadlock_cycle(void); * 2) unchanged light-weight change-count, * 3) this thread is valid and active. */ + +/* + * 鍔熻兘锛氭鏌ユ槸鍚︽湁绾跨▼鍙兘琚叾浠栫嚎绋嬫垨鑷韩闃诲 + * + * 鍙傛暟锛 + * ver1銆乿er2锛氱敤浜庢瘮杈冪嚎绋嬬殑鐘舵 + * + * 杩斿洖鍊硷細 + * bool绫诲瀷锛岃〃绀烘槸鍚﹀彲鑳借闃诲 + */ static inline bool maybe_this_thread_blocked(lwm_light_detect* ver1, lwm_light_detect* ver2) { + // 妫鏌ヤ袱涓増鏈殑绾跨▼ID鏄惁鐩稿悓 + // 妫鏌ヤ袱涓増鏈殑浼氳瘽ID鏄惁鐩稿悓 + // 妫鏌ヤ袱涓増鏈殑杞婚噺绾ч攣璁℃暟鏄惁鐩稿悓 + // 濡傛灉浠ヤ笂鏉′欢閮芥弧瓒筹紝鍒欒繑鍥 true锛岃〃绀哄彲鑳借闃诲 return (0 != ver2->entry_id.thread_id && ver2->entry_id.thread_id == ver1->entry_id.thread_id && ver2->entry_id.st_sessionid == ver1->entry_id.st_sessionid && ver2->lw_count == ver1->lw_count); } @@ -100,46 +115,84 @@ static inline bool maybe_this_thread_blocked(lwm_light_detect* ver1, lwm_light_d * compare two light detect data and check whether any thread may * be blocked by others or itself. may be deadlock happend ? */ + +/* + * 鍔熻兘锛氭瘮杈冧袱涓交閲忕骇妫娴嬫暟鎹殑鐗堟湰锛屼互纭畾鏄惁鏈夌嚎绋嬪彲鑳借鍏朵粬绾跨▼鎴栬嚜韬樆濉 + * + * 鍙傛暟锛 + * olds銆乶ews锛氭棫鐗堟湰鍜屾柊鐗堟湰鐨勮交閲忕骇妫娴嬫暟鎹 + * + * 杩斿洖鍊硷細 + * bool绫诲瀷锛岃〃绀烘槸鍚︽壘鍒颁簡鍙兘琚樆濉炵殑绾跨▼ + */ bool lwm_compare_light_detect(lwm_light_detect* olds, lwm_light_detect* news) { const int n = BackendStatusArray_size; bool found = false; - for (int i = 0; i < n; ++i) { + for (int i = 0; i < n; ++i) { // 閬嶅巻鏁扮粍鍏冪礌 + // 妫鏌ユ槸鍚﹀彲鑳借闃诲 if (maybe_this_thread_blocked(olds++, news++)) { + // 濡傛灉鎵惧埌涓涓彲鑳借闃诲鐨勭嚎绋 + // 灏 found 鏍囧織璁剧疆涓 true 骞惰烦鍑哄惊鐜 found = true; break; } } - return found; + return found; // 琛ㄧず鏄惁鎵惧埌浜嗗彲鑳借闃诲鐨勭嚎绋 } /* find all the candidates, remember their positions and number */ + +/* + * 鍔熻兘锛氭煡鎵炬墍鏈夊彲鑳借闃诲鐨勫欓夌嚎绋嬶紝骞惰浣忓畠浠殑浣嶇疆鍜屾暟閲 + * + * 鍙傛暟锛 + * olds銆乶ews锛氭棫鐗堟湰鍜屾柊鐗堟湰鐨勮交閲忕骇妫娴嬫暟鎹 + * out_num锛氳緭鍑哄欓夌嚎绋嬬殑鏁伴噺 + * + * 杩斿洖鍊硷細 + * 杩斿洖涓涓暣鏁版暟缁勶紝琛ㄧず鍊欓夌嚎绋嬬殑浣嶇疆 + */ int* lwm_find_candidates(lwm_light_detect* olds, lwm_light_detect* news, int* out_num) { const int n = BackendStatusArray_size; int tmp_num = 0; - int* candidates_pos = (int*)palloc(sizeof(int) * n); + int* candidates_pos = (int*)palloc(sizeof(int) * n); // 鐢ㄤ簬瀛樺偍鍊欓夌嚎绋嬬殑浣嶇疆 /* the first assignment */ *out_num = 0; - for (int i = 0; i < n; ++i) { + for (int i = 0; i < n; ++i) { // 閬嶅巻鏁扮粍鍏冪礌 + // 妫鏌ユ槸鍚﹀彲鑳借闃诲 if (maybe_this_thread_blocked(olds++, news++)) { + // 濡傛灉鎵惧埌涓涓彲鑳借闃诲鐨勭嚎绋嬶紝灏嗗叾浣嶇疆娣诲姞鍒 candidates_pos 鏁扮粍涓 /* remember candidates of lwlock deadlock */ candidates_pos[tmp_num++] = i; } } /* remember the number of candidates */ - *out_num = tmp_num; + *out_num = tmp_num; // 璧嬪硷紝琛ㄧず鍊欓夌嚎绋嬬殑鏁伴噺 return candidates_pos; } /* init entry if it's the first insert */ + +/* + * 鍔熻兘锛氬鏋滄槸绗竴娆℃彃鍏ヨ鏉$洰鍒欏垵濮嬪寲閿佹潯鐩 + * + * 鍙傛暟锛 + * entry锛氭寚鍚 lock_entry 缁撴瀯浣撶殑鎸囬拡锛岃〃绀鸿鍒濆鍖栫殑閿佹潯鐩 + * entry_key锛氭寚鍚 LWLockAddr 缁撴瀯浣撶殑鎸囬拡锛岃〃绀哄叧鑱旂殑閿佸湴鍧 + * + * 杩斿洖鍊硷細鏃 + */ static inline void init_entry_in_the_first_insert(lock_entry* entry, LWLockAddr *entry_key) { - entry->lock_addr.lock = entry_key->lock; + entry->lock_addr.lock = entry_key->lock; // 灏嗛攣鏉$洰鐨勯攣鍦板潃璁剧疆涓轰紶鍏ョ殑閿佸湴鍧 + // 鍒嗛厤鍐呭瓨鏉ュ瓨鍌ㄦ寔鏈夎呭拰绛夊緟鑰呯嚎绋嬬殑淇℃伅 entry->holders = (holding_lockmode*)palloc(sizeof(holding_lockmode) * DEFAULT_HOLDERS_NUM); entry->waiters = (lock_entry_id*)palloc(sizeof(lock_entry_id) * DEFAULT_HOLDERS_NUM); + // 琛ㄧず褰撳墠娌℃湁鎸佹湁鑰呭拰绛夊緟鑰 entry->holders_curnum = entry->waiters_curnum = 0; entry->holders_maxnum = entry->waiters_maxnum = DEFAULT_HOLDERS_NUM; } @@ -148,24 +201,43 @@ static inline void init_entry_in_the_first_insert(lock_entry* entry, LWLockAddr * remember the holders of this lock. * now the holder holds the lockids whose number is n. */ + +/* + * 鍔熻兘锛氬皢鎸佹湁閿佺殑绾跨▼鏄犲皠鍒扮浉搴旂殑閿佹潯鐩 + * + * 鍙傛暟锛 + * map锛氬搱甯岃〃 + * held_lwlocks锛氳〃绀烘寔鏈夌殑閿佷俊鎭 + * n锛氳〃绀烘寔鏈夌殑閿佺殑鏁伴噺 + * holder锛氳〃绀烘寔鏈夐攣鐨勭嚎绋嬬殑ID + * + * 杩斿洖鍊硷細鏃 + */ static inline void map_from_lock_to_holder(HTAB* map, lwlock_id_mode* held_lwlocks, int n, lock_entry_id* holder) { lock_entry* entry = NULL; lwlock_id_mode* holding_lwlock = NULL; int i = 0; - bool found = false; - + bool found = false; // 鐢ㄤ簬鎸囩ず鏄惁鍦ㄥ搱甯岃〃涓壘鍒扮浉搴旂殑閿佹潯鐩 + // 寰幆閬嶅巻鎸佹湁鐨勯攣淇℃伅 for (i = 0, holding_lwlock = held_lwlocks; i < n; ++i, ++holding_lwlock) { + // 鍦ㄥ搱甯岃〃涓煡鎵句笌閿佸湴鍧鐩稿叧鐨勯攣鏉$洰 entry = (lock_entry*)hash_search(map, &(holding_lwlock->lock_addr), HASH_ENTER, &found); + // 妫鏌ユ槸鍚︽壘鍒颁簡閿佹潯鐩 if (!found) { + // 濡傛灉娌℃湁鎵惧埌锛岃〃绀鸿繖鏄涓娆℃彃鍏ヨ鏉$洰锛屽垵濮嬪寲閿佹潯鐩 init_entry_in_the_first_insert(entry, &(holding_lwlock->lock_addr)); } + // 妫鏌ュ綋鍓嶆寔鏈夎呯嚎绋嬬殑鏁伴噺鏄惁瓒呰繃浜嗘渶澶у厑璁稿 if (unlikely(entry->holders_curnum >= entry->holders_maxnum)) { - int new_size = entry->holders_maxnum * 2; + // 濡傛灉瓒呰繃锛岃〃绀洪渶瑕佹墿灞曟寔鏈夎呮暟缁 + int new_size = entry->holders_maxnum * 2; // 璁$畻鏂扮殑鎸佹湁鑰呮暟缁勭殑澶у皬 + // 閲嶆柊鍒嗛厤鎸佹湁鑰呮暟缁勭殑鍐呭瓨 entry->holders = (holding_lockmode*)repalloc(entry->holders, sizeof(holding_lockmode) * new_size); - entry->holders_maxnum = new_size; + entry->holders_maxnum = new_size; // 鏇存柊鎸佹湁鑰呮暟缁勭殑鏈澶у閲 } /* remember the holders of this lock */ + // 灏嗘寔鏈夐攣鐨勭嚎绋嬬殑淇℃伅娣诲姞鍒伴攣鏉$洰鐨勬寔鏈夎呮暟缁勪腑 entry->holders[entry->holders_curnum].holder_tid.thread_id = holder->thread_id; entry->holders[entry->holders_curnum].holder_tid.st_sessionid = holder->st_sessionid; entry->holders[entry->holders_curnum].lock_sx = holding_lwlock->lock_sx; @@ -178,30 +250,46 @@ static inline void map_from_lock_to_holder(HTAB* map, lwlock_id_mode* held_lwloc * 1) lwlock id and its waiters; * 2) lwlock id and its holders; */ + +/* + * 鍔熻兘锛氭瀯寤轰袱涓槧灏勶紝涓涓粠閿両D鍒扮瓑寰呰呯殑鏄犲皠锛屽彟涓涓粠閿両D鍒版寔鏈夎呯殑鏄犲皠 + * + * 鍙傛暟锛 + * map锛氬搱甯岃〃锛岀敤浜庡皢閿佸湴鍧鏄犲皠鍒伴攣鏉$洰銆 + * candidates锛氫竴涓 lwm_lwlocks 缁撴瀯浣撶殑鎸囬拡鏁扮粍锛岃〃绀哄欓夌殑閿佷俊鎭 + * num_candidates锛氬欓夌殑閿佺殑鏁伴噺 + * + * 杩斿洖鍊硷細鏃 + */ static void build_holder_and_waiter_map(HTAB* map, lwm_lwlocks* candidates, int num_candidates) { lwm_lwlocks* lock = NULL; lock_entry* entry = NULL; bool found = false; - + // 閬嶅巻鍊欓夐攣 lock = candidates; for (int i = 0; i < num_candidates; ++i, ++lock) { if (0 == lock->be_tid.thread_id) { /* skip this lock if thread id is not valid */ - continue; + continue; // 濡傛灉绾跨▼ID鏃犳晥锛屽垯璺宠繃璇ラ攣 } /* build map from lock address to waiters */ + // 鏋勫缓浠庨攣鍦板潃鍒扮瓑寰呰呯殑鏄犲皠 entry = (lock_entry*)hash_search(map, &(lock->want_lwlock), HASH_ENTER, &found); if (!found) { + // 濡傛灉娌℃湁鎵惧埌锛岃〃绀鸿繖鏄涓娆℃彃鍏ヨ鏉$洰锛屽垵濮嬪寲閿佹潯鐩 init_entry_in_the_first_insert(entry, &(lock->want_lwlock)); } + // 妫鏌ュ綋鍓嶇瓑寰呰呯嚎绋嬬殑鏁伴噺鏄惁瓒呰繃浜嗘渶澶у厑璁稿 if (unlikely(entry->waiters_curnum >= entry->waiters_maxnum)) { + // 濡傛灉鏄垯鎵╁睍绛夊緟鑰呮暟缁 int new_size = entry->waiters_maxnum * 2; entry->waiters = (lock_entry_id*)repalloc(entry->waiters, sizeof(lock_entry_id) * new_size); entry->waiters_maxnum = new_size; } /* remember all the waiters (thread id) about this lwlock */ + // 灏嗘墍鏈夌瓑寰呰咃紙绾跨▼ID锛夌殑淇℃伅娣诲姞鍒伴攣鏉$洰鐨勭瓑寰呰呮暟缁勪腑 entry->waiters[entry->waiters_curnum].thread_id = lock->be_tid.thread_id; entry->waiters[entry->waiters_curnum].st_sessionid = lock->be_tid.st_sessionid; entry->waiters_curnum++; @@ -212,35 +300,60 @@ static void build_holder_and_waiter_map(HTAB* map, lwm_lwlocks* candidates, int } /* destroy lock hash table */ + +/* + * 鍔熻兘锛氶攢姣侀攣鍝堝笇琛紝閲婃斁鍐呭瓨 + * + * 鍙傛暟锛 + * lock_map锛氳閿姣佺殑鍝堝笇琛 + * + * 杩斿洖鍊硷細鏃 + */ static void destroy_lock_hashtbl(HTAB* lock_map) { lock_entry* entry = NULL; HASH_SEQ_STATUS hseq_stat; - hash_seq_init(&hseq_stat, lock_map); + hash_seq_init(&hseq_stat, lock_map); // 鍒濆鍖栧搱甯岃〃搴忓垪鎵弿鍣 + // 閬嶅巻鍝堝笇琛ㄤ腑鐨勬瘡涓攣鏉$洰 while ((entry = (lock_entry*)hash_seq_search(&hseq_stat)) != NULL) { + // 閲婃斁绛夊緟鑰呭拰鎸佹湁鑰呮暟缁勭殑鍐呭瓨 pfree_ext(entry->waiters); pfree_ext(entry->holders); } + // 閿姣佸搱甯岃〃 hash_destroy(lock_map); } /* build map between thread id and its acquired lwlock */ + +/* + * 鍔熻兘锛氭瀯寤虹嚎绋婭D鍜屽叾宸茶幏鍙栫殑杞婚噺绾ч攣锛坙wlock锛変箣闂寸殑鏄犲皠 + * + * 鍙傛暟锛 + * map锛氱嚎绋婭D鍒伴攣ID鐨勬槧灏勭殑鍝堝笇琛 + * candidates锛氫竴涓 lwm_lwlocks 缁撴瀯浣撶殑鎸囬拡鏁扮粍锛岃〃绀哄欓夌殑閿佷俊鎭 + * num_candidates锛氬欓夌殑閿佺殑鏁伴噺 + * + * 杩斿洖鍊硷細鏃 + */ static void build_map_from_threadid_to_lockid(HTAB* map, lwm_lwlocks* candidates, int num_candidates) { thread_entry* entry = NULL; lwm_lwlocks* lock = NULL; bool found = false; - + // 鍒濆鍖栫嚎绋嬫槧灏勭殑鍝堝笇琛ㄥ簭鍒楁壂鎻忓櫒 lock = candidates; for (int i = 0; i < num_candidates; ++i, ++lock) { if (0 == lock->be_tid.thread_id) { /* skip this lock if its thread id is not valid */ - continue; + continue; // 濡傛灉绾跨▼ID鏃犳晥锛屽垯璺宠繃璇ラ攣 } + // 鍦ㄥ搱甯岃〃涓煡鎵句笌绾跨▼ID鐩稿叧鐨勭嚎绋嬫潯鐩紝濡傛灉鎵句笉鍒帮紝鍒欏垱寤轰竴涓柊鐨 entry = (thread_entry*)hash_search(map, &(lock->be_tid), HASH_ENTER, &found); if (!found) { + // 濡傛灉娌℃湁鎵惧埌锛岃〃绀鸿繖鏄绾跨▼鐨勭涓涓攣锛屽垵濮嬪寲绾跨▼鏉$洰 /* one thread acquires only one lwlock */ entry->want_lwlock = lock->want_lwlock; entry->be_idx = lock->be_idx; @@ -249,6 +362,7 @@ static void build_map_from_threadid_to_lockid(HTAB* map, lwm_lwlocks* candidates * see LWLockQueueSelf(). * one thread cannot once wait more than one lwlock. */ + // 涓娆″彧鑳界瓑寰呬竴涓 lwlock锛屽鏋滄壘鍒颁簡澶氫釜锛屽垯鎶涘嚭鏂█閿欒 Assert(0); } } @@ -263,6 +377,21 @@ static void build_map_from_threadid_to_lockid(HTAB* map, lwm_lwlocks* candidates * deadlock [IN/OUT]: global infor about deadlock cycle * depth [IN]: recure depth */ + +/* + * 鍔熻兘锛氶掑綊鍦版煡鎵炬閿佸惊鐜 + * + * 鍙傛暟锛 + * check_thread: 瑕佹鏌ョ殑绾跨▼ + * lock_map: 閿佷笌鍏剁瓑寰呰呭拰鎸佹湁鑰呬箣闂寸殑鏄犲皠鍏崇郴 + * tid_map: 绾跨▼ID涓庢墍闇lwlock涔嬮棿鐨勬槧灏勫叧绯 + * visited: 鍏充簬宸茶闂嚎绋嬬殑鍏ㄥ眬淇℃伅 + * deadlock : 鍏充簬姝婚攣寰幆鐨勫叏灞淇℃伅 + * depth: 閫掑綊娣卞害 + * + * 杩斿洖鍊硷細 + * bool绫诲瀷锛屽鏋滄壘鍒版閿佸惊鐜紝鍒欒繑鍥 true锛涘惁鍒欒繑鍥 false + */ static bool find_lock_cycle_recurse(thread_entry* check_thread, HTAB* lock_map, HTAB* tid_map, lwm_visited_thread* visited, lwm_deadlock* deadlock, int depth) { @@ -294,7 +423,7 @@ static bool find_lock_cycle_recurse(thread_entry* check_thread, HTAB* lock_map, visited->entry_ids[visited->cur_num].thread_id = check_threadid; visited->entry_ids[visited->cur_num].st_sessionid = check_sessionid; visited->cur_num++; - + // 鍦ㄩ攣鏄犲皠琛ㄤ腑鏌ユ壘涓庤绾跨▼瑕佹眰鐨勯攣鐩稿叧鐨勬潯鐩 entry = (lock_entry*)hash_search(lock_map, &(check_thread->want_lwlock), HASH_FIND, &found); AssertEreport(found && entry != NULL, MOD_ALL, "the wanted lock is not found in cache"); const int holder_num = entry->holders_curnum; @@ -334,6 +463,16 @@ static bool find_lock_cycle_recurse(thread_entry* check_thread, HTAB* lock_map, } /* find the start point for this deadlock loop */ + +/* + * 鍔熻兘锛氭煡鎵炬閿佸惊鐜殑璧风偣 + * + * 鍙傛暟锛 + * deadlock锛氬叧浜庢閿佸惊鐜殑鍏ㄥ眬淇℃伅 + * + * 杩斿洖鍊硷細 + * bool绫诲瀷锛屽鏋滄壘鍒版閿佸惊鐜殑璧风偣锛屽垯杩斿洖 true锛涘惁鍒欒繑鍥 false + */ static bool find_cycle_start_point(lwm_deadlock* deadlock) { lw_deadlock_info* first = deadlock->info; @@ -358,6 +497,20 @@ static bool find_cycle_start_point(lwm_deadlock* deadlock) } /* enter point to find deadlock cycle */ + +/* + * 鍔熻兘锛氭煡鎵炬閿佸惊鐜殑鍏ュ彛鐐 + * + * 鍙傛暟锛 + * lock锛氶攣鐩稿叧鐨勭嚎绋嬫潯鐩 + * lock_map锛氶攣涓庡叾绛夊緟鑰呭拰鎸佹湁鑰呬箣闂寸殑鏄犲皠鍏崇郴銆 + * tid_map锛氱嚎绋婭D涓庢墍闇lwlock涔嬮棿鐨勬槧灏勫叧绯汇 + * visited锛氬叧浜庡凡璁块棶绾跨▼鐨勫叏灞淇℃伅銆 + * deadlock锛氬叧浜庢閿佸惊鐜殑鍏ㄥ眬淇℃伅銆 + * + * 杩斿洖鍊硷細 + * bool绫诲瀷锛屽鏋滄壘鍒版閿佸惊鐜紝鍒欒繑鍥 true锛涘惁鍒欒繑鍥 false + */ static bool find_lock_cycle( lwm_lwlocks* lock, HTAB* lock_map, HTAB* tid_map, lwm_visited_thread* visited, lwm_deadlock* deadlock) { @@ -368,33 +521,51 @@ static bool find_lock_cycle( deadlock->end = 0; bool found = false; + // 鏌ユ壘涓庣粰瀹氶攣鐨勭嚎绋嬬浉鍏崇殑鏉$洰 thread_entry* check_thread = (thread_entry*)hash_search(tid_map, &(lock->be_tid), HASH_FIND, &found); + // 濡傛灉鎵惧埌鐩稿叧鐨勭嚎绋嬫潯鐩 if (found) { + // 鏌ユ壘姝婚攣寰幆 if (find_lock_cycle_recurse(check_thread, lock_map, tid_map, visited, deadlock, 0)) { + // 濡傛灉鎵惧埌姝婚攣寰幆锛屾煡鎵炬閿佸惊鐜殑璧峰鐐 + // 濡傛灉 find_cycle_start_point 杩斿洖 true + // 琛ㄧず鎴愬姛鎵惧埌姝婚攣寰幆鐨勮捣濮嬬偣锛屽嚱鏁拌繑鍥 true return find_cycle_start_point(deadlock); } } - return false; + return false; // 琛ㄧず娌℃湁鎵惧埌姝婚攣寰幆 } /* * Report a detected deadlock, with available details. */ + +/* + * 鍔熻兘锛氭姤鍛婃娴嬪埌鐨勬閿 + * + * 鍙傛暟锛 + * deadlock锛氬叧浜庢閿佸惊鐜殑鍏ㄥ眬淇℃伅 + * + * 杩斿洖鍊硷細鏃 + */ void lwm_deadlock_report(lwm_deadlock* deadlock) { StringInfoData clientbuf; /* errdetail for client */ StringInfoData logbuf; /* errdetail for server log */ int i = 0; - + // 鍒濆鍖 initStringInfo(&clientbuf); initStringInfo(&logbuf); /* Generate the "waits for" lines sent to the client */ + // 寰幆澶勭悊姝婚攣淇℃伅锛岀敓鎴愬彂閫佺粰瀹㈡埛绔殑 "waits for" 琛 for (i = deadlock->start; i < deadlock->end; ++i) { lw_deadlock_info* info = deadlock->info + i; - if (i > 0) { + if (i > 0) { // 妫鏌ュ綋鍓嶅惊鐜槸鍚︿笉鏄涓娆¤凯浠 + // 濡傛灉涓嶆槸绗竴娆¤凯浠o紝鍒欏湪琛屼箣闂存坊鍔犳崲琛岀 appendStringInfoChar(&clientbuf, '\n'); } + // 鍚 clientbuf 娣诲姞鏂囨湰淇℃伅锛屽寘鎷嚎绋嬩俊鎭佷細璇濅俊鎭佺瓑寰呯殑閿佷俊鎭瓑 appendStringInfo(&clientbuf, _("thread %lu , session %lu waits for LWLOCK (%s), but blocked by thread %lu, session id %lu\ lock mode is %d(Exclusive 0, Shared 1, wait 2). lock index is %d"), @@ -413,20 +584,20 @@ void lwm_deadlock_report(lwm_deadlock* deadlock) /* ... and add info about query strings */ for (i = deadlock->start; i < deadlock->end; ++i) { lw_deadlock_info* info = deadlock->info + i; - + // 鍚 logbuf 娣诲姞鏂囨湰淇℃伅锛屽寘鎷嚎绋嬩俊鎭拰褰撳墠娲诲姩鐨勬煡璇俊鎭 appendStringInfoChar(&logbuf, '\n'); appendStringInfo(&logbuf, _("thread %lu: %s"), info->waiter.thread_id, pgstat_get_backend_current_activity(info->waiter.thread_id, false)); } - + // 鐢熸垚涓涓棩蹇楁姤鍛婏紝鎶ュ憡浜嗘娴嬪埌鐨勬閿佹儏鍐 ereport(LOG, (errcode(ERRCODE_T_R_DEADLOCK_DETECTED), errmsg("lwlock deadlock detected"), errdetail_internal("%s", clientbuf.data), errdetail_log("%s", logbuf.data))); - + // 閲婃斁浜嗕箣鍓嶅垎閰嶇殑鍐呭瓨锛屼互闃叉鍐呭瓨娉勬紡 pfree_ext(clientbuf.data); pfree_ext(logbuf.data); } @@ -437,6 +608,17 @@ void lwm_deadlock_report(lwm_deadlock* deadlock) * candidates [IN]: candidate threads who may be in deadlock loop. * num_candidates [IN]: number of candidates */ +/* + * 鍔熻兘锛氭娴嬪拰鎶ュ憡杞婚噺绾ч攣锛坙wlock锛夌殑姝婚攣鎯呭喌 + * + * 鍙傛暟锛 + * deadlock锛氬叧浜庢閿佸惊鐜殑鍏ㄥ眬淇℃伅 + * candidates锛氬欓夌嚎绋嬫暟缁 + * num_candidates锛氬欓夌嚎绋嬬殑鏁伴噺 + * + * 杩斿洖鍊硷細 + * bool绫诲瀷锛岃繑鍥炴槸鍚︽壘鍒版閿 + */ bool lwm_heavy_diagnosis(lwm_deadlock* deadlock, lwm_lwlocks* candidates, int num_candidates) { HASHCTL hctl; @@ -446,20 +628,22 @@ bool lwm_heavy_diagnosis(lwm_deadlock* deadlock, lwm_lwlocks* candidates, int nu hctl.entrysize = sizeof(lock_entry); /* LWLockAddr is not suitable for Oid type, so use tab_hash */ hctl.hash = tag_hash; - + // 鍒涘缓鍝堝笇琛紝鐢ㄤ簬瀛樺偍閿佺殑鎸佹湁鑰呭拰绛夊緟鑰呬俊鎭 HTAB* lock_map = hash_create("LWLOCK holder and waiter", 1024, /* default node number */ &hctl, HASH_ELEM | HASH_FUNCTION); /* build maps about holders and acquirers */ + // 灏嗛攣鐨勬寔鏈夎呭拰绛夊緟鑰呬俊鎭坊鍔犲埌lock_map鍝堝笇琛ㄤ腑 build_holder_and_waiter_map(lock_map, candidates, num_candidates); - + // 娓呴浂hctl缁撴瀯浣 ret = memset_s(&hctl, sizeof(HASHCTL), 0, sizeof(HASHCTL)); securec_check(ret, "\0", "\0"); + // 璁剧疆hctl缁撴瀯浣撶殑瀛楁锛岀敤浜庡垱寤哄彟涓涓搱甯岃〃 hctl.keysize = sizeof(lock_entry_id); hctl.entrysize = sizeof(thread_entry); hctl.hash = tag_hash; - + // 鍒涘缓鍝堝笇琛紝鐢ㄤ簬寤虹珛绾跨▼ID鍜屾墍闇閿佷箣闂寸殑鏄犲皠鍏崇郴 HTAB* thread_map = hash_create("thread and want lock", 1024, /* default node number */ &hctl, @@ -467,11 +651,11 @@ bool lwm_heavy_diagnosis(lwm_deadlock* deadlock, lwm_lwlocks* candidates, int nu /* build maps between thread id and lock to require */ build_map_from_threadid_to_lockid(thread_map, candidates, num_candidates); - lwm_visited_thread visited; + lwm_visited_thread visited; // 鐢ㄤ簬璺熻釜宸茶闂殑绾跨▼ visited.cur_num = 0; visited.max_num = 8; visited.entry_ids = (lock_entry_id*)palloc(sizeof(lock_entry_id) * visited.max_num); - + // 璁剧疆瀛楁锛岀敤浜庡瓨鍌ㄦ閿佽鎯 deadlock->start = -1; deadlock->end = 0; deadlock->max_num = 8; @@ -479,18 +663,23 @@ bool lwm_heavy_diagnosis(lwm_deadlock* deadlock, lwm_lwlocks* candidates, int nu /* check and find deadlock cycle */ bool found = false; + // 寰幆閬嶅巻鎵鏈夊欓夌嚎绋 for (int i = 0; i < num_candidates; ++i) { + // 妫娴嬫槸鍚﹀瓨鍦ㄦ閿 if (find_lock_cycle(candidates + i, lock_map, thread_map, &visited, deadlock)) { /* print deadlock detail message */ + // 濡傛灉鍙戠幇姝婚攣锛屾墦鍗版閿佺殑璇︾粏淇℃伅 lwm_deadlock_report(deadlock); found = true; break; } } - + // 閲婃斁鍒嗛厤鐨勫唴瀛 pfree_ext(visited.entry_ids); + // 閿姣佸搱甯岃〃 destroy_lock_hashtbl(lock_map); lock_map = NULL; + // 閿姣佸搱甯岃〃 hash_destroy(thread_map); thread_map = NULL; return found; @@ -501,39 +690,57 @@ bool lwm_heavy_diagnosis(lwm_deadlock* deadlock, lwm_lwlocks* candidates, int nu * deadlock [IN]: deadlock details * out_idx [OUT]: backend position of this victim */ +/* + * 鍔熻兘锛氫粠涓缁勬閿佷俊鎭腑閫夋嫨涓涓獀ictim锛堢嚎绋嬶級鏉ヨВ闄ゆ閿 + * 浼氶夋嫨鍏锋湁浠ヤ笅鐗瑰緛鐨勭嚎绋嬶細 + * 鍏锋湁鏈鎺ヨ繎鐨勪簨鍔″紑濮嬫椂闂存埑锛坣earest_xact_tm锛 + * 濡傛灉鏈夊涓嚎绋嬪叿鏈夌浉鍚岀殑浜嬪姟寮濮嬫椂闂存埑锛屽皢閫夋嫨娌℃湁鐙崰閿佺瓑寰呯殑绾跨▼ + * + * 鍙傛暟锛 + * deadlock锛氬叧浜庢閿佸惊鐜殑鍏ㄥ眬淇℃伅 + * out_idx锛歷ictim鍦ㄦ閿佷俊鎭暟缁勪腑鐨勪綅缃 + * + * 杩斿洖鍊硷細 + * int绫诲瀷锛屼唬琛ㄩ夋嫨鐨勫彈瀹宠呯嚎绋嬬殑鍚庣浣嶇疆鎴栬呰緟鍔╄繘绋嬬被鍨 + * 濡傛灉杩斿洖鍊煎ぇ浜庣瓑浜 0锛岃〃绀洪夋嫨鐨勫彈瀹宠呮槸涓涓悗绔嚎绋嬶紝骞朵笖杩斿洖鍊兼槸璇ュ悗绔嚎绋嬬殑鍚庣浣嶇疆 + * 濡傛灉杩斿洖鍊煎皬浜 0锛岃〃绀洪夋嫨鐨勫彈瀹宠呮槸涓涓緟鍔╄繘绋嬶紝骞朵笖杩斿洖鍊奸氬父鏄竴涓礋鏁帮紝琛ㄧず杈呭姪杩涚▼鐨勭被鍨 + */ static int choose_one_victim(lwm_deadlock* deadlock, int* out_idx) { + // 鏂█纭繚 deadlock 鐨勫紑濮嬩綅缃湪鏈夋晥鑼冨洿鍐 Assert(deadlock->start >= 0 && deadlock->start < deadlock->end); - TimestampTz nearest_xact_tm = 0; - TimestampTz tmp_xact_tm = 0; - int backend_index = -1; - int auxproc_index = NotAnAuxProcess; + TimestampTz nearest_xact_tm = 0; // 鐢ㄤ簬璁板綍鏈鎺ヨ繎鐨勪簨鍔℃椂闂存埑 + TimestampTz tmp_xact_tm = 0; // 鐢ㄤ簬鏆傚瓨浜嬪姟鏃堕棿鎴 + int backend_index = -1; // 璁板綍琚変腑鐨勫悗绔嚎绋嬬储寮 + int auxproc_index = NotAnAuxProcess; // 璁板綍杈呭姪杩涚▼绾跨▼绱㈠紩 - int i = deadlock->start; - int be_index = deadlock->info[i].waiter_index; + int i = deadlock->start; // 浠 deadlock 寮濮嬩綅缃紑濮 + int be_index = deadlock->info[i].waiter_index; // 鑾峰彇绗竴涓瓑寰呰呯殑绾跨▼绱㈠紩 /* init the victim */ if (be_index < MAX_BACKEND_SLOT) { backend_index = be_index; + // 鑾峰彇璇ョ嚎绋嬬殑浜嬪姟寮濮嬫椂闂存埑 nearest_xact_tm = pgstat_read_xact_start_tm(be_index); } else { - auxproc_index = be_index; + auxproc_index = be_index; // 濡傛灉鏄緟鍔╄繘绋嬬嚎绋嬶紝鍒欒褰曠储寮 } /* init the position of the first victim */ - *out_idx = i; + *out_idx = i; // 鍒濆鍖栫涓涓彈瀹宠呯殑浣嶇疆 /* begin from (deadlock->start + 1) */ for (++i; i < deadlock->end; ++i) { - be_index = deadlock->info[i].waiter_index; + be_index = deadlock->info[i].waiter_index; // 鑾峰彇涓嬩竴涓瓑寰呰呯殑绾跨▼绱㈠紩 if (be_index < MAX_BACKEND_SLOT) { - tmp_xact_tm = pgstat_read_xact_start_tm(be_index); + tmp_xact_tm = pgstat_read_xact_start_tm(be_index); // 鑾峰彇璇ョ嚎绋嬬殑浜嬪姟寮濮嬫椂闂存埑 /* prefer the shortest exclusive lock run time,equal condition used to test case for xact tz is 0 */ if (timestamptz_cmp_internal(tmp_xact_tm, nearest_xact_tm) >= 0 && 0 == deadlock->info[i].block_xmode) { nearest_xact_tm = tmp_xact_tm; backend_index = be_index; - *out_idx = i; + *out_idx = i; // 鏇存柊鍙楀鑰呬綅缃殑杈撳嚭鍙傛暟 #ifdef HAVE_INT64_TIMESTAMP + // 璁板綍鏃ュ織锛岃鏄庨夋嫨浜嗕竴涓彈瀹宠 ereport(LOG, (errmsg("choose_one_victim,lock_mode is %d,tran time is %lu,out index is %d,backend index is %d", deadlock->info[i].block_xmode, @@ -563,6 +770,15 @@ static int choose_one_victim(lwm_deadlock* deadlock, int* out_idx) return ((backend_index >= 0) ? backend_index : ((auxproc_index >= MAX_BACKEND_SLOT) ? auxproc_index : -1)); } +/* + * 鍔熻兘锛氬湪妫娴嬪埌杞婚噺绾ч攣姝婚攣鏃惰嚜鍔ㄥ皾璇曡В闄ゆ閿 + * + * 鍙傛暟锛 + * deadlock锛氬叧浜庢閿佸惊鐜殑鍏ㄥ眬淇℃伅 + * + * 杩斿洖鍊硷細 + * 鏃 + */ void lw_deadlock_auto_healing(lwm_deadlock* deadlock) { /* choose one thread to be victim */ @@ -571,21 +787,32 @@ void lw_deadlock_auto_healing(lwm_deadlock* deadlock) if (backend_victim >= 0) { if (backend_victim >= MAX_BACKEND_SLOT) { + // 濡傛灉鍙楀鑰呮槸杈呭姪绾跨▼锛屽垯瑙﹀彂 PANIC锛屽苟缁堟杩涚▼ ereport(PANIC, (errmsg("process suicides because the victim of lwlock deadlock is an auxiliary thread"))); return; } /* wake up this victim */ lw_deadlock_info* info = deadlock->info + info_idx; + // 鍞ら啋鍙楀鑰呯嚎绋嬶紝浠ヨВ闄ゆ閿 wakeup_victim(info->lock, info->waiter.thread_id); } else { /* LOG, maybe deadlock disappear */ + // 濡傛灉娌℃湁鎵惧埌鍙楀鑰咃紝鍙兘鏄閿佸凡缁忚В闄わ紝璁板綍鏃ュ織淇℃伅 ereport(LOG, (errmsg("victim not found, maybe lwlock deadlock disappear"))); } } +/* + * 鍔熻兘锛氱洃瑙嗛攣绛夊緟鎯呭喌骞舵墽琛岀浉搴旂殑鎿嶄綔 + * + * 鍙傛暟锛氭棤 + * + * 杩斿洖鍊硷細 + * 鏃 + */ NON_EXEC_STATIC void FaultMonitorMain() { - sigjmp_buf localSigjmpBuf; + sigjmp_buf localSigjmpBuf; // 鐢ㄤ簬澶勭悊寮傚父璺宠浆 MemoryContext lwm_context = NULL; lwm_light_detect* prev_snapshot = NULL; @@ -593,12 +820,12 @@ NON_EXEC_STATIC void FaultMonitorMain() long cur_timeout = 0; /* we are a postmaster subprocess now */ - IsUnderPostmaster = true; + IsUnderPostmaster = true; // 琛ㄧず褰撳墠杩涚▼鏄湪 postmaster 杩涚▼涓嬭繍琛岀殑 - t_thrd.proc_cxt.MyProcPid = gs_thread_self(); + t_thrd.proc_cxt.MyProcPid = gs_thread_self(); // 姝g‘鏍囪瘑绾跨▼ ereport(DEBUG5, (errmsg("lwlockmonitor process is started: %lu", t_thrd.proc_cxt.MyProcPid))); - + // 璁剧疆淇″彿澶勭悊绋嬪簭 (void)gspqsignal(SIGHUP, LWLockMonitorSigHupHandler); /* set flag to read config file */ (void)gspqsignal(SIGINT, LWLockMonitorShutdownHandler); /* request shutdown */ (void)gspqsignal(SIGTERM, LWLockMonitorShutdownHandler); /* request shutdown */ @@ -624,48 +851,53 @@ NON_EXEC_STATIC void FaultMonitorMain() * possible memory leaks. Formerly this code just ran in * t_thrd.top_mem_cxt, but resetting that would be a really bad idea. */ + // 鍒涘缓涓涓唴瀛樹笂涓嬫枃 lwm_context = AllocSetContextCreate(t_thrd.top_mem_cxt, "LWLock Monitor", ALLOCSET_DEFAULT_MINSIZE, ALLOCSET_DEFAULT_INITSIZE, ALLOCSET_DEFAULT_MAXSIZE); - (void)MemoryContextSwitchTo(lwm_context); + (void)MemoryContextSwitchTo(lwm_context); // 鍒囨崲鍒拌涓婁笅鏂 #ifdef ENABLE_UT /* unit testcase */ ut_test_find_deadlock_cycle(); #endif /* ENABLE_UT */ - + // 澶勭悊寮傚父鎯呭喌 int curTryCounter; int* oldTryCounter = NULL; if (sigsetjmp(localSigjmpBuf, 1) != 0) { + // 鍏抽棴鎵鏈夋墦寮鐨勬枃浠 gstrace_tryblock_exit(true, oldTryCounter); /* Since not using PG_TRY, must reset error stack by hand */ - t_thrd.log_cxt.error_context_stack = NULL; + t_thrd.log_cxt.error_context_stack = NULL; // 鎵嬪姩閲嶇疆閿欒鍫嗘爤 - t_thrd.log_cxt.call_stack = NULL; + t_thrd.log_cxt.call_stack = NULL; // 娓呯┖璋冪敤鏍 /* Prevent interrupts while cleaning up */ - HOLD_INTERRUPTS(); + HOLD_INTERRUPTS(); // 鍦ㄦ墽琛屾竻鐞嗘搷浣滄湡闂寸姝腑鏂 /* Report the error to the server log */ - EmitErrorReport(); + EmitErrorReport(); // 鎶ュ憡閿欒鍒版湇鍔″櫒鏃ュ織 /* release resource held by lsc */ - AtEOXact_SysDBCache(false); + AtEOXact_SysDBCache(false); // 閲婃斁鐢辩郴缁熸暟鎹簱缂撳瓨鎸佹湁鐨勮祫婧 /* * Now return to normal top-level context and clear ErrorContext for * next time. */ - (void)MemoryContextSwitchTo(lwm_context); + (void)MemoryContextSwitchTo(lwm_context); // 鍒囨崲绋嬪簭鐨勫唴瀛樹笂涓嬫枃 + // 娓呴櫎閿欒鐘舵侊紝灏嗕箣鍓嶅彲鑳借褰曠殑閿欒淇℃伅鍜岀姸鎬侀噸缃负绌 FlushErrorState(); /* Flush any leaked data in the top-level context */ + // 閲嶇疆骞跺垹闄や簡涔嬪墠鍒涘缓鐨勫唴瀛樹笂涓嬫枃 lwm_context 鍙婂叾鎵鏈夊瓙涓婁笅鏂 + // 纭繚鍦ㄥ紓甯稿鐞嗗畬鎴愬悗閲婃斁宸插垎閰嶇殑鍐呭瓨锛屼互閬垮厤鍐呭瓨娉勬紡 MemoryContextResetAndDeleteChildren(lwm_context); /* Now we can allow interrupts again */ - RESUME_INTERRUPTS(); + RESUME_INTERRUPTS(); // 鍏佽涓柇淇″彿鍐嶆琚崟鑾 /* * Sleep at least 1 second after any error. A write error is likely @@ -674,20 +906,27 @@ NON_EXEC_STATIC void FaultMonitorMain() */ pg_usleep(1000000L); } + // 璁板綍褰撳墠鐨勯敊璇鐞嗗爢鏍堣鏁板櫒 oldTryCounter = gstrace_tryblock_entry(&curTryCounter); /* We can now handle ereport(ERROR) */ + // 灏嗛敊璇鐞嗙殑璺宠浆缂撳啿鍖鸿缃负褰撳墠绾跨▼鐨勯敊璇鐞嗗爢鏍 t_thrd.log_cxt.PG_exception_stack = &localSigjmpBuf; /* Unblock signals (they were blocked when the postmaster forked us) */ + // 瑙i櫎淇″彿灞忚斀锛屽厑璁镐俊鍙峰啀娆¤鎹曡幏 gs_signal_setmask(&t_thrd.libpq_cxt.UnBlockSig, NULL); + // 瑙i櫎瀵 SIGUSR2 淇″彿鐨勫睆钄斤紝鍏佽鎺ユ敹 SIGUSR2 淇″彿 (void)gs_signal_unblock_sigusr2(); - + // 鏍囪瘑鐩戣鍣ㄨ繘绋嬪簲鐢ㄧ▼搴忓悕绉 pgstat_report_appname("LWLock Monitor"); + // 璁剧疆褰撳墠鐩戣鍣ㄨ繘绋嬬殑娲诲姩鐘舵佷负 "IDLE"锛岃〃绀虹洃瑙嗗櫒褰撳墠娌℃湁澶勭悊浠讳綍娲诲姩 pgstat_report_activity(STATE_IDLE, NULL); /* set current monitor timeout */ + // 璁剧疆褰撳墠鐩戣鍣ㄧ殑瓒呮椂鏃堕棿锛屽喅瀹氱洃瑙嗗櫒澶氫箙鎵ц涓娆¢攣鐘舵佺殑妫鏌 cur_timeout = (long)u_sess->attr.attr_common.fault_mon_timeout * 60 * 1000; + // 琛ㄧず鐩墠杩樻病鏈夊彲鐢ㄧ殑蹇収鏁版嵁 prev_snapshot = NULL; curr_snapshot = NULL; @@ -700,17 +939,18 @@ NON_EXEC_STATIC void FaultMonitorMain() /* Process any requests or signals received recently. */ if (t_thrd.lwm_cxt.got_SIGHUP) { t_thrd.lwm_cxt.got_SIGHUP = false; - ProcessConfigFile(PGC_SIGHUP); - + ProcessConfigFile(PGC_SIGHUP); // 澶勭悊閰嶇疆鏂囦欢鐨勯噸鏂板姞杞 + long newTimeout = (long)u_sess->attr.attr_common.fault_mon_timeout * 60 * 1000; - + // 濡傛灉鏂扮殑瓒呮椂鏃堕棿涓庡綋鍓嶇殑瓒呮椂鏃堕棿涓嶅悓 if (newTimeout != cur_timeout) { /* for lwlock debug info */ + // 灏 LWLock 鐨勮皟璇曚俊鎭啓鍏ユ湇鍔″櫒鏃ュ織 DumpLWLockInfoToServerLog(); } /* update monitor timeout */ - cur_timeout = newTimeout; + cur_timeout = newTimeout; // 鏇存柊鐩戣鍣ㄧ殑瓒呮椂鏃堕棿 } if (t_thrd.lwm_cxt.shutdown_requested) { @@ -720,22 +960,30 @@ NON_EXEC_STATIC void FaultMonitorMain() /* disable this feature if set u_sess->attr.attr_common.fault_mon_timeout be 0 */ if (u_sess->attr.attr_common.fault_mon_timeout > 0) { + // 濡傛灉琛ㄧず鍚敤浜嗙洃瑙嗗櫒鍔熻兘 /* start to do main work */ - if (NULL != prev_snapshot) { - lwm_deadlock deadlock = {NULL, 0, 0, 0}; - bool continue_next = false; + if (NULL != prev_snapshot) { // 濡傛灉涓虹┖鍒欒〃绀洪娆¤繍琛岀洃瑙嗗櫒 + lwm_deadlock deadlock = {NULL, 0, 0, 0}; // 鐢ㄤ簬淇濆瓨妫娴嬪埌鐨勬閿佷俊鎭 + bool continue_next = false; // 鐢ㄤ簬鍒ゆ柇鏄惁闇瑕佺户缁笅涓姝ョ殑鐩戣宸ヤ綔 /* phase 1: light-weight detect using fast changcount */ + // 鑾峰彇褰撳墠鐨勮交閲忕骇蹇収鏁版嵁 curr_snapshot = pgstat_read_light_detect(); + // 姣旇緝鍓嶅悗涓や釜蹇収鏁版嵁锛屽垽鏂槸鍚﹂渶瑕佺户缁繘琛岀洃瑙嗗伐浣 + // 濡傛灉鍙戠幇閿佺姸鎬佸彉鍖栵紝灏哻ontinue_next璁句负true锛岃〃绀洪渶瑕佺户缁 continue_next = lwm_compare_light_detect(prev_snapshot, curr_snapshot); + // 濡傛灉 continue_next 涓 true锛岃〃绀洪攣鐘舵佸彂鐢熷彉鍖栵紝缁х画杩涜鐩戣宸ヤ綔 if (continue_next) { /* phase 2 if needed: heavy-weight diagnosis for lwlock deadlock */ int candidates_num = 0; + // 鏌ユ壘鍙兘杩涘叆姝婚攣鐘舵佺殑鍊欓夐攣 int* candidates_pos = lwm_find_candidates(prev_snapshot, curr_snapshot, &candidates_num); + // 璇诲彇鐢ㄤ簬璇婃柇鐨勬暟鎹紝鍖呮嫭褰撳墠蹇収鏁版嵁銆佸欓夐攣鐨勪綅缃拰鏁伴噺 lwm_lwlocks* backend_locks = pgstat_read_diagnosis_data(curr_snapshot, candidates_pos, candidates_num); pfree_ext(candidates_pos); + // 璇婃柇鎿嶄綔锛屽苟灏嗙粨鏋滀繚瀛樺湪 deadlock 鍙橀噺涓 continue_next = lwm_heavy_diagnosis(&deadlock, backend_locks, candidates_num); /* clean up. */ @@ -748,27 +996,30 @@ NON_EXEC_STATIC void FaultMonitorMain() if (continue_next) { /* phase 3 if needed: auto healing for lwlock deadlock */ + // 灏濊瘯鑷姩淇锛岃В闄ゆ閿 lw_deadlock_auto_healing(&deadlock); } /* prepare for next monitor, and keep the current snapshot */ if (NULL != deadlock.info) { - pfree_ext(deadlock.info); + pfree_ext(deadlock.info); // 閲婃斁鍐呭瓨 } pfree_ext(prev_snapshot); - prev_snapshot = curr_snapshot; + prev_snapshot = curr_snapshot; // 鏇存柊蹇収鏁版嵁 curr_snapshot = NULL; } else { + // 濡傛灉 prev_snapshot 涓虹┖锛岃〃绀洪娆¤繍琛岀洃瑙嗗櫒 /* the first time to get snapshot */ - prev_snapshot = pgstat_read_light_detect(); + prev_snapshot = pgstat_read_light_detect(); // 鑾峰彇褰撳墠鐨勮交閲忕骇蹇収鏁版嵁 curr_snapshot = NULL; } } else { /* just set a default timeout: 10min */ cur_timeout = 10 * 60 * 1000; } - + // 璁剧疆褰撳墠鐩戣鍣ㄨ繘绋嬬殑娲诲姩鐘舵佷负 "IDLE"锛岃〃绀虹洃瑙嗗櫒褰撳墠娌℃湁澶勭悊浠讳綍娲诲姩 pgstat_report_activity(STATE_IDLE, NULL); + // 绛夊緟浜嬩欢鐨勫彂鐢 rc = WaitLatch(&t_thrd.proc->procLatch, WL_LATCH_SET | WL_TIMEOUT | WL_POSTMASTER_DEATH, cur_timeout); /* @@ -782,59 +1033,110 @@ NON_EXEC_STATIC void FaultMonitorMain() } /* SIGHUP: set flag to re-read config file at next convenient time */ +/* + *鍔熻兘锛氬鐞 SIGHUP 淇″彿锛岀敤浜庨噸鏂拌鍙栭厤缃枃浠 + * + * 鍙傛暟: + * SIGNAL_ARGS: 淇″彿澶勭悊绋嬪簭鐨勫弬鏁板垪琛紝鎻愪緵鍏充簬瑙﹀彂淇″彿鐨勪笂涓嬫枃淇℃伅 + * + * 杩斿洖鍊: + * 鏃 + */ static void LWLockMonitorSigHupHandler(SIGNAL_ARGS) { - int save_errno = errno; + int save_errno = errno; // 淇濆瓨褰撳墠鐨勯敊璇爜 - t_thrd.lwm_cxt.got_SIGHUP = true; + t_thrd.lwm_cxt.got_SIGHUP = true; // 琛ㄧず鎺ユ敹鍒 SIGHUP 淇″彿 if (t_thrd.proc) - SetLatch(&t_thrd.proc->procLatch); + SetLatch(&t_thrd.proc->procLatch); // 璁剧疆璇ョ嚎绋嬬殑latch - errno = save_errno; + errno = save_errno; // 鎭㈠涔嬪墠淇濆瓨鐨勯敊璇爜 } /* SIGTERM: set flag to exit normally */ +/* + *鍔熻兘锛氬鐞 SIGTERM 淇″彿锛岀敤浜庢甯搁鍑 + * + * 鍙傛暟: + * SIGNAL_ARGS: 淇″彿澶勭悊绋嬪簭鐨勫弬鏁板垪琛紝鎻愪緵鍏充簬瑙﹀彂淇″彿鐨勪笂涓嬫枃淇℃伅 + * + * 杩斿洖鍊: + * 鏃 + */ static void LWLockMonitorShutdownHandler(SIGNAL_ARGS) { - int save_errno = errno; + int save_errno = errno; // 淇濆瓨褰撳墠鐨勯敊璇爜 - t_thrd.lwm_cxt.shutdown_requested = true; + t_thrd.lwm_cxt.shutdown_requested = true; // 琛ㄧず璇锋眰姝e父閫鍑 - if (t_thrd.proc) - SetLatch(&t_thrd.proc->procLatch); + if (t_thrd.proc) // 绾跨▼瀛樺湪 + SetLatch(&t_thrd.proc->procLatch); // 璁剧疆璇ョ嚎绋嬬殑latch - errno = save_errno; + errno = save_errno; // 鎭㈠涔嬪墠淇濆瓨鐨勯敊璇爜 } #ifdef ENABLE_UT +/* + * 鍔熻兘锛氶噴鏀炬祴璇曚腑鍒嗛厤鐨勫唴瀛 + * + * 鍙傛暟: + * locks_array锛氱敤浜庡瓨鍌ㄦ祴璇曠敤渚嬩腑鐨勯攣淇℃伅 + * n_holders锛氱敤浜庡瓨鍌ㄩ攣鐨勬暟閲 + * + * 杩斿洖鍊: + * 鏃 + */ static void ut_free_locks(lwm_lwlocks* locks_array, int n_holders) { - for (int i = 0; i < n_holders; ++i) { + for (int i = 0; i < n_holders; ++i) { // 閬嶅巻閲婃斁鍐呭瓨 pfree_ext(locks_array[i].held_lwlocks); } - pfree_ext(locks_array); + pfree_ext(locks_array); // 閲婃斁鍐呭瓨 } +/* + * 鍔熻兘锛氭祴璇曠敤渚嬶紝鐢ㄤ簬妯℃嫙涓涓畝鍗曠殑姝婚攣鎯呭喌锛屼互娴嬭瘯閿佹閿佹娴嬪拰瑙i攣鍔熻兘 + * + * 鍙傛暟: + * locks_array锛氳閲婃斁鍐呭瓨鐨勯攣淇℃伅鏁扮粍 + * n_holders锛氳閲婃斁鐨勯攣淇℃伅鏁扮粍鐨勯暱搴 + * + * 杩斿洖鍊: + * 鏃 + */ static void ut_test_deadlock00(lwm_lwlocks* locks, int* nlocks) { - *nlocks = 1; + *nlocks = 1; // 琛ㄧず娴嬭瘯涓湁涓涓攣 /* holding lwlock 1 and acquiring lwlock 1 */ - locks->be_idx = 1; - locks->be_tid.thread_id = 1; - locks->want_lwlock.lock = GetMainLWLockByIndex(1); - locks->lwlocks_num = 1; + // 璁剧疆淇℃伅 + locks->be_idx = 1; // 绾跨▼绱㈠紩 + locks->be_tid.thread_id = 1; // 绾跨▼鐨勫敮涓鏍囪瘑绗 + locks->want_lwlock.lock = GetMainLWLockByIndex(1); // 鑾峰彇浜嗙紪鍙蜂负 1 鐨勪富瑕佽交閲忕骇閿 + locks->lwlocks_num = 1; // 鎸佹湁鐨勯攣鐨勬暟閲 + // 鍒嗛厤鍐呭瓨锛岀敤浜庡瓨鍌ㄦ寔鏈夌殑閿佺殑淇℃伅 locks->held_lwlocks = (lwlock_id_mode*)palloc(sizeof(lwlock_id_mode)); + // 璁剧疆鎸佹湁鐨勯攣鐨勪俊鎭 locks->held_lwlocks[0].lock_addr.lock = GetMainLWLockByIndex(1); locks->held_lwlocks[0].lock_sx = (LWLockMode)0; } +/* + * 鍔熻兘锛氭ā鎷熶竴涓攣姝绘儏鍐碉紝鍏朵腑鏈変袱涓嚎绋嬪皾璇曡幏鍙栦笉鍚岀殑涓や釜閿侊紝骞朵笖瀹冧滑閮芥寔鏈変竴涓攣锛屽悓鏃跺皾璇曡幏鍙栧彟涓涓 + * + * 鍙傛暟: + * nlocks锛氱敤浜庤繑鍥為攣鐨勬暟閲 + * + * 杩斿洖鍊: + * lwm_lwlocks* 琛ㄧず閿佺殑鐘舵 + */ static lwm_lwlocks* ut_test_deadlock01(int* nlocks) { - int nholders = 1; - *nlocks = 2; + int nholders = 1; // 琛ㄧず姣忎釜绾跨▼鎸佹湁涓涓攣 + *nlocks = 2; // 琛ㄧず閿佺殑鎬绘暟閲 + // 鍒嗛厤鍐呭瓨浠ュ瓨鍌ㄩ攣淇℃伅鐨勬暟缁 lwm_lwlocks* locks_array = (lwm_lwlocks*)palloc(sizeof(lwm_lwlocks) * (*nlocks)); /* holding lwlock 2, and acquiring lwlock 1 */ @@ -858,6 +1160,15 @@ static lwm_lwlocks* ut_test_deadlock01(int* nlocks) return locks_array; } +/* + * 鍔熻兘锛氭ā鎷熶竴涓緝澶嶆潅鐨勯攣姝绘儏鍐碉紝鍏朵腑鏈変簲涓嚎绋嬪皾璇曡幏鍙栦笉鍚岀殑浜斾釜閿侊紝骞朵笖瀹冧滑涔嬮棿褰㈡垚涓涓幆璺 + * + * 鍙傛暟: + * nlocks锛氱敤浜庤繑鍥為攣鐨勬暟閲 + * + * 杩斿洖鍊: + * lwm_lwlocks* 琛ㄧず閿佺殑鐘舵 + */ static lwm_lwlocks* ut_test_deadlock02(int* nlocks) { *nlocks = 5; @@ -918,19 +1229,29 @@ static lwm_lwlocks* ut_test_deadlock02(int* nlocks) #define held_lwlocks_1d(_x) locks_array[_x].held_lwlocks #define held_lwlocks_2d(_x, _y) locks_array[_x].held_lwlocks[_y] - +/* + * 鍔熻兘锛氭ā鎷熶竴涓洿澶嶆潅鐨勯攣姝绘儏鍐碉紝鍏朵腑鏈変簲涓嚎绋嬪皾璇曡幏鍙栦笉鍚岀殑浜斾釜閿侊紝瀹冧滑涔嬮棿褰㈡垚澶嶆潅鐨勪緷璧栧叧绯 + * + * 鍙傛暟: + * nlocks锛氱敤浜庤繑鍥為攣鐨勬暟閲 + * + * 杩斿洖鍊: + * lwm_lwlocks* 琛ㄧず閿佺殑鐘舵 + */ static lwm_lwlocks* ut_test_deadlock03(int* nlocks) { - *nlocks = 5; - int nholders = 5; + *nlocks = 5; // 琛ㄧず閿佺殑鎬绘暟閲 + int nholders = 5; // 琛ㄧず姣忎釜绾跨▼鎸佹湁浜斾釜閿 + // 鍒嗛厤鍐呭瓨浠ュ瓨鍌ㄩ攣淇℃伅鐨勬暟缁 lwm_lwlocks* locks_array = (lwm_lwlocks*)palloc(sizeof(lwm_lwlocks) * (*nlocks)); - + // 鍒濆鍖栵紝姣忎釜鍏冪礌琛ㄧず涓涓嚎绋嬬殑閿佺姸鎬 held_lwlocks_1d(0) = (lwlock_id_mode*)palloc(sizeof(lwlock_id_mode) * (nholders)); held_lwlocks_1d(1) = (lwlock_id_mode*)palloc(sizeof(lwlock_id_mode) * (nholders)); held_lwlocks_1d(2) = (lwlock_id_mode*)palloc(sizeof(lwlock_id_mode) * (nholders)); held_lwlocks_1d(3) = (lwlock_id_mode*)palloc(sizeof(lwlock_id_mode) * (nholders)); held_lwlocks_1d(4) = (lwlock_id_mode*)palloc(sizeof(lwlock_id_mode) * (nholders)); + // 閿佺殑鐘舵佽缃垚姣忎釜绾跨▼鎸佹湁澶氫釜閿侊紝骞跺皾璇曡幏鍙栧叾浠栭攣锛屼互鍒涘缓澶嶆潅鐨勪緷璧栧叧绯 locks_array[0].lwlocks_num = locks_array[1].lwlocks_num = locks_array[2].lwlocks_num = nholders; locks_array[3].lwlocks_num = locks_array[4].lwlocks_num = nholders; @@ -997,30 +1318,42 @@ typedef lwm_lwlocks* (*ut_test_deadlock)(int*); const ut_test_deadlock ut_testcases[] = {ut_test_deadlock01, ut_test_deadlock02, ut_test_deadlock03}; +/* + * 鍔熻兘锛氭祴璇曢攣姝绘娴嬪姛鑳 + * + * 鍙傛暟:鏃 + * + * 杩斿洖鍊:鏃 + */ static void ut_test_find_deadlock_cycle(void) { - int nlocks = 0; - bool has_cycle = false; + int nlocks = 0; // 鐢ㄤ簬瀛樺偍閿佺殑鏁伴噺 + bool has_cycle = false; // 鐢ㄤ簬琛ㄧず鏄惁妫娴嬪埌姝婚攣 - lwm_deadlock deadlock; - deadlock.info = NULL; + lwm_deadlock deadlock; // 鐢ㄤ簬瀛樺偍姝婚攣妫娴嬬殑鐩稿叧淇℃伅 + deadlock.info = NULL; // 琛ㄧず娌℃湁鍏充簬姝婚攣鐨勮缁嗕俊鎭 - lwm_lwlocks locks; - locks.held_lwlocks = NULL; + lwm_lwlocks locks; // 鐢ㄤ簬瀛樺偍閿佺殑淇℃伅 + locks.held_lwlocks = NULL; // 琛ㄧず褰撳墠娌℃湁绾跨▼鎸佹湁浠讳綍閿 + // 妯℃嫙涓涓閿佹儏鍐碉紝骞跺皢鐩稿叧淇℃伅瀛樺偍鍦 locks 涓紝鍚屾椂鏇存柊 nlocks 鐨勫间互琛ㄧず閿佺殑鏁伴噺 ut_test_deadlock00(&locks, &nlocks); + // 妫娴嬫閿佹儏鍐 has_cycle = lwm_heavy_diagnosis(&deadlock, &locks, nlocks); - Assert(has_cycle); - pfree_ext(locks.held_lwlocks); - + Assert(has_cycle); // 鏂█妫娴嬫閿佹儏鍐 + pfree_ext(locks.held_lwlocks); // 閲婃斁鍐呭瓨 + // 閬嶅巻娴嬭瘯鐢ㄤ緥鏁扮粍 for (int i = 0; i < (int)(sizeof(ut_testcases) / sizeof(ut_testcases[0])); ++i) { + // 妯℃嫙涓嶅悓鐨勬閿佹儏鍐 lwm_lwlocks* locks_array = ut_testcases[i](&nlocks); + // 妫娴嬪綋鍓嶆祴璇曠敤渚嬩笅鐨勬閿佹儏鍐碉紝骞跺皢缁撴灉瀛樺偍鍦 has_cycle 鍙橀噺涓 has_cycle = lwm_heavy_diagnosis(&deadlock, locks_array, nlocks); + // 浠ョ‘淇濇娴嬪埌浜嗘閿佹儏鍐 Assert(has_cycle); - lw_deadlock_auto_healing(&deadlock); - ut_free_locks(locks_array, nlocks); + lw_deadlock_auto_healing(&deadlock); // 閲婃斁褰撳墠娴嬭瘯鐢ㄤ緥涓垎閰嶇殑鍐呭瓨 + ut_free_locks(locks_array, nlocks); // 閲婃斁鍐呭瓨 } - pfree_ext(deadlock.info); + pfree_ext(deadlock.info); // 閲婃斁鍐呭瓨锛屾竻鐞嗘閿佹娴嬬殑鐩稿叧淇℃伅 } #endif /* ENABLE_UT */ diff --git a/src/gausskernel/process/postmaster/pagerepair.cpp b/src/gausskernel/process/postmaster/pagerepair.cpp index 68ebc65e7..099d20caf 100644 --- a/src/gausskernel/process/postmaster/pagerepair.cpp +++ b/src/gausskernel/process/postmaster/pagerepair.cpp @@ -79,11 +79,27 @@ static void PushBadFileToRemoteHashTbl(RepairFileKey key); (key1).relfilenode.opt == (key2).relfilenode.opt && (key1).forknum == (key2).forknum && \ (key1).blocknum == (key2).blocknum) -#define NOT_SUPPORT_PAGE_REPAIR \ +#define NOT_SUPPORT_PAGE_REPAIR \ (g_instance.attr.attr_common.cluster_run_mode == RUN_MODE_STANDBY || \ g_instance.attr.attr_common.stream_cluster_run_mode == RUN_MODE_STANDBY || \ t_thrd.xlog_cxt.is_hadr_main_standby || t_thrd.xlog_cxt.is_cascade_standby) - +/* + * 鍔熻兘锛氭鏌ヤ慨澶嶅潡鐨凩SN锛堟棩蹇楀簭鍒楀彿锛 + * + * 鍙傛暟鍒楄〃锛 + * xlogreader锛歑LogReaderState缁撴瀯浣撴寚閽堬紝鐢ㄤ簬璇诲彇XLOG璁板綍 + * key锛歊epairBlockKey缁撴瀯浣擄紝鍖呭惈浜嗚妫鏌ョ殑鍧楃殑鍏抽敭淇℃伅 + * page_old_lsn锛氬潡鐨勬棫LSN + * last_lsn锛氱敤浜庤繑鍥炲潡鐨勬渶鏂癓SN + * + * 杩斿洖鍊硷細 + * 濡傛灉妫鏌ユ垚鍔燂紝杩斿洖CHECK_SUCCESS锛 + * 濡傛灉闇瑕佺户缁鏌ュ叾浠栧潡锛岃繑鍥濶EED_CONTINUE_CHECK锛 + * 濡傛灉妫鏌ュけ璐ワ紝杩斿洖CHECK_FAIL銆 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庢鏌ヤ慨澶嶅潡鐨凩SN锛岄氳繃姣旇緝鍧楃殑鏈鏂癓SN涓庢棫LSN鏉ュ垽鏂潡鏄惁闇瑕佷慨澶嶃 + */ int CheckBlockLsn(XLogReaderState *xlogreader, RepairBlockKey key, XLogRecPtr page_old_lsn, XLogRecPtr *last_lsn) { RepairBlockKey temp_key = {0}; @@ -97,44 +113,41 @@ int CheckBlockLsn(XLogReaderState *xlogreader, RepairBlockKey key, XLogRecPtr pa getlsn = XLogRecGetBlockLastLsn(xlogreader, block_id, last_lsn); Assert(getlsn); if (XLogRecPtrIsInvalid(*last_lsn)) { - ereport(LOG, - (errmsg("check the repair page successfully, last_lsn is 0," - "the page %u/%u/%u bucketnode %d, forknum is %u, blocknum is %u", - key.relfilenode.spcNode, key.relfilenode.dbNode, key.relfilenode.relNode, - key.relfilenode.bucketNode, key.forknum, key.blocknum))); + ereport(LOG, (errmsg("check the repair page successfully, last_lsn is 0," + "the page %u/%u/%u bucketnode %d, forknum is %u, blocknum is %u", + key.relfilenode.spcNode, key.relfilenode.dbNode, key.relfilenode.relNode, + key.relfilenode.bucketNode, key.forknum, key.blocknum))); return CHECK_SUCCESS; } /* if the xlog record last_lsn equal the current standby page lsn, means found a complete xlog chain */ if (*last_lsn == page_old_lsn) { - ereport(LOG, - (errmsg("check the repair page successfully, the page %u/%u/%u bucketnode %d, " - "forknum is %u, blocknum is %u", - key.relfilenode.spcNode, key.relfilenode.dbNode, key.relfilenode.relNode, - key.relfilenode.bucketNode, key.forknum, key.blocknum))); + ereport(LOG, (errmsg("check the repair page successfully, the page %u/%u/%u bucketnode %d, " + "forknum is %u, blocknum is %u", + key.relfilenode.spcNode, key.relfilenode.dbNode, key.relfilenode.relNode, + key.relfilenode.bucketNode, key.forknum, key.blocknum))); return CHECK_SUCCESS; } /* if the xlog record last lsn */ if (*last_lsn < page_old_lsn) { ereport(WARNING, - (errmsg("check the repair page, lsn not match, page_old_lsn is %X/%X, last_lsn is %X/%X, " - "could not repair the page %u/%u/%u bucketnode %d, forknum is %u, blocknum is %u", - (uint32)(page_old_lsn >> XLOG_LSN_SWAP), (uint32)page_old_lsn, - (uint32)(*last_lsn >> XLOG_LSN_SWAP), (uint32)*last_lsn, - key.relfilenode.spcNode, key.relfilenode.dbNode, key.relfilenode.relNode, - key.relfilenode.bucketNode, key.forknum, key.blocknum))); + (errmsg("check the repair page, lsn not match, page_old_lsn is %X/%X, last_lsn is %X/%X, " + "could not repair the page %u/%u/%u bucketnode %d, forknum is %u, blocknum is %u", + (uint32)(page_old_lsn >> XLOG_LSN_SWAP), (uint32)page_old_lsn, + (uint32)(*last_lsn >> XLOG_LSN_SWAP), (uint32)*last_lsn, key.relfilenode.spcNode, + key.relfilenode.dbNode, key.relfilenode.relNode, key.relfilenode.bucketNode, + key.forknum, key.blocknum))); return CHECK_FAIL; } } } if (!page_found) { - ereport(WARNING, - (errmsg("check the repair page, not get page info, page_old_lsn is %X/%X, last_lsn is %X/%X, " - "could not repair the page %u/%u/%u bucketnode %d, forknum is %u, blocknum is %u", - (uint32)(page_old_lsn >> XLOG_LSN_SWAP), (uint32)page_old_lsn, - (uint32)(*last_lsn >> XLOG_LSN_SWAP), (uint32)*last_lsn, - key.relfilenode.spcNode, key.relfilenode.dbNode, key.relfilenode.relNode, - key.relfilenode.bucketNode, key.forknum, key.blocknum))); + ereport(WARNING, (errmsg("check the repair page, not get page info, page_old_lsn is %X/%X, last_lsn is %X/%X, " + "could not repair the page %u/%u/%u bucketnode %d, forknum is %u, blocknum is %u", + (uint32)(page_old_lsn >> XLOG_LSN_SWAP), (uint32)page_old_lsn, + (uint32)(*last_lsn >> XLOG_LSN_SWAP), (uint32)*last_lsn, key.relfilenode.spcNode, + key.relfilenode.dbNode, key.relfilenode.relNode, key.relfilenode.bucketNode, + key.forknum, key.blocknum))); return CHECK_FAIL; } return NEED_CONTINUE_CHECK; @@ -143,6 +156,21 @@ int CheckBlockLsn(XLogReaderState *xlogreader, RepairBlockKey key, XLogRecPtr pa /* CheckPrimaryPageLSN * Check whether the data page of the primary DN forms a complete xlog chain with the page of the standby DN. */ +/* + * 鍔熻兘锛氭鏌ヤ富鍧楃殑LSN锛堟棩蹇楀簭鍒楀彿锛 + * + * 鍙傛暟鍒楄〃锛 + * page_old_lsn锛氬潡鐨勬棫LSN + * page_new_lsn锛氬潡鐨勬柊LSN + * key锛歊epairBlockKey缁撴瀯浣擄紝鍖呭惈浜嗗潡鐨勫叧閿俊鎭 + * + * 杩斿洖鍊硷細 + * 濡傛灉妫鏌ユ垚鍔燂紝杩斿洖true锛 + * 濡傛灉妫鏌ュけ璐ワ紝杩斿洖false銆 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庢鏌ヤ富鍧楃殑LSN锛岄氳繃瑙f瀽XLOG璁板綍鏉ュ垽鏂潡鏄惁闇瑕佷慨澶嶃 + */ bool CheckPrimaryPageLSN(XLogRecPtr page_old_lsn, XLogRecPtr page_new_lsn, RepairBlockKey key) { XLogRecPtr prev_lsn = InvalidXLogRecPtr; @@ -159,9 +187,8 @@ bool CheckPrimaryPageLSN(XLogRecPtr page_old_lsn, XLogRecPtr page_new_lsn, Repai xlogreader = XLogReaderAllocate(&XLogPageRead, &readprivate); if (xlogreader == NULL) { - ereport(ERROR, - (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of memory"), - errdetail("Failed while allocating an XLog reading processor for pagerepair thread"))); + ereport(ERROR, (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of memory"), + errdetail("Failed while allocating an XLog reading processor for pagerepair thread"))); } xlogreader->system_identifier = t_thrd.shemem_ptr_cxt.ControlFile->system_identifier; @@ -177,13 +204,12 @@ bool CheckPrimaryPageLSN(XLogRecPtr page_old_lsn, XLogRecPtr page_new_lsn, Repai } record = XLogReadRecord(xlogreader, last_lsn, &errormsg); if (record == NULL) { - ereport(WARNING, - (errmsg("check the repair page, page_old_lsn is %X/%X, could not get the xlog %X/%X " - "could not repair the page %u/%u/%u bucketnode %d, forknum is %u, blocknum is %u", - (uint32)(page_old_lsn >> XLOG_LSN_SWAP), (uint32)page_old_lsn, - (uint32)(last_lsn >> XLOG_LSN_SWAP), (uint32)last_lsn, - key.relfilenode.spcNode, key.relfilenode.dbNode, key.relfilenode.relNode, - key.relfilenode.bucketNode, key.forknum, key.blocknum))); + ereport(WARNING, (errmsg("check the repair page, page_old_lsn is %X/%X, could not get the xlog %X/%X " + "could not repair the page %u/%u/%u bucketnode %d, forknum is %u, blocknum is %u", + (uint32)(page_old_lsn >> XLOG_LSN_SWAP), (uint32)page_old_lsn, + (uint32)(last_lsn >> XLOG_LSN_SWAP), (uint32)last_lsn, key.relfilenode.spcNode, + key.relfilenode.dbNode, key.relfilenode.relNode, key.relfilenode.bucketNode, + key.forknum, key.blocknum))); return false; } @@ -199,18 +225,22 @@ bool CheckPrimaryPageLSN(XLogRecPtr page_old_lsn, XLogRecPtr page_new_lsn, Repai } ereport(WARNING, - (errmsg("check the repair page, could not found the page info from the xlog " - "could not repair the page, page old lsn is %X/%X, last lsn is %X/%X, page new lsn is %X/%X" - "page info is %u/%u/%u bucketnode %d, forknum is %u, blocknum is %u", - (uint32)(page_old_lsn >> XLOG_LSN_SWAP), (uint32)page_old_lsn, - (uint32)(last_lsn >> XLOG_LSN_SWAP), (uint32)last_lsn, - (uint32)(page_new_lsn >> XLOG_LSN_SWAP), (uint32)page_new_lsn, - key.relfilenode.spcNode, key.relfilenode.dbNode, key.relfilenode.relNode, - key.relfilenode.bucketNode, key.forknum, key.blocknum))); + (errmsg("check the repair page, could not found the page info from the xlog " + "could not repair the page, page old lsn is %X/%X, last lsn is %X/%X, page new lsn is %X/%X" + "page info is %u/%u/%u bucketnode %d, forknum is %u, blocknum is %u", + (uint32)(page_old_lsn >> XLOG_LSN_SWAP), (uint32)page_old_lsn, (uint32)(last_lsn >> XLOG_LSN_SWAP), + (uint32)last_lsn, (uint32)(page_new_lsn >> XLOG_LSN_SWAP), (uint32)page_new_lsn, + key.relfilenode.spcNode, key.relfilenode.dbNode, key.relfilenode.relNode, + key.relfilenode.bucketNode, key.forknum, key.blocknum))); return false; } - +/* + * 鍔熻兘锛氬垵濮嬪寲椤甸潰淇鍝堝笇琛 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庡垵濮嬪寲椤甸潰淇鍝堝笇琛紝鍖呮嫭鍒嗛厤閿佸拰鍒涘缓鍝堝笇琛ㄣ + */ void PageRepairHashTblInit(void) { HASHCTL ctl; @@ -227,8 +257,8 @@ void PageRepairHashTblInit(void) ctl.entrysize = sizeof(RepairBlockEntry); ctl.hash = tag_hash; ctl.hcxt = INSTANCE_GET_MEM_CXT_GROUP(MEMORY_CONTEXT_STORAGE); - g_instance.repair_cxt.page_repair_hashtbl = hash_create("Page Repair Hash Table", MAX_REPAIR_PAGE_NUM, &ctl, - HASH_ELEM | HASH_FUNCTION |HASH_CONTEXT); + g_instance.repair_cxt.page_repair_hashtbl = + hash_create("Page Repair Hash Table", MAX_REPAIR_PAGE_NUM, &ctl, HASH_ELEM | HASH_FUNCTION | HASH_CONTEXT); if (!g_instance.repair_cxt.page_repair_hashtbl) ereport(FATAL, (errmsg("could not initialize page repair Hash table"))); @@ -236,7 +266,12 @@ void PageRepairHashTblInit(void) return; } - +/* + * 鍔熻兘锛氭竻鐞嗛〉闈慨澶嶇嚎绋嬬殑鍐呭瓨 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庢竻鐞嗛〉闈慨澶嶇嚎绋嬩娇鐢ㄧ殑鍐呭瓨锛屽寘鎷攢姣佸搱甯岃〃銆 + */ void ClearPageRepairTheadMem(void) { if (g_instance.repair_cxt.page_repair_hashtbl != NULL) { @@ -256,6 +291,16 @@ void ClearPageRepairTheadMem(void) * After remote read, copy the page to hash table and update the page_new_lsn * of page repair hash table, means that the page is correct. */ +/* + * 鍔熻兘锛氬皢椤甸潰鍐呭澶嶅埗鍒颁慨澶嶅搱甯岃〃涓殑鏉$洰 + * + * 鍙傛暟鍒楄〃锛 + * entry锛氭寚鍚戜慨澶嶅搱甯岃〃涓殑鏉$洰鐨勬寚閽 + * page_content锛氭寚鍚戦〉闈㈠唴瀹圭殑鎸囬拡 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庡皢椤甸潰鍐呭澶嶅埗鍒颁慨澶嶅搱甯岃〃涓殑鎸囧畾鏉$洰锛屽苟鏍规嵁閿欒绫诲瀷鏇存柊鏉$洰鐨勭姸鎬併 + */ void CopyPageToRepairHashTbl(RepairBlockEntry *entry, char *page_content) { XLogRecPtr page_lsn = PageGetLSN(page_content); @@ -272,7 +317,15 @@ void CopyPageToRepairHashTbl(RepairBlockEntry *entry, char *page_content) } return; } - +/* + * 鍔熻兘锛氭鏌ラ〉闈SN骞舵牴鎹渶瑕佷慨澶嶉〉闈 + * + * 鍙傛暟鍒楄〃锛 + * key锛氫慨澶嶉〉闈㈢殑鏍囪瘑閿 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庢鏌ラ〉闈㈢殑LSN锛屽鏋滈渶瑕佷慨澶嶏紝鍒欐墽琛屼慨澶嶆搷浣溿 + */ void CheckPageLSN(RepairBlockKey key) { HTAB *repair_hash = g_instance.repair_cxt.page_repair_hashtbl; @@ -284,7 +337,7 @@ void CheckPageLSN(RepairBlockKey key) LWLockAcquire(g_instance.repair_cxt.page_repair_hashtbl_lock, LW_EXCLUSIVE); - entry = (RepairBlockEntry*)hash_search(repair_hash, &(key), HASH_FIND, &found); + entry = (RepairBlockEntry *)hash_search(repair_hash, &(key), HASH_FIND, &found); if (found) { page_old_lsn = entry->page_old_lsn; page_lsn = PageGetLSN(entry->page_content); @@ -298,7 +351,7 @@ void CheckPageLSN(RepairBlockKey key) bool check = CheckPrimaryPageLSN(page_old_lsn, page_lsn, key); if (check) { LWLockAcquire(g_instance.repair_cxt.page_repair_hashtbl_lock, LW_EXCLUSIVE); - entry = (RepairBlockEntry*)hash_search(repair_hash, &(key), HASH_FIND, &found); + entry = (RepairBlockEntry *)hash_search(repair_hash, &(key), HASH_FIND, &found); if (found) { entry->page_new_lsn = page_lsn; entry->page_state = WAIT_REPAIR; @@ -306,21 +359,31 @@ void CheckPageLSN(RepairBlockKey key) } LWLockRelease(g_instance.repair_cxt.page_repair_hashtbl_lock); } else { - ereport(PANIC, - (errmsg("check the repair page lsn failed, could not repair the page, " - "page old lsn is %X/%X, primary lsn is %X/%X, " - "page info is %u/%u/%u bucketnode %d, forknum is %u, blocknum is %u", - (uint32)(page_old_lsn >> XLOG_LSN_SWAP), (uint32)page_old_lsn, - (uint32)(page_lsn >> XLOG_LSN_SWAP), (uint32)page_lsn, - key.relfilenode.spcNode, key.relfilenode.dbNode, key.relfilenode.relNode, - key.relfilenode.bucketNode, key.forknum, key.blocknum))); + ereport(PANIC, (errmsg("check the repair page lsn failed, could not repair the page, " + "page old lsn is %X/%X, primary lsn is %X/%X, " + "page info is %u/%u/%u bucketnode %d, forknum is %u, blocknum is %u", + (uint32)(page_old_lsn >> XLOG_LSN_SWAP), (uint32)page_old_lsn, + (uint32)(page_lsn >> XLOG_LSN_SWAP), (uint32)page_lsn, key.relfilenode.spcNode, + key.relfilenode.dbNode, key.relfilenode.relNode, key.relfilenode.bucketNode, + key.forknum, key.blocknum))); } } else { LWLockRelease(g_instance.repair_cxt.page_repair_hashtbl_lock); } return; } - +/* + * 鍔熻兘锛氶氳繃杩滅▼璇诲彇鑾峰彇鏂囦欢鐨勫ぇ灏忥紝涓嶅鐞嗛敊璇 + * + * 鍙傛暟鍒楄〃锛 + * key锛氫慨澶嶆枃浠剁殑鏍囪瘑閿 + * size锛氬瓨鍌ㄦ枃浠跺ぇ灏忕殑鎸囬拡 + * + * 杩斿洖鍊硷細杩滅▼璇诲彇鐨勭粨鏋滀唬鐮 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庨氳繃杩滅▼璇诲彇鑾峰彇鏂囦欢鐨勫ぇ灏忥紝涓嶅鐞嗛敊璇 + */ int RemoteReadFileSizeNoError(RepairFileKey *key, int64 *size) { /* get remote address */ @@ -330,20 +393,25 @@ int RemoteReadFileSizeNoError(RepairFileKey *key, int64 *size) GetRemoteReadAddress(remote_address1, remote_address2, MAXPGPATH); char *remote_address = remote_address1; + /* 濡傛灉杩滅▼鍦板潃涓虹┖鎴栦互鍐掑彿寮澶达紝琛ㄧず杩滅▼涓嶅彲鐢 */ if (remote_address[0] == '\0' || remote_address[0] == ':') { ereport(DEBUG1, (errmodule(MOD_REMOTE), errmsg("remote not available"))); return REMOTE_READ_IP_NOT_EXIST; } + /* 璁板綍鏃ュ織锛屾寚绀烘鍦ㄨ繙绋嬭鍙栨枃浠剁殑澶у皬 */ ereport(LOG, (errmodule(MOD_REMOTE), errmsg("remote read file size, file %s from %s", - relpathperm(key->relfilenode, key->forknum), - remote_address))); + relpathperm(key->relfilenode, key->forknum), remote_address))); + /* 鍑嗗杩滅▼璇诲彇鏂囦欢鐨勯敭 */ RemoteReadFileKey read_key; read_key.relfilenode = key->relfilenode; read_key.forknum = key->forknum; read_key.blockstart = 0; + /* 鍚姩杩滅▼璇诲彇鐨勬ц兘鍒嗘瀽 */ PROFILING_REMOTE_START(); + + /* 璋冪敤杩滅▼鑾峰彇鏂囦欢澶у皬鐨勫嚱鏁 */ int retCode = RemoteGetFileSize(remote_address, &read_key, InvalidXLogRecPtr, size, timeout); /* return file size + primary lsn */ PROFILING_REMOTE_END_READ(sizeof(uint64) + sizeof(uint64), (retCode == REMOTE_READ_OK)); @@ -353,68 +421,134 @@ int RemoteReadFileSizeNoError(RepairFileKey *key, int64 *size) /* RemoteReadFile * standby dn use this function repair file. */ -int RemoteReadFileNoError(RemoteReadFileKey *key, char *buf, XLogRecPtr lsn, uint32 size, - XLogRecPtr *remote_lsn, uint32 *remote_size) +/* + * 鍔熻兘锛氶氳繃杩滅▼璇诲彇鏂囦欢鍐呭锛屼笉澶勭悊閿欒 + * + * 鍙傛暟鍒楄〃锛 + * key锛氳繙绋嬭鍙栨枃浠剁殑鏍囪瘑閿 + * buf锛氬瓨鍌ㄦ枃浠跺唴瀹圭殑缂撳啿鍖 + * lsn锛氳姹傜殑LSN锛堟棩蹇楀簭鍒楀彿锛 + * size锛氳姹傜殑鏂囦欢鍐呭澶у皬 + * remote_lsn锛氬疄闄呰幏鍙栫殑LSN + * remote_size锛氬疄闄呰幏鍙栫殑鏂囦欢鍐呭澶у皬 + * + * 杩斿洖鍊硷細杩滅▼璇诲彇鐨勭粨鏋滀唬鐮 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庨氳繃杩滅▼璇诲彇鏂囦欢鍐呭锛屼笉澶勭悊閿欒銆 + */ +int RemoteReadFileNoError(RemoteReadFileKey *key, char *buf, XLogRecPtr lsn, uint32 size, XLogRecPtr *remote_lsn, + uint32 *remote_size) { - /* get remote address */ - char remote_address1[MAXPGPATH] = {0}; /* remote_address1[0] = '\0'; */ - char remote_address2[MAXPGPATH] = {0}; /* remote_address2[0] = '\0'; */ + /* 鑾峰彇杩滅▼鍦板潃 */ + char remote_address1[MAXPGPATH] = {0}; + char remote_address2[MAXPGPATH] = {0}; char *remote_address = NULL; GetRemoteReadAddress(remote_address1, remote_address2, MAXPGPATH); remote_address = remote_address1; int timeout = 0; + /* 濡傛灉杩滅▼鍦板潃涓虹┖鎴栦互鍐掑彿寮澶达紝琛ㄧず杩滅▼涓嶅彲鐢 */ if (remote_address[0] == '\0' || remote_address[0] == ':') { ereport(WARNING, (errcode(ERRCODE_IO_ERROR), errmodule(MOD_REMOTE), errmsg("remote not available"))); return REMOTE_READ_IP_NOT_EXIST; } - ereport(LOG, (errmodule(MOD_REMOTE), - errmsg("remote read file, file %s from %s, block start is %u", - relpathperm(key->relfilenode, key->forknum), remote_address, key->blockstart))); + /* 璁板綍鏃ュ織锛屾寚绀烘鍦ㄨ繙绋嬭鍙栨枃浠跺唴瀹 */ + ereport(LOG, (errmodule(MOD_REMOTE), + errmsg("remote read file, file %s from %s, block start is %u", + relpathperm(key->relfilenode, key->forknum), remote_address, key->blockstart))); + + /* 鍚姩杩滅▼璇诲彇鐨勬ц兘鍒嗘瀽 */ PROFILING_REMOTE_START(); + + /* 璋冪敤杩滅▼鑾峰彇鏂囦欢鍐呭鐨勫嚱鏁 */ int retCode = RemoteGetFile(remote_address, key, lsn, size, buf, remote_lsn, remote_size, timeout); + + /* 缁撴潫杩滅▼璇诲彇鐨勬ц兘鍒嗘瀽锛岃繑鍥炲疄闄呰幏鍙栫殑鏂囦欢鍐呭澶у皬 */ PROFILING_REMOTE_END_READ(size, (retCode == REMOTE_READ_OK)); return retCode; } +/* + * 鍔熻兘锛氶氳繃杩滅▼璇诲彇鏁版嵁鍧楀唴瀹癸紝涓嶅鐞嗛敊璇 + * + * 鍙傛暟鍒楄〃锛 + * key锛氳繙绋嬭鍙栨暟鎹潡鐨勬爣璇嗛敭 + * buf锛氬瓨鍌ㄦ暟鎹潡鍐呭鐨勭紦鍐插尯 + * lsn锛氳姹傜殑LSN锛堟棩蹇楀簭鍒楀彿锛 + * pblk锛氱墿鐞嗗潡淇℃伅锛堝彲閫夛級 + * + * 杩斿洖鍊硷細杩滅▼璇诲彇鐨勭粨鏋滀唬鐮 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庨氳繃杩滅▼璇诲彇鏁版嵁鍧楀唴瀹癸紝涓嶅鐞嗛敊璇 + */ int RemoteReadBlockNoError(RepairBlockKey *key, char *buf, XLogRecPtr lsn, const XLogPhyBlock *pblk) { - /* get remote address */ - char remote_address1[MAXPGPATH] = {0}; /* remote_address1[0] = '\0'; */ - char remote_address2[MAXPGPATH] = {0}; /* remote_address2[0] = '\0'; */ + /* 鑾峰彇杩滅▼鍦板潃 */ + char remote_address1[MAXPGPATH] = {0}; + char remote_address2[MAXPGPATH] = {0}; + char *remote_address = NULL; GetRemoteReadAddress(remote_address1, remote_address2, MAXPGPATH); - char *remote_address = remote_address1; + remote_address = remote_address1; + + /* 濡傛灉杩滅▼鍦板潃涓虹┖鎴栦互鍐掑彿寮澶达紝琛ㄧず杩滅▼涓嶅彲鐢 */ if (remote_address[0] == '\0' || remote_address[0] == ':') { ereport(DEBUG1, (errmodule(MOD_REMOTE), errmsg("remote not available"))); return REMOTE_READ_IP_NOT_EXIST; } + + /* 璁板綍鏃ュ織锛屾寚绀烘鍦ㄨ繙绋嬭鍙栨暟鎹潡鍐呭 */ if (pblk != NULL) { ereport(LOG, (errmodule(MOD_REMOTE), errmsg("remote read page, file %s block %u (pblk %u/%d) from %s", - relpathperm(key->relfilenode, key->forknum), key->blocknum, pblk->relNode, pblk->block, remote_address))); + relpathperm(key->relfilenode, key->forknum), key->blocknum, + pblk->relNode, pblk->block, remote_address))); } else { - ereport(LOG, (errmodule(MOD_REMOTE), errmsg("remote read page, file %s block %u from %s", - relpathperm(key->relfilenode, key->forknum), key->blocknum, remote_address))); + ereport(LOG, (errmodule(MOD_REMOTE), + errmsg("remote read page, file %s block %u from %s", relpathperm(key->relfilenode, key->forknum), + key->blocknum, remote_address))); } + /* 璁剧疆杩滅▼璇诲彇鐨勮秴鏃舵椂闂 */ const int TIMEOUT = 60; + + /* 鍚姩杩滅▼璇诲彇鐨勬ц兘鍒嗘瀽 */ PROFILING_REMOTE_START(); + + /* 璋冪敤杩滅▼鑾峰彇鏁版嵁鍧楀唴瀹圭殑鍑芥暟 */ int retCode = RemoteGetPage(remote_address, key, BLCKSZ, lsn, buf, pblk, TIMEOUT); + + /* 缁撴潫杩滅▼璇诲彇鐨勬ц兘鍒嗘瀽锛岃繑鍥炲疄闄呰幏鍙栫殑鏁版嵁鍧楀唴瀹瑰ぇ灏 */ PROFILING_REMOTE_END_READ(BLCKSZ, (retCode == REMOTE_READ_OK)); return retCode; } +/* + * 鍔熻兘锛氫慨澶嶆暟鎹潡锛屾牴鎹渶瑕佷粠杩滅▼璇诲彇鏁版嵁鍧楀唴瀹 + * + * 鍙傛暟鍒楄〃锛 + * entry锛氭暟鎹潡淇鏉$洰 + * page锛氬瓨鍌ㄦ暟鎹潡鍐呭鐨勭紦鍐插尯 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庝慨澶嶆暟鎹潡锛屾牴鎹渶瑕佷粠杩滅▼璇诲彇鏁版嵁鍧楀唴瀹广 + */ static void RepairPage(RepairBlockEntry *entry, char *page) { int retCode = 0; + /* 濡傛灉鏁版嵁鍧楀寘鍚墿鐞嗗潡淇℃伅 */ if (entry->pblk.relNode != InvalidOid) { retCode = RemoteReadBlockNoError(&entry->key, page, entry->page_old_lsn, &entry->pblk); } else { + /* 鍚﹀垯锛屽彧璇诲彇鏁版嵁鍧楀唴瀹 */ retCode = RemoteReadBlockNoError(&entry->key, page, entry->page_old_lsn, NULL); } + + /* 濡傛灉杩滅▼璇诲彇鎴愬姛锛屽垯灏嗘暟鎹潡鍐呭澶嶅埗鍒颁慨澶嶅搱甯岃〃涓 */ if (retCode == REMOTE_READ_OK) { CopyPageToRepairHashTbl(entry, page); } @@ -423,6 +557,12 @@ static void RepairPage(RepairBlockEntry *entry, char *page) } const int MAX_CHECK_LSN_NUM = 100; +/* + * 鍔熻兘锛氶『搴忚繙绋嬭鍙栨暟鎹潡骞惰繘琛屼慨澶 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庢寜椤哄簭杩唬淇鍝堝笇琛ㄤ腑鐨勬暟鎹潡锛屾牴鎹渶瑕佽繙绋嬭鍙栨暟鎹潡鍐呭骞惰繘琛屼慨澶嶃 + */ static void SeqRemoteReadPage() { HTAB *repair_hash = g_instance.repair_cxt.page_repair_hashtbl; @@ -436,29 +576,39 @@ static void SeqRemoteReadPage() LWLockAcquire(g_instance.repair_cxt.page_repair_hashtbl_lock, LW_EXCLUSIVE); + /* 鍒濆鍖栧搱甯岃〃杩唬鍣 */ hash_seq_init(&status, repair_hash); + + /* 閬嶅巻淇鍝堝笇琛ㄤ腑鐨勬暟鎹潡 */ while ((entry = (RepairBlockEntry *)hash_seq_search(&status)) != NULL) { need_repair_num++; + switch (entry->page_state) { case WAIT_REMOTE_READ: + /* 淇鏁版嵁鍧楀苟鏍规嵁闇瑕佽繘琛孡SN妫鏌 */ RepairPage(entry, page); + if (entry->error_type == LSN_CHECK_FAIL && entry->page_state == WAIT_LSN_CHECK && check_lsn_num < MAX_CHECK_LSN_NUM) { lsncheck[check_lsn_num] = entry->key; check_lsn_num++; } + if (entry->page_state == WAIT_REPAIR) { + /* 濡傛灉闇瑕佷慨澶嶏紝鍒欏悜鎭㈠绾跨▼鍙戦佷俊鍙 */ (void)gs_signal_send(entry->recovery_tid, SIGUSR1); repair_num++; } break; case WAIT_LSN_CHECK: if (check_lsn_num < MAX_CHECK_LSN_NUM) { + /* 灏嗛渶瑕佽繘琛孡SN妫鏌ョ殑鏁版嵁鍧楀姞鍏ユ鏌ラ槦鍒 */ lsncheck[check_lsn_num] = entry->key; check_lsn_num++; } break; case WAIT_REPAIR: + /* 濡傛灉闇瑕佷慨澶嶏紝鍒欏悜鎭㈠绾跨▼鍙戦佷俊鍙 */ repair_num++; (void)gs_signal_send(entry->recovery_tid, SIGUSR1); break; @@ -469,56 +619,76 @@ static void SeqRemoteReadPage() LWLockRelease(g_instance.repair_cxt.page_repair_hashtbl_lock); + /* 瀵归渶瑕佽繘琛孡SN妫鏌ョ殑鏁版嵁鍧楁墽琛屾鏌 */ for (int i = 0; i < check_lsn_num; i++) { RepairBlockKey temp = lsncheck[i]; CheckPageLSN(temp); } + + /* 濡傛灉鎵鏈夐渶瑕佷慨澶嶇殑鏁版嵁鍧楅兘宸蹭慨澶嶅畬姣曪紝璁剧疆淇璇锋眰鏍囧織涓篺alse */ if (need_repair_num == repair_num) { t_thrd.pagerepair_cxt.page_repair_requested = false; } + return; } +/* + * 鍔熻兘锛氬鐞嗛〉闈慨澶嶇嚎绋嬬殑涓柇璇锋眰 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庡鐞嗘潵鑷搷浣滅郴缁熸垨鍏朵粬杩涚▼鐨勪腑鏂姹傦紝鍖呮嫭SIGHUP鍜宻hutdown璇锋眰銆 + */ static void PageRepairHandleInterrupts(void) { + /* 妫鏌ユ槸鍚︽敹鍒颁簡SIGHUP淇″彿 */ if (t_thrd.pagerepair_cxt.got_SIGHUP) { t_thrd.pagerepair_cxt.got_SIGHUP = false; + + /* 閲嶆柊鍔犺浇閰嶇疆鏂囦欢 */ ProcessConfigFile(PGC_SIGHUP); } + /* 妫鏌ユ槸鍚︽敹鍒颁簡shutdown璇锋眰涓斿惎鍔ㄨ繘绋嬪凡缁忛鍑 */ if (t_thrd.pagerepair_cxt.shutdown_requested && g_instance.pid_cxt.StartupPID == 0) { ereport(LOG, (errmodule(MOD_REDO), errmsg("pagerepair thread shut down"))); + /* 璁剧疆ExitOnAnyError鏍囧織涓簍rue锛岀劧鍚庨鍑虹嚎绋 */ u_sess->attr.attr_common.ExitOnAnyError = true; proc_exit(0); } } +/* + * 鍔熻兘锛氶〉闈慨澶嶇嚎绋嬬殑涓诲嚱鏁 + */ void PageRepairMain(void) { MemoryContext pagerepair_context; char name[MAX_THREAD_NAME_LEN] = {0}; uint32 rc = 0; + /* 璁剧疆绾跨▼瑙掕壊涓篜AGEREPAIR_THREAD */ t_thrd.role = PAGEREPAIR_THREAD; + /* 璁剧疆椤甸潰淇绾跨▼鐨勪俊鍙峰鐞嗛挬瀛 */ SetupPageRepairSignalHook(); /* We allow SIGQUIT (quickdie) at all times */ (void)sigdelset(&t_thrd.libpq_cxt.BlockSig, SIGQUIT); + /* 璁板綍椤甸潰淇绾跨▼宸插惎鍔 */ ereport(LOG, (errmodule(MOD_REDO), errmsg("pagerepair started"))); /* * Create a resource owner to keep track of our resources (currently only * buffer pins). */ - errno_t err_rc = snprintf_s( - name, MAX_THREAD_NAME_LEN, MAX_THREAD_NAME_LEN - 1, "%s", "PageRepair"); + errno_t err_rc = snprintf_s(name, MAX_THREAD_NAME_LEN, MAX_THREAD_NAME_LEN - 1, "%s", "PageRepair"); securec_check_ss(err_rc, "", ""); - t_thrd.utils_cxt.CurrentResourceOwner = ResourceOwnerCreate(NULL, name, - THREAD_GET_MEM_CXT_GROUP(MEMORY_CONTEXT_STORAGE)); + t_thrd.utils_cxt.CurrentResourceOwner = + ResourceOwnerCreate(NULL, name, THREAD_GET_MEM_CXT_GROUP(MEMORY_CONTEXT_STORAGE)); /* * Create a memory context that we will do all our work in. We do this so @@ -526,8 +696,8 @@ void PageRepairMain(void) * possible memory leaks. Formerly this code just ran in * TopMemoryContext, but resetting that would be a really bad idea. */ - pagerepair_context = AllocSetContextCreate( - TopMemoryContext, name, ALLOCSET_DEFAULT_MINSIZE, ALLOCSET_DEFAULT_INITSIZE, ALLOCSET_DEFAULT_MAXSIZE); + pagerepair_context = AllocSetContextCreate(TopMemoryContext, name, ALLOCSET_DEFAULT_MINSIZE, + ALLOCSET_DEFAULT_INITSIZE, ALLOCSET_DEFAULT_MAXSIZE); (void)MemoryContextSwitchTo(pagerepair_context); /* @@ -536,12 +706,14 @@ void PageRepairMain(void) gs_signal_setmask(&t_thrd.libpq_cxt.UnBlockSig, NULL); (void)gs_signal_unblock_sigusr2(); + /* 鎶ュ憡绾跨▼鐨勫簲鐢ㄧ▼搴忓悕绉板拰鐘舵 */ pgstat_report_appname("PageRepair"); pgstat_report_activity(STATE_IDLE, NULL); /* * Loop forever */ + /* 杩涘叆鏃犻檺寰幆锛屽鐞嗛〉闈慨澶嶄换鍔 */ for (;;) { PageRepairHandleInterrupts(); pgstat_report_activity(STATE_IDLE, NULL); @@ -552,6 +724,7 @@ void PageRepairMain(void) ResetLatch(&t_thrd.proc->procLatch); pgstat_report_activity(STATE_RUNNING, NULL); + /* 濡傛灉娌℃湁鏀跺埌shutdown璇锋眰锛屽垯杩涜杩滅▼璇诲彇椤甸潰鍜屾枃浠舵搷浣 */ if (!t_thrd.pagerepair_cxt.shutdown_requested) { SeqRemoteReadPage(); SeqRemoteReadFile(); @@ -559,73 +732,92 @@ void PageRepairMain(void) } } +/* + * 鍔熻兘锛氳缃〉闈慨澶嶇嚎绋嬬殑淇″彿澶勭悊閽╁瓙 + */ static void SetupPageRepairSignalHook(void) { /* - * Reset some signals that are accepted by postmaster but not here + * 閲嶇疆涓浜涗俊鍙凤紝杩欎簺淇″彿琚玴ostmaster鎺ュ彈锛屼絾鍦ㄦ澶勪笉闇瑕 */ - (void)gspqsignal(SIGHUP, PageRepairSigHupHandler); - (void)gspqsignal(SIGINT, SIG_IGN); - (void)gspqsignal(SIGTERM, PageRepairShutDownHandler); - (void)gspqsignal(SIGQUIT, PageRepairQuickDie); /* hard crash time */ - (void)gspqsignal(SIGALRM, SIG_IGN); - (void)gspqsignal(SIGPIPE, SIG_IGN); - (void)gspqsignal(SIGUSR1, PageRepairSigUsr1Handler); - (void)gspqsignal(SIGUSR2, PageRepairSigUsr2Handler); + (void)gspqsignal(SIGHUP, PageRepairSigHupHandler); /* 閲嶆柊璇诲彇閰嶇疆鏂囦欢 */ + (void)gspqsignal(SIGINT, SIG_IGN); /* 蹇界暐涓柇淇″彿 */ + (void)gspqsignal(SIGTERM, PageRepairShutDownHandler); /* 鍏抽棴绾跨▼ */ + (void)gspqsignal(SIGQUIT, PageRepairQuickDie); /* 寮哄埗宕╂簝 */ + (void)gspqsignal(SIGALRM, SIG_IGN); /* 蹇界暐闂归挓淇″彿 */ + (void)gspqsignal(SIGPIPE, SIG_IGN); /* 蹇界暐绠¢亾淇″彿 */ + (void)gspqsignal(SIGUSR1, PageRepairSigUsr1Handler); /* 鐢ㄦ埛鑷畾涔変俊鍙1 */ + (void)gspqsignal(SIGUSR2, PageRepairSigUsr2Handler); /* 鐢ㄦ埛鑷畾涔変俊鍙2 */ /* - * Reset some signals that are accepted by postmaster but not here + * 閲嶇疆涓浜涗俊鍙凤紝杩欎簺淇″彿琚玴ostmaster鎺ュ彈锛屼絾鍦ㄦ澶勪笉闇瑕 */ - (void)gspqsignal(SIGCHLD, SIG_DFL); - (void)gspqsignal(SIGTTIN, SIG_DFL); - (void)gspqsignal(SIGTTOU, SIG_DFL); - (void)gspqsignal(SIGCONT, SIG_DFL); - (void)gspqsignal(SIGWINCH, SIG_DFL); + (void)gspqsignal(SIGCHLD, SIG_DFL); /* 瀛愯繘绋嬬姸鎬佹敼鍙 */ + (void)gspqsignal(SIGTTIN, SIG_DFL); /* 鍚庡彴杩涚▼缁勪腑鐨勫瓙杩涚▼璇锋眰璇 */ + (void)gspqsignal(SIGTTOU, SIG_DFL); /* 鍚庡彴杩涚▼缁勪腑鐨勫瓙杩涚▼璇锋眰鍐 */ + (void)gspqsignal(SIGCONT, SIG_DFL); /* 缁х画鍋滄鐨勮繘绋 */ + (void)gspqsignal(SIGWINCH, SIG_DFL); /* 绐楀彛灏哄璋冩暣 */ } +/* + * 鍔熻兘锛氬鐞哠IGUSR1淇″彿鐨勫鐞嗗嚱鏁 + */ static void PageRepairSigUsr1Handler(SIGNAL_ARGS) { int save_errno = errno; + /* 璁剧疆椤甸潰淇璇锋眰鏍囧織涓簍rue */ t_thrd.pagerepair_cxt.page_repair_requested = true; if (t_thrd.proc) { - SetLatch(&t_thrd.proc->procLatch); + SetLatch(&t_thrd.proc->procLatch); // 鍞ら啋杩涚▼ } errno = save_errno; } +/* + * 鍔熻兘锛氬鐞哠IGUSR2淇″彿鐨勫鐞嗗嚱鏁 + */ static void PageRepairSigUsr2Handler(SIGNAL_ARGS) { int save_errno = errno; + /* 璁剧疆鏂囦欢淇璇锋眰鏍囧織涓簍rue */ t_thrd.pagerepair_cxt.file_repair_requested = true; if (t_thrd.proc) { - SetLatch(&t_thrd.proc->procLatch); + SetLatch(&t_thrd.proc->procLatch); // 鍞ら啋杩涚▼ } errno = save_errno; } +/* + * 鍔熻兘锛氬鐞哠IGHUP淇″彿鐨勫鐞嗗嚱鏁 + */ static void PageRepairSigHupHandler(SIGNAL_ARGS) { int save_errno = errno; + /* 璁剧疆鎺ユ敹鍒癝IGHUP淇″彿鐨勬爣蹇椾负true */ t_thrd.pagerepair_cxt.got_SIGHUP = true; if (t_thrd.proc) { - SetLatch(&t_thrd.proc->procLatch); + SetLatch(&t_thrd.proc->procLatch); // 鍞ら啋杩涚▼ } errno = save_errno; } +/* + * 鍔熻兘锛氬鐞嗚繘绋嬪叧闂姹傜殑澶勭悊鍑芥暟 + */ static void PageRepairShutDownHandler(SIGNAL_ARGS) { int save_errno = errno; + /* 璁剧疆杩涚▼鍏抽棴璇锋眰鐨勬爣蹇椾负true */ t_thrd.pagerepair_cxt.shutdown_requested = true; if (t_thrd.proc) { - SetLatch(&t_thrd.proc->procLatch); + SetLatch(&t_thrd.proc->procLatch); // 鍞ら啋杩涚▼ } errno = save_errno; @@ -658,16 +850,39 @@ static void PageRepairQuickDie(SIGNAL_ARGS) /* recovery thread function */ -bool PushBadPageToRemoteHashTbl(RepairBlockKey key, PageErrorType error_type, XLogRecPtr old_lsn, - XLogPhyBlock pblk, ThreadId tid) +/* + * 鍔熻兘锛氬皢鎹熷潖鐨勯〉闈俊鎭坊鍔犲埌杩滅▼鍝堝笇琛ㄤ腑锛屽鏋滄湭鎵惧埌鍒欐坊鍔狅紝鍚屾椂鍞ら啋椤典慨澶嶇嚎绋 + * + * 鍙傛暟鍒楄〃锛 + * key锛氭崯鍧忛〉闈㈢殑鏍囪瘑閿 + * error_type锛氭崯鍧忛〉闈㈢殑閿欒绫诲瀷 + * old_lsn锛氭棫鐨凩SN锛堟棩蹇楀簭鍒楀彿锛 + * pblk锛氱墿鐞嗗潡淇℃伅 + * tid锛氱嚎绋婭D + * + * 杩斿洖鍊硷細濡傛灉宸叉壘鍒扮浉鍚岄敭鐨勬潯鐩紝鍒欒繑鍥瀟rue锛屽惁鍒欒繑鍥瀎alse + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁板皢椤甸潰鐨勬崯鍧忎俊鎭坊鍔犲埌杩滅▼鍝堝笇琛ㄤ腑锛屽苟鍞ら啋椤典慨澶嶇嚎绋嬫潵澶勭悊椤甸潰銆 + */ + +bool PushBadPageToRemoteHashTbl(RepairBlockKey key, PageErrorType error_type, XLogRecPtr old_lsn, XLogPhyBlock pblk, + ThreadId tid) { + // 鑾峰彇椤甸潰淇鐨勫搱甯岃〃鍜屽垵濮嬪寲found鏍囧織 HTAB *repair_hash = g_instance.repair_cxt.page_repair_hashtbl; bool found = false; + // 鏂█淇鍝堝笇琛ㄤ笉涓虹┖ Assert(repair_hash != NULL); + // 鑾峰彇椤甸潰淇鍝堝笇琛ㄧ殑閿 LWLockAcquire(g_instance.repair_cxt.page_repair_hashtbl_lock, LW_EXCLUSIVE); - RepairBlockEntry *entry = (RepairBlockEntry*)hash_search(repair_hash, &(key), HASH_ENTER, &found); + + // 鍦ㄥ搱甯岃〃涓煡鎵鹃〉闈 + RepairBlockEntry *entry = (RepairBlockEntry *)hash_search(repair_hash, &(key), HASH_ENTER, &found); + + // 濡傛灉鏈壘鍒伴〉闈紝鍒欐坊鍔犱俊鎭埌鍝堝笇琛ㄤ腑 if (!found) { entry->key = key; entry->recovery_tid = tid; @@ -677,14 +892,21 @@ bool PushBadPageToRemoteHashTbl(RepairBlockKey key, PageErrorType error_type, XL entry->page_new_lsn = InvalidXLogRecPtr; entry->pblk = pblk; } + + // 閲婃斁椤甸潰淇鍝堝笇琛ㄧ殑閿 LWLockRelease(g_instance.repair_cxt.page_repair_hashtbl_lock); + // 濡傛灉鏈壘鍒伴〉闈紝鍒欓渶瑕佹坊鍔犲埌鏁扮粍骞跺敜閱掗〉淇绾跨▼ if (!found) { - /* need add array and wakeup the page repair thread */ + // 鑾峰彇椤典慨澶嶇嚎绋嬬殑杩涚▼ID ThreadId PageRepairPID = g_instance.pid_cxt.PageRepairPID; + + // 濡傛灉椤典慨澶嶇嚎绋嬬殑杩涚▼ID涓嶄负绌猴紝鍒欏悜鍏跺彂閫丼IGUSR1淇″彿浠ュ敜閱掑畠 if (PageRepairPID != 0) { (void)gs_signal_send(PageRepairPID, SIGUSR1); } + + // 濡傛灉淇杩涚▼鐨刲atch涓嶄负绌猴紝鍒欒缃畠浠ラ氱煡椤典慨澶嶇嚎绋 if (g_instance.repair_cxt.repair_proc_latch != NULL) { SetLatch(g_instance.repair_cxt.repair_proc_latch); } @@ -693,8 +915,26 @@ bool PushBadPageToRemoteHashTbl(RepairBlockKey key, PageErrorType error_type, XL return found; } -bool BlockNodeMatch(RepairBlockKey key, XLogPhyBlock pblk, RelFileNode node, - ForkNumber forknum, BlockNumber minblkno, bool segment_shrink) +/* + * 鍔熻兘锛氭鏌ュ潡鐨勬爣璇嗛敭銆佺墿鐞嗗潡淇℃伅銆佸叧鑱旀枃浠惰妭鐐广佸垎鏀彿鍜屽潡鍙锋槸鍚﹀尮閰 + * + * 鍙傛暟鍒楄〃锛 + * key锛氬潡鐨勬爣璇嗛敭 + * pblk锛氱墿鐞嗗潡淇℃伅 + * node锛氬叧鑱旀枃浠惰妭鐐 + * forknum锛氬垎鏀彿 + * minblkno锛氭渶灏忓潡鍙 + * segment_shrink锛氭爣蹇椾綅锛屾寚绀烘槸鍚﹁繘琛屽垎娈垫敹缂 + * + * 杩斿洖鍊硷細濡傛灉鍖归厤鍒欒繑鍥瀟rue锛屽惁鍒欒繑鍥瀎alse + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁版鏌ュ潡鐨勬爣璇嗛敭銆佺墿鐞嗗潡淇℃伅銆佸叧鑱旀枃浠惰妭鐐广佸垎鏀彿鍜屽潡鍙锋槸鍚﹀尮閰嶏紝 + * 濡傛灉 segment_shrink 涓 true锛屽垯浼氬皢鍧楃殑 relNode 鏇存柊涓虹墿鐞嗗潡鐨 relNode銆 + * 瀵逛簬 bucket 鏂囦欢鑺傜偣锛屽嚱鏁颁細浣跨敤 RelFileNodeEquals 妫鏌ユ枃浠惰妭鐐规槸鍚︾浉绛夈 + */ +bool BlockNodeMatch(RepairBlockKey key, XLogPhyBlock pblk, RelFileNode node, ForkNumber forknum, BlockNumber minblkno, + bool segment_shrink) { if (segment_shrink) { RelFileNode rnode = key.relfilenode; @@ -708,14 +948,31 @@ bool BlockNodeMatch(RepairBlockKey key, XLogPhyBlock pblk, RelFileNode node, } } +/* + * 鍔熻兘锛氭鏌ュ叧鑱旀枃浠惰妭鐐圭殑鐗瑰畾鍒嗗尯鑺傜偣鍜屾暟鎹簱鑺傜偣鏄惁鍖归厤 + * + * 鍙傛暟鍒楄〃锛 + * rnode锛氬叧鑱旀枃浠惰妭鐐 + * spcNode锛氭湡鏈涚殑鍒嗗尯鑺傜偣锛堝彲閫夛級 + * dbNode锛氭湡鏈涚殑鏁版嵁搴撹妭鐐癸紙鍙夛級 + * + * 杩斿洖鍊硷細濡傛灉鍒嗗尯鑺傜偣鍜屾暟鎹簱鑺傜偣鍖归厤鍒欒繑鍥瀟rue锛屽惁鍒欒繑鍥瀎alse + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁版鏌ュ叧鑱旀枃浠惰妭鐐圭殑鍒嗗尯鑺傜偣鍜屾暟鎹簱鑺傜偣鏄惁涓庣粰瀹氱殑 spcNode 鍜 dbNode 鍖归厤銆 + * 濡傛灉 spcNode 鎴 dbNode 涓烘湁鏁堝硷紝骞朵笖涓庡叧鑱旀枃浠惰妭鐐逛笉鍖归厤锛屽垯杩斿洖 false銆 + */ bool dbNodeandSpcNodeMatch(RelFileNode *rnode, Oid spcNode, Oid dbNode) { + // 濡傛灉 spcNode 涓烘湁鏁堝间笖涓庡叧鑱旀枃浠惰妭鐐圭殑鍒嗗尯鑺傜偣涓嶅尮閰嶏紝鍒欒繑鍥 false銆 if (OidIsValid(spcNode) && rnode->spcNode != spcNode) { return false; } + // 濡傛灉 dbNode 涓烘湁鏁堝间笖涓庡叧鑱旀枃浠惰妭鐐圭殑鏁版嵁搴撹妭鐐逛笉鍖归厤锛屽垯杩斿洖 false銆 if (OidIsValid(dbNode) && rnode->dbNode != dbNode) { return false; } + // 濡傛灉鍒嗗尯鑺傜偣鍜屾暟鎹簱鑺傜偣閮藉尮閰嶏紝鍒欒繑鍥 true銆 return true; } @@ -723,24 +980,43 @@ bool dbNodeandSpcNodeMatch(RelFileNode *rnode, Oid spcNode, Oid dbNode) * drop database, or drop segmentspace, need clear the page repair hashTbl, * if the repair page key dbNode match and spcNode match, need remove. */ +/* + * 鍔熻兘锛氭壒閲忔竻闄ら〉淇鍝堝笇琛ㄤ腑涓庣粰瀹氱殑鍒嗗尯鑺傜偣鍜屾暟鎹簱鑺傜偣鍖归厤鐨勬潯鐩 + * + * 鍙傛暟鍒楄〃锛 + * spcNode锛氭湡鏈涚殑鍒嗗尯鑺傜偣 + * dbNode锛氭湡鏈涚殑鏁版嵁搴撹妭鐐 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庢壒閲忔竻闄ら〉淇鍝堝笇琛ㄤ腑涓庣粰瀹氬垎鍖鸿妭鐐瑰拰鏁版嵁搴撹妭鐐瑰尮閰嶇殑鏉$洰銆 + */ void BatchClearPageRepairHashTbl(Oid spcNode, Oid dbNode) { + // 鑾峰彇椤典慨澶嶅搱甯岃〃 HTAB *repair_hash = g_instance.repair_cxt.page_repair_hashtbl; bool found = false; RepairBlockEntry *entry = NULL; HASH_SEQ_STATUS status; + // 鑾峰彇椤典慨澶嶅搱甯岃〃閿侊紙鐙崰妯″紡锛 LWLockAcquire(g_instance.repair_cxt.page_repair_hashtbl_lock, LW_EXCLUSIVE); + // 鍒濆鍖栧搱甯岃〃搴忓垪鎵弿鐘舵 hash_seq_init(&status, repair_hash); + + // 寰幆鎵弿鍝堝笇琛ㄤ腑鐨勬瘡涓潯鐩 while ((entry = (RepairBlockEntry *)hash_seq_search(&status)) != NULL) { + // 濡傛灉鏁版嵁搴撹妭鐐瑰拰鍒嗗尯鑺傜偣鍖归厤锛屽垯鍒犻櫎璇ユ潯鐩 if (dbNodeandSpcNodeMatch(&(entry->key.relfilenode), spcNode, dbNode)) { + // 鍒犻櫎鍖归厤鐨勬潯鐩 if (hash_search(repair_hash, &(entry->key), HASH_REMOVE, &found) == NULL) { + // 濡傛灉鍒犻櫎鎿嶄綔澶辫触锛屾姤鍛婃暟鎹崯鍧忛敊璇 ereport(ERROR, (errcode(ERRCODE_DATA_CORRUPTED), errmsg("page repair hash table corrupted"))); } } } + // 閲婃斁椤典慨澶嶅搱甯岃〃閿 LWLockRelease(g_instance.repair_cxt.page_repair_hashtbl_lock); return; @@ -750,25 +1026,45 @@ void BatchClearPageRepairHashTbl(Oid spcNode, Oid dbNode) * drop table, or truncate table, need clear the page repair hashTbl, if the * repair page Filenode match need remove. */ -void ClearPageRepairHashTbl(const RelFileNode &node, ForkNumber forknum, BlockNumber minblkno, - bool segment_shrink) +/* + * 鍔熻兘锛氭竻闄ら〉淇鍝堝笇琛ㄤ腑涓庣粰瀹氭潯浠跺尮閰嶇殑鏉$洰 + * + * 鍙傛暟鍒楄〃锛 + * node锛氬叧鑱旀枃浠剁殑RelFileNode + * forknum锛氬叧鑱旀枃浠剁殑ForkNumber + * minblkno锛氭渶灏忓潡鍙凤紝鍖归厤鐨勫潡鍙峰ぇ浜庢垨绛変簬姝ゅ + * segment_shrink锛氭槸鍚﹀湪娈电缉灏忔湡闂 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庢竻闄ら〉淇鍝堝笇琛ㄤ腑涓庣粰瀹氭潯浠跺尮閰嶇殑鏉$洰銆 + */ +void ClearPageRepairHashTbl(const RelFileNode &node, ForkNumber forknum, BlockNumber minblkno, bool segment_shrink) { + // 鑾峰彇椤典慨澶嶅搱甯岃〃 HTAB *repair_hash = g_instance.repair_cxt.page_repair_hashtbl; bool found = false; RepairBlockEntry *entry = NULL; HASH_SEQ_STATUS status; + // 鑾峰彇椤典慨澶嶅搱甯岃〃閿侊紙鐙崰妯″紡锛 LWLockAcquire(g_instance.repair_cxt.page_repair_hashtbl_lock, LW_EXCLUSIVE); + // 鍒濆鍖栧搱甯岃〃搴忓垪鎵弿鐘舵 hash_seq_init(&status, repair_hash); + + // 寰幆鎵弿鍝堝笇琛ㄤ腑鐨勬瘡涓潯鐩 while ((entry = (RepairBlockEntry *)hash_seq_search(&status)) != NULL) { + // 濡傛灉鏉′欢鍖归厤锛屽垯鍒犻櫎璇ユ潯鐩 if (BlockNodeMatch(entry->key, entry->pblk, node, forknum, minblkno, segment_shrink)) { + // 鍒犻櫎鍖归厤鐨勬潯鐩 if (hash_search(repair_hash, &(entry->key), HASH_REMOVE, &found) == NULL) { + // 濡傛灉鍒犻櫎鎿嶄綔澶辫触锛屾姤鍛婃暟鎹崯鍧忛敊璇 ereport(ERROR, (errcode(ERRCODE_DATA_CORRUPTED), errmsg("page repair hash table corrupted"))); } } } + // 閲婃斁椤典慨澶嶅搱甯岃〃閿 LWLockRelease(g_instance.repair_cxt.page_repair_hashtbl_lock); return; @@ -777,21 +1073,37 @@ void ClearPageRepairHashTbl(const RelFileNode &node, ForkNumber forknum, BlockNu /* ClearSpecificsPageRepairHashTbl * If the page repair finish, need clear the page repair hashTbl. */ +/* + * 鍔熻兘锛氭竻闄ら〉淇鍝堝笇琛ㄤ腑涓庣粰瀹氭潯浠跺尮閰嶇殑鐗瑰畾鏉$洰 + * + * 鍙傛暟鍒楄〃锛 + * key锛氳鍒犻櫎鐨勭壒瀹氭潯浠剁殑RepairBlockKey + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庝粠椤典慨澶嶅搱甯岃〃涓垹闄や笌缁欏畾鏉′欢鍖归厤鐨勭壒瀹氭潯鐩 + */ void ClearSpecificsPageRepairHashTbl(RepairBlockKey key) { + // 鍒濆鍖栨槸鍚︽壘鍒板尮閰嶆潯鐩殑鏍囧織 bool found = false; + // 鑾峰彇椤典慨澶嶅搱甯岃〃 HTAB *repair_hash = g_instance.repair_cxt.page_repair_hashtbl; + // 鑾峰彇椤典慨澶嶅搱甯岃〃閿侊紙鐙崰妯″紡锛 LWLockAcquire(g_instance.repair_cxt.page_repair_hashtbl_lock, LW_EXCLUSIVE); - if ((RepairBlockEntry*)hash_search(repair_hash, &(key), HASH_REMOVE, &found) == NULL) { + // 灏濊瘯浠庡搱甯岃〃涓垹闄ゅ叿鏈夌粰瀹氭潯浠剁殑鐗瑰畾鏉$洰 + if ((RepairBlockEntry *)hash_search(repair_hash, &(key), HASH_REMOVE, &found) == NULL) { + // 濡傛灉娌℃湁鎵惧埌鍖归厤鐨勬潯鐩紝鍙戝嚭璀﹀憡 ereport(WARNING, - (errmsg("the %u/%u/%u bucketnode %d forknum %u, blknum %u, remove form repair hashtbl, not found", - key.relfilenode.spcNode, key.relfilenode.dbNode, key.relfilenode.relNode, key.relfilenode.bucketNode, - key.forknum, key.blocknum))); + (errmsg("the %u/%u/%u bucketnode %d forknum %u, blknum %u, remove form repair hashtbl, not found", + key.relfilenode.spcNode, key.relfilenode.dbNode, key.relfilenode.relNode, + key.relfilenode.bucketNode, key.forknum, key.blocknum))); } + // 閲婃斁椤典慨澶嶅搱甯岃〃閿 LWLockRelease(g_instance.repair_cxt.page_repair_hashtbl_lock); + return; } @@ -799,73 +1111,123 @@ void ClearSpecificsPageRepairHashTbl(RepairBlockKey key) * recovery thread check the primary page lsn (page_new_lsn) is in the range * from record_min_lsn to record_max_lsn, */ +/* + * 鍔熻兘锛氭鏌ヤ慨澶嶉〉闈㈡槸鍚﹀湪鎸囧畾鐨凩SN鑼冨洿鍐咃紝骞惰繑鍥炴槸鍚﹀彲浠ユ仮澶嶉〉闈 + * + * 鍙傛暟鍒楄〃锛 + * key锛氱敤浜庢煡鎵句慨澶嶉〉闈㈢殑RepairBlockKey + * min_lsn锛氳姣旇緝鐨勬渶灏廘SN锛堟棩蹇楀簭鍒楀彿锛 + * max_lsn锛氳姣旇緝鐨勬渶澶SN锛堟棩蹇楀簭鍒楀彿锛 + * page锛氱敤浜庡瓨鍌ㄤ慨澶嶉〉闈㈠唴瀹圭殑缂撳啿鍖 + * + * 杩斿洖鍊硷細濡傛灉淇椤甸潰鍦↙SN鑼冨洿鍐呬笖鍙互鎭㈠锛屽垯杩斿洖true锛屽惁鍒欒繑鍥瀎alse + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庢鏌ヤ慨澶嶉〉闈㈡槸鍚﹀湪鎸囧畾鐨凩SN鑼冨洿鍐咃紝骞惰繑鍥炴槸鍚﹀彲浠ユ仮澶嶉〉闈€ + */ bool CheckRepairPage(RepairBlockKey key, XLogRecPtr min_lsn, XLogRecPtr max_lsn, char *page) { + // 鍒濆鍖栨槸鍚︽壘鍒板尮閰嶆潯鐩殑鏍囧織 bool found = false; + // 鍒濆鍖栨槸鍚﹀彲浠ユ仮澶嶉〉闈㈢殑鏍囧織 bool can_recovery = false; + // 鐢ㄤ簬瀛樺偍鏌ユ壘鍒扮殑淇椤甸潰鏉$洰 RepairBlockEntry *entry = NULL; + // 鑾峰彇椤典慨澶嶅搱甯岃〃 HTAB *repair_hash = g_instance.repair_cxt.page_repair_hashtbl; + // 鑾峰彇椤典慨澶嶅搱甯岃〃閿侊紙鐙崰妯″紡锛 LWLockAcquire(g_instance.repair_cxt.page_repair_hashtbl_lock, LW_EXCLUSIVE); - entry = (RepairBlockEntry*)hash_search(repair_hash, &(key), HASH_FIND, &found); + // 灏濊瘯浠庡搱甯岃〃涓煡鎵惧叿鏈夌粰瀹氭潯浠剁殑淇椤甸潰鏉$洰 + entry = (RepairBlockEntry *)hash_search(repair_hash, &(key), HASH_FIND, &found); if (entry == NULL) { + // 濡傛灉娌℃湁鎵惧埌鍖归厤鐨勬潯鐩紝鍙戝嚭閿欒娑堟伅骞舵姤鍛婂搱甯岃〃鎹熷潖 ereport(ERROR, (errmsg("the page repair hash table corrupted "))); } - /* the page_new_lsn is in the range from record_min_lsn to record_max_lsn */ + // 濡傛灉淇椤甸潰鐨勭姸鎬佷负绛夊緟淇锛屽苟涓斿叾LSN鍦ㄦ寚瀹氱殑鑼冨洿鍐 if (entry->page_state == WAIT_REPAIR && entry->page_new_lsn <= max_lsn && entry->page_new_lsn >= min_lsn) { + // 澶嶅埗淇椤甸潰鐨勫唴瀹瑰埌鎻愪緵鐨勭紦鍐插尯 errno_t rc; can_recovery = true; rc = memcpy_s(page, BLCKSZ, entry->page_content, BLCKSZ); securec_check(rc, "", ""); } + + // 閲婃斁椤典慨澶嶅搱甯岃〃閿 LWLockRelease(g_instance.repair_cxt.page_repair_hashtbl_lock); + // 杩斿洖鏄惁鍙互鎭㈠椤甸潰鐨勬爣蹇 return can_recovery; } +/* + * 鍔熻兘锛氱瓑寰呴噸鏀惧畬鎴 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庣瓑寰呴噸鏀惧畬鎴愶紝鏍规嵁褰撳墠閲嶅仛鏂瑰紡閲囩敤涓嶅悓鐨勭瓑寰呯瓥鐣ャ + * 濡傛灉鏄瀬绔噸鍋氾紙Extreme Redo锛夛紝绛夊緟鎵鏈夐噸鏀惧伐浣滆呯┖闂层 + * 濡傛灉鏄苟琛岄噸鍋氾紙Parallel Redo锛夛紝绛夊緟鎵鏈夐〉闈㈠伐浣滆呴槦鍒椾负绌恒 + * 鍚﹀垯锛岀瓑寰呬富鏈烘鍦ㄩ噸鏀剧殑LSN杩借刀鎸傝捣鐨凩SN锛岀劧鍚庣户缁 + */ void WaitRepalyFinish() { - /* file repair finish, need clean the invalid page */ + /* 濡傛灉鏄瀬绔噸鍋氾紝绛夊緟鎵鏈夐噸鏀惧伐浣滆呯┖闂 */ if (IsExtremeRedo()) { extreme_rto::WaitAllReplayWorkerIdle(); - } else if (IsParallelRedo()) { + } + /* 濡傛灉鏄苟琛岄噸鍋氾紝绛夊緟鎵鏈夐〉闈㈠伐浣滆呴槦鍒椾负绌 */ + else if (IsParallelRedo()) { parallel_recovery::WaitAllPageWorkersQueueEmpty(); - } else { + } + /* 鍚﹀垯锛岀瓑寰呬富鏈烘鍦ㄩ噸鏀剧殑LSN杩借刀鎸傝捣鐨凩SN锛岀劧鍚庣户缁 */ + else { + // 鑾峰彇涓绘満褰撳墠姝e湪閲嶆斁鐨凩SN XLogRecPtr standby_replay_lsn = GetXLogReplayRecPtr(NULL, NULL); + // 鑾峰彇鎸傝捣鐨凩SN XLogRecPtr suspend_lsn = pg_atomic_read_u64(&g_instance.startup_cxt.suspend_lsn); - /* if suspend_lsn > standby_replay_lsn then need wait */ + + /* 濡傛灉鎸傝捣鐨凩SN澶т簬姝e湪閲嶆斁鐨凩SN锛屽垯闇瑕佺瓑寰 */ while (!XLByteLE(suspend_lsn, standby_replay_lsn)) { - /* sleep 1s */ + /* 浼戠湢1绉 */ PageRepairHandleInterrupts(); pg_usleep(1000000L); - /* get current replay lsn again */ + /* 鍐嶆鑾峰彇褰撳墠閲嶆斁鐨凩SN */ (void)GetXLogReplayRecPtr(NULL, &standby_replay_lsn); } } } const int MAX_REPAIR_FILE_NUM = 20; +/* + * 鍔熻兘锛氬垵濮嬪寲鏂囦欢淇鍝堝笇琛 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庡垵濮嬪寲鏂囦欢淇鍝堝笇琛ㄣ傚鏋滃搱甯岃〃鏈垱寤猴紝鍒欐牴鎹厤缃垱寤哄搱甯岃〃銆 + * 鍝堝笇琛ㄤ互RepairFileKey涓洪敭锛孯epairFileEntry涓哄艰繘琛岃闂 + */ void FileRepairHashTblInit(void) { HASHCTL ctl; + // 濡傛灉鏂囦欢淇鍝堝笇琛ㄧ殑閿佷负绌猴紝鍒嗛厤涓涓攣 if (g_instance.repair_cxt.file_repair_hashtbl_lock == NULL) { g_instance.repair_cxt.file_repair_hashtbl_lock = LWLockAssign(LWTRANCHE_FILE_REPAIR); } + // 濡傛灉鏂囦欢淇鍝堝笇琛ㄤ负绌猴紝鏍规嵁閰嶇疆鍒涘缓鍝堝笇琛 if (g_instance.repair_cxt.file_repair_hashtbl == NULL) { - /* hash accessed by database file id */ + /* 浣跨敤鏁版嵁搴撴枃浠禝D杩涜璁块棶鐨勫搱甯岃〃 */ errno_t rc = memset_s(&ctl, sizeof(ctl), 0, sizeof(ctl)); securec_check(rc, "", ""); ctl.keysize = sizeof(RepairFileKey); ctl.entrysize = sizeof(RepairFileEntry); ctl.hash = tag_hash; ctl.hcxt = INSTANCE_GET_MEM_CXT_GROUP(MEMORY_CONTEXT_STORAGE); - g_instance.repair_cxt.file_repair_hashtbl = hash_create("File Repair Hash Table", MAX_REPAIR_FILE_NUM, &ctl, - HASH_ELEM | HASH_FUNCTION |HASH_CONTEXT); + g_instance.repair_cxt.file_repair_hashtbl = + hash_create("File Repair Hash Table", MAX_REPAIR_FILE_NUM, &ctl, HASH_ELEM | HASH_FUNCTION | HASH_CONTEXT); if (!g_instance.repair_cxt.file_repair_hashtbl) ereport(FATAL, (errmsg("could not initialize file repair Hash table"))); @@ -874,9 +1236,23 @@ void FileRepairHashTblInit(void) return; } +/* + * 鍔熻兘锛氭鏌ユ枃浠朵慨澶嶅搱甯岃〃涓槸鍚﹀瓨鍦ㄧ壒瀹氭潯鐩 + * + * 鍙傛暟鍒楄〃锛 + * rnode锛氭枃浠剁殑鍏崇郴鏂囦欢鑺傜偣锛圧elFileNode锛 + * forknum锛氭枃浠剁殑鍒嗗弶鍙凤紙ForkNumber锛 + * segno锛氭枃浠舵鍙 + * + * 杩斿洖鍊硷細濡傛灉瀛樺湪涓庣粰瀹氬弬鏁板尮閰嶇殑鏉$洰锛屽垯杩斿洖true锛屽惁鍒欒繑鍥瀎alse + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庢鏌ユ枃浠朵慨澶嶅搱甯岃〃涓槸鍚﹀瓨鍦ㄧ壒瀹氱殑鏉$洰銆傚畠浣跨敤鍏崇郴鏂囦欢鑺傜偣銆佸垎鍙夊彿鍜屾鍙蜂綔涓哄叧閿潵鎼滅储鍝堝笇琛ㄣ + * 濡傛灉鎵惧埌鍖归厤鐨勬潯鐩紝灏嗘牴鎹潯鐩殑鐘舵佸垽鏂槸鍚﹁繑鍥瀟rue銆傚鏋滃搱甯岃〃涓虹┖锛屽垯鐩存帴杩斿洖false銆 + */ bool CheckFileRepairHashTbl(RelFileNode rnode, ForkNumber forknum, uint32 segno) { - HTAB* file_hashtbl = g_instance.repair_cxt.file_repair_hashtbl; + HTAB *file_hashtbl = g_instance.repair_cxt.file_repair_hashtbl; RepairFileKey key; RepairFileEntry *entry = NULL; bool found = false; @@ -885,38 +1261,71 @@ bool CheckFileRepairHashTbl(RelFileNode rnode, ForkNumber forknum, uint32 segno) key.forknum = forknum; key.segno = segno; + // 濡傛灉鏂囦欢淇鍝堝笇琛ㄤ负绌猴紝鐩存帴杩斿洖false if (file_hashtbl == NULL) { return found; } + + // 鑾峰彇鏂囦欢淇鍝堝笇琛ㄧ殑鍏变韩閿 LWLockAcquire(FILE_REPAIR_LOCK, LW_SHARED); - entry = (RepairFileEntry*)hash_search(file_hashtbl, &(key), HASH_FIND, &found); + // 浣跨敤鍏抽敭瀛楀湪鍝堝笇琛ㄤ腑鏌ユ壘鏉$洰锛屽苟杩斿洖鏄惁鎵惧埌鐨勬爣蹇 + entry = (RepairFileEntry *)hash_search(file_hashtbl, &(key), HASH_FIND, &found); if (found) { + // 濡傛灉鎵惧埌鍖归厤鐨勬潯鐩紝鏍规嵁鏉$洰鐨勭姸鎬佸垽鏂槸鍚﹁繑鍥瀟rue if (entry->file_state == WAIT_FILE_REPAIR || entry->file_state == WAIT_RENAME) { found = true; } else { found = false; } } + // 閲婃斁鏂囦欢淇鍝堝笇琛ㄧ殑閿 LWLockRelease(FILE_REPAIR_LOCK); return found; } +/* + * 鍔熻兘锛氭鏌ユ槸鍚﹂渶瑕佽褰曞潖鏂囦欢淇℃伅鍒拌繙绋嬪搱甯岃〃 + * + * 鍙傛暟鍒楄〃锛 + * key锛氫慨澶嶆枃浠剁殑鏍囪瘑閿 + * nblock锛氭枃浠剁殑鍧楁暟锛堝彲閫夛級 + * blocknum锛氬潖鍧楃殑鍧楀彿锛堝彲閫夛級 + * pblk锛氱墿鐞嗗潡淇℃伅锛堝彲閫夛級 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庢鏌ユ槸鍚﹂渶瑕佽褰曞潖鏂囦欢淇℃伅鍒拌繙绋嬪搱甯岃〃銆傚畠鍩轰簬澶氫釜鏉′欢鏉ュ喅瀹氭槸鍚︽墽琛岃繖涓搷浣滐紝鍖呮嫭鐗堟湰鏀寔銆佸潡鏁般佹槸鍚︿负涓诲妯″紡銆佹槸鍚︽敮鎸佷慨澶嶇瓑銆 + * 濡傛灉闇瑕佽褰曞潖鏂囦欢淇℃伅锛屽皢璋冪敤PushBadFileToRemoteHashTbl鍑芥暟鏉ュ畬鎴愩 + */ void CheckNeedRecordBadFile(RepairFileKey key, uint32 nblock, uint32 blocknum, const XLogPhyBlock *pblk) { + // 妫鏌ユ槸鍚︽敮鎸佺増鏈紝浠ュ強鏄惁婊¤冻鍏朵粬鏉′欢 if (CheckVerionSupportRepair() && (nblock == 0 || blocknum / RELSEG_SIZE > nblock / RELSEG_SIZE) && IsPrimaryClusterStandbyDN() && g_instance.repair_cxt.support_repair) { + // 濡傛灉鎻愪緵浜嗙墿鐞嗗潡淇℃伅锛屽垯鏇存柊鍏崇郴鏂囦欢鑺傜偣鍜屾鍙 if (pblk != NULL) { key.relfilenode.relNode = pblk->relNode; key.segno = pblk->block / RELSEG_SIZE; } + // 濡傛灉鏄鏂囦欢鑺傜偣锛岃缃産ucketNode涓篠egmentBktId if (IsSegmentFileNode(key.relfilenode)) { key.relfilenode.bucketNode = SegmentBktId; } + // 璋冪敤PushBadFileToRemoteHashTbl鍑芥暟灏嗗潖鏂囦欢淇℃伅璁板綍鍒拌繙绋嬪搱甯岃〃 PushBadFileToRemoteHashTbl(key); } } +/* + * 鍔熻兘锛氬皢鍧忔枃浠朵俊鎭帹閫佸埌杩滅▼鍝堝笇琛 + * + * 鍙傛暟鍒楄〃锛 + * key锛氫慨澶嶆枃浠剁殑鏍囪瘑閿 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庡皢鍧忔枃浠朵俊鎭帹閫佸埌杩滅▼鍝堝笇琛ㄤ腑銆傚畠棣栧厛鑾峰彇鎺у埗鏂囦欢涓殑minRecoveryPoint锛岀劧鍚庡皢鍧忔枃浠剁殑淇℃伅锛堝寘鎷枃浠惰矾寰勩佹鍙风瓑锛夎褰曞埌鍝堝笇琛ㄤ腑锛岀姸鎬佷负绛夊緟鏂囦欢妫鏌ュ拰淇銆 + * 濡傛灉鍝堝笇琛ㄤ腑宸插瓨鍦ㄧ浉鍚岀殑淇鏂囦欢淇℃伅锛屽垯涓嶆墽琛屼换浣曟搷浣溿 + */ static void PushBadFileToRemoteHashTbl(RepairFileKey key) { HTAB *file_hash = g_instance.repair_cxt.file_repair_hashtbl; @@ -924,13 +1333,17 @@ static void PushBadFileToRemoteHashTbl(RepairFileKey key) bool found = false; XLogRecPtr min_recovery_point; + // 鑾峰彇鎺у埗鏂囦欢涓殑minRecoveryPoint LWLockAcquire(ControlFileLock, LW_SHARED); min_recovery_point = t_thrd.shemem_ptr_cxt.ControlFile->minRecoveryPoint; LWLockRelease(ControlFileLock); + // 鑾峰彇鏂囦欢淇鍝堝笇琛ㄧ殑閿 LWLockAcquire(FILE_REPAIR_LOCK, LW_EXCLUSIVE); - entry = (RepairFileEntry*)hash_search(file_hash, &(key), HASH_ENTER, &found); + // 灏濊瘯鍦ㄥ搱甯岃〃涓煡鎵炬寚瀹氱殑淇鏂囦欢淇℃伅 + entry = (RepairFileEntry *)hash_search(file_hash, &(key), HASH_ENTER, &found); if (!found) { + // 濡傛灉鏈壘鍒扮浉鍚岀殑淇鏂囦欢淇℃伅锛屽垯灏嗗叾璁板綍鍒板搱甯岃〃涓 entry->key.relfilenode.relNode = key.relfilenode.relNode; entry->key.relfilenode.dbNode = key.relfilenode.dbNode; entry->key.relfilenode.spcNode = key.relfilenode.spcNode; @@ -942,79 +1355,149 @@ static void PushBadFileToRemoteHashTbl(RepairFileKey key) entry->file_state = WAIT_FILE_CHECK_REPAIR; entry->primary_file_lsn = InvalidXLogRecPtr; + // 璁板綍鏃ュ織锛岃鏄庡凡灏嗗潖鏂囦欢淇℃伅鎺ㄩ佸埌鍝堝笇琛 ereport(LOG, (errmodule(MOD_REDO), - errmsg("[file repair] push to file repair hashtbl, path is %s segno is %u", - relpathperm(entry->key.relfilenode, entry->key.forknum), entry->key.segno))); + errmsg("[file repair] push to file repair hashtbl, path is %s segno is %u", + relpathperm(entry->key.relfilenode, entry->key.forknum), entry->key.segno))); } + // 閲婃斁鏂囦欢淇鍝堝笇琛ㄧ殑閿 LWLockRelease(FILE_REPAIR_LOCK); return; } +/* + * 鍔熻兘锛氭鏌ヤ慨澶嶆枃浠朵俊鎭槸鍚︿笌缁欏畾鍙傛暟鍖归厤 + * + * 鍙傛暟鍒楄〃锛 + * key锛氫慨澶嶆枃浠剁殑鏍囪瘑閿 + * node锛氭枃浠剁殑RelFileNode + * forknum锛氭枃浠剁殑ForkNumber + * segno锛氭鍙 + * + * 杩斿洖鍊硷細濡傛灉淇鏂囦欢淇℃伅涓庣粰瀹氬弬鏁板尮閰嶏紝鍒欒繑鍥瀟rue锛屽惁鍒欒繑鍥瀎alse + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庢鏌ヤ慨澶嶆枃浠朵俊鎭槸鍚︿笌缁欏畾鐨凴elFileNode銆丗orkNumber鍜屾鍙峰尮閰嶃 + * 濡傛灉缁欏畾鐨勬枃浠朵俊鎭笌淇鏂囦欢淇℃伅鍖归厤锛屽垯杩斿洖true锛涘惁鍒欒繑鍥瀎alse銆 + */ bool FileNodeMatch(RepairFileKey key, RelFileNode node, ForkNumber forknum, uint32 segno) { + // 妫鏌ョ粰瀹氱殑RelFileNode鏄惁涓庝慨澶嶆枃浠朵俊鎭腑鐨凴elFileNode鍖归厤 bool node_equal = RelFileNodeRelEquals(node, key.relfilenode); + // 杩斿洖缁撴灉锛歊elFileNode鍖归厤锛孎orkNumber鍖归厤锛屾鍙峰ぇ浜庣瓑浜庣粰瀹氭鍙 return node_equal && key.forknum == forknum && key.segno >= segno; } +/* + * 鍔熻兘锛氭竻闄ゅ潖鏂囦欢鍝堝笇琛ㄤ腑鐨勭壒瀹氭枃浠朵俊鎭 + * + * 鍙傛暟鍒楄〃锛 + * node锛氭枃浠剁殑RelFileNode + * forknum锛氭枃浠剁殑ForkNumber + * segno锛氭鍙 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庢竻闄ゅ潖鏂囦欢鍝堝笇琛ㄤ腑涓庣粰瀹氱殑RelFileNode銆丗orkNumber鍜屾鍙峰尮閰嶇殑鏂囦欢淇℃伅銆 + * 濡傛灉鍖归厤鎴愬姛锛屽皢浠庡搱甯岃〃涓垹闄ょ浉搴旂殑鏂囦欢淇℃伅銆 + */ void ClearBadFileHashTbl(const RelFileNode &node, ForkNumber forknum, uint32 segno) { + // 鑾峰彇鍧忔枃浠跺搱甯岃〃 HTAB *file_hash = g_instance.repair_cxt.file_repair_hashtbl; RepairFileEntry *entry = NULL; bool found = false; HASH_SEQ_STATUS status; + // 鑾峰彇鏂囦欢淇閿佷互鎵ц鍝堝笇琛ㄦ搷浣 LWLockAcquire(FILE_REPAIR_LOCK, LW_EXCLUSIVE); + // 鍒濆鍖栧搱甯岃〃杩唬鍣 hash_seq_init(&status, file_hash); while ((entry = (RepairFileEntry *)hash_seq_search(&status)) != NULL) { + // 濡傛灉缁欏畾鐨勬枃浠朵俊鎭笌鍝堝笇琛ㄤ腑鐨勬煇涓枃浠朵俊鎭尮閰 if (FileNodeMatch(entry->key, node, forknum, segno)) { + // 浠庡搱甯岃〃涓垹闄ゅ尮閰嶇殑鏂囦欢淇℃伅 if (hash_search(file_hash, &(entry->key), HASH_REMOVE, &found) == NULL) { + // 濡傛灉鍒犻櫎鎿嶄綔澶辫触锛岄噴鏀鹃攣骞舵姤鍛婃暟鎹崯鍧忛敊璇 LWLockRelease(FILE_REPAIR_LOCK); ereport(ERROR, (errcode(ERRCODE_DATA_CORRUPTED), errmsg("file repair hash table corrupted"))); } else { + // 濡傛灉鍒犻櫎鎴愬姛锛岃褰曟枃浠朵俊鎭凡鍦ㄥ垹闄よ〃鎴栨埅鏂〃鏃惰绉婚櫎 ereport(LOG, (errmodule(MOD_REDO), - errmsg("[file repair] file %s segno is %u entry remove when drop table or truncate table", - relpathperm(entry->key.relfilenode, entry->key.forknum), entry->key.segno))); + errmsg("[file repair] file %s segno is %u entry remove when drop table or truncate table", + relpathperm(entry->key.relfilenode, entry->key.forknum), entry->key.segno))); } } } + // 閲婃斁鏂囦欢淇閿 LWLockRelease(FILE_REPAIR_LOCK); return; } - +/* + * 鍔熻兘锛氭壒閲忔竻闄ゅ潖鏂囦欢鍝堝笇琛ㄤ腑鐨勬枃浠朵俊鎭 + * + * 鍙傛暟鍒楄〃锛 + * spcNode锛氭暟鎹簱琛ㄧ┖闂磋妭鐐癸紙鍙夛級 + * dbNode锛氭暟鎹簱鑺傜偣锛堝彲閫夛級 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庢壒閲忔竻闄ゅ潖鏂囦欢鍝堝笇琛ㄤ腑涓庣粰瀹氭暟鎹簱琛ㄧ┖闂磋妭鐐瑰拰鏁版嵁搴撹妭鐐瑰尮閰嶇殑鏂囦欢淇℃伅銆 + * 濡傛灉鍖归厤鎴愬姛锛屽皢浠庡搱甯岃〃涓垹闄ょ浉搴旂殑鏂囦欢淇℃伅銆 + */ void BatchClearBadFileHashTbl(Oid spcNode, Oid dbNode) { + // 鑾峰彇鍧忔枃浠跺搱甯岃〃 HTAB *file_hash = g_instance.repair_cxt.file_repair_hashtbl; RepairFileEntry *entry = NULL; bool found = false; HASH_SEQ_STATUS status; + // 鑾峰彇鏂囦欢淇閿佷互鎵ц鍝堝笇琛ㄦ搷浣 LWLockAcquire(FILE_REPAIR_LOCK, LW_EXCLUSIVE); + // 鍒濆鍖栧搱甯岃〃杩唬鍣 hash_seq_init(&status, file_hash); while ((entry = (RepairFileEntry *)hash_seq_search(&status)) != NULL) { + // 濡傛灉缁欏畾鐨勬暟鎹簱琛ㄧ┖闂磋妭鐐瑰拰鏁版嵁搴撹妭鐐瑰尮閰嶅搱甯岃〃涓殑鏌愪釜鏂囦欢淇℃伅 if (dbNodeandSpcNodeMatch(&(entry->key.relfilenode), spcNode, dbNode)) { + // 浠庡搱甯岃〃涓垹闄ゅ尮閰嶇殑鏂囦欢淇℃伅 if (hash_search(file_hash, &(entry->key), HASH_REMOVE, &found) == NULL) { + // 濡傛灉鍒犻櫎鎿嶄綔澶辫触锛岄噴鏀鹃攣骞舵姤鍛婃暟鎹崯鍧忛敊璇 LWLockRelease(FILE_REPAIR_LOCK); ereport(ERROR, (errcode(ERRCODE_DATA_CORRUPTED), errmsg("file repair hash table corrupted"))); } else { - ereport(LOG, (errmodule(MOD_REDO), - errmsg("[file repair] file %s segno is %u entry remove when drop database or segment space", - relpathperm(entry->key.relfilenode, entry->key.forknum), entry->key.segno))); + // 濡傛灉鍒犻櫎鎴愬姛锛岃褰曟枃浠朵俊鎭凡鍦ㄥ垹闄ゆ暟鎹簱鎴栨绌洪棿鏃惰绉婚櫎 + ereport(LOG, + (errmodule(MOD_REDO), + errmsg("[file repair] file %s segno is %u entry remove when drop database or segment space", + relpathperm(entry->key.relfilenode, entry->key.forknum), entry->key.segno))); } } } + // 閲婃斁鏂囦欢淇閿 LWLockRelease(FILE_REPAIR_LOCK); return; } +/* + * 鍔熻兘锛氶噸鍛藉悕淇鏂囦欢 + * + * 鍙傛暟鍒楄〃锛 + * key锛氫慨澶嶆枃浠剁殑鍏抽敭淇℃伅 + * clear_entry锛氭槸鍚︽竻闄ゅ搱甯岃〃涓殑鏂囦欢鏉$洰 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庡皢淇鍚庣殑鏂囦欢閲嶅懡鍚嶅洖鍏跺師濮嬪悕绉般 + * 濡傛灉 clear_entry 涓 true锛屽垯杩樹細浠庡搱甯岃〃涓垹闄ゆ枃浠舵潯鐩 + */ void RenameRepairFile(RepairFileKey *key, bool clear_entry) { + // 澹版槑鍙橀噺 errno_t rc; bool found = false; HTAB *file_hash = g_instance.repair_cxt.file_repair_hashtbl; @@ -1022,32 +1505,35 @@ void RenameRepairFile(RepairFileKey *key, bool clear_entry) char *tempsegpath = (char *)palloc(strlen(path) + SEGLEN); char *segpath = (char *)palloc(strlen(path) + SEGLEN); - /* wait all dirty page flush */ - RequestCheckpoint(CHECKPOINT_FLUSH_DIRTY|CHECKPOINT_WAIT); + // 鎵ц妫鏌ョ偣浠ョ‘淇濇寔涔呮 + RequestCheckpoint(CHECKPOINT_FLUSH_DIRTY | CHECKPOINT_WAIT); + // 鏍规嵁娈靛彿鐢熸垚涓存椂璺緞鍜屾渶缁堣矾寰 if (key->segno == 0) { rc = sprintf_s(segpath, strlen(path) + SEGLEN, "%s", path); - securec_check_ss(rc, "", "") - rc = sprintf_s(tempsegpath, strlen(path) + SEGLEN, "%s.repair", path); + securec_check_ss(rc, "", "") rc = sprintf_s(tempsegpath, strlen(path) + SEGLEN, "%s.repair", path); securec_check_ss(rc, "", "") } else { rc = sprintf_s(segpath, strlen(path) + SEGLEN, "%s.%u", path, key->segno); - securec_check_ss(rc, "", "") - rc = sprintf_s(tempsegpath, strlen(path) + SEGLEN, "%s.%u.repair", path, key->segno); + securec_check_ss(rc, "", "") rc = + sprintf_s(tempsegpath, strlen(path) + SEGLEN, "%s.%u.repair", path, key->segno); securec_check_ss(rc, "", "") } + // 鎵ц鎸佷箙鎬ч噸鍛藉悕鎿嶄綔 rc = durable_rename(tempsegpath, segpath, WARNING); if (rc == 0) { - ereport(LOG, (errmodule(MOD_REDO), - errmsg("[file repair] file rename from %s to %s finish", tempsegpath, segpath))); + ereport(LOG, + (errmodule(MOD_REDO), errmsg("[file repair] file rename from %s to %s finish", tempsegpath, segpath))); - /* file repair finish, need clean the invalid page */ + // 鏍规嵁淇鐨勬枃浠剁被鍨嬫墽琛岀浉搴旀搷浣滐紙Extreme Redo銆丳arallel Redo 鎴栧叾浠栨儏鍐碉級 if (IsExtremeRedo()) { + // 鎵ц鏋佺鎭㈠鎿嶄綔 extreme_rto::DispatchCleanInvalidPageMarkToAllRedoWorker(*key); extreme_rto::DispatchClosefdMarkToAllRedoWorker(); extreme_rto::WaitAllReplayWorkerIdle(); } else if (IsParallelRedo()) { + // 鎵ц骞惰鎭㈠鎿嶄綔 if (AmStartupProcess()) { ProcTxnWorkLoad(true); } @@ -1055,26 +1541,37 @@ void RenameRepairFile(RepairFileKey *key, bool clear_entry) parallel_recovery::SendClosefdMarkToAllWorkers(); parallel_recovery::WaitAllPageWorkersQueueEmpty(); } else { + // 鍏朵粬鎯呭喌锛堟湭鎵ц浠讳綍鎿嶄綔锛 } - forget_range_invalid_pages((void*)key); + + // 蹇樿鏃犳晥椤佃寖鍥 + forget_range_invalid_pages((void *)key); smgrcloseall(); + // 鑾峰彇鏂囦欢淇閿佷互鎵ц鍝堝笇琛ㄦ搷浣 LWLockAcquire(FILE_REPAIR_LOCK, LW_EXCLUSIVE); if (clear_entry) { + // 濡傛灉闇瑕佹竻闄ゅ搱甯岃〃涓殑鏂囦欢鏉$洰 if (hash_search(file_hash, key, HASH_REMOVE, &found) == NULL) { + // 濡傛灉鍒犻櫎鎿嶄綔澶辫触锛岄噴鏀惧唴瀛樺苟鎶ュ憡鏁版嵁鎹熷潖閿欒 pfree(path); pfree(segpath); pfree(tempsegpath); LWLockRelease(FILE_REPAIR_LOCK); ereport(ERROR, (errcode(ERRCODE_DATA_CORRUPTED), errmsg("file repair hash table corrupted"))); } else { + // 濡傛灉鍒犻櫎鎴愬姛锛岃褰曟枃浠朵俊鎭凡鍦ㄥ垹闄ゆ暟鎹簱鎴栨绌洪棿鏃惰绉婚櫎 ereport(LOG, (errmodule(MOD_REDO), - errmsg("[file repair] file %s repair finish, remove the entry", segpath))); + errmsg("[file repair] file %s repair finish, remove the entry", segpath))); } } + + // 閲婃斁鏂囦欢淇閿 LWLockRelease(FILE_REPAIR_LOCK); } + + // 閲婃斁鍐呭瓨 pfree(path); pfree(segpath); pfree(tempsegpath); @@ -1082,8 +1579,15 @@ void RenameRepairFile(RepairFileKey *key, bool clear_entry) return; } +/* + * 鍔熻兘锛氭鏌ユ槸鍚﹂渶瑕侀噸鍛藉悕鏂囦欢 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庢鏌ヤ慨澶嶆枃浠舵槸鍚﹂渶瑕佽繘琛岄噸鍛藉悕锛屼互鍙婃槸鍚﹂渶瑕佽繘琛屽叾浠栨搷浣溿 + */ void CheckNeedRenameFile() { + // 澹版槑鍙橀噺 HASH_SEQ_STATUS status; RepairFileEntry *entry = NULL; HTAB *file_hash = g_instance.repair_cxt.file_repair_hashtbl; @@ -1093,22 +1597,31 @@ void CheckNeedRenameFile() errno_t rc = 0; uint32 i = 0; + // 鑾峰彇鏂囦欢淇閿佷互鎵ц鍝堝笇琛ㄦ搷浣 LWLockAcquire(FILE_REPAIR_LOCK, LW_EXCLUSIVE); hash_seq_init(&status, file_hash); + + // 閬嶅巻鍝堝笇琛ㄤ互璁$畻闇瑕侀噸鍛藉悕鍜岄渶瑕佷慨澶嶇殑鏂囦欢鏁扮洰 while ((entry = (RepairFileEntry *)hash_seq_search(&status)) != NULL) { if (entry->file_state == WAIT_RENAME) { need_rename_num++; } } + + // 濡傛灉鏈夐渶瑕侀噸鍛藉悕鐨勬枃浠讹紝鍒欏垎閰嶉噸鍛藉悕閿殑鍐呭瓨绌洪棿 if (need_rename_num > 0) { - rename_key = (RepairFileKey*)palloc0(sizeof(RepairFileKey) * need_rename_num); + rename_key = (RepairFileKey *)palloc0(sizeof(RepairFileKey) * need_rename_num); } + // 閲嶆柊鍒濆鍖栧搱甯岃〃閬嶅巻鐘舵 hash_seq_init(&status, file_hash); + i = 0; + // 鍐嶆閬嶅巻鍝堝笇琛紝鏍规嵁鏂囦欢鐘舵佹墽琛岀浉搴旀搷浣 while ((entry = (RepairFileEntry *)hash_seq_search(&status)) != NULL) { switch (entry->file_state) { case WAIT_RENAME: + // 濡傛灉鏂囦欢闇瑕侀噸鍛藉悕锛屽垯灏嗗叾璁板綍鍒伴噸鍛藉悕閿暟缁勪腑 Assert(XLByteLE(entry->primary_file_lsn, GetXLogReplayRecPtr(NULL, NULL))); Assert(!IsSegmentFileNode(entry->key.relfilenode)); rc = memcpy_s(&rename_key[i], sizeof(RepairFileKey), &(entry->key), sizeof(RepairFileKey)); @@ -1117,45 +1630,56 @@ void CheckNeedRenameFile() break; case WAIT_FILE_REMOTE_READ: case WAIT_FILE_REPAIR_SEGMENT: + // 濡傛灉鏂囦欢闇瑕佽繘琛岃繙绋嬭鍙栨垨娈典慨澶嶏紝鍒欏鍔犻渶瑕佷慨澶嶇殑鏂囦欢鏁扮洰 need_repair_num++; break; case WAIT_FOREGT_INVALID_PAGE: - { - forget_range_invalid_pages((void*)&entry->key); - bool found = false; - if (hash_search(file_hash, &(entry->key), HASH_REMOVE, &found) == NULL) { - LWLockRelease(FILE_REPAIR_LOCK); - ereport(ERROR, (errcode(ERRCODE_DATA_CORRUPTED), errmsg("file repair hash table corrupted"))); - } else { - ereport(LOG, (errmodule(MOD_REDO), - errmsg("[file repair] file %s seg is %d, repair finish, remove the entry", - relpathperm(entry->key.relfilenode, entry->key.forknum), entry->key.segno))); - } + // 濡傛灉鏂囦欢闇瑕佸繕璁版棤鏁堥〉鑼冨洿锛屽垯鎵ц鐩稿簲鎿嶄綔骞朵粠鍝堝笇琛ㄤ腑鍒犻櫎璇ユ枃浠 + forget_range_invalid_pages((void *)&entry->key); + bool found = false; + if (hash_search(file_hash, &(entry->key), HASH_REMOVE, &found) == NULL) { + LWLockRelease(FILE_REPAIR_LOCK); + ereport(ERROR, (errcode(ERRCODE_DATA_CORRUPTED), errmsg("file repair hash table corrupted"))); + } else { + ereport(LOG, (errmodule(MOD_REDO), + errmsg("[file repair] file %s seg is %d, repair finish, remove the entry", + relpathperm(entry->key.relfilenode, entry->key.forknum), entry->key.segno))); } break; default: break; } } + + // 閲婃斁鏂囦欢淇閿 LWLockRelease(FILE_REPAIR_LOCK); + // 閬嶅巻闇瑕侀噸鍛藉悕鐨勬枃浠跺苟鎵ц閲嶅懡鍚嶆搷浣滐紝鍚屾椂娓呴櫎鍝堝笇琛ㄤ腑鐨勭浉搴旀潯鐩 for (i = 0; i < need_rename_num; i++) { RepairFileKey *key = &rename_key[i]; RenameRepairFile(key, true); } + + // 濡傛灉娌℃湁闇瑕佷慨澶嶇殑鏂囦欢锛屽皢鎭㈠鏆傚仠鏍囧織璁剧疆涓 false if (need_rename_num > 0) { pfree(rename_key); rename_key = NULL; } if (need_repair_num == 0) { SetRecoverySuspend(false); - ereport(LOG, (errmodule(MOD_REDO), - errmsg("set recovery suspend to false, the need repair num is zero"))); + ereport(LOG, (errmodule(MOD_REDO), errmsg("set recovery suspend to false, the need repair num is zero"))); } } +/* + * 鍔熻兘锛氭鏌ユ槸鍚﹀仠姝㈡仮澶 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庢鏌ユ槸鍚﹂渶瑕佸仠姝㈡仮澶嶏紝浠ュ強鎵ц鐩稿簲鐨勬搷浣溿 + */ void CheckIsStopRecovery(void) { + // 澹版槑鍙橀噺 uint32 need_repair_num = 0; uint32 need_rename_num = 0; HASH_SEQ_STATUS status; @@ -1164,48 +1688,65 @@ void CheckIsStopRecovery(void) XLogRecPtr repaly = GetXLogReplayRecPtr(NULL, NULL); XLogRecPtr flush = GetStandbyFlushRecPtr(NULL); + // 濡傛灉鏂囦欢淇鍝堝笇琛ㄤ负绌猴紝鍒欒繑鍥 if (file_hash == NULL) { return; } + // 灏濊瘯鑾峰彇鏂囦欢淇閿侊紝浠ユ墽琛屽搱甯岃〃鎿嶄綔 if (LWLockConditionalAcquire(FILE_REPAIR_LOCK, LW_EXCLUSIVE)) { + // 鍒濆鍖栧搱甯岃〃閬嶅巻鐘舵 hash_seq_init(&status, file_hash); + + // 閬嶅巻鍝堝笇琛ㄤ互妫鏌ユ枃浠剁姸鎬佸苟鎵ц鐩稿簲鎿嶄綔 while ((entry = (RepairFileEntry *)hash_seq_search(&status)) != NULL) { flush = GetStandbyFlushRecPtr(NULL); - if (!XLogRecPtrIsInvalid(entry->min_recovery_point) && XLByteLT(entry->min_recovery_point, repaly) - && entry->file_state == WAIT_FILE_CHECK_REPAIR) { + + // 妫鏌ユ槸鍚﹂渶瑕佸皢绛夊緟鏂囦欢淇鐨勬枃浠剁姸鎬佽缃负绛夊緟杩滅▼璇诲彇 + if (!XLogRecPtrIsInvalid(entry->min_recovery_point) && XLByteLT(entry->min_recovery_point, repaly) && + entry->file_state == WAIT_FILE_CHECK_REPAIR) { entry->file_state = WAIT_FILE_REMOTE_READ; } + // 妫鏌ユ槸鍚﹂渶瑕佽繘琛岃繙绋嬭鍙栨垨娈典慨澶嶏紝鍚屾椂澧炲姞鐩稿簲璁℃暟 if (entry->file_state == WAIT_FILE_REMOTE_READ || entry->file_state == WAIT_FILE_REPAIR_SEGMENT) { need_repair_num++; - ereport(LOG, (errmodule(MOD_REDO), - errmsg("[file repair] need remote read or segment file wait rename, file path %s segno is %u", - relpathperm(entry->key.relfilenode, entry->key.forknum), entry->key.segno))); + ereport(LOG, + (errmodule(MOD_REDO), + errmsg("[file repair] need remote read or segment file wait rename, file path %s segno is %u", + relpathperm(entry->key.relfilenode, entry->key.forknum), entry->key.segno))); } + // 妫鏌ユ槸鍚﹂渶瑕侀噸鍛藉悕鏂囦欢锛屽悓鏃跺鍔犵浉搴旇鏁 if ((entry->file_state == WAIT_FILE_REPAIR && !IsSegmentFileNode(entry->key.relfilenode) && - XLByteLT(entry->primary_file_lsn, repaly)) || entry->file_state == WAIT_RENAME) { + XLByteLT(entry->primary_file_lsn, repaly)) || + entry->file_state == WAIT_RENAME) { entry->file_state = WAIT_RENAME; need_rename_num++; ereport(LOG, (errmodule(MOD_REDO), - errmsg("[file repair] need rename, file path %s segno is %u", - relpathperm(entry->key.relfilenode, entry->key.forknum), entry->key.segno))); + errmsg("[file repair] need rename, file path %s segno is %u", + relpathperm(entry->key.relfilenode, entry->key.forknum), entry->key.segno))); } } + // 閲婃斁鏂囦欢淇閿 LWLockRelease(FILE_REPAIR_LOCK); + // 濡傛灉鏈夐渶瑕佷慨澶嶇殑鏂囦欢鎴栭渶瑕侀噸鍛藉悕鐨勬枃浠讹紝鍒欐墽琛岀浉搴旀搷浣 if (need_repair_num > 0 || need_rename_num > 0) { load_server_mode(); + + // 濡傛灉涓嶆敮鎸侀〉闈慨澶嶏紝鍒欒繑鍥 if (NOT_SUPPORT_PAGE_REPAIR) { return; } + + // 濡傛灉鏈嶅姟鍣ㄦā寮忎负STANDBY_MODE涓旀敮鎸佷慨澶嶏紝鍒欒缃仮澶嶆殏鍋滄爣蹇椾负true if (t_thrd.xlog_cxt.server_mode == STANDBY_MODE && g_instance.repair_cxt.support_repair) { SetRecoverySuspend(true); ereport(LOG, (errmodule(MOD_REDO), - errmsg("set recovery suspend to true, the need repair num is %d, need rename num is %d", - need_repair_num, need_rename_num))); + errmsg("set recovery suspend to true, the need repair num is %d, need rename num is %d", + need_repair_num, need_rename_num))); } } } @@ -1214,72 +1755,125 @@ void CheckIsStopRecovery(void) } const int REPAIR_LEN = 8; +/* + * 鍔熻兘锛氬垱寤轰慨澶嶆枃浠 + * + * 鍙傛暟鍒楄〃锛 + * path锛氬師濮嬫枃浠惰矾寰 + * + * 杩斿洖鍊硷細鎴愬姛鏃惰繑鍥炴枃浠舵弿杩扮锛坒d锛夛紝澶辫触鏃惰繑鍥-1 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庡垱寤轰竴涓敤浜庝慨澶嶇殑鏂囦欢锛屽苟杩斿洖鍏舵枃浠舵弿杩扮銆 + */ int CreateRepairFile(char *path) { + // 鍒濆鍖栨枃浠舵弿杩扮涓-1 int fd = -1; + // 鍒濆鍖栭噸璇曟鏁颁负0 int retry_times = 0; + // 瀹氫箟鏈澶ч噸璇曟鏁 const int MAX_RETRY_TIME = 2; errno_t rc; + // 涓轰慨澶嶆枃浠惰矾寰勫垎閰嶅唴瀛 char *reapirpath = (char *)palloc(strlen(path) + REPAIR_LEN); + // 鏍煎紡鍖栦慨澶嶆枃浠惰矾寰 rc = sprintf_s(reapirpath, strlen(path) + REPAIR_LEN, "%s.repair", path); securec_check_ss(rc, "", ""); RETRY: - fd = BasicOpenFile((char*)reapirpath, O_CREAT | O_RDWR | PG_BINARY, S_IRUSR | S_IWUSR); + // 鎵撳紑鏂囦欢锛屽苟璁剧疆鏍囧織浣嶄负鍒涘缓銆佽鍐欍佷簩杩涘埗妯″紡锛屾潈闄愪负鐢ㄦ埛鍙鍜岀敤鎴峰彲鍐 + fd = BasicOpenFile((char *)reapirpath, O_CREAT | O_RDWR | PG_BINARY, S_IRUSR | S_IWUSR); retry_times++; + + // 妫鏌ユ枃浠舵槸鍚︽垚鍔熸墦寮 if (fd < 0) { + // 濡傛灉鏈垚鍔熸墦寮鏂囦欢锛屽苟涓旈噸璇曟鏁板皬浜庢渶澶ч噸璇曟鏁帮紝鍒欒繘琛岄噸璇 if (retry_times < MAX_RETRY_TIME) { goto RETRY; } + + // 濡傛灉閿欒涓嶆槸鏂囦欢涓嶅瓨鍦紙ENOENT锛夛紝鍒欐姤鍛婅鍛婂苟閲婃斁璧勬簮鍚庤繑鍥-1 if (errno != ENOENT) { - ereport(WARNING, (errcode_for_file_access(), - errmsg("[file repair] could not open file \"%s\": %m", reapirpath))); + ereport(WARNING, + (errcode_for_file_access(), errmsg("[file repair] could not open file \"%s\": %m", reapirpath))); pfree(reapirpath); return -1; } } + // 閲婃斁淇鏂囦欢璺緞鐨勫唴瀛樺苟杩斿洖鏂囦欢鎻忚堪绗 pfree(reapirpath); return fd; } -int WriteRepairFile(int fd, char* path, char *buf, uint32 offset, uint32 size) +/* + * 鍔熻兘锛氬啓淇鏂囦欢 + * + * 鍙傛暟鍒楄〃锛 + * fd锛氭枃浠舵弿杩扮 + * path锛氬師濮嬫枃浠惰矾寰 + * buf锛氳鍐欏叆鐨勬暟鎹紦鍐插尯 + * offset锛氬啓鍏ユ暟鎹殑鍋忕Щ閲 + * size锛氳鍐欏叆鐨勬暟鎹ぇ灏 + * + * 杩斿洖鍊硷細鎴愬姛鏃惰繑鍥0锛屽け璐ユ椂杩斿洖-1 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庡悜淇鏂囦欢鍐欏叆鏁版嵁锛屽叿浣撳疄鐜颁簡鍐欏叆鍜屽悓姝ユ搷浣溿 + */ +int WriteRepairFile(int fd, char *path, char *buf, uint32 offset, uint32 size) { errno_t rc = 0; + // 涓轰慨澶嶆枃浠惰矾寰勫垎閰嶅唴瀛 char *reapirpath = (char *)palloc(strlen(path) + REPAIR_LEN); + // 鏍煎紡鍖栦慨澶嶆枃浠惰矾寰 rc = sprintf_s(reapirpath, strlen(path) + REPAIR_LEN, "%s.repair", path); securec_check_ss(rc, "", ""); + // 灏嗘枃浠跺亸绉昏缃负鎸囧畾鐨勫亸绉婚噺 if (lseek(fd, offset, SEEK_SET) < 0) { - ereport(WARNING, (errcode_for_file_access(), errmsg("[file repair] could not seek reapir file %s : %m", - reapirpath))); + ereport(WARNING, + (errcode_for_file_access(), errmsg("[file repair] could not seek repair file %s : %m", reapirpath))); pfree(reapirpath); return -1; } + // 鍐欏叆鏁版嵁鍒版枃浠 if (write(fd, buf, size) != size) { /* if write didn't set errno, assume problem is no disk space */ if (errno == 0) { errno = ENOSPC; } - ereport(WARNING, (errcode_for_file_access(), errmsg("[file repair] could not write to temp file %s : %m", - reapirpath))); + ereport(WARNING, + (errcode_for_file_access(), errmsg("[file repair] could not write to temp file %s : %m", reapirpath))); pfree(reapirpath); return -1; } + // 鍚屾鏂囦欢锛岀‘淇濇暟鎹鍐欏叆纾佺洏 if (fsync(fd) != 0) { - ereport(WARNING, (errcode_for_file_access(), errmsg("[file repair] could not fsync temp file %s : %m", - reapirpath))); + ereport(WARNING, + (errcode_for_file_access(), errmsg("[file repair] could not fsync temp file %s : %m", reapirpath))); pfree(reapirpath); return -1; } + // 閲婃斁淇鏂囦欢璺緞鐨勫唴瀛樺苟杩斿洖0琛ㄧず鎴愬姛 pfree(reapirpath); return 0; } - +/* + * 鍔熻兘锛氬垹闄ゆ棫鐨勫潖鏂囦欢 + * + * 鍙傛暟鍒楄〃锛 + * path锛氳鍒犻櫎鐨勬枃浠剁殑璺緞 + * key锛氫慨澶嶆枃浠剁殑閿 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮瓑寰匵LOG閲嶆斁瀹屾垚锛屽苟澶勭悊鐩稿叧鐨勫悗绔嚎绋嬨傜劧鍚庡垹闄ゆ枃浠讹紝骞舵竻闄や笌璇ユ枃浠剁浉鍏崇殑鍏变韩缂撳啿鍖恒 + */ void UnlinkOldBadFile(char *path, RepairFileKey key) { /* wait the xlog repaly finish */ @@ -1302,7 +1896,7 @@ void UnlinkOldBadFile(char *path, RepairFileKey key) } } /* wait all dirty page flush */ - RequestCheckpoint(CHECKPOINT_FLUSH_DIRTY|CHECKPOINT_WAIT); + RequestCheckpoint(CHECKPOINT_FLUSH_DIRTY | CHECKPOINT_WAIT); /* handle the backend thread */ RelFileNodeBackend rnode; @@ -1324,6 +1918,20 @@ void UnlinkOldBadFile(char *path, RepairFileKey key) return; } +/* + * 鍔熻兘锛氫慨澶嶅垎娈垫枃浠 + * + * 鍙傛暟鍒楄〃锛 + * key锛氫慨澶嶆枃浠剁殑閿 + * segpath锛氬垎娈垫枃浠剁殑璺緞 + * seg_no锛氬垎娈靛彿 + * max_segno锛氭渶澶у垎娈靛彿 + * size锛氭枃浠跺ぇ灏 + * + * 娉ㄦ剰锛 + * 鍑芥暟棣栧厛鍒涘缓涓涓慨澶嶆枃浠跺苟鎵撳紑瀹冿紝鐒跺悗寰幆杩滅▼璇诲彇鏁版嵁鍧楋紝灏嗘暟鎹啓鍏ヤ慨澶嶆枃浠朵腑銆備箣鍚庣瓑寰 + * 淇鏂囦欢鐨勬暟鎹鍒锋柊鍒扮鐩樸傛渶鍚庯紝濡傛灉涓嶆槸鍒嗘鏂囦欢锛屽垯鍒犻櫎鏃ф枃浠讹紝鏇存柊淇鏂囦欢鐨勭姸鎬併 + */ static void RepairSegFile(RepairFileKey key, char *segpath, uint32 seg_no, uint32 max_segno, uint64 size) { char *buf = 0; @@ -1338,22 +1946,25 @@ static void RepairSegFile(RepairFileKey key, char *segpath, uint32 seg_no, uint3 XLogRecPtr standby_flush_lsn = InvalidXLogRecPtr; bool found = false; + // 鍒涘缓淇鏂囦欢骞舵墦寮瀹 fd = CreateRepairFile(segpath); if (fd < 0) { - ereport(WARNING, (errcode_for_file_access(), - errmsg("[file repair] could not create repair file \"%s\", segno is %d", - relpathperm(key.relfilenode, key.forknum), seg_no))); + ereport(WARNING, + (errcode_for_file_access(), errmsg("[file repair] could not create repair file \"%s\", segno is %d", + relpathperm(key.relfilenode, key.forknum), seg_no))); return; } read_key.relfilenode = key.relfilenode; read_key.forknum = key.forknum; read_key.blockstart = seg_no * RELSEG_SIZE; - buf = (char*)palloc(MAX_BATCH_READ_BLOCKNUM * BLCKSZ); + // 鍒嗛厤缂撳啿鍖轰互鎵归噺璇诲彇鏁版嵁鍧 + buf = (char *)palloc(MAX_BATCH_READ_BLOCKNUM * BLCKSZ); seg_size = (seg_no < max_segno ? (RELSEG_SIZE * BLCKSZ) : (size % (RELSEG_SIZE * BLCKSZ))); int batch_size = MAX_BATCH_READ_BLOCKNUM * BLCKSZ; int max_times = seg_size % batch_size == 0 ? seg_size / batch_size : (seg_size / batch_size + 1); + // 寰幆璇诲彇鏁版嵁鍧楀苟鍐欏叆淇鏂囦欢 for (int j = 0; j < max_times; j++) { int read_size = 0; if (seg_size % batch_size != 0) { @@ -1368,16 +1979,16 @@ static void RepairSegFile(RepairFileKey key, char *segpath, uint32 seg_no, uint3 rc = WriteRepairFile(fd, segpath, buf, j * batch_size, read_size); if (rc != 0) { ereport(WARNING, (errcode_for_file_access(), - errmsg("[file repair] could not write repair file \"%s\", segno is %d", - relpathperm(key.relfilenode, key.forknum), seg_no))); + errmsg("[file repair] could not write repair file \"%s\", segno is %d", + relpathperm(key.relfilenode, key.forknum), seg_no))); pfree(buf); (void)close(fd); return; } } else { ereport(WARNING, (errcode_for_file_access(), - errmsg("[file repair] remote read file failed \"%s\", segno is %d, block start %u", - relpathperm(key.relfilenode, key.forknum), seg_no, read_key.blockstart))); + errmsg("[file repair] remote read file failed \"%s\", segno is %d, block start %u", + relpathperm(key.relfilenode, key.forknum), seg_no, read_key.blockstart))); pfree(buf); (void)close(fd); return; @@ -1386,27 +1997,29 @@ static void RepairSegFile(RepairFileKey key, char *segpath, uint32 seg_no, uint3 pfree(buf); (void)close(fd); + // 绛夊緟淇鏂囦欢鐨勬暟鎹鍒锋柊鍒扮鐩 if (ret_code == REMOTE_READ_OK) { standby_flush_lsn = GetStandbyFlushRecPtr(NULL); while (!XLByteLT(remote_lsn, standby_flush_lsn)) { PageRepairHandleInterrupts(); - /* sleep 10ms */ + /* 绛夊緟10姣 */ pg_usleep(10000L); - /* get current replay lsn again */ + /* 鍐嶆鑾峰彇褰撳墠閲嶆斁LSN */ standby_flush_lsn = GetStandbyFlushRecPtr(NULL); } - ereport(LOG, (errmsg("[file repair] wait lsn flush, remote lsn is %X/%X", - (uint32)(remote_lsn >> XLOG_LSN_SWAP), (uint32)remote_lsn))); + ereport(LOG, (errmsg("[file repair] wait lsn flush, remote lsn is %X/%X", (uint32)(remote_lsn >> XLOG_LSN_SWAP), + (uint32)remote_lsn))); } else { return; } /* wait xlog repaly */ + // 濡傛灉涓嶆槸鍒嗘鏂囦欢锛屽垯鍒犻櫎鏃ф枃浠 if (!IsSegmentFileNode(key.relfilenode)) { if (stat(segpath, &statBuf) < 0) { if (errno != ENOENT) { ereport(WARNING, (errcode_for_file_access(), - errmsg("[file repair] could not stat file \"%s\" before repair: %m", segpath))); + errmsg("[file repair] could not stat file \"%s\" before repair: %m", segpath))); UnlinkOldBadFile(segpath, key); } } else { @@ -1416,8 +2029,8 @@ static void RepairSegFile(RepairFileKey key, char *segpath, uint32 seg_no, uint3 /* wait xlog repaly finish, need get lock */ LWLockAcquire(FILE_REPAIR_LOCK, LW_EXCLUSIVE); - RepairFileEntry *temp_entry = (RepairFileEntry*)hash_search(g_instance.repair_cxt.file_repair_hashtbl, &(key), - HASH_FIND, &found); + RepairFileEntry *temp_entry = + (RepairFileEntry *)hash_search(g_instance.repair_cxt.file_repair_hashtbl, &(key), HASH_FIND, &found); if (found) { temp_entry->file_state = IsSegmentFileNode(key.relfilenode) ? WAIT_FILE_REPAIR_SEGMENT : WAIT_FILE_REPAIR; temp_entry->primary_file_lsn = remote_lsn; @@ -1425,7 +2038,27 @@ static void RepairSegFile(RepairFileKey key, char *segpath, uint32 seg_no, uint3 LWLockRelease(FILE_REPAIR_LOCK); return; } - +/* + * 鍔熻兘锛氭鏌ユ墍鏈夊垎娈垫枃浠舵槸鍚﹀凡瀹屾垚杩滅▼璇诲彇锛屽苟鍦ㄦ弧瓒虫潯浠舵椂鎵ц涓绯诲垪鎿嶄綔 + * + * 鍙傛暟鍒楄〃锛 + * key锛氫慨澶嶆枃浠剁殑閿 + * max_segno锛氭渶澶у垎娈靛彿 + * + * 杩斿洖鍊硷細 + * 濡傛灉鎵鏈夊垎娈垫枃浠跺凡瀹屾垚杩滅▼璇诲彇锛屽垯杩斿洖true锛屽惁鍒欒繑鍥瀎alse + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁伴鍏堥亶鍘嗘墍鏈夊垎娈垫枃浠讹紝妫鏌ュ畠浠殑鐘舵佹槸鍚︿负WAIT_FILE_REPAIR_SEGMENT锛堢瓑寰呭垎娈典慨澶嶏級锛 + * 濡傛灉鏄紝鍒欏鍔燻repair_num`璁℃暟銆傚鏋渀repair_num`绛変簬`max_segno + 1`锛岃〃绀烘墍鏈夊垎娈垫枃浠 + * 閮藉凡瀹屾垚杩滅▼璇诲彇锛岀劧鍚庤繘琛屼互涓嬫搷浣滐細 + * 1. 閲嶅懡鍚嶆墍鏈夊垎娈垫枃浠躲 + * 2. 鎵撳紑鎵鏈夊垎娈垫枃浠躲 + * 3. 鏇存敼鏂囦欢鐘舵佷负WAIT_FOREGT_INVALID_PAGE锛堢瓑寰呭繕璁版棤鏁堥〉闈級銆 + * 鏈鍚庯紝鍑芥暟杩斿洖true銆 + * + * 濡傛灉娌℃湁婊¤冻鏉′欢鐨勬儏鍐碉紝鍒欏嚱鏁拌繑鍥瀎alse銆 + */ bool CheckAllSegmentFileRepair(RepairFileKey key, uint32 max_segno) { uint32 repair_num = 0; @@ -1443,8 +2076,8 @@ bool CheckAllSegmentFileRepair(RepairFileKey key, uint32 max_segno) temp_key.forknum = key.forknum; temp_key.segno = i; - RepairFileEntry *entry = (RepairFileEntry*)hash_search(g_instance.repair_cxt.file_repair_hashtbl, - &(temp_key), HASH_FIND, &found); + RepairFileEntry *entry = + (RepairFileEntry *)hash_search(g_instance.repair_cxt.file_repair_hashtbl, &(temp_key), HASH_FIND, &found); Assert(found); if (found && entry->file_state == WAIT_FILE_REPAIR_SEGMENT) { repair_num++; @@ -1467,7 +2100,7 @@ bool CheckAllSegmentFileRepair(RepairFileKey key, uint32 max_segno) rename_key.segno = i; LWLockAcquire(FILE_REPAIR_LOCK, LW_EXCLUSIVE); - (void*)hash_search(g_instance.repair_cxt.file_repair_hashtbl, &(rename_key), HASH_FIND, &found); + (void *)hash_search(g_instance.repair_cxt.file_repair_hashtbl, &(rename_key), HASH_FIND, &found); Assert(found); LWLockRelease(FILE_REPAIR_LOCK); if (found) { @@ -1491,8 +2124,8 @@ bool CheckAllSegmentFileRepair(RepairFileKey key, uint32 max_segno) change_key.forknum = key.forknum; change_key.segno = i; - RepairFileEntry *entry = (RepairFileEntry*)hash_search(g_instance.repair_cxt.file_repair_hashtbl, - &(change_key), HASH_FIND, &found); + RepairFileEntry *entry = (RepairFileEntry *)hash_search(g_instance.repair_cxt.file_repair_hashtbl, + &(change_key), HASH_FIND, &found); Assert(found); if (found) { entry->file_state = WAIT_FOREGT_INVALID_PAGE; @@ -1523,8 +2156,8 @@ RETYR: pfree(path); pfree(segpath); LWLockAcquire(FILE_REPAIR_LOCK, LW_EXCLUSIVE); - RepairFileEntry *temp_entry = (RepairFileEntry*)hash_search(g_instance.repair_cxt.file_repair_hashtbl, - &(key), HASH_FIND, &found); + RepairFileEntry *temp_entry = + (RepairFileEntry *)hash_search(g_instance.repair_cxt.file_repair_hashtbl, &(key), HASH_FIND, &found); if (found) { temp_entry->file_state = WAIT_CLEAN; } @@ -1534,13 +2167,15 @@ RETYR: max_segno = size / (RELSEG_SIZE * BLCKSZ); /* max_segno start from 0 */ if (key.segno > max_segno) { - ereport(WARNING, (errcode_for_file_access(), - errmsg("[file repair] primary this file %s , segno is %d also not exist, can not repair, wait clean", - relpathperm(key.relfilenode, key.forknum), key.segno))); + ereport( + WARNING, + (errcode_for_file_access(), + errmsg("[file repair] primary this file %s , segno is %d also not exist, can not repair, wait clean", + relpathperm(key.relfilenode, key.forknum), key.segno))); LWLockAcquire(FILE_REPAIR_LOCK, LW_EXCLUSIVE); - RepairFileEntry *temp_entry = (RepairFileEntry*)hash_search(g_instance.repair_cxt.file_repair_hashtbl, - &(key), HASH_FIND, &found); + RepairFileEntry *temp_entry = + (RepairFileEntry *)hash_search(g_instance.repair_cxt.file_repair_hashtbl, &(key), HASH_FIND, &found); if (found) { temp_entry->file_state = WAIT_CLEAN; } @@ -1555,7 +2190,7 @@ RETYR: /* wait all dirty page flush */ WaitRepalyFinish(); /* wait all dirty page flush */ - RequestCheckpoint(CHECKPOINT_FLUSH_DIRTY|CHECKPOINT_WAIT); + RequestCheckpoint(CHECKPOINT_FLUSH_DIRTY | CHECKPOINT_WAIT); df_clear_and_close_all_file(key, max_segno); } @@ -1575,7 +2210,26 @@ RETYR: pfree(segpath); return; } - +/* + * 鍔熻兘锛氭鏌ヤ笌褰撳墠鏂囦欢鍏锋湁鐩稿悓閿絾涓嶅悓鍒嗘鍙风殑鍏朵粬鍒嗘鏂囦欢鏄惁闇瑕佷慨澶嶏紝骞舵墽琛岀浉搴旂殑鎿嶄綔銆 + * + * 鍙傛暟鍒楄〃锛 + * key锛氫慨澶嶆枃浠剁殑閿 + * max_segno锛氭枃浠剁殑鏈澶у垎娈靛彿 + * size锛氭枃浠剁殑澶у皬 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁板惊鐜亶鍘嗕笉鍚岀殑鍒嗘鍙凤紝瀵规瘡涓垎娈靛彿鎵ц浠ヤ笅鎿嶄綔锛 + * 1. 鐢熸垚鍒嗘鏂囦欢鐨勮矾寰勩 + * 2. 濡傛灉鍒嗘鍙蜂笌褰撳墠鏂囦欢鐨勫垎娈靛彿鐩稿悓锛岀户缁笅涓涓垎娈靛彿鐨勬鏌ャ + * 3. 妫鏌ユ槸鍚﹀湪鍝堝笇琛ㄤ腑鎵惧埌鍏锋湁鐩稿悓閿絾鐘舵佷负WAIT_FILE_REMOTE_READ鐨勫垎娈垫枃浠躲 + * 4. 濡傛灉鎵惧埌锛岄噴鏀惧搱甯岃〃鐨勯攣骞舵墽琛孯epairSegFile鍑芥暟淇鍒嗘鏂囦欢銆 + * 5. 鍚﹀垯锛屾鏌ユ槸鍚﹀垎娈垫枃浠跺瓨鍦紝濡傛灉瀛樺湪鍒欑户缁笅涓涓垎娈靛彿鐨勬鏌ャ + * 6. + * 濡傛灉鍒嗘鏂囦欢涓嶅瓨鍦ㄦ垨鍑虹幇閿欒锛屽垯灏嗗叿鏈夌浉鍚岄敭浣嗕笉鍚屽垎娈靛彿鐨勫垎娈垫枃浠舵坊鍔犲埌鍝堝笇琛ㄤ腑锛屽苟鏍囪涓篧AIT_FILE_REMOTE_READ鐘舵侊紝鐒跺悗閲婃斁閿佸苟鎵цRepairSegFile鍑芥暟淇鍒嗘鏂囦欢銆 + * + * 鏈鍚庯紝閲婃斁鍒嗛厤鐨勫唴瀛樺苟杩斿洖銆 + */ static void checkOtherFile(RepairFileKey key, uint32 max_segno, uint64 size) { errno_t rc; @@ -1609,7 +2263,7 @@ static void checkOtherFile(RepairFileKey key, uint32 max_segno, uint64 size) temp_key.segno = i; LWLockAcquire(FILE_REPAIR_LOCK, LW_EXCLUSIVE); - temp_entry = (RepairFileEntry*)hash_search(file_hash, &(temp_key), HASH_FIND, &found); + temp_entry = (RepairFileEntry *)hash_search(file_hash, &(temp_key), HASH_FIND, &found); if (found && temp_entry->file_state == WAIT_FILE_REMOTE_READ) { LWLockRelease(FILE_REPAIR_LOCK); RepairSegFile(temp_key, segpath, i, max_segno, size); @@ -1628,7 +2282,7 @@ static void checkOtherFile(RepairFileKey key, uint32 max_segno, uint64 size) LWLockAcquire(FILE_REPAIR_LOCK, LW_EXCLUSIVE); - temp_entry = (RepairFileEntry*)hash_search(file_hash, &(temp_key), HASH_ENTER, &found); + temp_entry = (RepairFileEntry *)hash_search(file_hash, &(temp_key), HASH_ENTER, &found); if (!found) { LWLockAcquire(ControlFileLock, LW_SHARED); XLogRecPtr min_recovery_point = t_thrd.shemem_ptr_cxt.ControlFile->minRecoveryPoint; @@ -1638,9 +2292,10 @@ static void checkOtherFile(RepairFileKey key, uint32 max_segno, uint64 size) temp_entry->file_state = WAIT_FILE_REMOTE_READ; temp_entry->primary_file_lsn = InvalidXLogRecPtr; - ereport(LOG, (errmodule(MOD_REDO), - errmsg("[file repair] check other seg file push to file repair hashtbl, path is %s segno is %u", - relpathperm(key.relfilenode, key.forknum), i))); + ereport(LOG, + (errmodule(MOD_REDO), + errmsg("[file repair] check other seg file push to file repair hashtbl, path is %s segno is %u", + relpathperm(key.relfilenode, key.forknum), i))); LWLockRelease(FILE_REPAIR_LOCK); RepairSegFile(temp_key, segpath, i, max_segno, size); } else { @@ -1653,6 +2308,24 @@ static void checkOtherFile(RepairFileKey key, uint32 max_segno, uint64 size) } const int MAX_FILE_REPAIR_NUM = 10; +/* + * 鍔熻兘锛氭寜椤哄簭妫鏌ユ枃浠朵慨澶嶅搱甯岃〃涓殑鏂囦欢锛屽苟鏍规嵁瀹冧滑鐨勭姸鎬佹墽琛屼笉鍚岀殑鎿嶄綔銆 + * 娉ㄦ剰锛 + * 璇ュ嚱鏁伴鍏堟鏌ユ仮澶嶆槸鍚﹁鎸傝捣锛屼互鍙婃槸鍚﹁缃簡鎸傝捣鐨凩SN銆傚鏋滄湭鎸傝捣鎭㈠鎴朙SN鏃犳晥锛屽垯杩斿洖銆 + * 鐒跺悗锛屽畠鍒涘缓涓涓敤浜庡瓨鍌ㄩ渶瑕佽繙绋嬭鍙栫殑鏂囦欢鐨勬暟缁 `remote_read`锛屽苟灏嗗叾鍒濆鍖栦负闆躲 + * 鎺ョ潃锛屽嚱鏁扮瓑寰匵LOG鎭㈠瀹屾垚銆 + * 闅忓悗锛屽畠鑾峰彇鏂囦欢淇閿侊紝鍒濆鍖栧搱甯岃〃鐨勫簭鍒楃姸鎬佸苟閬嶅巻鍝堝笇琛ㄤ腑鐨勬墍鏈夋枃浠舵潯鐩 + * 瀵逛簬姣忎釜鏂囦欢鏉$洰锛屽畠鏍规嵁鏂囦欢鐨勭姸鎬侀噰鍙栦互涓嬫搷浣滐細 + * - 濡傛灉鏂囦欢鐘舵佹槸 WAIT_FILE_CHECK_REPAIR銆乄AIT_FILE_REPAIR銆乄AIT_FOREGT_INVALID_PAGE銆乄AIT_CLEAN 鎴 + * WAIT_RENAME锛屽垯涓嶆墽琛屼换浣曟搷浣溿 + * - 濡傛灉鏂囦欢鐘舵佹槸 WAIT_FILE_REPAIR_SEGMENT 鎴 WAIT_FILE_REMOTE_READ锛屽垯灏嗘枃浠剁姸鎬佽缃负 + * WAIT_FILE_REMOTE_READ锛岀劧鍚庡皢鏂囦欢鏉$洰澶嶅埗鍒 `remote_read` 鏁扮粍涓紝濡傛灉鏁扮粍宸叉弧鍒欏仠姝㈠鍒躲 + * - 濡傛灉鏂囦欢鐘舵佹棤娉曡瘑鍒紝鍒欓噴鏀炬枃浠朵慨澶嶉攣锛屾姏鍑洪敊璇 + * 鎺ヤ笅鏉ワ紝鍑芥暟閲婃斁鏂囦欢淇閿侊紝骞跺惊鐜亶鍘 `remote_read` 鏁扮粍涓殑鏂囦欢锛屽姣忎釜鏂囦欢鎵ц `StandbyRemoteReadFile` + * 鍑芥暟锛岀敤浜庤繙绋嬭鍙栨枃浠躲 鏈鍚庯紝鍑芥暟鍐嶆鑾峰彇鏂囦欢淇閿侊紝閬嶅巻鍝堝笇琛ㄥ苟妫鏌ユ枃浠剁姸鎬佹槸鍚︿负 + * WAIT_FILE_REPAIR_SEGMENT銆乄AIT_FILE_REMOTE_READ 鎴 WAIT_RENAME銆傚鏋滄槸锛屽皢 `need_repair_num` 澧炲姞銆 + * 濡傛灉娌℃湁浠讳綍鏂囦欢闇瑕佷慨澶嶏紝灏嗘仮澶嶆寕璧风姸鎬佽缃负 false銆 + */ static void SeqRemoteReadFile() { HTAB *repair_hash = g_instance.repair_cxt.file_repair_hashtbl; @@ -1668,7 +2341,7 @@ static void SeqRemoteReadFile() } rc = memset_s(remote_read, sizeof(RepairFileEntry) * MAX_FILE_REPAIR_NUM, 0, - sizeof(RepairFileEntry) * MAX_FILE_REPAIR_NUM); + sizeof(RepairFileEntry) * MAX_FILE_REPAIR_NUM); securec_check(rc, "", ""); /* wait the xlog repaly finish */ WaitRepalyFinish(); @@ -1691,8 +2364,8 @@ static void SeqRemoteReadFile() if (need_repair_num >= MAX_FILE_REPAIR_NUM) { break; } else { - rc = memcpy_s(&remote_read[need_repair_num], sizeof(RepairFileEntry), - entry, sizeof(RepairFileEntry)); + rc = memcpy_s(&remote_read[need_repair_num], sizeof(RepairFileEntry), entry, + sizeof(RepairFileEntry)); securec_check(rc, "", ""); } break; @@ -1701,7 +2374,6 @@ static void SeqRemoteReadFile() ereport(ERROR, (errmsg("[file repair] error file state during remote read"))); break; } - } LWLockRelease(FILE_REPAIR_LOCK); for (uint32 i = 0; i < need_repair_num; i++) { @@ -1721,7 +2393,7 @@ static void SeqRemoteReadFile() if (need_repair_num == 0) { SetRecoverySuspend(false); ereport(LOG, (errmodule(MOD_REDO), - errmsg("pagerepair thread set recovery suspend to false, the need repair num is zero"))); + errmsg("pagerepair thread set recovery suspend to false, the need repair num is zero"))); } return; } diff --git a/src/gausskernel/process/postmaster/pagewriter.cpp b/src/gausskernel/process/postmaster/pagewriter.cpp index a1860f9a9..41f692053 100755 --- a/src/gausskernel/process/postmaster/pagewriter.cpp +++ b/src/gausskernel/process/postmaster/pagewriter.cpp @@ -85,17 +85,23 @@ static uint32 calculate_pagewriter_flush_num(); static void candidate_buf_push(int buf_id, int thread_id); static void seg_candidate_buf_push(int buf_id, int thread_id); static void init_candidate_list(); -static uint32 incre_ckpt_pgwr_flush_dirty_page(WritebackContext wb_context, - const CkptSortItem *dirty_buf_list, int start, int batch_num); +static uint32 incre_ckpt_pgwr_flush_dirty_page(WritebackContext wb_context, const CkptSortItem *dirty_buf_list, + int start, int batch_num); static void incre_ckpt_pgwr_flush_dirty_queue(WritebackContext wb_context); static void incre_ckpt_pgwr_scan_buf_pool(WritebackContext wb_context); static void push_to_candidate_list(BufferDesc *buf_desc); static uint32 get_candidate_buf_and_flush_list(uint32 start, uint32 end, uint32 max_flush_num, - bool *contain_hashbucket); + bool *contain_hashbucket); static int64 get_thread_candidate_nums(int thread_id); static int64 get_thread_seg_candidate_nums(int thread_id); const int XLOG_LSN_SWAP = 32; +/* + * 鍔熻兘锛氳幏鍙栧綋鍓嶈妭鐐圭殑鍚嶇О + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庤幏鍙栧綋鍓嶈妭鐐圭殑鍚嶇О銆傚鏋滆妭鐐瑰悕绉版湭瀹氫箟鎴栦负绌猴紝鍒欒繑鍥 "not define"銆 + */ Datum ckpt_view_get_node_name() { if (g_instance.attr.attr_common.PGXCNodeName == NULL || g_instance.attr.attr_common.PGXCNodeName[0] == '\0') { @@ -121,6 +127,17 @@ Datum ckpt_view_get_remian_dirty_page_num() } const int LSN_LENGTH = 64; +/* + * 鍔熻兘锛氳幏鍙栨渶灏忕殑鎭㈠LSN锛堟棩蹇楀簭鍒楀彿锛 + * + * 鍙傛暟鍒楄〃锛氭棤 + * + * 杩斿洖鍊硷細杩斿洖涓涓枃鏈暟鎹被鍨嬬殑琛ㄧず鏈灏忔仮澶峀SN鐨勫瓧绗︿覆 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庤幏鍙栨暟鎹簱涓殑鏈灏忔仮澶峀SN銆侺SN锛堟棩蹇楀簭鍒楀彿锛夌敤浜庢爣璇哤AL锛堝啓鍓嶆棩蹇楋級涓殑浣嶇疆锛 + * 杩欏浜庢暟鎹簱鐨勬仮澶嶅拰涓鑷存ч潪甯搁噸瑕併傚嚱鏁板皢鏈灏忔仮澶峀SN琛ㄧず涓哄崄鍏繘鍒跺瓧绗︿覆骞惰繑鍥炪 + */ Datum ckpt_view_get_min_rec_lsn() { errno_t ret; @@ -130,14 +147,24 @@ Datum ckpt_view_get_min_rec_lsn() ret = memset_s(queue_rec_lsn_s, LSN_LENGTH, 0, LSN_LENGTH); securec_check(ret, "", ""); - ret = snprintf_s(queue_rec_lsn_s, LSN_LENGTH, LSN_LENGTH - 1, "%X/%X", - (uint32)(queue_rec_lsn >> XLOG_LSN_SWAP), (uint32)queue_rec_lsn); + ret = snprintf_s(queue_rec_lsn_s, LSN_LENGTH, LSN_LENGTH - 1, "%X/%X", (uint32)(queue_rec_lsn >> XLOG_LSN_SWAP), + (uint32)queue_rec_lsn); securec_check_ss(ret, "", ""); return CStringGetTextDatum(queue_rec_lsn_s); } +/* + * 鍔熻兘锛氳幏鍙栬剰椤甸槦鍒楃殑鏈灏忔仮澶峀SN锛堟棩蹇楀簭鍒楀彿锛 + * + * 杩斿洖鍊硷細杩斿洖涓涓枃鏈暟鎹被鍨嬬殑琛ㄧず鑴忛〉闃熷垪鐨勬渶灏忔仮澶峀SN鐨勫瓧绗︿覆 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庤幏鍙栨暟鎹簱涓剰椤甸槦鍒楃殑鏈灏忔仮澶峀SN銆侺SN锛堟棩蹇楀簭鍒楀彿锛夌敤浜庢爣璇哤AL锛堝啓鍓嶆棩蹇楋級涓殑浣嶇疆锛 + * 杩欏浜庢暟鎹簱鐨勬仮澶嶅拰涓鑷存ч潪甯搁噸瑕併傚嚱鏁板皢鑴忛〉闃熷垪鐨勬渶灏忔仮澶峀SN琛ㄧず涓哄崄鍏繘鍒跺瓧绗︿覆骞惰繑鍥炪 + */ Datum ckpt_view_get_queue_rec_lsn() { + errno_t ret; char queue_rec_lsn_s[LSN_LENGTH]; XLogRecPtr queue_rec_lsn = get_dirty_page_queue_rec_lsn(); @@ -145,39 +172,69 @@ Datum ckpt_view_get_queue_rec_lsn() ret = memset_s(queue_rec_lsn_s, LSN_LENGTH, 0, LSN_LENGTH); securec_check(ret, "", ""); - ret = snprintf_s(queue_rec_lsn_s, LSN_LENGTH, LSN_LENGTH - 1, "%X/%X", - (uint32)(queue_rec_lsn >> XLOG_LSN_SWAP), (uint32)queue_rec_lsn); + ret = snprintf_s(queue_rec_lsn_s, LSN_LENGTH, LSN_LENGTH - 1, "%X/%X", (uint32)(queue_rec_lsn >> XLOG_LSN_SWAP), + (uint32)queue_rec_lsn); securec_check_ss(ret, "", ""); return CStringGetTextDatum(queue_rec_lsn_s); } +/* + * 鍔熻兘锛氳幏鍙栧綋鍓峏LOG鎻掑叆LSN锛堟棩蹇楀簭鍒楀彿锛 + * + * 杩斿洖鍊硷細杩斿洖涓涓枃鏈暟鎹被鍨嬬殑琛ㄧず褰撳墠XLOG鎻掑叆LSN鐨勫瓧绗︿覆 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庤幏鍙栧綋鍓峏LOG鎻掑叆LSN锛屽嵆褰撳墠鏁版嵁搴撲腑姝e湪鍐欏叆鐨勫啓鍓嶆棩蹇楋紙WAL锛変綅缃 + * LSN锛堟棩蹇楀簭鍒楀彿锛夌敤浜庢爣璇哤AL涓殑浣嶇疆锛屽浜庢暟鎹簱鐨勪竴鑷存у拰鎭㈠闈炲父閲嶈銆 + */ + Datum ckpt_view_get_current_xlog_insert_lsn() { + // 澹版槑涓涓敊璇彿鍙橀噺 errno_t ret; + // 鐢ㄤ簬淇濆瓨LSN鐨勫瓧绗︽暟缁 char current_lsn_s[LSN_LENGTH]; + // 鑾峰彇褰撳墠XLOG鎻掑叆浣嶇疆 XLogRecPtr current_xlog_insert = GetXLogInsertRecPtr(); - + // 灏嗗瓧绗︽暟缁勫垵濮嬪寲涓洪浂 ret = memset_s(current_lsn_s, LSN_LENGTH, 0, LSN_LENGTH); securec_check(ret, "", ""); - - ret = snprintf_s(current_lsn_s, LSN_LENGTH, LSN_LENGTH - 1, "%X/%X", - (uint32)(current_xlog_insert >> XLOG_LSN_SWAP), (uint32)current_xlog_insert); + // 灏哫LOG鎻掑叆LSN琛ㄧず涓哄崄鍏繘鍒跺瓧绗︿覆 + ret = snprintf_s(current_lsn_s, LSN_LENGTH, LSN_LENGTH - 1, "%X/%X", (uint32)(current_xlog_insert >> XLOG_LSN_SWAP), + (uint32)current_xlog_insert); securec_check_ss(ret, "", ""); + // 灏哃SN瀛楃涓茶浆鎹负鏂囨湰鏁版嵁绫诲瀷骞惰繑鍥 return CStringGetTextDatum(current_lsn_s); } +/* + * 鍔熻兘锛氳幏鍙栧綋鍓嶉噸鍋氱偣鐨刋LOG鎻掑叆LSN锛堟棩蹇楀簭鍒楀彿锛 + * + * 鍙傛暟鍒楄〃锛氭棤 + * + * 杩斿洖鍊硷細杩斿洖涓涓枃鏈暟鎹被鍨嬬殑琛ㄧず褰撳墠閲嶅仛鐐圭殑XLOG鎻掑叆LSN鐨勫瓧绗︿覆 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庤幏鍙栧綋鍓嶆暟鎹簱鐨勯噸鍋氱偣锛坮edo point锛夛紝瀹冩槸鏁版嵁搴撳湪鎭㈠鏈熼棿鐨勫叧閿爣蹇椼 + * 閲嶅仛鐐硅〃绀烘暟鎹簱鐨勪竴鑷存э紝鐢ㄤ簬纭畾闇瑕侀噸鍋氬摢浜涗簨鍔′互淇濇寔鏁版嵁搴撶殑涓鑷存с + */ + Datum ckpt_view_get_redo_point() { + // 澹版槑涓涓敊璇彿鍙橀噺 errno_t ret; + // 鐢ㄤ簬淇濆瓨LSN鐨勫瓧绗︽暟缁 char redo_lsn_s[LSN_LENGTH]; + // 鑾峰彇褰撳墠閲嶅仛鐐圭殑XLOG鎻掑叆LSN XLogRecPtr redo_lsn = g_instance.ckpt_cxt_ctl->ckpt_view.ckpt_current_redo_point; - + // 灏嗗瓧绗︽暟缁勫垵濮嬪寲涓洪浂 ret = memset_s(redo_lsn_s, LSN_LENGTH, 0, LSN_LENGTH); securec_check(ret, "", ""); - - ret = snprintf_s( - redo_lsn_s, LSN_LENGTH, LSN_LENGTH - 1, "%X/%X", (uint32)(redo_lsn >> XLOG_LSN_SWAP), (uint32)redo_lsn); + // 灏哫LOG鎻掑叆LSN琛ㄧず涓哄崄鍏繘鍒跺瓧绗︿覆 + ret = snprintf_s(redo_lsn_s, LSN_LENGTH, LSN_LENGTH - 1, "%X/%X", (uint32)(redo_lsn >> XLOG_LSN_SWAP), + (uint32)redo_lsn); securec_check_ss(ret, "", ""); + // 灏哃SN瀛楃涓茶浆鎹负鏂囨湰鏁版嵁绫诲瀷骞惰繑鍥 return CStringGetTextDatum(redo_lsn_s); } @@ -255,11 +312,10 @@ const incre_ckpt_view_col g_pagewirter_view_two_col[CANDIDATE_VIEW_COL_NUM] = { {"get_buf_clock_sweep", INT8OID, ckpt_view_get_num_clock_sweep}, {"seg_candidate_slots", INT4OID, ckpt_view_get_seg_candidate_nums}, {"seg_get_buf_from_list", INT8OID, ckpt_view_seg_get_num_candidate_list}, - {"seg_get_buf_clock_sweep", INT8OID, ckpt_view_seg_get_num_clock_sweep} -}; + {"seg_get_buf_clock_sweep", INT8OID, ckpt_view_seg_get_num_clock_sweep}}; - -const incre_ckpt_view_col g_ckpt_view_col[INCRE_CKPT_VIEW_COL_NUM] = {{"node_name", TEXTOID, ckpt_view_get_node_name}, +const incre_ckpt_view_col g_ckpt_view_col[INCRE_CKPT_VIEW_COL_NUM] = { + {"node_name", TEXTOID, ckpt_view_get_node_name}, {"ckpt_redo_point", TEXTOID, ckpt_view_get_redo_point}, {"ckpt_clog_flush_num", INT8OID, ckpt_view_get_clog_flush_num}, {"ckpt_csnlog_flush_num", INT8OID, ckpt_view_get_csnlog_flush_num}, @@ -284,78 +340,105 @@ bool IsPagewriterProcess(void) const int MAX_DIRTY_LIST_FLUSH_NUM = 1000 * DW_DIRTY_PAGE_MAX_FOR_NOHBK; +/* + * 鍔熻兘锛氬閲忔鏌ョ偣椤靛啓鍏ユā鍧楃殑涓婁笅鏂囧垵濮嬪寲 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庡垵濮嬪寲澧為噺妫鏌ョ偣椤靛啓鍏ユā鍧楃殑涓婁笅鏂囷紝鍖呮嫭鍒嗛厤鍐呭瓨銆佸垵濮嬪寲鏁版嵁缁撴瀯绛夈 + */ + void incre_ckpt_pagewriter_cxt_init() { + // 鍒囨崲鍐呭瓨涓婁笅鏂囧埌澧為噺妫鏌ョ偣涓婁笅鏂 MemoryContext oldcontext = MemoryContextSwitchTo(g_instance.increCheckPoint_context); - int thread_num = g_instance.attr.attr_storage.pagewriter_thread_num + 1; /* sub thread + one main thread */ - - g_instance.ckpt_cxt_ctl->pgwr_procs.writer_proc = (PageWriterProc*)palloc0(sizeof(PageWriterProc) * thread_num); + // 璁$畻绾跨▼鏁帮紙鍖呮嫭涓荤嚎绋嬶級 + int thread_num = g_instance.attr.attr_storage.pagewriter_thread_num + 1; + // 鍒嗛厤椤靛啓鍏ヨ繘绋嬬粨鏋勭殑鍐呭瓨锛屽垵濮嬪寲鐩稿叧淇℃伅 + g_instance.ckpt_cxt_ctl->pgwr_procs.writer_proc = (PageWriterProc *)palloc0(sizeof(PageWriterProc) * thread_num); g_instance.ckpt_cxt_ctl->pgwr_procs.num = thread_num; g_instance.ckpt_cxt_ctl->pgwr_procs.sub_num = g_instance.attr.attr_storage.pagewriter_thread_num; g_instance.ckpt_cxt_ctl->pgwr_procs.running_num = 0; - + // 鍒濆鍖栦竴浜涙鏌ョ偣缂撳啿鍖虹浉鍏崇殑鍙橀噺 g_instance.ckpt_cxt_ctl->prepared = 0; g_instance.ckpt_cxt_ctl->CkptBufferIdsTail = 0; g_instance.ckpt_cxt_ctl->CkptBufferIdsFlushPages = 0; g_instance.ckpt_cxt_ctl->CkptBufferIdsCompletedPages = 0; - + // 璁$畻姣忎釜绾跨▼鐨勮剰椤靛垪琛ㄥぇ灏 uint32 dirty_list_size = MAX_DIRTY_LIST_FLUSH_NUM / thread_num; - - /* init thread dw cxt and dirty list */ + // 鍒濆鍖栨瘡涓〉鍐欏叆杩涚▼鐨勬暟鎹粨鏋 for (int i = 0; i < thread_num; i++) { PageWriterProc *pgwr = &g_instance.ckpt_cxt_ctl->pgwr_procs.writer_proc[i]; - char *unaligned_buf = (char*)palloc0((DW_BUF_MAX_FOR_NOHBK + 1) * BLCKSZ); - pgwr->thrd_dw_cxt.dw_buf = (char*)TYPEALIGN(BLCKSZ, unaligned_buf); + // 鍒嗛厤骞跺榻愮紦鍐插尯鍐呭瓨 + char *unaligned_buf = (char *)palloc0((DW_BUF_MAX_FOR_NOHBK + 1) * BLCKSZ); + pgwr->thrd_dw_cxt.dw_buf = (char *)TYPEALIGN(BLCKSZ, unaligned_buf); + // 鍒濆鍖栧叾浠栧瓧娈 pgwr->thrd_dw_cxt.dw_page_idx = -1; pgwr->thrd_dw_cxt.is_new_relfilenode = false; pgwr->dirty_list_size = dirty_list_size; pgwr->dirty_buf_list = (CkptSortItem *)palloc0(dirty_list_size * sizeof(CkptSortItem)); } - + // 鍒濆鍖栧欓夊垪琛 init_candidate_list(); + // 鎭㈠鍘熷鍐呭瓨涓婁笅鏂 (void)MemoryContextSwitchTo(oldcontext); } +/* + * 鍔熻兘锛氬欓夌紦鍐插尯鐨勫垵濮嬪寲 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庡垵濮嬪寲鍊欓夌紦鍐插尯锛屽垎閰嶅唴瀛樺苟鍒濆鍖栫浉鍏虫暟鎹粨鏋勩 + * 璇ュ姛鑳藉湪澧為噺妫鏌ョ偣妯″紡涓嬫墠鍚敤銆 + */ + void candidate_buf_init(void) { + // 鏍囧織鍙橀噺锛岀敤浜庢鏌ユ槸鍚︽壘鍒颁簡鍊欓夌紦鍐插尯鍜屽欓夎嚜鐢辨槧灏 bool found_candidate_buf = false; bool found_candidate_fm = false; - int buffer_num = TOTAL_BUFFER_NUM; + int buffer_num = TOTAL_BUFFER_NUM; // 鎬荤紦鍐插尯鏁伴噺 + // 濡傛灉鏈惎鐢ㄥ閲忔鏌ョ偣锛屽垯鐩存帴杩斿洖 if (!ENABLE_INCRE_CKPT) { return; } - /* - * Each thread manages a part of the buffer. Several slots are reserved to - * prevent the thread first and last slots equals. - */ - g_instance.ckpt_cxt_ctl->candidate_buffers = (Buffer *) - ShmemInitStruct("CandidateBuffers", buffer_num * sizeof(Buffer), &found_candidate_buf); - g_instance.ckpt_cxt_ctl->candidate_free_map = (bool *) - ShmemInitStruct("CandidateFreeMap", buffer_num * sizeof(bool), &found_candidate_fm); + // 鍒嗛厤鍊欓夌紦鍐插尯鍜屽欓夎嚜鐢辨槧灏勭殑鍏变韩鍐呭瓨绌洪棿 + g_instance.ckpt_cxt_ctl->candidate_buffers = + (Buffer *)ShmemInitStruct("CandidateBuffers", buffer_num * sizeof(Buffer), &found_candidate_buf); + g_instance.ckpt_cxt_ctl->candidate_free_map = + (bool *)ShmemInitStruct("CandidateFreeMap", buffer_num * sizeof(bool), &found_candidate_fm); + + // 濡傛灉宸茬粡鎵惧埌浜嗗欓夌紦鍐插尯鍜屽欓夎嚜鐢辨槧灏勶紝鍒欐柇瑷涓よ呴兘宸茬粡鎵惧埌 if (found_candidate_buf || found_candidate_fm) { Assert(found_candidate_buf && found_candidate_fm); } else { - /* The memory of the memset sometimes exceeds 2 GB. so, memset_s cannot be used. */ - MemSet((char*)g_instance.ckpt_cxt_ctl->candidate_buffers, 0, buffer_num * sizeof(Buffer)); - MemSet((char*)g_instance.ckpt_cxt_ctl->candidate_free_map, 0, buffer_num * sizeof(bool)); + // 濡傛灉鏈壘鍒帮紝鍒濆鍖栧欓夌紦鍐插尯鍜屽欓夎嚜鐢辨槧灏勭殑鍐呭瓨绌洪棿 + MemSet((char *)g_instance.ckpt_cxt_ctl->candidate_buffers, 0, buffer_num * sizeof(Buffer)); + MemSet((char *)g_instance.ckpt_cxt_ctl->candidate_free_map, 0, buffer_num * sizeof(bool)); - /* switchover will triggers the following code */ + // 濡傛灉椤靛啓鍏ヨ繘绋嬪凡缁忓垵濮嬪寲锛屽垵濮嬪寲鍊欓夊垪琛 if (g_instance.ckpt_cxt_ctl->pgwr_procs.writer_proc != NULL) { init_candidate_list(); } } } +/* + * 鍔熻兘锛氬垵濮嬪寲鍊欓夊垪琛 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庡垵濮嬪寲鍊欓夊垪琛紝鍒嗛厤鍐呭瓨骞惰缃浉鍏虫暟鎹粨鏋勶紝浠ユ敮鎸佸閲忔鏌ョ偣鎿嶄綔銆 + */ + static void init_candidate_list() { int thread_num = g_instance.ckpt_cxt_ctl->pgwr_procs.sub_num; - int normal_avg_num = SharedBufferNumber / thread_num; - int seg_avr_num = SEGMENT_BUFFER_NUM / thread_num; + int normal_avg_num = SharedBufferNumber / thread_num; // 骞冲潎姣忎釜绾跨▼鐨勬櫘閫氬欓夌紦鍐插尯鏁伴噺 + int seg_avr_num = SEGMENT_BUFFER_NUM / thread_num; // 骞冲潎姣忎釜绾跨▼鐨勬鍊欓夌紦鍐插尯鏁伴噺 PageWriterProc *pgwr = NULL; - /* Init main thread, the candidate list only store segment buffer */ + /* 鍒濆鍖栦富绾跨▼锛屽欓夊垪琛ㄤ粎瀛樺偍娈电紦鍐插尯 */ pgwr = &g_instance.ckpt_cxt_ctl->pgwr_procs.writer_proc[0]; pgwr->cand_buf_list = NULL; pgwr->cand_list_size = 0; @@ -372,19 +455,21 @@ static void init_candidate_list() int end = start + normal_avg_num; int seg_start = SegmentBufferStartID + seg_avr_num * (i - 1); int seg_end = seg_start + seg_avr_num; + + // 濡傛灉鏄渶鍚庝竴涓嚎绋嬶紝璋冩暣缁撴潫绱㈠紩浠ュ鐞嗗墿浣欑殑缂撳啿鍖 if (i == thread_num) { end += SharedBufferNumber % thread_num; seg_end += SEGMENT_BUFFER_NUM % thread_num; } - /* init normal candidat list */ + /* 鍒濆鍖栨櫘閫氬欓夊垪琛 */ pgwr->head = 0; pgwr->tail = 0; pgwr->buf_id_start = start; pgwr->cand_list_size = end - start; pgwr->cand_buf_list = &g_instance.ckpt_cxt_ctl->candidate_buffers[start]; - /* init segment candidat list */ + /* 鍒濆鍖栨鍊欓夊垪琛 */ pgwr->seg_head = 0; pgwr->seg_tail = 0; pgwr->seg_cand_list_size = seg_end - seg_start; @@ -392,75 +477,137 @@ static void init_candidate_list() pgwr->seg_id_start = seg_start; } } - +/* + * 鍔熻兘锛氳幏鍙栬剰椤甸槦鍒楀ご缂撳啿鍖 + * + * 杩斿洖鍊硷細鑴忛〉闃熷垪澶寸紦鍐插尯鐨勭储寮 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庤幏鍙栬剰椤甸槦鍒楃殑澶寸紦鍐插尯銆傚畠浠庡師瀛愬彉閲忎腑璇诲彇闃熷垪澶翠綅缃紝璁$畻瀹為檯浣嶇疆锛屽苟杩斿洖瀵瑰簲缂撳啿鍖虹殑绱㈠紩銆 + */ int get_dirty_page_queue_head_buffer() { + // 璇诲彇鑴忛〉闃熷垪澶撮儴鐨勪綅缃 uint64 dirty_queue_head = pg_atomic_read_u64(&g_instance.ckpt_cxt_ctl->dirty_page_queue_head); + // 璁$畻瀹為檯浣嶇疆 uint64 actual_loc = dirty_queue_head % g_instance.ckpt_cxt_ctl->dirty_page_queue_size; + // 杩斿洖鑴忛〉闃熷垪澶撮儴鐨勭紦鍐插尯缂栧彿 return g_instance.ckpt_cxt_ctl->dirty_page_queue[actual_loc].buffer; } - -bool is_dirty_page_queue_full(BufferDesc* buf) +/* + * 鍔熻兘锛氭鏌ヨ剰椤甸槦鍒楁槸鍚﹀凡婊 + * + * 鍙傛暟鍒楄〃锛 + * buf锛氳妫鏌ョ殑缂撳啿鍖烘弿杩扮 + * + * 杩斿洖鍊硷細濡傛灉鑴忛〉闃熷垪宸叉弧锛岃繑鍥瀟rue锛涘惁鍒欙紝杩斿洖false + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庢鏌ヨ剰椤甸槦鍒楁槸鍚﹀凡婊°傚鏋滆剰椤垫暟閲忓凡杈惧埌闃熷垪瀹归噺鐨勪竴瀹氱櫨鍒嗘瘮锛屽苟涓斿綋鍓嶇嚎绋嬫病鏈夋寔鏈夐槦鍒楀ご缂撳啿鍖虹殑閿侊紝 + * 鍒欒涓洪槦鍒楀凡婊★紝杩斿洖true銆 + */ +bool is_dirty_page_queue_full(BufferDesc *buf) { + // 妫鏌ヨ剰椤垫暟閲忔槸鍚﹀凡杈惧埌涓瀹氱櫨鍒嗘瘮 if ((get_dirty_page_num() >= - g_instance.ckpt_cxt_ctl->dirty_page_queue_size * PAGE_QUEUE_SLOT_USED_MAX_PERCENTAGE) && + g_instance.ckpt_cxt_ctl->dirty_page_queue_size * PAGE_QUEUE_SLOT_USED_MAX_PERCENTAGE) && g_instance.ckpt_cxt_ctl->backend_wait_lock != buf->content_lock) { + // 鑾峰彇鑴忛〉闃熷垪澶撮儴鐨勭紦鍐插尯 Buffer queue_head_buffer = get_dirty_page_queue_head_buffer(); + // 濡傛灉闃熷垪澶撮儴缂撳啿鍖烘湁鏁 if (!BufferIsInvalid(queue_head_buffer)) { - BufferDesc* queue_head_buffer_desc = GetBufferDescriptor(queue_head_buffer - 1); + // 鑾峰彇闃熷垪澶撮儴缂撳啿鍖虹殑鎻忚堪绗 + BufferDesc *queue_head_buffer_desc = GetBufferDescriptor(queue_head_buffer - 1); + // 濡傛灉褰撳墠绾跨▼娌℃湁鎸佹湁闃熷垪澶寸紦鍐插尯鐨勯攣 if (!LWLockHeldByMeInMode(queue_head_buffer_desc->content_lock, LW_EXCLUSIVE)) { + // 璁や负闃熷垪宸叉弧锛岃繑鍥瀟rue return true; } } else { + // 濡傛灉闃熷垪澶撮儴缂撳啿鍖烘棤鏁堬紝涔熻涓洪槦鍒楀凡婊★紝杩斿洖true return true; } } + // 闃熷垪鏈弧锛岃繑鍥瀎alse return false; } -bool atomic_push_pending_flush_queue(Buffer buffer, XLogRecPtr* queue_head_lsn, uint64* new_tail_loc) +/* + * 鍔熻兘锛氬師瀛愭柟寮忓皢缂撳啿鍖烘帹閫佸埌寰呭埛鏂伴槦鍒 + * + * 鍙傛暟鍒楄〃锛 + * buffer锛氳鎺ㄩ佺殑缂撳啿鍖 + * queue_head_lsn锛氶槦鍒楀ご閮ㄧ殑LSN鍊 + * new_tail_loc锛氭柊鐨勯槦鍒楀熬閮ㄤ綅缃 + * + * 杩斿洖鍊硷細濡傛灉鎴愬姛鎺ㄩ佺紦鍐插尯鍒伴槦鍒楋紝杩斿洖true锛涘惁鍒欙紝杩斿洖false + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庡皢缂撳啿鍖哄師瀛愭柟寮忔帹閫佸埌寰呭埛鏂伴槦鍒椼傚畠棣栧厛姣旇緝骞朵氦鎹㈤槦鍒楃殑澶撮儴LSN鍜屽熬閮ㄤ綅缃紝鐒跺悗妫鏌 + * 寰呭埛鏂伴槦鍒楁槸鍚﹀凡婊★紝濡傛灉闃熷垪宸叉弧鍒欒繑鍥瀎alse銆傚鏋滈槦鍒楁湭婊★紝灏嗙紦鍐插尯鎺ㄩ佸埌闃熷垪锛屽苟杩斿洖true銆 + */ +bool atomic_push_pending_flush_queue(Buffer buffer, XLogRecPtr *queue_head_lsn, uint64 *new_tail_loc) { + // 瀹氫箟姣旇緝銆佷氦鎹㈠拰褰撳墠鍊肩殑鍙橀噺 uint128_u compare; uint128_u exchange; uint128_u current; - - compare = atomic_compare_and_swap_u128((uint128_u*)&g_instance.ckpt_cxt_ctl->dirty_page_queue_reclsn); + // 浣跨敤鍘熷瓙鏂瑰紡姣旇緝鍜屼氦鎹㈤槦鍒楃殑LSN鍊 + compare = atomic_compare_and_swap_u128((uint128_u *)&g_instance.ckpt_cxt_ctl->dirty_page_queue_reclsn); + // 鏂█纭繚LSN鍊肩殑澶у皬绗﹀悎棰勬湡 Assert(sizeof(g_instance.ckpt_cxt_ctl->dirty_page_queue_reclsn) == SIZE_OF_UINT64); Assert(sizeof(g_instance.ckpt_cxt_ctl->dirty_page_queue_tail) == SIZE_OF_UINT64); - loop: + // 璁剧疆浜ゆ崲鍊间负姣旇緝鍊肩殑鎷疯礉锛屽苟灏嗗熬閮ㄤ綅缃姞1 exchange.u64[0] = compare.u64[0]; exchange.u64[1] = compare.u64[1] + 1; *new_tail_loc = exchange.u64[1]; - + // 妫鏌ュ緟鍒锋柊闃熷垪鏄惁宸叉弧锛屽鏋滃凡婊″垯杩斿洖false if ((uint64)(get_dirty_page_num() + PAGE_QUEUE_SLOT_MIN_RESERVE_NUM) >= g_instance.ckpt_cxt_ctl->dirty_page_queue_size) { return false; } - - current = atomic_compare_and_swap_u128( - (uint128_u*)&g_instance.ckpt_cxt_ctl->dirty_page_queue_reclsn, compare, exchange); - + // 浣跨敤鍘熷瓙鏂瑰紡姣旇緝鍜屼氦鎹㈤槦鍒楃殑LSN鍊煎拰灏鹃儴浣嶇疆 + current = + atomic_compare_and_swap_u128((uint128_u *)&g_instance.ckpt_cxt_ctl->dirty_page_queue_reclsn, compare, exchange); + // 濡傛灉姣旇緝鍜屼氦鎹㈠け璐ワ紝閲嶈瘯 if (!UINT128_IS_EQUAL(compare, current)) { UINT128_COPY(compare, current); goto loop; } - + // 璁剧疆闃熷垪澶撮儴鐨凩SN鍊间负褰撳墠鍊肩殑绗竴涓64浣 *queue_head_lsn = current.u64[0]; + // 鍑忓幓1浠ユ洿鏂版柊鐨勫熬閮ㄤ綅缃 *new_tail_loc -= 1; return true; } +/* + * 鍔熻兘锛氬皢缂撳啿鍖烘帹閫佸埌寰呭埛鏂伴槦鍒 + * + * 鍙傛暟鍒楄〃锛 + * buffer锛氳鎺ㄩ佺殑缂撳啿鍖 + * + * 杩斿洖鍊硷細濡傛灉鎴愬姛鎺ㄩ佺紦鍐插尯鍒伴槦鍒楋紝杩斿洖true锛涘惁鍒欙紝杩斿洖false + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庡皢缂撳啿鍖烘帹閫佸埌寰呭埛鏂伴槦鍒椼傚畠棣栧厛妫鏌ョ紦鍐插尯鐨凩SN鏄惁鏃犳晥锛屽鏋滀笉鏄棤鏁堢殑LSN锛屽垯杩斿洖false銆 + * 濡傛灉LSN鏃犳晥锛屾牴鎹钩鍙扮殑涓嶅悓浣跨敤涓嶅悓鐨勬柟寮忔帹閫佺紦鍐插尯鍒伴槦鍒椼傚鏋滅紦鍐插尯鏁伴噺杈惧埌闄愬埗锛屽垯杩斿洖false銆 + * 鍚﹀垯锛屽皢缂撳啿鍖烘帹閫佸埌闃熷垪锛屾洿鏂癓SN鍜岄槦鍒椾綅缃瓑淇℃伅锛屽苟杩斿洖true銆 + */ bool push_pending_flush_queue(Buffer buffer) { uint64 new_tail_loc = 0; uint64 actual_loc; XLogRecPtr queue_head_lsn = InvalidXLogRecPtr; - BufferDesc* buf_desc = GetBufferDescriptor(buffer - 1); + BufferDesc *buf_desc = GetBufferDescriptor(buffer - 1); bool push_finish = false; + // 鏂█纭繚缂撳啿鍖虹殑LSN鏃犳晥 Assert(XLogRecPtrIsInvalid(pg_atomic_read_u64(&buf_desc->rec_lsn))); + + // 鏍规嵁骞冲彴浣跨敤涓嶅悓鐨勬柟寮忔帹閫佺紦鍐插尯鍒伴槦鍒 #if defined(__x86_64__) || defined(__aarch64__) push_finish = atomic_push_pending_flush_queue(buffer, &queue_head_lsn, &new_tail_loc); if (!push_finish) { @@ -469,6 +616,7 @@ bool push_pending_flush_queue(Buffer buffer) #else SpinLockAcquire(&g_instance.ckpt_cxt_ctl->queue_lock); + // 妫鏌ラ槦鍒楁槸鍚﹀凡婊★紝濡傛灉宸叉弧鍒欓噴鏀捐嚜鏃嬮攣骞惰繑鍥瀎alse if ((uint64)(get_dirty_page_num() + PAGE_QUEUE_SLOT_MIN_RESERVE_NUM) >= g_instance.ckpt_cxt_ctl->dirty_page_queue_size) { SpinLockRelease(&g_instance.ckpt_cxt_ctl->queue_lock); @@ -479,6 +627,7 @@ bool push_pending_flush_queue(Buffer buffer) SpinLockRelease(&g_instance.ckpt_cxt_ctl->queue_lock); #endif + // 鏇存柊缂撳啿鍖虹殑LSN鍊煎拰浣嶇疆淇℃伅 pg_atomic_write_u64(&buf_desc->rec_lsn, queue_head_lsn); actual_loc = new_tail_loc % g_instance.ckpt_cxt_ctl->dirty_page_queue_size; buf_desc->dirty_queue_loc = actual_loc; @@ -489,19 +638,44 @@ bool push_pending_flush_queue(Buffer buffer) return true; } -void remove_dirty_page_from_queue(BufferDesc* buf) +/* + * 鍔熻兘锛氫粠鑴忛〉闃熷垪涓Щ闄ょ紦鍐插尯 + * + * 鍙傛暟鍒楄〃锛 + * buf锛氳浠庨槦鍒椾腑绉婚櫎鐨勭紦鍐插尯 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庝粠鑴忛〉闃熷垪涓Щ闄ょ紦鍐插尯銆傚畠棣栧厛鏂█缂撳啿鍖虹殑dirty_queue_loc涓嶆槸PG_UINT64_MAX锛屼互纭繚缂撳啿鍖哄湪闃熷垪涓 + * 鐒跺悗锛屽皢缂撳啿鍖哄湪闃熷垪涓殑浣嶇疆鏍囪涓虹┖锛屽皢缂撳啿鍖虹殑LSN鏍囪涓烘棤鏁堬紝灏嗙紦鍐插尯鐨刣irty_queue_loc鏍囪涓篜G_UINT64_MAX锛 + * 骞堕掑噺鑴忛〉闃熷垪涓殑瀹為檯鑴忛〉鏁伴噺銆 + */ +void remove_dirty_page_from_queue(BufferDesc *buf) { + // 鏂█纭繚缂撳啿鍖哄湪闃熷垪涓 Assert(buf->dirty_queue_loc != PG_UINT64_MAX); + // 灏嗙紦鍐插尯鍦ㄩ槦鍒椾腑鐨勪綅缃爣璁颁负绌 g_instance.ckpt_cxt_ctl->dirty_page_queue[buf->dirty_queue_loc].buffer = 0; + // 灏嗙紦鍐插尯鐨凩SN鏍囪涓烘棤鏁 pg_atomic_write_u64(&buf->rec_lsn, InvalidXLogRecPtr); + // 灏嗙紦鍐插尯鐨刣irty_queue_loc鏍囪涓篜G_UINT64_MAX buf->dirty_queue_loc = PG_UINT64_MAX; + // 閫掑噺鑴忛〉闃熷垪涓殑瀹為檯鑴忛〉鏁伴噺 (void)pg_atomic_fetch_sub_u32(&g_instance.ckpt_cxt_ctl->actual_dirty_page_num, 1); } +/* + * 鍔熻兘锛氳幏鍙栬剰椤甸槦鍒楃殑灏鹃儴浣嶇疆 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庤幏鍙栬剰椤甸槦鍒楃殑灏鹃儴浣嶇疆銆傛牴鎹綋绯荤粨鏋勭殑涓嶅悓锛屽畠浣跨敤涓嶅悓鐨勬柟寮忚鍙栭槦鍒楀熬閮ㄤ綅缃 + * 瀵逛簬x86_64鍜宎arch64浣撶郴缁撴瀯锛屼娇鐢ㄥ師瀛愭搷浣減g_atomic_barrier_read_u64()鏉ヨ鍙栧熬閮ㄤ綅缃 + * 瀵逛簬鍏朵粬浣撶郴缁撴瀯锛屼娇鐢ㄨ嚜鏃嬮攣鏉ヤ繚鎶ゅ苟璇诲彇灏鹃儴浣嶇疆銆 + */ uint64 get_dirty_page_queue_tail() { uint64 tail = 0; + // 鏍规嵁浣撶郴缁撴瀯鐨勪笉鍚岋紝閲囩敤涓嶅悓鐨勬柟寮忚鍙栭槦鍒楀熬閮ㄤ綅缃 #if defined(__x86_64__) || defined(__aarch64__) tail = pg_atomic_barrier_read_u64(&g_instance.ckpt_cxt_ctl->dirty_page_queue_tail); #else @@ -513,11 +687,23 @@ uint64 get_dirty_page_queue_tail() return tail; } +/* + * 鍔熻兘锛氳幏鍙栬剰椤垫暟閲 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庤幏鍙栬剰椤甸槦鍒椾腑鐨勮剰椤垫暟閲忋傚畠閫氳繃璇诲彇鑴忛〉闃熷垪鐨勫ご閮ㄥ拰灏鹃儴浣嶇疆锛 + * 璁$畻涓よ呬箣闂寸殑宸兼潵纭畾鑴忛〉鐨勬暟閲忋備娇鐢╲olatile鍏抽敭瀛椾慨楗癲irty_page_head锛 + * 浠ョ‘淇濈紪璇戝櫒涓嶄細瀵瑰叾杩涜浼樺寲銆 + */ int64 get_dirty_page_num() { + // 璇诲彇鑴忛〉闃熷垪鐨勫ご閮ㄤ綅缃 volatile uint64 dirty_page_head = pg_atomic_read_u64(&g_instance.ckpt_cxt_ctl->dirty_page_queue_head); + // 鑾峰彇鑴忛〉闃熷垪鐨勫熬閮ㄤ綅缃 uint64 dirty_page_tail = get_dirty_page_queue_tail(); + // 璁$畻鑴忛〉鏁伴噺 int64 page_num = dirty_page_tail - dirty_page_head; + // 纭繚鑴忛〉鏁伴噺涓嶅皬浜0 Assert(page_num >= 0); return page_num; } @@ -569,54 +755,75 @@ static uint32 ckpt_get_expected_flush_num() * @out Offset to the new head * @return Actual number of dirty pages need to flush */ -const int MAX_SCAN_NUM = 131072; /* 1GB buffers */ +const int MAX_SCAN_NUM = 131072; /* 1GB buffers */ +/* + * 鍔熻兘锛氬鑴忛〉闃熷垪杩涜鎺掑簭浠ュ噯澶囧埛鏂 + * + * 鍙傛暟鍒楄〃锛 + * is_new_relfilenode锛氭寚绀烘槸鍚﹀瓨鍦ㄦ柊鐨勫叧绯绘枃浠惰妭鐐 + * flush_queue_num锛氳鍒锋柊鐨勮剰椤甸槦鍒楃殑鏁伴噺 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庡鑴忛〉闃熷垪涓殑鑴忛〉杩涜鎺掑簭锛屼互鍑嗗鍒锋柊鎿嶄綔銆傚畠浼氭牴鎹竴瀹氱殑绛栫暐閫夋嫨瑕佸埛鏂扮殑鑴忛〉锛 + * 骞跺皢瀹冧滑瀛樺偍鍦–kptBufferIds鏁扮粍涓傚悓鏃讹紝鍑芥暟浼氭洿鏂癷s_new_relfilenode浠ユ寚绀烘槸鍚﹀瓨鍦ㄦ柊鐨勫叧绯绘枃浠惰妭鐐广 + */ static uint32 ckpt_qsort_dirty_page_for_flush(bool *is_new_relfilenode, uint32 flush_queue_num) { - uint32 num_to_flush = 0; - errno_t rc; - uint32 i; - uint32 scan_end = 0; - int64 dirty_page_num; - uint64 dirty_queue_head; - uint32 buf_num = TOTAL_BUFFER_NUM; - uint32 buffer_slot_num = MIN(flush_queue_num, buf_num); + uint32 num_to_flush = 0; // 瑕佸埛鏂扮殑鑴忛〉鏁伴噺 + errno_t rc; // 鐢ㄤ簬澶勭悊杩斿洖鍊肩殑鍙橀噺 + uint32 i; // 寰幆璁℃暟鍙橀噺 + uint32 scan_end = 0; // 鎵弿缁撴潫浣嶇疆 + int64 dirty_page_num; // 鑴忛〉鏁伴噺 + uint64 dirty_queue_head; // 鑴忛〉闃熷垪澶撮儴浣嶇疆 + uint32 buf_num = TOTAL_BUFFER_NUM; // 鎬荤殑缂撳啿鍖烘暟閲 + uint32 buffer_slot_num = MIN(flush_queue_num, buf_num); // 瑕佸埛鏂扮殑缂撳啿鍖烘Ы鏁伴噺锛屼笉瓒呰繃flush_queue_num鍜宐uf_num - rc = memset_s(g_instance.ckpt_cxt_ctl->CkptBufferIds, buffer_slot_num * sizeof(CkptSortItem), - 0, buffer_slot_num * sizeof(CkptSortItem)); + // 鍒濆鍖朇kptBufferIds鏁扮粍 + rc = memset_s(g_instance.ckpt_cxt_ctl->CkptBufferIds, buffer_slot_num * sizeof(CkptSortItem), 0, + buffer_slot_num * sizeof(CkptSortItem)); securec_check(rc, "", ""); /* - * Before selecting a batch of dirty pages to flush, move dirty page queue head to - * skip slot of invalid buffer of queue head. + * 鍦ㄩ夋嫨涓鎵硅鍒锋柊鐨勮剰椤典箣鍓嶏紝灏嗚剰椤甸槦鍒楀ご閮ㄧЩ鍔紝璺宠繃闃熷垪澶撮儴鐨勬棤鏁堢紦鍐叉Ы銆 */ ckpt_try_prune_dirty_page_queue(); + + // 绉诲姩鍒伴槦鍒楀ご閮ㄧ殑鏃犳晥鍏冪礌 ckpt_try_skip_invalid_elem_in_queue_head(); + + // 鑾峰彇鑴忛〉鏁伴噺鍜岃剰椤甸槦鍒楀ご閮ㄤ綅缃 dirty_page_num = get_dirty_page_num(); dirty_queue_head = pg_atomic_read_u64(&g_instance.ckpt_cxt_ctl->dirty_page_queue_head); + + // 纭畾瑕佹壂鎻忕殑缁撴潫浣嶇疆锛屾渶澶氭壂鎻廙AX_SCAN_NUM涓剰椤 scan_end = MIN(MAX_SCAN_NUM, dirty_page_num); + // 寰幆鎵弿鑴忛〉闃熷垪 for (i = 0; i < scan_end; i++) { uint32 buf_state; Buffer buffer; - BufferDesc* buf_desc = NULL; - CkptSortItem* item = NULL; + BufferDesc *buf_desc = NULL; + CkptSortItem *item = NULL; uint64 temp_loc = (dirty_queue_head + i) % g_instance.ckpt_cxt_ctl->dirty_page_queue_size; - volatile DirtyPageQueueSlot* slot = &g_instance.ckpt_cxt_ctl->dirty_page_queue[temp_loc]; + volatile DirtyPageQueueSlot *slot = &g_instance.ckpt_cxt_ctl->dirty_page_queue[temp_loc]; - /* slot location is pre-occupied, but the buffer not set finish, need break. */ + /* 濡傛灉妲戒綅鐨勭姸鎬佹棤鏁堬紝璇存槑妲戒綅宸茶娓呯┖锛岃烦鍑哄惊鐜 */ if (!(pg_atomic_read_u32(&slot->slot_state) & SLOT_VALID)) { break; } pg_memory_barrier(); buffer = slot->buffer; - /* slot state is valid, buffer is invalid, the slot buffer set 0 when BufferAlloc or InvalidateBuffer */ + + /* 濡傛灉缂撳啿鍖烘棤鏁堬紝璇存槑璇ヨ剰椤靛凡琚Щ闄わ紝缁х画涓嬩竴涓Ы浣嶇殑澶勭悊 */ if (BufferIsInvalid(buffer)) { - continue; /* this tempLoc maybe set 0 when remove dirty page */ + continue; } + // 鑾峰彇缂撳啿鍖烘弿杩扮 buf_desc = GetBufferDescriptor(buffer - 1); buf_state = LockBufHdr(buf_desc); + // 濡傛灉缂撳啿鍖虹姸鎬佷负鑴忛〉锛屽垯鍔犲叆瑕佸埛鏂扮殑闃熷垪涓 if (buf_state & BM_DIRTY) { buf_state |= BM_CHECKPOINT_NEEDED; item = &g_instance.ckpt_cxt_ctl->CkptBufferIds[num_to_flush++]; @@ -626,7 +833,7 @@ static uint32 ckpt_qsort_dirty_page_for_flush(bool *is_new_relfilenode, uint32 f item->bucketNode = buf_desc->tag.rnode.bucketNode; item->forkNum = buf_desc->tag.forkNum; item->blockNum = buf_desc->tag.blockNum; - if(IsSegmentFileNode(buf_desc->tag.rnode) || buf_desc->tag.rnode.opt != 0) { + if (IsSegmentFileNode(buf_desc->tag.rnode) || buf_desc->tag.rnode.opt != 0) { *is_new_relfilenode = true; } } @@ -637,46 +844,71 @@ static uint32 ckpt_qsort_dirty_page_for_flush(bool *is_new_relfilenode, uint32 f } } + // 瀵规帓搴忓悗鐨勮剰椤佃繘琛屾帓搴 qsort(g_instance.ckpt_cxt_ctl->CkptBufferIds, num_to_flush, sizeof(CkptSortItem), ckpt_buforder_comparator); return num_to_flush; } +/* + * 鍔熻兘锛氬敜閱掑瓙绾跨▼ + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庡敜閱掑瓙绾跨▼锛屼娇瀹冧滑寮濮嬪伐浣溿傚畠灏嗛噸缃瓙绾跨▼鐨勭姸鎬佸拰闇瑕佸埛鏂扮殑鏁伴噺锛 + * 鐒跺悗閫氳繃璁剧疆绾跨▼鐨刾rocLatch鏉ヨЕ鍙戠嚎绋嬬殑鎵ц銆 + */ static void wakeup_sub_thread() { PageWriterProc *pgwr = NULL; + // 閬嶅巻瀛愮嚎绋嬪垪琛紝璺宠繃涓荤嚎绋 for (int thread_loc = 1; thread_loc < g_instance.ckpt_cxt_ctl->pgwr_procs.num; thread_loc++) { pgwr = &g_instance.ckpt_cxt_ctl->pgwr_procs.writer_proc[thread_loc]; + // 閲嶇疆瀛愮嚎绋嬬殑鐘舵佸拰闇瑕佸埛鏂扮殑鏁伴噺 pgwr->start_loc = 0; pgwr->need_flush_num = 0; - if (pgwr->proc != NULL) { + // 澧炲姞杩愯涓殑瀛愮嚎绋嬭鏁 (void)pg_atomic_add_fetch_u32(&g_instance.ckpt_cxt_ctl->pgwr_procs.running_num, 1); pg_write_barrier(); + // 璁剧疆瀛愮嚎绋嬮渶瑕佸埛鏂版暟鎹殑鏍囧織 g_instance.ckpt_cxt_ctl->pgwr_procs.writer_proc[thread_loc].need_flush = true; pg_write_barrier(); + // 瑙﹀彂绾跨▼鎵ц SetLatch(&(pgwr->proc->procLatch)); } } } +/* + * 鍔熻兘锛氬噯澶囪剰椤靛簲鐢ㄧ姸鎬 + * + * 鍙傛暟鍒楄〃锛 + * requested_flush_num锛氳姹傚埛鏂扮殑鑴忛〉鏁伴噺 + * is_new_relfilenode锛氭槸鍚︿负鏂扮殑relfilenode + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庡噯澶囪剰椤电殑搴旂敤鐘舵併傚畠鍒濆鍖栦竴浜涜鏁板櫒鍜岀姸鎬侊紝浠ュ強鏍囧織鏄惁涓烘柊鐨剅elfilenode銆 + */ static void prepare_dirty_page_applied_state(uint32 requested_flush_num, bool is_new_relfilenode) { int thread_loc; int thread_num; - + // 鍒濆鍖栬鏁板櫒 pg_atomic_init_u32(&g_instance.ckpt_cxt_ctl->CkptBufferIdsCompletedPages, 0); pg_atomic_init_u32(&g_instance.ckpt_cxt_ctl->CkptBufferIdsTail, 0); + // 璁剧疆璇锋眰鍒锋柊鐨勮剰椤垫暟閲 g_instance.ckpt_cxt_ctl->CkptBufferIdsFlushPages = requested_flush_num; + // 鑾峰彇绾跨▼鏁 thread_num = g_instance.ckpt_cxt_ctl->pgwr_procs.num; - PageWriterProc* pgwr; - + PageWriterProc *pgwr; + // 璁剧疆鏄惁涓烘柊鐨剅elfilenode g_instance.dw_batch_cxt.is_new_relfilenode = is_new_relfilenode; + // 閬嶅巻瀛愮嚎绋嬶紝鐩墠娌℃湁瀹為檯鎿嶄綔 for (thread_loc = 1; thread_loc < thread_num; thread_loc++) { pgwr = &g_instance.ckpt_cxt_ctl->pgwr_procs.writer_proc[thread_loc]; } - pg_write_barrier(); + // 鍒濆鍖栧噯澶囩姸鎬 pg_atomic_init_u32(&g_instance.ckpt_cxt_ctl->prepared, 1); pg_write_barrier(); } @@ -699,7 +931,7 @@ static void ckpt_move_queue_head_after_flush() /* Finish flush dirty page, move the dirty page queue head, and clear the slot state. */ for (uint32 i = 0; i < dirty_page_num; i++) { uint64 temp_loc = (dirty_queue_head + i) % g_instance.ckpt_cxt_ctl->dirty_page_queue_size; - volatile DirtyPageQueueSlot* slot = &g_instance.ckpt_cxt_ctl->dirty_page_queue[temp_loc]; + volatile DirtyPageQueueSlot *slot = &g_instance.ckpt_cxt_ctl->dirty_page_queue[temp_loc]; if (!(pg_atomic_read_u32(&slot->slot_state) & SLOT_VALID)) { break; } @@ -729,8 +961,8 @@ static void ckpt_move_queue_head_after_flush() if (u_sess->attr.attr_storage.log_pagewriter) { ereport(LOG, (errmodule(MOD_INCRE_CKPT), - errmsg("Page Writer flushed: %u pages, remaining dirty_page_num: %ld", - g_instance.ckpt_cxt_ctl->page_writer_last_flush, get_dirty_page_num()))); + errmsg("Page Writer flushed: %u pages, remaining dirty_page_num: %ld", + g_instance.ckpt_cxt_ctl->page_writer_last_flush, get_dirty_page_num()))); } return; } @@ -739,76 +971,110 @@ static void ckpt_move_queue_head_after_flush() * @Description: pagewriter main thread select one batch dirty page, divide this batch page to all thread, * wait all thread finish flush, update the statistics. */ +/* + * 鍔熻兘锛氭鏌ュ苟鍒锋柊鑴忛〉 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庢鏌ュ苟鍒锋柊鑴忛〉銆傚畠鍒濆鍖栧啓鍥炰笂涓嬫枃銆佽幏鍙栭鏈熷埛鏂版暟閲忥紝骞舵牴鎹剰椤垫帓搴忚幏鍙栬姹傚埛鏂版暟閲忋 + * 鎺ョ潃鍑嗗鑴忛〉鐨勫簲鐢ㄧ姸鎬侊紝鍞ら啋瀛愮嚎绋嬶紝鏈鍚庡畬鎴愬埛鏂版搷浣溿 + */ static void ckpt_pagewriter_main_thread_flush_dirty_page() { - WritebackContext wb_context; - uint32 requested_flush_num; - int32 expected_flush_num; - bool is_new_relfilenode = false; - + WritebackContext wb_context; // 鍐欏洖涓婁笅鏂 + uint32 requested_flush_num; // 璇锋眰鍒锋柊鐨勮剰椤垫暟閲 + int32 expected_flush_num; // 棰勬湡鍒锋柊鐨勮剰椤垫暟閲 + bool is_new_relfilenode = false; // 鏄惁涓烘柊鐨剅elfilenode + // 鏂█褰撳墠绾跨▼鏄富绾跨▼ Assert(t_thrd.pagewriter_cxt.pagewriter_id == 0); + // 鍒濆鍖栧啓鍥炰笂涓嬫枃 WritebackContextInit(&wb_context, &t_thrd.pagewriter_cxt.page_writer_after); + // 鎵╁睍璧勬簮鎷ユ湁鑰呯殑缂撳啿鍖 ResourceOwnerEnlargeBuffers(t_thrd.utils_cxt.CurrentResourceOwner); - + // 鑾峰彇棰勬湡鍒锋柊鐨勮剰椤垫暟閲 expected_flush_num = ckpt_get_expected_flush_num(); + // 濡傛灉棰勬湡鍒锋柊鏁伴噺涓0锛屽敜閱掑瓙绾跨▼骞惰繑鍥 if (expected_flush_num == 0) { - /* if not dirty page flush, wakeup sub thread can the buffer pool */ wakeup_sub_thread(); return; } - + // 閲嶇疆涓婃闃熷垪鍒锋柊鍜屽埛鏂扮殑鏃堕棿 g_instance.ckpt_cxt_ctl->page_writer_last_queue_flush = 0; g_instance.ckpt_cxt_ctl->page_writer_last_flush = 0; - + // 鏍规嵁鑴忛〉鎺掑簭鑾峰彇璇锋眰鍒锋柊鐨勮剰椤垫暟閲忥紝骞舵爣蹇楁槸鍚︿负鏂扮殑relfilenode requested_flush_num = ckpt_qsort_dirty_page_for_flush(&is_new_relfilenode, expected_flush_num); - - /* Step 1: set up atomic state for dirty page appiled. */ + // 鍑嗗鑴忛〉鐨勫簲鐢ㄧ姸鎬 prepare_dirty_page_applied_state(requested_flush_num, is_new_relfilenode); - - /* Step 2: wake up all subthreads and main thread sleep. */ + // 鍞ら啋瀛愮嚎绋 wakeup_sub_thread(); - + // 瀹屾垚鍒锋柊鎿嶄綔 ckpt_move_queue_head_after_flush(); smgrcloseall(); return; } +/* + * 鍔熻兘锛氳幏鍙栭〉鍐欏叆鍣ㄧ殑鐫$湢鏃堕棿 + * + * 杩斿洖鍊硷細 + * 杩斿洖椤靛啓鍏ュ櫒闇瑕佺潯鐪犵殑鏃堕棿锛堜互姣涓哄崟浣嶏級 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庣‘瀹氶〉鍐欏叆鍣ㄩ渶瑕佷紤鐪犵殑鏃堕棿锛屼互鎺у埗鍒锋柊鑴忛〉鐨勯鐜囥 + * 濡傛灉FULL_CKPT涓虹湡锛岃〃绀哄叏閲忔鏌ョ偣锛屼笉闇瑕佷紤鐪狅紝杩斿洖0銆 + * 鍚﹀垯锛岃绠楀綋鍓嶆椂闂村拰涓嬩竴娆″埛鏂扮殑鏃堕棿宸紝灏嗗叾闄愬埗鍦╱_sess->attr.attr_storage.pageWriterSleep涔嬪唴锛 + * 骞惰繑鍥炰紤鐪犳椂闂淬 + */ static int64 get_pagewriter_sleep_time() { - uint64 now; - int64 time_diff; - + uint64 now; // 褰撳墠鏃堕棿 + int64 time_diff; // 鏃堕棿宸 + // 濡傛灉鏄叏閲忔鏌ョ偣锛屼笉闇瑕佷紤鐪狅紝杩斿洖0 if (FULL_CKPT) { return 0; } - + // 鑾峰彇褰撳墠鏃堕棿锛堜互姣涓哄崟浣嶏級 now = get_time_ms(); + // 璁$畻涓嬩竴娆″埛鏂扮殑鏃堕棿涓庡綋鍓嶆椂闂寸殑鏃堕棿宸 if (t_thrd.pagewriter_cxt.next_flush_time > now) { time_diff = MAX(t_thrd.pagewriter_cxt.next_flush_time - now, 1); } else { time_diff = 0; } + // 灏嗘椂闂村樊闄愬埗鍦╱_sess->attr.attr_storage.pageWriterSleep涔嬪唴 time_diff = MIN(time_diff, u_sess->attr.attr_storage.pageWriterSleep); + // 杩斿洖浼戠湢鏃堕棿 return time_diff; } +/* + * 鍔熻兘锛氳幏鍙栫洰鏍嘗SN鎵鍦ㄤ綅缃殑闃熷垪浣嶇疆 + * + * 鍙傛暟锛 + * target_lsn锛氱洰鏍嘗SN锛岀敤浜庢煡鎵句綅缃 + * + * 杩斿洖鍊硷細 + * 杩斿洖鐩爣LSN鎵鍦ㄤ綅缃殑闃熷垪浣嶇疆锛坲int64绫诲瀷锛 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庢煡鎵剧洰鏍嘗SN鍦ㄨ剰椤甸槦鍒椾腑鐨勪綅缃 + * 瀹冮亶鍘嗚剰椤甸槦鍒楋紝鏍规嵁LSN鐨勬瘮杈冪‘瀹氱洰鏍嘗SN鐨勪綅缃紝骞惰繑鍥為槦鍒椾綅缃 + */ uint64 get_loc_for_lsn(XLogRecPtr target_lsn) { - uint64 last_loc = 0; - XLogRecPtr page_rec_lsn = InvalidXLogRecPtr; - uint64 queue_loc = pg_atomic_read_u64(&g_instance.ckpt_cxt_ctl->dirty_page_queue_head); - + uint64 last_loc = 0; // 鏈缁堜綅缃 + XLogRecPtr page_rec_lsn = InvalidXLogRecPtr; // 椤电殑LSN + uint64 queue_loc = pg_atomic_read_u64(&g_instance.ckpt_cxt_ctl->dirty_page_queue_head); // 闃熷垪浣嶇疆 + // 濡傛灉鑴忛〉鏁颁负0锛岃繑鍥炶剰椤甸槦鍒楃殑灏鹃儴浣嶇疆 if (get_dirty_page_num() == 0) { return get_dirty_page_queue_tail(); } - + // 閬嶅巻鑴忛〉闃熷垪锛屾煡鎵剧洰鏍嘗SN鐨勪綅缃 while (queue_loc < get_dirty_page_queue_tail()) { Buffer buffer; BufferDesc *buf_desc = NULL; uint64 temp_loc = queue_loc % g_instance.ckpt_cxt_ctl->dirty_page_queue_size; volatile DirtyPageQueueSlot *slot = &g_instance.ckpt_cxt_ctl->dirty_page_queue[temp_loc]; - - /* slot location is pre-occupied, but the buffer not set finish, need wait and retry. */ + /* slot浣嶇疆琚崰鐢紝浣嗙紦鍐插尯鏈缃畬鎴愶紝闇瑕佺瓑寰呭苟閲嶈瘯 */ if (!(pg_atomic_read_u32(&slot->slot_state) & SLOT_VALID)) { pg_usleep(1); queue_loc = pg_atomic_read_u64(&g_instance.ckpt_cxt_ctl->dirty_page_queue_head); @@ -816,53 +1082,68 @@ uint64 get_loc_for_lsn(XLogRecPtr target_lsn) } queue_loc++; pg_memory_barrier(); - buffer = slot->buffer; - /* slot state is vaild, buffer is invalid, the slot buffer set 0 when BufferAlloc or InvalidateBuffer */ + /* slot鐘舵佹湁鏁堬紝浣嗙紦鍐插尯鏃犳晥锛屽嵆缂撳啿鍖鸿缃负0锛圔ufferAlloc鎴朓nvalidateBuffer鏃剁殑鎯呭喌锛 */ if (BufferIsInvalid(buffer)) { continue; } buf_desc = GetBufferDescriptor(buffer - 1); page_rec_lsn = pg_atomic_read_u64(&buf_desc->rec_lsn); + // 濡傛灉缂撳啿鍖烘湁鏁堜笖鐩爣LSN灏忎簬绛変簬椤电殑LSN锛岀‘瀹氫綅缃苟涓柇寰幆 if (!BufferIsInvalid(slot->buffer) && XLByteLE(target_lsn, page_rec_lsn)) { last_loc = queue_loc - 1; break; } } - + // 濡傛灉鏈壘鍒颁綅缃紝杩斿洖鑴忛〉闃熷垪鐨勫熬閮ㄤ綅缃 if (last_loc == 0) { return get_dirty_page_queue_tail(); } - + // 杩斿洖鐩爣LSN鎵鍦ㄤ綅缃殑闃熷垪浣嶇疆 return last_loc; } -static uint32 get_page_num_for_lsn(XLogRecPtr target_lsn, uint32 max_num) +/* + * 鍔熻兘锛氳幏鍙栫洰鏍嘗SN涔嬪墠鐨勮剰椤垫暟閲忥紙鏈澶歮ax_num涓級 + * + * 鍙傛暟锛 + * target_lsn锛氱洰鏍嘗SN锛岀敤浜庤绠楄剰椤垫暟閲 + * max_num锛氭渶澶氳绠楃殑鑴忛〉鏁伴噺 + * + * 杩斿洖鍊硷細 + * 杩斿洖鐩爣LSN涔嬪墠鐨勮剰椤垫暟閲忥紙uint32绫诲瀷锛 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庤绠楃洰鏍嘗SN涔嬪墠鐨勮剰椤垫暟閲忥紝鏈澶氳绠梞ax_num涓 + * 瀹冮亶鍘嗚剰椤甸槦鍒楋紝鏍规嵁LSN鐨勬瘮杈冪‘瀹氳剰椤电殑鏁伴噺锛屼笉瓒呰繃max_num涓 + */ +uint32 get_page_num_for_lsn(XLogRecPtr target_lsn, uint32 max_num) { uint32 i; - uint32 num_for_lsn = 0; - XLogRecPtr page_rec_lsn = InvalidXLogRecPtr; - int64 dirty_page_num = get_dirty_page_num(); - uint64 dirty_queue_head = pg_atomic_read_u64(&g_instance.ckpt_cxt_ctl->dirty_page_queue_head); + uint32 num_for_lsn = 0; // 鐩爣LSN涔嬪墠鐨勮剰椤垫暟閲 + XLogRecPtr page_rec_lsn = InvalidXLogRecPtr; // 椤电殑LSN + int64 dirty_page_num = get_dirty_page_num(); // 鑴忛〉鏁伴噺 + uint64 dirty_queue_head = pg_atomic_read_u64(&g_instance.ckpt_cxt_ctl->dirty_page_queue_head); // 闃熷垪澶翠綅缃 + // 閬嶅巻鑴忛〉闃熷垪锛岃绠楃洰鏍嘗SN涔嬪墠鐨勮剰椤垫暟閲忥紙涓嶈秴杩噈ax_num涓級 for (i = 0; i < dirty_page_num; i++) { Buffer buffer; - BufferDesc* buf_desc = NULL; + BufferDesc *buf_desc = NULL; uint64 temp_loc = (dirty_queue_head + i) % g_instance.ckpt_cxt_ctl->dirty_page_queue_size; - volatile DirtyPageQueueSlot* slot = &g_instance.ckpt_cxt_ctl->dirty_page_queue[temp_loc]; - - /* slot location is pre-occupied, but the buffer not set finish, need break. */ + volatile DirtyPageQueueSlot *slot = &g_instance.ckpt_cxt_ctl->dirty_page_queue[temp_loc]; + /* slot浣嶇疆琚崰鐢紝浣嗙紦鍐插尯鏈缃畬鎴愶紝闇瑕佷腑鏂惊鐜 */ if (!(pg_atomic_read_u32(&slot->slot_state) & SLOT_VALID)) { break; } pg_read_barrier(); buffer = slot->buffer; - /* slot state is valid, buffer is invalid, the slot buffer set 0 when BufferAlloc or InvalidateBuffer */ + /* slot鐘舵佹湁鏁堬紝浣嗙紦鍐插尯鏃犳晥锛屽嵆缂撳啿鍖鸿缃负0锛圔ufferAlloc鎴朓nvalidateBuffer鏃剁殑鎯呭喌锛 */ if (BufferIsInvalid(buffer)) { - continue; /* this tempLoc maybe set 0 when remove dirty page */ + continue; /* 褰撶Щ闄よ剰椤垫椂锛屾tempLoc鍙兘璁剧疆涓0 */ } buf_desc = GetBufferDescriptor(buffer - 1); page_rec_lsn = pg_atomic_read_u64(&buf_desc->rec_lsn); + // 濡傛灉缂撳啿鍖烘湁鏁堜笖鐩爣LSN灏忎簬绛変簬椤电殑LSN锛岃绠楀畬鎴愬苟涓柇寰幆 if (!BufferIsInvalid(slot->buffer) && XLByteLE(target_lsn, page_rec_lsn)) { break; } @@ -876,98 +1157,114 @@ static uint32 get_page_num_for_lsn(XLogRecPtr target_lsn, uint32 max_num) const float HIGH_WATER = 0.75; const int BYTE_PER_KB = 1024; +/* + * 鍔熻兘锛氳绠楁渶澶х殑鍒锋柊鏁伴噺 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庤绠楁渶澶х殑鍒锋柊鏁伴噺锛屼互鎺у埗鍐欏叆IO鐨勯熺巼銆 + * 瀹冨熀浜嶭SN鍜岀紦鍐插尯鐨勪娇鐢ㄦ儏鍐碉紝鍔ㄦ佸湴璋冩暣闃熷垪鍒锋柊鍜屽垪琛ㄥ埛鏂扮殑鏈澶ф暟閲忋 + */ static void calculate_max_flush_num() { - uint32 blk_size = BLCKSZ / BYTE_PER_KB; - uint32 max_io = u_sess->attr.attr_storage.max_io_capacity / blk_size / 2; - float rate_lsn; - float rate_buf; - uint32 queue_flush_max; - uint32 list_flush_max; - XLogRecPtr min_lsn = InvalidXLogRecPtr; - XLogRecPtr cur_lsn = InvalidXLogRecPtr; - double lsn_percent; - + uint32 blk_size = BLCKSZ / BYTE_PER_KB; // 鍧楀ぇ灏忥紙浠B涓哄崟浣嶏級 + uint32 max_io = u_sess->attr.attr_storage.max_io_capacity / blk_size / 2; // 鏈澶O瀹归噺锛堜互鍧椾负鍗曚綅鐨勪竴鍗婏級 + float rate_lsn; // 鍩轰簬LSN鐨勫埛鏂扮巼 + float rate_buf; // 鍩轰簬缂撳啿鍖虹殑鍒锋柊鐜 + uint32 queue_flush_max; // 闃熷垪鍒锋柊鐨勬渶澶ф暟閲 + uint32 list_flush_max; // 鍒楄〃鍒锋柊鐨勬渶澶ф暟閲 + XLogRecPtr min_lsn = InvalidXLogRecPtr; // 鏈灏廘SN + XLogRecPtr cur_lsn = InvalidXLogRecPtr; // 褰撳墠LSN + double lsn_percent; // LSN浣跨敤鐧惧垎姣 + // 濡傛灉澶勪簬FULL_CKPT妯″紡涓斾笉澶勪簬鎭㈠涓紝鍒欏皢闃熷垪鍜屽垪琛ㄧ殑鏈澶у埛鏂版暟閲忛兘璁剧疆涓烘渶澶O瀹归噺鐨勪竴鍗 if (unlikely(FULL_CKPT && !RecoveryInProgress())) { g_instance.ckpt_cxt_ctl->pgwr_procs.queue_flush_max = max_io; g_instance.ckpt_cxt_ctl->pgwr_procs.list_flush_max = 0; return; } - + // 鑾峰彇鏈灏廘SN min_lsn = ckpt_get_min_rec_lsn(); if (XLogRecPtrIsInvalid(min_lsn)) { min_lsn = get_dirty_page_queue_rec_lsn(); } - - /* primary get the xlog insert loc, standby get the replay loc */ + // 濡傛灉澶勪簬鎭㈠涓紝鍒欒幏鍙栧洖鏀綥SN锛涘惁鍒欒幏鍙栧綋鍓嶆彃鍏SN if (RecoveryInProgress()) { cur_lsn = GetXLogReplayRecPtr(NULL); } else { cur_lsn = GetXLogInsertRecPtr(); } - - lsn_percent = (double)(cur_lsn - min_lsn) / - ((double)u_sess->attr.attr_storage.max_redo_log_size * BYTE_PER_KB); - + // 璁$畻LSN浣跨敤鐧惧垎姣 + lsn_percent = (double)(cur_lsn - min_lsn) / ((double)u_sess->attr.attr_storage.max_redo_log_size * BYTE_PER_KB); + // 璁$畻鍩轰簬LSN鐨勫埛鏂扮巼 rate_lsn = 1 - HIGH_WATER / (lsn_percent + HIGH_WATER); - + // 闄愬埗LSN鍒锋柊鐜囦笉瓒呰繃HIGH_WATER rate_lsn = MIN(rate_lsn, HIGH_WATER); - + // 鍩轰簬缂撳啿鍖虹殑鍒锋柊鐜囦负1鍑忓幓LSN鍒锋柊鐜 rate_buf = 1 - rate_lsn; - + // 璁$畻闃熷垪鍒锋柊鐨勬渶澶ф暟閲忓拰鍒楄〃鍒锋柊鐨勬渶澶ф暟閲 queue_flush_max = max_io * rate_lsn; list_flush_max = max_io * rate_buf; - + // 璁剧疆闃熷垪鍒锋柊鍜屽垪琛ㄥ埛鏂扮殑鏈澶ф暟閲 g_instance.ckpt_cxt_ctl->pgwr_procs.queue_flush_max = queue_flush_max; g_instance.ckpt_cxt_ctl->pgwr_procs.list_flush_max = list_flush_max; - + // 濡傛灉鍚敤浜嗘棩蹇楄褰曪紝杈撳嚭鐩稿叧淇℃伅 if (u_sess->attr.attr_storage.log_pagewriter) { - ereport(LOG, (errmodule(MOD_INCRE_CKPT), - errmsg("calculate max io, lsn_percent is %f, rate_lsn is %f, queue flush num is %u, list flush num is %u", - lsn_percent, rate_lsn, queue_flush_max, list_flush_max))); + ereport( + LOG, + (errmodule(MOD_INCRE_CKPT), + errmsg("calculate max io, lsn_percent is %f, rate_lsn is %f, queue flush num is %u, list flush num is %u", + lsn_percent, rate_lsn, queue_flush_max, list_flush_max))); } } const int AVG_CALCULATE_NUM = 30; const uint UPDATE_REC_XLOG_NUM = 4; +/* + * 鍔熻兘锛氳绠桺age Writer鐨勫埛鏂版暟閲 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庤绠桺age Writer搴旇鍒锋柊鐨勯〉闈㈡暟閲忥紝浠ユ帶鍒跺埛鏂伴熺巼銆 + * 瀹冨熀浜庡涓洜绱狅紝鍖呮嫭LSN銆佽剰椤电櫨鍒嗘瘮绛夈 + */ static uint32 calculate_pagewriter_flush_num() { - static XLogRecPtr prev_lsn = InvalidXLogRecPtr; - static XLogRecPtr avg_lsn_rate = InvalidXLogRecPtr; - static pg_time_t prev_time = 0; - static int64 total_flush_num = 0; - static uint32 avg_flush_num = 0; - static uint32 prev_lsn_num = 0; - static int counter = 0; - XLogRecPtr target_lsn; - XLogRecPtr cur_lsn; - XLogRecPtr min_lsn; - uint32 flush_num = 0; - uint64 now; - int64 time_diff; - float dirty_page_pct; - float dirty_slot_pct; - uint32 num_for_dirty; - uint32 num_for_lsn; - uint32 min_io = DW_DIRTY_PAGE_MAX_FOR_NOHBK; - uint32 max_io = g_instance.ckpt_cxt_ctl->pgwr_procs.queue_flush_max; - uint32 num_for_lsn_max; - float dirty_percent; - double lsn_target_percent = 0; - uint32 lsn_scan_factor = 3; + static XLogRecPtr prev_lsn = InvalidXLogRecPtr; // 涓婁竴娆$殑LSN + static XLogRecPtr avg_lsn_rate = InvalidXLogRecPtr; // 骞冲潎LSN閫熺巼 + static pg_time_t prev_time = 0; // 涓婁竴娆¤绠楃殑鏃堕棿 + static int64 total_flush_num = 0; // 鎬荤殑鍒锋柊鏁伴噺 + static uint32 avg_flush_num = 0; // 骞冲潎鍒锋柊鏁伴噺 + static uint32 prev_lsn_num = 0; // 涓婁竴娆SN鐨勫埛鏂版暟閲 + static int counter = 0; // 璁℃暟鍣紝鐢ㄤ簬鎺у埗璁$畻棰戠巼 + XLogRecPtr target_lsn; // 鐩爣LSN + XLogRecPtr cur_lsn; // 褰撳墠LSN + XLogRecPtr min_lsn; // 鏈灏廘SN + uint32 flush_num = 0; // 鍒锋柊鏁伴噺 + uint64 now; // 褰撳墠鏃堕棿 + int64 time_diff; // 鏃堕棿宸 + float dirty_page_pct; // 鑴忛〉鍗犳瘮 + float dirty_slot_pct; // 鑴忔Ы鍗犳瘮 + uint32 num_for_dirty; // 鐢ㄤ簬鑴忛〉鐨勬暟閲 + uint32 num_for_lsn; // 鐢ㄤ簬LSN鐨勬暟閲 + uint32 min_io = DW_DIRTY_PAGE_MAX_FOR_NOHBK; // 鏈灏廔O瀹归噺锛堟棤鐑妯″紡涓嬶級 + uint32 max_io = g_instance.ckpt_cxt_ctl->pgwr_procs.queue_flush_max; // 鏈澶O瀹归噺 + uint32 num_for_lsn_max; // LSN鏈澶ф暟閲 + float dirty_percent; // 鑴忛〉鐧惧垎姣 + double lsn_target_percent = 0; // LSN鐩爣鐧惧垎姣 + uint32 lsn_scan_factor = 3; // LSN鎵弿鍥犲瓙 + // 鑾峰彇鏈灏廘SN min_lsn = ckpt_get_min_rec_lsn(); if (XLogRecPtrIsInvalid(min_lsn)) { min_lsn = get_dirty_page_queue_rec_lsn(); } - /* primary get the xlog insert loc, standby get the replay loc */ + // 濡傛灉澶勪簬鎭㈠涓紝鍒欒幏鍙栧洖鏀綥SN锛涘惁鍒欒幏鍙栧綋鍓嶆彃鍏SN if (RecoveryInProgress()) { cur_lsn = GetXLogReplayRecPtr(NULL); } else { cur_lsn = GetXLogInsertRecPtr(); } + // 濡傛灉涓婁竴娆SN鏄棤鏁堢殑锛屽垯鍒濆鍖栦竴浜涘彉閲忓苟杩斿洖榛樿鍊 if (XLogRecPtrIsInvalid(prev_lsn)) { prev_lsn = cur_lsn; prev_time = get_time_ms(); @@ -975,38 +1272,42 @@ static uint32 calculate_pagewriter_flush_num() goto DEFAULT; } + // 绱姞鎬诲埛鏂版暟閲忓拰璁$畻鏃堕棿宸 total_flush_num += g_instance.ckpt_cxt_ctl->page_writer_last_queue_flush; now = get_time_ms(); time_diff = now - prev_time; /* - * We update our variables every AVG_CALCULATE_NUM times to smooth - * pagewriter flush page nums; + * 鎴戜滑姣忛殧AVG_CALCULATE_NUM娆℃洿鏂颁竴娆″彉閲忥紝浠ュ钩婊慞age Writer鐨勫埛鏂版暟閲忥紱 */ - if (++counter > AVG_CALCULATE_NUM || - time_diff > AVG_CALCULATE_NUM * u_sess->attr.attr_storage.pageWriterSleep) { + if (++counter > AVG_CALCULATE_NUM || time_diff > AVG_CALCULATE_NUM * u_sess->attr.attr_storage.pageWriterSleep) { time_diff = MAX(1, time_diff); - avg_flush_num = (uint32)((((double)total_flush_num) / time_diff * u_sess->attr.attr_storage.pageWriterSleep - + avg_flush_num) / 2); - avg_lsn_rate = ((double)(cur_lsn - prev_lsn) / time_diff * u_sess->attr.attr_storage.pageWriterSleep - + avg_lsn_rate) / 2; + // 璁$畻骞冲潎鍒锋柊鏁伴噺鍜屽钩鍧嘗SN閫熺巼 + avg_flush_num = (uint32)((((double)total_flush_num) / time_diff * u_sess->attr.attr_storage.pageWriterSleep + + avg_flush_num) / + 2); + avg_lsn_rate = + ((double)(cur_lsn - prev_lsn) / time_diff * u_sess->attr.attr_storage.pageWriterSleep + avg_lsn_rate) / 2; - /* reset our variables */ + // 閲嶇疆涓浜涘彉閲 prev_lsn = cur_lsn; prev_time = now; total_flush_num = 0; counter = 0; } + // 璁$畻鑴忛〉鐧惧垎姣旓紝浠ュ強鑴忔Ы鐧惧垎姣 dirty_page_pct = g_instance.ckpt_cxt_ctl->actual_dirty_page_num / (float)(g_instance.attr.attr_storage.NBuffers); dirty_slot_pct = get_dirty_page_num() / (float)(g_instance.ckpt_cxt_ctl->dirty_page_queue_size); dirty_percent = MAX(dirty_page_pct, dirty_slot_pct) / u_sess->attr.attr_storage.dirty_page_percent_max; + // 濡傛灉澶勪簬鎭㈠涓紝鍒欏皢鏈澶O瀹归噺闄嶄綆鍒90% if (RecoveryInProgress()) { max_io = max_io * 0.9; } + // 鏍规嵁鑴忛〉鐧惧垎姣旇绠楃敤浜庤剰椤电殑鏁伴噺鍜孡SN鐨勬暟閲忎笂闄 if (dirty_percent < HIGH_WATER) { num_for_dirty = min_io; num_for_lsn_max = max_io; @@ -1018,29 +1319,34 @@ static uint32 calculate_pagewriter_flush_num() num_for_lsn_max = max_io * 2; } - lsn_target_percent = (double)(cur_lsn - min_lsn) / - ((double)u_sess->attr.attr_storage.max_redo_log_size * BYTE_PER_KB); + // 璁$畻LSN鐨勭洰鏍囩櫨鍒嗘瘮 + lsn_target_percent = + (double)(cur_lsn - min_lsn) / ((double)u_sess->attr.attr_storage.max_redo_log_size * BYTE_PER_KB); + /* - * If the xlog generation speed is slower than dirty queue rec lsn update speed and not many dirty pages, - * no need to scan too many dirty page, because the dirty page rec lsn is same. + * 濡傛灉XLOG鐢熸垚閫熷害鎱簬鑴忛〉闃熷垪鐨凩SN鏇存柊閫熷害锛屼笖鑴忛〉杈冨皯锛 + * 鍒欎笉闇瑕佹壂鎻忓お澶氳剰椤碉紝鍥犱负鑴忛〉鐨凩SN鐩稿悓銆 */ if (dirty_percent < HIGH_WATER && avg_lsn_rate < XLOG_SEG_SIZE * UPDATE_REC_XLOG_NUM && lsn_target_percent < HIGH_WATER) { lsn_scan_factor = 1; } + // 璁$畻鐩爣LSN骞惰幏鍙栫敤浜嶭SN鐨勯〉闈㈡暟閲 target_lsn = min_lsn + avg_lsn_rate * lsn_scan_factor; num_for_lsn = get_page_num_for_lsn(target_lsn, num_for_lsn_max); + // 濡傛灉LSN鐩爣鐧惧垎姣斾綆浜嶩IGH_WATER锛屽皢鐢ㄤ簬LSN鐨勬暟閲忛櫎浠SN鎵弿鍥犲瓙骞堕檺鍒朵负max_io if (lsn_target_percent < HIGH_WATER) { num_for_lsn = MIN(num_for_lsn / lsn_scan_factor, max_io); } else if (lsn_target_percent < 1) { num_for_lsn = MIN(num_for_lsn / lsn_scan_factor, max_io) + - (float)(lsn_target_percent - HIGH_WATER) / (float)(1 - HIGH_WATER) * max_io; + (float)(lsn_target_percent - HIGH_WATER) / (float)(1 - HIGH_WATER) * max_io; } else { num_for_lsn = max_io * 2; } + // 璁$畻鏈缁堢殑鍒锋柊鏁伴噺锛屽彇骞冲潎鍒锋柊鏁伴噺銆佺敤浜庤剰椤电殑鏁伴噺鍜岀敤浜嶭SN鐨勬暟閲忕殑骞冲潎鍊 num_for_lsn = (num_for_lsn + prev_lsn_num) / 2; prev_lsn_num = num_for_lsn; @@ -1048,10 +1354,11 @@ static uint32 calculate_pagewriter_flush_num() DEFAULT: + // 濡傛灉鍒锋柊鏁伴噺瓒呰繃鏈澶O瀹归噺锛屽皢鍏堕檺鍒朵负max_io锛涘鏋滀綆浜巑in_io锛屽皢鍏惰涓簃in_io if (flush_num > max_io) { flush_num = max_io; } else if (flush_num < min_io) { - flush_num = min_io; + flush_num = min_io; } return flush_num; @@ -1066,8 +1373,8 @@ void dw_upgrade_batch() ereport(LOG, (errmodule(MOD_DW), errmsg("dw batch upgrade start"))); uint64 dw_file_size; - knl_g_dw_context* dw_batch_cxt = &g_instance.dw_batch_cxt; - dw_batch_file_context* dw_file_cxt = &dw_batch_cxt->batch_file_cxts[0]; + knl_g_dw_context *dw_batch_cxt = &g_instance.dw_batch_cxt; + dw_batch_file_context *dw_file_cxt = &dw_batch_cxt->batch_file_cxts[0]; (void)LWLockConditionalAcquire(dw_batch_cxt->flush_lock, LW_EXCLUSIVE); (void)LWLockConditionalAcquire(dw_file_cxt->flush_lock, LW_EXCLUSIVE); @@ -1089,18 +1396,16 @@ void dw_upgrade_batch() */ int fd = open(DW_BATCH_UPGRADE_META_FILE_NAME, (DW_FILE_FLAG | O_CREAT), DW_FILE_PERM); if (fd == -1) { - ereport(PANIC, - (errcode_for_file_access(), errmodule(MOD_DW), - errmsg("Could not create file \"%s\"", DW_BATCH_UPGRADE_META_FILE_NAME))); + ereport(PANIC, (errcode_for_file_access(), errmodule(MOD_DW), + errmsg("Could not create file \"%s\"", DW_BATCH_UPGRADE_META_FILE_NAME))); } /* create new version meta file and batch files */ dw_generate_meta_file(&dw_batch_cxt->batch_meta_file); if (close(fd) != 0 || unlink(DW_BATCH_UPGRADE_META_FILE_NAME) != 0) { - ereport(PANIC, - (errcode_for_file_access(), errmodule(MOD_DW), - errmsg("Could not close or remove the DW batch meta upgrade file"))); + ereport(PANIC, (errcode_for_file_access(), errmodule(MOD_DW), + errmsg("Could not close or remove the DW batch meta upgrade file"))); } /* @@ -1109,19 +1414,16 @@ void dw_upgrade_batch() */ fd = open(DW_BATCH_UPGRADE_BATCH_FILE_NAME, (DW_FILE_FLAG | O_CREAT), DW_FILE_PERM); if (fd == -1) { - ereport(PANIC, - (errcode_for_file_access(), errmodule(MOD_DW), - errmsg("Could not create file \"%s\"", DW_BATCH_UPGRADE_BATCH_FILE_NAME))); + ereport(PANIC, (errcode_for_file_access(), errmodule(MOD_DW), + errmsg("Could not create file \"%s\"", DW_BATCH_UPGRADE_BATCH_FILE_NAME))); } dw_file_size = DW_FILE_SIZE_UNIT * dw_batch_cxt->batch_meta_file.dw_file_size; dw_generate_batch_files(dw_batch_cxt->batch_meta_file.dw_file_num, dw_file_size); - if (close(fd) != 0 || unlink(DW_BATCH_UPGRADE_BATCH_FILE_NAME) != 0) { - ereport(PANIC, - (errcode_for_file_access(), errmodule(MOD_DW), - errmsg("Could not close or remove the DW batch upgrade file"))); + ereport(PANIC, (errcode_for_file_access(), errmodule(MOD_DW), + errmsg("Could not close or remove the DW batch upgrade file"))); } dw_cxt_init_batch(); @@ -1130,12 +1432,10 @@ void dw_upgrade_batch() /* close and remove old version dw batch file */ if (close(dw_file_cxt->fd) != 0 || unlink(OLD_DW_FILE_NAME) != 0) { - ereport(PANIC, - (errcode_for_file_access(), errmodule(MOD_DW), - errmsg("Could not close or remove the DW batch old version file"))); + ereport(PANIC, (errcode_for_file_access(), errmodule(MOD_DW), + errmsg("Could not close or remove the DW batch old version file"))); } - LWLockRelease(dw_file_cxt->flush_lock); pfree(dw_file_cxt); @@ -1149,50 +1449,67 @@ void dw_upgrade_batch() void dw_upgrade_single() { + // 濡傛灉DW鍔熻兘鏈惎鐢紝鍒欑洿鎺ヨ繑鍥 if (!dw_enabled()) { return; } + // 璁板綍鍗囩骇寮濮嬬殑鏃ュ織淇℃伅 ereport(LOG, (errmodule(MOD_DW), errmsg("dw single upgrade start"))); - knl_g_dw_context* dw_single_cxt = &g_instance.dw_single_cxt; + // 鑾峰彇鍗曟枃浠禗W涓婁笅鏂 + knl_g_dw_context *dw_single_cxt = &g_instance.dw_single_cxt; + + // 鑾峰彇鍗曟枃浠禗W鐨勪簩娆″埛鏂伴攣 (void)LWLockAcquire(dw_single_cxt->second_flush_lock, LW_EXCLUSIVE); + + // 绛夊緟鎵鏈夊崟鏂囦欢DW鐨勫埛鏂版搷浣滃畬鎴 wait_all_single_dw_finish_flush_old(); + + // 绛夊緟Page Writer鍚屾 PageWriterSync(); - /* create dw batch flush file */ + // 鍒涘缓DW鍗囩骇鏂囦欢 int fd = open(DW_UPGRADE_FILE_NAME, (DW_FILE_FLAG | O_CREAT), DW_FILE_PERM); if (fd == -1) { - ereport(PANIC, - (errcode_for_file_access(), errmodule(MOD_DW), - errmsg("Could not create file \"%s\"", DW_UPGRADE_FILE_NAME))); + // 濡傛灉鍒涘缓澶辫触锛岃褰曢敊璇俊鎭苟閫鍑 + ereport(PANIC, (errcode_for_file_access(), errmodule(MOD_DW), + errmsg("Could not create file \"%s\"", DW_UPGRADE_FILE_NAME))); } - /* close old version file */ + + // 鍏抽棴鏃х増鏈殑鏂囦欢骞跺垹闄 if (close(dw_single_cxt->fd) != 0 || unlink(SINGLE_DW_FILE_NAME) != 0) { - ereport(PANIC, - (errcode_for_file_access(), errmodule(MOD_DW), - errmsg("Could not close or remove the DW single old version file"))); + // 濡傛灉鍏抽棴鎴栧垹闄ゅけ璐ワ紝璁板綍閿欒淇℃伅骞堕鍑 + ereport(PANIC, (errcode_for_file_access(), errmodule(MOD_DW), + errmsg("Could not close or remove the DW single old version file"))); } + + // 閲嶇疆鍗曟枃浠禗W涓婁笅鏂囩殑鐩稿叧淇℃伅 dw_single_cxt->fd = -1; dw_single_cxt->single_stat_info.total_writes = 0; dw_single_cxt->single_stat_info.file_trunc_num = 0; dw_single_cxt->single_stat_info.file_reset_num = 0; + + // 鐢熸垚鏂扮殑鍗曟枃浠禗W骞舵墦寮 dw_generate_new_single_file(); dw_single_cxt->fd = open(SINGLE_DW_FILE_NAME, DW_FILE_FLAG, DW_FILE_PERM); if (dw_single_cxt->fd == -1) { - ereport(PANIC, - (errcode_for_file_access(), errmodule(MOD_DW), errmsg("during upgrade, could not open file \"%s\"", - SINGLE_DW_FILE_NAME))); + // 濡傛灉鎵撳紑鏂版枃浠跺け璐ワ紝璁板綍閿欒淇℃伅骞堕鍑 + ereport(PANIC, (errcode_for_file_access(), errmodule(MOD_DW), + errmsg("during upgrade, could not open file \"%s\"", SINGLE_DW_FILE_NAME))); } + + // 鏇存柊DW鐨勭増鏈俊鎭负鏀寔鏂扮殑鍗曟枃浠跺埛鏂版ā寮 pg_atomic_write_u32(&g_instance.dw_single_cxt.dw_version, DW_SUPPORT_NEW_SINGLE_FLUSH); + // 鍏抽棴骞跺垹闄ゅ崌绾ф枃浠 if (close(fd) != 0 || unlink(DW_UPGRADE_FILE_NAME) != 0) { - ereport(PANIC, - (errcode_for_file_access(), errmodule(MOD_DW), - errmsg("Could not close or remove the DW upgrade file"))); + // 濡傛灉鍏抽棴鎴栧垹闄ゅけ璐ワ紝璁板綍閿欒淇℃伅骞堕鍑 + ereport(PANIC, (errcode_for_file_access(), errmodule(MOD_DW), + errmsg("Could not close or remove the DW upgrade file"))); } - /* after upgrade, need free the old version buf context */ + // 鍦ㄥ崌绾у悗锛岄噴鏀炬棫鐗堟湰鐨勭紦鍐插尯涓婁笅鏂 if (dw_single_cxt->recovery_buf.unaligned_buf != NULL) { pfree(dw_single_cxt->recovery_buf.unaligned_buf); dw_single_cxt->recovery_buf.unaligned_buf = NULL; @@ -1202,20 +1519,33 @@ void dw_upgrade_single() pfree(dw_single_cxt->recovery_buf.single_flush_state); dw_single_cxt->recovery_buf.single_flush_state = NULL; } + + // 閲婃斁浜屾鍒锋柊閿 LWLockRelease(dw_single_cxt->second_flush_lock); + // 璁板綍鍗囩骇缁撴潫鐨勬棩蹇椾俊鎭 ereport(LOG, (errmodule(MOD_DW), errmsg("dw single upgrade end"))); return; } +/* + * 鍔熻兘锛氬鐞哖ageWriter涓荤嚎绋嬩腑鏂 + * + * 鍙傛暟鍒楄〃锛氭棤 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庡鐞哖ageWriter涓荤嚎绋嬩腑鐨勪笉鍚屼腑鏂儏鍐碉紝鍖呮嫭SIGHUP淇″彿鍜屽悓姝ヨ姹傘 + */ static void HandlePageWriterMainInterrupts() { + // 濡傛灉鏀跺埌SIGHUP淇″彿锛岄噸鏂板姞杞介厤缃枃浠 if (t_thrd.pagewriter_cxt.got_SIGHUP) { t_thrd.pagewriter_cxt.got_SIGHUP = false; ProcessConfigFile(PGC_SIGHUP); } + // 濡傛灉鏈夊悓姝ヨ姹傛垨閲嶈瘯鏍囧織涓虹湡锛屽垯鎵цPageWriterSyncWithAbsorption鍚屾鍑芥暟 if (t_thrd.pagewriter_cxt.sync_requested || t_thrd.pagewriter_cxt.sync_retry) { t_thrd.pagewriter_cxt.sync_requested = false; @@ -1226,10 +1556,10 @@ static void HandlePageWriterMainInterrupts() /* main thread should finally exit. */ while (t_thrd.pagewriter_cxt.shutdown_requested && g_instance.ckpt_cxt_ctl->page_writer_can_exit) { + // 濡傛灉褰撳墠浠呭墿涓涓狿ageWriter绾跨▼ if (pg_atomic_read_u32(&g_instance.ckpt_cxt_ctl->current_page_writer_count) == 1) { - ereport(LOG, - (errmodule(MOD_INCRE_CKPT), - errmsg("pagewriter thread shut down, id is %d", t_thrd.pagewriter_cxt.pagewriter_id))); + ereport(LOG, (errmodule(MOD_INCRE_CKPT), + errmsg("pagewriter thread shut down, id is %d", t_thrd.pagewriter_cxt.pagewriter_id))); /* * From here on, elog(ERROR) should end with exit(1), not send @@ -1243,37 +1573,47 @@ static void HandlePageWriterMainInterrupts() return; } +/* + * 鍔熻兘锛歅ageWriter涓荤嚎绋嬪惊鐜 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜嶱ageWriter涓荤嚎绋嬬殑涓诲惊鐜紝澶勭悊鑴忛〉鍒锋柊銆佷腑鏂鐞嗗拰绛夊緟鏉′欢銆 + */ static void ckpt_pagewriter_main_thread_loop(void) { - uint32 rc = 0; - uint64 now; - int64 sleep_time; - uint32 candidate_num = 0; - + uint32 rc = 0; // 鍑芥暟杩斿洖鐮 + uint64 now; // 褰撳墠鏃堕棿 + int64 sleep_time; // 鐫$湢鏃堕棿 + uint32 candidate_num = 0; // 鍊欓夎剰椤垫暟閲 + // 澶勭悊涓荤嚎绋嬩腑鏂 HandlePageWriterMainInterrupts(); - + // 鑾峰彇鍊欓夎剰椤垫暟閲 candidate_num = get_curr_candidate_nums(false) + get_curr_candidate_nums(true); + // 褰撹剰椤垫暟閲忎负0锛屽欓夎剰椤垫暟绛変簬鎬荤紦鍐叉睜椤垫暟锛屽苟涓旀湭璇锋眰鍏抽棴绾跨▼鏃惰繘鍏ュ惊鐜 while (get_dirty_page_num() == 0 && candidate_num == (uint32)TOTAL_BUFFER_NUM && - !t_thrd.pagewriter_cxt.shutdown_requested) { + !t_thrd.pagewriter_cxt.shutdown_requested) { rc = WaitLatch(&t_thrd.proc->procLatch, WL_TIMEOUT | WL_POSTMASTER_DEATH, (long)TEN_MILLISECOND); if (rc & WL_POSTMASTER_DEATH) { gs_thread_exit(1); } - + // 澶勭悊涓荤嚎绋嬩腑鏂 HandlePageWriterMainInterrupts(); - + // 閲嶆柊鑾峰彇鍊欓夎剰椤垫暟閲 candidate_num = get_curr_candidate_nums(false) + get_curr_candidate_nums(true); + // 濡傛灉鍊欓夎剰椤垫暟閲忎负0涓旀湭璇锋眰鍏抽棴绾跨▼锛屽敜閱掑瓙绾跨▼鎵弿缂撳啿姹狅紝鍒濆鍖栧欓夊垪琛 if (candidate_num == 0 && !t_thrd.pagewriter_cxt.shutdown_requested) { - /* wakeup sub thread scan the buffer pool, init the candidate list */ wakeup_sub_thread(); } } - + // 濡傛灉PageWriter瀛愮嚎绋嬪叏閮ㄧ粨鏉熶笖PageWriter涓荤嚎绋嬫暟閲忕瓑浜庢荤嚎绋嬫暟閲 if (pg_atomic_read_u32(&g_instance.ckpt_cxt_ctl->pgwr_procs.running_num) == 0 && pg_atomic_read_u32(&g_instance.ckpt_cxt_ctl->current_page_writer_count) == (uint32)g_instance.ckpt_cxt_ctl->pgwr_procs.num) { + // 灏濊瘯璺宠繃闃熷垪澶撮儴鐨勬棤鏁堝厓绱 ckpt_try_skip_invalid_elem_in_queue_head(); + // 灏濊瘯淇壀鑴忛〉闃熷垪 ckpt_try_prune_dirty_page_queue(); + // 鍚告敹鏂囦欢鍚屾璇锋眰 PgwrAbsorbFsyncRequests(); /* Full checkpoint, don't sleep */ sleep_time = get_pagewriter_sleep_time(); @@ -1283,11 +1623,9 @@ static void ckpt_pagewriter_main_thread_loop(void) pg_usleep(MILLISECOND_TO_MICROSECOND); sleep_time -= 1; } - /* Calculate next flush time before flush this batch dirty page */ now = get_time_ms(); t_thrd.pagewriter_cxt.next_flush_time = now + u_sess->attr.attr_storage.pageWriterSleep; - /* pagewriter thread flush dirty page */ calculate_max_flush_num(); ckpt_pagewriter_main_thread_flush_dirty_page(); @@ -1295,7 +1633,12 @@ static void ckpt_pagewriter_main_thread_loop(void) } return; } - +/* + * 鍔熻兘锛氬敜閱扨ageWriter涓荤嚎绋 + * + * 娉ㄦ剰锛 + * 濡傛灉褰撳墠鍊欓夊垪琛ㄤ负绌猴紝鍞ら啋PageWriter涓荤嚎绋嬨 + */ static void wakeup_pagewriter_main_thread() { PageWriterProc *pgwr = &g_instance.ckpt_cxt_ctl->pgwr_procs.writer_proc[0]; @@ -1306,30 +1649,56 @@ static void wakeup_pagewriter_main_thread() } return; } - -static bool apply_batch_flush_pages(PageWriterProc* pgwr) +/* + * 鍔熻兘锛氬簲鐢ㄦ壒閲忓埛鏂伴〉闈 + * + * 鍙傛暟鍒楄〃锛 + * pgwr锛歅ageWriter绾跨▼鐨勫鐞嗗櫒 + * + * 杩斿洖鍊硷細 + * 杩斿洖鏄惁鎴愬姛搴旂敤鎵归噺鍒锋柊椤甸潰 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庡簲鐢ㄦ壒閲忓埛鏂伴〉闈€傚畠浠庡叏灞鐨凜kptBufferIdsFlushPages涓幏鍙栭〉闈紝骞跺皢鍏跺垎閰嶇粰PageWriter绾跨▼杩涜鍒锋柊銆 + * 璇ュ嚱鏁伴鍏堣幏鍙栬捣濮嬩綅缃(start_loc)锛岀劧鍚庤绠楅渶瑕佸埛鏂扮殑椤甸潰鏁伴噺(need_flush_num)銆 + * 濡傛灉璧峰浣嶇疆鍔犱笂闇瑕佸埛鏂扮殑椤甸潰鏁伴噺瓒呰繃浜嗘诲叡瑕佸埛鏂扮殑椤甸潰鏁帮紝鍒欎細灏唍eed_flush_num鍑忓皯浠ヤ繚璇佷笉瓒呰繃銆 + * 鏈鍚庯紝灏唖tart_loc鍜宯eed_flush_num璁剧疆鍒皃gwr鐨勭浉搴斿睘鎬т腑锛岃〃绀鸿鍒锋柊鐨勯〉闈㈣寖鍥淬 + */ +static bool apply_batch_flush_pages(PageWriterProc *pgwr) { - uint32 start_loc; - int need_flush_num; - bool is_new_relfilenode = pgwr->thrd_dw_cxt.is_new_relfilenode; - int dw_batch_page_max = GET_DW_DIRTY_PAGE_MAX(is_new_relfilenode); - uint32 total_flush_pages = g_instance.ckpt_cxt_ctl->CkptBufferIdsFlushPages; + uint32 start_loc; // 璧峰浣嶇疆锛岀敤浜庣‘瀹氳鍒锋柊鐨勯〉闈㈣寖鍥寸殑璧峰浣嶇疆 + int need_flush_num; // 闇瑕佸埛鏂扮殑椤甸潰鏁伴噺 + bool is_new_relfilenode = pgwr->thrd_dw_cxt.is_new_relfilenode; // 鏄惁涓烘柊鐨勫叧绯绘枃浠惰妭鐐 + int dw_batch_page_max = GET_DW_DIRTY_PAGE_MAX(is_new_relfilenode); // 鑾峰彇鎵归噺鍒锋柊鐨勬渶澶ч〉闈㈡暟 + uint32 total_flush_pages = g_instance.ckpt_cxt_ctl->CkptBufferIdsFlushPages; // 鑾峰彇鎬诲叡瑕佸埛鏂扮殑椤甸潰鏁 + // 浣跨敤鍘熷瓙鎿嶄綔鑾峰彇璧峰浣嶇疆锛屼繚璇佸绾跨▼鐜涓嬭幏鍙栫殑浣嶇疆涓嶅啿绐 start_loc = pg_atomic_fetch_add_u32(&g_instance.ckpt_cxt_ctl->CkptBufferIdsTail, dw_batch_page_max); - + // 濡傛灉璧峰浣嶇疆宸茬粡瓒呰繃鎴栫瓑浜庢诲叡瑕佸埛鏂扮殑椤甸潰鏁帮紝杩斿洖false琛ㄧず鏃犻渶鍒锋柊 if (start_loc >= total_flush_pages) { return false; } - + // 璁$畻瀹為檯闇瑕佸埛鏂扮殑椤甸潰鏁伴噺锛屽鏋滆秴杩囨诲叡瑕佸埛鏂扮殑椤甸潰鏁帮紝鍒欏噺灏戜互淇濊瘉涓嶈秴杩 need_flush_num = dw_batch_page_max; if (start_loc + need_flush_num > total_flush_pages) { need_flush_num = total_flush_pages - start_loc; } - + // 灏嗚捣濮嬩綅缃拰闇瑕佸埛鏂扮殑椤甸潰鏁伴噺璁剧疆鍒皃gwr鐨勭浉搴斿睘鎬т腑锛岃〃绀鸿鍒锋柊鐨勯〉闈㈣寖鍥 pgwr->start_loc = start_loc; pgwr->need_flush_num = need_flush_num; return true; } - +/* + * 鍔熻兘锛歅ageWriter瀛愮嚎绋嬩富寰幆 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁版槸PageWriter瀛愮嚎绋嬬殑涓昏宸ヤ綔寰幆锛岃礋璐e埛鏂拌剰椤靛埌纾佺洏銆 + * 瀹冮鍏堟鏌ユ槸鍚﹂渶瑕佸叧闂嚎绋嬫垨杩涜鍏朵粬鎿嶄綔銆 + * 鐒跺悗锛屽畠绛夊緟涓涓椂闂撮棿闅旓紝浠ラ槻姝㈤绻佺殑鏃犵敤寰幆銆 + * 濡傛灉闇瑕佸埛鏂拌剰椤碉紝瀹冧細鎵弿缂撳啿姹犱互鑾峰彇瑕佸埛鏂扮殑椤甸潰鍒楄〃锛屽苟灏嗗畠浠坊鍔犲埌鍒锋柊闃熷垪涓 + * 鎺ョ潃锛屽畠浼氫笉鏂湴浠庡埛鏂伴槦鍒椾腑鑾峰彇瑕佸埛鏂扮殑椤甸潰锛屽埛鏂板畠浠埌纾佺洏锛屽苟鏇存柊宸插畬鎴愮殑椤甸潰鏁般 + * 褰撴墍鏈夐〉闈㈤兘鍒锋柊瀹屾垚鏃讹紝瀹冧細灏唒repared鏍囧織璁剧疆涓0锛岃〃绀哄噯澶囧畬鎴愩 + * 鏈鍚庯紝瀹冧細鍏抽棴鎵鏈夋墦寮鐨勬枃浠讹紝瀹屾垚鍒锋柊宸ヤ綔銆 + */ static void ckpt_pagewriter_sub_thread_loop() { uint32 rc = 0; @@ -1342,9 +1711,8 @@ static void ckpt_pagewriter_sub_thread_loop() WritebackContextInit(&wb_context, &t_thrd.pagewriter_cxt.page_writer_after); if (t_thrd.pagewriter_cxt.shutdown_requested && g_instance.ckpt_cxt_ctl->page_writer_can_exit) { - ereport(LOG, - (errmodule(MOD_INCRE_CKPT), - errmsg("pagewriter thread shut down, id is %d", t_thrd.pagewriter_cxt.pagewriter_id))); + ereport(LOG, (errmodule(MOD_INCRE_CKPT), + errmsg("pagewriter thread shut down, id is %d", t_thrd.pagewriter_cxt.pagewriter_id))); /* * From here on, elog(ERROR) should end with exit(1), not send control back to @@ -1358,7 +1726,7 @@ static void ckpt_pagewriter_sub_thread_loop() if (!t_thrd.pagewriter_cxt.shutdown_requested) { /* Wait first */ rc = WaitLatch(&t_thrd.proc->procLatch, WL_TIMEOUT | WL_LATCH_SET | WL_POSTMASTER_DEATH, - (long)u_sess->attr.attr_storage.pageWriterSleep /* ms */); + (long)u_sess->attr.attr_storage.pageWriterSleep /* ms */); } if (rc & WL_POSTMASTER_DEATH) { @@ -1366,7 +1734,7 @@ static void ckpt_pagewriter_sub_thread_loop() } ResetLatch(&t_thrd.proc->procLatch); - PageWriterProc* pgwr = &g_instance.ckpt_cxt_ctl->pgwr_procs.writer_proc[thread_id]; + PageWriterProc *pgwr = &g_instance.ckpt_cxt_ctl->pgwr_procs.writer_proc[thread_id]; if (pgwr->need_flush) { /* scan buffer pool, get flush list and candidate list */ @@ -1374,10 +1742,10 @@ static void ckpt_pagewriter_sub_thread_loop() if (t_thrd.pagewriter_cxt.next_scan_time <= now) { incre_ckpt_pgwr_scan_buf_pool(wb_context); now = get_time_ms(); - t_thrd.pagewriter_cxt.next_scan_time = now + - MAX(u_sess->attr.attr_storage.BgWriterDelay, u_sess->attr.attr_storage.pageWriterSleep); + t_thrd.pagewriter_cxt.next_scan_time = + now + MAX(u_sess->attr.attr_storage.BgWriterDelay, u_sess->attr.attr_storage.pageWriterSleep); } else if ((int64)(t_thrd.pagewriter_cxt.next_scan_time - now) > - MAX(u_sess->attr.attr_storage.BgWriterDelay, u_sess->attr.attr_storage.pageWriterSleep)) { + MAX(u_sess->attr.attr_storage.BgWriterDelay, u_sess->attr.attr_storage.pageWriterSleep)) { /* preventing Time Jumps */ t_thrd.pagewriter_cxt.next_scan_time = now; } @@ -1385,10 +1753,10 @@ static void ckpt_pagewriter_sub_thread_loop() pg_read_barrier(); total_flush_pages = g_instance.ckpt_cxt_ctl->CkptBufferIdsFlushPages; - while (pg_atomic_read_u32(&g_instance.ckpt_cxt_ctl->prepared) == 1 - && pg_atomic_read_u32(&g_instance.ckpt_cxt_ctl->CkptBufferIdsCompletedPages) < total_flush_pages) { + while (pg_atomic_read_u32(&g_instance.ckpt_cxt_ctl->prepared) == 1 && + pg_atomic_read_u32(&g_instance.ckpt_cxt_ctl->CkptBufferIdsCompletedPages) < total_flush_pages) { /* apply one batch dirty pages */ - if(!apply_batch_flush_pages(pgwr)) { + if (!apply_batch_flush_pages(pgwr)) { break; } @@ -1397,8 +1765,8 @@ static void ckpt_pagewriter_sub_thread_loop() incre_ckpt_pgwr_flush_dirty_queue(wb_context); /* add up completed pages */ - completed_pages = pg_atomic_add_fetch_u32( - &g_instance.ckpt_cxt_ctl->CkptBufferIdsCompletedPages, pgwr->need_flush_num); + completed_pages = + pg_atomic_add_fetch_u32(&g_instance.ckpt_cxt_ctl->CkptBufferIdsCompletedPages, pgwr->need_flush_num); /* if flush finished, set prepared to 0 */ if (completed_pages == total_flush_pages) { @@ -1487,7 +1855,20 @@ static void ckpt_pagewriter_handle_exception(MemoryContext pagewriter_context) return; } - +/* + * 鍔熻兘锛歅agewriter绾跨▼缁堟鏃剁殑澶勭悊鍑芥暟 + * + * 鍙傛暟锛 + * code锛氶鍑轰唬鐮 + * arg锛氶檮鍔犲弬鏁 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜嶱agewriter绾跨▼缁堟鏃剁殑娓呯悊宸ヤ綔銆 + * 瀹冮鍏堟鏌agewriter绾跨▼鐨処D锛岀劧鍚庢牴鎹笉鍚岀殑绾跨▼ID鎵ц涓嶅悓鐨勬竻鐞嗗伐浣溿 + * 瀵逛簬ID涓0鐨勭嚎绋嬶紝閿姣佸緟澶勭悊鐨勬搷浣滃搱甯岃〃銆 + * 鐒跺悗锛屽畠纭繚绾跨▼閫鍑烘椂鏍囪浜嗛渶瑕佸埛鏂扮殑鐘舵侊紝浠ラ伩鍏嶄富Pagewriter绾跨▼绛夊緟绾跨▼閫鍑恒 + * 鏈鍚庯紝鍑忓皯Page Writer绾跨▼璁℃暟锛屽皢鐩稿簲绾跨▼鐨刾roc瀛楁缃负NULL锛屼互琛ㄧず绾跨▼宸茬粡缁堟銆 + */ static void pagewriter_kill(int code, Datum arg) { int id = t_thrd.pagewriter_cxt.pagewriter_id; @@ -1497,7 +1878,8 @@ static void pagewriter_kill(int code, Datum arg) hash_destroy(u_sess->storage_cxt.pendingOps); u_sess->storage_cxt.pendingOps = NULL; } - /* Making sure that we mark our exit status (as sub threads) so that main pagewriter thread would not be waiting for us in vain */ + /* Making sure that we mark our exit status (as sub threads) so that main pagewriter thread would not be waiting for + * us in vain */ if (g_instance.ckpt_cxt_ctl->pgwr_procs.writer_proc[id].need_flush) { g_instance.ckpt_cxt_ctl->pgwr_procs.writer_proc[id].need_flush = false; pg_atomic_fetch_sub_u32(&g_instance.ckpt_cxt_ctl->pgwr_procs.running_num, 1); @@ -1528,8 +1910,8 @@ int get_pagewriter_thread_id(void) for (i = 0; i < g_instance.ckpt_cxt_ctl->pgwr_procs.num; i++) { void *expected = NULL; if (pg_atomic_compare_exchange_uintptr( - (uintptr_t *)&g_instance.ckpt_cxt_ctl->pgwr_procs.writer_proc[i].proc, - (uintptr_t *)&expected, (uintptr_t)t_thrd.proc)) { + (uintptr_t *)&g_instance.ckpt_cxt_ctl->pgwr_procs.writer_proc[i].proc, (uintptr_t *)&expected, + (uintptr_t)t_thrd.proc)) { t_thrd.pagewriter_cxt.pagewriter_id = i; break; } @@ -1593,9 +1975,8 @@ void ckpt_pagewriter_main(void) /* We allow SIGQUIT (quickdie) at all times */ (void)sigdelset(&t_thrd.libpq_cxt.BlockSig, SIGQUIT); - ereport(LOG, - (errmodule(MOD_INCRE_CKPT), - errmsg("pagewriter started, thread id is %d", t_thrd.pagewriter_cxt.pagewriter_id))); + ereport(LOG, (errmodule(MOD_INCRE_CKPT), + errmsg("pagewriter started, thread id is %d", t_thrd.pagewriter_cxt.pagewriter_id))); g_last_snapshot_ts = GetCurrentTimestamp(); /* @@ -1603,12 +1984,12 @@ void ckpt_pagewriter_main(void) * buffer pins). */ Assert(t_thrd.pagewriter_cxt.pagewriter_id >= 0); - errno_t err_rc = snprintf_s( - name, MAX_THREAD_NAME_LEN, MAX_THREAD_NAME_LEN - 1, "%s%d", "PageWriter", t_thrd.pagewriter_cxt.pagewriter_id); + errno_t err_rc = snprintf_s(name, MAX_THREAD_NAME_LEN, MAX_THREAD_NAME_LEN - 1, "%s%d", "PageWriter", + t_thrd.pagewriter_cxt.pagewriter_id); securec_check_ss(err_rc, "", ""); - t_thrd.utils_cxt.CurrentResourceOwner = ResourceOwnerCreate(NULL, name, - THREAD_GET_MEM_CXT_GROUP(MEMORY_CONTEXT_STORAGE)); + t_thrd.utils_cxt.CurrentResourceOwner = + ResourceOwnerCreate(NULL, name, THREAD_GET_MEM_CXT_GROUP(MEMORY_CONTEXT_STORAGE)); /* * Create a memory context that we will do all our work in. We do this so @@ -1616,8 +1997,8 @@ void ckpt_pagewriter_main(void) * possible memory leaks. Formerly this code just ran in * TopMemoryContext, but resetting that would be a really bad idea. */ - pagewriter_context = AllocSetContextCreate( - TopMemoryContext, name, ALLOCSET_DEFAULT_MINSIZE, ALLOCSET_DEFAULT_INITSIZE, ALLOCSET_DEFAULT_MAXSIZE); + pagewriter_context = AllocSetContextCreate(TopMemoryContext, name, ALLOCSET_DEFAULT_MINSIZE, + ALLOCSET_DEFAULT_INITSIZE, ALLOCSET_DEFAULT_MAXSIZE); (void)MemoryContextSwitchTo(pagewriter_context); on_shmem_exit(pagewriter_kill, (Datum)0); @@ -1656,10 +2037,10 @@ void ckpt_pagewriter_main(void) InitSync(); } - pg_time_t now = (pg_time_t) time(NULL); + pg_time_t now = (pg_time_t)time(NULL); t_thrd.pagewriter_cxt.next_flush_time = now + u_sess->attr.attr_storage.pageWriterSleep; - t_thrd.pagewriter_cxt.next_scan_time = now + - MAX(u_sess->attr.attr_storage.BgWriterDelay, u_sess->attr.attr_storage.pageWriterSleep); + t_thrd.pagewriter_cxt.next_scan_time = + now + MAX(u_sess->attr.attr_storage.BgWriterDelay, u_sess->attr.attr_storage.pageWriterSleep); /* * Loop forever @@ -1689,8 +2070,8 @@ void ckpt_pagewriter_main(void) * when double write is disabled, pg_dw_meta will be created with dw_file_num = 0, so * here is for upgrading process. pagewrite will run when enable_incremetal_checkpoint = on. */ - if (pg_atomic_read_u32(&g_instance.dw_batch_cxt.dw_version) < DW_SUPPORT_REABLE_DOUBLE_WRITE - && t_thrd.proc->workingVersionNum >= DW_SUPPORT_REABLE_DOUBLE_WRITE) { + if (pg_atomic_read_u32(&g_instance.dw_batch_cxt.dw_version) < DW_SUPPORT_REABLE_DOUBLE_WRITE && + t_thrd.proc->workingVersionNum >= DW_SUPPORT_REABLE_DOUBLE_WRITE) { dw_upgrade_renable_double_write(); } @@ -1709,7 +2090,7 @@ static void print_dirty_page_queue_info(bool after_prune) { uint64 i = 0; uint64 temp_loc; - volatile DirtyPageQueueSlot* slot = NULL; + volatile DirtyPageQueueSlot *slot = NULL; uint64 print_info_num = MIN(((uint64)(MAX_VALID_BUF_SLOT + MAX_VALID_BUF_SLOT)), ((uint64)get_dirty_page_num())); uint64 dirty_queue_head = pg_atomic_read_u64(&g_instance.ckpt_cxt_ctl->dirty_page_queue_head); @@ -1717,17 +2098,14 @@ static void print_dirty_page_queue_info(bool after_prune) temp_loc = (dirty_queue_head + i) % g_instance.ckpt_cxt_ctl->dirty_page_queue_size; slot = &g_instance.ckpt_cxt_ctl->dirty_page_queue[temp_loc]; ereport(DEBUG1, - (errmodule(MOD_INCRE_CKPT), - errmsg("%s, dirty page queue loc is %lu, buffer is %d, slot_state is %u", - after_prune ? "after prune" : "before prune", - temp_loc, - slot->buffer, - slot->slot_state))); + (errmodule(MOD_INCRE_CKPT), + errmsg("%s, dirty page queue loc is %lu, buffer is %d, slot_state is %u", + after_prune ? "after prune" : "before prune", temp_loc, slot->buffer, slot->slot_state))); } } -static bool ckpt_found_valid_and_invalid_buffer_loc( - uint64* valid_buffer_array, uint32 array_size, uint32* valid_slot_num, uint64* last_invalid_slot) +static bool ckpt_found_valid_and_invalid_buffer_loc(uint64 *valid_buffer_array, uint32 array_size, + uint32 *valid_slot_num, uint64 *last_invalid_slot) { int64 i; uint64 temp_loc; @@ -1735,7 +2113,7 @@ static bool ckpt_found_valid_and_invalid_buffer_loc( uint32 max_invalid_slot = MAX_INVALID_BUF_SLOT; int64 dirty_page_num; uint64 dirty_queue_head; - volatile DirtyPageQueueSlot* slot = NULL; + volatile DirtyPageQueueSlot *slot = NULL; dirty_page_num = get_dirty_page_num(); @@ -1779,16 +2157,16 @@ static void ckpt_try_prune_dirty_page_queue() uint32 valid_slot_num = 0; uint64 last_invalid_slot = 0; bool can_found = false; - uint64* valid_buffer_array = NULL; + uint64 *valid_buffer_array = NULL; if (get_dirty_page_num() < g_instance.ckpt_cxt_ctl->dirty_page_queue_size * NEED_PRUNE_DIRTY_QUEUE_SLOT) { return; } - valid_buffer_array = (uint64*)palloc0(MAX_VALID_BUF_SLOT * sizeof(uint64)); + valid_buffer_array = (uint64 *)palloc0(MAX_VALID_BUF_SLOT * sizeof(uint64)); - can_found = ckpt_found_valid_and_invalid_buffer_loc( - valid_buffer_array, MAX_VALID_BUF_SLOT, &valid_slot_num, &last_invalid_slot); + can_found = ckpt_found_valid_and_invalid_buffer_loc(valid_buffer_array, MAX_VALID_BUF_SLOT, &valid_slot_num, + &last_invalid_slot); /* * Read valid_buffer_array form the last to first, move the buffer to last_invalid_slot, @@ -1799,9 +2177,9 @@ static void ckpt_try_prune_dirty_page_queue() uint64 temp_loc; uint64 move_loc; uint32 buf_state; - volatile DirtyPageQueueSlot* slot = NULL; - volatile DirtyPageQueueSlot* move_slot = NULL; - BufferDesc* bufhdr = NULL; + volatile DirtyPageQueueSlot *slot = NULL; + volatile DirtyPageQueueSlot *move_slot = NULL; + BufferDesc *bufhdr = NULL; /* * If full checkpoint set the full_ckpt_expected_flush_loc is queue slot 100, some @@ -1877,7 +2255,7 @@ static void ckpt_try_skip_invalid_elem_in_queue_head() for (i = 0; i < dirty_page_num; i++) { uint64 temp_loc = (dirty_queue_head + i) % g_instance.ckpt_cxt_ctl->dirty_page_queue_size; - volatile DirtyPageQueueSlot* slot = &g_instance.ckpt_cxt_ctl->dirty_page_queue[temp_loc]; + volatile DirtyPageQueueSlot *slot = &g_instance.ckpt_cxt_ctl->dirty_page_queue[temp_loc]; /* slot location is pre-occupied, but the buffer not set finish, need break. */ if (!(pg_atomic_read_u32(&slot->slot_state) & SLOT_VALID)) { break; @@ -1893,17 +2271,15 @@ static void ckpt_try_skip_invalid_elem_in_queue_head() } } if (u_sess->attr.attr_storage.log_pagewriter) { - ereport(DEBUG1, - (errmodule(MOD_INCRE_CKPT), - errmsg("skip invalid element dirty, page queue head add %u, dirty page remain: %ld", - head_move_num, - get_dirty_page_num()))); + ereport(DEBUG1, (errmodule(MOD_INCRE_CKPT), + errmsg("skip invalid element dirty, page queue head add %u, dirty page remain: %ld", + head_move_num, get_dirty_page_num()))); } return; } -static uint32 incre_ckpt_pgwr_flush_dirty_page(WritebackContext wb_context, - const CkptSortItem *dirty_buf_list, int start, int batch_num) +static uint32 incre_ckpt_pgwr_flush_dirty_page(WritebackContext wb_context, const CkptSortItem *dirty_buf_list, + int start, int batch_num) { uint32 num_actual_flush = 0; uint32 buf_state; @@ -1936,7 +2312,7 @@ static uint32 incre_ckpt_pgwr_flush_dirty_page(WritebackContext wb_context, static void incre_ckpt_pgwr_flush_dirty_queue(WritebackContext wb_context) { int thread_id = t_thrd.pagewriter_cxt.pagewriter_id; - PageWriterProc* pgwr = &g_instance.ckpt_cxt_ctl->pgwr_procs.writer_proc[thread_id]; + PageWriterProc *pgwr = &g_instance.ckpt_cxt_ctl->pgwr_procs.writer_proc[thread_id]; bool is_new_relfilenode = g_instance.dw_batch_cxt.is_new_relfilenode; uint32 start_loc = pgwr->start_loc; int need_flush_num = pgwr->need_flush_num; @@ -1973,7 +2349,7 @@ static void incre_ckpt_pgwr_flush_dirty_queue(WritebackContext wb_context) } static void incre_ckpt_pgwr_flush_dirty_list(WritebackContext wb_context, uint32 need_flush_num, - bool is_new_relfilenode) + bool is_new_relfilenode) { int thread_id = t_thrd.pagewriter_cxt.pagewriter_id; PageWriterProc *pgwr = &g_instance.ckpt_cxt_ctl->pgwr_procs.writer_proc[thread_id]; @@ -2014,19 +2390,19 @@ static void incre_ckpt_pgwr_flush_dirty_list(WritebackContext wb_context, uint32 } if (u_sess->attr.attr_storage.log_pagewriter) { - ereport(LOG, - (errmodule(MOD_INCRE_CKPT), - errmsg("flush dirty page %d, thread id is %d", num_actual_flush, thread_id))); + ereport(LOG, (errmodule(MOD_INCRE_CKPT), + errmsg("flush dirty page %d, thread id is %d", num_actual_flush, thread_id))); } } -static bool check_buffer_dirty_flag(BufferDesc* buf_desc) +static bool check_buffer_dirty_flag(BufferDesc *buf_desc) { bool segment_buf = (buf_desc->buf_id >= SegmentBufferStartID); Block tmpBlock = BufHdrGetBlock(buf_desc); uint32 local_buf_state = pg_atomic_read_u32(&buf_desc->state); bool check_lsn_not_match = (local_buf_state & BM_VALID) && !(local_buf_state & BM_DIRTY) && - XLByteLT(buf_desc->lsn_on_disk, PageGetLSN(tmpBlock)) && RecoveryInProgress() && !segment_buf; + XLByteLT(buf_desc->lsn_on_disk, PageGetLSN(tmpBlock)) && RecoveryInProgress() && + !segment_buf; if (check_lsn_not_match) { PinBuffer(buf_desc, NULL); @@ -2034,18 +2410,20 @@ static bool check_buffer_dirty_flag(BufferDesc* buf_desc) pg_memory_barrier(); local_buf_state = pg_atomic_read_u32(&buf_desc->state); check_lsn_not_match = (local_buf_state & BM_VALID) && !(local_buf_state & BM_DIRTY) && - XLByteLT(buf_desc->lsn_on_disk, PageGetLSN(tmpBlock)) && RecoveryInProgress(); + XLByteLT(buf_desc->lsn_on_disk, PageGetLSN(tmpBlock)) && RecoveryInProgress(); if (check_lsn_not_match) { MarkBufferDirty(BufferDescriptorGetBuffer(buf_desc)); LWLockRelease(buf_desc->content_lock); UnpinBuffer(buf_desc, true); const uint32 shiftSize = 32; - ereport(DEBUG1, (errmodule(MOD_INCRE_BG), - errmsg("check lsn is not matched on disk:%X/%X on page %X/%X, relnode info:%u/%u/%u %u %u stat:%u", - (uint32)(buf_desc->lsn_on_disk >> shiftSize), (uint32)(buf_desc->lsn_on_disk), - (uint32)(PageGetLSN(tmpBlock) >> shiftSize), (uint32)(PageGetLSN(tmpBlock)), - buf_desc->tag.rnode.spcNode, buf_desc->tag.rnode.dbNode, buf_desc->tag.rnode.relNode, - buf_desc->tag.blockNum, buf_desc->tag.forkNum, local_buf_state))); + ereport( + DEBUG1, + (errmodule(MOD_INCRE_BG), + errmsg("check lsn is not matched on disk:%X/%X on page %X/%X, relnode info:%u/%u/%u %u %u stat:%u", + (uint32)(buf_desc->lsn_on_disk >> shiftSize), (uint32)(buf_desc->lsn_on_disk), + (uint32)(PageGetLSN(tmpBlock) >> shiftSize), (uint32)(PageGetLSN(tmpBlock)), + buf_desc->tag.rnode.spcNode, buf_desc->tag.rnode.dbNode, buf_desc->tag.rnode.relNode, + buf_desc->tag.blockNum, buf_desc->tag.forkNum, local_buf_state))); return true; } else { @@ -2104,17 +2482,17 @@ static uint32 get_list_flush_num(bool is_segment) } if (cur_candidate_num >= high_water_mark) { - flush_num = min_io; /* only flush one batch dirty page */ + flush_num = min_io; /* only flush one batch dirty page */ } else if (cur_candidate_num >= total_target) { - flush_num = min_io + (float)(high_water_mark - cur_candidate_num) / - (float)(high_water_mark - total_target) * (max_io - min_io); + flush_num = min_io + (float)(high_water_mark - cur_candidate_num) / (float)(high_water_mark - total_target) * + (max_io - min_io); } else { /* every time flush max_io dirty pages */ flush_num = max_io; } ereport(DEBUG1, (errmodule(MOD_INCRE_BG), - errmsg("list flush_num is %u, now candidate buf is %u", flush_num, cur_candidate_num))); + errmsg("list flush_num is %u, now candidate buf is %u", flush_num, cur_candidate_num))); return flush_num; } @@ -2183,14 +2561,13 @@ static void incre_ckpt_pgwr_scan_buf_pool(WritebackContext wb_context) * @out: Return the number of dirty buffers and dirty buffer list and this batch buffer * whether hashbucket is included. */ -static uint32 get_candidate_buf_and_flush_list(uint32 start, uint32 end, uint32 max_flush_num, - bool *contain_hashbucket) +static uint32 get_candidate_buf_and_flush_list(uint32 start, uint32 end, uint32 max_flush_num, bool *contain_hashbucket) { uint32 need_flush_num = 0; uint32 candidates = 0; BufferDesc *buf_desc = NULL; uint32 local_buf_state; - CkptSortItem* item = NULL; + CkptSortItem *item = NULL; bool check_not_need_flush = false; bool check_usecount = false; int thread_id = t_thrd.pagewriter_cxt.pagewriter_id; @@ -2244,13 +2621,13 @@ static uint32 get_candidate_buf_and_flush_list(uint32 start, uint32 end, uint32 goto UNLOCK; } - check_not_need_flush = (need_flush_num >= max_flush_num || (!RecoveryInProgress() - && XLogNeedsFlush(BufferGetLSN(buf_desc)))); + check_not_need_flush = + (need_flush_num >= max_flush_num || (!RecoveryInProgress() && XLogNeedsFlush(BufferGetLSN(buf_desc)))); if (check_not_need_flush) { goto UNLOCK; } -PUSH_DIRTY: + PUSH_DIRTY: local_buf_state |= BM_CHECKPOINT_NEEDED; item = &dirty_buf_list[need_flush_num++]; item->buf_id = buf_id; @@ -2263,14 +2640,13 @@ PUSH_DIRTY: *contain_hashbucket = true; } -UNLOCK: + UNLOCK: UnlockBufHdr(buf_desc, local_buf_state); } if (u_sess->attr.attr_storage.log_pagewriter) { ereport(LOG, - (errmodule(MOD_INCRE_CKPT), - errmsg("get candidate buf %d, thread id is %d", candidates, thread_id))); + (errmodule(MOD_INCRE_CKPT), errmsg("get candidate buf %d, thread id is %d", candidates, thread_id))); } return need_flush_num; } @@ -2304,7 +2680,6 @@ static void push_to_candidate_list(BufferDesc *buf_desc) return; } - /** * @Description: Push buffer bufId to thread threadId's candidate list. * @in: buf_id, buffer id which need push to the list @@ -2329,7 +2704,19 @@ static void candidate_buf_push(int buf_id, int thread_id) pgwr->cand_buf_list[tail_loc] = buf_id; (void)pg_atomic_fetch_add_u64(&pgwr->tail, 1); } - +/* + * 鍔熻兘锛氬皢缂撳啿鍖篒D鎺ㄥ叆娈靛欓夊垪琛 + * + * 鍙傛暟锛 + * buf_id锛氱紦鍐插尯ID + * thread_id锛氱嚎绋婭D + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庡皢缂撳啿鍖篒D鎺ㄥ叆鎸囧畾绾跨▼鐨勬鍊欓夊垪琛ㄣ + * 棣栧厛鑾峰彇绾跨▼鐨勫欓夊垪琛ㄥぇ灏忓拰褰撳墠澶村熬浣嶇疆銆 + * 鐒跺悗锛屾鏌ュ鏋滃熬浣嶇疆鍑忓幓澶翠綅缃ぇ浜庣瓑浜庡欓夊垪琛ㄥぇ灏忥紝鍒欒Е鍙戞柇瑷銆 + * 鍚﹀垯锛岃绠楄鎺ㄥ叆鐨勪綅缃紝灏嗙紦鍐插尯ID瀛樺叆鍊欓夊垪琛紝鐒跺悗澧炲姞灏句綅缃 + */ static void seg_candidate_buf_push(int buf_id, int thread_id) { PageWriterProc *pgwr = &g_instance.ckpt_cxt_ctl->pgwr_procs.writer_proc[thread_id]; @@ -2368,7 +2755,7 @@ bool candidate_buf_pop(int *buf_id, int thread_id) volatile uint64 tail = pg_atomic_read_u64(&pgwr->tail); if (unlikely(head >= tail)) { - return false; /* candidate list is empty */ + return false; /* candidate list is empty */ } head_loc = head % list_size; @@ -2378,7 +2765,22 @@ bool candidate_buf_pop(int *buf_id, int thread_id) } } } - +/* + * 鍔熻兘锛氫粠娈靛欓夊垪琛ㄤ腑寮瑰嚭缂撳啿鍖篒D + * + * 鍙傛暟锛 + * buf_id锛氱敤浜庤繑鍥炲脊鍑虹殑缂撳啿鍖篒D + * thread_id锛氱嚎绋婭D + * + * 杩斿洖鍊硷細 + * 濡傛灉鎴愬姛寮瑰嚭缂撳啿鍖篒D锛屽垯杩斿洖true锛屽惁鍒欒繑鍥瀎alse锛堝欓夊垪琛ㄤ负绌猴級 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庝粠鎸囧畾绾跨▼鐨勬鍊欓夊垪琛ㄤ腑寮瑰嚭涓涓紦鍐插尯ID銆 + * 棣栧厛鑾峰彇绾跨▼鐨勫欓夊垪琛ㄥぇ灏忓拰褰撳墠澶村熬浣嶇疆銆 + * 鐒跺悗锛屽湪寰幆涓紝妫鏌ュ鏋滃ご浣嶇疆澶т簬绛変簬灏句綅缃紝鍒欏欓夊垪琛ㄤ负绌猴紝杩斿洖false銆 + * 鍚﹀垯锛岃绠楄寮瑰嚭鐨勪綅缃紝灏濊瘯鍘熷瓙鎿嶄綔鍦版洿鏂板ご浣嶇疆骞惰幏鍙栫紦鍐插尯ID锛屽鏋滄垚鍔熷垯杩斿洖true锛屽惁鍒欑户缁惊鐜 + */ bool seg_candidate_buf_pop(int *buf_id, int thread_id) { PageWriterProc *pgwr = &g_instance.ckpt_cxt_ctl->pgwr_procs.writer_proc[thread_id]; @@ -2392,7 +2794,7 @@ bool seg_candidate_buf_pop(int *buf_id, int thread_id) volatile uint64 tail = pg_atomic_read_u64(&pgwr->seg_tail); if (unlikely(head >= tail)) { - return false; /* candidate list is empty */ + return false; /* candidate list is empty */ } head_loc = head % list_size; @@ -2403,31 +2805,66 @@ bool seg_candidate_buf_pop(int *buf_id, int thread_id) } } +/* + * 鍔熻兘锛氳幏鍙栫嚎绋嬬殑鍊欓夐〉闈㈡暟閲 + * + * 鍙傛暟锛 + * thread_id锛氱嚎绋嬫爣璇 + * + * 杩斿洖鍊硷細 + * 褰撳墠鍊欓夐〉闈㈡暟閲 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庤幏鍙栨寚瀹氱嚎绋嬬殑鍊欓夐〉闈㈡暟閲忋 + */ static int64 get_thread_candidate_nums(int thread_id) { PageWriterProc *pgwr = &g_instance.ckpt_cxt_ctl->pgwr_procs.writer_proc[thread_id]; - volatile uint64 head = pg_atomic_read_u64(&pgwr->head); - pg_memory_barrier(); - volatile uint64 tail = pg_atomic_read_u64(&pgwr->tail); - int64 curr_cand_num = tail - head; - Assert(curr_cand_num >= 0); + volatile uint64 head = pg_atomic_read_u64(&pgwr->head); // 鑾峰彇澶存寚閽 + pg_memory_barrier(); // 鍐呭瓨灞忛殰锛岀‘淇濆唴瀛樿鍙栫殑椤哄簭 + volatile uint64 tail = pg_atomic_read_u64(&pgwr->tail); // 鑾峰彇灏炬寚閽 + int64 curr_cand_num = tail - head; // 璁$畻褰撳墠鍊欓夐〉闈㈡暟閲 + Assert(curr_cand_num >= 0); // 鏂█锛岀‘淇濆欓夐〉闈㈡暟閲忛潪璐熸暟 return curr_cand_num; } - +/* + * 鍔熻兘锛氳幏鍙栫嚎绋嬬殑娈靛欓夐〉闈㈡暟閲 + * + * 鍙傛暟锛 + * thread_id锛氱嚎绋嬫爣璇 + * + * 杩斿洖鍊硷細 + * 褰撳墠娈靛欓夐〉闈㈡暟閲 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庤幏鍙栨寚瀹氱嚎绋嬬殑娈靛欓夐〉闈㈡暟閲忋 + */ static int64 get_thread_seg_candidate_nums(int thread_id) { PageWriterProc *pgwr = &g_instance.ckpt_cxt_ctl->pgwr_procs.writer_proc[thread_id]; - volatile uint64 head = pg_atomic_read_u64(&pgwr->seg_head); - pg_memory_barrier(); - volatile uint64 tail = pg_atomic_read_u64(&pgwr->seg_tail); - int64 curr_cand_num = tail - head; - Assert(curr_cand_num >= 0); + volatile uint64 head = pg_atomic_read_u64(&pgwr->seg_head); // 鑾峰彇娈靛ご鎸囬拡 + pg_memory_barrier(); // 鍐呭瓨灞忛殰锛岀‘淇濆唴瀛樿鍙栫殑椤哄簭 + volatile uint64 tail = pg_atomic_read_u64(&pgwr->seg_tail); // 鑾峰彇娈靛熬鎸囬拡 + int64 curr_cand_num = tail - head; // 璁$畻褰撳墠娈靛欓夐〉闈㈡暟閲 + Assert(curr_cand_num >= 0); // 鏂█锛岀‘淇濇鍊欓夐〉闈㈡暟閲忛潪璐熸暟 return curr_cand_num; } /** * @Description: Return a rough estimate of the current number of buffers in the candidate list. */ +/* + * 鍔熻兘锛氳幏鍙栧綋鍓嶅欓夐〉闈㈡暟閲 + * + * 鍙傛暟锛 + * segment锛氭槸鍚﹁幏鍙栨鐨勫欓夐〉闈㈡暟閲忥紝true琛ㄧず鑾峰彇娈电殑锛宖alse琛ㄧず鑾峰彇鏁翠綋鐨 + * + * 杩斿洖鍊硷細 + * 褰撳墠鍊欓夐〉闈㈡暟閲 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庤幏鍙栧綋鍓嶅欓夐〉闈㈡暟閲忥紝鍙互閫夋嫨鑾峰彇鏁翠綋鎴栨鐨勫欓夐〉闈㈡暟閲忋 + */ uint32 get_curr_candidate_nums(bool segment) { uint32 currCandidates = 0; @@ -2437,7 +2874,7 @@ uint32 get_curr_candidate_nums(bool segment) for (int i = 1; i < g_instance.ckpt_cxt_ctl->pgwr_procs.num; i++) { pgwr = &g_instance.ckpt_cxt_ctl->pgwr_procs.writer_proc[i]; if (pgwr->proc != NULL) { - currCandidates += get_thread_seg_candidate_nums(i); + currCandidates += get_thread_seg_candidate_nums(i); // 鑾峰彇娈电殑鍊欓夐〉闈㈡暟閲 } } return currCandidates; @@ -2446,33 +2883,45 @@ uint32 get_curr_candidate_nums(bool segment) for (int i = 1; i < g_instance.ckpt_cxt_ctl->pgwr_procs.num; i++) { pgwr = &g_instance.ckpt_cxt_ctl->pgwr_procs.writer_proc[i]; if (pgwr->proc != NULL) { - currCandidates += get_thread_candidate_nums(i); + currCandidates += get_thread_candidate_nums(i); // 鑾峰彇鏁翠綋鐨勫欓夐〉闈㈡暟閲 } } return currCandidates; } +/* + * 鍔熻兘锛氬鐞哠IGHUP淇″彿鐨勫鐞嗗嚱鏁 + * + * 鍙傛暟锛 + * sigInfo锛氫俊鍙蜂俊鎭 + */ static void ckpt_pagewriter_sighup_handler(SIGNAL_ARGS) { int save_errno = errno; - t_thrd.pagewriter_cxt.got_SIGHUP = true; + t_thrd.pagewriter_cxt.got_SIGHUP = true; // 璁剧疆SIGHUP鏍囧織涓簍rue锛岃〃绀烘敹鍒癝IGHUP淇″彿 if (t_thrd.proc) { - SetLatch(&t_thrd.proc->procLatch); + SetLatch(&t_thrd.proc->procLatch); // 璁剧疆杩涚▼Latch锛岄氱煡杩涚▼鏈塖IGHUP淇″彿 } errno = save_errno; } /* SIGINT: set flag to run a normal checkpoint right away */ +/* + * 鍔熻兘锛氬鐞哠IGINT淇″彿鐨勫鐞嗗嚱鏁 + * + * 鍙傛暟锛 + * sigInfo锛氫俊鍙蜂俊鎭 + */ static void ckpt_pagewriter_sigint_handler(SIGNAL_ARGS) { int save_errno = errno; - t_thrd.pagewriter_cxt.sync_requested = true; + t_thrd.pagewriter_cxt.sync_requested = true; // 璁剧疆鍚屾璇锋眰鏍囧織涓簍rue锛岃〃绀烘敹鍒癝IGINT淇″彿 if (t_thrd.proc) - SetLatch(&t_thrd.proc->procLatch); + SetLatch(&t_thrd.proc->procLatch); // 璁剧疆杩涚▼Latch锛岄氱煡杩涚▼鏈塖IGINT淇″彿 errno = save_errno; } @@ -2502,13 +2951,20 @@ static void ckpt_pagewriter_quick_die(SIGNAL_ARGS) gs_thread_exit(EXIT_MODE_TWO); } +/* + * 鍔熻兘锛氬鐞嗚姹傚叧闂俊鍙风殑澶勭悊鍑芥暟 + * + * 鍙傛暟锛 + * sigInfo锛氫俊鍙蜂俊鎭 + */ static void ckpt_pagewriter_request_shutdown_handler(SIGNAL_ARGS) { int save_errno = errno; - t_thrd.pagewriter_cxt.shutdown_requested = true; + t_thrd.pagewriter_cxt.shutdown_requested = true; // 璁剧疆鍏抽棴璇锋眰鏍囧織涓簍rue锛岃〃绀烘敹鍒拌姹傚叧闂俊鍙 + if (t_thrd.proc) { - SetLatch(&t_thrd.proc->procLatch); + SetLatch(&t_thrd.proc->procLatch); // 璁剧疆杩涚▼Latch锛岄氱煡杩涚▼鏈夎姹傚叧闂俊鍙 } errno = save_errno; @@ -2535,7 +2991,6 @@ void ckpt_shutdown_pagewriter() } } - /* The following functions are used by the pagewriter thread to process file sync requests. */ Size PageWriterShmemSize(void) @@ -2559,11 +3014,11 @@ void PageWriterSyncShmemInit(void) bool found = false; g_instance.ckpt_cxt_ctl->incre_ckpt_sync_shmem = - (IncreCkptSyncShmemStruct*)ShmemInitStruct("Incre Ckpt Sync Data", size, &found); + (IncreCkptSyncShmemStruct *)ShmemInitStruct("Incre Ckpt Sync Data", size, &found); if (!found) { /* The memory of the memset sometimes exceeds 2 GB. so, memset_s cannot be used. */ - MemSet((char*)g_instance.ckpt_cxt_ctl->incre_ckpt_sync_shmem, 0, size); + MemSet((char *)g_instance.ckpt_cxt_ctl->incre_ckpt_sync_shmem, 0, size); SpinLockInit(&g_instance.ckpt_cxt_ctl->incre_ckpt_sync_shmem->sync_lock); g_instance.ckpt_cxt_ctl->incre_ckpt_sync_shmem->max_requests = TOTAL_BUFFER_NUM; g_instance.ckpt_cxt_ctl->incre_ckpt_sync_shmem->sync_queue_lwlock = LWLockAssign(LWTRANCHE_PGWR_SYNC_QUEUE); diff --git a/src/gausskernel/process/postmaster/pgarch.cpp b/src/gausskernel/process/postmaster/pgarch.cpp index 1926735fc..e3221ca6a 100755 --- a/src/gausskernel/process/postmaster/pgarch.cpp +++ b/src/gausskernel/process/postmaster/pgarch.cpp @@ -118,15 +118,31 @@ static void pgarch_ArchiverObsCopyLoop(XLogRecPtr flushPtr, doArchive fun); static void InitArchiverLastTaskLsn(ArchiveSlotConfig* obs_archive_slot); #endif +/* + * 鍔熻兘锛氭鏌ユ暟鎹疄渚嬪綊妗f槸鍚︽甯革紝鐢ㄤ簬鍛婅澶勭悊 + * + * 鍙傛暟锛 + * alarm锛氭寚鍚戝憡璀︿俊鎭殑鎸囬拡锛岀敤浜庤褰曞憡璀︿俊鎭 + * additionalParam锛氭寚鍚戝憡璀﹂檮鍔犲弬鏁扮殑鎸囬拡锛岀敤浜庡~鍏呭憡璀﹂檮鍔犱俊鎭 + * + * 杩斿洖鍊硷細 + * AlarmCheckResult 鏋氫妇绫诲瀷锛岃〃绀哄綊妗f鏌ョ粨鏋 + * 濡傛灉 g_instance.WalSegmentArchSucceed 涓 true锛岃〃绀哄綊妗f垚鍔燂紝杩斿洖 ALM_ACR_Normal + * 濡傛灉 g_instance.WalSegmentArchSucceed 涓 false锛岃〃绀哄綊妗e紓甯革紝杩斿洖 ALM_ACR_Abnormal + */ AlarmCheckResult DataInstArchChecker(Alarm* alarm, AlarmAdditionalParam* additionalParam) { + // 妫鏌ュ叏灞褰掓。鐘舵佸彉閲 if (true == g_instance.WalSegmentArchSucceed) { // fill the resume message + // 濡傛灉褰掓。鎴愬姛锛屽~鍐欐甯告仮澶嶆秷鎭 WriteAlarmAdditionalInfo( additionalParam, g_instance.attr.attr_common.PGXCNodeName, "", "", alarm, ALM_AT_Resume); + // 杩斿洖褰掓。妫鏌ョ粨鏋滀负姝e父 return ALM_ACR_Normal; } else { // fill the alarm message + // 濡傛灉褰掓。寮傚父锛屽~鍐欏紓甯稿憡璀︽秷鎭 WriteAlarmAdditionalInfo(additionalParam, g_instance.attr.attr_common.PGXCNodeName, "", @@ -134,17 +150,27 @@ AlarmCheckResult DataInstArchChecker(Alarm* alarm, AlarmAdditionalParam* additio alarm, ALM_AT_Fault, g_instance.attr.attr_common.PGXCNodeName); + // 杩斿洖褰掓。妫鏌ョ粨鏋滀负寮傚父 return ALM_ACR_Abnormal; } } +/* + * 鍔熻兘锛氳缃瀵熻呭綊妗e櫒鐨勯樆濉為攣锛圠atch锛 + * + * 鍙傛暟锛 + * latch锛氭寚鍚戣璁剧疆鐨勯樆濉為攣鐨勬寚閽 + * + * 杩斿洖鍊硷細鏃 + */ void setObsArchLatch(const Latch* latch) { /* use volatile pointer to prevent code rearrangement */ + // 鐢变簬杩欎釜鍑芥暟鍙兘鍦ㄤ笉鍚岀殑绾跨▼涓墽琛岋紝鎵浠ヤ娇鐢ㄤ簡 volatile 鎸囬拡浠ラ槻姝唬鐮侀噸鎺 volatile WalRcvData *walrcv = t_thrd.walreceiverfuncs_cxt.WalRcv; - SpinLockAcquire(&walrcv->mutex); - walrcv->obsArchLatch = (Latch *)latch; - SpinLockRelease(&walrcv->mutex); + SpinLockAcquire(&walrcv->mutex); // 鑾峰彇 WalRcvData 缁撴瀯浣撶殑浜掓枼閿 + walrcv->obsArchLatch = (Latch *)latch; // 璁剧疆瑙傚療鑰呭綊妗e櫒鐨勯樆濉為攣涓轰紶鍏ョ殑闃诲閿 + SpinLockRelease(&walrcv->mutex); // 閲婃斁浜掓枼閿 } /* ------------------------------------------------------------ * Public functions called from postmaster follow @@ -194,6 +220,14 @@ ThreadId pgarch_start() * The argc/argv parameters are valid only in EXEC_BACKEND case. However, * since we don't use 'em, it hardly matters... */ +/* + * 鍔熻兘锛氬綊妗g▼搴忎富鍑芥暟锛屽綊妗g▼搴忕殑鍏ュ彛鐐 + * + * 鍙傛暟锛 + * arg锛氱嚎绋嬪弬鏁 + * + * 杩斿洖鍊硷細鏃 + */ NON_EXEC_STATIC void PgArchiverMain(knl_thread_arg* arg) { IsUnderPostmaster = true; /* we are a postmaster subprocess now */ @@ -215,7 +249,7 @@ NON_EXEC_STATIC void PgArchiverMain(knl_thread_arg* arg) * Ignore all signals usually bound to some action in the postmaster, * except for SIGHUP, SIGTERM, SIGUSR1, SIGUSR2, and SIGQUIT. */ - + // 淇″彿澶勭悊鍑芥暟 (void)gspqsignal(SIGHUP, ArchSigHupHandler); (void)gspqsignal(SIGINT, SIG_IGN); (void)gspqsignal(SIGTERM, ArchSigTermHandler); @@ -237,15 +271,15 @@ NON_EXEC_STATIC void PgArchiverMain(knl_thread_arg* arg) /* * Identify myself via ps */ - init_ps_display("archiver process", "", "", ""); - setObsArchLatch(&t_thrd.arch.mainloop_latch); + init_ps_display("archiver process", "", "", ""); /* 鍒濆鍖 ps 鏄剧ず锛屾爣璇嗗綊妗g▼搴 */ + setObsArchLatch(&t_thrd.arch.mainloop_latch); /* 璁剧疆瑙傚療鑰呭綊妗e櫒鐨勪富寰幆闃诲閿 */ #ifndef ENABLE_LITE_MODE - InitArchiverLastTaskLsn(NULL); + InitArchiverLastTaskLsn(NULL); /* 鍒濆鍖栧綊妗g▼搴忕殑鏈鍚庝换鍔 LSN锛堥昏緫搴忓垪鍙凤級 */ #endif - pgarch_MainLoop(); + pgarch_MainLoop(); /* 杩涘叆褰掓。绋嬪簭鐨勪富寰幆 */ - gs_thread_exit(0); + gs_thread_exit(0); /* 閫鍑虹嚎绋嬶紝杩斿洖鍊间负 0 */ } /* SIGQUIT signal handler for archiver process */ @@ -256,21 +290,37 @@ static void pgarch_exit(SIGNAL_ARGS) } /* SIGHUP signal handler for archiver process */ +/* + * 鍔熻兘锛歋IGHUP 淇″彿澶勭悊鍑芥暟锛岀敤浜庡鐞嗛厤缃枃浠堕噸璇讳俊鍙 + * + * 鍙傛暟锛 + * SIGNAL_ARGS锛氫俊鍙峰鐞嗗嚱鏁扮殑鍙傛暟瀹 + * + * 杩斿洖鍊硷細鏃 + */ static void ArchSigHupHandler(SIGNAL_ARGS) { - int save_errno = errno; + int save_errno = errno; /* 淇濆瓨褰撳墠鐨勯敊璇爜 */ /* set flag to re-read config file at next convenient time */ - t_thrd.arch.got_SIGHUP = true; - SetLatch(&t_thrd.arch.mainloop_latch); + t_thrd.arch.got_SIGHUP = true; /* 璁剧疆 SIGHUP 淇″彿鏍囧織涓虹湡 */ + SetLatch(&t_thrd.arch.mainloop_latch); /* 璁剧疆涓诲惊鐜殑闃诲閿佷互鍞ら啋涓诲惊鐜 */ - errno = save_errno; + errno = save_errno; /* 鎭㈠涔嬪墠淇濆瓨鐨勯敊璇爜 */ } /* SIGTERM signal handler for archiver process */ +/* + * 鍔熻兘锛歋IGTERM 淇″彿澶勭悊鍑芥暟锛岀敤浜庡鐞嗙粓姝俊鍙 + * + * 鍙傛暟锛 + * SIGNAL_ARGS锛氫俊鍙峰鐞嗗嚱鏁扮殑鍙傛暟瀹 + * + * 杩斿洖鍊硷細鏃 + */ static void ArchSigTermHandler(SIGNAL_ARGS) { - int save_errno = errno; + int save_errno = errno; /* 淇濆瓨褰撳墠鐨勯敊璇爜 */ /* * The postmaster never sends us SIGTERM, so we assume that this means @@ -278,45 +328,70 @@ static void ArchSigTermHandler(SIGNAL_ARGS) * too long we'll get SIGKILL'd. Set flag to prevent starting any more * archive commands. */ - t_thrd.arch.got_SIGTERM = true; - SetLatch(&t_thrd.arch.mainloop_latch); + t_thrd.arch.got_SIGTERM = true; /* 璁剧疆 SIGTERM 淇″彿鏍囧織涓虹湡 */ + SetLatch(&t_thrd.arch.mainloop_latch); /* 璁剧疆涓诲惊鐜殑闃诲閿佷互鍞ら啋涓诲惊鐜 */ - errno = save_errno; + errno = save_errno; /* 鎭㈠涔嬪墠淇濆瓨鐨勯敊璇爜 */ } /* SIGUSR1 signal handler for archiver process */ +/* + * 鍔熻兘锛歋IGUSR1 淇″彿澶勭悊鍑芥暟锛岀敤浜庡敜閱掑綊妗g▼搴 + * + * 鍙傛暟锛 + * SIGNAL_ARGS锛氫俊鍙峰鐞嗗嚱鏁扮殑鍙傛暟瀹 + * + * 杩斿洖鍊硷細鏃 + */ static void pgarch_waken(SIGNAL_ARGS) { - int save_errno = errno; + int save_errno = errno; /* 淇濆瓨褰撳墠鐨勯敊璇爜 */ /* set flag that there is work to be done */ - t_thrd.arch.wakened = true; - SetLatch(&t_thrd.arch.mainloop_latch); - errno = save_errno; + t_thrd.arch.wakened = true; /* 璁剧疆鍞ら啋鏍囧織涓虹湡 */ + SetLatch(&t_thrd.arch.mainloop_latch); /* 璁剧疆涓诲惊鐜殑闃诲閿佷互鍞ら啋涓诲惊鐜 */ + errno = save_errno; /* 鎭㈠涔嬪墠淇濆瓨鐨勯敊璇爜 */ } /* SIGUSR2 signal handler for archiver process */ +/* + * 鍔熻兘锛歋IGUSR2 淇″彿澶勭悊鍑芥暟锛岀敤浜庨氱煡褰掓。绋嬪簭鍑嗗鍋滄 + * + * 鍙傛暟锛 + * SIGNAL_ARGS锛氫俊鍙峰鐞嗗嚱鏁扮殑鍙傛暟瀹 + * + * 杩斿洖鍊硷細鏃 + */ static void pgarch_waken_stop(SIGNAL_ARGS) { - int save_errno = errno; + int save_errno = errno; /* 淇濆瓨褰撳墠鐨勯敊璇爜 */ /* set flag to do a final cycle and shut down afterwards */ - t_thrd.arch.ready_to_stop = true; - SetLatch(&t_thrd.arch.mainloop_latch); + t_thrd.arch.ready_to_stop = true; /* 璁剧疆鍑嗗鍋滄鏍囧織涓虹湡 */ + SetLatch(&t_thrd.arch.mainloop_latch); /* 璁剧疆涓诲惊鐜殑闃诲閿佷互鍞ら啋涓诲惊鐜 */ - errno = save_errno; + errno = save_errno; /* 鎭㈠涔嬪墠淇濆瓨鐨勯敊璇爜 */ } - +/* + * 鍔熻兘锛氶獙璇佺洰鏍囩洰褰曟槸鍚︿负绌烘垨鍒涘缓鐩綍 + * + * 鍙傛暟锛 + * dirname锛氳楠岃瘉鐨勭洰褰曞悕 + * + * 杩斿洖鍊硷細鏃 + */ static void VerifyDestDirIsEmptyOrCreate(char* dirname) { switch (pg_check_dir(dirname)) { case 0: /* Does not exist, so create */ + // 鐩綍涓嶅瓨鍦紝鍒涘缓鐩綍锛屽苟璧嬩簣鎵鏈夎呰鍐欐墽琛屾潈闄 if (pg_mkdir_p(dirname, S_IRWXU) == -1) { ereport(FATAL, (errmsg_internal("could not create directory \"%s\": %s\n", dirname, strerror(errno)))); } case -1: /* Access problem */ + // 鐩綍鏃犳硶璁块棶锛屾姤鍛婅嚧鍛介敊璇 ereport(FATAL, (errmsg_internal("could not access directory \"%s\": %s\n", dirname, strerror(errno)))); default: /* Nothing */ break; @@ -330,11 +405,18 @@ static void VerifyDestDirIsEmptyOrCreate(char* dirname) * * Main loop for archiver */ +/* + * 鍔熻兘锛氬綊妗g▼搴忕殑涓诲惊鐜紝鎵ц褰掓。浠诲姟 + * + * 鍙傛暟锛氭棤 + * + * 杩斿洖鍊硷細鏃 + */ static void pgarch_MainLoop(void) { struct timeval last_copy_time; - gettimeofday(&last_copy_time, NULL); - bool time_to_stop = false; + gettimeofday(&last_copy_time, NULL); /* 鑾峰彇褰撳墠鏃堕棿锛岀敤浜庤褰曚笂涓娆″鍒剁殑鏃堕棿鐐 */ + bool time_to_stop = false; /* 鏍囧織鏄惁闇瑕佸仠姝㈠綊妗 */ #ifndef ENABLE_LITE_MODE doArchive fun = NULL; const int millitosec = 1000; @@ -346,7 +428,7 @@ static void pgarch_MainLoop(void) * archiver died unexpectedly). After that we wait for a signal or * timeout before doing more. */ - t_thrd.arch.wakened = true; + t_thrd.arch.wakened = true; /* 鍞ら啋鏍囧織璁句负鐪燂紝琛ㄧず闇瑕佸敜閱掑綊妗f搷浣 */ ArchiveSlotConfig *obs_archive_slot = NULL; if (XLogArchiveDestSet()) { @@ -359,18 +441,18 @@ static void pgarch_MainLoop(void) * wakes up occasionally to allow herself to be proactive. */ do { - ResetLatch(&t_thrd.arch.mainloop_latch); + ResetLatch(&t_thrd.arch.mainloop_latch); /* 閲嶇疆涓诲惊鐜殑闃诲閿 */ struct timeval curtime; /* When we get SIGUSR2, we do one more archive cycle, then exit */ - time_to_stop = t_thrd.arch.ready_to_stop; + time_to_stop = t_thrd.arch.ready_to_stop; /* 鑾峰彇鍋滄鏍囧織 */ /* Check for config update */ if (t_thrd.arch.got_SIGHUP) { - t_thrd.arch.got_SIGHUP = false; - ProcessConfigFile(PGC_SIGHUP); + t_thrd.arch.got_SIGHUP = false; /* 閲嶇疆 SIGHUP 淇″彿鏍囧織 */ + ProcessConfigFile(PGC_SIGHUP); /* 澶勭悊閰嶇疆鏂囦欢閲嶈淇″彿 */ if (!XLogArchivingActive() && getArchiveReplicationSlot() == NULL) { - ereport(LOG, (errmsg("PgArchiver exit"))); + ereport(LOG, (errmsg("PgArchiver exit"))); /* 濡傛灉褰掓。涓嶆椿璺冧笖鏃犲鍒舵Ы锛岃褰曟棩蹇楀苟閫鍑 */ return; } } @@ -388,10 +470,10 @@ static void pgarch_MainLoop(void) if (t_thrd.arch.last_sigterm_time == 0) t_thrd.arch.last_sigterm_time = icurtime; else if ((unsigned int)(icurtime - t_thrd.arch.last_sigterm_time) >= (unsigned int)60) - break; + break; /* 濡傛灉 SIGTERM 淇″彿鎺ユ敹鍒板悗锛岀粡杩 60 绉掞紝閫鍑哄惊鐜 */ } #ifndef ENABLE_LITE_MODE - load_server_mode(); + load_server_mode(); /* 鍔犺浇鏈嶅姟鍣ㄦā寮 */ if (IsServerModeStandby()) { ArchiveTaskStatus *archive_task_status = NULL; @@ -403,7 +485,7 @@ static void pgarch_MainLoop(void) /* if we should do pitr archive, for standby */ volatile unsigned int *pitr_task_status = &archive_task_status->pitr_task_status; if (unlikely(pg_atomic_read_u32(pitr_task_status) == PITR_TASK_GET)) { - pgarch_archiveRoachForPitrStandby(); + pgarch_archiveRoachForPitrStandby(); /* 鎵ц PITR 褰掓。鎿嶄綔 */ pg_atomic_write_u32(pitr_task_status, PITR_TASK_DONE); update_archive_start_end_location_file(archive_task_status->archive_task.targetLsn, TIME_GET_MILLISEC(last_copy_time)); @@ -413,7 +495,7 @@ static void pgarch_MainLoop(void) /* Do what we're here for */ if (t_thrd.arch.wakened || time_to_stop) { - t_thrd.arch.wakened = false; + t_thrd.arch.wakened = false; /* 閲嶇疆鍞ら啋鏍囧織 */ #ifndef ENABLE_LITE_MODE obs_archive_slot = getArchiveReplicationSlot(); if (obs_archive_slot != NULL && !IsServerModeStandby()) { @@ -456,24 +538,27 @@ static void pgarch_MainLoop(void) (errmsg("pgarch_ArchiverObsCopyLoop failed when call SyncRepGetSyncRecPtr"))); } } - + /* + * 妫鏌ユ槸鍚︽弧瓒虫墽琛屽綊妗g殑鏉′欢锛 + * 1. 鏃堕棿闂撮殧澶т簬绛変簬褰掓。闂撮殧锛堝綊妗e懆鏈燂級鎴栬呭緟褰掓。鐨勬暟鎹揪鍒 OBS_XLOG_SLICE_BLOCK_SIZE 澶у皬銆 + */ if (time_diff >= (u_sess->attr.attr_storage.archive_interval * millitosec) || XLByteDifference(flushPtr, t_thrd.arch.pitr_task_last_lsn) >= OBS_XLOG_SLICE_BLOCK_SIZE) { if (IS_PGXC_COORDINATOR) { - fun = &pgarch_archiveRoachForCoordinator; + fun = &pgarch_archiveRoachForCoordinator; /* 濡傛灉鏄崗璋冨櫒鑺傜偣锛岄夋嫨鍗忚皟鍣ㄧ殑褰掓。鍑芥暟 */ } else { - fun = &pgarch_archiveRoachForPitrMaster; + fun = &pgarch_archiveRoachForPitrMaster; /* 鍚﹀垯锛岄夋嫨 PITR 涓昏妭鐐圭殑褰掓。鍑芥暟 */ #ifndef ENABLE_MULTIPLE_NODES if (g_instance.attr.attr_storage.dcf_attr.enable_dcf) - fun = &DcfArchiveRoachForPitrMaster; + fun = &DcfArchiveRoachForPitrMaster; /* 濡傛灉鍚敤 DCF锛岄夋嫨 DCF 涓昏妭鐐圭殑褰掓。鍑芥暟 */ #endif } - pgarch_ArchiverObsCopyLoop(flushPtr, fun); + pgarch_ArchiverObsCopyLoop(flushPtr, fun); /* 鎵ц褰掓。鎿嶄綔锛屼紶鍏ュ緟褰掓。鏁版嵁鐨勪綅缃拰褰掓。鍑芥暟 */ } } else { #endif - pgarch_ArchiverCopyLoop(); - gettimeofday(&last_copy_time, NULL); + pgarch_ArchiverCopyLoop(); /* 鍚﹀垯锛屾墽琛屾櫘閫氬綊妗f搷浣 */ + gettimeofday(&last_copy_time, NULL); /* 鏇存柊涓婁竴娆″鍒剁殑鏃堕棿鐐 */ #ifndef ENABLE_LITE_MODE } #endif @@ -489,21 +574,21 @@ static void pgarch_MainLoop(void) long last_time; /* Don't wait during last iteration */ if (obs_archive_slot != NULL) { - wait_interval = t_thrd.arch.task_wait_interval; - last_time = t_thrd.arch.last_arch_time; + wait_interval = t_thrd.arch.task_wait_interval; /* 鑾峰彇浠诲姟绛夊緟闂撮殧鏃堕棿 */ + last_time = t_thrd.arch.last_arch_time; /* 鑾峰彇涓婁竴娆″綊妗g殑鏃堕棿鐐 */ } else { - wait_interval = PGARCH_AUTOWAKE_INTERVAL; - last_time = TIME_GET_MILLISEC(last_copy_time); + wait_interval = PGARCH_AUTOWAKE_INTERVAL; /* 榛樿绛夊緟闂撮殧鏃堕棿 */ + last_time = TIME_GET_MILLISEC(last_copy_time); /* 鑾峰彇涓婁竴娆″鍒剁殑鏃堕棿鐐 */ } gettimeofday(&curtime, NULL); - long time_diff = (long)TIME_GET_MILLISEC(curtime) - last_time; + long time_diff = (long)TIME_GET_MILLISEC(curtime) - last_time; /* 璁$畻鏃堕棿宸 */ if (time_diff < 0) { time_diff = 0; } - long timeout = wait_interval - time_diff; + long timeout = wait_interval - time_diff; /* 璁$畻瓒呮椂鏃堕棿 */ if (timeout < 0 && IsServerModeStandby()) { /* sleep 100ms for check next task */ - timeout = 100; + timeout = 100; /* 濡傛灉瓒呮椂鏃堕棿灏忎簬 0锛岃缃粯璁ょ瓑寰 100 姣 */ } if (timeout > 0) { int rc; @@ -537,6 +622,15 @@ static void pgarch_MainLoop(void) * * Archives all outstanding xlogs then returns */ +/* + * 鍔熻兘锛氭墽琛屽綊妗f搷浣滅殑涓诲惊鐜 + * + * 璇ュ嚱鏁扮敤浜庡惊鐜鐞嗛渶瑕佽繘琛屽綊妗g殑 xlog 鏂囦欢锛屾墽琛屽綊妗f搷浣溿傚湪褰掓。杩囩▼涓紝浼氭鏌ユ槸鍚︽帴鏀跺埌缁堟淇″彿锛屼互鍙婃槸鍚﹂渶瑕佹洿鏂伴厤缃枃浠躲 + * + * 鍙傛暟锛氭棤 + * + * 杩斿洖鍊硷細鏃 + */ static void pgarch_ArchiverCopyLoop(void) { char xlog[MAX_XFN_CHARS + 1]; @@ -603,28 +697,39 @@ static void pgarch_ArchiverCopyLoop(void) * * Returns true if successful */ +/* + * 鍔熻兘锛氬皢鎸囧畾鐨 xlog 鏂囦欢褰掓。鍒扮洰鏍囦綅缃 + * + * 鍙傛暟锛 + * xlog锛氶渶瑕佸綊妗g殑 xlog 鏂囦欢鐨勫悕绉 + * + * 杩斿洖鍊硷細 + * bool 绫诲瀷锛岃〃绀哄綊妗f槸鍚︽垚鍔 + * 濡傛灉鎴愬姛锛岃繑鍥 true锛涘惁鍒欒繑鍥 false + */ static bool PgarchArchiveXlogToDest(const char* xlog) { - int fdSrc = -1; - int fdDest = -1; - char srcPath[PATH_MAX + 1] = {0}; - char destPath[PATH_MAX + 1] = {0}; - char activitymsg[MAXFNAMELEN + 16]; - long int fileBytes = 0; - int rc = 0; - char tempPath[PATH_MAX] = {0}; - char* retVal = NULL; + int fdSrc = -1; // 婧愭枃浠舵弿杩扮 + int fdDest = -1; // 鐩爣鏂囦欢鎻忚堪绗 + char srcPath[PATH_MAX + 1] = {0}; // 婧愭枃浠惰矾寰 + char destPath[PATH_MAX + 1] = {0}; // 鐩爣鏂囦欢璺緞 + char activitymsg[MAXFNAMELEN + 16]; // 鐢ㄤ簬璁板綍鎿嶄綔娑堟伅 + long int fileBytes = 0; // 璇诲彇鐨勬枃浠跺瓧鑺傛暟 + int rc = 0; // 鐢ㄤ簬璁板綍 snprintf_s 鐨勮繑鍥炲 + char tempPath[PATH_MAX] = {0}; // 鐢ㄤ簬鏋勫缓鏂囦欢璺緞鐨勪复鏃剁紦鍐插尯 + char* retVal = NULL; // 鐢ㄤ簬璁板綍 realpath 鐨勮繑鍥炲 if (xlog == NULL) { return false; } - + // 鏋勫缓婧愭枃浠惰矾寰 rc = snprintf_s(tempPath, PATH_MAX, PATH_MAX - 1, XLOGDIR "/%s", xlog); securec_check_ss(rc, "\0", "\0"); retVal = realpath(tempPath, srcPath); if (retVal == NULL) { ereport(FATAL, (errmsg_internal("realpath src %s failed:%m\n", tempPath))); } + // 鏋勫缓鐩爣鏂囦欢璺緞 retVal = realpath(u_sess->attr.attr_storage.XLogArchiveDest, destPath); if (retVal == NULL) { ereport(FATAL, (errmsg_internal("realpath dest %s failed:%m\n", u_sess->attr.attr_storage.XLogArchiveDest))); @@ -634,7 +739,7 @@ static bool PgarchArchiveXlogToDest(const char* xlog) if ((fdSrc = open(srcPath, O_RDONLY)) >= 0) { if ((fdDest = open(destPath, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR)) >= 0) { - char pbuff[ARCHIVE_BUF_SIZE] = {0}; + char pbuff[ARCHIVE_BUF_SIZE] = {0}; // 鐢ㄤ簬缂撳瓨璇诲彇鐨勬暟鎹 while ((fileBytes = read(fdSrc, pbuff, sizeof(pbuff))) > 0) { if (write(fdDest, pbuff, fileBytes) != fileBytes) { @@ -651,7 +756,7 @@ static bool PgarchArchiveXlogToDest(const char* xlog) ereport(FATAL, (errmsg_internal("could not read file\"%s\":%m\n", xlog))); } - g_instance.WalSegmentArchSucceed = true; + g_instance.WalSegmentArchSucceed = true; // 鏍囪褰掓。鎴愬姛 ereport(DEBUG1, (errmsg("archived transaction log file \"%s\"", xlog))); rc = snprintf_s(activitymsg, sizeof(activitymsg), sizeof(activitymsg) - 1, "last was %s", xlog); @@ -674,13 +779,24 @@ static bool PgarchArchiveXlogToDest(const char* xlog) * Update archived xlog LSN for barrier. * */ +/* + * 鍔熻兘锛氭洿鏂板綊妗g殑LSN锛堟棩蹇楀簭鍒楀彿锛 + * + * 鍙傛暟锛 + * targetLsn锛氳鏇存柊鐨勭洰鏍嘗SN + * + * 杩斿洖鍊硷細鏃 + */ static inline void UpdateArchivedLsn(XLogRecPtr targetLsn) { - ArchiveTaskStatus *archive_task_status = nullptr; + ArchiveTaskStatus *archive_task_status = nullptr; // 鐢ㄤ簬瀛樺偍褰掓。浠诲姟鐨勭姸鎬 + // 鏌ユ壘涓庡綋鍓嶇嚎绋嬪叧鑱旂殑褰掓。浠诲姟鐘舵 archive_task_status = find_archive_task_status(&t_thrd.arch.archive_task_idx); + // 濡傛灉鏈壘鍒板綊妗d换鍔$姸鎬侊紝鍒欑洿鎺ヨ繑鍥 if (archive_task_status == nullptr) { return; } + // 鏇存柊褰掓。浠诲姟鐘舵佷腑鐨勫凡褰掓。LSN archive_task_status->archived_lsn = targetLsn; } @@ -690,6 +806,14 @@ static inline void UpdateArchivedLsn(XLogRecPtr targetLsn) * * Archives all outstanding xlogs then returns */ + +/* + * 鍔熻兘锛氭墽琛屽綊妗f搷浣滅殑涓诲惊鐜紙鐢ㄤ簬褰掓。瑙傚療鑰呮ā寮忥級 + * + * 鍙傛暟锛 + * flushPtr锛氱洰鏍嘗SN锛岃〃绀鸿褰掓。鐨勬棩蹇楃殑涓婇檺 + * fun锛氭墽琛屽綊妗f搷浣滅殑鍑芥暟鎸囬拡 + */ static void pgarch_ArchiverObsCopyLoop(XLogRecPtr flushPtr, doArchive fun) { ereport(LOG, @@ -716,6 +840,7 @@ static void pgarch_ArchiverObsCopyLoop(XLogRecPtr flushPtr, doArchive fun) * command, and the second is to avoid conflicts with another * archiver spawned by a newer postmaster. */ + // 濡傛灉鏀跺埌SIGTERM淇″彿銆丳ostmaster宸插仠姝㈡垨鏃堕棿鍒拌揪鍋滄鏃堕棿锛岀粨鏉熷綊妗e惊鐜 if (t_thrd.arch.got_SIGTERM || !PostmasterIsAlive() || time_to_stop) { return; } @@ -725,10 +850,11 @@ static void pgarch_ArchiverObsCopyLoop(XLogRecPtr flushPtr, doArchive fun) * setting for archive_command as soon as possible, even if there * is a backlog of files to be archived. */ - if (t_thrd.arch.got_SIGHUP) { + if (t_thrd.arch.got_SIGHUP) {// 澶勭悊SIGHUP淇″彿锛屾洿鏂伴厤缃 ProcessConfigFile(PGC_SIGHUP); t_thrd.arch.got_SIGHUP = false; } + // 璁$畻鐩爣LSN if (flushPtr == InvalidXLogRecPtr) { targetLsn = t_thrd.arch.pitr_task_last_lsn + OBS_XLOG_SLICE_BLOCK_SIZE - (t_thrd.arch.pitr_task_last_lsn % OBS_XLOG_SLICE_BLOCK_SIZE) - 1; @@ -741,13 +867,14 @@ static void pgarch_ArchiverObsCopyLoop(XLogRecPtr flushPtr, doArchive fun) if (t_thrd.arch.pitr_task_last_lsn == targetLsn) { targetLsn = Min(targetLsn + OBS_XLOG_SLICE_BLOCK_SIZE, flushPtr); } - + // 鎵ц褰掓。鎿嶄綔 if (fun(targetLsn) == false) { ereport(WARNING, (errmsg("xlog file \"%X/%X\" could not be archived: try again", (uint32)(targetLsn >> 32), (uint32)(targetLsn)))); pg_usleep(1000000L); /* wait a bit before retrying */ } else { + // 褰掓。鎴愬姛鐨勫鐞 if (g_instance.roach_cxt.isXLogForceRecycled && !g_instance.roach_cxt.forceAdvanceSlotTigger) { g_instance.roach_cxt.isXLogForceRecycled = false; ereport(LOG, (errmsg("PgArch force advance slot success"))); @@ -776,6 +903,15 @@ static void pgarch_ArchiverObsCopyLoop(XLogRecPtr flushPtr, doArchive fun) * * Returns true if successful */ +/* + * 鍔熻兘锛氬皾璇曞皢鎸囧畾鐨刉AL鏂囦欢杩涜褰掓。 + * + * 鍙傛暟锛 + * xlog锛氳褰掓。鐨刉AL鏂囦欢鍚 + * + * 杩斿洖鍊硷細 + * 濡傛灉鎴愬姛褰掓。锛屽垯杩斿洖true锛屽惁鍒欒繑鍥瀎alse + */ static bool pgarch_archiveXlog(char* xlog) { char xlogarchcmd[MAXPGPATH]; @@ -785,11 +921,12 @@ static bool pgarch_archiveXlog(char* xlog) char* endp = NULL; const char* sp = NULL; int rc = 0; - + // 鏋勫缓WAL鏂囦欢鐨勫畬鏁磋矾寰 rc = snprintf_s(pathname, MAXPGPATH, MAXPGPATH - 1, XLOGDIR "/%s", xlog); securec_check_ss(rc, "\0", "\0"); /* archive_dest is preferred over archive_command */ + // 濡傛灉宸茶缃甔Log褰掓。鐩爣锛屽垯璋冪敤 PgarchArchiveXlogToDest 鍑芥暟杩涜褰掓。 if (XLogArchiveDestSet()) { return PgarchArchiveXlogToDest(xlog); } @@ -800,7 +937,7 @@ static bool pgarch_archiveXlog(char* xlog) dp = xlogarchcmd; endp = xlogarchcmd + MAXPGPATH - 1; *endp = '\0'; - + // 鏋勫缓褰掓。鍛戒护 for (sp = u_sess->attr.attr_storage.XLogArchiveCommand; *sp; sp++) { if (*sp == '%') { switch (sp[1]) { @@ -845,10 +982,11 @@ static bool pgarch_archiveXlog(char* xlog) rc = snprintf_s(activitymsg, sizeof(activitymsg), sizeof(activitymsg) - 1, "archiving %s", xlog); securec_check_ss(rc, "\0", "\0"); - set_ps_display(activitymsg, false); - + set_ps_display(activitymsg, false); // 璁剧疆杩涚▼鐘舵佹樉绀 + // 鎵ц褰掓。鍛戒护 rc = gs_popen_security(xlogarchcmd); if (rc != 0) { + // 褰掓。澶辫触鐨勫鐞 /* If execute archive command failed, we report an alarm */ g_instance.WalSegmentArchSucceed = false; @@ -898,6 +1036,7 @@ static bool pgarch_archiveXlog(char* xlog) return false; } + // 褰掓。鎴愬姛鐨勫鐞 g_instance.WalSegmentArchSucceed = true; ereport(DEBUG1, (errmsg("archived transaction log file \"%s\"", xlog))); @@ -930,6 +1069,17 @@ static bool pgarch_archiveXlog(char* xlog) * higher priority for archiving. This seems okay, or at least not * obviously worth changing. */ +/* + * + * 鍔熻兘锛氭煡鎵 pg_xlog 鐩綍涓嬪噯澶囧ソ褰掓。鐨勬渶鏃 WAL 鏂囦欢鐨勫悕绉 + * + * 鍙傛暟锛 + * xlog锛氱敤浜庡瓨鍌ㄦ壘鍒扮殑 WAL 鏂囦欢鍚嶇殑瀛楃鏁扮粍锛岃嚦灏戣鏈 XLOG_FNAME_LEN + 1 瀛楄妭 + * + * 杩斿洖鍊硷細 + * 濡傛灉鎵惧埌鍚堥傜殑鏂囦欢锛屽垯灏嗗叾鍚嶇О瀛樺偍鍦 xlog 涓紝骞惰繑鍥 true锛屽惁鍒欒繑鍥 false + * + */ static bool pgarch_readyXlog(char* xlog, int xlog_length) { /* @@ -938,36 +1088,38 @@ static bool pgarch_readyXlog(char* xlog, int xlog_length) * this code, though only a single file is expected on the vast majority * of calls, so.... */ - char XLogArchiveStatusDir[MAXPGPATH]; - char newxlog[MAX_XFN_CHARS + 6 + 1]; - DIR* rldir = NULL; - struct dirent* rlde = NULL; - bool found = false; - int rc = 0; - + char XLogArchiveStatusDir[MAXPGPATH]; // 褰掓。鐘舵佺洰褰曠殑璺緞 + char newxlog[MAX_XFN_CHARS + 6 + 1]; // 鐢ㄤ簬瀛樺偍鎵惧埌鐨勬渶鏂扮殑鍑嗗濂藉綊妗g殑XLog鏂囦欢鍚 + DIR* rldir = NULL; // 鐩綍鍙ユ焺 + struct dirent* rlde = NULL; // 鐩綍椤圭粨鏋 + bool found = false; // 鏄惁鎵惧埌鍑嗗濂藉綊妗g殑XLog鏂囦欢 + int rc = 0; // 鐢ㄤ簬淇濆瓨鍑芥暟杩斿洖鍊 + // 鏋勫缓褰掓。鐘舵佺洰褰曠殑瀹屾暣璺緞 rc = snprintf_s(XLogArchiveStatusDir, MAXPGPATH, MAXPGPATH - 1, XLOGDIR "/archive_status"); securec_check_ss(rc, "", ""); - + // 鎵撳紑褰掓。鐘舵佺洰褰 rldir = AllocateDir(XLogArchiveStatusDir); if (rldir == NULL) ereport(ERROR, (errcode_for_file_access(), errmsg("could not open archive status directory \"%s\": %m", XLogArchiveStatusDir))); - + // 閬嶅巻褰掓。鐘舵佺洰褰曚笅鐨勬枃浠 while ((rlde = ReadDir(rldir, XLogArchiveStatusDir)) != NULL) { int basenamelen = (int)strlen(rlde->d_name) - 6; - + // 妫鏌ユ枃浠跺悕鏄惁绗﹀悎褰掓。鏂囦欢鐨勫懡鍚嶈鑼 if (basenamelen >= MIN_XFN_CHARS && basenamelen <= MAX_XFN_CHARS && strspn(rlde->d_name, VALID_XFN_CHARS) >= (size_t)basenamelen && strcmp(rlde->d_name + basenamelen, ".ready") == 0) { errno_t rc = EOK; if (!found) { + // 绗竴娆℃壘鍒板噯澶囧ソ褰掓。鐨勬枃浠 rc = strcpy_s(newxlog, MAX_XFN_CHARS + 6 + 1, rlde->d_name); securec_check(rc, "\0", "\0"); found = true; } else { + // 姣旇緝鏂囦欢鍚嶏紝閫夊彇杈冩柊鐨勬枃浠 if (strcmp(rlde->d_name, newxlog) < 0) { rc = strcpy_s(newxlog, MAX_XFN_CHARS + 6 + 1, rlde->d_name); securec_check(rc, "\0", "\0"); @@ -975,8 +1127,8 @@ static bool pgarch_readyXlog(char* xlog, int xlog_length) } } } - FreeDir(rldir); - + FreeDir(rldir); // 鍏抽棴鐩綍鍙ユ焺 + // 濡傛灉鎵惧埌鍑嗗濂藉綊妗g殑鏂囦欢锛屽皢鍏惰祴鍊肩粰浼犲叆鐨剎log鍙傛暟 if (found) { errno_t rc = EOK; @@ -985,7 +1137,7 @@ static bool pgarch_readyXlog(char* xlog, int xlog_length) rc = strcpy_s(xlog, (size_t)xlog_length, newxlog); securec_check(rc, "\0", "\0"); } - return found; + return found; // 杩斿洖鏄惁鎵惧埌鍑嗗濂藉綊妗g殑鏂囦欢 } /* @@ -996,21 +1148,44 @@ static bool pgarch_readyXlog(char* xlog, int xlog_length) * Eventually, a checkpoint process will notice this and delete both the * NNN.done file and the xlog file itself. */ +/* + * 鍔熻兘锛氬皢鎸囧畾鐨刉AL鏂囦欢浠".ready"鐘舵佸綊妗e埌".done"鐘舵 + * + * 鍙傛暟锛 + * xlog锛氳浠".ready"鐘舵佸綊妗e埌".done"鐘舵佺殑WAL鏂囦欢鍚 + * + * 杩斿洖鍊硷細鏃 + */ static void pgarch_archiveDone(const char* xlog) { char rlogready[MAXPGPATH]; char rlogdone[MAXPGPATH]; - + // 鐢熸垚 ".ready" 鍜 ".done" 鏂囦欢鐨勫畬鏁磋矾寰 StatusFilePath(rlogready, MAXPGPATH, xlog, ".ready"); StatusFilePath(rlogdone, MAXPGPATH, xlog, ".done"); + + // 灏 ".ready" 鏂囦欢閲嶅懡鍚嶄负 ".done" 鏂囦欢鏉ヨ〃绀烘垚鍔熷綊妗 (void)durable_rename(rlogready, rlogdone, WARNING); } +/* + * archKill + * + * 鍔熻兘锛氱敤浜庡鐞嗗綊妗g嚎绋嬬殑閫鍑烘搷浣滐紝閲婃斁鐩稿叧璧勬簮 + * + * 鍙傛暟锛 + * code锛氶鍑轰唬鐮 + * arg锛氶澶栫殑鍙傛暟锛堟湭浣跨敤锛 + * + * 杩斿洖鍊硷細鏃 + */ static void archKill(int code, Datum arg) { - setObsArchLatch(NULL); + setObsArchLatch(NULL);// 娓呴櫎褰掓。绾跨▼鐨勪富寰幆Latch + // 鎵撳嵃鏃ュ織锛岃〃绀哄綊妗g嚎绋嬪凡鍏抽棴 ereport(LOG, (errmsg("arch thread shut down, slotName: %s", t_thrd.arch.slot_name))); - pfree_ext(t_thrd.arch.slot_name); + pfree_ext(t_thrd.arch.slot_name); // 閲婃斁褰掓。绾跨▼浣跨敤鐨剆lot鍚嶇О鍐呭瓨 + // 閲婃斁杩炴帴閰嶇疆鐩稿叧鍐呭瓨锛屽鏋滃瓨鍦 if (t_thrd.arch.archive_config != NULL && t_thrd.arch.archive_config->archive_config.conn_config != NULL) { pfree_ext(t_thrd.arch.archive_config->archive_config.conn_config->obs_address); pfree_ext(t_thrd.arch.archive_config->archive_config.conn_config->obs_bucket); @@ -1024,14 +1199,29 @@ static void archKill(int code, Datum arg) * pgarch_archiveRoachForPitrStandby * get signal from walreceiver, fork a roach process to archive xlog */ + +/* + * 鍔熻兘锛氱敤浜嶴tandby鑺傜偣杩涜澶勭悊PITR锛圥oint-In-Time Recovery锛夋ā寮忎笅鐨勫綊妗f搷浣滐紝 + * 棣栧厛鑾峰彇褰掓。浠诲姟鐨勭姸鎬侊紝鐒跺悗鏍规嵁浠诲姟鐨勭姸鎬佽繘琛屽綊妗c + * 濡傛灉褰掓。鎴愬姛锛屽皢璁剧疆褰掓。浠诲姟鐨勫畬鎴愭爣蹇椼 + * 濡傛灉褰掓。澶辫触锛屽皢璁剧疆褰掓。浠诲姟鐨勫け璐ユ爣蹇椼 + * 鏈鍚庯紝鍑芥暟浼氭墦鍗扮浉搴旂殑鏃ュ織璁板綍褰掓。鐨勮缁嗕俊鎭 + * + * 鍙傛暟锛氭棤 + * + * 杩斿洖鍊硷細鏃 + */ static void pgarch_archiveRoachForPitrStandby() { ArchiveTaskStatus *archive_task_status = NULL; + // 鑾峰彇褰掓。浠诲姟鐨勭姸鎬 archive_task_status = find_archive_task_status(&t_thrd.arch.archive_task_idx); if (archive_task_status == NULL) { + // 濡傛灉鏃犳硶鑾峰彇褰掓。浠诲姟鐘舵侊紝鍒欐姤閿欏苟閫鍑 ereport(ERROR, (errmsg("pgarch_archiveRoachForPitrStandby failed because could not get an archive task status."))); } + // 鎵撳嵃鏃ュ織锛岃褰曞綊妗d换鍔$殑璇︾粏淇℃伅 ereport(LOG, (errmsg("pgarch_archiveRoachForPitrStandby %s : %X/%X, term:%d, subterm:%d", archive_task_status->slotname, @@ -1040,13 +1230,16 @@ static void pgarch_archiveRoachForPitrStandby() archive_task_status->archive_task.term, archive_task_status->archive_task.sub_term))); if (archive_task_status->archive_task.targetLsn == InvalidXLogSegPtr) { + // 濡傛灉褰掓。浠诲姟鐨勭洰鏍嘗SN鏃犳晥锛屽垯鎶ュ憡骞跺己鍒舵彁鍓嶈繘鍏ヤ笅涓涓猄lot volatile unsigned int *pitr_task_status = &archive_task_status->pitr_task_status; pg_atomic_write_u32(pitr_task_status, PITR_TASK_NONE); ereport(LOG, (errmsg("PgArch standby receive invalid lsn for slot force advance"))); } + // 璋冪敤ArchiveReplicationAchiver鍑芥暟杩涜褰掓。锛屽鏋滃綊妗f垚鍔燂紝璁剧疆瀹屾垚鏍囧織锛屽惁鍒欒缃け璐ユ爣蹇 if (ArchiveReplicationAchiver(&archive_task_status->archive_task) == 0) { archive_task_status->pitr_finish_result = true; } else { + // 濡傛灉褰掓。澶辫触锛屾墦鍗拌鍛婁俊鎭苟璁剧疆澶辫触鏍囧織 ereport(WARNING, (errmsg("error when pgarch_archiveRoachForPitrStandby %s : %X/%X, term:%d, subterm:%d", archive_task_status->slotname, @@ -1063,59 +1256,80 @@ static void pgarch_archiveRoachForPitrStandby() * pgarch_archiveRoachForPitrMaster * choose a walsender to send archive command */ +/* + * 鍔熻兘锛氱敤浜庝富鑺傜偣杩涜澶勭悊PITR锛圥oint-In-Time Recovery锛夋ā寮忎笅鐨勫綊妗f搷浣 + * + * 鍙傛暟锛 + * targetLsn锛氳褰掓。鍒扮殑鐩爣LSN + * + * 杩斿洖鍊硷細 + * 濡傛灉鎴愬姛鍙戣捣褰掓。浠诲姟锛屽垯杩斿洖true锛屽惁鍒欒繑鍥瀎alse + */ static bool pgarch_archiveRoachForPitrMaster(XLogRecPtr targetLsn) { ArchiveTaskStatus *archive_task_status = NULL; + // 鑾峰彇褰掓。浠诲姟鐨勭姸鎬 archive_task_status = find_archive_task_status(&t_thrd.arch.archive_task_idx); if (archive_task_status == NULL) { + // 濡傛灉鏃犳硶鑾峰彇褰掓。浠诲姟鐘舵侊紝鍒欒繑鍥炲け璐 return false; } - + // 鏇存柊褰掓。浠诲姟鐨勭洰鏍嘗SN銆佹椂闂寸嚎鍜宼erm archive_task_status->archive_task.targetLsn = targetLsn; archive_task_status->archive_task.tli = get_controlfile_timeline(); archive_task_status->archive_task.term = Max(g_instance.comm_cxt.localinfo_cxt.term_from_file, g_instance.comm_cxt.localinfo_cxt.term_from_xlog); if (g_instance.roach_cxt.forceAdvanceSlotTigger) { + // 濡傛灉闇瑕佸己鍒舵彁鍓嶈繘鍏ヤ笅涓涓猄lot锛屽垯璁剧疆鐩爣LSN涓烘棤鏁 archive_task_status->archive_task.targetLsn = InvalidXLogRecPtr; g_instance.roach_cxt.forceAdvanceSlotTigger = false; ereport(LOG, (errmsg("PgArch need force advance this time in primary"))); } /* subterm update when walsender changed */ + // 鏇存柊褰掓。浠诲姟鐨剆lot鍚嶇О int rc = strcpy_s(archive_task_status->archive_task.slot_name, NAMEDATALEN, t_thrd.arch.slot_name); securec_check(rc, "\0", "\0"); + // 鎵撳嵃鏃ュ織锛岃褰曞綊妗d换鍔$殑璇︾粏淇℃伅 ereport(LOG, (errmsg("%s : pgarch_archiveRoachForPitrMaster %X/%X", t_thrd.arch.slot_name, (uint32)(targetLsn >> 32), (uint32)(targetLsn)))); + // 閫夋嫨涓涓悎閫傜殑WAL鍙戦佽繘绋 WalSnd* walsnd = pgarch_chooseWalsnd(targetLsn); if (walsnd == NULL) { + // 濡傛灉娌℃湁鍋ュ悍鐨凷tandby鑺傜偣鍙敤锛屽垯杩斿洖澶辫触 ereport(WARNING, (errmsg("pgarch_archiveRoachForPitrMaster failed for no health standby %X/%X", (uint32)(targetLsn >> 32), (uint32)(targetLsn)))); return false; } + // 灏嗗綊妗d换鍔℃坊鍔犲埌褰掓。浠诲姟鍒楄〃锛屽苟閫氱煡WAL鍙戦佽繘绋嬫墽琛屽綊妗 archive_task_status->archiver_latch = &t_thrd.arch.mainloop_latch; add_archive_task_to_list(t_thrd.arch.archive_task_idx, walsnd); SetLatch(&walsnd->latch); ResetLatch(&t_thrd.arch.mainloop_latch); + // 绛夊緟褰掓。浠诲姟瀹屾垚鎴栬秴鏃 rc = WaitLatch(&t_thrd.arch.mainloop_latch, WL_LATCH_SET | WL_TIMEOUT | WL_POSTMASTER_DEATH, 3000L); if (rc & WL_POSTMASTER_DEATH) { + // 濡傛灉Postmaster宸茬粡閫鍑猴紝鍒欓鍑虹嚎绋 gs_thread_exit(1); } if (rc & WL_TIMEOUT) { + // 濡傛灉绛夊緟瓒呮椂锛屽垯杩斿洖澶辫触 return false; } /* * check targetLsn and g_instance.archive_obs_cxt.archive_task.targetLsn for deal message with wrong order */ + // 妫鏌ュ綊妗d换鍔$殑瀹屾垚鐘舵侊紝濡傛灉瀹屾垚涓旂洰鏍嘗SN鍖归厤锛屽垯杩斿洖鎴愬姛 if (archive_task_status->pitr_finish_result == true && XLByteEQ(archive_task_status->archive_task.targetLsn, targetLsn)) { archive_task_status->pitr_finish_result = false; return true; } else { - return false; + return false; // 鍚﹀垯杩斿洖澶辫触 } } @@ -1123,22 +1337,36 @@ static bool pgarch_archiveRoachForPitrMaster(XLogRecPtr targetLsn) * pgarch_archiveRoachForPitrMaster * choose a walsender to send archive command */ +/* + * 鍔熻兘锛氱敤浜庡鐞嗗崗璋冭妭鐐癸紙Coordinator锛夌殑PITR锛圥oint-In-Time Recovery锛夋ā寮忎笅鐨勫綊妗f搷浣 + * + * 鍙傛暟锛 + * targetLsn锛氳褰掓。鍒扮殑鐩爣LSN + * + * 杩斿洖鍊硷細 + * 濡傛灉鎴愬姛鍙戣捣褰掓。浠诲姟锛屽垯杩斿洖true锛屽惁鍒欒繑鍥瀎alse + */ static bool pgarch_archiveRoachForCoordinator(XLogRecPtr targetLsn) { struct timeval tv; gettimeofday(&tv, NULL); ArchiveTaskStatus *archive_task_status = NULL; + // 鑾峰彇褰掓。浠诲姟鐨勭姸鎬 archive_task_status = find_archive_task_status(&t_thrd.arch.archive_task_idx); if (archive_task_status == NULL) { + // 濡傛灉鏃犳硶鑾峰彇褰掓。浠诲姟鐘舵侊紝鍒欒繑鍥炲け璐 ereport(ERROR, (errmsg("pgarch_archiveRoachForCoordinator failed because could not get an archive task status."))); } + // 鍒濆鍖栧綊妗d俊鎭粨鏋 ArchiveXlogMessage archive_xlog_info; archive_xlog_info.targetLsn = targetLsn; archive_xlog_info.term = 0; archive_xlog_info.sub_term = 0; archive_xlog_info.tli = 0; + // 璋冪敤褰掓。鍑芥暟杩涜褰掓。 if (ArchiveReplicationAchiver(&archive_xlog_info) != 0) { + // 褰掓。澶辫触锛岃缃綊妗e畬鎴愭爣蹇椾负false锛屾墦鍗伴敊璇俊鎭紝鐒跺悗绛夊緟涓娈垫椂闂村悗閲嶈瘯 archive_task_status->pitr_finish_result = false; ereport(WARNING, (errmsg("error when pgarch_archiveRoachForCoordinator %s : %X/%X, term:%d, subterm:%d", @@ -1150,16 +1378,19 @@ static bool pgarch_archiveRoachForCoordinator(XLogRecPtr targetLsn) ResetLatch(&t_thrd.arch.mainloop_latch); int rc; /* wait and try again */ + // 绛夊緟涓娈垫椂闂村悗閲嶈瘯 rc = WaitLatch(&t_thrd.arch.mainloop_latch, WL_TIMEOUT | WL_POSTMASTER_DEATH, 500); return false; } else { + // 褰掓。鎴愬姛锛岃缃綊妗e畬鎴愭爣蹇椾负true锛屾洿鏂板綊妗h捣濮嬪拰缁撴潫浣嶇疆鏂囦欢 archive_task_status->pitr_finish_result = true; archive_task_status->archive_task.targetLsn = targetLsn; update_archive_start_end_location_file(archive_task_status->archive_task.targetLsn, TIME_GET_MILLISEC(tv)); } + // 鎵撳嵃鎴愬姛鐨勫綊妗d俊鎭 ereport(LOG, (errmsg("pgarch_archiveRoachForCoordinator %X/%X", (uint32)(targetLsn >> 32), (uint32)(targetLsn)))); @@ -1167,10 +1398,20 @@ static bool pgarch_archiveRoachForCoordinator(XLogRecPtr targetLsn) } /* check if there is any wal sender alive. */ +/* + * 鍔熻兘锛氶夋嫨閫傚綋鐨刉AL鍙戦佽咃紙Walsnd锛夌敤浜庤繘琛屽綊妗 + * + * 鍙傛暟锛 + * targetLsn锛氳褰掓。鍒扮殑鐩爣LSN + * + * 杩斿洖鍊硷細 + * 濡傛灉鎴愬姛閫夋嫨Walsnd锛屽垯杩斿洖鎸囧悜閫夊畾鐨刉alsnd鐨勬寚閽堬紝鍚﹀垯杩斿洖NULL + */ static WalSnd* pgarch_chooseWalsnd(XLogRecPtr targetLsn) { int i; volatile WalSnd* walsnd = NULL; + // 棣栧厛灏濊瘯閫夋嫨涓庡悓姝alsnd锛堝鏋滃瓨鍦級 if (t_thrd.arch.sync_walsender_idx >= 0) { walsnd = &t_thrd.walsender_cxt.WalSndCtl->walsnds[t_thrd.arch.sync_walsender_idx]; SpinLockAcquire(&walsnd->mutex); @@ -1182,7 +1423,7 @@ static WalSnd* pgarch_chooseWalsnd(XLogRecPtr targetLsn) } SpinLockRelease(&walsnd->mutex); } - + // 灏濊瘯閫夋嫨鍏朵粬閫傚悎褰掓。鐨刉alsnd for (i = 0; i < g_instance.attr.attr_storage.max_wal_senders; i++) { /* use volatile pointer to prevent code rearrangement */ walsnd = &t_thrd.walsender_cxt.WalSndCtl->walsnds[i]; @@ -1196,6 +1437,7 @@ static WalSnd* pgarch_chooseWalsnd(XLogRecPtr targetLsn) ArchiveTaskStatus *archive_status = NULL; archive_status = find_archive_task_status(t_thrd.arch.slot_name); if (archive_status == NULL) { + // 鏈壘鍒板綊妗d换鍔$姸鎬佹椂锛屾姏鍑洪敊璇 ereport(ERROR, (errmsg("pgarch_chooseWalsnd has change from %d to %d, but not find slot", t_thrd.arch.sync_walsender_idx, i))); @@ -1209,22 +1451,32 @@ static WalSnd* pgarch_chooseWalsnd(XLogRecPtr targetLsn) return (WalSnd*)walsnd; } } - SpinLockRelease(&walsnd->mutex); + SpinLockRelease(&walsnd->mutex); // 閲婃斁閿 } - return NULL; + return NULL; // 濡傛灉娌℃湁鍚堥傜殑Walsnd鍙緵閫夋嫨锛岃繑鍥濶ULL } +/* + * 鍔熻兘锛氫粠鏈嶅姟鍣ㄨ幏鍙栨渶鍚庝竴涓换鍔$殑LSN + * + * 鍙傛暟锛 + * obs_archive_slot锛氬綊妗f彃妲介厤缃俊鎭 + * + * 杩斿洖鍊硷細 + * 杩斿洖鑾峰彇鍒扮殑鏈鍚庝竴涓换鍔$殑LSN + */ static XLogRecPtr GetLastTaskLsnFromServer(ArchiveSlotConfig* obs_archive_slot) { ArchiveXlogMessage obs_archive_info; XLogRecPtr pitr_task_last_lsn; - + // 灏濊瘯浠庢湇鍔″櫒鑾峰彇鏈鍚庝竴涓换鍔$殑LSN淇℃伅 if (archive_replication_get_last_xlog(&obs_archive_info, &obs_archive_slot->archive_config) == 0) { pitr_task_last_lsn = obs_archive_info.targetLsn; ereport(LOG, (errmsg("initLastTaskLsn update lsn to %X/%X from server", (uint32)(pitr_task_last_lsn >> 32), (uint32)(pitr_task_last_lsn)))); } else { + // 濡傛灉浠庢湇鍔″櫒鑾峰彇澶辫触锛屼粠鏈湴鑾峰彇 XLogRecPtr targetLsn = GetFlushRecPtr(); pitr_task_last_lsn = targetLsn - (targetLsn % XLogSegSize); ereport(LOG, @@ -1234,19 +1486,32 @@ static XLogRecPtr GetLastTaskLsnFromServer(ArchiveSlotConfig* obs_archive_slot) return pitr_task_last_lsn; } +/* + * 鍔熻兘锛氬垵濮嬪寲褰掓。鍣ㄧ殑鏈鍚庝竴涓换鍔SN + * + * 鍙傛暟锛 + * obs_archive_slot锛氬綊妗f彃妲介厤缃俊鎭 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庡垵濮嬪寲褰掓。鍣ㄧ殑鏈鍚庝竴涓换鍔SN銆傞鍏堝皾璇曚粠鏈湴鎴栨湇鍔″櫒鑾峰彇鏈鍚庝竴涓换鍔$殑LSN淇℃伅锛 + * 鐒跺悗灏嗗叾璁剧疆涓哄綊妗e櫒鐨勬渶鍚庝竴涓换鍔SN銆傚鏋滆幏鍙栧け璐ユ垨鏃犳晥锛屽垯浼氭姏鍑洪敊璇垨璀﹀憡銆 + */ static void InitArchiverLastTaskLsn(ArchiveSlotConfig* obs_archive_slot) { struct timeval tv; - load_server_mode(); - gettimeofday(&tv,NULL); - + load_server_mode(); // 鍔犺浇鏈嶅姟鍣ㄦā寮 + gettimeofday(&tv,NULL); // 鑾峰彇褰撳墠鏃堕棿 + // 濡傛灉鏈彁渚涘綊妗f彃妲介厤缃俊鎭紝鍒欏皾璇曡幏鍙 if (obs_archive_slot == NULL) { - t_thrd.arch.last_arch_time = TIME_GET_MILLISEC(tv); + t_thrd.arch.last_arch_time = TIME_GET_MILLISEC(tv); // 鍒濆鍖栨渶鍚庡綊妗f椂闂 obs_archive_slot = getArchiveReplicationSlot(); } - volatile int *slot_idx = &t_thrd.arch.slot_idx; + volatile int *slot_idx = &t_thrd.arch.slot_idx; // 鑾峰彇褰撳墠绾跨▼鐨勬Ы绱㈠紩 + if (obs_archive_slot != NULL && !IsServerModeStandby() && !RecoveryInProgress()) { + // 濡傛灉浼犲叆鐨勫綊妗e鍒舵Ы閰嶇疆淇℃伅涓嶄负绌猴紝涓斿綋鍓嶄笉澶勪簬澶囨満妯″紡鍜屼笉澶勪簬鎭㈠涓 if (likely(*slot_idx != -1) && *slot_idx < g_instance.attr.attr_storage.max_replication_slots) { + // 濡傛灉妲界储寮曟湁鏁堜笖灏忎簬鏈澶у鍒舵Ы鏁 ReplicationSlot *slot = &t_thrd.slot_cxt.ReplicationSlotCtl->replication_slots[*slot_idx]; SpinLockAcquire(&slot->mutex); if (slot->in_use == true && slot->archive_config != NULL) { @@ -1255,13 +1520,16 @@ static void InitArchiverLastTaskLsn(ArchiveSlotConfig* obs_archive_slot) * position, but in new version is initialized from local slot. * During the upgrade, the local restart lsn may be 0, so initialize it with old version way. */ + // 濡傛灉妲芥鍦ㄤ娇鐢ㄤ笖鍏锋湁褰掓。閰嶇疆 if (slot->data.restart_lsn == InvalidXLogRecPtr && t_thrd.proc->workingVersionNum < PITR_INIT_VERSION_NUM) { - SpinLockRelease(&slot->mutex); + // 濡傛灉閲嶅惎LSN鏃犳晥涓斿綋鍓嶅伐浣滅増鏈彿灏忎簬PITR_INIT_VERSION_NUM + SpinLockRelease(&slot->mutex); // 鑾峰彇閿 + // 浠庢湇鍔″櫒鑾峰彇鏈鍚庝换鍔SN t_thrd.arch.pitr_task_last_lsn = GetLastTaskLsnFromServer(obs_archive_slot); } else { t_thrd.arch.pitr_task_last_lsn = slot->data.restart_lsn; - SpinLockRelease(&slot->mutex); + SpinLockRelease(&slot->mutex); // 閲婃斁閿 } } else { SpinLockRelease(&slot->mutex); diff --git a/src/gausskernel/process/postmaster/pgaudit.cpp b/src/gausskernel/process/postmaster/pgaudit.cpp index 87a733645..1f96dc79f 100755 --- a/src/gausskernel/process/postmaster/pgaudit.cpp +++ b/src/gausskernel/process/postmaster/pgaudit.cpp @@ -118,10 +118,10 @@ typedef union { */ #ifdef WIN32 #define LBF_MODE _IONBF -#define DIR_SEP "\\" +#define DIR_SEP "\\" #else #define LBF_MODE _IOLBF -#define DIR_SEP "/" +#define DIR_SEP "/" #endif /* @@ -131,16 +131,12 @@ typedef union { */ #define READ_BUF_SIZE (2 * PIPE_CHUNK_SIZE) -THR_LOCAL int PolicyAudit_RotationAge = 5; // 5 seconds +THR_LOCAL int PolicyAudit_RotationAge = 5; // 5 seconds /* * Brief : bitnum in integer Audit_Session * Description : */ -typedef enum { - SESSION_LOGIN_SUCCESS = 0, - SESSION_LOGIN_FAILED, - SESSION_LOGOUT -} SessionType; +typedef enum { SESSION_LOGIN_SUCCESS = 0, SESSION_LOGIN_FAILED, SESSION_LOGOUT } SessionType; /* * Globally visible state (used by postmaster.c) @@ -150,8 +146,8 @@ static bool auditpipe_done = false; /* build audit pipe for auditor process? */ /* * Private state */ -static char* pgaudit_filename = "%s/%d_adt"; -static char* policy_audit_filename = "%s/%lld_event.bin"; +static char *pgaudit_filename = "%s/%d_adt"; +static char *policy_audit_filename = "%s/%lld_event.bin"; static int pgaudit_filemode = S_IRUSR | S_IWUSR; /* rotation time for auditing policy */ static THR_LOCAL pg_time_t policy_next_rotation_time; @@ -204,13 +200,13 @@ typedef struct AuditIndexItem { * Description : */ typedef struct AuditIndexTableNew { - uint32 maxnum; /* max count of the audit index item */ - uint32 begidx; /* the position of the first audit index item */ - uint32 thread_num; /* the running audit thread num */ - volatile uint32 latest_idx; /* the latest next position of all audit threads index items */ - uint32 curidx[MAX_AUDIT_NUM]; /* the position of the current audit thread index item */ - uint32 count; /* the count of the audit index item */ - pg_time_t last_audit_time; /* the audit time of the latest audit record */ + uint32 maxnum; /* max count of the audit index item */ + uint32 begidx; /* the position of the first audit index item */ + uint32 thread_num; /* the running audit thread num */ + volatile uint32 latest_idx; /* the latest next position of all audit threads index items */ + uint32 curidx[MAX_AUDIT_NUM]; /* the position of the current audit thread index item */ + uint32 count; /* the count of the audit index item */ + pg_time_t last_audit_time; /* the audit time of the latest audit record */ AuditIndexItem data[1]; } AuditIndexTableNew; @@ -232,7 +228,7 @@ static const char audit_indextbl_old_file[] = "index_table"; static const int indextbl_header_size = offsetof(AuditIndexTableNew, data); static const int old_indextbl_header_size = offsetof(AuditIndexTable, data); -static const char* AuditTypeDescs[] = {"unknown", +static const char *AuditTypeDescs[] = {"unknown", "login_success", "login_failed", "user_logout", @@ -282,13 +278,13 @@ static const char* AuditTypeDescs[] = {"unknown", "ddl_publication_subscription", "ddl_foreign_data_wrapper"}; -static const int AuditTypeNum = sizeof(AuditTypeDescs) / sizeof(char*); +static const int AuditTypeNum = sizeof(AuditTypeDescs) / sizeof(char *); #define AuditTypeDesc(type) (((type) > 0 && (type) < AuditTypeNum) ? AuditTypeDescs[(type)] : AuditTypeDescs[0]) -static const char* AuditResultDescs[] = {"unknown", "ok", "failed"}; +static const char *AuditResultDescs[] = {"unknown", "ok", "failed"}; -static const int AuditResultNum = sizeof(AuditResultDescs) / sizeof(char*); +static const int AuditResultNum = sizeof(AuditResultDescs) / sizeof(char *); #define AuditResultDesc(type) (((type) > 0 && (type) < AuditResultNum) ? AuditResultDescs[(type)] : AuditResultDescs[0]) @@ -336,46 +332,44 @@ typedef struct AuditData { #define MAXNUMLEN 16 -#define WRITE_TO_AUDITPIPE (auditpipe_done && t_thrd.role != AUDITOR) +#define WRITE_TO_AUDITPIPE (auditpipe_done && t_thrd.role != AUDITOR) #define WRITE_TO_STDAUDITFILE(ctype) (t_thrd.role == AUDITOR && ctype == STD_AUDIT_TYPE) #define WRITE_TO_UNIAUDITFILE(ctype) (t_thrd.role == AUDITOR && ctype == UNIFIED_AUDIT_TYPE) struct AuditEventInfo { - AuditEventInfo() : userid{0}, - username(NULL), - dbname(NULL), - appname(NULL), - remotehost(NULL), - client_info{0}, - threadid{0}, - localport{0}, - remoteport{0} {} + AuditEventInfo() + : userid{0}, + username(NULL), + dbname(NULL), + appname(NULL), + remotehost(NULL), + client_info{0}, + threadid{0}, + localport{0}, + remoteport{0} + {} char userid[MAXNUMLEN]; - const char* username; - const char* dbname; - const char* appname; - const char* remotehost; + const char *username; + const char *dbname; + const char *appname; + const char *remotehost; char client_info[MAX_CONNECTION_INFO_SIZE]; char threadid[MAXNUMLEN * 4]; char localport[MAXNUMLEN]; char remoteport[MAXNUMLEN]; }; -typedef enum { - SYSAUDITFILE_TYPE = 1, - POLICYAUDITFILE_TYPE, - UNKNOWNFILE_TYPE -} AuditFileType; +typedef enum { SYSAUDITFILE_TYPE = 1, POLICYAUDITFILE_TYPE, UNKNOWNFILE_TYPE } AuditFileType; /* Local subroutines */ -static void process_pipe_input(char* auditbuffer, int* bytes_in_auditbuffer); -static void flush_pipe_input(char* auditbuffer, int* bytes_in_auditbuffer); -static void pgaudit_write_file(char* buffer, int count); +static void process_pipe_input(char *auditbuffer, int *bytes_in_auditbuffer); +static void flush_pipe_input(char *auditbuffer, int *bytes_in_auditbuffer); +static void pgaudit_write_file(char *buffer, int count); static void auditfile_init(bool allow_errors = false); static FILE *auditfile_open(pg_time_t timestamp, const char *mode, bool allow_errors, - const char *filename = pgaudit_filename, bool ignore_num = false); + const char *filename = pgaudit_filename, bool ignore_num = false); static void auditfile_close(AuditFileType flag); /****** audit logs management ******/ @@ -391,28 +385,26 @@ static void sig_thread_quit_handler(); static void sig_thread_config_handler(int ¤tAuditRotationAge, int ¤tAuditRemainThreshold); static void pgauditor_kill(int code, Datum arg); -static void write_pipe_chunks(char* data, int len, AuditClassType type = STD_AUDIT_TYPE); -static void appendStringField(StringInfo str, const char* s); -static void pgaudit_close_file(FILE* fp, const char* file); -static void pgaudit_read_indexfile(const char* audit_directory); -static void pgaudit_update_indexfile(const char* mode, bool allow_errors); +static void write_pipe_chunks(char *data, int len, AuditClassType type = STD_AUDIT_TYPE); +static void appendStringField(StringInfo str, const char *s); +static void pgaudit_close_file(FILE *fp, const char *file); +static void pgaudit_read_indexfile(const char *audit_directory); +static void pgaudit_update_indexfile(const char *mode, bool allow_errors); static bool pgaudit_find_indexfile(void); static void pgaudit_indexfile_upgrade(void); -static void pgaudit_indexfile_sync(const char* mode, bool allow_errors); +static void pgaudit_indexfile_sync(const char *mode, bool allow_errors); static void pgaudit_rewrite_indexfile(void); static void pgaudit_indextbl_init_new(void); static void pgaudit_reset_indexfile(); -static const char* pgaudit_string_field(AuditData* adata, int num); -static void deserialization_to_tuple(Datum (&values)[PGAUDIT_QUERY_COLS], - AuditData *adata, - const AuditMsgHdr &header); +static const char *pgaudit_string_field(AuditData *adata, int num); +static void deserialization_to_tuple(Datum (&values)[PGAUDIT_QUERY_COLS], AuditData *adata, const AuditMsgHdr &header); static void pgaudit_query_file(Tuplestorestate *state, TupleDesc tdesc, uint32 fnum, TimestampTz begtime, TimestampTz endtime, const char *audit_directory); static void pgaudit_query_valid_check(const ReturnSetInfo *rsinfo, FunctionCallInfoData *fcinfo, TupleDesc &tupdesc); static uint32 pgaudit_get_auditfile_num(); -static void pgaudit_update_auditfile_time(pg_time_t timestamp, bool exist); -static void pgaudit_switch_next_auditfile(); +static void pgaudit_update_auditfile_time(pg_time_t timestamp, bool exist); +static void pgaudit_switch_next_auditfile(); /********** unified audit ******/ static void pgaudit_send_data_to_elastic(); @@ -420,11 +412,11 @@ static void pgaudit_query_file_for_elastic(); static void elasic_search_connection_test(); static void policy_auditfile_rotate(); static void set_next_policy_rotation_time(void); -static void pgaudit_write_policy_audit_file(const char* buffer, int count); +static void pgaudit_write_policy_audit_file(const char *buffer, int count); /********** toughness *********/ static void CheckAuditFile(void); -static bool pgaudit_valid_header(const AuditMsgHdr* header); +static bool pgaudit_valid_header(const AuditMsgHdr *header); static void pgaudit_mark_corrupt_info(uint32 fnum); static void audit_append_xid_info(const char *detail_info, char *detail_info_xid, uint32 len); static bool audit_status_check_ok(); @@ -587,11 +579,9 @@ NON_EXEC_STATIC void PgAuditorMain() init_audit_signal_handlers(); if (t_thrd.mem_cxt.pgAuditLocalContext == NULL) - t_thrd.mem_cxt.pgAuditLocalContext = AllocSetContextCreate(t_thrd.top_mem_cxt, - "audit memory context", - ALLOCSET_DEFAULT_MINSIZE, - ALLOCSET_DEFAULT_INITSIZE * 3, - ALLOCSET_DEFAULT_MAXSIZE * 3); + t_thrd.mem_cxt.pgAuditLocalContext = + AllocSetContextCreate(t_thrd.top_mem_cxt, "audit memory context", ALLOCSET_DEFAULT_MINSIZE, + ALLOCSET_DEFAULT_INITSIZE * 3, ALLOCSET_DEFAULT_MAXSIZE * 3); on_shmem_exit(pgauditor_kill, (Datum)0); (void)MemoryContextSwitchTo(t_thrd.mem_cxt.pgAuditLocalContext); @@ -599,7 +589,7 @@ NON_EXEC_STATIC void PgAuditorMain() /* If an exception is encountered, processing resumes here. */ sigjmp_buf local_sigjmp_buf; int curTryCounter; - int* oldTryCounter = NULL; + int *oldTryCounter = NULL; if (sigsetjmp(local_sigjmp_buf, 1) != 0) { gstrace_tryblock_exit(true, oldTryCounter); pgaudit_handle_exception(); @@ -607,7 +597,6 @@ NON_EXEC_STATIC void PgAuditorMain() oldTryCounter = gstrace_tryblock_entry(&curTryCounter); t_thrd.log_cxt.PG_exception_stack = &local_sigjmp_buf; /* We can now handle ereport(ERROR) */ - /* remember active auditfile parameters */ currentAuditRotationAge = u_sess->attr.attr_security.Audit_RotationAge; currentAuditRemainThreshold = u_sess->attr.attr_security.Audit_RemainThreshold; @@ -743,7 +732,6 @@ NON_EXEC_STATIC void PgAuditorMain() if (t_thrd.audit.pipe_eof_seen) { break; } - } /* @@ -779,22 +767,37 @@ void pgaudit_send_data_to_elastic() { if (IS_PGXC_COORDINATOR && g_instance.attr.attr_security.use_elastic_search) { pgaudit_query_file_for_elastic(); - } + } } /* * Start all audit subprocesses */ +/* + * 鍔熻兘锛氬惎鍔ㄦ墍鏈夊璁¤繘绋 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁颁細鍒濆鍖栧璁¤繘绋嬩笂涓嬫枃锛屽苟鍚姩澶氫釜瀹¤杩涚▼浠ュ鐞嗗璁℃棩蹇椼 + * 濡傛灉瀹¤杩涚▼宸茬粡鍚姩锛屽垯涓嶄細鍐嶆鍚姩銆 + * 瀵逛簬姣忎釜瀹¤杩涚▼锛屼細璁板綍鍏惰繘绋婭D鍜屾棩蹇椾俊鎭 + */ void pgaudit_start_all(void) { + // 濡傛灉瀹¤杩涚▼鏁扮粍涓虹┖锛岀洿鎺ヨ繑鍥 if (g_instance.pid_cxt.PgAuditPID == NULL) { return; } + // 鍒濆鍖栧璁¤繘绋嬩笂涓嬫枃 audit_process_cxt_init(); + + // 閬嶅巻瀹¤绾跨▼鏁 for (int i = 0; i < g_instance.audit_cxt.thread_num; ++i) { + // 濡傛灉瀹¤杩涚▼鏈惎鍔紝鍒欏惎鍔ㄥ畠 if (g_instance.pid_cxt.PgAuditPID[i] == 0) { g_instance.pid_cxt.PgAuditPID[i] = pgaudit_start(); + + // 璁板綍瀹¤杩涚▼鍚姩淇℃伅鍒版棩蹇 ereport(LOG, (errmsg("auditor process %d started, pid=%lu", i, g_instance.pid_cxt.PgAuditPID[i]))); } } @@ -803,27 +806,56 @@ void pgaudit_start_all(void) /* * Stop all audit subprocesses */ +/* + * 鍔熻兘锛氬仠姝㈡墍鏈夊璁¤繘绋 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁颁細閬嶅巻鎵鏈夊璁¤繘绋嬶紝骞跺悜瀹冧滑鍙戦 SIGQUIT 淇″彿浠ヨ姹傞鍑恒 + * 鍦ㄨ姹傞鍑哄悗锛屼細閲婃斁瀹¤杩涚▼鐨勭浉鍏宠祫婧愩 + * 姝ゅ嚱鏁伴氬父鐢ㄤ簬鍋滄瀹¤杩涚▼銆 + */ void pgaudit_stop_all(void) { + // 閬嶅巻瀹¤绾跨▼鏁 for (int i = 0; i < g_instance.audit_cxt.thread_num; ++i) { + // 濡傛灉瀹¤杩涚▼宸茬粡鍚姩锛屽垯鍙戦 SIGQUIT 淇″彿璇锋眰鍏堕鍑 if (g_instance.pid_cxt.PgAuditPID[i] != 0) { Assert(!dummyStandbyMode); signal_child(g_instance.pid_cxt.PgAuditPID[i], SIGQUIT, -1); } } + + // 閲婃斁瀹¤杩涚▼涓婁笅鏂囪祫婧 audit_process_cxt_exit(); } /* * Postmaster subroutine to start a sysauditor subprocess. */ +/* + * 鍔熻兘锛氬惎鍔ㄥ璁¤繘绋 + * + * 杩斿洖鍊硷細 + * 杩斿洖瀹¤杩涚▼鐨勭嚎绋 ID锛圱hreadId锛夋垨 0锛堣〃绀哄惎鍔ㄥけ璐ワ級銆 + * + * 娉ㄦ剰锛 + * 濡傛灉瀹¤鍔熻兘鏈惎鐢紙u_sess->attr.attr_security.Audit_enabled 涓哄亣锛夛紝鍒欎笉浼氬惎鍔ㄥ璁¤繘绋嬨 + * 鍚﹀垯锛屽畠灏嗛氳繃璋冪敤 initialize_util_thread(AUDITOR) 鏉ュ皾璇曞垵濮嬪寲骞跺惎鍔ㄥ璁¤繘绋嬨 + * 濡傛灉鎴愬姛鍚姩瀹¤杩涚▼锛屽垯杩斿洖鍏剁嚎绋 ID锛屽惁鍒欒繑鍥 0銆 + * 璇ュ嚱鏁伴氬父鍦 PostgreSQL 鍚姩鏃惰皟鐢ㄤ互鍚姩瀹¤鍔熻兘銆 + */ ThreadId pgaudit_start(void) { ThreadId sysauditorPid; + + // 濡傛灉鏈惎鐢ㄥ璁″姛鑳斤紝鐩存帴杩斿洖 0 琛ㄧず鍚姩澶辫触 if (!u_sess->attr.attr_security.Audit_enabled) return 0; + // 璋冪敤 initialize_util_thread(AUDITOR) 鏉ュ惎鍔ㄥ璁¤繘绋 sysauditorPid = initialize_util_thread(AUDITOR); + + // 濡傛灉鎴愬姛鍚姩瀹¤杩涚▼锛岃繑鍥炲叾绾跨▼ ID if (sysauditorPid != 0) { /* success, in postmaster */ return (ThreadId)sysauditorPid; @@ -865,9 +897,9 @@ void allow_immediate_pgaudit_restart(void) * of bytes present. On exit, any not-yet-eaten data is left-justified in * auditbuffer, and *bytes_in_auditbuffer is updated. */ -static void process_pipe_input(char* auditbuffer, int* bytes_in_auditbuffer) +static void process_pipe_input(char *auditbuffer, int *bytes_in_auditbuffer) { - char* cursor = auditbuffer; + char *cursor = auditbuffer; int count = *bytes_in_auditbuffer; /* While we have enough for a header, process data... */ @@ -881,10 +913,10 @@ static void process_pipe_input(char* auditbuffer, int* bytes_in_auditbuffer) securec_check(errorno, "\0", "\0"); if (p.nuls[0] == '\0' && p.nuls[1] == '\0' && p.len > 0 && p.len <= PIPE_MAX_PAYLOAD && p.pid != 0 && (p.is_last == 't' || p.is_last == 'f')) { - List* buffer_list = NULL; - ListCell* cell = NULL; - save_buffer* existing_slot = NULL; - save_buffer* free_slot = NULL; + List *buffer_list = NULL; + ListCell *cell = NULL; + save_buffer *existing_slot = NULL; + save_buffer *free_slot = NULL; StringInfo str; chunklen = PIPE_HEADER_SIZE + p.len; /* Fall out of loop if we don't have the whole chunk yet */ @@ -894,7 +926,7 @@ static void process_pipe_input(char* auditbuffer, int* bytes_in_auditbuffer) /* Locate any existing buffer for this source pid */ buffer_list = t_thrd.audit.buffer_lists[p.pid % NBUFFER_LISTS]; foreach (cell, buffer_list) { - save_buffer* buf = (save_buffer*)lfirst(cell); + save_buffer *buf = (save_buffer *)lfirst(cell); if (buf->pid == p.pid) { existing_slot = buf; @@ -921,7 +953,7 @@ static void process_pipe_input(char* auditbuffer, int* bytes_in_auditbuffer) * Need a free slot, but there isn't one in the list, * so create a new one and extend the list with it. */ - free_slot = (save_buffer*)palloc(sizeof(save_buffer)); + free_slot = (save_buffer *)palloc(sizeof(save_buffer)); buffer_list = lappend(buffer_list, free_slot); t_thrd.audit.buffer_lists[p.pid % NBUFFER_LISTS] = buffer_list; } @@ -994,17 +1026,17 @@ static void process_pipe_input(char* auditbuffer, int* bytes_in_auditbuffer) * This is currently used only at sysauditor shutdown, but could perhaps be * useful at other times, so it is careful to leave things in a clean state. */ -static void flush_pipe_input(char* auditbuffer, int* bytes_in_auditbuffer) +static void flush_pipe_input(char *auditbuffer, int *bytes_in_auditbuffer) { int i; /* Dump any incomplete protocol messages */ for (i = 0; i < NBUFFER_LISTS; i++) { - List* list = t_thrd.audit.buffer_lists[i]; - ListCell* cell = NULL; + List *list = t_thrd.audit.buffer_lists[i]; + ListCell *cell = NULL; foreach (cell, list) { - save_buffer* buf = (save_buffer*)lfirst(cell); + save_buffer *buf = (save_buffer *)lfirst(cell); if (buf->pid != 0) { StringInfo str = &(buf->data); @@ -1040,7 +1072,7 @@ static void flush_pipe_input(char* auditbuffer, int* bytes_in_auditbuffer) * This allows the sysauditor process to record elog messages of its own, * even though its stderr does not point at the sysaudit pipe. */ -static void pgaudit_write_file(char* buffer, int count) +static void pgaudit_write_file(char *buffer, int count) { int rc; pg_time_t curtime; @@ -1051,10 +1083,10 @@ static void pgaudit_write_file(char* buffer, int count) curtime = time(NULL); errorno = memcpy_s(buffer + offsetof(AuditMsgHdr, time), READ_BUF_SIZE - offsetof(AuditMsgHdr, time), &curtime, - sizeof(pg_time_t)); + sizeof(pg_time_t)); securec_check(errorno, "\0", "\0"); - errorno = memcpy_s( - buffer + offsetof(AuditMsgHdr, size), READ_BUF_SIZE - offsetof(AuditMsgHdr, size), &count, sizeof(uint32)); + errorno = memcpy_s(buffer + offsetof(AuditMsgHdr, size), READ_BUF_SIZE - offsetof(AuditMsgHdr, size), &count, + sizeof(uint32)); securec_check(errorno, "\0", "\0"); errno = 0; @@ -1082,7 +1114,7 @@ retry1: (void)fflush(t_thrd.audit.sysauditFile); } -static void pgaudit_write_policy_audit_file(const char* buffer, int count) +static void pgaudit_write_policy_audit_file(const char *buffer, int count) { /* flush policy audit info only if elastic system configure */ if (!IS_PGXC_COORDINATOR || !g_instance.attr.attr_security.use_elastic_search) { @@ -1141,11 +1173,11 @@ static void auditfile_init(bool allow_errors) * Otherwise, errors are treated as fatal. */ static FILE *auditfile_open(pg_time_t timestamp, const char *mode, bool allow_errors, const char *_filename, - bool ignore_num) + bool ignore_num) { - FILE *fh = NULL; - char* filename = NULL; - uint32 fnum = 0; + FILE *fh = NULL; + char *filename = NULL; + uint32 fnum = 0; int thread_idx = t_thrd.audit.cur_thread_idx; struct stat st; @@ -1155,10 +1187,10 @@ static FILE *auditfile_open(pg_time_t timestamp, const char *mode, bool allow_er } ereport(DEBUG1, (errmsg("audit thread idx: %d auditfile_open ok fnum : %d", thread_idx, fnum))); - filename = (char*)palloc(MAXPGPATH); - int rc = snprintf_s( - filename, MAXPGPATH, MAXPGPATH - 1, _filename, g_instance.attr.attr_security.Audit_directory, fnum); - securec_check_intval(rc,, NULL); + filename = (char *)palloc(MAXPGPATH); + int rc = + snprintf_s(filename, MAXPGPATH, MAXPGPATH - 1, _filename, g_instance.attr.attr_security.Audit_directory, fnum); + securec_check_intval(rc, , NULL); /* * Note we do not let pgaudit_filemode disable IWUSR, since we certainly want @@ -1177,7 +1209,7 @@ static FILE *auditfile_open(pg_time_t timestamp, const char *mode, bool allow_er int save_errno = errno; ereport(allow_errors ? LOG : FATAL, - (errcode_for_file_access(), errmsg("could not open audit file \"%s\": %m", filename))); + (errcode_for_file_access(), errmsg("could not open audit file \"%s\": %m", filename))); errno = save_errno; } @@ -1186,7 +1218,7 @@ static FILE *auditfile_open(pg_time_t timestamp, const char *mode, bool allow_er int save_errno = errno; ereport(allow_errors ? LOG : FATAL, - (errcode_for_file_access(), errmsg("could not chmod audit file \"%s\": %m", filename))); + (errcode_for_file_access(), errmsg("could not chmod audit file \"%s\": %m", filename))); errno = save_errno; } } @@ -1199,33 +1231,71 @@ static FILE *auditfile_open(pg_time_t timestamp, const char *mode, bool allow_er * Brief : close the audit file. * Description : */ -static void auditfile_close(AuditFileType flag) +/* + * 鍔熻兘锛氬叧闂璁℃枃浠 + * + * 鍙傛暟锛 + * flag锛氳〃绀哄璁℃枃浠剁被鍨嬬殑鏍囧織锛屽彲浠ユ槸 SYSAUDITFILE_TYPE 鎴 POLICYAUDITFILE_TYPE銆 + * SYSAUDITFILE_TYPE 琛ㄧず绯荤粺瀹¤鏂囦欢锛孭OLICYAUDITFILE_TYPE 琛ㄧず绛栫暐瀹¤鏂囦欢銆 + * + * 娉ㄦ剰锛 + * 濡傛灉瀹¤鏂囦欢娌℃湁鎵撳紑锛坱_thrd.audit.sysauditFile 鎴 t_thrd.audit.policyauditFile 涓 NULL锛夛紝 + * 鍒欎笉浼氭墽琛屼换浣曟搷浣滐紝鐩存帴杩斿洖銆 + * 濡傛灉 flag 涓 SYSAUDITFILE_TYPE锛屽皢鎵ц浠ヤ笅鎿嶄綔锛 + * 1. 鍒囨崲鍒颁笅涓涓璁℃枃浠躲 + * 2. 鏇存柊瀹¤绱㈠紩鏂囦欢锛坅udit index file锛夈 + * 3. 鍏抽棴绯荤粺瀹¤鏂囦欢銆 + * 濡傛灉 flag 涓 POLICYAUDITFILE_TYPE锛屽皢鍏抽棴绛栫暐瀹¤鏂囦欢銆 + * 姝ゅ嚱鏁伴氬父鍦ㄥ璁℃枃浠剁殑鎿嶄綔瀹屾垚鍚庤皟鐢紝鐢ㄤ簬鍏抽棴鏂囦欢骞舵洿鏂扮浉鍏充俊鎭 + */ +void auditfile_close(AuditFileType flag) { + // 濡傛灉瀹¤鏂囦欢鏈墦寮锛岀洿鎺ヨ繑鍥 if (t_thrd.audit.sysauditFile == NULL) return; - if ((flag == SYSAUDITFILE_TYPE) && g_instance.audit_cxt.audit_indextbl != NULL) { - /* switch to next audit file */ - pgaudit_switch_next_auditfile(); - pgaudit_update_indexfile(PG_BINARY_W, true); - } + // 濡傛灉 flag 涓 SYSAUDITFILE_TYPE锛屽垯鎵ц绯荤粺瀹¤鏂囦欢鐨勫叧闂拰鏇存柊鎿嶄綔 if (flag == SYSAUDITFILE_TYPE) { + // 鍒囨崲鍒颁笅涓涓璁℃枃浠 + pgaudit_switch_next_auditfile(); + // 鏇存柊瀹¤绱㈠紩鏂囦欢锛坅udit index file锛 + pgaudit_update_indexfile(PG_BINARY_W, true); + // 鍏抽棴绯荤粺瀹¤鏂囦欢 fclose(t_thrd.audit.sysauditFile); t_thrd.audit.sysauditFile = NULL; } + + // 濡傛灉 flag 涓 POLICYAUDITFILE_TYPE锛屽垯鍏抽棴绛栫暐瀹¤鏂囦欢 if (flag == POLICYAUDITFILE_TYPE) { fclose(t_thrd.audit.policyauditFile); t_thrd.audit.policyauditFile = NULL; } - - return; } +/* + * 鍔熻兘锛氱瓥鐣ュ璁℃枃浠惰疆鎹 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庣瓥鐣ュ璁℃枃浠剁殑杞崲鎿嶄綔銆傛牴鎹厤缃殑杞崲鏉′欢锛屽彲鑳戒細鍏抽棴褰撳墠瀹¤鏂囦欢锛 + * 閲嶅懡鍚嶅畠锛屽苟鍒涘缓涓涓柊鐨勫璁℃枃浠讹紝鐒跺悗缁х画鍐欏叆瀹¤鏁版嵁銆傚璁℃枃浠惰疆鎹㈠彲浠ユ牴鎹 + * 閰嶇疆鐨勮疆鎹㈠懆鏈燂紙PolicyAudit_RotationAge锛夋垨鏂囦欢澶у皬鏉ヨЕ鍙戙 + * 濡傛灉绛栫暐瀹¤鏂囦欢鏈墦寮锛坱_thrd.audit.policyauditFile 涓 NULL锛夛紝鍒欏嚱鏁扮洿鎺ヨ繑鍥炪 + * 濡傛灉鍚敤浜嗚疆鎹紝鍑芥暟浼氭牴鎹厤缃殑杞崲鍛ㄦ湡鍜屽綋鍓嶅璁℃枃浠剁殑澶у皬锛屽垽鏂槸鍚﹂渶瑕佹墽琛岃疆鎹㈡搷浣溿 + * 濡傛灉闇瑕佽疆鎹紝鍒欎細鎵ц浠ヤ笅鎿嶄綔锛 + * 1. 鍏抽棴褰撳墠鐨勭瓥鐣ュ璁℃枃浠躲 + * 2. 鏍规嵁杞崲鏃堕棿鏋勫缓鏂版枃浠跺悕锛屽苟閲嶅懡鍚嶅綋鍓嶆枃浠躲 + * 3. 鍒涘缓涓涓柊鐨勭瓥鐣ュ璁℃枃浠讹紝骞跺皢鍏舵墦寮浠ョ户缁褰曞璁℃暟鎹 + * 4. 璁剧疆涓嬩竴娆¤疆鎹㈢殑鏃堕棿銆 + * 濡傛灉鏃犳硶鍒涘缓鏂扮殑瀹¤鏂囦欢锛屽嚱鏁颁細璁板綍鏃ュ織骞跺仠姝㈠皾璇曞垱寤烘枃浠讹紝浣嗕笉浼氱鐢ㄥ璁° + */ static void policy_auditfile_rotate() { + // 濡傛灉绛栫暐瀹¤鏂囦欢鏈墦寮锛岀洿鎺ヨ繑鍥 if (t_thrd.audit.policyauditFile == NULL) return; - pg_time_t fntime = (pg_time_t) time(NULL); + + // 鑾峰彇褰撳墠鏃堕棿 + pg_time_t fntime = (pg_time_t)time(NULL); int rc; /* * When doing a time-based rotation, invent the new auditfile name based on @@ -1233,22 +1303,25 @@ static void policy_auditfile_rotate() * file name when we don't do the rotation immediately. */ int64 filesize = ftell(t_thrd.audit.policyauditFile); - if ((fntime + PolicyAudit_RotationAge) > policy_next_rotation_time && filesize > 0) { + if ((fntime + PolicyAudit_RotationAge) > policy_next_rotation_time && filesize > 0) { + // 鍏抽棴褰撳墠绛栫暐瀹¤鏂囦欢 auditfile_close(POLICYAUDITFILE_TYPE); char oldname[MAXPGPATH] = {0}; // current file rc = snprintf_s(oldname, sizeof(oldname), sizeof(oldname) - 1, "%s" DIR_SEP "0_event.bin", - g_instance.attr.attr_security.Audit_directory); + g_instance.attr.attr_security.Audit_directory); securec_check_ss(rc, "\0", "\0"); char newfile[MAXPGPATH] = {0}; // new rotate file rc = snprintf_s(newfile, sizeof(oldname), sizeof(oldname) - 1, "%s" DIR_SEP "done" DIR_SEP "%lld_event.bin", - g_instance.attr.attr_security.Audit_directory, (long long)fntime); + g_instance.attr.attr_security.Audit_directory, (long long)fntime); securec_check_ss(rc, "\0", "\0"); + // 灏嗗綋鍓嶆枃浠堕噸鍛藉悕涓烘柊鏂囦欢 if (rename(oldname, newfile) != 0) { ereport(LOG, (errmsg("can't rename \"%s\" to \"%s\": %m", oldname, newfile))); } - FILE* fh = auditfile_open(fntime, "a", true, policy_audit_filename, true); + // 鎵撳紑涓涓柊鐨勫璁℃枃浠朵互缁х画璁板綍 + FILE *fh = auditfile_open(fntime, "a", true, policy_audit_filename, true); if (fh == NULL) { /* @@ -1258,11 +1331,11 @@ static void policy_auditfile_rotate() * trying to create files. */ if (errno != ENFILE && errno != EMFILE) { - ereport(LOG, - (errmsg("disabling automatic rotation (use SIGHUP to re-enable)"))); + ereport(LOG, (errmsg("disabling automatic rotation (use SIGHUP to re-enable)"))); } return; } + // 璁剧疆涓嬩竴娆¤疆鎹㈢殑鏃堕棿 t_thrd.audit.policyauditFile = fh; set_next_policy_rotation_time(); } @@ -1275,7 +1348,7 @@ static void policy_auditfile_rotate() static void auditfile_rotate(bool time_based_rotation, bool size_based_rotation) { pg_time_t fntime; - FILE* fh = NULL; + FILE *fh = NULL; t_thrd.audit.rotation_requested = false; /* * When doing a time-based rotation, invent the new auditfile name based on @@ -1309,12 +1382,25 @@ static void auditfile_rotate(bool time_based_rotation, bool size_based_rotation) set_next_rotation_time(); } +/* + * 鍔熻兘锛氳缃笅涓娆$瓥鐣ュ璁℃枃浠惰疆鎹㈢殑鏃堕棿 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁版牴鎹厤缃殑绛栫暐瀹¤鏂囦欢杞崲鍛ㄦ湡锛圥olicyAudit_RotationAge锛夋潵璁$畻涓嬩竴娆¤疆鎹㈢殑鏃堕棿銆 + * 濡傛灉杞崲鍛ㄦ湡灏忎簬鎴栫瓑浜0锛屽垯鍑芥暟鐩存帴杩斿洖锛屼笉璁剧疆涓嬩竴娆¤疆鎹㈡椂闂淬 + * + * 璁$畻涓嬩竴娆¤疆鎹㈢殑鏃堕棿鏄氳繃褰撳墠鏃堕棿鍔犱笂杞崲鍛ㄦ湡寰楀埌鐨勩 + * 杞崲鍛ㄦ湡鏄互绉掍负鍗曚綅鐨勬椂闂撮棿闅旓紝鐢ㄤ簬鎺у埗绛栫暐瀹¤鏂囦欢鐨勮疆鎹€ + */ static void set_next_policy_rotation_time(void) { + // 濡傛灉杞崲鍛ㄦ湡灏忎簬鎴栫瓑浜0锛岀洿鎺ヨ繑鍥烇紝涓嶈缃笅涓娆¤疆鎹㈡椂闂 if (PolicyAudit_RotationAge <= 0) { return; } - policy_next_rotation_time = (pg_time_t) time(NULL); + // 鑾峰彇褰撳墠鏃堕棿 + policy_next_rotation_time = (pg_time_t)time(NULL); + // 璁$畻涓嬩竴娆¤疆鎹㈢殑鏃堕棿锛屽姞涓婅疆鎹㈠懆鏈 policy_next_rotation_time += PolicyAudit_RotationAge; } @@ -1324,7 +1410,7 @@ static void set_next_policy_rotation_time(void) static void set_next_rotation_time(void) { pg_time_t now; - struct pg_tm* tm = NULL; + struct pg_tm *tm = NULL; int rotinterval; /* nothing to do if time-based rotation is disabled */ if (u_sess->attr.attr_security.Audit_RotationAge <= 0) @@ -1347,7 +1433,21 @@ static void set_next_rotation_time(void) now -= tm->tm_gmtoff; t_thrd.audit.next_rotation_time = now; } - +/* + * 鍔熻兘锛氱敓鎴愬璁℃枃浠惰鍛婁俊鎭 + * + * 鍙傛暟锛 + * remain_time锛氬墿浣欐椂闂达紝浠ョ涓哄崟浣 + * filesize锛氭枃浠跺ぇ灏忥紝浠ュ瓧鑺備负鍗曚綅 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁版牴鎹璁¢厤缃拰瀹¤鏂囦欢鐘舵佺敓鎴愯鍛婁俊鎭傛牴鎹笉鍚岀殑閰嶇疆鍜岀姸鎬侊紝鍙兘浼氱敓鎴愪互涓嬭鍛婏細 + * 1. + * 褰撳璁℃竻鐞嗙瓥鐣ワ紙Audit_CleanupPolicy锛夋垨鍓╀綑鏃堕棿涓0锛屼笖瀹¤鏂囦欢鎬荤┖闂磋秴杩囧璁$┖闂撮檺鍒讹紙Audit_SpaceLimit锛夋椂锛岀敓鎴愯鍛娿 + * 2. 褰撳璁℃竻鐞嗙瓥鐣ヤ负0锛屽墿浣欐椂闂村ぇ浜0锛屼笖瀹¤鏂囦欢鎬荤┖闂磋秴杩囧璁$┖闂撮檺鍒舵椂锛岀敓鎴愯鍛娿 + * 3. 褰撳璁℃枃浠舵绘暟瓒呰繃瀹¤鏂囦欢淇濈暀闃堝硷紙Audit_RemainThreshold锛夋椂锛岀敓鎴愯鍛娿 + * 璀﹀憡淇℃伅鍖呮嫭瀹¤鏂囦欢鐨勬荤┖闂淬佸璁$┖闂撮檺鍒躲佸璁℃枃浠剁殑鍓╀綑鏃堕棿銆佸璁℃枃浠舵绘暟绛変俊鎭 + */ void pgaudit_gen_auditfile_warning(pg_time_t remain_time, uint4 filesize) { if ((u_sess->attr.attr_security.Audit_CleanupPolicy || remain_time == 0) && @@ -1373,11 +1473,11 @@ void pgaudit_gen_auditfile_warning(pg_time_t remain_time, uint4 filesize) (long long int)(g_instance.audit_cxt.pgaudit_totalspace + filesize), u_sess->attr.attr_security.Audit_SpaceLimit))); #else - ereport(WARNING, (errmsg("Based on time-priority policy, the oldest audit file is beyond %d days or " - "audit file total space(%ld B) exceed guc parameter(audit_space_limit: %d KB)", - u_sess->attr.attr_security.Audit_RemainAge, - (g_instance.audit_cxt.pgaudit_totalspace + filesize), - u_sess->attr.attr_security.Audit_SpaceLimit))); + ereport(WARNING, (errmsg("Based on time-priority policy, the oldest audit file is beyond %d days or " + "audit file total space(%ld B) exceed guc parameter(audit_space_limit: %d KB)", + u_sess->attr.attr_security.Audit_RemainAge, + (g_instance.audit_cxt.pgaudit_totalspace + filesize), + u_sess->attr.attr_security.Audit_SpaceLimit))); #endif if (g_instance.audit_cxt.audit_indextbl->count > (uint32)u_sess->attr.attr_security.Audit_RemainThreshold) ereport(WARNING, @@ -1385,7 +1485,26 @@ void pgaudit_gen_auditfile_warning(pg_time_t remain_time, uint4 filesize) g_instance.audit_cxt.audit_indextbl->count, u_sess->attr.attr_security.Audit_RemainThreshold))); ereport(WARNING, (errmsg("%s", t_thrd.audit.pgaudit_filepath))); } - +/* + * 鍔熻兘锛氭牴鎹椂闂寸瓥鐣ュ垽鏂槸鍚﹀簲淇濈暀瀹¤鏂囦欢 + * + * 鍙傛暟锛 + * remain_time锛氬墿浣欐椂闂达紝浠ョ涓哄崟浣 + * filesize锛氭枃浠跺ぇ灏忥紝浠ュ瓧鑺備负鍗曚綅 + * index锛氬綋鍓嶅璁℃枃浠剁储寮 + * item锛氬綋鍓嶅璁℃枃浠剁殑鍏冩暟鎹俊鎭 + * + * 杩斿洖鍊硷細 + * 濡傛灉鏍规嵁鏃堕棿绛栫暐搴旇淇濈暀瀹¤鏂囦欢锛屽垯杩斿洖 true锛涘惁鍒欒繑鍥 false銆 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁版牴鎹璁℃枃浠剁殑鎬绘暟銆佸墿浣欐椂闂村拰绌洪棿闄愬埗浠ュ強鏃堕棿鎴充俊鎭垽鏂槸鍚﹀簲璇ヤ繚鐣欏璁℃枃浠躲傚叿浣撻昏緫鍖呮嫭锛 + * 1.濡傛灉瀹¤鏂囦欢鎬绘暟灏忎簬鎴栫瓑浜庡璁℃枃浠朵繚鐣欓槇鍊硷紙Audit_RemainThreshold锛夊苟涓斿墿浣欐椂闂村ぇ浜0锛屽苟涓斿璁℃枃浠舵荤┖闂存湭瓒呰繃鏈澶ч檺鍒讹紙SPACE_MAXIMUM_SIZE锛夛紝鍒欑户缁垽鏂 + * 2. 濡傛灉瀹¤鏂囦欢鎬荤┖闂磋秴杩囧璁$┖闂撮檺鍒讹紙Audit_SpaceLimit锛夛紝鍒欑敓鎴愯鍛婁俊鎭 + * 3.鑾峰彇褰撳墠瀹¤鏂囦欢鍜屼笅涓涓璁℃枃浠剁殑鏃堕棿鎴充俊鎭紝濡傛灉鍓╀綑鏃堕棿澶т簬鎴栫瓑浜庡綋鍓嶅璁℃枃浠剁殑鍒涘缓鏃堕棿璺濈涓婃瀹¤鐨勬椂闂达紝鎴栬呬笅涓涓璁℃枃浠跺瓨鍦ㄤ笖鍓╀綑鏃堕棿澶т簬涓嬩竴涓璁℃枃浠剁殑鍒涘缓鏃堕棿璺濈涓婃瀹¤鐨勬椂闂达紝鍒欒繑鍥 + * true锛岃〃绀哄簲璇ヤ繚鐣欏璁℃枃浠躲 + * 4. 濡傛灉涓嶆弧瓒充笂杩版潯浠讹紝鍒欒繑鍥 false锛岃〃绀轰笉搴旇淇濈暀瀹¤鏂囦欢銆 + */ bool should_keep_basedon_timepolicy(pg_time_t remain_time, uint4 filesize, uint32 index, const AuditIndexItem *item) { if (g_instance.audit_cxt.audit_indextbl->count <= (uint32)u_sess->attr.attr_security.Audit_RemainThreshold && @@ -1424,7 +1543,7 @@ bool should_keep_basedon_timepolicy(pg_time_t remain_time, uint4 filesize, uint3 static void pgaudit_cleanup(void) { uint32 index = 0; - AuditIndexItem* item = NULL; + AuditIndexItem *item = NULL; bool truncated = false; if (g_instance.audit_cxt.audit_indextbl == NULL) return; @@ -1436,8 +1555,8 @@ static void pgaudit_cleanup(void) LWLockAcquire(g_instance.audit_cxt.index_file_lock, LW_EXCLUSIVE); index = g_instance.audit_cxt.audit_indextbl->begidx; while (g_instance.audit_cxt.pgaudit_totalspace + filesize >= - ((uint64)u_sess->attr.attr_security.Audit_SpaceLimit * 1024L) || - g_instance.audit_cxt.audit_indextbl->count > (uint32)u_sess->attr.attr_security.Audit_RemainThreshold) { + ((uint64)u_sess->attr.attr_security.Audit_SpaceLimit * 1024L) || + g_instance.audit_cxt.audit_indextbl->count > (uint32)u_sess->attr.attr_security.Audit_RemainThreshold) { errno_t errorno = EOK; item = g_instance.audit_cxt.audit_indextbl->data + index; uint32 fnum = item->filenum; @@ -1453,7 +1572,7 @@ static void pgaudit_cleanup(void) /* trunate audit file */ int rc = snprintf_s(t_thrd.audit.pgaudit_filepath, MAXPGPATH, MAXPGPATH - 1, pgaudit_filename, - g_instance.attr.attr_security.Audit_directory, item->filenum); + g_instance.attr.attr_security.Audit_directory, item->filenum); securec_check_intval(rc, , ); struct stat statbuf; if (stat(t_thrd.audit.pgaudit_filepath, &statbuf) == 0 && unlink(t_thrd.audit.pgaudit_filepath) < 0) { @@ -1502,6 +1621,17 @@ static void pgaudit_cleanup(void) * -------------------------------- */ /* SIGQUIT signal handler for auditor process */ +/* + * 鍔熻兘锛氬璁″瓙杩涚▼鐨勯鍑轰俊鍙峰鐞嗗嚱鏁 + * + * 鍙傛暟锛 + * SIGNAL_ARGS锛氫俊鍙峰鐞嗗嚱鏁扮殑鍙傛暟锛岄氬父涓烘爣鍑嗙殑 SIGNAL_ARGS 绫诲瀷 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁拌鐢ㄤ簬澶勭悊瀹¤瀛愯繘绋嬬殑閫鍑轰俊鍙枫傚湪鍑芥暟鍐呴儴锛屽畠灏 `t_thrd.audit.need_exit` 鏍囧織璁剧疆涓 true锛 + * 鐒跺悗閫氳繃 `SetLatch` 鍑芥暟璁剧疆瀹¤瀛愯繘绋嬬殑淇″彿浜嬩欢锛屼互瑙﹀彂瀹¤瀛愯繘绋嬬殑閫鍑恒傝鍑芥暟杩樹繚瀛樺拰鎭㈠浜 `errno`锛 + * 浠ョ‘淇濅笉褰卞搷鍏朵粬浠g爜銆 + */ static void pgaudit_exit(SIGNAL_ARGS) { int save_errno = errno; @@ -1511,6 +1641,17 @@ static void pgaudit_exit(SIGNAL_ARGS) } /* SIGHUP: set flag to reload config file */ +/* + * 鍔熻兘锛歋IGHUP淇″彿澶勭悊鍑芥暟 + * + * 鍙傛暟锛 + * SIGNAL_ARGS锛氫俊鍙峰鐞嗗嚱鏁扮殑鍙傛暟锛岄氬父涓烘爣鍑嗙殑SIGNAL_ARGS绫诲瀷 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁拌鐢ㄤ簬澶勭悊SIGHUP淇″彿銆傚湪鍑芥暟鍐呴儴锛屽畠灏哷t_thrd.audit.got_SIGHUP`鏍囧織璁剧疆涓簍rue锛 + * 鐒跺悗閫氳繃`SetLatch`鍑芥暟璁剧疆瀹¤瀛愯繘绋嬬殑淇″彿浜嬩欢锛屼互瑙﹀彂鐩稿叧鎿嶄綔銆傝鍑芥暟杩樹繚瀛樺拰鎭㈠浜哷errno`锛 + * 浠ョ‘淇濅笉褰卞搷鍏朵粬浠g爜銆 + */ static void sigHupHandler(SIGNAL_ARGS) { int save_errno = errno; @@ -1520,6 +1661,17 @@ static void sigHupHandler(SIGNAL_ARGS) } /* SIGUSR1: set flag to rotate auditfile */ +/* + * 鍔熻兘锛歋IGUSR1淇″彿澶勭悊鍑芥暟 + * + * 鍙傛暟锛 + * SIGNAL_ARGS锛氫俊鍙峰鐞嗗嚱鏁扮殑鍙傛暟锛岄氬父涓烘爣鍑嗙殑SIGNAL_ARGS绫诲瀷 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁拌鐢ㄤ簬澶勭悊SIGUSR1淇″彿銆傚湪鍑芥暟鍐呴儴锛屽畠灏哷t_thrd.audit.rotation_requested`鏍囧織璁剧疆涓簍rue锛 + * 鐒跺悗閫氳繃`SetLatch`鍑芥暟璁剧疆瀹¤瀛愯繘绋嬬殑淇″彿浜嬩欢锛屼互瑙﹀彂鐩稿叧鎿嶄綔銆傝鍑芥暟杩樹繚瀛樺拰鎭㈠浜哷errno`锛 + * 浠ョ‘淇濅笉褰卞搷鍏朵粬浠g爜銆 + */ static void sigUsr1Handler(SIGNAL_ARGS) { int save_errno = errno; @@ -1550,7 +1702,7 @@ static void sigUsr1Handler(SIGNAL_ARGS) * warning from ignoring write()'s result, so do a little dance with casting * rc to void to shut up the compiler. */ -static void write_pipe_chunks(char* data, int len, AuditClassType type) +static void write_pipe_chunks(char *data, int len, AuditClassType type) { static volatile uint32 pipe_count = 0; int thread_num = g_instance.audit_cxt.thread_num; @@ -1603,7 +1755,20 @@ static void write_pipe_chunks(char* data, int len, AuditClassType type) * Brief : append a string field to a streamed data * Description : */ -static void appendStringField(StringInfo str, const char* s) +/* + * 鍔熻兘锛氬悜StringInfo缁撴瀯涓坊鍔犱竴涓瓧绗︿覆瀛楁 + * + * 鍙傛暟锛 + * str锛氭寚鍚慡tringInfo缁撴瀯鐨勬寚閽堬紝鐢ㄤ簬瀛樺偍瀛楃涓插瓧娈 + * s锛氭寚鍚戝緟娣诲姞鐨勫瓧绗︿覆鐨勬寚閽堬紝鍙互涓篘ULL + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庡皢瀛楃涓插瓧娈垫坊鍔犲埌StringInfo缁撴瀯涓紝StringInfo鏄竴涓敤浜庢瀯寤哄拰鎿嶄綔瀛楃涓茬殑宸ュ叿銆 + * 濡傛灉杈撳叆鐨勫瓧绗︿覆鎸囬拡s涓篘ULL锛屽垯鍑芥暟浼氭坊鍔犱竴涓┖瀛楃涓插瓧娈碉紝瀛楁澶у皬涓0銆 + * 鍚﹀垯锛屽嚱鏁颁細璁$畻瀛楃涓瞫鐨勫ぇ灏忥紝灏嗗叾澶у皬娣诲姞鍒癝tringInfo涓紝鐒跺悗鍐嶆坊鍔犲瓧绗︿覆s鐨勫唴瀹广 + * 瀛楃涓插瓧娈电殑鏍煎紡閫氬父涓猴細[瀛楁澶у皬锛4瀛楄妭锛塢[瀛楁鍐呭]锛屼互渚垮悗缁鍙栧拰瑙f瀽銆 + */ +static void appendStringField(StringInfo str, const char *s) { int size = 0; @@ -1611,35 +1776,59 @@ static void appendStringField(StringInfo str, const char* s) return; if (s == NULL) - appendBinaryStringInfo(str, (char*)&size, sizeof(int)); + appendBinaryStringInfo(str, (char *)&size, sizeof(int)); else { size = strlen(s) + 1; - appendBinaryStringInfo(str, (char*)&size, sizeof(int)); + appendBinaryStringInfo(str, (char *)&size, sizeof(int)); appendBinaryStringInfo(str, s, size); } } +/* + * 鍔熻兘锛氳幏鍙栧綋鍓嶇殑鏃堕棿鎴筹紙浠ユ绉掍负鍗曚綅锛 + * + * 杩斿洖鍊硷細浠ユ绉掍负鍗曚綅鐨勫綋鍓嶆椂闂存埑 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁颁娇鐢ㄧ郴缁熻皟鐢╜gettimeofday`鏉ヨ幏鍙栧綋鍓嶆椂闂达紝绮剧‘鍒板井绉掔骇鍒 + * 瀹冨皢绉掑拰寰閮ㄥ垎鐩稿姞锛屽皢鍏惰浆鎹负姣骞惰繑鍥炪 + * 鏃堕棿鎴宠〃绀轰粠鏌愪釜鍙傝冪偣锛堥氬父鏄疷NIX绾厓锛夊埌鐜板湪缁忚繃鐨勬椂闂达紝浠ユ绉掍负鍗曚綅銆 + * 杩欏湪寰堝搴旂敤涓兘鏄湁鐢ㄧ殑锛屽鎬ц兘鍒嗘瀽銆佷簨浠惰鏃剁瓑銆 + */ static pg_time_t current_timestamp() { struct timeval te; - gettimeofday(&te, NULL); // get current time - pg_time_t milliseconds = te.tv_sec * 1000LL + te.tv_usec / 1000; // calculate milliseconds + gettimeofday(&te, NULL); // 鑾峰彇褰撳墠鏃堕棿 + pg_time_t milliseconds = te.tv_sec * 1000LL + te.tv_usec / 1000; // 璁$畻姣 return milliseconds; } - +/* + * 鍔熻兘锛氭鏌ユ槸鍚︽弧瓒虫墽琛屽璁$殑鏉′欢 + * + * 杩斿洖鍊硷細濡傛灉婊¤冻鎵ц瀹¤鐨勬潯浠讹紝鍒欒繑鍥瀟rue锛屽惁鍒欒繑鍥瀎alse + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庣‘瀹氭槸鍚﹀簲璇ユ墽琛屽璁℃搷浣溿 + * 瀹冧細妫鏌ヤ互涓嬫潯浠讹細 + * 1. 鏄惁宸插惎鐢ㄥ璁★紙閫氳繃妫鏌ラ厤缃弬鏁皍_sess->attr.attr_security.Audit_enabled锛夈 + * 2. 鏄惁澶勪簬涓昏妭鐐规ā寮忥紙瀵逛簬澶氳妭鐐归泦缇わ紝妫鏌ユ槸鍚﹁繛鎺ュ埌涓昏妭鐐癸級銆 + * 3. 鏄惁澶勪簬绛夊緟妯″紡锛堝浜庡鑺傜偣闆嗙兢锛屾鏌ユ槸鍚﹀浜庣瓑寰呮ā寮忥級銆 + * 濡傛灉涓婅堪鏉′欢涔嬩竴涓嶆弧瓒筹紝鍑芥暟灏嗚繑鍥瀎alse锛岃〃绀轰笉搴旀墽琛屽璁℃搷浣溿 + * 鍚﹀垯锛屽皢杩斿洖true锛岃〃绀哄彲浠ユ墽琛屽璁℃搷浣溿 + */ static bool audit_status_check_ok() { #ifdef ENABLE_MULTIPLE_NODES /* check whether POSTMASTER is running in standby mode */ if (!u_sess->attr.attr_security.Audit_enabled || (PGSharedMemoryAttached() && t_thrd.postmaster_cxt.HaShmData && - (STANDBY_MODE == t_thrd.postmaster_cxt.HaShmData->current_mode || - PENDING_MODE == t_thrd.postmaster_cxt.HaShmData->current_mode))) + (STANDBY_MODE == t_thrd.postmaster_cxt.HaShmData->current_mode || + PENDING_MODE == t_thrd.postmaster_cxt.HaShmData->current_mode))) return false; #else /* After the standby read function is added, the standby node needs to be audited. */ if (!u_sess->attr.attr_security.Audit_enabled || (PGSharedMemoryAttached() && t_thrd.postmaster_cxt.HaShmData && - PENDING_MODE == t_thrd.postmaster_cxt.HaShmData->current_mode)) - return false; + PENDING_MODE == t_thrd.postmaster_cxt.HaShmData->current_mode)) + return false; #endif return true; @@ -1669,7 +1858,7 @@ static bool audit_type_validcheck(AuditType type) break; case AUDIT_LOCK_USER: case AUDIT_UNLOCK_USER: - type_status = (unsigned int)u_sess->attr.attr_security.Audit_LockUser; + type_status = (unsigned int)u_sess->attr.attr_security.Audit_LockUser; break; case AUDIT_GRANT_ROLE: case AUDIT_REVOKE_ROLE: @@ -1789,7 +1978,7 @@ static bool audit_type_validcheck(AuditType type) } /* get all Audit Event Info from Proc Port */ -static bool audit_get_clientinfo(AuditType type, const char* object_name, AuditEventInfo &event_info) +static bool audit_get_clientinfo(AuditType type, const char *object_name, AuditEventInfo &event_info) { /* * Note that the number of field should keep the same with PGAUDIT_QUERY_COLS @@ -1816,7 +2005,7 @@ static bool audit_get_clientinfo(AuditType type, const char* object_name, AuditE } else { *username = u_sess->proc_cxt.MyProcPort->user_name; } - + /* * append user id information, get user id from table as invalid in session * not safe when access table when run logout process as not in normal transaction @@ -1829,8 +2018,8 @@ static bool audit_get_clientinfo(AuditType type, const char* object_name, AuditE if (*username != NULL && useroid == 0) { ResourceOwner currentOwner = NULL; currentOwner = t_thrd.utils_cxt.CurrentResourceOwner; - ResourceOwner tmpOwner = ResourceOwnerCreate(t_thrd.utils_cxt.CurrentResourceOwner, "CheckUserOid", - THREAD_GET_MEM_CXT_GROUP(MEMORY_CONTEXT_SECURITY)); + ResourceOwner tmpOwner = ResourceOwnerCreate(t_thrd.utils_cxt.CurrentResourceOwner, "CheckUserOid", + THREAD_GET_MEM_CXT_GROUP(MEMORY_CONTEXT_SECURITY)); t_thrd.utils_cxt.CurrentResourceOwner = tmpOwner; useroid = get_role_oid(*username, true); ResourceOwnerRelease(tmpOwner, RESOURCE_RELEASE_BEFORE_LOCKS, true, true); @@ -1861,12 +2050,8 @@ static bool audit_get_clientinfo(AuditType type, const char* object_name, AuditE break; } t_thrd.audit.user_login_time = GetCurrentTimestamp(); - errorno = snprintf_s(threadid, - MAXNUMLEN * 4, - MAXNUMLEN * 4 - 1, - "%lu@%ld", - t_thrd.proc_cxt.MyProcPid, - t_thrd.audit.user_login_time); + errorno = snprintf_s(threadid, MAXNUMLEN * 4, MAXNUMLEN * 4 - 1, "%lu@%ld", t_thrd.proc_cxt.MyProcPid, + t_thrd.audit.user_login_time); securec_check_ss(errorno, "\0", "\0"); int portNum; @@ -1890,12 +2075,8 @@ static bool audit_get_clientinfo(AuditType type, const char* object_name, AuditE if (*remotehost == NULL || (**remotehost) == '\0') *remotehost = _("[unknown]"); - errorno = snprintf_s(event_info.client_info, - MAX_CONNECTION_INFO_SIZE, - MAX_CONNECTION_INFO_SIZE - 1, - "%s@%s", - *appname, - *remotehost); + errorno = snprintf_s(event_info.client_info, MAX_CONNECTION_INFO_SIZE, MAX_CONNECTION_INFO_SIZE - 1, "%s@%s", + *appname, *remotehost); securec_check_ss(errorno, "\0", "\0"); return true; @@ -1907,7 +2088,7 @@ static bool audit_get_clientinfo(AuditType type, const char* object_name, AuditE * 1. verify type and process to decide whehter to report audit or not * 2. get all audit info from connection * 3. append audit info to string buffer - * 4. last, write audit file or send to auditor process to deal with + * 4. last, write audit file or send to auditor process to deal with * the fileds are arraged as below sequence, Note it's not liable to modify them as to keep compatibility of version * header|userid|username|dbname|client_info|object_name|detail_info|nodename|threadid|localport|remoteport */ @@ -1929,15 +2110,15 @@ void audit_report(AuditType type, AuditResult result, const char *object_name, c AuditData adata; AuditEventInfo event_info; if (!audit_get_clientinfo(type, object_name, event_info)) { - return; + return; } char *userid = event_info.userid; - const char* username = event_info.username; - const char* dbname = event_info.dbname; - char* client_info = event_info.client_info; - char* threadid = event_info.threadid; - char* localport = event_info.localport; - char* remoteport = event_info.remoteport; + const char *username = event_info.username; + const char *dbname = event_info.dbname; + char *client_info = event_info.client_info; + char *threadid = event_info.threadid; + char *localport = event_info.localport; + char *remoteport = event_info.remoteport; /* append xid info when audit_xid_info = 1 */ char *detail_info_xid = NULL; @@ -1959,7 +2140,7 @@ void audit_report(AuditType type, AuditResult result, const char *object_name, c adata.type = type; adata.result = result; initStringInfo(&buf); - appendBinaryStringInfo(&buf, (char*)&adata, AUDIT_HEADER_SIZE); + appendBinaryStringInfo(&buf, (char *)&adata, AUDIT_HEADER_SIZE); /* append audit data */ appendStringField(&buf, userid); @@ -1995,7 +2176,21 @@ void audit_report(AuditType type, AuditResult result, const char *object_name, c } /* Brief : close a file. */ -static void pgaudit_close_file(FILE* fp, const char* file) +/* + * 鍔熻兘锛氬叧闂枃浠跺苟澶勭悊鍙兘鍑虹幇鐨勯敊璇 + * + * 鍙傛暟锛 + * fp锛氳鍏抽棴鐨勬枃浠舵寚閽堛 + * file锛氭枃浠跺悕锛岀敤浜庡湪鍑虹幇閿欒鏃惰褰曢敊璇秷鎭 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庡叧闂枃浠讹紝骞跺湪鏂囦欢鎿嶄綔鍑虹幇閿欒鏃惰褰曠浉搴旂殑閿欒娑堟伅銆 + * 瀹冮鍏堟鏌ユ枃浠舵寚閽堝拰鏂囦欢鍚嶆槸鍚︿负绌猴紝濡傛灉涓虹┖锛屽垯鐩存帴杩斿洖锛屼笉鎵ц浠讳綍鎿嶄綔銆 + * 鐒跺悗锛屽畠妫鏌ユ枃浠舵槸鍚﹀湪鍐欏叆杩囩▼涓嚭鐜伴敊璇紙浣跨敤ferror()鍑芥暟锛夛紝濡傛灉鏄紝鍒欒褰曠浉搴旂殑閿欒娑堟伅锛屽苟灏濊瘯鍏抽棴鏂囦欢銆 + * 鏈鍚庯紝濡傛灉鍏抽棴鏂囦欢鏃跺嚭鐜伴敊璇紝涔熶細璁板綍鐩稿簲鐨勯敊璇秷鎭 + * 鍑芥暟鐨勭洰鐨勬槸纭繚鏂囦欢鑳藉姝g‘鍏抽棴锛屽苟鍦ㄥ嚭鐜伴敊璇椂璁板綍閿欒娑堟伅锛屼互渚胯繘琛屾晠闅滄帓闄ゃ + */ +static void pgaudit_close_file(FILE *fp, const char *file) { if (NULL == file || NULL == fp) { return; @@ -2012,16 +2207,16 @@ static void pgaudit_close_file(FILE* fp, const char* file) } /* Brief : read the index table into memory from file. */ -static void pgaudit_read_indexfile(const char* audit_directory) +static void pgaudit_read_indexfile(const char *audit_directory) { - FILE* fp = NULL; + FILE *fp = NULL; struct stat statbuf; char tblfile_path[MAXPGPATH] = {0}; size_t nread = 0; AuditIndexTableNew indextbl; int rc = snprintf_s(tblfile_path, MAXPGPATH, MAXPGPATH - 1, "%s/%s", audit_directory, audit_indextbl_file); - securec_check_intval(rc,,); + securec_check_intval(rc, , ); /* upgrade processing and sync old index table for old version */ if (pgaudit_find_indexfile()) { pgaudit_rewrite_indexfile(); @@ -2081,26 +2276,22 @@ static void pgaudit_read_indexfile(const char* audit_directory) * Brief : write the index table into file from memory. * Description : */ -static void pgaudit_update_indexfile(const char* mode, bool allow_errors) +static void pgaudit_update_indexfile(const char *mode, bool allow_errors) { - FILE* fp = NULL; + FILE *fp = NULL; char tblfile_path[MAXPGPATH] = {0}; size_t nwritten = 0; size_t count = 0; - int rc = snprintf_s(tblfile_path, - MAXPGPATH, - MAXPGPATH - 1, - "%s/%s", - g_instance.attr.attr_security.Audit_directory, - audit_indextbl_file); - securec_check_intval(rc,,); + int rc = snprintf_s(tblfile_path, MAXPGPATH, MAXPGPATH - 1, "%s/%s", g_instance.attr.attr_security.Audit_directory, + audit_indextbl_file); + securec_check_intval(rc, , ); /* Open the audit index table file to write out the current values. */ fp = AllocateFile(tblfile_path, mode); if (NULL == fp) { ereport(allow_errors ? LOG : FATAL, - (errcode_for_file_access(), errmsg("could not open audit index table file \"%s\": %m", tblfile_path))); + (errcode_for_file_access(), errmsg("could not open audit index table file \"%s\": %m", tblfile_path))); return; } /* check upgrade version to do audit upgrade processing */ @@ -2111,7 +2302,7 @@ static void pgaudit_update_indexfile(const char* mode, bool allow_errors) nwritten = fwrite(g_instance.audit_cxt.audit_indextbl, 1, count, fp); if (nwritten != count) ereport(allow_errors ? LOG : FATAL, - (errcode_for_file_access(), errmsg("could not write to audit index file: %m"))); + (errcode_for_file_access(), errmsg("could not write to audit index file: %m"))); } LWLockRelease(g_instance.audit_cxt.index_file_lock); ereport(DEBUG1, (errmsg("pgaudit_update_indexfile index size: %ld", (long)ftell(fp)))); @@ -2119,16 +2310,36 @@ static void pgaudit_update_indexfile(const char* mode, bool allow_errors) pgaudit_close_file(fp, tblfile_path); } +/* + * 鍔熻兘锛氳幏鍙栧綋鍓嶅璁$储寮曡〃涓殑鏈澶ф枃浠跺彿 + * + * 鍙傛暟锛 + * old_thread_num - 鏃х殑瀹¤绾跨▼鏁 + * + * 杩斿洖鍊硷細 + * 褰撳墠瀹¤绱㈠紩琛ㄤ腑鐨勬渶澶ф枃浠跺彿 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁伴亶鍘嗗璁$储寮曡〃涓殑褰撳墠绱㈠紩椤癸紝鎵惧埌鏈澶х殑鏂囦欢鍙凤紝骞惰繑鍥炲畠銆 + * 鏂囦欢鍙风敤浜庢爣璇嗗璁℃棩蹇楁枃浠躲 + */ static uint32 pgaudit_get_max_fnum(uint32 old_thread_num) { uint32 currrent_max_fnum = 0; + + // 閬嶅巻鏃х殑瀹¤绾跨▼鏁 for (uint32 i = 0; i < old_thread_num; ++i) { + // 鑾峰彇褰撳墠绱㈠紩椤 AuditIndexItem *cur_item = g_instance.audit_cxt.audit_indextbl->data + g_instance.audit_cxt.audit_indextbl->curidx[i]; + + // 妫鏌ユ槸鍚︽湁鏇村ぇ鐨勬枃浠跺彿 if (currrent_max_fnum < cur_item->filenum) { currrent_max_fnum = cur_item->filenum; } } + + // 杩斿洖褰撳墠瀹¤绱㈠紩琛ㄤ腑鐨勬渶澶ф枃浠跺彿 return currrent_max_fnum; } @@ -2140,12 +2351,8 @@ static bool pgaudit_find_indexfile(void) { struct stat statbuf; char tblfile_path[MAXPGPATH] = {0}; - int rc = snprintf_s(tblfile_path, - MAXPGPATH, - MAXPGPATH - 1, - "%s/%s", - g_instance.attr.attr_security.Audit_directory, - audit_indextbl_old_file); + int rc = snprintf_s(tblfile_path, MAXPGPATH, MAXPGPATH - 1, "%s/%s", g_instance.attr.attr_security.Audit_directory, + audit_indextbl_old_file); securec_check_ss(rc, "\0", "\0"); if (stat(tblfile_path, &statbuf) == 0) { return true; @@ -2164,13 +2371,9 @@ static void pgaudit_indexfile_upgrade(void) if (t_thrd.proc == NULL) { return; } - int rc = snprintf_s(tblfile_path, - MAXPGPATH, - MAXPGPATH - 1, - "%s/%s", - g_instance.attr.attr_security.Audit_directory, - audit_indextbl_old_file); - securec_check_intval(rc,,); + int rc = snprintf_s(tblfile_path, MAXPGPATH, MAXPGPATH - 1, "%s/%s", g_instance.attr.attr_security.Audit_directory, + audit_indextbl_old_file); + securec_check_intval(rc, , ); ereport(DEBUG1, (errmsg("audit upgrade processing index file upgrade enter"))); if (t_thrd.proc->workingVersionNum >= AUDIT_INDEX_TABLE_VERSION_NUM) { @@ -2198,24 +2401,25 @@ static void pgaudit_indexfile_upgrade(void) * Brief : pgaudit_indexfile_sync * Description : sync old and new index table file function */ -static void pgaudit_indexfile_sync(const char* mode, bool allow_errors) +static void pgaudit_indexfile_sync(const char *mode, bool allow_errors) { - FILE* fp = NULL; + FILE *fp = NULL; struct stat statbuf; char tblfile_path[MAXPGPATH] = {0}; size_t nwritten = 0; size_t count = 0; int rc = snprintf_s(tblfile_path, MAXPGPATH, MAXPGPATH - 1, "%s/%s", g_instance.attr.attr_security.Audit_directory, - audit_indextbl_old_file); - securec_check_intval(rc, ,); + audit_indextbl_old_file); + securec_check_intval(rc, , ); ereport(DEBUG1, (errmsg("audit upgrade processing index file sync enter"))); if (stat(tblfile_path, &statbuf) == 0) { /* old index table file is exist and sync file */ fp = AllocateFile(tblfile_path, mode); if (NULL == fp) { - ereport(allow_errors ? LOG : FATAL, (errcode_for_file_access(), - errmsg("could not open audit index table file \"%s\": %m", tblfile_path))); + ereport( + allow_errors ? LOG : FATAL, + (errcode_for_file_access(), errmsg("could not open audit index table file \"%s\": %m", tblfile_path))); return; } /* copy audit indextbl from new to old in memory */ @@ -2241,7 +2445,7 @@ static void pgaudit_indexfile_sync(const char* mode, bool allow_errors) nwritten = fwrite(g_instance.audit_cxt.audit_indextbl_old, 1, count, fp); if (nwritten != count) ereport(allow_errors ? LOG : FATAL, - (errcode_for_file_access(), errmsg("could not write to audit old index file: %m"))); + (errcode_for_file_access(), errmsg("could not write to audit old index file: %m"))); } LWLockRelease(g_instance.audit_cxt.index_file_lock); ereport(LOG, (errmsg("pgaudit_indexfile_sync index size: %ld", (long)ftell(fp)))); @@ -2255,23 +2459,19 @@ static void pgaudit_indexfile_sync(const char* mode, bool allow_errors) */ static void pgaudit_rewrite_indexfile(void) { - FILE* fp = NULL; + FILE *fp = NULL; char tblfile_path[MAXPGPATH] = {0}; size_t nread = 0; AuditIndexTable old_index_tbl; - int rc = snprintf_s(tblfile_path, - MAXPGPATH, - MAXPGPATH - 1, - "%s/%s", - g_instance.attr.attr_security.Audit_directory, - audit_indextbl_old_file); - securec_check_intval(rc,,); + int rc = snprintf_s(tblfile_path, MAXPGPATH, MAXPGPATH - 1, "%s/%s", g_instance.attr.attr_security.Audit_directory, + audit_indextbl_old_file); + securec_check_intval(rc, , ); /* open old index file and read audit index table */ fp = AllocateFile(tblfile_path, PG_BINARY_R); if (NULL == fp) { - ereport(LOG, - (errcode_for_file_access(), errmsg("could not open audit old index table file \"%s\": %m", tblfile_path))); + ereport(LOG, (errcode_for_file_access(), + errmsg("could not open audit old index table file \"%s\": %m", tblfile_path))); return; } ereport(LOG, (errmsg("audit upgrade processing rewrite enter"))); @@ -2292,8 +2492,8 @@ static void pgaudit_rewrite_indexfile(void) g_instance.audit_cxt.global_audit_context, (old_index_tbl.maxnum * sizeof(AuditIndexItem) + old_indextbl_header_size)); errorno = memcpy_s(g_instance.audit_cxt.audit_indextbl_old, - old_index_tbl.maxnum * sizeof(AuditIndexItem) + old_indextbl_header_size, - &old_index_tbl, old_indextbl_header_size); + old_index_tbl.maxnum * sizeof(AuditIndexItem) + old_indextbl_header_size, &old_index_tbl, + old_indextbl_header_size); securec_check(errorno, "\0", "\0"); /* rewrite old index table to new index table */ g_instance.audit_cxt.audit_indextbl = (AuditIndexTableNew *)MemoryContextAllocZero( @@ -2333,8 +2533,8 @@ static void pgaudit_indextbl_init_new(void) /* init new one when but not from index file when database init first time */ if (g_instance.audit_cxt.audit_indextbl == NULL) { ereport(LOG, (errmsg("pgaudit_indextbl_init_new first init"))); - g_instance.audit_cxt.audit_indextbl = - (AuditIndexTableNew *)MemoryContextAllocZero(g_instance.audit_cxt.global_audit_context, + g_instance.audit_cxt.audit_indextbl = (AuditIndexTableNew *)MemoryContextAllocZero( + g_instance.audit_cxt.global_audit_context, (u_sess->attr.attr_security.Audit_RemainThreshold + 1) * sizeof(AuditIndexItem) + indextbl_header_size); g_instance.audit_cxt.audit_indextbl->maxnum = u_sess->attr.attr_security.Audit_RemainThreshold + 1; g_instance.audit_cxt.audit_indextbl->count = 0; /* audit files count will be updated by auditfile_open */ @@ -2417,38 +2617,49 @@ static void pgaudit_indextbl_init_new(void) return; } +/* + * 鍔熻兘锛氭洿鏂板璁$储寮曡〃鐨勬渶澶у閲忓拰鏁版嵁 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庢洿鏂板璁$储寮曡〃鐨勬渶澶у閲忓拰鏁版嵁銆傞鍏堬紝瀹冩牴鎹厤缃弬鏁拌绠楁柊鐨勭储寮曡〃鐨勫閲忥紝 + * 鐒跺悗涓烘柊绱㈠紩琛ㄥ垎閰嶅唴瀛橈紝骞跺皢鏃х储寮曡〃涓殑鏁版嵁澶嶅埗鍒版柊绱㈠紩琛ㄤ腑銆 + * 鏈鍚庯紝鍑芥暟閲婃斁鏃х储寮曡〃鐨勫唴瀛橈紝灏嗘柊绱㈠紩琛ㄨ缃负鍏ㄥ眬瀹¤涓婁笅鏂囩殑褰撳墠绱㈠紩琛ㄣ + */ static void pgaudit_update_maxnum() { errno_t errorno = EOK; int thread_num = g_instance.attr.attr_security.audit_thread_num; + // 璁$畻鏂扮储寮曡〃鐨勬暟鎹暱搴 int new_indextbl_data_lenth = (u_sess->attr.attr_security.Audit_RemainThreshold + 1) * sizeof(AuditIndexItem); + + // 鍒嗛厤鍐呭瓨浠ュ瓨鍌ㄦ柊鐨勫璁$储寮曡〃鏁版嵁 AuditIndexTableNew *new_indextbl = (AuditIndexTableNew *)MemoryContextAllocZero( g_instance.audit_cxt.global_audit_context, new_indextbl_data_lenth + indextbl_header_size); - /* curidx and latest_idx should be updated later from old index table file */ + // 璁剧疆鏂扮储寮曡〃鐨勫睘鎬 new_indextbl->begidx = 0; new_indextbl->maxnum = u_sess->attr.attr_security.Audit_RemainThreshold + 1; new_indextbl->last_audit_time = g_instance.audit_cxt.audit_indextbl->last_audit_time; new_indextbl->thread_num = g_instance.audit_cxt.audit_indextbl->thread_num; + // 濡傛灉鏃х储寮曡〃涓湁鏁版嵁锛屽垯灏嗗叾澶嶅埗鍒版柊绱㈠紩琛ㄤ腑 if (g_instance.audit_cxt.audit_indextbl->count > 0) { AuditIndexItem *item = NULL; uint32 latest_idx = g_instance.audit_cxt.audit_indextbl->latest_idx; - uint32 last_idx = (latest_idx == 0) ? (g_instance.audit_cxt.audit_indextbl->maxnum - 1): (latest_idx - 1); + uint32 last_idx = (latest_idx == 0) ? (g_instance.audit_cxt.audit_indextbl->maxnum - 1) : (latest_idx - 1); uint32 index = g_instance.audit_cxt.audit_indextbl->begidx; uint32 pos = new_indextbl->begidx; + do { + // 澶嶅埗鏃х储寮曡〃涓殑鏁版嵁鍒版柊绱㈠紩琛 item = g_instance.audit_cxt.audit_indextbl->data + index; errorno = memcpy_s(new_indextbl->data + pos, (new_indextbl_data_lenth - (pos * sizeof(AuditIndexItem))), item, sizeof(AuditIndexItem)); securec_check(errorno, "\0", "\0"); new_indextbl->count++; - /* - * finished copy old index table file from range [begin, latest_idx) - * then update new index table file curidxes - */ + // 濡傛灉宸插鍒跺埌鏈鍚庝竴涓储寮曪紝鍒欒缃浉鍏冲睘鎬у苟閫鍑哄惊鐜 if (index == last_idx) { for (int i = 0; i < thread_num; ++i) { new_indextbl->curidx[i] = pos - thread_num + 1 + i; @@ -2461,6 +2672,8 @@ static void pgaudit_update_maxnum() index = (index + 1) % g_instance.audit_cxt.audit_indextbl->maxnum; } while (true); } + + // 閲婃斁鏃х储寮曡〃鐨勫唴瀛橈紝骞跺皢鏂扮储寮曡〃璁剧疆涓哄綋鍓嶇储寮曡〃 pfree(g_instance.audit_cxt.audit_indextbl); g_instance.audit_cxt.audit_indextbl = new_indextbl; } @@ -2478,8 +2691,8 @@ static void pgaudit_reset_indexfile() uint32 old_maxnum = g_instance.audit_cxt.audit_indextbl->maxnum; if (old_maxnum > (uint32)u_sess->attr.attr_security.Audit_RemainThreshold + 1) { int rc = snprintf_s(t_thrd.audit.pgaudit_filepath, MAXPGPATH, MAXPGPATH - 1, "%s/%s", - g_instance.attr.attr_security.Audit_directory, audit_indextbl_file); - securec_check_intval(rc,,); + g_instance.attr.attr_security.Audit_directory, audit_indextbl_file); + securec_check_intval(rc, , ); if (unlink(t_thrd.audit.pgaudit_filepath) < 0) ereport(WARNING, (errmsg("could not remove audit index table file: %m"))); @@ -2502,12 +2715,12 @@ static void pgaudit_reset_indexfile() * Brief : get the specified string field. * Description : */ -static const char* pgaudit_string_field(AuditData* adata, int num) +static const char *pgaudit_string_field(AuditData *adata, int num) { int index = 0; uint32 size = 0; uint32 datalen = 0; - const char* field = NULL; + const char *field = NULL; if (adata == NULL) return NULL; @@ -2539,11 +2752,33 @@ static const char* pgaudit_string_field(AuditData* adata, int num) return field; } -static char* serialize_event_to_json(AuditData *adata, long long eventTime) +/* + * 鍔熻兘锛氬皢 AuditData 缁撴瀯浣撳拰浜嬩欢鏃堕棿搴忓垪鍖栦负 JSON 鏍煎紡鐨勫瓧绗︿覆 + * + * 鍙傛暟锛 + * adata锛氭寚鍚 AuditData 缁撴瀯浣撶殑鎸囬拡锛屽寘鍚搴忓垪鍖栫殑瀹¤鏁版嵁 + * eventTime锛氫簨浠舵椂闂寸殑鏃堕棿鎴 + * + * 杩斿洖鍊硷細 + * 杩斿洖鎸囧悜 JSON 鏍煎紡瀛楃涓茬殑鎸囬拡锛堥渶瑕佹墜鍔ㄩ噴鏀惧唴瀛橈級 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庡皢 AuditData 缁撴瀯浣撳拰浜嬩欢鏃堕棿搴忓垪鍖栦负 JSON 鏍煎紡鐨勫瓧绗︿覆銆 + * 鍑芥暟棣栧厛鍒涘缓涓涓 AuditElasticEvent 缁撴瀯浣擄紝鐒跺悗璋冪敤 WRITE_JSON_START 瀹忓紑濮 JSON 瀛楃涓茬殑鏋勫缓銆 + * 鎺ヤ笅鏉ワ紝鍑芥暟灏 AuditData 缁撴瀯浣撲腑鐨勫悇涓瓧娈典互鍙婁簨浠舵椂闂村~鍏呭埌 AuditElasticEvent 缁撴瀯浣撶殑鐩稿簲瀛楁涓紝 + * 骞朵娇鐢 WRITE_JSON_STRING銆乄RITE_JSON_INT 绛夊畯鏉ュ皢瀹冧滑搴忓垪鍖栧埌 JSON 瀛楃涓蹭腑銆 + * 鏈鍚庯紝鍑芥暟閫氳繃 WRITE_JSON_END 瀹忕粨鏉 JSON 瀛楃涓茬殑鏋勫缓銆 + * 杩斿洖鐨 JSON 鏍煎紡瀛楃涓查渶瑕佹墜鍔ㄩ噴鏀惧唴瀛樹互閬垮厤鍐呭瓨娉勬紡銆 + */ +static char *serialize_event_to_json(AuditData *adata, long long eventTime) { + // 鍒涘缓 AuditElasticEvent 缁撴瀯浣 AuditElasticEvent event; + + // 寮濮嬫瀯寤 JSON 瀛楃涓 WRITE_JSON_START(AuditElasticEvent, &event); + // 濉厖 AuditElasticEvent 缁撴瀯浣撶殑鍚勪釜瀛楁 event.aDataType = AuditTypeDesc(adata->type); WRITE_JSON_STRING(aDataType); event.aDataResult = AuditResultDesc(adata->result); @@ -2570,26 +2805,65 @@ static char* serialize_event_to_json(AuditData *adata, long long eventTime) WRITE_JSON_STRING(remotePortInfo); event.eventTime = eventTime; WRITE_JSON_INT(eventTime); + + // 缁撴潫 JSON 瀛楃涓茬殑鏋勫缓 WRITE_JSON_END(); + + // 杩斿洖 JSON 鏍煎紡瀛楃涓茬殑鎸囬拡锛岄渶瑕佹墜鍔ㄩ噴鏀惧唴瀛 + return json_result; } struct AuditElasticIndex { - const char* _index; - const char* _type; + const char *_index; + const char *_type; }; -char* serialize_index_to_json(const char* audit_str) +/* + * 鍔熻兘锛氬皢 AuditElasticIndex 缁撴瀯浣撳簭鍒楀寲涓 JSON 鏍煎紡鐨勫瓧绗︿覆 + * + * 鍙傛暟锛 + * audit_str锛氱敤浜庡~鍏 AuditElasticIndex 缁撴瀯浣撶殑瀛楃涓 + * + * 杩斿洖鍊硷細 + * 杩斿洖鎸囧悜 JSON 鏍煎紡瀛楃涓茬殑鎸囬拡锛堥渶瑕佹墜鍔ㄩ噴鏀惧唴瀛橈級 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庡皢 AuditElasticIndex 缁撴瀯浣撳簭鍒楀寲涓 JSON 鏍煎紡鐨勫瓧绗︿覆銆 + * AuditElasticIndex 缁撴瀯浣撲腑鍖呭惈涓や釜瀛楃涓插瓧娈 _index 鍜 _type锛岃繖涓や釜瀛楁浼氳濉厖涓轰紶鍏ョ殑 audit_str 瀛楃涓层 + * 鍑芥暟棣栧厛璋冪敤 WRITE_JSON_START 瀹忓紑濮 JSON 瀛楃涓茬殑鏋勫缓锛岀劧鍚庡垎鍒~鍏 _index 鍜 _type 瀛楁锛 + * 鏈鍚庨氳繃 WRITE_JSON_END 瀹忕粨鏉 JSON 瀛楃涓茬殑鏋勫缓銆 + * 杩斿洖鐨 JSON 鏍煎紡瀛楃涓查渶瑕佹墜鍔ㄩ噴鏀惧唴瀛樹互閬垮厤鍐呭瓨娉勬紡銆 + */ +char *serialize_index_to_json(const char *audit_str) { + // 鍒涘缓 AuditElasticIndex 缁撴瀯浣 AuditElasticIndex index; + // 寮濮嬫瀯寤 JSON 瀛楃涓 WRITE_JSON_START(AuditElasticIndex, &index); + // 濉厖 _index 鍜 _type 瀛楁 index._index = audit_str; WRITE_JSON_STRING(_index); index._type = audit_str; WRITE_JSON_STRING(_type); + // 缁撴潫 JSON 瀛楃涓茬殑鏋勫缓 WRITE_JSON_END(); + // 杩斿洖 JSON 鏍煎紡瀛楃涓茬殑鎸囬拡锛岄渶瑕佹墜鍔ㄩ噴鏀惧唴瀛 + return json_result; } -void fix_json(char* json) +/* + * 鍔熻兘锛氫慨澶嶅寘鍚崲琛岀鐨 JSON 瀛楃涓 + * + * 鍙傛暟锛 + * json锛氶渶瑕佷慨澶嶇殑 JSON 瀛楃涓诧紙浼犲叆鍙傛暟浼氳淇敼锛 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庝慨澶嶅寘鍚崲琛岀鐨 JSON 瀛楃涓诧紝灏嗘崲琛岀鏇挎崲涓虹┖鏍硷紝浠ヤ究鏇村鏄撳鐞嗐 + * 鍑芥暟浼氶亶鍘嗗瓧绗︿覆涓殑姣忎釜瀛楃锛屽鏋滃瓧绗︿负鎹㈣绗 '\n'锛屽垯灏嗗叾鏇挎崲涓虹┖鏍 ' '銆 + * 濡傛灉瀛楃涓哄瓧绗︿覆缁堟绗 '\0'锛屽垯浼氭彁鍓嶇粨鏉熷惊鐜紝浠ラ伩鍏嶅鐞嗗瓧绗︿覆鐨勫悗缁儴鍒嗐 + * 璇锋敞鎰忥紝浼犲叆鍙傛暟鐨勫唴瀹逛細琚慨鏀癸紝鍥犳璋冪敤鍑芥暟鍓嶈纭繚宸插浠藉師濮嬫暟鎹垨涓嶉渶瑕佷繚鐣欏師濮嬫暟鎹 + */ +void fix_json(char *json) { for (int i = 0; i < (int)strlen(json); i++) { if (json[i] == '\n') { @@ -2608,46 +2882,43 @@ static void pgaudit_query_file_for_elastic() int rc; char file_path[MAXPGPATH] = {0}; rc = snprintf_s(file_path, sizeof(file_path), sizeof(file_path) - 1, "%s" DIR_SEP "done", - g_instance.attr.attr_security.Audit_directory); + g_instance.attr.attr_security.Audit_directory); securec_check_ss(rc, "\0", "\0"); std::vector done_files; get_files_list(file_path, done_files, ".bin", MAX_QUEUE_SIZE); while (!done_files.empty()) { - for (const std::string& file_item : done_files) { + for (const std::string &file_item : done_files) { rc = snprintf_s(file_path, sizeof(file_path), sizeof(file_path) - 1, "%s" DIR_SEP "done" DIR_SEP "%s", - g_instance.attr.attr_security.Audit_directory, file_item.c_str()); + g_instance.attr.attr_security.Audit_directory, file_item.c_str()); securec_check_ss(rc, "\0", "\0"); /* Open the audit file to scan the audit record. */ - FILE* fp = AllocateFile(file_path, PG_BINARY_R); + FILE *fp = AllocateFile(file_path, PG_BINARY_R); if (fp == NULL) { ereport(WARNING, - (errcode_for_file_access(), errmsg("could not open audit file \"%s\": %m", file_path))); + (errcode_for_file_access(), errmsg("could not open audit file \"%s\": %m", file_path))); continue; } - FILE* bulkfile = fopen("audit_bulk.json", "w"); // , "a"); + FILE *bulkfile = fopen("audit_bulk.json", "w"); // , "a"); int event_count = 0; do { errno_t errorno = EOK; /* read the audit message header first */ - int nread = fread((char*)&header, sizeof(AuditMsgHdr), 1, fp); + int nread = fread((char *)&header, sizeof(AuditMsgHdr), 1, fp); if (nread == 0) { break; } - if (header.signature[0] != 'A' || - header.signature[1] != 'U' || - header.version != 0 || - header.fields != PGAUDIT_QUERY_COLS || - (header.size <= sizeof(AuditMsgHdr))) { - ereport(LOG, (errmsg("invalid data in audit file \"%s\"", file_path))); + if (header.signature[0] != 'A' || header.signature[1] != 'U' || header.version != 0 || + header.fields != PGAUDIT_QUERY_COLS || (header.size <= sizeof(AuditMsgHdr))) { + ereport(LOG, (errmsg("invalid data in audit file \"%s\"", file_path))); break; } /* read the whole audit record */ adata = (AuditData *)palloc(header.size); errorno = memcpy_s(adata, header.size, &header, sizeof(AuditMsgHdr)); securec_check(errorno, "\0", "\0"); - nread = fread((char*)adata + sizeof(AuditMsgHdr), header.size - sizeof(AuditMsgHdr), 1, fp); + nread = fread((char *)adata + sizeof(AuditMsgHdr), header.size - sizeof(AuditMsgHdr), 1, fp); if (nread != 1) { ereport(WARNING, (errcode_for_file_access(), errmsg("could not read audit file \"%s\": %m", file_path))); @@ -2655,11 +2926,11 @@ static void pgaudit_query_file_for_elastic() break; } - char* json = serialize_event_to_json(adata, adata->header.time); + char *json = serialize_event_to_json(adata, adata->header.time); ereport(DEBUG1, (errmsg("++++++++++++++++++++++++++ Write to JSON adata->type = %d(%s)", adata->type, - AuditTypeDesc(adata->type)))); + AuditTypeDesc(adata->type)))); fix_json(json); - const char* indexType = "audit"; + const char *indexType = "audit"; switch (adata->type) { case AUDIT_POLICY_EVENT: indexType = "audit_policy"; @@ -2673,7 +2944,7 @@ static void pgaudit_query_file_for_elastic() default: break; } - char* jsonIndex = serialize_index_to_json(indexType); + char *jsonIndex = serialize_index_to_json(indexType); fix_json(jsonIndex); /* And append a separator */ @@ -2700,13 +2971,13 @@ static void pgaudit_query_file_for_elastic() * --data-binary @audit_bulk.json curl -XPOST -k https://ip:9200/audit/events/_bulk?pretty -H * 'Content-type: application/json' --data-binary @audit_bulk.json */ - std::string url = ((std::string) g_instance.attr.attr_security.elastic_search_ip_addr) + + std::string url = ((std::string)g_instance.attr.attr_security.elastic_search_ip_addr) + ((std::string) ":9200/audit/events/_bulk?pretty"); m_curlUtils.http_post_file_request(url, "audit_bulk.json"); } } rc = snprintf_s(file_path, sizeof(file_path), sizeof(file_path) - 1, "%s" DIR_SEP "done", - g_instance.attr.attr_security.Audit_directory); + g_instance.attr.attr_security.Audit_directory); securec_check_ss(rc, "\0", "\0"); done_files.clear(); get_files_list(file_path, done_files, ".bin", MAX_QUEUE_SIZE); @@ -2716,12 +2987,10 @@ static void pgaudit_query_file_for_elastic() /* * Brief : scan the specified audit file into tuple * Description : Note we use old/new version to differ whether there is user_id field in the file. - * for expanding new field later, maybe we will depend on version id to implement + * for expanding new field later, maybe we will depend on version id to implement * backward compatibility but not bool variable */ -static void deserialization_to_tuple(Datum (&values)[PGAUDIT_QUERY_COLS], - AuditData *adata, - const AuditMsgHdr &header) +static void deserialization_to_tuple(Datum (&values)[PGAUDIT_QUERY_COLS], AuditData *adata, const AuditMsgHdr &header) { /* append timestamp info to data tuple */ int i = 0; @@ -2734,7 +3003,7 @@ static void deserialization_to_tuple(Datum (&values)[PGAUDIT_QUERY_COLS], * the older audit file do not have userid info, so let it to be null */ int index_field = 0; - const char* field = NULL; + const char *field = NULL; bool new_version = (header.fields == PGAUDIT_QUERY_COLS); field = new_version ? pgaudit_string_field(adata, index_field++) : NULL; values[i++] = CStringGetTextDatum(FILED_NULLABLE(field)); /* user id */ @@ -2760,75 +3029,96 @@ static void deserialization_to_tuple(Datum (&values)[PGAUDIT_QUERY_COLS], Assert(i == PGAUDIT_QUERY_COLS); } +/* + * 鍔熻兘锛氫粠瀹¤鏂囦欢涓煡璇㈡暟鎹苟灏嗗叾鏀惧叆鍏冪粍瀛樺偍鍣 + * + * 鍙傛暟锛 + * state锛歍uplestorestate 鍏冪粍瀛樺偍鍣ㄧ殑鐘舵 + * tdesc锛歍upleDesc 鍏冪粍鐨勬弿杩扮 + * fnum锛氬璁℃枃浠剁殑缂栧彿 + * begtime锛氭煡璇㈢殑寮濮嬫椂闂 + * endtime锛氭煡璇㈢殑缁撴潫鏃堕棿 + * audit_directory锛氬璁℃枃浠剁殑瀛樺偍鐩綍 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁颁粠瀹¤鏂囦欢涓鍙栨暟鎹紝灏嗘弧瓒虫椂闂磋寖鍥存潯浠剁殑鏁版嵁鏀惧叆鍏冪粍瀛樺偍鍣ㄤ腑銆 + * 棣栧厛锛屽嚱鏁版瀯寤哄璁℃枃浠剁殑瀹屾暣璺緞锛屽苟灏濊瘯鎵撳紑鏂囦欢銆 + * 濡傛灉鏂囦欢鏃犳硶鎵撳紑锛屽垯璁板綍閿欒娑堟伅骞惰繑鍥炪 + * 鐒跺悗锛屽嚱鏁板惊鐜鍙栨枃浠朵腑鐨勬瘡涓璁℃秷鎭紝妫鏌ユ秷鎭殑鏃堕棿鎴虫槸鍚﹀湪鎸囧畾鐨勬椂闂磋寖鍥村唴锛 + * 濡傛灉婊¤冻鏉′欢锛屽垯灏嗘秷鎭殑鏁版嵁鍙嶅簭鍒楀寲涓哄厓缁勫苟娣诲姞鍒板厓缁勫瓨鍌ㄥ櫒涓 + * 鏈鍚庯紝鍑芥暟鍏抽棴鏂囦欢骞堕噴鏀剧浉鍏冲唴瀛樸 + */ static void pgaudit_query_file(Tuplestorestate *state, TupleDesc tdesc, uint32 fnum, TimestampTz begtime, TimestampTz endtime, const char *audit_directory) { - FILE* fp = NULL; + FILE *fp = NULL; size_t nread = 0; TimestampTz datetime; AuditMsgHdr header; - AuditData* adata = NULL; + AuditData *adata = NULL; + // 妫鏌ヨ緭鍏ュ弬鏁版槸鍚︿负NULL if (state == NULL || tdesc == NULL) return; + // 鏋勫缓瀹¤鏂囦欢鐨勫畬鏁磋矾寰勫苟灏濊瘯鎵撳紑鏂囦欢 int rcs = snprintf_s(t_thrd.audit.pgaudit_filepath, MAXPGPATH, MAXPGPATH - 1, pgaudit_filename, audit_directory, fnum); - securec_check_intval(rcs,,); - /* Open the audit file to scan the audit record. */ + securec_check_intval(rcs, , ); fp = AllocateFile(t_thrd.audit.pgaudit_filepath, PG_BINARY_R); if (fp == NULL) { - ereport(LOG, - (errcode_for_file_access(), errmsg("could not open audit file \"%s\": %m", t_thrd.audit.pgaudit_filepath))); + ereport(LOG, (errcode_for_file_access(), + errmsg("could not open audit file \"%s\": %m", t_thrd.audit.pgaudit_filepath))); return; } + // 寰幆璇诲彇瀹¤鏂囦欢涓殑姣忎釜娑堟伅 do { Datum values[PGAUDIT_QUERY_COLS] = {0}; bool nulls[PGAUDIT_QUERY_COLS] = {0}; errno_t errorno = EOK; - /* - * two scenarios tell that the audit file corrupt - * 1. fail to parse the header length - * 2. header encoding is not valid - */ + + // 妫鏌ユ枃浠舵槸鍚﹀凡缁忕粨鏉 if (fgetc(fp) == EOF) { break; } (void)fseek(fp, -1, SEEK_CUR); + + // 璇诲彇娑堟伅澶 size_t header_available = fread(&header, sizeof(AuditMsgHdr), 1, fp); if (header_available != 1 || !pgaudit_valid_header(&header)) { ereport(LOG, (errmsg("invalid data in audit file \"%s\"", t_thrd.audit.pgaudit_filepath))); - /* label the currupt file num, then it may be reinit in audit thread but not here. */ pgaudit_mark_corrupt_info(fnum); break; } - /* read the whole audit record */ - adata = (AuditData*)palloc(header.size); + // 鍒嗛厤鍐呭瓨骞惰鍙栧畬鏁存秷鎭 + adata = (AuditData *)palloc(header.size); errorno = memcpy_s(adata, header.size, &header, sizeof(AuditMsgHdr)); securec_check(errorno, "\0", "\0"); - nread = fread((char*)adata + sizeof(AuditMsgHdr), header.size - sizeof(AuditMsgHdr), 1, fp); + nread = fread((char *)adata + sizeof(AuditMsgHdr), header.size - sizeof(AuditMsgHdr), 1, fp); if (nread != 1) { - ereport(LOG, - (errcode_for_file_access(), - errmsg("could not read audit file \"%s\": %m", t_thrd.audit.pgaudit_filepath))); - /* label the currupt file num, then it may be reinit in audit thread but not here. */ + ereport(LOG, (errcode_for_file_access(), + errmsg("could not read audit file \"%s\": %m", t_thrd.audit.pgaudit_filepath))); pgaudit_mark_corrupt_info(fnum); pfree(adata); break; } - /* filt and assemble audit info into tuplestore */ + // 灏嗘椂闂存埑杞崲涓烘椂闂寸被鍨 datetime = time_t_to_timestamptz(adata->header.time); + + // 濡傛灉娑堟伅鐨勬椂闂村湪鎸囧畾鐨勬椂闂磋寖鍥村唴锛屽苟涓旀秷鎭爣蹇椾负AUDIT_TUPLE_NORMAL锛屽垯灏嗘秷鎭弽搴忓垪鍖栦负鍏冪粍骞舵坊鍔犲埌鍏冪粍瀛樺偍鍣ㄤ腑 if (datetime >= begtime && datetime < endtime && header.flags == AUDIT_TUPLE_NORMAL) { deserialization_to_tuple(values, adata, header); tuplestore_putvalues(state, tdesc, values, nulls); } + // 閲婃斁鍐呭瓨 pfree(adata); } while (true); + // 鍏抽棴鏂囦欢骞堕噴鏀惧唴瀛 pgaudit_close_file(fp, t_thrd.audit.pgaudit_filepath); } @@ -2843,19 +3133,15 @@ static void pgaudit_delete_file(uint32 fnum, TimestampTz begtime, TimestampTz en TimestampTz datetime; AuditMsgHdr header; - int rc = snprintf_s(t_thrd.audit.pgaudit_filepath, - MAXPGPATH, - MAXPGPATH - 1, - pgaudit_filename, - g_instance.attr.attr_security.Audit_directory, - fnum); - securec_check_intval(rc,,); + int rc = snprintf_s(t_thrd.audit.pgaudit_filepath, MAXPGPATH, MAXPGPATH - 1, pgaudit_filename, + g_instance.attr.attr_security.Audit_directory, fnum); + securec_check_intval(rc, , ); /* Open the audit file to scan the audit record. */ fd = open(t_thrd.audit.pgaudit_filepath, O_RDWR, pgaudit_filemode); if (fd < 0) { - ereport(LOG, - (errcode_for_file_access(), errmsg("could not open audit file \"%s\": %m", t_thrd.audit.pgaudit_filepath))); + ereport(LOG, (errcode_for_file_access(), + errmsg("could not open audit file \"%s\": %m", t_thrd.audit.pgaudit_filepath))); return; } @@ -2865,11 +3151,8 @@ static void pgaudit_delete_file(uint32 fnum, TimestampTz begtime, TimestampTz en if (nread <= 0) break; - if (header.signature[0] != 'A' || - header.signature[1] != 'U' || - header.version != 0 || - !(header.fields == (PGAUDIT_QUERY_COLS - 1) || - header.fields == PGAUDIT_QUERY_COLS)) { + if (header.signature[0] != 'A' || header.signature[1] != 'U' || header.version != 0 || + !(header.fields == (PGAUDIT_QUERY_COLS - 1) || header.fields == PGAUDIT_QUERY_COLS)) { /* make sure we are compatible with the older version audit file */ ereport(LOG, (errmsg("invalid data in audit file \"%s\"", t_thrd.audit.pgaudit_filepath))); break; @@ -2903,7 +3186,7 @@ static bool pgaudit_check_system(TimestampTz begtime, TimestampTz endtime, uint3 bool satisfied = false; TimestampTz curr_filetime = 0; TimestampTz next_filetime = 0; - AuditIndexItem* item = t_thrd.audit.audit_indextbl->data + index; + AuditIndexItem *item = t_thrd.audit.audit_indextbl->data + index; uint32 earliest_idx = t_thrd.audit.audit_indextbl->latest_idx - g_instance.audit_cxt.thread_num; if (item->ctime > 0) { @@ -2976,14 +3259,14 @@ static void pgaudit_query_valid_check(const ReturnSetInfo *rsinfo, FunctionCallI */ Datum pg_query_audit(PG_FUNCTION_ARGS) { - ReturnSetInfo* rsinfo = (ReturnSetInfo*)fcinfo->resultinfo; + ReturnSetInfo *rsinfo = (ReturnSetInfo *)fcinfo->resultinfo; TupleDesc tupdesc = NULL; - Tuplestorestate* tupstore = NULL; + Tuplestorestate *tupstore = NULL; MemoryContext per_query_ctx = NULL; MemoryContext oldcontext = NULL; TimestampTz begtime = PG_GETARG_TIMESTAMPTZ(0); TimestampTz endtime = PG_GETARG_TIMESTAMPTZ(1); - char* audit_dir = NULL; + char *audit_dir = NULL; pgaudit_query_valid_check(rsinfo, fcinfo, tupdesc); @@ -3027,7 +3310,7 @@ Datum pg_query_audit(PG_FUNCTION_ARGS) bool satisfied = false; uint32 index = 0; uint32 fnum = 0; - AuditIndexItem* item = NULL; + AuditIndexItem *item = NULL; index = t_thrd.audit.audit_indextbl->begidx; do { @@ -3073,7 +3356,7 @@ Datum pg_delete_audit(PG_FUNCTION_ARGS) ereport(ERROR, (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), errmsg("permission denied to delete audit"))); } - /* + /* * load the index audit table from global index audit table instance * then use the local thread one when iterate all audit files */ @@ -3095,7 +3378,7 @@ Datum pg_delete_audit(PG_FUNCTION_ARGS) bool satisfied = false; uint32 index; uint32 fnum; - AuditIndexItem* item = NULL; + AuditIndexItem *item = NULL; index = t_thrd.audit.audit_indextbl->begidx; do { @@ -3121,8 +3404,8 @@ Datum pg_delete_audit(PG_FUNCTION_ARGS) PG_RETURN_VOID(); } -/* - * if use_elastic_search is set on, user should make sure connection is ok, +/* + * if use_elastic_search is set on, user should make sure connection is ok, * or process will not start successfully */ static void elasic_search_connection_test() @@ -3130,12 +3413,12 @@ static void elasic_search_connection_test() if (!g_instance.attr.attr_security.use_elastic_search) { return; } - std::string url = ((std::string) g_instance.attr.attr_security.elastic_search_ip_addr) + + std::string url = ((std::string)g_instance.attr.attr_security.elastic_search_ip_addr) + ((std::string) ":9200/audit/events/_bulk?pretty"); (void)m_curlUtils.http_post_file_request(url, "", true); } -/* +/* * check and reinit the audit files * 1. whether the audit file is exist * 2. recognize the corrupt file @@ -3181,7 +3464,7 @@ static void CheckAuditFile(void) int fd = open(t_thrd.audit.pgaudit_filepath, O_RDWR | O_TRUNC, pgaudit_filemode); if (fd < 0) { ereport(ERROR, (errcode_for_file_access(), - errmsg("could not truncate audit file \"%s\": %m", t_thrd.audit.pgaudit_filepath))); + errmsg("could not truncate audit file \"%s\": %m", t_thrd.audit.pgaudit_filepath))); } else { close(fd); } @@ -3202,11 +3485,11 @@ static void CheckAuditFile(void) auditfile_init(true); } -static bool pgaudit_valid_header(const AuditMsgHdr* header) +static bool pgaudit_valid_header(const AuditMsgHdr *header) { return !((header->signature[0]) != 'A' || header->signature[1] != 'U' || header->version != 0 || - !(header->fields == (PGAUDIT_QUERY_COLS - 1) || header->fields == PGAUDIT_QUERY_COLS) || - (header->size <= sizeof(AuditMsgHdr))); + !(header->fields == (PGAUDIT_QUERY_COLS - 1) || header->fields == PGAUDIT_QUERY_COLS) || + (header->size <= sizeof(AuditMsgHdr))); } /* @@ -3244,7 +3527,7 @@ static void pgaudit_mark_corrupt_info(uint32 fnum) } ereport(WARNING, (errmsg("audit file num %d is corrupted.", fnum))); - + /* * if any other thread have updated the audit_fnum or fnum is older one, do nothing but break here */ @@ -3357,7 +3640,7 @@ void audit_process_cxt_init() /* init audit path */ char Audit_directory_Done[MAXPGPATH] = {0}; int rc = snprintf_s(Audit_directory_Done, sizeof(Audit_directory_Done), sizeof(Audit_directory_Done) - 1, "%s/done", - g_instance.attr.attr_security.Audit_directory); + g_instance.attr.attr_security.Audit_directory); securec_check_ss(rc, "\0", "\0"); (void)pg_mkdir_p(g_instance.attr.attr_security.Audit_directory, S_IRWXU); (void)pg_mkdir_p(Audit_directory_Done, S_IRWXU); @@ -3463,7 +3746,7 @@ void pgaudit_switch_next_auditfile() LWLockRelease(g_instance.audit_cxt.index_file_lock); ereport(DEBUG1, (errmsg("pgaudit_switch_next_auditfile new fnum :%d cur pgaudit_totalspace: %ld MB", new_fnum, - g_instance.audit_cxt.pgaudit_totalspace))); + g_instance.audit_cxt.pgaudit_totalspace))); } /* diff --git a/src/gausskernel/process/postmaster/pgstat.cpp b/src/gausskernel/process/postmaster/pgstat.cpp index 79d69bdb9..a0151eaf5 100644 --- a/src/gausskernel/process/postmaster/pgstat.cpp +++ b/src/gausskernel/process/postmaster/pgstat.cpp @@ -150,7 +150,7 @@ #define ThreadSiblingFile "/sys/devices/system/cpu/cpu0/topology/thread_siblings" #define CoreSiblingFile "/sys/devices/system/cpu/cpu0/topology/core_siblings" -extern void WLMGetCPUDataIndicator(PgBackendStatus*, WLMDataIndicator*); +extern void WLMGetCPUDataIndicator(PgBackendStatus *, WLMDataIndicator *); /* * Structures in which backends store per-table info that's waiting to be @@ -166,7 +166,7 @@ extern void WLMGetCPUDataIndicator(PgBackendStatus*, WLMDataIndicator*); #define TABSTAT_QUANTUM 100 /* we alloc this many at a time */ typedef struct TabStatusArray { - struct TabStatusArray* tsa_next; /* link to next array, if any */ + struct TabStatusArray *tsa_next; /* link to next array, if any */ int tsa_used; /* # entries currently used */ PgStat_TableStatus tsa_entries[TABSTAT_QUANTUM]; /* per-table data */ } TabStatusArray; @@ -174,7 +174,7 @@ typedef struct TabStatusArray { /* pgStatTabHash entry */ typedef struct TabStatHashEntry { PgStat_StatTabKey t_key; - PgStat_TableStatus* tsa_entry; + PgStat_TableStatus *tsa_entry; } TabStatHashEntry; /* @@ -186,15 +186,15 @@ typedef struct TabStatHashEntry { */ typedef struct PgStat_SubXactStatus { int nest_level; /* subtransaction nest level */ - struct PgStat_SubXactStatus* prev; /* higher-level subxact if any */ - PgStat_TableXactStatus* first; /* head of list for this subxact */ + struct PgStat_SubXactStatus *prev; /* higher-level subxact if any */ + PgStat_TableXactStatus *first; /* head of list for this subxact */ } PgStat_SubXactStatus; /* Record that's written to 2PC state file when pgstat state is persisted */ typedef struct TwoPhasePgStatRecord { - PgStat_Counter tuples_inserted; /* tuples inserted in xact */ - PgStat_Counter tuples_updated; /* tuples updated in xact */ - PgStat_Counter tuples_deleted; /* tuples deleted in xact */ + PgStat_Counter tuples_inserted; /* tuples inserted in xact */ + PgStat_Counter tuples_updated; /* tuples updated in xact */ + PgStat_Counter tuples_deleted; /* tuples deleted in xact */ PgStat_Counter tuples_inplace_updated; PgStat_Counter inserted_pre_trunc; /* tuples inserted prior to truncate */ PgStat_Counter updated_pre_trunc; /* tuples updated prior to truncate */ @@ -206,9 +206,9 @@ typedef struct TwoPhasePgStatRecord { PgStat_Counter tuples_deleted_accum; PgStat_Counter tuples_inplace_updated_accum; - Oid t_id; /* table's OID */ - bool t_shared; /* is it a shared catalog? */ - bool t_truncated; /* was the relation truncated? */ + Oid t_id; /* table's OID */ + bool t_shared; /* is it a shared catalog? */ + bool t_truncated; /* was the relation truncated? */ /* * if t_id is a parition oid , then t_statFlag is the corresponding * partitioned table oid; if t_id is a non-parition oid, then t_statFlag is InvlaidOId @@ -224,124 +224,73 @@ const OSRunInfoDesc osStatDescArrayOrg[TOTAL_OS_RUN_INFO_TYPES] = { /* cpu numbers */ {Int32GetNumberDatum, "NUM_CPUS", false, false, "Number of CPUs or processors available"}, - {Int32GetNumberDatum, - "NUM_CPU_CORES", - false, - false, - "Number of CPU cores available (includes subcores of multicore CPUs as well as single-core CPUs)"}, + {Int32GetNumberDatum, "NUM_CPU_CORES", false, false, + "Number of CPU cores available (includes subcores of multicore CPUs as well as single-core CPUs)"}, - {Int32GetNumberDatum, - "NUM_CPU_SOCKETS", - false, - false, - "Number of CPU sockets available (represents an absolute count of CPU chips on the system, regardless of " - "multithreading or multi-core architectures)"}, + {Int32GetNumberDatum, "NUM_CPU_SOCKETS", false, false, + "Number of CPU sockets available (represents an absolute count of CPU chips on the system, regardless of " + "multithreading or multi-core architectures)"}, /* cpu times */ - {Int64GetNumberDatum, - "IDLE_TIME", - true, - false, - "Number of hundredths of a second that a processor has been idle, totalled over all processors"}, + {Int64GetNumberDatum, "IDLE_TIME", true, false, + "Number of hundredths of a second that a processor has been idle, totalled over all processors"}, - {Int64GetNumberDatum, - "BUSY_TIME", - true, - false, - "Number of hundredths of a second that a processor has been busy executing user or kernel code, totalled over " - "all processors"}, + {Int64GetNumberDatum, "BUSY_TIME", true, false, + "Number of hundredths of a second that a processor has been busy executing user or kernel code, totalled over " + "all processors"}, - {Int64GetNumberDatum, - "USER_TIME", - true, - false, - "Number of hundredths of a second that a processor has been busy executing user code, totalled over all " - "processors"}, + {Int64GetNumberDatum, "USER_TIME", true, false, + "Number of hundredths of a second that a processor has been busy executing user code, totalled over all " + "processors"}, - {Int64GetNumberDatum, - "SYS_TIME", - true, - false, - "Number of hundredths of a second that a processor has been busy executing kernel code, totalled over all " - "processors"}, + {Int64GetNumberDatum, "SYS_TIME", true, false, + "Number of hundredths of a second that a processor has been busy executing kernel code, totalled over all " + "processors"}, - {Int64GetNumberDatum, - "IOWAIT_TIME", - true, - false, - "Number of hundredths of a second that a processor has been waiting for I/O to complete, totalled over all " - "processors"}, + {Int64GetNumberDatum, "IOWAIT_TIME", true, false, + "Number of hundredths of a second that a processor has been waiting for I/O to complete, totalled over all " + "processors"}, - {Int64GetNumberDatum, - "NICE_TIME", - true, - false, - "Number of hundredths of a second that a processor has been busy executing low-priority user code, totalled " - "over all processors"}, + {Int64GetNumberDatum, "NICE_TIME", true, false, + "Number of hundredths of a second that a processor has been busy executing low-priority user code, totalled " + "over all processors"}, /* avg cpu times */ - {Int64GetNumberDatum, - "AVG_IDLE_TIME", - true, - false, - "Number of hundredths of a second that a processor has been idle, averaged over all processors"}, + {Int64GetNumberDatum, "AVG_IDLE_TIME", true, false, + "Number of hundredths of a second that a processor has been idle, averaged over all processors"}, - {Int64GetNumberDatum, - "AVG_BUSY_TIME", - true, - false, - "Number of hundredths of a second that a processor has been busy executing user or kernel code, averaged over " - "all processors"}, + {Int64GetNumberDatum, "AVG_BUSY_TIME", true, false, + "Number of hundredths of a second that a processor has been busy executing user or kernel code, averaged over " + "all processors"}, - {Int64GetNumberDatum, - "AVG_USER_TIME", - true, - false, - "Number of hundredths of a second that a processor has been busy executing user code, averaged over all " - "processors"}, + {Int64GetNumberDatum, "AVG_USER_TIME", true, false, + "Number of hundredths of a second that a processor has been busy executing user code, averaged over all " + "processors"}, - {Int64GetNumberDatum, - "AVG_SYS_TIME", - true, - false, - "Number of hundredths of a second that a processor has been busy executing kernel code, averaged over all " - "processors"}, + {Int64GetNumberDatum, "AVG_SYS_TIME", true, false, + "Number of hundredths of a second that a processor has been busy executing kernel code, averaged over all " + "processors"}, - {Int64GetNumberDatum, - "AVG_IOWAIT_TIME", - true, - false, - "Number of hundredths of a second that a processor has been waiting for I/O to complete, averaged over all " - "processors"}, + {Int64GetNumberDatum, "AVG_IOWAIT_TIME", true, false, + "Number of hundredths of a second that a processor has been waiting for I/O to complete, averaged over all " + "processors"}, - {Int64GetNumberDatum, - "AVG_NICE_TIME", - true, - false, - "Number of hundredths of a second that a processor has been busy executing low-priority user code, averaged " - "over all processors"}, + {Int64GetNumberDatum, "AVG_NICE_TIME", true, false, + "Number of hundredths of a second that a processor has been busy executing low-priority user code, averaged " + "over all processors"}, /* virtual memory page in/out data */ - {Int64GetNumberDatum, - "VM_PAGE_IN_BYTES", - true, - false, - "Total number of bytes of data that have been paged in due to virtual memory paging"}, + {Int64GetNumberDatum, "VM_PAGE_IN_BYTES", true, false, + "Total number of bytes of data that have been paged in due to virtual memory paging"}, - {Int64GetNumberDatum, - "VM_PAGE_OUT_BYTES", - true, - false, - "Total number of bytes of data that have been paged out due to virtual memory paging"}, + {Int64GetNumberDatum, "VM_PAGE_OUT_BYTES", true, false, + "Total number of bytes of data that have been paged out due to virtual memory paging"}, /* os run load */ - {Float8GetNumberDatum, - "LOAD", - false, - false, - "Current number of processes that are either running or in the ready state, waiting to be selected by the " - "operating-system scheduler to run. On many platforms, this statistic reflects the average load over the past " - "minute."}, + {Float8GetNumberDatum, "LOAD", false, false, + "Current number of processes that are either running or in the ready state, waiting to be selected by the " + "operating-system scheduler to run. On many platforms, this statistic reflects the average load over the past " + "minute."}, /* physical memory size */ {Int64GetNumberDatum, "PHYSICAL_MEMORY_BYTES", false, false, "Total number of bytes of physical memory"}}; @@ -354,57 +303,57 @@ static void pgstat_exit(SIGNAL_ARGS); static void pgstat_beshutdown_hook(int code, Datum arg); static void pgstat_sighup_handler(SIGNAL_ARGS); -static PgStat_StatDBEntry* pgstat_get_db_entry(Oid databaseid, bool create); -static PgStat_StatTabEntry* pgstat_get_tab_entry( - PgStat_StatDBEntry* dbentry, Oid tableoid, bool create, uint32 statFlag); +static PgStat_StatDBEntry *pgstat_get_db_entry(Oid databaseid, bool create); +static PgStat_StatTabEntry *pgstat_get_tab_entry(PgStat_StatDBEntry *dbentry, Oid tableoid, bool create, + uint32 statFlag); static void pgstat_write_statsfile(bool permanent); -static HTAB* pgstat_read_statsfile(Oid onlydb, bool permanent); +static HTAB *pgstat_read_statsfile(Oid onlydb, bool permanent); static void backend_read_statsfile(void); -static void pgstat_send_tabstat(PgStat_MsgTabstat* tsmsg); +static void pgstat_send_tabstat(PgStat_MsgTabstat *tsmsg); static void pgstat_send_funcstats(void); -static HTAB* pgstat_collect_oids(Oid catalogid); -static HTAB* pgstat_collect_tabkeys(void); -static PgStat_TableStatus* get_tabstat_entry(Oid rel_id, bool isshared, uint32 statFlag); +static HTAB *pgstat_collect_oids(Oid catalogid); +static HTAB *pgstat_collect_tabkeys(void); +static PgStat_TableStatus *get_tabstat_entry(Oid rel_id, bool isshared, uint32 statFlag); static void pgstat_collect_thread_status_setup_memcxt(void); static void pgstat_collect_thread_status_clear_resource(void); -const char* pgstat_get_wait_io(WaitEventIO w); +const char *pgstat_get_wait_io(WaitEventIO w); -static void pgstat_setheader(PgStat_MsgHdr* hdr, StatMsgType mtype); -void pgstat_send(void* msg, int len); +static void pgstat_setheader(PgStat_MsgHdr *hdr, StatMsgType mtype); +void pgstat_send(void *msg, int len); -static void pgstat_recv_inquiry(PgStat_MsgInquiry* msg, int len); -static void pgstat_recv_tabstat(PgStat_MsgTabstat* msg, int len); -static void pgstat_recv_tabpurge(PgStat_MsgTabpurge* msg, int len); -static void pgstat_recv_dropdb(PgStat_MsgDropdb* msg, int len); -static void pgstat_recv_resetcounter(PgStat_MsgResetcounter* msg, int len); -static void pgstat_recv_resetsharedcounter(PgStat_MsgResetsharedcounter* msg, int len); -static void pgstat_recv_resetsinglecounter(PgStat_MsgResetsinglecounter* msg, int len); -static void pgstat_recv_autovac(PgStat_MsgAutovacStart* msg, int len); -static void pgstat_recv_vacuum(PgStat_MsgVacuum* msg, int len); -static void pgstat_recv_data_changed(PgStat_MsgDataChanged* msg, int len); -static void pgstat_recv_truncate(PgStat_MsgTruncate* msg, int len); -static void pgstat_recv_analyze(PgStat_MsgAnalyze* msg, int len); -static void pgstat_recv_bgwriter(PgStat_MsgBgWriter* msg, int len); -static void pgstat_recv_funcstat(PgStat_MsgFuncstat* msg, int len); -static void pgstat_recv_funcpurge(PgStat_MsgFuncpurge* msg, int len); -static void pgstat_recv_recoveryconflict(const PgStat_MsgRecoveryConflict* msg); -static void pgstat_recv_deadlock(const PgStat_MsgDeadlock* msg); -static void pgstat_recv_tempfile(PgStat_MsgTempFile* msg, int len); -static void pgstat_recv_memReserved(const PgStat_MsgMemReserved* msg); -static void pgstat_recv_autovac_stat(PgStat_MsgAutovacStat* msg, int len); -static void PgstatRecvPrunestat(PgStat_MsgPrune* msg, int len); +static void pgstat_recv_inquiry(PgStat_MsgInquiry *msg, int len); +static void pgstat_recv_tabstat(PgStat_MsgTabstat *msg, int len); +static void pgstat_recv_tabpurge(PgStat_MsgTabpurge *msg, int len); +static void pgstat_recv_dropdb(PgStat_MsgDropdb *msg, int len); +static void pgstat_recv_resetcounter(PgStat_MsgResetcounter *msg, int len); +static void pgstat_recv_resetsharedcounter(PgStat_MsgResetsharedcounter *msg, int len); +static void pgstat_recv_resetsinglecounter(PgStat_MsgResetsinglecounter *msg, int len); +static void pgstat_recv_autovac(PgStat_MsgAutovacStart *msg, int len); +static void pgstat_recv_vacuum(PgStat_MsgVacuum *msg, int len); +static void pgstat_recv_data_changed(PgStat_MsgDataChanged *msg, int len); +static void pgstat_recv_truncate(PgStat_MsgTruncate *msg, int len); +static void pgstat_recv_analyze(PgStat_MsgAnalyze *msg, int len); +static void pgstat_recv_bgwriter(PgStat_MsgBgWriter *msg, int len); +static void pgstat_recv_funcstat(PgStat_MsgFuncstat *msg, int len); +static void pgstat_recv_funcpurge(PgStat_MsgFuncpurge *msg, int len); +static void pgstat_recv_recoveryconflict(const PgStat_MsgRecoveryConflict *msg); +static void pgstat_recv_deadlock(const PgStat_MsgDeadlock *msg); +static void pgstat_recv_tempfile(PgStat_MsgTempFile *msg, int len); +static void pgstat_recv_memReserved(const PgStat_MsgMemReserved *msg); +static void pgstat_recv_autovac_stat(PgStat_MsgAutovacStat *msg, int len); +static void PgstatRecvPrunestat(PgStat_MsgPrune *msg, int len); static void pgstat_send_badblock_stat(void); -static void pgstat_recv_badblock_stat(PgStat_MsgBadBlock* msg, int len); +static void pgstat_recv_badblock_stat(PgStat_MsgBadBlock *msg, int len); static bool checkSysFileSystem(void); static bool checkLogicalCpu(uint32 cpuNum); -static uint32 parseSiblingFile(const char* path); -static void pgstat_recv_filestat(PgStat_MsgFile* msg, int len); -static void prepare_calculate(SqlRTInfoArray* sql_rt_info, int* counter); -static void pgstat_recv_sql_responstime(PgStat_SqlRT* msg, int len); +static uint32 parseSiblingFile(const char *path); +static void pgstat_recv_filestat(PgStat_MsgFile *msg, int len); +static void prepare_calculate(SqlRTInfoArray *sql_rt_info, int *counter); +static void pgstat_recv_sql_responstime(PgStat_SqlRT *msg, int len); void initGlobalBadBlockStat(); @@ -417,7 +366,7 @@ static void AttachMySessionTimeEntry(void); static void AttachMySessionMemoryEntry(void); static void endMySessionTimeEntry(int code, Datum arg); -static void DetachMySessionTimeEntry(volatile SessionTimeEntry* pEntry); +static void DetachMySessionTimeEntry(volatile SessionTimeEntry *pEntry); /* ------------------------------------------------------------ * Public functions called from postmaster follow @@ -491,8 +440,8 @@ void pgstat_init(void) #ifdef F_SETFD if (fcntl(g_instance.stat_cxt.pgStatSock, F_SETFD, FD_CLOEXEC) == -1) { - ereport(LOG, - (errcode_for_socket_access(), errmsg("setsockopt(FD_CLOEXEC) failed for statistics collector: %m"))); + ereport(LOG, (errcode_for_socket_access(), + errmsg("setsockopt(FD_CLOEXEC) failed for statistics collector: %m"))); closesocket(g_instance.stat_cxt.pgStatSock); g_instance.stat_cxt.pgStatSock = PGINVALID_SOCKET; continue; @@ -511,9 +460,9 @@ void pgstat_init(void) } alen = sizeof(pgStatAddr); - if (getsockname(g_instance.stat_cxt.pgStatSock, (struct sockaddr*)&pgStatAddr, &alen) < 0) { - ereport(LOG, - (errcode_for_socket_access(), errmsg("could not get address of socket for statistics collector: %m"))); + if (getsockname(g_instance.stat_cxt.pgStatSock, (struct sockaddr *)&pgStatAddr, &alen) < 0) { + ereport(LOG, (errcode_for_socket_access(), + errmsg("could not get address of socket for statistics collector: %m"))); closesocket(g_instance.stat_cxt.pgStatSock); g_instance.stat_cxt.pgStatSock = PGINVALID_SOCKET; continue; @@ -525,9 +474,9 @@ void pgstat_init(void) * provides a kernel-level check that only packets from this same * address will be received. */ - if (connect(g_instance.stat_cxt.pgStatSock, (struct sockaddr*)&pgStatAddr, alen) < 0) { - ereport( - LOG, (errcode_for_socket_access(), errmsg("could not connect socket for statistics collector: %m"))); + if (connect(g_instance.stat_cxt.pgStatSock, (struct sockaddr *)&pgStatAddr, alen) < 0) { + ereport(LOG, + (errcode_for_socket_access(), errmsg("could not connect socket for statistics collector: %m"))); closesocket(g_instance.stat_cxt.pgStatSock); g_instance.stat_cxt.pgStatSock = PGINVALID_SOCKET; continue; @@ -546,9 +495,8 @@ void pgstat_init(void) if (send(g_instance.stat_cxt.pgStatSock, &test_byte, 1, 0) <= 0) { if (errno == EINTR) goto retry1; /* if interrupted, just retry */ - ereport(LOG, - (errcode_for_socket_access(), - errmsg("could not send test message on socket for statistics collector: %m"))); + ereport(LOG, (errcode_for_socket_access(), + errmsg("could not send test message on socket for statistics collector: %m"))); closesocket(g_instance.stat_cxt.pgStatSock); g_instance.stat_cxt.pgStatSock = PGINVALID_SOCKET; continue; @@ -564,7 +512,7 @@ void pgstat_init(void) FD_ZERO(&rset); if (g_instance.stat_cxt.pgStatSock + 1 > FD_SETSIZE) { ereport(ERROR, - (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("fd + 1 cannot be greater than FD_SETSIZE"))); + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("fd + 1 cannot be greater than FD_SETSIZE"))); } FD_SET(g_instance.stat_cxt.pgStatSock, &rset); @@ -587,9 +535,8 @@ void pgstat_init(void) * * errno will not be set meaningfully here, so don't use it. */ - ereport(LOG, - (errcode(ERRCODE_CONNECTION_FAILURE), - errmsg("test message did not get through on socket for statistics collector"))); + ereport(LOG, (errcode(ERRCODE_CONNECTION_FAILURE), + errmsg("test message did not get through on socket for statistics collector"))); closesocket(g_instance.stat_cxt.pgStatSock); g_instance.stat_cxt.pgStatSock = PGINVALID_SOCKET; continue; @@ -602,9 +549,8 @@ void pgstat_init(void) if (recv(g_instance.stat_cxt.pgStatSock, &test_byte, 1, 0) <= 0) { if (errno == EINTR) goto retry2; /* if interrupted, just retry */ - ereport(LOG, - (errcode_for_socket_access(), - errmsg("could not receive test message on socket for statistics collector: %m"))); + ereport(LOG, (errcode_for_socket_access(), + errmsg("could not receive test message on socket for statistics collector: %m"))); closesocket(g_instance.stat_cxt.pgStatSock); g_instance.stat_cxt.pgStatSock = PGINVALID_SOCKET; continue; @@ -612,9 +558,8 @@ void pgstat_init(void) if (test_byte != TESTBYTEVAL) { /* strictly paranoia ... */ - ereport(LOG, - (errcode(ERRCODE_WRONG_OBJECT_TYPE), - errmsg("incorrect test message transmission on socket for statistics collector"))); + ereport(LOG, (errcode(ERRCODE_WRONG_OBJECT_TYPE), + errmsg("incorrect test message transmission on socket for statistics collector"))); closesocket(g_instance.stat_cxt.pgStatSock); g_instance.stat_cxt.pgStatSock = PGINVALID_SOCKET; continue; @@ -634,8 +579,8 @@ void pgstat_init(void) * block waiting to send messages to the collector. */ if (!pg_set_noblock(g_instance.stat_cxt.pgStatSock)) { - ereport(LOG, - (errcode_for_socket_access(), errmsg("could not set statistics collector socket to nonblocking mode: %m"))); + ereport(LOG, (errcode_for_socket_access(), + errmsg("could not set statistics collector socket to nonblocking mode: %m"))); goto startup_failed; } @@ -651,7 +596,7 @@ void pgstat_init(void) int new_rcvbuf; ACCEPT_TYPE_ARG3 rcvbufsize = sizeof(old_rcvbuf); - if (getsockopt(g_instance.stat_cxt.pgStatSock, SOL_SOCKET, SO_RCVBUF, (char*)&old_rcvbuf, &rcvbufsize) < 0) { + if (getsockopt(g_instance.stat_cxt.pgStatSock, SOL_SOCKET, SO_RCVBUF, (char *)&old_rcvbuf, &rcvbufsize) < 0) { elog(LOG, "getsockopt(SO_RCVBUF) failed: %m"); /* if we can't get existing size, always try to set it */ old_rcvbuf = 0; @@ -659,9 +604,8 @@ void pgstat_init(void) new_rcvbuf = PGSTAT_MIN_RCVBUF; if (old_rcvbuf < new_rcvbuf) { - if (setsockopt( - g_instance.stat_cxt.pgStatSock, SOL_SOCKET, SO_RCVBUF, (char*)&new_rcvbuf, sizeof(new_rcvbuf)) < - 0) { + if (setsockopt(g_instance.stat_cxt.pgStatSock, SOL_SOCKET, SO_RCVBUF, (char *)&new_rcvbuf, + sizeof(new_rcvbuf)) < 0) { elog(LOG, "setsockopt(SO_RCVBUF) failed: %m"); } } @@ -700,10 +644,8 @@ startup_failed: */ void pgstat_reset_all(void) { - elog(LOG, - "[Pgstat] remove statfiles in %s, %s", - u_sess->stat_cxt.pgstat_stat_filename, - PGSTAT_STAT_PERMANENT_FILENAME); + elog(LOG, "[Pgstat] remove statfiles in %s, %s", u_sess->stat_cxt.pgstat_stat_filename, + PGSTAT_STAT_PERMANENT_FILENAME); unlink(u_sess->stat_cxt.pgstat_stat_filename); unlink(PGSTAT_STAT_PERMANENT_FILENAME); } @@ -766,8 +708,8 @@ static inline bool pgstat_tablist_too_big(const int len) /* destroy current u_sess->stat_cxt.pgStatTabList and make it be null */ static void pgstat_free_tablist(void) { - TabStatusArray* currItem = NULL; - TabStatusArray* nextItem = NULL; + TabStatusArray *currItem = NULL; + TabStatusArray *nextItem = NULL; currItem = u_sess->stat_cxt.pgStatTabList; @@ -797,7 +739,7 @@ void pgstat_report_stat(bool force) TimestampTz now; PgStat_MsgTabstat regular_msg; PgStat_MsgTabstat shared_msg; - TabStatusArray* tsa = NULL; + TabStatusArray *tsa = NULL; int i; int tablist_len = 0; /* length of u_sess->stat_cxt.pgStatTabList */ bool force_to_destory = false; @@ -839,9 +781,9 @@ void pgstat_report_stat(bool force) /* count the length of u_sess->stat_cxt.pgStatTabList */ tablist_len++; for (i = 0; i < tsa->tsa_used; i++) { - PgStat_TableStatus* entry = &tsa->tsa_entries[i]; - PgStat_MsgTabstat* this_msg = NULL; - PgStat_TableEntry* this_ent = NULL; + PgStat_TableStatus *entry = &tsa->tsa_entries[i]; + PgStat_MsgTabstat *this_msg = NULL; + PgStat_TableEntry *this_ent = NULL; /* Shouldn't have any pending transaction-dependent counts */ Assert(entry->trans == NULL); @@ -869,10 +811,8 @@ void pgstat_report_stat(bool force) } } /* zero out TableStatus structs after use */ - rc = memset_s(tsa->tsa_entries, - TABSTAT_QUANTUM * sizeof(PgStat_TableStatus), - 0, - tsa->tsa_used * sizeof(PgStat_TableStatus)); + rc = memset_s(tsa->tsa_entries, TABSTAT_QUANTUM * sizeof(PgStat_TableStatus), 0, + tsa->tsa_used * sizeof(PgStat_TableStatus)); securec_check(rc, "\0", "\0"); tsa->tsa_used = 0; @@ -882,8 +822,8 @@ void pgstat_report_stat(bool force) bool need_reset_counter = (is_unique_sql_enabled() && IS_PGXC_DATANODE && u_sess->unique_sql_cxt.last_stat_counter != NULL); if (need_reset_counter) { - rc = memset_s( - u_sess->unique_sql_cxt.last_stat_counter, sizeof(PgStat_TableCounts), 0, sizeof(PgStat_TableCounts)); + rc = memset_s(u_sess->unique_sql_cxt.last_stat_counter, sizeof(PgStat_TableCounts), 0, + sizeof(PgStat_TableCounts)); securec_check(rc, "\0", "\0"); } @@ -924,7 +864,7 @@ void pgstat_report_stat(bool force) /* * Subroutine for pgstat_report_stat: finish and send a tabstat message */ -static void pgstat_send_tabstat(PgStat_MsgTabstat* tsmsg) +static void pgstat_send_tabstat(PgStat_MsgTabstat *tsmsg) { int n; int len; @@ -969,7 +909,7 @@ static void pgstat_send_funcstats(void) static const PgStat_FunctionCounts all_zeroes = {0}; PgStat_MsgFuncstat msg; - PgStat_BackendFunctionEntry* entry = NULL; + PgStat_BackendFunctionEntry *entry = NULL; HASH_SEQ_STATUS fstat; if (u_sess->stat_cxt.pgStatFunctions == NULL) @@ -980,8 +920,8 @@ static void pgstat_send_funcstats(void) msg.m_nentries = 0; hash_seq_init(&fstat, u_sess->stat_cxt.pgStatFunctions); - while ((entry = (PgStat_BackendFunctionEntry*)hash_seq_search(&fstat)) != NULL) { - PgStat_FunctionEntry* m_ent = NULL; + while ((entry = (PgStat_BackendFunctionEntry *)hash_seq_search(&fstat)) != NULL) { + PgStat_FunctionEntry *m_ent = NULL; errno_t rc; /* Skip it if no counts accumulated since last time */ @@ -1019,13 +959,13 @@ static void pgstat_send_funcstats(void) */ void pgstat_vacuum_stat(void) { - HTAB* htab = NULL; + HTAB *htab = NULL; PgStat_MsgTabpurge msg; PgStat_MsgFuncpurge f_msg; HASH_SEQ_STATUS hstat; - PgStat_StatDBEntry* dbentry = NULL; - PgStat_StatTabEntry* tabentry = NULL; - PgStat_StatFuncEntry* funcentry = NULL; + PgStat_StatDBEntry *dbentry = NULL; + PgStat_StatTabEntry *tabentry = NULL; + PgStat_StatFuncEntry *funcentry = NULL; int len; if (g_instance.stat_cxt.pgStatSock == PGINVALID_SOCKET) @@ -1047,13 +987,13 @@ void pgstat_vacuum_stat(void) * collector to drop them. */ hash_seq_init(&hstat, u_sess->stat_cxt.pgStatDBHash); - while ((dbentry = (PgStat_StatDBEntry*)hash_seq_search(&hstat)) != NULL) { + while ((dbentry = (PgStat_StatDBEntry *)hash_seq_search(&hstat)) != NULL) { Oid dbid = dbentry->databaseid; CHECK_FOR_INTERRUPTS(); /* the DB entry for shared tables (with InvalidOid) is never dropped */ - if (OidIsValid(dbid) && hash_search(htab, (void*)&dbid, HASH_FIND, NULL) == NULL) + if (OidIsValid(dbid) && hash_search(htab, (void *)&dbid, HASH_FIND, NULL) == NULL) pgstat_drop_database(dbid); } @@ -1063,8 +1003,8 @@ void pgstat_vacuum_stat(void) /* * Lookup our own database entry; if not found, nothing more to do. */ - dbentry = (PgStat_StatDBEntry*)hash_search( - u_sess->stat_cxt.pgStatDBHash, (void*)&u_sess->proc_cxt.MyDatabaseId, HASH_FIND, NULL); + dbentry = (PgStat_StatDBEntry *)hash_search(u_sess->stat_cxt.pgStatDBHash, (void *)&u_sess->proc_cxt.MyDatabaseId, + HASH_FIND, NULL); if (dbentry == NULL || dbentry->tables == NULL) return; @@ -1082,12 +1022,12 @@ void pgstat_vacuum_stat(void) * Check for all tables listed in stats hashtable if they still exist. */ hash_seq_init(&hstat, dbentry->tables); - while ((tabentry = (PgStat_StatTabEntry*)hash_seq_search(&hstat)) != NULL) { + while ((tabentry = (PgStat_StatTabEntry *)hash_seq_search(&hstat)) != NULL) { PgStat_StatTabKey tabkey = tabentry->tablekey; CHECK_FOR_INTERRUPTS(); - if (hash_search(htab, (void*)(&tabkey), HASH_FIND, NULL) != NULL) + if (hash_search(htab, (void *)(&tabkey), HASH_FIND, NULL) != NULL) continue; /* @@ -1137,12 +1077,12 @@ void pgstat_vacuum_stat(void) f_msg.m_nentries = 0; hash_seq_init(&hstat, dbentry->functions); - while ((funcentry = (PgStat_StatFuncEntry*)hash_seq_search(&hstat)) != NULL) { + while ((funcentry = (PgStat_StatFuncEntry *)hash_seq_search(&hstat)) != NULL) { Oid funcid = funcentry->functionid; CHECK_FOR_INTERRUPTS(); - if (hash_search(htab, (void*)&funcid, HASH_FIND, NULL) != NULL) + if (hash_search(htab, (void *)&funcid, HASH_FIND, NULL) != NULL) continue; /* @@ -1184,9 +1124,9 @@ void pgstat_vacuum_stat(void) * so that it will be freed properly in event of an error.) * ---------- */ -static HTAB* pgstat_collect_oids(Oid catalogid) +static HTAB *pgstat_collect_oids(Oid catalogid) { - HTAB* htab = NULL; + HTAB *htab = NULL; HASHCTL hash_ctl; Relation rel; TableScanDesc scan; @@ -1199,17 +1139,17 @@ static HTAB* pgstat_collect_oids(Oid catalogid) hash_ctl.entrysize = sizeof(Oid); hash_ctl.hash = oid_hash; hash_ctl.hcxt = CurrentMemoryContext; - htab = hash_create( - "Temporary table of OIDs", PGSTAT_TAB_HASH_SIZE, &hash_ctl, HASH_ELEM | HASH_FUNCTION | HASH_CONTEXT); + htab = hash_create("Temporary table of OIDs", PGSTAT_TAB_HASH_SIZE, &hash_ctl, + HASH_ELEM | HASH_FUNCTION | HASH_CONTEXT); rel = heap_open(catalogid, AccessShareLock); scan = tableam_scan_begin(rel, SnapshotNow, 0, NULL); - while ((tup = (HeapTuple) tableam_scan_getnexttuple(scan, ForwardScanDirection)) != NULL) { + while ((tup = (HeapTuple)tableam_scan_getnexttuple(scan, ForwardScanDirection)) != NULL) { Oid thisoid = HeapTupleGetOid(tup); CHECK_FOR_INTERRUPTS(); - (void)hash_search(htab, (void*)&thisoid, HASH_ENTER, NULL); + (void)hash_search(htab, (void *)&thisoid, HASH_ENTER, NULL); } tableam_scan_end(scan); heap_close(rel, AccessShareLock); @@ -1225,9 +1165,9 @@ static HTAB* pgstat_collect_oids(Oid catalogid) * : done with it. (However, we make the table in CurrentMemoryContext * : so that it will be freed properly in event of an error.) */ -static HTAB* pgstat_collect_tabkeys(void) +static HTAB *pgstat_collect_tabkeys(void) { - HTAB* htab = NULL; + HTAB *htab = NULL; HASHCTL hash_ctl; Relation pgRelation; Relation pgPartition; @@ -1242,18 +1182,18 @@ static HTAB* pgstat_collect_tabkeys(void) hash_ctl.entrysize = sizeof(PgStat_StatTabKey); hash_ctl.hash = tag_hash; hash_ctl.hcxt = CurrentMemoryContext; - htab = hash_create( - "Temporary table of OIDs", PGSTAT_TAB_HASH_SIZE, &hash_ctl, HASH_ELEM | HASH_FUNCTION | HASH_CONTEXT); + htab = hash_create("Temporary table of OIDs", PGSTAT_TAB_HASH_SIZE, &hash_ctl, + HASH_ELEM | HASH_FUNCTION | HASH_CONTEXT); /* deal with relation */ tabkey.statFlag = InvalidOid; pgRelation = heap_open(RelationRelationId, AccessShareLock); scan = tableam_scan_begin(pgRelation, SnapshotNow, 0, NULL); - while ((tuple = (HeapTuple) tableam_scan_getnexttuple(scan, ForwardScanDirection)) != NULL) { + while ((tuple = (HeapTuple)tableam_scan_getnexttuple(scan, ForwardScanDirection)) != NULL) { tabkey.tableid = HeapTupleGetOid(tuple); CHECK_FOR_INTERRUPTS(); - (void)hash_search(htab, (void*)(&tabkey), HASH_ENTER, NULL); + (void)hash_search(htab, (void *)(&tabkey), HASH_ENTER, NULL); } tableam_scan_end(scan); heap_close(pgRelation, AccessShareLock); @@ -1261,7 +1201,7 @@ static HTAB* pgstat_collect_tabkeys(void) /* deal with partition */ pgPartition = heap_open(PartitionRelationId, AccessShareLock); scan = tableam_scan_begin(pgPartition, SnapshotNow, 0, NULL); - while ((tuple = (HeapTuple) tableam_scan_getnexttuple(scan, ForwardScanDirection)) != NULL) { + while ((tuple = (HeapTuple)tableam_scan_getnexttuple(scan, ForwardScanDirection)) != NULL) { partForm = (Form_pg_partition)GETSTRUCT(tuple); /* skip partitioned object in pg_partition */ @@ -1273,7 +1213,7 @@ static HTAB* pgstat_collect_tabkeys(void) CHECK_FOR_INTERRUPTS(); - (void)hash_search(htab, (void*)(&tabkey), HASH_ENTER, NULL); + (void)hash_search(htab, (void *)(&tabkey), HASH_ENTER, NULL); } tableam_scan_end(scan); heap_close(pgPartition, AccessShareLock); @@ -1292,12 +1232,14 @@ static HTAB* pgstat_collect_tabkeys(void) void pgstat_drop_database(Oid databaseid) { PgStat_MsgDropdb msg; - + // 妫鏌ュ叏灞鍙橀噺 g_instance.stat_cxt.pgStatSock 鏄惁涓烘棤鏁堢殑濂楁帴瀛 if (g_instance.stat_cxt.pgStatSock == PGINVALID_SOCKET) return; pgstat_setheader(&msg.m_hdr, PGSTAT_MTYPE_DROPDB); + // 灏嗘暟鎹簱鐨処D瀛樺偍鍦 msg.m_databaseid 涓 msg.m_databaseid = databaseid; + // 灏嗘秷鎭彂閫佸埌缁熻鏀堕泦绯荤粺 pgstat_send(&msg, sizeof(msg)); } @@ -1315,21 +1257,28 @@ void pgstat_drop_database(Oid databaseid) #ifdef NOT_USED void pgstat_drop_relation(Oid relid) { - PgStat_MsgTabpurge msg; - int len; + PgStat_MsgTabpurge msg; // 鍒涘缓涓涓 PgStat_MsgTabpurge 缁撴瀯鐨勬秷鎭彉閲 + int len; // 鐢ㄤ簬瀛樺偍娑堟伅鐨勯暱搴 - if (g_instance.stat_cxt.pgStatSock == PGINVALID_SOCKET) - return; - msg.m_entry[0].m_tableid = relid; - msg.m_entry[0].m_statFlag = STATFLG_RELATION; - msg.m_nentries = 1; + if (g_instance.stat_cxt.pgStatSock == PGINVALID_SOCKET) // 妫鏌ョ粺璁″鎺ュ瓧鏄惁鏈夋晥 + return; // 濡傛灉鏃犳晥锛岀洿鎺ヨ繑鍥烇紝涓嶆墽琛屽悗缁搷浣 + msg.m_entry[0].m_tableid = relid; // 璁剧疆娑堟伅涓殑琛ㄦ垨绱㈠紩鐨 ID + msg.m_entry[0].m_statFlag = STATFLG_RELATION; // 璁剧疆缁熻鏍囧織涓哄叧绯伙紙琛ㄦ垨绱㈠紩锛 + msg.m_nentries = 1; // 璁剧疆娑堟伅涓殑鏉$洰鏁颁负 1 + + // 璁$畻娑堟伅鐨勬婚暱搴︼紝鍖呮嫭娑堟伅澶村拰鎵鏈夋潯鐩殑闀垮害 len = offsetof(PgStat_MsgTabpurge, m_entry[0]) + sizeof(PgStat_MsgTabEntry); + // 浣跨敤 pgstat_setheader 鍑芥暟璁剧疆娑堟伅澶寸殑绫诲瀷涓 PGSTAT_MTYPE_TABPURGE pgstat_setheader(&msg.m_hdr, PGSTAT_MTYPE_TABPURGE); - msg.m_databaseid = u_sess->proc_cxt.MyDatabaseId; + + msg.m_databaseid = u_sess->proc_cxt.MyDatabaseId; // 璁剧疆娑堟伅涓殑鏁版嵁搴 ID + + // 鍙戦佹秷鎭埌缁熻鏀堕泦绯荤粺锛屾秷鎭殑澶у皬涓 len pgstat_send(&msg, len); } + #endif /* NOT_USED */ /* ---------- @@ -1340,17 +1289,21 @@ void pgstat_drop_relation(Oid relid) */ void pgstat_reset_counters(void) { - PgStat_MsgResetcounter msg; + PgStat_MsgResetcounter msg; // 鍒涘缓涓涓 PgStat_MsgResetcounter 缁撴瀯鐨勬秷鎭彉閲 - if (g_instance.stat_cxt.pgStatSock == PGINVALID_SOCKET) - return; + if (g_instance.stat_cxt.pgStatSock == PGINVALID_SOCKET) // 妫鏌ョ粺璁″鎺ュ瓧鏄惁鏈夋晥 + return; // 濡傛灉鏃犳晥锛岀洿鎺ヨ繑鍥烇紝涓嶆墽琛屽悗缁搷浣 - if (!superuser()) + if (!superuser()) // 妫鏌ュ綋鍓嶇敤鎴锋槸鍚︿负瓒呯骇鐢ㄦ埛 ereport(ERROR, - (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), errmsg("must be system admin to reset statistics counters"))); + (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), errmsg("must be system admin to reset statistics counters"))); + // 浣跨敤 pgstat_setheader 鍑芥暟璁剧疆娑堟伅澶寸殑绫诲瀷涓 PGSTAT_MTYPE_RESETCOUNTER pgstat_setheader(&msg.m_hdr, PGSTAT_MTYPE_RESETCOUNTER); - msg.m_databaseid = u_sess->proc_cxt.MyDatabaseId; + + msg.m_databaseid = u_sess->proc_cxt.MyDatabaseId; // 璁剧疆娑堟伅涓殑鏁版嵁搴 ID + + // 鍙戦佹秷鎭埌缁熻鏀堕泦绯荤粺锛屾秷鎭殑澶у皬涓 sizeof(msg) pgstat_send(&msg, sizeof(msg)); } @@ -1360,25 +1313,34 @@ void pgstat_reset_counters(void) * Tell the statistics collector to reset cluster-wide shared counters. * ---------- */ -void pgstat_reset_shared_counters(const char* target) +/* + * 鍔熻兘锛氶噸缃叡浜粺璁¤鏁板櫒 + * + * 鍙傛暟鍒楄〃锛 + * target锛氳閲嶇疆鐨勭粺璁¤鏁板櫒鐩爣 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庨噸缃寚瀹氱殑鍏变韩缁熻璁℃暟鍣ㄣ傚畠瑕佹眰璋冪敤鑰呭繀椤诲叿鏈夎秴绾х敤鎴锋潈闄愩 + * 鏀寔鐨勭洰鏍囧间负 "bgwriter"銆 + */ +void pgstat_reset_shared_counters(const char *target) { PgStat_MsgResetsharedcounter msg; + /* 妫鏌ョ粺璁″鎺ュ瓧鏄惁鏈夋晥 */ if (g_instance.stat_cxt.pgStatSock == PGINVALID_SOCKET) return; - + /* 妫鏌ユ槸鍚﹀叿鏈夎秴绾х敤鎴锋潈闄愶紝鍚﹀垯鎶ラ敊 */ if (!superuser()) ereport(ERROR, - (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), errmsg("must be system admin to reset statistics counters"))); - + (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), errmsg("must be system admin to reset statistics counters"))); + /* 鏍规嵁鐩爣鍊艰缃秷鎭殑閲嶇疆鐩爣 */ if (strcmp(target, "bgwriter") == 0) msg.m_resettarget = RESET_BGWRITER; else - ereport(ERROR, - (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("unrecognized reset target: \"%s\"", target), - errhint("Target must be \"bgwriter\"."))); - + ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("unrecognized reset target: \"%s\"", target), + errhint("Target must be \"bgwriter\"."))); + /* 璁剧疆娑堟伅澶撮儴骞跺彂閫佹秷鎭 */ pgstat_setheader(&msg.m_hdr, PGSTAT_MTYPE_RESETSHAREDCOUNTER); pgstat_send(&msg, sizeof(msg)); } @@ -1389,23 +1351,35 @@ void pgstat_reset_shared_counters(const char* target) * Tell the statistics collector to reset a single counter. * ---------- */ +/* + * 鍔熻兘锛氶噸缃叡浜鏁板櫒 + * + * 鍙傛暟鍒楄〃锛 + * target锛氳閲嶇疆鐨勭洰鏍囧悕绉 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庡悜缁熻瀛愮郴缁熷彂閫佹秷鎭互閲嶇疆鍏变韩璁℃暟鍣ㄣ傚畠瑕佹眰璋冪敤鑰呭繀椤诲叿鏈夎秴绾х敤鎴锋潈闄愩 + * 鍑芥暟鏍规嵁浼犲叆鐨勭洰鏍囧悕绉扮‘瀹氳閲嶇疆鐨勮鏁板櫒绫诲瀷锛屽苟灏嗘秷鎭彂閫佺粰缁熻瀛愮郴缁熴 + */ void pgstat_reset_single_counter(Oid p_objoid, Oid objoid, PgStat_Single_Reset_Type type) { PgStat_MsgResetsinglecounter msg; + // 妫鏌ョ粺璁″鎺ュ瓧鏄惁鏈夋晥 if (g_instance.stat_cxt.pgStatSock == PGINVALID_SOCKET) return; - + // 妫鏌ユ槸鍚﹀叿鏈夎秴绾х敤鎴锋潈闄愶紝鍚﹀垯鎶ラ敊 if (!superuser()) ereport(ERROR, - (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), errmsg("must be system admin to reset statistics counters"))); - + (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), errmsg("must be system admin to reset statistics counters"))); + // 璁剧疆娑堟伅澶撮儴 pgstat_setheader(&msg.m_hdr, PGSTAT_MTYPE_RESETSINGLECOUNTER); + // 璁剧疆娑堟伅鐨勬暟鎹簱ID銆侀噸缃被鍨嬪拰瀵硅薄ID msg.m_databaseid = u_sess->proc_cxt.MyDatabaseId; msg.m_resettype = type; msg.m_objectid = objoid; msg.p_objectid = p_objoid; - + // 鍙戦佹秷鎭 pgstat_send(&msg, sizeof(msg)); } @@ -1417,17 +1391,31 @@ void pgstat_reset_single_counter(Oid p_objoid, Oid objoid, PgStat_Single_Reset_T * the db OID must be passed in, instead. * ---------- */ +/* + * 鍔熻兘锛氭眹鎶ヨ嚜鍔ㄦ竻鐞嗕换鍔$殑鍚姩 + * + * 鍙傛暟鍒楄〃锛 + * dboid锛氭暟鎹簱OID锛岃〃绀鸿娓呯悊鐨勬暟鎹簱 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庡悜缁熻瀛愮郴缁熸姤鍛婅嚜鍔ㄦ竻鐞嗕换鍔$殑鍚姩鎯呭喌銆傚鏋滅粺璁″瓙绯荤粺鐨勫鎺ュ瓧鏃犳晥锛 + * 鍑芥暟浼氱珛鍗宠繑鍥炪傚嚱鏁伴鍏堣缃秷鎭ご锛屽寘鎷秷鎭被鍨嬨佹暟鎹簱OID鍜屼换鍔″惎鍔ㄦ椂闂达紝鐒跺悗 + * 灏嗘秷鎭彂閫佺粰缁熻瀛愮郴缁熴 + */ void pgstat_report_autovac(Oid dboid) { PgStat_MsgAutovacStart msg; + // 濡傛灉缁熻瀛愮郴缁熺殑濂楁帴瀛楁棤鏁堬紝鐩存帴杩斿洖 if (g_instance.stat_cxt.pgStatSock == PGINVALID_SOCKET) return; + // 璁剧疆娑堟伅澶达紝鍖呮嫭娑堟伅绫诲瀷銆佹暟鎹簱OID鍜屼换鍔″惎鍔ㄦ椂闂 pgstat_setheader(&msg.m_hdr, PGSTAT_MTYPE_AUTOVAC_START); msg.m_databaseid = dboid; msg.m_start_time = GetCurrentTimestamp(); + // 灏嗘秷鎭彂閫佺粰缁熻瀛愮郴缁 pgstat_send(&msg, sizeof(msg)); } @@ -1437,19 +1425,36 @@ void pgstat_report_autovac(Oid dboid) * Tell the collector about the table we just vacuumed. * --------- */ +/* + * 鍔熻兘锛氭眹鎶ヨ嚜鍔ㄦ竻鐞嗕换鍔″洜瓒呮椂鑰岀粓姝 + * + * 鍙傛暟鍒楄〃锛 + * tableoid锛氳〃鐨凮ID锛岃〃绀鸿Е鍙戣嚜鍔ㄦ竻鐞嗙殑琛 + * statFlag锛氱粺璁℃爣蹇楋紝琛ㄧず缁熻鐨勭被鍨嬶紙濡傜储寮曘佽〃銆佸叡浜〃绛夛級 + * shared锛氭寚绀烘槸鍚︽槸鍏变韩琛 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庡悜缁熻瀛愮郴缁熸姤鍛婅嚜鍔ㄦ竻鐞嗕换鍔″洜瓒呮椂鑰岀粓姝㈢殑鎯呭喌銆 + * 濡傛灉缁熻瀛愮郴缁熺殑濂楁帴瀛楁棤鏁堟垨鑰呮湭鍚敤缁熻璁℃暟锛屽垯鍑芥暟浼氱珛鍗宠繑鍥炪 + * 棣栧厛锛屽嚱鏁颁細璁剧疆娑堟伅澶达紝鍖呮嫭娑堟伅绫诲瀷銆佹暟鎹簱OID锛堝鏋滀笉鏄叡浜〃锛夈佽〃OID銆佺粺璁℃爣蹇楀拰瓒呮椂鐘舵併 + * 鐒跺悗锛屽皢娑堟伅鍙戦佺粰缁熻瀛愮郴缁熶互璁板綍瓒呮椂鐨勮嚜鍔ㄦ竻鐞嗕换鍔° + */ + void pgstat_report_autovac_timeout(Oid tableoid, uint32 statFlag, bool shared) { PgStat_MsgAutovacStat msg; - + // 濡傛灉缁熻瀛愮郴缁熺殑濂楁帴瀛楁棤鏁堟垨鑰呮湭鍚敤缁熻璁℃暟锛屽垯鐩存帴杩斿洖 if (g_instance.stat_cxt.pgStatSock == PGINVALID_SOCKET || !u_sess->attr.attr_common.pgstat_track_counts) return; - + // 璁剧疆娑堟伅澶 pgstat_setheader(&msg.m_hdr, PGSTAT_MTYPE_AUTOVAC_STAT); + // 濡傛灉涓嶆槸鍏变韩琛紝鍒欎娇鐢ㄥ綋鍓嶄細璇濈殑鏁版嵁搴揙ID msg.m_databaseid = shared ? InvalidOid : u_sess->proc_cxt.MyDatabaseId; + // 璁剧疆琛ㄧ殑OID銆佺粺璁℃爣蹇楀拰瓒呮椂鐘舵 msg.m_tableoid = tableoid; msg.m_statFlag = statFlag; msg.m_autovacStat = AV_TIMEOUT; - + // 鍙戦佹秷鎭粰缁熻瀛愮郴缁熶互璁板綍瓒呮椂鐨勮嚜鍔ㄦ竻鐞嗕换鍔 pgstat_send(&msg, sizeof(msg)); } @@ -1459,20 +1464,40 @@ void pgstat_report_autovac_timeout(Oid tableoid, uint32 statFlag, bool shared) * Tell the collector about the table we just vacuumed. * --------- */ +/* + * 鍔熻兘锛氬悜缁熻瀛愮郴缁熸姤鍛奦ACUUM鎿嶄綔鐨勭粺璁′俊鎭 + * + * 鍙傛暟鍒楄〃锛 + * tableoid锛氳〃鐨凮ID锛岃〃绀鸿Е鍙慥ACUUM鎿嶄綔鐨勮〃 + * statFlag锛氱粺璁℃爣蹇楋紝琛ㄧず缁熻鐨勭被鍨嬶紙濡傜储寮曘佽〃銆佸叡浜〃绛夛級 + * shared锛氭寚绀烘槸鍚︽槸鍏变韩琛 + * tuples锛歏ACUUM鎿嶄綔褰卞搷鐨勫厓缁勬暟閲 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庡悜缁熻瀛愮郴缁熸姤鍛奦ACUUM鎿嶄綔鐨勭粺璁′俊鎭 + * 濡傛灉缁熻瀛愮郴缁熺殑濂楁帴瀛楁棤鏁堟垨鑰呮湭鍚敤缁熻璁℃暟锛屽垯鍑芥暟浼氱珛鍗宠繑鍥炪 + * 棣栧厛锛屽嚱鏁颁細璁剧疆娑堟伅澶达紝鍖呮嫭娑堟伅绫诲瀷銆佹暟鎹簱OID锛堝鏋滀笉鏄叡浜〃锛夈佽〃OID銆佺粺璁℃爣蹇椼 + * 鏄惁涓鸿嚜鍔╒ACUUM宸ヤ綔杩涚▼銆乂ACUUM鎿嶄綔鐨勬椂闂存埑鍜屽奖鍝嶇殑鍏冪粍鏁伴噺銆 + * 鐒跺悗锛屽皢娑堟伅鍙戦佺粰缁熻瀛愮郴缁熶互璁板綍VACUUM鎿嶄綔鐨勭粺璁′俊鎭 + */ + void pgstat_report_vacuum(Oid tableoid, uint32 statFlag, bool shared, PgStat_Counter tuples) { PgStat_MsgVacuum msg; - + // 濡傛灉缁熻瀛愮郴缁熺殑濂楁帴瀛楁棤鏁堟垨鑰呮湭鍚敤缁熻璁℃暟锛屽垯鐩存帴杩斿洖 if (g_instance.stat_cxt.pgStatSock == PGINVALID_SOCKET || !u_sess->attr.attr_common.pgstat_track_counts) return; - + // 璁剧疆娑堟伅澶 pgstat_setheader(&msg.m_hdr, PGSTAT_MTYPE_VACUUM); + // 濡傛灉涓嶆槸鍏变韩琛紝鍒欎娇鐢ㄥ綋鍓嶄細璇濈殑鏁版嵁搴揙ID msg.m_databaseid = shared ? InvalidOid : u_sess->proc_cxt.MyDatabaseId; + // 璁剧疆琛ㄧ殑OID銆佺粺璁℃爣蹇椼佹槸鍚︿负鑷姩VACUUM宸ヤ綔杩涚▼銆乂ACUUM鎿嶄綔鐨勬椂闂存埑鍜屽奖鍝嶇殑鍏冪粍鏁伴噺 msg.m_tableoid = tableoid; msg.m_statFlag = statFlag; msg.m_autovacuum = IsAutoVacuumWorkerProcess() || IsFromAutoVacWoker(); msg.m_vacuumtime = GetCurrentTimestamp(); msg.m_tuples = tuples; + // 鍙戦佹秷鎭粰缁熻瀛愮郴缁熶互璁板綍VACUUM鎿嶄綔鐨勭粺璁′俊鎭 pgstat_send(&msg, sizeof(msg)); } @@ -1482,21 +1507,40 @@ void pgstat_report_vacuum(Oid tableoid, uint32 statFlag, bool shared, PgStat_Cou * Tell the collector how many blocks we scanned and successfully pruned * --------- */ -void PgstatReportPrunestat(Oid tableoid, uint32 statFlag, - bool shared, PgStat_Counter scanned, - PgStat_Counter pruned) +/* + * 鍔熻兘锛氬悜缁熻瀛愮郴缁熸姤鍛奝RUNE鎿嶄綔鐨勭粺璁′俊鎭 + * + * 鍙傛暟鍒楄〃锛 + * tableoid锛氳〃鐨凮ID锛岃〃绀鸿Е鍙慞RUNE鎿嶄綔鐨勮〃 + * statFlag锛氱粺璁℃爣蹇楋紝琛ㄧず缁熻鐨勭被鍨嬶紙濡傜储寮曘佽〃銆佸叡浜〃绛夛級 + * shared锛氭寚绀烘槸鍚︽槸鍏变韩琛 + * scanned锛歅RUNE鎿嶄綔鎵弿鐨勫潡鏁 + * pruned锛歅RUNE鎿嶄綔淇壀鐨勫潡鏁 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庡悜缁熻瀛愮郴缁熸姤鍛奝RUNE鎿嶄綔鐨勭粺璁′俊鎭 + * 濡傛灉缁熻瀛愮郴缁熺殑濂楁帴瀛楁棤鏁堬紝鍒欏嚱鏁颁細绔嬪嵆杩斿洖銆 + * 棣栧厛锛屽嚱鏁颁細璁剧疆娑堟伅澶达紝鍖呮嫭娑堟伅绫诲瀷銆佹暟鎹簱OID锛堝鏋滀笉鏄叡浜〃锛夈佽〃OID銆佺粺璁℃爣蹇椼 + * 鎵弿鐨勫潡鏁板拰淇壀鐨勫潡鏁般 + * 鐒跺悗锛屽皢娑堟伅鍙戦佺粰缁熻瀛愮郴缁熶互璁板綍PRUNE鎿嶄綔鐨勭粺璁′俊鎭 + */ + +void PgstatReportPrunestat(Oid tableoid, uint32 statFlag, bool shared, PgStat_Counter scanned, PgStat_Counter pruned) { PgStat_MsgPrune msg; - + // 濡傛灉缁熻瀛愮郴缁熺殑濂楁帴瀛楁棤鏁堬紝鍒欑洿鎺ヨ繑鍥 if (g_instance.stat_cxt.pgStatSock == PGINVALID_SOCKET) return; - + // 璁剧疆娑堟伅澶 pgstat_setheader(&msg.m_hdr, PGSTAT_MTYPE_PRUNESTAT); + // 濡傛灉涓嶆槸鍏变韩琛紝鍒欎娇鐢ㄥ綋鍓嶄細璇濈殑鏁版嵁搴揙ID msg.m_databaseid = shared ? InvalidOid : u_sess->proc_cxt.MyDatabaseId; + // 璁剧疆琛ㄧ殑OID銆佺粺璁℃爣蹇椼佹壂鎻忕殑鍧楁暟鍜屼慨鍓殑鍧楁暟 msg.m_tableoid = tableoid; msg.m_statFlag = statFlag; msg.m_scanned_blocks = scanned; msg.m_pruned_blocks = pruned; + // 鍙戦佹秷鎭粰缁熻瀛愮郴缁熶互璁板綍PRUNE鎿嶄綔鐨勭粺璁′俊鎭 pgstat_send(&msg, sizeof(msg)); } @@ -1507,18 +1551,36 @@ void PgstatReportPrunestat(Oid tableoid, uint32 statFlag, * copy/[exchange/truncate/drop] partition. * --------- */ +/* + * 鍔熻兘锛氬悜缁熻瀛愮郴缁熸姤鍛婃暟鎹彉鏇寸殑缁熻淇℃伅 + * + * 鍙傛暟鍒楄〃锛 + * tableoid锛氳〃鐨凮ID锛岃〃绀鸿Е鍙戞暟鎹彉鏇寸殑琛 + * statFlag锛氱粺璁℃爣蹇楋紝琛ㄧず缁熻鐨勭被鍨嬶紙濡傜储寮曘佽〃銆佸叡浜〃绛夛級 + * shared锛氭寚绀烘槸鍚︽槸鍏变韩琛 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庡悜缁熻瀛愮郴缁熸姤鍛婃暟鎹彉鏇寸殑缁熻淇℃伅銆 + * 濡傛灉缁熻瀛愮郴缁熺殑濂楁帴瀛楁棤鏁堟垨鏈惎鐢ㄧ粺璁★紝鍒欏嚱鏁颁細绔嬪嵆杩斿洖銆 + * 棣栧厛锛屽嚱鏁颁細璁剧疆娑堟伅澶达紝鍖呮嫭娑堟伅绫诲瀷銆佹暟鎹簱OID锛堝鏋滀笉鏄叡浜〃锛夈佽〃OID銆佺粺璁℃爣蹇楀拰鍙樻洿鐨勬椂闂存埑銆 + * 鐒跺悗锛屽皢娑堟伅鍙戦佺粰缁熻瀛愮郴缁熶互璁板綍鏁版嵁鍙樻洿鐨勭粺璁′俊鎭 + */ + void pgstat_report_data_changed(Oid tableoid, uint32 statFlag, bool shared) { PgStat_MsgDataChanged msg; - + // 濡傛灉缁熻瀛愮郴缁熺殑濂楁帴瀛楁棤鏁堟垨鏈惎鐢ㄧ粺璁★紝鍒欑洿鎺ヨ繑鍥 if (g_instance.stat_cxt.pgStatSock == PGINVALID_SOCKET || !u_sess->attr.attr_common.pgstat_track_counts) return; - + // 璁剧疆娑堟伅澶 pgstat_setheader(&msg.m_hdr, PGSTAT_MTYPE_DATA_CHANGED); + // 濡傛灉涓嶆槸鍏变韩琛紝鍒欎娇鐢ㄥ綋鍓嶄細璇濈殑鏁版嵁搴揙ID msg.m_databaseid = shared ? InvalidOid : u_sess->proc_cxt.MyDatabaseId; + // 璁剧疆琛ㄧ殑OID銆佺粺璁℃爣蹇楀拰鍙樻洿鐨勬椂闂存埑 msg.m_tableoid = tableoid; msg.m_statFlag = statFlag; msg.m_changed_time = GetCurrentTimestamp(); + // 鍙戦佹秷鎭粰缁熻瀛愮郴缁熶互璁板綍鏁版嵁鍙樻洿鐨勭粺璁′俊鎭 pgstat_send(&msg, sizeof(msg)); } @@ -1528,33 +1590,65 @@ void pgstat_report_data_changed(Oid tableoid, uint32 statFlag, bool shared) * Tell the collector about the sql responsetime. * --------- */ +/* + * 鍔熻兘锛氬悜缁熻瀛愮郴缁熸姤鍛奡QL鍝嶅簲鏃堕棿缁熻淇℃伅 + * + * 鍙傛暟鍒楄〃锛 + * UniqueSQLId锛氬敮涓鐨凷QL鏍囪瘑锛岃〃绀篠QL璇彞鐨勫敮涓鏍囪瘑绗 + * start_time锛歋QL寮濮嬫墽琛岀殑鏃堕棿鎴 + * rt锛歋QL鐨勫搷搴旀椂闂 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庡悜缁熻瀛愮郴缁熸姤鍛奡QL鍝嶅簲鏃堕棿缁熻淇℃伅銆 + * 濡傛灉鏄崟鑺傜偣妯″紡銆佺粺璁″瓙绯荤粺鐨勫鎺ュ瓧鏃犳晥銆佹湭鍚敤瀹炴椂鐧惧垎浣嶇粺璁℃垨鑰呬富鏈虹姸鎬佷笉鏄繍琛岀姸鎬侊紝鍒欏嚱鏁颁細绔嬪嵆杩斿洖銆 + * 棣栧厛锛屽嚱鏁颁細璁剧疆娑堟伅澶达紝鍖呮嫭娑堟伅绫诲瀷鍜孲QL鍝嶅簲鏃堕棿淇℃伅銆 + * 鐒跺悗锛屽皢娑堟伅鍙戦佺粰缁熻瀛愮郴缁熶互璁板綍SQL鐨勫搷搴旀椂闂寸粺璁′俊鎭 + */ + void pgstat_report_sql_rt(uint64 UniqueSQLId, int64 start_time, int64 rt) { PgStat_SqlRT msg; - + // 濡傛灉鏄崟鑺傜偣妯″紡锛岀洿鎺ヨ繑鍥烇紙涓轰簡鎬ц兘闂鑰岀鐢級 if (IS_SINGLE_NODE) { - return; /* disable in single node tmp for performance issue */ - } - if (g_instance.stat_cxt.pgStatSock == PGINVALID_SOCKET || !u_sess->attr.attr_common.enable_instr_rt_percentile) - return; - if (!PMstateIsRun()) { return; } + // 濡傛灉缁熻瀛愮郴缁熺殑濂楁帴瀛楁棤鏁堛佹湭鍚敤瀹炴椂鐧惧垎浣嶇粺璁℃垨鑰呬富鏈虹姸鎬佷笉鏄繍琛岀姸鎬侊紝鍒欑洿鎺ヨ繑鍥 + if (g_instance.stat_cxt.pgStatSock == PGINVALID_SOCKET || !u_sess->attr.attr_common.enable_instr_rt_percentile || + !PMstateIsRun()) { + return; + } + // 璁剧疆娑堟伅澶 pgstat_setheader(&msg.m_hdr, PGSTAT_MTYPE_RESPONSETIME); + // 璁剧疆SQL鍝嶅簲鏃堕棿淇℃伅 msg.sqlRT.UniqueSQLId = UniqueSQLId; msg.sqlRT.start_time = start_time; msg.sqlRT.rt = rt; + // 鍙戦佹秷鎭粰缁熻瀛愮郴缁熶互璁板綍SQL鐨勫搷搴旀椂闂寸粺璁′俊鎭 pgstat_send(&msg, sizeof(msg)); } +/* + * 鍔熻兘锛氬悜缁熻瀛愮郴缁熸姤鍛婅繘绋嬬殑鐧惧垎浣嶇粺璁′俊鎭 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庡悜缁熻瀛愮郴缁熸姤鍛婅繘绋嬬殑鐧惧垎浣嶇粺璁′俊鎭 + * 濡傛灉缁熻瀛愮郴缁熺殑濂楁帴瀛楁棤鏁堬紝鍒欏嚱鏁颁細绔嬪嵆杩斿洖銆 + * 棣栧厛锛屽嚱鏁颁細璁剧疆娑堟伅澶达紝鍖呮嫭娑堟伅绫诲瀷鍜屽綋鍓嶆椂闂存埑銆 + * 鐒跺悗锛屽皢娑堟伅鍙戦佺粰缁熻瀛愮郴缁熶互璁板綍杩涚▼鐨勭櫨鍒嗕綅缁熻淇℃伅銆 + */ + void pgstat_report_process_percentile() { PgStat_PrsPtl msg; - - if (g_instance.stat_cxt.pgStatSock == PGINVALID_SOCKET) + // 濡傛灉缁熻瀛愮郴缁熺殑濂楁帴瀛楁棤鏁堬紝鐩存帴杩斿洖 + if (g_instance.stat_cxt.pgStatSock == PGINVALID_SOCKET) { return; + } + // 璁剧疆娑堟伅澶 pgstat_setheader(&msg.m_hdr, PGSTAT_MTYPE_PROCESSPERCENTILE); + // 璁剧疆褰撳墠鏃堕棿鎴 msg.now = GetCurrentTimestamp(); + // 鍙戦佹秷鎭粰缁熻瀛愮郴缁熶互璁板綍杩涚▼鐨勭櫨鍒嗕綅缁熻淇℃伅 pgstat_send(&msg, sizeof(msg)); } @@ -1564,17 +1658,37 @@ void pgstat_report_process_percentile() * Tell the collector about the table we just truncated. * --------- */ +/* + * 鍔熻兘锛氬悜缁熻瀛愮郴缁熸姤鍛婅〃鎴柇鎿嶄綔鐨勭粺璁′俊鎭 + * + * 鍙傛暟鍒楄〃锛 + * tableoid锛氳鎴柇鐨勮〃鐨凮ID + * statFlag锛氱粺璁℃爣蹇 + * shared锛氭槸鍚︿负鍏变韩琛 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庡悜缁熻瀛愮郴缁熸姤鍛婅〃鎴柇鎿嶄綔鐨勭粺璁′俊鎭 + * 濡傛灉缁熻瀛愮郴缁熺殑濂楁帴瀛楁棤鏁堟垨鑰呮湭鍚敤缁熻璁℃暟锛屽垯鍑芥暟浼氱珛鍗宠繑鍥炪 + * 棣栧厛锛屽嚱鏁颁細璁剧疆娑堟伅澶达紝鍖呮嫭娑堟伅绫诲瀷銆 + * 鐒跺悗锛岃缃秷鎭腑鐨勬暟鎹簱ID銆佽〃OID鍜岀粺璁℃爣蹇椼 + * 鏈鍚庯紝灏嗘秷鎭彂閫佺粰缁熻瀛愮郴缁熶互璁板綍琛ㄦ埅鏂搷浣滅殑缁熻淇℃伅銆 + */ + void pgstat_report_truncate(Oid tableoid, uint32 statFlag, bool shared) { PgStat_MsgTruncate msg; - - if (g_instance.stat_cxt.pgStatSock == PGINVALID_SOCKET || !u_sess->attr.attr_common.pgstat_track_counts) + // 濡傛灉缁熻瀛愮郴缁熺殑濂楁帴瀛楁棤鏁堟垨鑰呮湭鍚敤缁熻璁℃暟锛岀洿鎺ヨ繑鍥 + if (g_instance.stat_cxt.pgStatSock == PGINVALID_SOCKET || !u_sess->attr.attr_common.pgstat_track_counts) { return; - + } + // 璁剧疆娑堟伅澶 pgstat_setheader(&msg.m_hdr, PGSTAT_MTYPE_TRUNCATE); + // 璁剧疆鏁版嵁搴揑D msg.m_databaseid = shared ? InvalidOid : u_sess->proc_cxt.MyDatabaseId; + // 璁剧疆琛∣ID鍜岀粺璁℃爣蹇 msg.m_tableoid = tableoid; msg.m_statFlag = statFlag; + // 鍙戦佹秷鎭粰缁熻瀛愮郴缁熶互璁板綍琛ㄦ埅鏂搷浣滅殑缁熻淇℃伅 pgstat_send(&msg, sizeof(msg)); } @@ -1602,7 +1716,7 @@ void pgstat_report_analyze(Relation rel, PgStat_Counter livetuples, PgStat_Count * committing.) */ if (rel->pgstat_info != NULL) { - PgStat_TableXactStatus* trans = NULL; + PgStat_TableXactStatus *trans = NULL; for (trans = rel->pgstat_info->trans; trans; trans = trans->upper) { livetuples -= trans->tuples_inserted - trans->tuples_deleted; @@ -1632,16 +1746,33 @@ void pgstat_report_analyze(Relation rel, PgStat_Counter livetuples, PgStat_Count * Tell the collector about a Hot Standby recovery conflict. * -------- */ +/* + * 鍔熻兘锛氬悜缁熻瀛愮郴缁熸姤鍛婃仮澶嶅啿绐佺殑缁熻淇℃伅 + * + * 鍙傛暟鍒楄〃锛 + * reason锛氭仮澶嶅啿绐佺殑鍘熷洜 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庡悜缁熻瀛愮郴缁熸姤鍛婃仮澶嶅啿绐佺殑缁熻淇℃伅銆 + * 濡傛灉缁熻瀛愮郴缁熺殑濂楁帴瀛楁棤鏁堟垨鑰呮湭鍚敤缁熻璁℃暟锛屽垯鍑芥暟浼氱珛鍗宠繑鍥炪 + * 棣栧厛锛屽嚱鏁颁細璁剧疆娑堟伅澶达紝鍖呮嫭娑堟伅绫诲瀷銆 + * 鐒跺悗锛岃缃秷鎭腑鐨勬暟鎹簱ID鍜屾仮澶嶅啿绐佺殑鍘熷洜銆 + * 鏈鍚庯紝灏嗘秷鎭彂閫佺粰缁熻瀛愮郴缁熶互璁板綍鎭㈠鍐茬獊鐨勭粺璁′俊鎭 + */ + void pgstat_report_recovery_conflict(int reason) { PgStat_MsgRecoveryConflict msg; - - if (g_instance.stat_cxt.pgStatSock == PGINVALID_SOCKET || !u_sess->attr.attr_common.pgstat_track_counts) + // 濡傛灉缁熻瀛愮郴缁熺殑濂楁帴瀛楁棤鏁堟垨鑰呮湭鍚敤缁熻璁℃暟锛岀洿鎺ヨ繑鍥 + if (g_instance.stat_cxt.pgStatSock == PGINVALID_SOCKET || !u_sess->attr.attr_common.pgstat_track_counts) { return; - + } + // 璁剧疆娑堟伅澶 pgstat_setheader(&msg.m_hdr, PGSTAT_MTYPE_RECOVERYCONFLICT); + // 璁剧疆鏁版嵁搴揑D鍜屾仮澶嶅啿绐佺殑鍘熷洜 msg.m_databaseid = u_sess->proc_cxt.MyDatabaseId; msg.m_reason = reason; + // 鍙戦佹秷鎭粰缁熻瀛愮郴缁熶互璁板綍鎭㈠鍐茬獊鐨勭粺璁′俊鎭 pgstat_send(&msg, sizeof(msg)); } @@ -1651,15 +1782,29 @@ void pgstat_report_recovery_conflict(int reason) * Tell the collector about a deadlock detected. * -------- */ +/* + * 鍔熻兘锛氬悜缁熻瀛愮郴缁熸姤鍛婃閿佺殑缁熻淇℃伅 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庡悜缁熻瀛愮郴缁熸姤鍛婃閿佺殑缁熻淇℃伅銆 + * 濡傛灉缁熻瀛愮郴缁熺殑濂楁帴瀛楁棤鏁堟垨鑰呮湭鍚敤缁熻璁℃暟锛屽垯鍑芥暟浼氱珛鍗宠繑鍥炪 + * 棣栧厛锛屽嚱鏁颁細璁剧疆娑堟伅澶达紝鍖呮嫭娑堟伅绫诲瀷銆 + * 鐒跺悗锛岃缃秷鎭腑鐨勬暟鎹簱ID銆 + * 鏈鍚庯紝灏嗘秷鎭彂閫佺粰缁熻瀛愮郴缁熶互璁板綍姝婚攣鐨勭粺璁′俊鎭 + */ + void pgstat_report_deadlock(void) { PgStat_MsgDeadlock msg; - - if (g_instance.stat_cxt.pgStatSock == PGINVALID_SOCKET || !u_sess->attr.attr_common.pgstat_track_counts) + // 濡傛灉缁熻瀛愮郴缁熺殑濂楁帴瀛楁棤鏁堟垨鑰呮湭鍚敤缁熻璁℃暟锛岀洿鎺ヨ繑鍥 + if (g_instance.stat_cxt.pgStatSock == PGINVALID_SOCKET || !u_sess->attr.attr_common.pgstat_track_counts) { return; - + } + // 璁剧疆娑堟伅澶 pgstat_setheader(&msg.m_hdr, PGSTAT_MTYPE_DEADLOCK); + // 璁剧疆鏁版嵁搴揑D msg.m_databaseid = u_sess->proc_cxt.MyDatabaseId; + // 鍙戦佹秷鎭粰缁熻瀛愮郴缁熶互璁板綍姝婚攣鐨勭粺璁′俊鎭 pgstat_send(&msg, sizeof(msg)); } @@ -1669,16 +1814,34 @@ void pgstat_report_deadlock(void) * Tell the collector about a temporary file. * -------- */ +/* + * 鍔熻兘锛氬悜缁熻瀛愮郴缁熸姤鍛婁复鏃舵枃浠剁殑缁熻淇℃伅 + * + * 鍙傛暟鍒楄〃锛 + * filesize锛氫复鏃舵枃浠剁殑澶у皬 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庡悜缁熻瀛愮郴缁熸姤鍛婁复鏃舵枃浠剁殑缁熻淇℃伅銆 + * 濡傛灉缁熻瀛愮郴缁熺殑濂楁帴瀛楁棤鏁堟垨鑰呮湭鍚敤缁熻璁℃暟锛屽垯鍑芥暟浼氱珛鍗宠繑鍥炪 + * 棣栧厛锛屽嚱鏁颁細璁剧疆娑堟伅澶达紝鍖呮嫭娑堟伅绫诲瀷銆 + * 鐒跺悗锛岃缃秷鎭腑鐨勬暟鎹簱ID鍜屼复鏃舵枃浠剁殑澶у皬銆 + * 鏈鍚庯紝灏嗘秷鎭彂閫佺粰缁熻瀛愮郴缁熶互璁板綍涓存椂鏂囦欢鐨勭粺璁′俊鎭 + */ + void pgstat_report_tempfile(size_t filesize) { PgStat_MsgTempFile msg; - - if (g_instance.stat_cxt.pgStatSock == PGINVALID_SOCKET || !u_sess->attr.attr_common.pgstat_track_counts) + // 濡傛灉缁熻瀛愮郴缁熺殑濂楁帴瀛楁棤鏁堟垨鑰呮湭鍚敤缁熻璁℃暟锛岀洿鎺ヨ繑鍥 + if (g_instance.stat_cxt.pgStatSock == PGINVALID_SOCKET || !u_sess->attr.attr_common.pgstat_track_counts) { return; - + } + // 璁剧疆娑堟伅澶 pgstat_setheader(&msg.m_hdr, PGSTAT_MTYPE_TEMPFILE); + // 璁剧疆鏁版嵁搴揑D msg.m_databaseid = u_sess->proc_cxt.MyDatabaseId; + // 璁剧疆涓存椂鏂囦欢鐨勫ぇ灏 msg.m_filesize = filesize; + // 鍙戦佹秷鎭粰缁熻瀛愮郴缁熶互璁板綍涓存椂鏂囦欢鐨勭粺璁′俊鎭 pgstat_send(&msg, sizeof(msg)); } @@ -1688,17 +1851,37 @@ void pgstat_report_tempfile(size_t filesize) * Tell the collector about memory reservation * ---------- */ +/* + * 鍔熻兘锛氬悜缁熻瀛愮郴缁熸姤鍛婂唴瀛樹繚鐣欑殑缁熻淇℃伅 + * + * 鍙傛暟鍒楄〃锛 + * memReserved锛氬唴瀛樹繚鐣欑殑澶у皬锛堜互MB涓哄崟浣嶏級 + * reserve_or_release锛氫繚鐣欐垨閲婃斁鍐呭瓨鐨勬爣蹇楋紙0琛ㄧず閲婃斁锛1琛ㄧず淇濈暀锛 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庡悜缁熻瀛愮郴缁熸姤鍛婂唴瀛樹繚鐣欑殑缁熻淇℃伅銆 + * 濡傛灉缁熻瀛愮郴缁熺殑濂楁帴瀛楁棤鏁堟垨鑰呮湭鍚敤缁熻璁℃暟锛屽垯鍑芥暟浼氱珛鍗宠繑鍥炪 + * 棣栧厛锛屽嚱鏁颁細璁剧疆娑堟伅澶达紝鍖呮嫭娑堟伅绫诲瀷銆 + * 鐒跺悗锛岃缃秷鎭腑鐨勬暟鎹簱ID銆佸唴瀛樹繚鐣欑殑澶у皬浠ュ強淇濈暀鎴栭噴鏀惧唴瀛樼殑鏍囧織銆 + * 鏈鍚庯紝灏嗘秷鎭彂閫佺粰缁熻瀛愮郴缁熶互璁板綍鍐呭瓨淇濈暀鐨勭粺璁′俊鎭 + */ + void pgstat_report_memReserved(int4 memReserved, int reserve_or_release) { PgStat_MsgMemReserved msg; - - if (g_instance.stat_cxt.pgStatSock == PGINVALID_SOCKET || !u_sess->attr.attr_common.pgstat_track_counts) + // 濡傛灉缁熻瀛愮郴缁熺殑濂楁帴瀛楁棤鏁堟垨鑰呮湭鍚敤缁熻璁℃暟锛岀洿鎺ヨ繑鍥 + if (g_instance.stat_cxt.pgStatSock == PGINVALID_SOCKET || !u_sess->attr.attr_common.pgstat_track_counts) { return; - + } + // 璁剧疆娑堟伅澶 pgstat_setheader(&msg.m_hdr, PGSTAT_MTYPE_MEMRESERVED); + // 璁剧疆鏁版嵁搴揑D msg.m_databaseid = u_sess->proc_cxt.MyDatabaseId; + // 璁剧疆鍐呭瓨淇濈暀鐨勫ぇ灏忥紙浠B涓哄崟浣嶏級 msg.m_memMbytes = memReserved; + // 璁剧疆淇濈暀鎴栭噴鏀惧唴瀛樼殑鏍囧織锛0琛ㄧず閲婃斁锛1琛ㄧず淇濈暀锛 msg.m_reserve_or_release = reserve_or_release; + // 鍙戦佹秷鎭粰缁熻瀛愮郴缁熶互璁板綍鍐呭瓨淇濈暀鐨勭粺璁′俊鎭 pgstat_send(&msg, sizeof(msg)); } @@ -1708,14 +1891,25 @@ void pgstat_report_memReserved(int4 memReserved, int reserve_or_release) * Send some junk data to the collector to increase traffic. * ---------- */ +/* + * 鍔熻兘锛氬悜缁熻瀛愮郴缁熷彂閫 ping 娑堟伅浠ヤ繚鎸佽繛鎺 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庡悜缁熻瀛愮郴缁熷彂閫 ping 娑堟伅浠ヤ繚鎸佽繛鎺ャ傚鏋滅粺璁″瓙绯荤粺鐨勫鎺ュ瓧鏃犳晥锛屽嚱鏁颁細绔嬪嵆杩斿洖銆 + * 棣栧厛锛屽嚱鏁颁細璁剧疆 ping 娑堟伅鐨勬秷鎭ご锛屽寘鎷秷鎭被鍨嬨 + * 鐒跺悗锛屽皢 ping 娑堟伅鍙戦佺粰缁熻瀛愮郴缁熶互淇濇寔杩炴帴銆 + */ + void pgstat_ping(void) { PgStat_MsgDummy msg; - - if (g_instance.stat_cxt.pgStatSock == PGINVALID_SOCKET) + // 濡傛灉缁熻瀛愮郴缁熺殑濂楁帴瀛楁棤鏁堬紝鐩存帴杩斿洖 + if (g_instance.stat_cxt.pgStatSock == PGINVALID_SOCKET) { return; - + } + // 璁剧疆娑堟伅澶 pgstat_setheader(&msg.m_hdr, PGSTAT_MTYPE_DUMMY); + // 鍙戦 ping 娑堟伅缁欑粺璁″瓙绯荤粺浠ヤ繚鎸佽繛鎺 pgstat_send(&msg, sizeof(msg)); } @@ -1726,12 +1920,25 @@ void pgstat_ping(void) * ts specifies the minimum acceptable timestamp for the stats file. * ---------- */ +/* + * 鍔熻兘锛氬彂閫佷竴涓煡璇㈡秷鎭粰缁熻瀛愮郴缁 + * + * 鍙傛暟鍒楄〃锛 + * ts锛氭煡璇㈡椂闂存埑 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庡悜缁熻瀛愮郴缁熷彂閫佹煡璇㈡秷鎭傞鍏堬紝鍑芥暟浼氳缃煡璇㈡秷鎭殑娑堟伅澶达紝鍖呮嫭娑堟伅绫诲瀷銆 + * 鐒跺悗锛屽皢鏌ヨ鏃堕棿鎴虫坊鍔犲埌娑堟伅涓紝骞跺皢娑堟伅鍙戦佺粰缁熻瀛愮郴缁熴 + */ + static void pgstat_send_inquiry(TimestampTz ts) { PgStat_MsgInquiry msg; - + // 璁剧疆娑堟伅澶 pgstat_setheader(&msg.m_hdr, PGSTAT_MTYPE_INQUIRY); + // 娣诲姞鏌ヨ鏃堕棿鎴冲埌娑堟伅涓 msg.inquiry_time = ts; + // 鍙戦佹煡璇㈡秷鎭粰缁熻瀛愮郴缁 pgstat_send(&msg, sizeof(msg)); } @@ -1739,9 +1946,9 @@ static void pgstat_send_inquiry(TimestampTz ts) * Initialize function call usage data. * Called by the executor before invoking a function. */ -void pgstat_init_function_usage(FunctionCallInfoData* fcinfo, PgStat_FunctionCallUsage* fcu) +void pgstat_init_function_usage(FunctionCallInfoData *fcinfo, PgStat_FunctionCallUsage *fcu) { - PgStat_BackendFunctionEntry* htabent = NULL; + PgStat_BackendFunctionEntry *htabent = NULL; bool found = false; errno_t rc; @@ -1761,13 +1968,13 @@ void pgstat_init_function_usage(FunctionCallInfoData* fcinfo, PgStat_FunctionCal hash_ctl.entrysize = sizeof(PgStat_BackendFunctionEntry); hash_ctl.hash = oid_hash; hash_ctl.hcxt = u_sess->stat_cxt.pgStatLocalContext; - u_sess->stat_cxt.pgStatFunctions = hash_create( - "Function stat entries", PGSTAT_FUNCTION_HASH_SIZE, &hash_ctl, HASH_ELEM | HASH_FUNCTION | HASH_CONTEXT); + u_sess->stat_cxt.pgStatFunctions = hash_create("Function stat entries", PGSTAT_FUNCTION_HASH_SIZE, &hash_ctl, + HASH_ELEM | HASH_FUNCTION | HASH_CONTEXT); } /* Get the stats entry for this function, create if necessary */ - htabent = (PgStat_BackendFunctionEntry*)hash_search( - u_sess->stat_cxt.pgStatFunctions, &fcinfo->flinfo->fn_oid, HASH_ENTER, &found); + htabent = (PgStat_BackendFunctionEntry *)hash_search(u_sess->stat_cxt.pgStatFunctions, &fcinfo->flinfo->fn_oid, + HASH_ENTER, &found); if (!found) { rc = memset_s(&htabent->f_counts, sizeof(PgStat_FunctionCounts), 0, sizeof(PgStat_FunctionCounts)); securec_check(rc, "\0", "\0"); @@ -1791,13 +1998,29 @@ void pgstat_init_function_usage(FunctionCallInfoData* fcinfo, PgStat_FunctionCal * * If no entry, return NULL, don't create a new one */ -PgStat_BackendFunctionEntry* find_funcstat_entry(Oid func_id) +/* + * 鍔熻兘锛氭煡鎵剧粰瀹氬嚱鏁癐D鐨勭粺璁′俊鎭潯鐩 + * + * 鍙傛暟鍒楄〃锛 + * func_id锛氳鏌ユ壘鐨勫嚱鏁癐D + * + * 杩斿洖鍊硷細 + * 杩斿洖鎸囧悜PgStat_BackendFunctionEntry缁撴瀯鐨勬寚閽堬紝琛ㄧず鎵惧埌鐨勭粺璁′俊鎭潯鐩紱 + * 濡傛灉鏈壘鍒帮紝鍒欒繑鍥濶ULL銆 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庡湪缁熻淇℃伅涓煡鎵剧粰瀹氬嚱鏁癐D鐨勭粺璁′俊鎭潯鐩傚鏋滄壘鍒板搴旂殑缁熻淇℃伅鏉$洰锛 + * 鍒欒繑鍥炶鏉$洰鐨勬寚閽堬紱鍚﹀垯杩斿洖NULL銆 + */ +PgStat_BackendFunctionEntry *find_funcstat_entry(Oid func_id) { + // 濡傛灉缁熻淇℃伅鐨勫搱甯岃〃涓虹┖锛岃繑鍥濶ULL if (u_sess->stat_cxt.pgStatFunctions == NULL) return NULL; - return (PgStat_BackendFunctionEntry*)hash_search( - u_sess->stat_cxt.pgStatFunctions, (void*)&func_id, HASH_FIND, NULL); + // 鍦ㄥ搱甯岃〃涓煡鎵炬寚瀹氬嚱鏁癐D鐨勭粺璁′俊鎭潯鐩 + return (PgStat_BackendFunctionEntry *)hash_search(u_sess->stat_cxt.pgStatFunctions, (void *)&func_id, HASH_FIND, + NULL); } /* @@ -1809,9 +2032,9 @@ PgStat_BackendFunctionEntry* find_funcstat_entry(Oid func_id) * calls for what the user considers a single call of the function. The * finalize flag should be TRUE on the last call. */ -void pgstat_end_function_usage(PgStat_FunctionCallUsage* fcu, bool finalize) +void pgstat_end_function_usage(PgStat_FunctionCallUsage *fcu, bool finalize) { - PgStat_FunctionCounts* fs = fcu->fs; + PgStat_FunctionCounts *fs = fcu->fs; instr_time f_total; instr_time f_others; instr_time f_self; @@ -1872,7 +2095,7 @@ void pgstat_initstats(Relation rel) /* We only count stats for things that have storage */ if (!(relkind == RELKIND_RELATION || relkind == RELKIND_MATVIEW || relkind == RELKIND_INDEX || - relkind == RELKIND_GLOBAL_INDEX || relkind == RELKIND_TOASTVALUE || RELKIND_IS_SEQUENCE(relkind))) { + relkind == RELKIND_GLOBAL_INDEX || relkind == RELKIND_TOASTVALUE || RELKIND_IS_SEQUENCE(relkind))) { rel->pgstat_info = NULL; return; } @@ -1888,30 +2111,39 @@ void pgstat_initstats(Relation rel) } /* - * Make sure pgStatTabList and pgStatTabHash are initialized. + * 鍔熻兘锛氱‘淇濈粺璁¤〃宸插垵濮嬪寲 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庣‘淇濈粺璁¤〃宸插垵濮嬪寲銆傚鏋滃皻鏈垵濮嬪寲锛屽垯浼氬垎閰嶅唴瀛樺苟杩涜鍒濆鍖栥 + * 鍒濆鍖栧寘鎷垱寤哄搱甯岃〃銆佸垎閰嶅唴瀛樼┖闂寸瓑鎿嶄綔銆 */ static void make_sure_stat_tab_initialized() { HASHCTL ctl; errno_t rc; + // 濡傛灉缁熻琛ㄥ垪琛ㄤ负绌猴紝鍒嗛厤鍐呭瓨骞跺垵濮嬪寲 if (u_sess->stat_cxt.pgStatTabList == NULL) { /* This is first time procedure is called */ - u_sess->stat_cxt.pgStatTabList = - (TabStatusArray*)MemoryContextAllocZero(SESS_GET_MEM_CXT_GROUP(MEMORY_CONTEXT_DFX), sizeof(TabStatusArray)); + u_sess->stat_cxt.pgStatTabList = (TabStatusArray *)MemoryContextAllocZero( + SESS_GET_MEM_CXT_GROUP(MEMORY_CONTEXT_DFX), sizeof(TabStatusArray)); } + // 濡傛灉鍝堝笇琛ㄥ凡瀛樺湪锛岀洿鎺ヨ繑鍥 if (u_sess->stat_cxt.pgStatTabHash != NULL) { return; } + // 濡傛灉鍝堝笇琛ㄤ笂涓嬫枃涓虹┖锛屽垱寤哄搱甯岃〃涓婁笅鏂 if (u_sess->stat_cxt.pgStatTabHashContext == NULL) { u_sess->stat_cxt.pgStatTabHashContext = AllocSetContextCreate(u_sess->top_mem_cxt, "PGStatLookupHashTableContext", ALLOCSET_DEFAULT_SIZES); } else { + // 濡傛灉鍝堝笇琛ㄤ笂涓嬫枃宸插瓨鍦紝閲嶇疆涓婁笅鏂囦互閲婃斁鏃х殑鍝堝笇琛ㄥ唴瀛 MemoryContextReset(u_sess->stat_cxt.pgStatTabHashContext); } + // 鍒濆鍖栧搱甯岃〃鎺у埗淇℃伅 rc = memset_s(&ctl, sizeof(ctl), 0, sizeof(ctl)); securec_check(rc, "\0", "\0"); ctl.keysize = sizeof(PgStat_StatTabKey); @@ -1919,20 +2151,19 @@ static void make_sure_stat_tab_initialized() ctl.hash = tag_hash; ctl.hcxt = u_sess->stat_cxt.pgStatTabHashContext; - u_sess->stat_cxt.pgStatTabHash = hash_create("pgstat sessionid to tsa_entry lookup hash table", - TABSTAT_QUANTUM, - &ctl, - HASH_ELEM | HASH_FUNCTION | HASH_CONTEXT); + // 鍒涘缓鍝堝笇琛 + u_sess->stat_cxt.pgStatTabHash = hash_create("pgstat sessionid to tsa_entry lookup hash table", TABSTAT_QUANTUM, + &ctl, HASH_ELEM | HASH_FUNCTION | HASH_CONTEXT); } /* * get_tabstat_entry - find or create a PgStat_TableStatus entry for rel */ -static PgStat_TableStatus* get_tabstat_entry(Oid rel_id, bool isshared, uint32 statFlag) +static PgStat_TableStatus *get_tabstat_entry(Oid rel_id, bool isshared, uint32 statFlag) { - TabStatHashEntry* hash_entry = NULL; - PgStat_TableStatus* entry = NULL; - TabStatusArray* tsa = NULL; + TabStatHashEntry *hash_entry = NULL; + PgStat_TableStatus *entry = NULL; + TabStatusArray *tsa = NULL; bool found = false; make_sure_stat_tab_initialized(); @@ -1941,7 +2172,7 @@ static PgStat_TableStatus* get_tabstat_entry(Oid rel_id, bool isshared, uint32 s PgStat_StatTabKey rel_key; rel_key.tableid = rel_id; rel_key.statFlag = statFlag; - hash_entry = (TabStatHashEntry*)hash_search(u_sess->stat_cxt.pgStatTabHash, &rel_key, HASH_ENTER, &found); + hash_entry = (TabStatHashEntry *)hash_search(u_sess->stat_cxt.pgStatTabHash, &rel_key, HASH_ENTER, &found); if (found) { return hash_entry->tsa_entry; } @@ -1953,8 +2184,8 @@ static PgStat_TableStatus* get_tabstat_entry(Oid rel_id, bool isshared, uint32 s tsa = u_sess->stat_cxt.pgStatTabList; while (tsa->tsa_used == TABSTAT_QUANTUM) { if (tsa->tsa_next == NULL) { - tsa->tsa_next = (TabStatusArray*)MemoryContextAllocZero( - SESS_GET_MEM_CXT_GROUP(MEMORY_CONTEXT_DFX), sizeof(TabStatusArray)); + tsa->tsa_next = (TabStatusArray *)MemoryContextAllocZero(SESS_GET_MEM_CXT_GROUP(MEMORY_CONTEXT_DFX), + sizeof(TabStatusArray)); } tsa = tsa->tsa_next; } @@ -1981,52 +2212,89 @@ static PgStat_TableStatus* get_tabstat_entry(Oid rel_id, bool isshared, uint32 s * * If no entry, return NULL, don't create a new one */ -PgStat_TableStatus* find_tabstat_entry(Oid rel_id, uint32 statFlag) +/* + * 鍔熻兘锛氭煡鎵剧粺璁¤〃鏉$洰 + * + * 鍙傛暟鍒楄〃锛 + * rel_id锛氬叧绯荤殑Oid + * statFlag锛氱粺璁℃爣蹇 + * + * 杩斿洖鍊硷細 + * 濡傛灉鎵惧埌瀵瑰簲鐨勭粺璁¤〃鏉$洰锛岃繑鍥炶鏉$洰鐨勬寚閽堬紱鍚﹀垯锛岃繑鍥濶ULL銆 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庢煡鎵剧粰瀹氬叧绯诲拰缁熻鏍囧織鐨勭粺璁¤〃鏉$洰銆傞鍏堟鏌ュ搱甯岃〃鏄惁宸茬粡鍒濆鍖栵紝 + * 濡傛灉鏈垵濮嬪寲鍒欒繑鍥濶ULL銆傜劧鍚庢瀯寤烘煡鎵惧叧閿瓧锛屼娇鐢ㄥ搱甯岃〃鏌ユ壘骞惰繑鍥炵浉搴旂殑缁熻琛ㄦ潯鐩 + */ +PgStat_TableStatus *find_tabstat_entry(Oid rel_id, uint32 statFlag) { - TabStatHashEntry* hash_entry; + TabStatHashEntry *hash_entry; /* * There are no entries at all. */ + // 濡傛灉鍝堝笇琛ㄦ湭鍒濆鍖栵紝杩斿洖NULL if (!u_sess->stat_cxt.pgStatTabHash) return NULL; - + // 鏋勫缓鏌ユ壘鍏抽敭瀛 PgStat_StatTabKey rel_key; rel_key.tableid = rel_id; rel_key.statFlag = statFlag; - hash_entry = (TabStatHashEntry*)hash_search(u_sess->stat_cxt.pgStatTabHash, &rel_key, HASH_FIND, NULL); + // 浣跨敤鍝堝笇琛ㄦ煡鎵剧浉搴旂殑缁熻琛ㄦ潯鐩 + hash_entry = (TabStatHashEntry *)hash_search(u_sess->stat_cxt.pgStatTabHash, &rel_key, HASH_FIND, NULL); + // 濡傛灉鏈壘鍒板搴旂殑鏉$洰锛岃繑鍥濶ULL if (!hash_entry) return NULL; - + // 杩斿洖鎵惧埌鐨勭粺璁¤〃鏉$洰鐨勬寚閽 return hash_entry->tsa_entry; } /* * get_tabstat_stack_level - add a new (sub)transaction stack entry if needed */ -static PgStat_SubXactStatus* get_tabstat_stack_level(int nest_level) +/* + * 鍔熻兘锛氳幏鍙栫粺璁′俊鎭瓙浜嬪姟鐘舵佺殑鏍堢骇鍒 + * + * 鍙傛暟鍒楄〃锛 + * nest_level锛氬瓙浜嬪姟鐨勫祵濂楃骇鍒 + * + * 杩斿洖鍊硷細 + * 杩斿洖瀵瑰簲瀛愪簨鍔$姸鎬佺殑鎸囬拡锛屽鏋滀笉瀛樺湪鍒欏垱寤哄苟杩斿洖鏂扮殑瀛愪簨鍔$姸鎬併 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庤幏鍙栨垨鍒涘缓瀛愪簨鍔$姸鎬佺殑鏍堢骇鍒傞鍏堟鏌ュ綋鍓嶅瓙浜嬪姟鐘舵佹爤鏄惁涓虹┖锛 + * 鎴栬呭綋鍓嶆爤椤剁殑瀛愪簨鍔$姸鎬佺殑宓屽绾у埆鏄惁涓庣粰瀹氱殑宓屽绾у埆涓鑷淬傚鏋滀笉涓鑷达紝 + * 鍒欏垱寤烘柊鐨勫瓙浜嬪姟鐘舵佸苟灏嗗叾鎺ㄥ叆鏍堜腑銆 + */ +static PgStat_SubXactStatus *get_tabstat_stack_level(int nest_level) { - PgStat_SubXactStatus* xact_state = NULL; - + PgStat_SubXactStatus *xact_state = NULL; + // 鑾峰彇褰撳墠瀛愪簨鍔$姸鎬佹爤鐨勬爤椤剁姸鎬 xact_state = u_sess->stat_cxt.pgStatXactStack; + // 濡傛灉鏍堜负绌烘垨鑰呮爤椤跺瓙浜嬪姟鐘舵佺殑宓屽绾у埆涓庣粰瀹氱殑宓屽绾у埆涓嶄竴鑷 if (xact_state == NULL || xact_state->nest_level != nest_level) { + // 鍒嗛厤鏂扮殑瀛愪簨鍔$姸鎬 xact_state = - (PgStat_SubXactStatus*)MemoryContextAlloc(u_sess->top_transaction_mem_cxt, sizeof(PgStat_SubXactStatus)); + (PgStat_SubXactStatus *)MemoryContextAlloc(u_sess->top_transaction_mem_cxt, sizeof(PgStat_SubXactStatus)); + // 璁剧疆瀛愪簨鍔$姸鎬佺殑宓屽绾у埆 xact_state->nest_level = nest_level; + // 鍒濆鍖栧瓙浜嬪姟鐘舵佺殑閾捐〃 xact_state->prev = u_sess->stat_cxt.pgStatXactStack; xact_state->first = NULL; + // 灏嗘柊鐨勫瓙浜嬪姟鐘舵佹帹鍏ユ爤涓 u_sess->stat_cxt.pgStatXactStack = xact_state; } + // 杩斿洖瀛愪簨鍔$姸鎬佺殑鎸囬拡 return xact_state; } /* * add_tabstat_xact_level - add a new (sub)transaction state record */ -static void add_tabstat_xact_level(PgStat_TableStatus* pgstat_info, int nest_level) +static void add_tabstat_xact_level(PgStat_TableStatus *pgstat_info, int nest_level) { - PgStat_SubXactStatus* xact_state = NULL; - PgStat_TableXactStatus* trans = NULL; + PgStat_SubXactStatus *xact_state = NULL; + PgStat_TableXactStatus *trans = NULL; /* * If this is the first rel to be modified at the current nest level, we @@ -2035,8 +2303,8 @@ static void add_tabstat_xact_level(PgStat_TableStatus* pgstat_info, int nest_lev xact_state = get_tabstat_stack_level(nest_level); /* Now make a per-table stack entry */ - trans = (PgStat_TableXactStatus*)MemoryContextAllocZero( - u_sess->top_transaction_mem_cxt, sizeof(PgStat_TableXactStatus)); + trans = (PgStat_TableXactStatus *)MemoryContextAllocZero(u_sess->top_transaction_mem_cxt, + sizeof(PgStat_TableXactStatus)); trans->nest_level = nest_level; trans->upper = pgstat_info->trans; trans->parent = pgstat_info; @@ -2048,17 +2316,30 @@ static void add_tabstat_xact_level(PgStat_TableStatus* pgstat_info, int nest_lev /* * pgstat_count_heap_insert - count a tuple insertion of n tuples */ +/* + * 鍔熻兘锛氭洿鏂拌〃鎻掑叆鎿嶄綔鐨勭粺璁′俊鎭 + * + * 鍙傛暟鍒楄〃锛 + * rel锛氬叧绯荤殑鎸囬拡 + * n锛氭彃鍏ョ殑鍏冪粍鏁伴噺 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庢洿鏂板叧绯荤殑鎻掑叆鎿嶄綔鐨勭粺璁′俊鎭傞鍏堟鏌ュ叧绯绘槸鍚﹀叿鏈 PgStat_TableStatus锛 + * 濡傛灉鏄紝鍒欒幏鍙栧綋鍓嶄簨鍔$殑宓屽绾у埆銆傜劧鍚庯紝妫鏌ヤ簨鍔$姸鎬佹槸鍚﹀凡鍒涘缓鎴栬呮槸鍚︿笌褰撳墠浜嬪姟鐨勫祵濂楃骇鍒笉涓鑷达紝 + * 濡傛灉鏄紝鍒欏垱寤烘柊鐨勪簨鍔$姸鎬併傛渶鍚庯紝鏇存柊浜嬪姟鐘舵佷腑鐨勬彃鍏ュ厓缁勬暟閲忋 + */ void pgstat_count_heap_insert(Relation rel, int n) { - PgStat_TableStatus* pgstat_info = rel->pgstat_info; - + PgStat_TableStatus *pgstat_info = rel->pgstat_info; + // 濡傛灉鍏崇郴鍏锋湁 PgStat_TableStatus if (pgstat_info != NULL) { /* We have to log the effect at the proper transactional level */ int nest_level = GetCurrentTransactionNestLevel(); - + // 濡傛灉浜嬪姟鐘舵佷负绌烘垨鑰呬簨鍔$姸鎬佺殑宓屽绾у埆涓庡綋鍓嶄簨鍔$殑宓屽绾у埆涓嶄竴鑷 if (pgstat_info->trans == NULL || pgstat_info->trans->nest_level != nest_level) + // 鍒涘缓鏂扮殑浜嬪姟鐘舵 add_tabstat_xact_level(pgstat_info, nest_level); - + // 鏇存柊浜嬪姟鐘舵佷腑鐨勬彃鍏ュ厓缁勬暟閲 pgstat_info->trans->tuples_inserted += n; pgstat_info->trans->tuples_inserted_accum += n; } @@ -2067,21 +2348,34 @@ void pgstat_count_heap_insert(Relation rel, int n) /* * pgstat_count_heap_update - count a tuple update */ +/* + * 鍔熻兘锛氭洿鏂拌〃鏇存柊鎿嶄綔鐨勭粺璁′俊鎭 + * + * 鍙傛暟鍒楄〃锛 + * rel锛氬叧绯荤殑鎸囬拡 + * hot锛氭槸鍚︿负鐑洿鏂 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庢洿鏂板叧绯荤殑鏇存柊鎿嶄綔鐨勭粺璁′俊鎭傞鍏堟鏌ュ叧绯绘槸鍚﹀叿鏈 PgStat_TableStatus锛 + * 濡傛灉鏄紝鍒欒幏鍙栧綋鍓嶄簨鍔$殑宓屽绾у埆銆傜劧鍚庯紝妫鏌ヤ簨鍔$姸鎬佹槸鍚﹀凡鍒涘缓鎴栬呮槸鍚︿笌褰撳墠浜嬪姟鐨勫祵濂楃骇鍒笉涓鑷达紝 + * 濡傛灉鏄紝鍒欏垱寤烘柊鐨勪簨鍔$姸鎬併傛渶鍚庯紝鏇存柊浜嬪姟鐘舵佷腑鐨勬洿鏂板厓缁勬暟閲忎互鍙婄儹鏇存柊璁℃暟锛堝鏋滄槸鐑洿鏂帮級銆 + */ void pgstat_count_heap_update(Relation rel, bool hot) { - PgStat_TableStatus* pgstat_info = rel->pgstat_info; - + PgStat_TableStatus *pgstat_info = rel->pgstat_info; + // 濡傛灉鍏崇郴鍏锋湁 PgStat_TableStatus if (pgstat_info != NULL) { /* We have to log the effect at the proper transactional level */ int nest_level = GetCurrentTransactionNestLevel(); - + // 濡傛灉浜嬪姟鐘舵佷负绌烘垨鑰呬簨鍔$姸鎬佺殑宓屽绾у埆涓庡綋鍓嶄簨鍔$殑宓屽绾у埆涓嶄竴鑷 if (pgstat_info->trans == NULL || pgstat_info->trans->nest_level != nest_level) + // 鍒涘缓鏂扮殑浜嬪姟鐘舵 add_tabstat_xact_level(pgstat_info, nest_level); - + // 鏇存柊浜嬪姟鐘舵佷腑鐨勬洿鏂板厓缁勬暟閲 pgstat_info->trans->tuples_updated++; pgstat_info->trans->tuples_updated_accum++; - /* t_tuples_hot_updated is nontransactional, so just advance it */ + // 濡傛灉鏄儹鏇存柊锛屽鍔犵儹鏇存柊璁℃暟 if (hot) pgstat_info->t_counts.t_tuples_hot_updated++; } @@ -2090,17 +2384,31 @@ void pgstat_count_heap_update(Relation rel, bool hot) /* * pgstat_count_heap_delete - count a tuple deletion */ +/* + * 鍔熻兘锛氭洿鏂拌〃鍒犻櫎鎿嶄綔鐨勭粺璁′俊鎭 + * + * 鍙傛暟鍒楄〃锛 + * rel锛氬叧绯荤殑鎸囬拡 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庢洿鏂板叧绯荤殑鍒犻櫎鎿嶄綔鐨勭粺璁′俊鎭傞鍏堟鏌ュ叧绯绘槸鍚﹀叿鏈 PgStat_TableStatus锛 + * 濡傛灉鏄紝鍒欒幏鍙栧綋鍓嶄簨鍔$殑宓屽绾у埆銆傜劧鍚庯紝妫鏌ヤ簨鍔$姸鎬佹槸鍚﹀凡鍒涘缓鎴栬呮槸鍚︿笌褰撳墠浜嬪姟鐨勫祵濂楃骇鍒笉涓鑷达紝 + * 濡傛灉鏄紝鍒欏垱寤烘柊鐨勪簨鍔$姸鎬併傛渶鍚庯紝鏇存柊浜嬪姟鐘舵佷腑鐨勫垹闄ゅ厓缁勬暟閲忋 + */ void pgstat_count_heap_delete(Relation rel) { - PgStat_TableStatus* pgstat_info = rel->pgstat_info; + PgStat_TableStatus *pgstat_info = rel->pgstat_info; + // 濡傛灉鍏崇郴鍏锋湁 PgStat_TableStatus if (pgstat_info != NULL) { + // 鑾峰彇褰撳墠浜嬪姟鐨勫祵濂楃骇鍒 /* We have to log the effect at the proper transactional level */ int nest_level = GetCurrentTransactionNestLevel(); - + // 濡傛灉浜嬪姟鐘舵佷负绌烘垨鑰呬簨鍔$姸鎬佺殑宓屽绾у埆涓庡綋鍓嶄簨鍔$殑宓屽绾у埆涓嶄竴鑷 if (pgstat_info->trans == NULL || pgstat_info->trans->nest_level != nest_level) + // 鍒涘缓鏂扮殑浜嬪姟鐘舵 add_tabstat_xact_level(pgstat_info, nest_level); - + // 鏇存柊浜嬪姟鐘舵佷腑鐨勫垹闄ゅ厓缁勬暟閲 pgstat_info->trans->tuples_deleted++; pgstat_info->trans->tuples_deleted_accum++; } @@ -2114,13 +2422,30 @@ void pgstat_count_heap_delete(Relation rel) * the counters can be restored to the saved (pre-truncate) values. Note we do * this on the first truncate in any particular subxact level only. */ -static void pgstat_truncate_save_counters(PgStat_TableXactStatus* trans) +/* + * 鍔熻兘锛氫繚瀛樻埅鏂墠鐨勭粺璁¤鏁板櫒鍊 + * + * 鍙傛暟鍒楄〃锛 + * trans锛氳〃浜嬪姟鐘舵佺殑鎸囬拡 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庝繚瀛樻埅鏂墠鐨勭粺璁¤鏁板櫒鍊笺傚鏋滆〃浜嬪姟鐘舵佺殑 "truncated" 瀛楁涓哄亣锛 + * 鍒欏皢浠ヤ笅缁熻璁℃暟鍣ㄥ间繚瀛樺湪浜嬪姟鐘舵佷腑锛屽苟灏 "truncated" 瀛楁璁剧疆涓虹湡锛 + * - 鎻掑叆鍏冪粍鏁伴噺 (inserted_pre_trunc) + * - 鏇存柊鍏冪粍鏁伴噺 (updated_pre_trunc) + * - 鍒犻櫎鍏冪粍鏁伴噺 (deleted_pre_trunc) + * - 鍘熷湴鏇存柊鍏冪粍鏁伴噺 (inplace_updated_pre_trunc) + */ +static void pgstat_truncate_save_counters(PgStat_TableXactStatus *trans) { + // 濡傛灉浜嬪姟鐘舵佺殑 "truncated" 瀛楁涓哄亣 if (!trans->truncated) { + // 淇濆瓨缁熻璁℃暟鍣ㄥ trans->inserted_pre_trunc = trans->tuples_inserted; trans->updated_pre_trunc = trans->tuples_updated; trans->deleted_pre_trunc = trans->tuples_deleted; trans->inplace_updated_pre_trunc = trans->tuples_inplace_updated; + // 璁剧疆 "truncated" 瀛楁涓虹湡 trans->truncated = true; } } @@ -2128,9 +2453,25 @@ static void pgstat_truncate_save_counters(PgStat_TableXactStatus* trans) /* * pgstat_truncate_restore_counters - restore counters when a truncate aborts */ -static void pgstat_truncate_restore_counters(PgStat_TableXactStatus* trans) +/* + * 鍔熻兘锛氭仮澶嶄繚瀛樼殑鎴柇鍓嶇殑缁熻璁℃暟鍣ㄥ + * + * 鍙傛暟鍒楄〃锛 + * trans锛氳〃浜嬪姟鐘舵佺殑鎸囬拡 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庢仮澶嶄箣鍓嶄繚瀛樼殑鎴柇鍓嶇殑缁熻璁℃暟鍣ㄥ笺傚鏋滆〃浜嬪姟鐘舵佺殑 "truncated" 瀛楁涓虹湡锛 + * 鍒欏皢浠ヤ笅淇濆瓨鐨勭粺璁¤鏁板櫒鍊兼仮澶嶅埌浜嬪姟鐘舵佷腑锛 + * - 鎻掑叆鍏冪粍鏁伴噺 (inserted_pre_trunc) + * - 鏇存柊鍏冪粍鏁伴噺 (updated_pre_trunc) + * - 鍒犻櫎鍏冪粍鏁伴噺 (deleted_pre_trunc) + * - 鍘熷湴鏇存柊鍏冪粍鏁伴噺 (inplace_updated_pre_trunc) + */ +static void pgstat_truncate_restore_counters(PgStat_TableXactStatus *trans) { + // 濡傛灉浜嬪姟鐘舵佺殑 "truncated" 瀛楁涓虹湡 if (trans->truncated) { + // 鎭㈠淇濆瓨鐨勭粺璁¤鏁板櫒鍊 trans->tuples_inserted = trans->inserted_pre_trunc; trans->tuples_updated = trans->updated_pre_trunc; trans->tuples_deleted = trans->deleted_pre_trunc; @@ -2141,9 +2482,22 @@ static void pgstat_truncate_restore_counters(PgStat_TableXactStatus* trans) /* * pgstat_count_truncate - update tuple counters due to truncate */ +/* + * 鍔熻兘锛氭洿鏂颁笌鎴柇鐩稿叧鐨勭粺璁¤鏁板櫒鍊 + * + * 鍙傛暟鍒楄〃锛 + * rel锛氳鎴柇鐨勫叧绯荤殑鎸囬拡 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庢洿鏂颁笌鎴柇鐩稿叧鐨勭粺璁¤鏁板櫒鍊笺傚畠棣栧厛妫鏌ュ叧绯荤殑 PgStat_TableStatus + * 缁撴瀯鏄惁瀛樺湪锛屽苟涓斿湪褰撳墠浜嬪姟宓屽绾у埆涓槸鍚﹀瓨鍦 PgStat_TableXactStatus 缁撴瀯銆 + * 濡傛灉涓嶅瓨鍦紝鍒欎娇鐢 add_tabstat_xact_level 鍑芥暟鍒涘缓鏂扮殑 PgStat_TableXactStatus 缁撴瀯銆 + * 鐒跺悗锛屽畠璋冪敤 pgstat_truncate_save_counters 鍑芥暟淇濆瓨褰撳墠缁熻璁℃暟鍣ㄥ硷紝骞跺皢杩欎簺鍊 + * 閲嶇疆涓洪浂銆 + */ void pgstat_count_truncate(Relation rel) { - PgStat_TableStatus* pgstat_info = rel->pgstat_info; + PgStat_TableStatus *pgstat_info = rel->pgstat_info; if (pgstat_info != NULL) { /* We have to log the effect at the proper transactional level */ @@ -2152,6 +2506,7 @@ void pgstat_count_truncate(Relation rel) if (pgstat_info->trans == NULL || pgstat_info->trans->nest_level != nest_level) add_tabstat_xact_level(pgstat_info, nest_level); + // 淇濆瓨褰撳墠缁熻璁℃暟鍣ㄥ煎苟灏嗗叾閲嶇疆涓洪浂 pgstat_truncate_save_counters(pgstat_info->trans); pgstat_info->trans->tuples_inserted = 0; pgstat_info->trans->tuples_updated = 0; @@ -2163,8 +2518,19 @@ void pgstat_count_truncate(Relation rel) /* * pgstat_count_uheap_update - count a tuple update inplace */ -void -PgstatCountHeapUpdateInplace(Relation rel) +/* + * 鍔熻兘锛氭洿鏂板湪浣嶆洿鏂扮殑鍫嗙粺璁¤鏁板櫒鍊 + * + * 鍙傛暟鍒楄〃锛 + * rel锛氳杩涜鍦ㄤ綅鏇存柊鐨勫叧绯绘寚閽 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庢洿鏂板湪浣嶆洿鏂扮殑鍫嗙殑缁熻璁℃暟鍣ㄥ笺傚畠棣栧厛妫鏌ュ叧绯荤殑 PgStat_TableStatus + * 缁撴瀯鏄惁瀛樺湪锛屽苟涓斿湪褰撳墠浜嬪姟宓屽绾у埆涓槸鍚﹀瓨鍦 PgStat_TableXactStatus 缁撴瀯銆 + * 濡傛灉涓嶅瓨鍦紝鍒欎娇鐢 add_tabstat_xact_level 鍑芥暟鍒涘缓鏂扮殑 PgStat_TableXactStatus 缁撴瀯銆 + * 鐒跺悗锛屽畠閫掑浜 tuples_updated 鍜 tuples_updated_accum 璁℃暟鍣紝骞跺鍔犱簡 tuples_inplace_updated 璁℃暟鍣ㄣ + */ +void PgstatCountHeapUpdateInplace(Relation rel) { PgStat_TableStatus *pgstat_info = rel->pgstat_info; @@ -2177,9 +2543,11 @@ PgstatCountHeapUpdateInplace(Relation rel) } /* increase, similar to pgstat_count_heap_update */ + // 閫掑缁熻璁℃暟鍣 pgstat_info->trans->tuples_updated++; pgstat_info->trans->tuples_updated_accum++; + // 澧炲姞鍦ㄤ綅鏇存柊鐨勮鏁板櫒 pgstat_info->trans->tuples_inplace_updated++; } } @@ -2192,20 +2560,44 @@ PgstatCountHeapUpdateInplace(Relation rel) * rather than increasing, and the change goes straight into the per-table * counter, not into transactional state. */ +/* + * 鍔熻兘锛氭洿鏂板爢鐨勬鍏冪粍璁℃暟鍣ㄥ + * + * 鍙傛暟鍒楄〃锛 + * rel锛氳鏇存柊姝诲厓缁勮鏁板櫒鐨勫叧绯绘寚閽 + * delta锛氳澧炲姞锛堟垨鍑忓皯锛屽鏋滀负璐熸暟锛夊埌姝诲厓缁勮鏁板櫒鐨勫 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庢洿鏂板爢鐨勬鍏冪粍璁℃暟鍣ㄥ笺傚畠棣栧厛妫鏌ュ叧绯荤殑 PgStat_TableStatus 缁撴瀯鏄惁瀛樺湪銆 + * 濡傛灉瀛樺湪锛屽垯浠庤缁撴瀯涓噺鍘 delta 鐨勫硷紝浠ユ洿鏂版鍏冪粍璁℃暟鍣ㄣ + */ void pgstat_update_heap_dead_tuples(Relation rel, int delta) { - PgStat_TableStatus* pgstat_info = rel->pgstat_info; + PgStat_TableStatus *pgstat_info = rel->pgstat_info; - if (pgstat_info != NULL) + if (pgstat_info != NULL) { + // 鍑忓幓 delta 鐨勫间互鏇存柊姝诲厓缁勮鏁板櫒 pgstat_info->t_counts.t_delta_dead_tuples -= delta; + } } /* * pgstat_count_cu/dfs_update - count a cstore/dfs update */ +/* + * 鍔熻兘锛氭洿鏂 CU 鏇存柊璁℃暟鍣ㄥ + * + * 鍙傛暟鍒楄〃锛 + * rel锛氳鏇存柊 CU 鏇存柊璁℃暟鍣ㄧ殑鍏崇郴鎸囬拡 + * n锛氳澧炲姞鍒 CU 鏇存柊璁℃暟鍣ㄧ殑鍊 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庢洿鏂 CU 鏇存柊璁℃暟鍣ㄥ笺傚畠棣栧厛妫鏌ュ叧绯荤殑 PgStat_TableStatus 缁撴瀯鏄惁瀛樺湪銆 + * 濡傛灉瀛樺湪锛屽垯浠庤缁撴瀯涓噺鍘 n 鐨勫硷紝浠ユ洿鏂 CU 鏇存柊璁℃暟鍣ㄣ + */ void pgstat_count_cu_update(Relation rel, int n) { - PgStat_TableStatus* pgstat_info = rel->pgstat_info; + PgStat_TableStatus *pgstat_info = rel->pgstat_info; if (pgstat_info != NULL) { /* We have to log the effect at the proper transactional level */ @@ -2223,24 +2615,49 @@ void pgstat_count_cu_update(Relation rel, int n) /* * pgstat_count_cu/dfs_delete - count a cstore/dfs deletion */ +/* + * 鍔熻兘锛氭洿鏂 CU 鍒犻櫎璁℃暟鍣ㄥ + * + * 鍙傛暟鍒楄〃锛 + * rel锛氳鏇存柊 CU 鍒犻櫎璁℃暟鍣ㄧ殑鍏崇郴鎸囬拡 + * n锛氳澧炲姞鍒 CU 鍒犻櫎璁℃暟鍣ㄧ殑鍊 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庢洿鏂 CU 鍒犻櫎璁℃暟鍣ㄥ笺傚畠棣栧厛妫鏌ュ叧绯荤殑 PgStat_TableStatus 缁撴瀯鏄惁瀛樺湪銆 + * 濡傛灉瀛樺湪锛屽垯浠庤缁撴瀯涓噺鍘 n 鐨勫硷紝浠ユ洿鏂 CU 鍒犻櫎璁℃暟鍣ㄣ + */ void pgstat_count_cu_delete(Relation rel, int n) { - PgStat_TableStatus* pgstat_info = rel->pgstat_info; + // 妫鏌ュ叧绯荤殑 PgStat_TableStatus 缁撴瀯鏄惁瀛樺湪 + PgStat_TableStatus *pgstat_info = rel->pgstat_info; if (pgstat_info != NULL) { + // 鑾峰彇褰撳墠浜嬪姟宓屽绾у埆 /* We have to log the effect at the proper transactional level */ int nest_level = GetCurrentTransactionNestLevel(); - - if (pgstat_info->trans == NULL || pgstat_info->trans->nest_level != nest_level) + // 濡傛灉鍏崇郴鐨 PgStat_TableStatus 缁撴瀯涓嶅瓨鍦ㄦ垨宓屽绾у埆涓嶅尮閰嶏紝鍒欐坊鍔犳柊鐨勫祵濂楃骇鍒 + if (pgstat_info->trans == NULL || pgstat_info->trans->nest_level != nest_level) { add_tabstat_xact_level(pgstat_info, nest_level); + } + // 澧炲姞 CU 鍒犻櫎璁℃暟鍣ㄧ殑鍊硷紝骞剁疮绉埌璁℃暟鍣ㄤ腑 pgstat_info->trans->tuples_deleted += n; pgstat_info->trans->tuples_deleted_accum += n; } } -static inline void init_tuplecount_truncate(PgStat_TableStatus* tabstat) +/* + * 鍔熻兘锛氬垵濮嬪寲琛ㄨ鏁板櫒鐨勬埅鏂悗缁熻鍊 + * + * 鍙傛暟鍒楄〃锛 + * tabstat锛氳鍒濆鍖栨埅鏂悗缁熻鍊肩殑 PgStat_TableStatus 缁撴瀯鎸囬拡 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庡垵濮嬪寲琛ㄨ鏁板櫒鐨勬埅鏂悗缁熻鍊硷紝灏嗗悇缁熻椤归兘璁剧疆涓0銆 + */ +static inline void init_tuplecount_truncate(PgStat_TableStatus *tabstat) { + // 鍒濆鍖栬〃璁℃暟鍣ㄧ殑鎴柇鍚庣粺璁″间负0 /* forget live/dead stats seen by backend thus far */ tabstat->t_counts.t_tuples_inserted_post_truncate = 0; tabstat->t_counts.t_tuples_updated_post_truncate = 0; @@ -2258,7 +2675,7 @@ static inline void init_tuplecount_truncate(PgStat_TableStatus* tabstat) */ void AtEOXact_PgStat(bool isCommit) { - PgStat_SubXactStatus* xact_state = NULL; + PgStat_SubXactStatus *xact_state = NULL; /* * Count transaction commit or abort. (We use counters, not just bools, @@ -2285,12 +2702,12 @@ void AtEOXact_PgStat(bool isCommit) */ xact_state = u_sess->stat_cxt.pgStatXactStack; if (xact_state != NULL) { - PgStat_TableXactStatus* trans = NULL; + PgStat_TableXactStatus *trans = NULL; Assert(xact_state->nest_level == 1); Assert(xact_state->prev == NULL); for (trans = xact_state->first; trans != NULL; trans = trans->next) { - PgStat_TableStatus* tabstat = NULL; + PgStat_TableStatus *tabstat = NULL; Assert(trans->nest_level == 1); Assert(trans->upper == NULL); @@ -2346,7 +2763,7 @@ void AtEOXact_PgStat(bool isCommit) */ void AtEOSubXact_PgStat(bool isCommit, int nestDepth) { - PgStat_SubXactStatus* xact_state = NULL; + PgStat_SubXactStatus *xact_state = NULL; /* * Transfer transactional insert/update counts into the next higher @@ -2354,14 +2771,14 @@ void AtEOSubXact_PgStat(bool isCommit, int nestDepth) */ xact_state = u_sess->stat_cxt.pgStatXactStack; if (xact_state != NULL && xact_state->nest_level >= nestDepth) { - PgStat_TableXactStatus* trans = NULL; - PgStat_TableXactStatus* next_trans = NULL; + PgStat_TableXactStatus *trans = NULL; + PgStat_TableXactStatus *next_trans = NULL; /* delink xact_state from stack immediately to simplify reuse case */ u_sess->stat_cxt.pgStatXactStack = xact_state->prev; for (trans = xact_state->first; trans != NULL; trans = next_trans) { - PgStat_TableStatus* tabstat = NULL; + PgStat_TableStatus *tabstat = NULL; next_trans = trans->next; Assert(trans->nest_level == nestDepth); @@ -2399,7 +2816,7 @@ void AtEOSubXact_PgStat(bool isCommit, int nestDepth) * into the parent level, though, and that might mean * pushing a new entry into the u_sess->stat_cxt.pgStatXactStack. */ - PgStat_SubXactStatus* upper_xact_state = NULL; + PgStat_SubXactStatus *upper_xact_state = NULL; upper_xact_state = get_tabstat_stack_level(nestDepth - 1); trans->next = upper_xact_state->first; @@ -2419,7 +2836,7 @@ void AtEOSubXact_PgStat(bool isCommit, int nestDepth) tabstat->t_counts.t_tuples_deleted += trans->tuples_deleted_accum; tabstat->t_counts.t_tuples_inplace_updated += trans->tuples_inplace_updated_accum; /* inserted tuples are dead, deleted tuples are unaffected */ - tabstat->t_counts.t_delta_dead_tuples += + tabstat->t_counts.t_delta_dead_tuples += trans->tuples_inserted + (trans->tuples_updated - trans->tuples_inplace_updated); tabstat->trans = trans->upper; pfree(trans); @@ -2438,16 +2855,16 @@ void AtEOSubXact_PgStat(bool isCommit, int nestDepth) */ void AtPrepare_PgStat(void) { - PgStat_SubXactStatus* xact_state = NULL; + PgStat_SubXactStatus *xact_state = NULL; xact_state = u_sess->stat_cxt.pgStatXactStack; if (xact_state != NULL) { - PgStat_TableXactStatus* trans = NULL; + PgStat_TableXactStatus *trans = NULL; Assert(xact_state->nest_level == 1); Assert(xact_state->prev == NULL); for (trans = xact_state->first; trans != NULL; trans = trans->next) { - PgStat_TableStatus* tabstat = NULL; + PgStat_TableStatus *tabstat = NULL; TwoPhasePgStatRecord record; Assert(trans->nest_level == 1); @@ -2490,7 +2907,7 @@ void AtPrepare_PgStat(void) */ void PostPrepare_PgStat(void) { - PgStat_SubXactStatus* xact_state = NULL; + PgStat_SubXactStatus *xact_state = NULL; /* * We don't bother to free any of the transactional state, since it's all @@ -2498,10 +2915,10 @@ void PostPrepare_PgStat(void) */ xact_state = u_sess->stat_cxt.pgStatXactStack; if (xact_state != NULL) { - PgStat_TableXactStatus* trans = NULL; + PgStat_TableXactStatus *trans = NULL; for (trans = xact_state->first; trans != NULL; trans = trans->next) { - PgStat_TableStatus* tabstat = NULL; + PgStat_TableStatus *tabstat = NULL; tabstat = trans->parent; tabstat->trans = NULL; @@ -2518,10 +2935,10 @@ void PostPrepare_PgStat(void) * * Load the saved counts into our local pgstats state. */ -void pgstat_twophase_postcommit(TransactionId xid, uint16 info, void* recdata, uint32 len) +void pgstat_twophase_postcommit(TransactionId xid, uint16 info, void *recdata, uint32 len) { - TwoPhasePgStatRecord* rec = (TwoPhasePgStatRecord*)recdata; - PgStat_TableStatus* pgstat_info = NULL; + TwoPhasePgStatRecord *rec = (TwoPhasePgStatRecord *)recdata; + PgStat_TableStatus *pgstat_info = NULL; /* Find or create a tabstat entry for the rel */ pgstat_info = get_tabstat_entry(rec->t_id, rec->t_shared, rec->t_statFlag); @@ -2542,7 +2959,7 @@ void pgstat_twophase_postcommit(TransactionId xid, uint16 info, void* recdata, u pgstat_info->t_counts.t_tuples_inplace_updated_post_truncate += rec->tuples_inplace_updated; } pgstat_info->t_counts.t_delta_live_tuples += rec->tuples_inserted - rec->tuples_deleted; - pgstat_info->t_counts.t_delta_dead_tuples += + pgstat_info->t_counts.t_delta_dead_tuples += (rec->tuples_updated - rec->tuples_inplace_updated) + rec->tuples_deleted; pgstat_info->t_counts.t_changed_tuples += rec->tuples_inserted + rec->tuples_updated + rec->tuples_deleted; } @@ -2553,10 +2970,10 @@ void pgstat_twophase_postcommit(TransactionId xid, uint16 info, void* recdata, u * Load the saved counts into our local pgstats state, but treat them * as aborted. */ -void pgstat_twophase_postabort(TransactionId xid, uint16 info, void* recdata, uint32 len) +void pgstat_twophase_postabort(TransactionId xid, uint16 info, void *recdata, uint32 len) { - TwoPhasePgStatRecord* rec = (TwoPhasePgStatRecord*)recdata; - PgStat_TableStatus* pgstat_info = NULL; + TwoPhasePgStatRecord *rec = (TwoPhasePgStatRecord *)recdata; + PgStat_TableStatus *pgstat_info = NULL; /* Find or create a tabstat entry for the rel */ pgstat_info = get_tabstat_entry(rec->t_id, rec->t_shared, rec->t_statFlag); @@ -2585,7 +3002,7 @@ void pgstat_twophase_postabort(TransactionId xid, uint16 info, void* recdata, ui * collector, so the caller is better off to report ZERO instead. * ---------- */ -PgStat_StatDBEntry* pgstat_fetch_stat_dbentry(Oid dbid) +PgStat_StatDBEntry *pgstat_fetch_stat_dbentry(Oid dbid) { /* * If not done for this transaction, read the statistics collector stats @@ -2596,7 +3013,7 @@ PgStat_StatDBEntry* pgstat_fetch_stat_dbentry(Oid dbid) /* * Lookup the requested database; return NULL if not found */ - return (PgStat_StatDBEntry*)hash_search(u_sess->stat_cxt.pgStatDBHash, (void*)&dbid, HASH_FIND, NULL); + return (PgStat_StatDBEntry *)hash_search(u_sess->stat_cxt.pgStatDBHash, (void *)&dbid, HASH_FIND, NULL); } /* ---------- @@ -2608,11 +3025,11 @@ PgStat_StatDBEntry* pgstat_fetch_stat_dbentry(Oid dbid) * collector, so the caller is better off to report ZERO instead. * ---------- */ -PgStat_StatTabEntry* pgstat_fetch_stat_tabentry(PgStat_StatTabKey* tabkey) +PgStat_StatTabEntry *pgstat_fetch_stat_tabentry(PgStat_StatTabKey *tabkey) { Oid dbid; - PgStat_StatDBEntry* dbentry = NULL; - PgStat_StatTabEntry* tabentry = NULL; + PgStat_StatDBEntry *dbentry = NULL; + PgStat_StatTabEntry *tabentry = NULL; /* * If not done for this transaction, read the statistics collector stats @@ -2624,9 +3041,9 @@ PgStat_StatTabEntry* pgstat_fetch_stat_tabentry(PgStat_StatTabKey* tabkey) * Lookup our database, then look in its table hash table. */ dbid = u_sess->proc_cxt.MyDatabaseId; - dbentry = (PgStat_StatDBEntry*)hash_search(u_sess->stat_cxt.pgStatDBHash, (void*)&dbid, HASH_FIND, NULL); + dbentry = (PgStat_StatDBEntry *)hash_search(u_sess->stat_cxt.pgStatDBHash, (void *)&dbid, HASH_FIND, NULL); if (dbentry != NULL && dbentry->tables != NULL) { - tabentry = (PgStat_StatTabEntry*)hash_search(dbentry->tables, (void*)tabkey, HASH_FIND, NULL); + tabentry = (PgStat_StatTabEntry *)hash_search(dbentry->tables, (void *)tabkey, HASH_FIND, NULL); if (tabentry != NULL) return tabentry; } @@ -2635,9 +3052,9 @@ PgStat_StatTabEntry* pgstat_fetch_stat_tabentry(PgStat_StatTabKey* tabkey) * If we didn't find it, maybe it's a shared table. */ dbid = InvalidOid; - dbentry = (PgStat_StatDBEntry*)hash_search(u_sess->stat_cxt.pgStatDBHash, (void*)&dbid, HASH_FIND, NULL); + dbentry = (PgStat_StatDBEntry *)hash_search(u_sess->stat_cxt.pgStatDBHash, (void *)&dbid, HASH_FIND, NULL); if (dbentry != NULL && dbentry->tables != NULL) { - tabentry = (PgStat_StatTabEntry*)hash_search(dbentry->tables, (void*)tabkey, HASH_FIND, NULL); + tabentry = (PgStat_StatTabEntry *)hash_search(dbentry->tables, (void *)tabkey, HASH_FIND, NULL); if (tabentry != NULL) return tabentry; } @@ -2652,10 +3069,10 @@ PgStat_StatTabEntry* pgstat_fetch_stat_tabentry(PgStat_StatTabKey* tabkey) * the collected statistics for one function or NULL. * ---------- */ -PgStat_StatFuncEntry* pgstat_fetch_stat_funcentry(Oid func_id) +PgStat_StatFuncEntry *pgstat_fetch_stat_funcentry(Oid func_id) { - PgStat_StatDBEntry* dbentry = NULL; - PgStat_StatFuncEntry* funcentry = NULL; + PgStat_StatDBEntry *dbentry = NULL; + PgStat_StatFuncEntry *funcentry = NULL; /* load the stats file if needed */ backend_read_statsfile(); @@ -2663,7 +3080,7 @@ PgStat_StatFuncEntry* pgstat_fetch_stat_funcentry(Oid func_id) /* Lookup our database, then find the requested function. */ dbentry = pgstat_fetch_stat_dbentry(u_sess->proc_cxt.MyDatabaseId); if (dbentry != NULL && dbentry->functions != NULL) { - funcentry = (PgStat_StatFuncEntry*)hash_search(dbentry->functions, (void*)&func_id, HASH_FIND, NULL); + funcentry = (PgStat_StatFuncEntry *)hash_search(dbentry->functions, (void *)&func_id, HASH_FIND, NULL); } return funcentry; @@ -2677,7 +3094,7 @@ PgStat_StatFuncEntry* pgstat_fetch_stat_funcentry(Oid func_id) * a pointer to the global statistics struct. * --------- */ -PgStat_GlobalStats* pgstat_fetch_global(void) +PgStat_GlobalStats *pgstat_fetch_global(void) { backend_read_statsfile(); @@ -2688,10 +3105,9 @@ PgStat_GlobalStats* pgstat_fetch_global(void) * Functions for management of the shared-memory PgBackendStatus array * ------------------------------------------------------------ */ -static THR_LOCAL char* BackendNspRelnameBuffer = NULL; - -PgBackendStatus* PgBackendStatusArray = NULL; +static THR_LOCAL char *BackendNspRelnameBuffer = NULL; +PgBackendStatus *PgBackendStatusArray = NULL; THR_LOCAL XLogStatCollect *g_xlog_stat_shared = NULL; @@ -2725,7 +3141,7 @@ void XLogStatShmemInit(void) * a pointer to WaitCountBuffer. * --------- */ -PgStat_WaitCountStatus* pgstat_fetch_waitcount(void) +PgStat_WaitCountStatus *pgstat_fetch_waitcount(void) { return t_thrd.shemem_ptr_cxt.WaitCountBuffer; } @@ -2757,12 +3173,12 @@ Size BackendStatusShmemSize(void) /** * init memory whose size may be large than INT_MAX by calling func memset_s many times */ -static void MemsetHugeSize(char* dest, const Size size, const char c) +static void MemsetHugeSize(char *dest, const Size size, const char c) { Size block_size = 0x40000000; errno_t rc; Size remain_size = size; - char* ptr = dest; + char *ptr = dest; while (remain_size > 0) { if (remain_size < block_size) { block_size = remain_size; @@ -2783,12 +3199,12 @@ void CreateSharedBackendStatus(void) Size size; bool found = false; int i; - char* buffer = NULL; + char *buffer = NULL; errno_t rc; /* Create or attach to the shared array */ size = mul_size(sizeof(PgBackendStatus), BackendStatusArray_size); - t_thrd.shemem_ptr_cxt.BackendStatusArray = (PgBackendStatus*)ShmemInitStruct("Backend Status Array", size, &found); + t_thrd.shemem_ptr_cxt.BackendStatusArray = (PgBackendStatus *)ShmemInitStruct("Backend Status Array", size, &found); if (!found) { /* @@ -2796,7 +3212,7 @@ void CreateSharedBackendStatus(void) * call MemsetHugeSize because the size may be larger than INT_MAX, * when memset_s can only init memory less than INT_MAX. */ - MemsetHugeSize((char*)t_thrd.shemem_ptr_cxt.BackendStatusArray, size, 0); + MemsetHugeSize((char *)t_thrd.shemem_ptr_cxt.BackendStatusArray, size, 0); /* init mutex for full/slow sql */ TimestampTz current_time = GetCurrentTimestamp(); @@ -2810,7 +3226,7 @@ void CreateSharedBackendStatus(void) /* Create or attach to the shared appname buffer */ size = mul_size(NAMEDATALEN, BackendStatusArray_size); t_thrd.shemem_ptr_cxt.BackendAppnameBuffer = - (char*)ShmemInitStruct("Backend Application Name Buffer", size, &found); + (char *)ShmemInitStruct("Backend Application Name Buffer", size, &found); if (!found) { rc = memset_s(t_thrd.shemem_ptr_cxt.BackendAppnameBuffer, size, 0, size); @@ -2827,13 +3243,13 @@ void CreateSharedBackendStatus(void) /* Create or attach to the shared conninfo buffer */ size = mul_size(CONNECTIONINFO_LEN, BackendStatusArray_size); t_thrd.shemem_ptr_cxt.BackendConninfoBuffer = - (char*)ShmemInitStruct("Backend Connection Information Buffer", size, &found); + (char *)ShmemInitStruct("Backend Connection Information Buffer", size, &found); if (!found) { /* call MemsetHugeSize because the size may be larger than INT_MAX, * when memset_s can only init memory less than INT_MAX. */ - MemsetHugeSize((char*)t_thrd.shemem_ptr_cxt.BackendConninfoBuffer, size, 0); + MemsetHugeSize((char *)t_thrd.shemem_ptr_cxt.BackendConninfoBuffer, size, 0); /* Initialize st_appname pointers. */ buffer = t_thrd.shemem_ptr_cxt.BackendConninfoBuffer; @@ -2846,7 +3262,7 @@ void CreateSharedBackendStatus(void) /* Create or attach to the shared client hostname buffer */ size = mul_size(NAMEDATALEN, BackendStatusArray_size); t_thrd.shemem_ptr_cxt.BackendClientHostnameBuffer = - (char*)ShmemInitStruct("Backend Client Host Name Buffer", size, &found); + (char *)ShmemInitStruct("Backend Client Host Name Buffer", size, &found); if (!found) { rc = memset_s(t_thrd.shemem_ptr_cxt.BackendClientHostnameBuffer, size, 0, size); @@ -2864,12 +3280,11 @@ void CreateSharedBackendStatus(void) t_thrd.shemem_ptr_cxt.BackendActivityBufferSize = mul_size(g_instance.attr.attr_common.pgstat_track_activity_query_size, BackendStatusArray_size); t_thrd.shemem_ptr_cxt.BackendActivityBuffer = - (char*)ShmemInitStruct("Backend Activity Buffer", t_thrd.shemem_ptr_cxt.BackendActivityBufferSize, &found); + (char *)ShmemInitStruct("Backend Activity Buffer", t_thrd.shemem_ptr_cxt.BackendActivityBufferSize, &found); if (!found) { /* call MemsetHugeSize instead because the size may be larger than INT_MAX. */ - MemsetHugeSize( - t_thrd.shemem_ptr_cxt.BackendActivityBuffer, t_thrd.shemem_ptr_cxt.BackendActivityBufferSize, 0); + MemsetHugeSize(t_thrd.shemem_ptr_cxt.BackendActivityBuffer, t_thrd.shemem_ptr_cxt.BackendActivityBufferSize, 0); /* Initialize st_activity pointers. */ buffer = t_thrd.shemem_ptr_cxt.BackendActivityBuffer; @@ -2881,7 +3296,8 @@ void CreateSharedBackendStatus(void) /* Create or attach to the shared array */ size = sizeof(PgStat_WaitCountStatus); - t_thrd.shemem_ptr_cxt.WaitCountBuffer = (PgStat_WaitCountStatus*)ShmemInitStruct("Wait Count Buffer", size, &found); + t_thrd.shemem_ptr_cxt.WaitCountBuffer = + (PgStat_WaitCountStatus *)ShmemInitStruct("Wait Count Buffer", size, &found); if (!found) { /* initialize */ rc = memset_s(t_thrd.shemem_ptr_cxt.WaitCountBuffer, size, 0, size); @@ -2890,7 +3306,7 @@ void CreateSharedBackendStatus(void) /* Create or attach to the shared relname buffer */ size = mul_size(NAMEDATALEN * 2, BackendStatusArray_size); - BackendNspRelnameBuffer = (char*)ShmemInitStruct("Backend Namespace Relname Buffer", size, &found); + BackendNspRelnameBuffer = (char *)ShmemInitStruct("Backend Namespace Relname Buffer", size, &found); if (!found) { rc = memset_s(BackendNspRelnameBuffer, size, 0, size); securec_check(rc, "\0", "\0"); @@ -2917,10 +3333,10 @@ static int GetAuxProcStatEntryIndex() return index; } -static const char* REMOTE_CONN_TYPET[REMOTE_CONN_GTM_TOOL + 1] = { - "app", "coordinator", "datanode", "gtm", "gtm_proxy", "inetrnal_tool", "gtm_tool"}; +static const char *REMOTE_CONN_TYPET[REMOTE_CONN_GTM_TOOL + 1] = {"app", "coordinator", "datanode", "gtm", + "gtm_proxy", "inetrnal_tool", "gtm_tool"}; -const char* remote_conn_type_string(int remote_conn_type) +const char *remote_conn_type_string(int remote_conn_type) { Assert(remote_conn_type >= REMOTE_CONN_APP && remote_conn_type <= REMOTE_CONN_GTM_TOOL); return REMOTE_CONN_TYPET[remote_conn_type]; @@ -2945,8 +3361,8 @@ void pgstat_initialize(void) if (t_thrd.proc_cxt.MyBackendId != InvalidBackendId) { Assert(t_thrd.proc_cxt.MyBackendId >= 1 && t_thrd.proc_cxt.MyBackendId <= (g_instance.attr.attr_common.enable_thread_pool - ? GLOBAL_RESERVE_SESSION_NUM - : g_instance.shmem_cxt.MaxBackends)); + ? GLOBAL_RESERVE_SESSION_NUM + : g_instance.shmem_cxt.MaxBackends)); t_thrd.shemem_ptr_cxt.MyBEEntry = &t_thrd.shemem_ptr_cxt.BackendStatusArray[t_thrd.proc_cxt.MyBackendId - 1]; } else { // Auxiliary thread @@ -2978,8 +3394,8 @@ void pgstat_initialize_session(void) Assert(t_thrd.shemem_ptr_cxt.BackendStatusArray); Assert(u_sess->session_ctr_index >= GLOBAL_RESERVE_SESSION_NUM && u_sess->session_ctr_index < MAX_BACKEND_SLOT); Assert(t_thrd.proc_cxt.MyBackendId != InvalidBackendId); - Assert( - t_thrd.shemem_ptr_cxt.MyBEEntry == &t_thrd.shemem_ptr_cxt.BackendStatusArray[t_thrd.proc_cxt.MyBackendId - 1]); + Assert(t_thrd.shemem_ptr_cxt.MyBEEntry == + &t_thrd.shemem_ptr_cxt.BackendStatusArray[t_thrd.proc_cxt.MyBackendId - 1]); /* * pool worker reports being coupled to one session @@ -3045,7 +3461,7 @@ void pgstat_bestart(void) TimestampTz proc_start_timestamp; Oid userid = InvalidOid; SockAddr clientaddr; - volatile PgBackendStatus* beentry = NULL; + volatile PgBackendStatus *beentry = NULL; errno_t rc = 0; /* @@ -3106,7 +3522,7 @@ void pgstat_bestart(void) beentry->st_xact_start_timestamp = 0; beentry->st_databaseid = u_sess->proc_cxt.MyDatabaseId; beentry->st_userid = userid; - rc = memcpy_s((void*)&beentry->st_clientaddr, sizeof(SockAddr), &clientaddr, sizeof(clientaddr)); + rc = memcpy_s((void *)&beentry->st_clientaddr, sizeof(SockAddr), &clientaddr, sizeof(clientaddr)); securec_check(rc, "\0", "\0"); beentry->st_clienthostname[0] = '\0'; beentry->st_state = STATE_UNDEFINED; @@ -3172,44 +3588,37 @@ void pgstat_bestart(void) if (u_sess->proc_cxt.MyProcPort != NULL) { if (u_sess->proc_cxt.MyProcPort->is_logic_conn) { if (u_sess->proc_cxt.MyProcPort->libcomm_addrinfo != NULL) { - rc = memcpy_s((void*)&beentry->remote_info.remote_name, - NAMEDATALEN, - u_sess->proc_cxt.MyProcPort->libcomm_addrinfo->nodename, - NAMEDATALEN); + rc = memcpy_s((void *)&beentry->remote_info.remote_name, NAMEDATALEN, + u_sess->proc_cxt.MyProcPort->libcomm_addrinfo->nodename, NAMEDATALEN); securec_check(rc, "\0", "\0"); - rc = memcpy_s((void*)&beentry->remote_info.remote_ip, - MAX_IP_STR_LEN, - u_sess->proc_cxt.MyProcPort->libcomm_addrinfo->host, - strlen(u_sess->proc_cxt.MyProcPort->libcomm_addrinfo->host) + 1); + rc = memcpy_s((void *)&beentry->remote_info.remote_ip, MAX_IP_STR_LEN, + u_sess->proc_cxt.MyProcPort->libcomm_addrinfo->host, + strlen(u_sess->proc_cxt.MyProcPort->libcomm_addrinfo->host) + 1); securec_check(rc, "\0", "\0"); - rc = memcpy_s((void*)&beentry->remote_info.remote_port, - MAX_PORT_LEN, - &(u_sess->proc_cxt.MyProcPort->libcomm_addrinfo->listen_port), - MAX_PORT_LEN); + rc = memcpy_s((void *)&beentry->remote_info.remote_port, MAX_PORT_LEN, + &(u_sess->proc_cxt.MyProcPort->libcomm_addrinfo->listen_port), MAX_PORT_LEN); securec_check(rc, "\0", "\0"); beentry->remote_info.socket = -1; beentry->remote_info.logic_id = u_sess->proc_cxt.MyProcPort->gs_sock.sid; } } else { if (u_sess->proc_cxt.MyProcPort->sock >= 0) { - const char* remote_node = remote_conn_type_string(u_sess->attr.attr_common.remoteConnType); - rc = memcpy_s( - (void*)&beentry->remote_info.remote_name, NAMEDATALEN, remote_node, strlen(remote_node) + 1); + const char *remote_node = remote_conn_type_string(u_sess->attr.attr_common.remoteConnType); + rc = memcpy_s((void *)&beentry->remote_info.remote_name, NAMEDATALEN, remote_node, + strlen(remote_node) + 1); securec_check(rc, "\0", "\0"); if (u_sess->proc_cxt.MyProcPort->remote_host != NULL) { - rc = memcpy_s((void*)&beentry->remote_info.remote_ip, - MAX_IP_STR_LEN, - u_sess->proc_cxt.MyProcPort->remote_host, - strlen(u_sess->proc_cxt.MyProcPort->remote_host) + 1); + rc = memcpy_s((void *)&beentry->remote_info.remote_ip, MAX_IP_STR_LEN, + u_sess->proc_cxt.MyProcPort->remote_host, + strlen(u_sess->proc_cxt.MyProcPort->remote_host) + 1); securec_check(rc, "\0", "\0"); } if (u_sess->proc_cxt.MyProcPort->remote_port != NULL && u_sess->proc_cxt.MyProcPort->remote_port[0] != '\0') { - rc = memcpy_s((void*)&beentry->remote_info.remote_port, - MAX_PORT_LEN, - u_sess->proc_cxt.MyProcPort->remote_port, - strlen(u_sess->proc_cxt.MyProcPort->remote_port) + 1); + rc = memcpy_s((void *)&beentry->remote_info.remote_port, MAX_PORT_LEN, + u_sess->proc_cxt.MyProcPort->remote_port, + strlen(u_sess->proc_cxt.MyProcPort->remote_port) + 1); securec_check(rc, "\0", "\0"); } @@ -3238,7 +3647,7 @@ void pgstat_bestart(void) * only if light-weight lock information is never accessed by other backends, * this backend can exit. */ -static void WaitUntilLWLockInfoNeverAccess(volatile PgBackendStatus* backendEntry) +static void WaitUntilLWLockInfoNeverAccess(volatile PgBackendStatus *backendEntry) { START_CRIT_SECTION(); @@ -3266,7 +3675,7 @@ static void WaitUntilLWLockInfoNeverAccess(volatile PgBackendStatus* backendEntr */ void pgstat_couple_decouple_session(bool is_couple) { - volatile PgBackendStatus* beentry = NULL; + volatile PgBackendStatus *beentry = NULL; Assert(u_sess->session_id != 0); /* @@ -3305,7 +3714,7 @@ void pgstat_couple_decouple_session(bool is_couple) */ static void pgstat_beshutdown_hook(int code, Datum arg) { - volatile PgBackendStatus* beentry = t_thrd.shemem_ptr_cxt.MyBEEntry; + volatile PgBackendStatus *beentry = t_thrd.shemem_ptr_cxt.MyBEEntry; /* * If we got as far as discovering our own database ID, we can report what @@ -3351,12 +3760,12 @@ static void pgstat_beshutdown_hook(int code, Datum arg) */ if (IS_THREAD_POOL_WORKER && u_sess->session_ctr_index >= GLOBAL_RESERVE_SESSION_NUM && u_sess->session_ctr_index < MAX_BACKEND_SLOT) { - release_statement_context(&t_thrd.shemem_ptr_cxt.BackendStatusArray[u_sess->session_ctr_index], - __FUNCTION__, __LINE__); + release_statement_context(&t_thrd.shemem_ptr_cxt.BackendStatusArray[u_sess->session_ctr_index], __FUNCTION__, + __LINE__); } if (t_thrd.proc_cxt.MyBackendId != InvalidBackendId) { release_statement_context(&t_thrd.shemem_ptr_cxt.BackendStatusArray[t_thrd.proc_cxt.MyBackendId - 1], - __FUNCTION__, __LINE__); + __FUNCTION__, __LINE__); } else { release_statement_context(t_thrd.shemem_ptr_cxt.MyBEEntry, __FUNCTION__, __LINE__); } @@ -3381,7 +3790,7 @@ void pgstat_beshutdown_session(int ctrl_index) { /* proc_exit already release the slot of MyBeEntry, cannot release again */ if (!t_thrd.proc_cxt.proc_exit_inprogress) { - volatile PgBackendStatus* beentry = &t_thrd.shemem_ptr_cxt.BackendStatusArray[ctrl_index]; + volatile PgBackendStatus *beentry = &t_thrd.shemem_ptr_cxt.BackendStatusArray[ctrl_index]; /* * If we got as far as discovering our own database ID, we can report what @@ -3420,7 +3829,7 @@ void pgstat_beshutdown_session(int ctrl_index) * if t_thrd.proc_cxt.proc_exit_inprogress is true, thread backend entry and * session backend entry can be reused by other backend(CleanupInvalidationState * is called before), so backend entry cann't be accessed during this stage. - * when false, just case that thread pool worker is detaching or closing session, + * when false, just case that thread pool worker is detaching or closing session, * so we need to release statemement context. */ release_statement_context(&t_thrd.shemem_ptr_cxt.BackendStatusArray[ctrl_index], __FUNCTION__, __LINE__); @@ -3476,9 +3885,9 @@ void pgstat_beshutdown_session(int ctrl_index) * ensure the compiler doesn't try to get cute. * ---------- */ -void pgstat_report_activity(BackendState state, const char* cmd_str) +void pgstat_report_activity(BackendState state, const char *cmd_str) { - volatile PgBackendStatus* beentry = t_thrd.shemem_ptr_cxt.MyBEEntry; + volatile PgBackendStatus *beentry = t_thrd.shemem_ptr_cxt.MyBEEntry; TimestampTz start_timestamp; TimestampTz current_timestamp; int len = 0; @@ -3541,16 +3950,16 @@ void pgstat_report_activity(BackendState state, const char* cmd_str) /* If mask successfully, store the mask_string. Otherwise, the cmd_str is recorded. */ if (mask_string == NULL) { - rc = memcpy_s((char*)beentry->st_activity, g_instance.attr.attr_common.pgstat_track_activity_query_size, - cmd_str, len); + rc = memcpy_s((char *)beentry->st_activity, g_instance.attr.attr_common.pgstat_track_activity_query_size, + cmd_str, len); securec_check(rc, "\0", "\0"); } else { int copy_len = strlen(mask_string); if (len < copy_len) { copy_len = len; } - rc = memcpy_s((char*)beentry->st_activity, g_instance.attr.attr_common.pgstat_track_activity_query_size, - mask_string, copy_len); + rc = memcpy_s((char *)beentry->st_activity, g_instance.attr.attr_common.pgstat_track_activity_query_size, + mask_string, copy_len); securec_check(rc, "\0", "\0"); pfree(mask_string); } @@ -3568,9 +3977,9 @@ void pgstat_report_activity(BackendState state, const char* cmd_str) * Called to update our application name. * ---------- */ -void pgstat_report_appname(const char* appname) +void pgstat_report_appname(const char *appname) { - volatile PgBackendStatus* beentry = t_thrd.shemem_ptr_cxt.MyBEEntry; + volatile PgBackendStatus *beentry = t_thrd.shemem_ptr_cxt.MyBEEntry; int len; errno_t rc; @@ -3588,7 +3997,7 @@ void pgstat_report_appname(const char* appname) pgstat_increment_changecount_before(beentry); if (len > 0) { - rc = memcpy_s((char*)beentry->st_appname, len, appname, len); + rc = memcpy_s((char *)beentry->st_appname, len, appname, len); securec_check(rc, "\0", "\0"); } @@ -3603,9 +4012,9 @@ void pgstat_report_appname(const char* appname) * Called to update our connection info. * ---------- */ -void pgstat_report_conninfo(const char* conninfo) +void pgstat_report_conninfo(const char *conninfo) { - volatile PgBackendStatus* beentry = t_thrd.shemem_ptr_cxt.MyBEEntry; + volatile PgBackendStatus *beentry = t_thrd.shemem_ptr_cxt.MyBEEntry; int len; errno_t rc; @@ -3623,7 +4032,7 @@ void pgstat_report_conninfo(const char* conninfo) pgstat_increment_changecount_before(beentry); if (len > 0) { - rc = memcpy_s((char*)beentry->st_conninfo, len, conninfo, len); + rc = memcpy_s((char *)beentry->st_conninfo, len, conninfo, len); securec_check(rc, "\0", "\0"); } @@ -3638,7 +4047,7 @@ void pgstat_report_conninfo(const char* conninfo) */ void pgstat_report_xact_timestamp(TimestampTz tstamp) { - volatile PgBackendStatus* beentry = t_thrd.shemem_ptr_cxt.MyBEEntry; + volatile PgBackendStatus *beentry = t_thrd.shemem_ptr_cxt.MyBEEntry; if (!u_sess->attr.attr_common.pgstat_track_activities || (beentry == NULL)) return; @@ -3653,43 +4062,81 @@ void pgstat_report_xact_timestamp(TimestampTz tstamp) pgstat_increment_changecount_after(beentry); } +/* + * 鍔熻兘锛氭眹鎶ュ叏灞浼氳瘽ID + * + * 鍙傛暟鍒楄〃锛 + * globalSessionId锛氬叏灞浼氳瘽ID + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庢眹鎶ュ叏灞浼氳瘽ID锛屼絾浠呭湪鍚敤澶氳妭鐐规ā寮忎笖浼氳瘽ID涓嶄负0鏃舵墠鎵ц銆 + * 棣栧厛锛岃幏鍙栧綋鍓嶅悗绔繘绋嬬殑鐘舵佷俊鎭紝鐒跺悗鏇存柊鍏朵腑鐨勫叏灞浼氳瘽ID淇℃伅銆 + */ void pgstat_report_global_session_id(GlobalSessionId globalSessionId) { #ifndef ENABLE_MULTIPLE_NODES - return; + return; // 涓嶅惎鐢ㄥ鑺傜偣妯″紡锛岀洿鎺ヨ繑鍥 #endif - volatile PgBackendStatus* beentry = t_thrd.shemem_ptr_cxt.MyBEEntry; - + volatile PgBackendStatus *beentry = t_thrd.shemem_ptr_cxt.MyBEEntry; + // 濡傛灉鏈畾涔塸gstate璺熻釜鎴栦細璇滻D涓0锛屽垯鐩存帴杩斿洖 if (IS_PGSTATE_TRACK_UNDEFINE || globalSessionId.sessionId == 0) return; + // 鍦ㄦ洿鏂板叏灞浼氳瘽ID涔嬪墠锛屽鍔犵姸鎬佷俊鎭殑鏇存敼璁℃暟鍣 pgstat_increment_changecount_before(beentry); + // 鏇存柊鐘舵佷俊鎭腑鐨勫叏灞浼氳瘽ID淇℃伅 beentry->globalSessionId.sessionId = globalSessionId.sessionId; beentry->globalSessionId.nodeId = globalSessionId.nodeId; beentry->globalSessionId.seq = globalSessionId.seq; + // 鍦ㄦ洿鏂板叏灞浼氳瘽ID涔嬪悗锛屽鍔犵姸鎬佷俊鎭殑鏇存敼璁℃暟鍣 pgstat_increment_changecount_after(beentry); } +/* + * 鍔熻兘锛氭眹鎶ュ敮涓SQL鏍囪瘑 + * + * 鍙傛暟鍒楄〃锛 + * resetUniqueSql锛氭槸鍚﹂噸缃敮涓SQL鏍囪瘑 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庢眹鎶ュ敮涓SQL鏍囪瘑锛屼絾浠呭湪pgstate璺熻釜琚畾涔夋椂鎵ц銆 + * 鏍规嵁resetUniqueSql鍙傛暟鐨勫硷紝鍙互閫夋嫨閲嶇疆鎴栨洿鏂板敮涓SQL鏍囪瘑銆 + * 濡傛灉resetUniqueSql涓虹湡锛屽垯灏嗗敮涓SQL鏍囪瘑閲嶇疆涓0銆 + * 鍚﹀垯锛屽皢鍞竴SQL鏍囪瘑璁剧疆涓哄綋鍓嶄細璇濈殑鍞竴SQL淇℃伅銆 + */ void pgstat_report_unique_sql_id(bool resetUniqueSql) { - volatile PgBackendStatus* beentry = t_thrd.shemem_ptr_cxt.MyBEEntry; - + volatile PgBackendStatus *beentry = t_thrd.shemem_ptr_cxt.MyBEEntry; + // 濡傛灉pgstate璺熻釜鏈畾涔夛紝鍒欑洿鎺ヨ繑鍥 if (IS_PGSTATE_TRACK_UNDEFINE) return; if (resetUniqueSql) { + // 濡傛灉闇瑕侀噸缃敮涓SQL鏍囪瘑锛屽垯灏嗗叾璁剧疆涓0 beentry->st_unique_sql_key.unique_sql_id = 0; beentry->st_unique_sql_key.cn_id = 0; beentry->st_unique_sql_key.user_id = 0; } else { + // 鍚﹀垯锛屽皢鍞竴SQL鏍囪瘑璁剧疆涓哄綋鍓嶄細璇濈殑鍞竴SQL淇℃伅 beentry->st_unique_sql_key.unique_sql_id = u_sess->unique_sql_cxt.unique_sql_id; beentry->st_unique_sql_key.cn_id = u_sess->unique_sql_cxt.unique_sql_cn_id; beentry->st_unique_sql_key.user_id = u_sess->unique_sql_cxt.unique_sql_user_id; } } +/* + * 鍔熻兘锛氭眹鎶ユ煡璇D + * + * 鍙傛暟鍒楄〃锛 + * queryid锛氳姹囨姤鐨勬煡璇D + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庢眹鎶ユ煡璇D锛屼絾浠呭湪pgstate璺熻釜琚畾涔夋椂鎵ц銆 + * 灏嗘煡璇D璁剧疆涓烘寚瀹氱殑queryid鍊笺 + */ void pgstat_report_queryid(uint64 queryid) { - volatile PgBackendStatus* beentry = t_thrd.shemem_ptr_cxt.MyBEEntry; + volatile PgBackendStatus *beentry = t_thrd.shemem_ptr_cxt.MyBEEntry; + // 濡傛灉pgstate璺熻釜鏈畾涔夛紝鍒欑洿鎺ヨ繑鍥 if (IS_PGSTATE_TRACK_UNDEFINE) return; @@ -3698,39 +4145,76 @@ void pgstat_report_queryid(uint64 queryid) * may modify, there seems no need to bother with the st_changecount * protocol. The update must appear atomic in any case. */ + // 璁剧疆鏌ヨID涓烘寚瀹氱殑queryid鍊 beentry->st_queryid = queryid; } +/* + * 鍔熻兘锛氭眹鎶ヨ拷韪狪D + * + * 鍙傛暟鍒楄〃锛 + * trace_cxt锛氳拷韪笂涓嬫枃 + * is_report_trace_id锛氭槸鍚﹁姹囨姤杩借釜ID + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庢眹鎶ヨ拷韪狪D锛屼絾浠呭湪pgstate璺熻釜琚畾涔夋椂鎵ц銆 + * 濡傛灉is_report_trace_id涓簍rue锛屽垯灏嗚拷韪狪D璁剧疆涓簍race_cxt涓殑鍊笺 + */ void pgstat_report_trace_id(knl_u_trace_context *trace_cxt, bool is_report_trace_id) { - volatile PgBackendStatus* beentry = t_thrd.shemem_ptr_cxt.MyBEEntry; + volatile PgBackendStatus *beentry = t_thrd.shemem_ptr_cxt.MyBEEntry; + // 濡傛灉pgstate璺熻釜鏈畾涔夛紝鍒欑洿鎺ヨ繑鍥 if (IS_PGSTATE_TRACK_UNDEFINE) return; + // 濡傛灉is_report_trace_id涓簍rue锛屽垯灏嗚拷韪狪D璁剧疆涓簍race_cxt涓殑鍊 if (is_report_trace_id) { - errno_t rc = - memcpy_s((void*)beentry->trace_cxt.trace_id, MAX_TRACE_ID_SIZE, trace_cxt->trace_id, - strlen(trace_cxt->trace_id) + 1); + errno_t rc = memcpy_s((void *)beentry->trace_cxt.trace_id, MAX_TRACE_ID_SIZE, trace_cxt->trace_id, + strlen(trace_cxt->trace_id) + 1); securec_check(rc, "\0", "\0"); } } +/* + * 鍔熻兘锛氭眹鎶ヤ綔涓欼D + * + * 鍙傛暟鍒楄〃锛 + * jobid锛氫綔涓欼D + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庢眹鎶ヤ綔涓欼D锛屼絾浠呭湪pgstate璺熻釜琚畾涔夋椂鎵ц銆 + * 灏嗕綔涓欼D璁剧疆涓哄綋鍓嶅悗绔繘绋嬬殑浣滀笟ID銆 + */ void pgstat_report_jobid(uint64 jobid) { - volatile PgBackendStatus* beentry = t_thrd.shemem_ptr_cxt.MyBEEntry; + volatile PgBackendStatus *beentry = t_thrd.shemem_ptr_cxt.MyBEEntry; + // 濡傛灉pgstate璺熻釜鏈畾涔夛紝鍒欑洿鎺ヨ繑鍥 if (IS_PGSTATE_TRACK_UNDEFINE) return; /* * Update jobid when it starts */ + // 灏嗕綔涓欼D璁剧疆涓哄綋鍓嶅悗绔繘绋嬬殑浣滀笟ID beentry->st_jobid = jobid; } +/* + * 鍔熻兘锛氭眹鎶ョ埗浼氳瘽ID鍜岀嚎绋嬬骇鍒 + * + * 鍙傛暟鍒楄〃锛 + * sessionid锛氫細璇滻D + * level锛氱嚎绋嬬骇鍒 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庢眹鎶ョ埗浼氳瘽ID鍜岀嚎绋嬬骇鍒紝浣嗕粎鍦╬gstate璺熻釜琚畾涔夋椂鎵ц銆 + * 璁剧疆褰撳墠鍚庣杩涚▼鐨勪細璇滻D銆佺埗浼氳瘽ID鍜岀嚎绋嬬骇鍒 + */ void pgstat_report_parent_sessionid(uint64 sessionid, uint32 level) { - volatile PgBackendStatus* beentry = t_thrd.shemem_ptr_cxt.MyBEEntry; + volatile PgBackendStatus *beentry = t_thrd.shemem_ptr_cxt.MyBEEntry; + // 濡傛灉pgstate璺熻釜鏈畾涔夛紝鍒欑洿鎺ヨ繑鍥 if (IS_PGSTATE_TRACK_UNDEFINE) return; @@ -3739,6 +4223,7 @@ void pgstat_report_parent_sessionid(uint64 sessionid, uint32 level) * may modify, there seems no need to bother with the st_changecount * protocol. The update must appear atomic in any case. */ + // 璁剧疆褰撳墠鍚庣杩涚▼鐨勪細璇滻D銆佺埗浼氳瘽ID鍜岀嚎绋嬬骇鍒 beentry->st_sessionid = sessionid; beentry->st_parent_sessionid = sessionid; beentry->st_thread_level = level; @@ -3756,7 +4241,7 @@ void pgstat_report_parent_sessionid(uint64 sessionid, uint32 level) */ void pgstat_report_connected_gtm_host(GtmHostIndex gtm_host) { - volatile PgBackendStatus* beentry = t_thrd.shemem_ptr_cxt.MyBEEntry; + volatile PgBackendStatus *beentry = t_thrd.shemem_ptr_cxt.MyBEEntry; if (beentry == NULL) return; @@ -3784,7 +4269,7 @@ void pgstat_report_connected_gtm_host(GtmHostIndex gtm_host) */ void pgstat_report_connected_gtm_timeline(GTM_Timeline gtm_timeline) { - volatile PgBackendStatus* beentry = t_thrd.shemem_ptr_cxt.MyBEEntry; + volatile PgBackendStatus *beentry = t_thrd.shemem_ptr_cxt.MyBEEntry; if (beentry == NULL) return; @@ -3799,10 +4284,21 @@ void pgstat_report_connected_gtm_timeline(GTM_Timeline gtm_timeline) beentry->st_gtmtimeline = gtm_timeline; } +/* + * 鍔熻兘锛氭眹鎶MP ID + * + * 鍙傛暟鍒楄〃锛 + * smpid锛歋MP ID + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庢眹鎶MP ID锛屼絾浠呭湪pgstate璺熻釜琚畾涔夋椂鎵ц銆 + * 璁剧疆褰撳墠鍚庣杩涚▼鐨凷MP ID銆 + */ void pgstat_report_smpid(uint32 smpid) { - volatile PgBackendStatus* beentry = t_thrd.shemem_ptr_cxt.MyBEEntry; + volatile PgBackendStatus *beentry = t_thrd.shemem_ptr_cxt.MyBEEntry; + // 濡傛灉pgstate璺熻釜鏈畾涔夛紝鍒欑洿鎺ヨ繑鍥 if (IS_PGSTATE_TRACK_UNDEFINE) return; @@ -3811,32 +4307,42 @@ void pgstat_report_smpid(uint32 smpid) * may modify, there seems no need to bother with the st_changecount * protocol. The update must appear atomic in any case. */ + // 璁剧疆褰撳墠鍚庣杩涚▼鐨凷MP ID beentry->st_smpid = smpid; } /* * report blocking session into waitLockThrd's PgBackendStatus */ -void pgstat_report_blocksid(void* waitLockThrd, uint64 blockSessionId) +/* + * 鍔熻兘锛氭眹鎶ラ攣闃诲鐨勪細璇滻D + * + * 鍙傛暟鍒楄〃锛 + * waitLockThrd锛氱瓑寰呴攣鐨勭嚎绋嬫寚閽 + * blockSessionId锛氶樆濉炵殑浼氳瘽ID + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庢眹鎶ラ攣闃诲鐨勪細璇滻D锛屼絾浠呭湪pgstate璺熻釜琚畾涔夋椂鎵ц銆 + * 璁剧疆绾跨▼鐨勯樆濉炰細璇滻D锛岀敤浜庤窡韪攣鐨勭瓑寰呮儏鍐点 + */ +void pgstat_report_blocksid(void *waitLockThrd, uint64 blockSessionId) { + // 濡傛灉pgstate璺熻釜鏈畾涔夛紝鍒欑洿鎺ヨ繑鍥 if (IS_PGSTATE_TRACK_UNDEFINE) return; - knl_thrd_context* thrd = (knl_thrd_context*)waitLockThrd; - volatile PgBackendStatus* beentry = thrd->shemem_ptr_cxt.MyBEEntry; + knl_thrd_context *thrd = (knl_thrd_context *)waitLockThrd; + volatile PgBackendStatus *beentry = thrd->shemem_ptr_cxt.MyBEEntry; if (beentry->st_block_sessionid != blockSessionId) { /* dont print lock info while wait ends. Moreover waitLock is not access at this time. */ if (blockSessionId == 0) { - ereport(DEBUG1, - (errmsg("thread %lu waiting for lock ends", thrd->proc_cxt.MyProcPid))); + ereport(DEBUG1, (errmsg("thread %lu waiting for lock ends", thrd->proc_cxt.MyProcPid))); } else if (thrd->proc->waitLock != NULL) { ereport(DEBUG1, - (errmsg("thread %lu waiting for %s on %s, blocking session %lu", - thrd->proc_cxt.MyProcPid, - GetLockmodeName(thrd->proc->waitLock->tag.locktag_lockmethodid, thrd->proc->waitLockMode), - LocktagToString(thrd->proc->waitLock->tag), - blockSessionId))); + (errmsg("thread %lu waiting for %s on %s, blocking session %lu", thrd->proc_cxt.MyProcPid, + GetLockmodeName(thrd->proc->waitLock->tag.locktag_lockmethodid, thrd->proc->waitLockMode), + LocktagToString(thrd->proc->waitLock->tag), blockSessionId))); } /* @@ -3852,23 +4358,46 @@ void pgstat_report_blocksid(void* waitLockThrd, uint64 blockSessionId) * updateMaxValueForAtomicType - using atomic type to store max value, * we need update the max value by using atomic method */ -static void updateMaxValueForAtomicType(uint64 new_val, uint64* max) +/* + * 鍔熻兘锛氬師瀛愬湴鏇存柊鏈澶у + * + * 鍙傛暟鍒楄〃锛 + * new_val锛氭柊鐨勫 + * max锛氬綋鍓嶆渶澶у肩殑鎸囬拡 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁伴氳繃鍘熷瓙鎿嶄綔鏉ユ洿鏂版渶澶у笺傚畠棣栧厛鑾峰彇褰撳墠鐨勬渶澶у硷紝 + * 鐒跺悗涓庢柊鐨勫兼瘮杈冿紝濡傛灉鏂扮殑鍊兼洿澶т笖鏇挎崲鎴愬姛锛屽氨鏇存柊鏈澶у笺 + */ +static void updateMaxValueForAtomicType(uint64 new_val, uint64 *max) { - uint64 prev; - do - prev = *max; - while (prev < new_val && !pg_atomic_compare_exchange_u64(max, &prev, new_val)); + uint64 prev; // 鐢ㄤ簬瀛樺偍鍓嶄竴涓渶澶у + do { + prev = *max; // 鑾峰彇褰撳墠鐨勬渶澶у + } while (prev < new_val && !pg_atomic_compare_exchange_u64(max, &prev, new_val)); // 寰幆鐩村埌鏇存柊鎴愬姛 } /* * updateMinValueForAtomicType - update ming value for atomic type */ -static void updateMinValueForAtomicType(uint64 new_val, uint64* mix) +/* + * 鍔熻兘锛氬師瀛愬湴鏇存柊鏈灏忓 + * + * 鍙傛暟鍒楄〃锛 + * new_val锛氭柊鐨勫 + * mix锛氬綋鍓嶆渶灏忓肩殑鎸囬拡 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁伴氳繃鍘熷瓙鎿嶄綔鏉ユ洿鏂版渶灏忓笺傚畠棣栧厛鑾峰彇褰撳墠鐨勬渶灏忓硷紝 + * 鐒跺悗涓庢柊鐨勫兼瘮杈冿紝濡傛灉鏂扮殑鍊兼洿灏忎笖鏇挎崲鎴愬姛锛屽氨鏇存柊鏈灏忓笺 + */ +static void updateMinValueForAtomicType(uint64 new_val, uint64 *mix) { - uint64 prev; - do - prev = *mix; - while ((prev == 0 || prev > new_val) && !pg_atomic_compare_exchange_u64(mix, &prev, new_val)); + uint64 prev; // 鐢ㄤ簬瀛樺偍鍓嶄竴涓渶灏忓 + do { + prev = *mix; // 鑾峰彇褰撳墠鐨勬渶灏忓 + } while ((prev == 0 || prev > new_val) && + !pg_atomic_compare_exchange_u64(mix, &prev, new_val)); // 寰幆鐩村埌鏇存柊鎴愬姛 } /* @@ -3883,8 +4412,8 @@ static void RemoveWaitCount(Oid userId) } /* remove user from WaitCountHashTbl */ - WaitCountHashValue* waitCountIdx = - (WaitCountHashValue*)hash_search(g_instance.stat_cxt.WaitCountHashTbl, &userId, HASH_REMOVE, NULL); + WaitCountHashValue *waitCountIdx = + (WaitCountHashValue *)hash_search(g_instance.stat_cxt.WaitCountHashTbl, &userId, HASH_REMOVE, NULL); if (waitCountIdx == NULL) { return; } @@ -3892,24 +4421,37 @@ static void RemoveWaitCount(Oid userId) /* reset the location in WaitCountStatusList */ int dataId = waitCountIdx->idx % WAIT_COUNT_ARRAY_SIZE; int listNodeId = waitCountIdx->idx / WAIT_COUNT_ARRAY_SIZE; - ListCell* lc = list_nth_cell(g_instance.stat_cxt.WaitCountStatusList, listNodeId); - PgStat_WaitCountStatusCell* waitCountStatusCell = (PgStat_WaitCountStatusCell*)lfirst(lc); + ListCell *lc = list_nth_cell(g_instance.stat_cxt.WaitCountStatusList, listNodeId); + PgStat_WaitCountStatusCell *waitCountStatusCell = (PgStat_WaitCountStatusCell *)lfirst(lc); pg_atomic_write_u32(&waitCountStatusCell->WaitCountArray[dataId].userid, 0); } +/* + * 鍔熻兘锛氭鏌ユ寚瀹氱殑璁よ瘉ID鏄惁鏈夋晥 + * + * 鍙傛暟鍒楄〃锛 + * authid锛氳妫鏌ョ殑璁よ瘉ID + * + * 杩斿洖鍊硷細 + * 濡傛灉璁よ瘉ID鏈夋晥锛岃繑鍥瀟rue锛涘惁鍒欒繑鍥瀎alse銆 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁板湪绯荤粺缂撳瓨涓悳绱㈢粰瀹氱殑璁よ瘉ID銆傚鏋滄壘鍒板搴旂殑鍏冪粍锛 + * 琛ㄧず璁よ瘉ID鏈夋晥锛岀劧鍚庨噴鏀剧郴缁熺紦瀛樺苟杩斿洖true锛屽惁鍒欒繑鍥瀎alse銆 + */ bool pg_check_authid(Oid authid) { - HeapTuple roletup = NULL; - + HeapTuple roletup = NULL; // 鐢ㄤ簬瀛樺偍璁よ瘉ID瀵瑰簲鐨勫厓缁 /* * Get the pg_authid entry and print the result */ + // 鍦ㄧ郴缁熺紦瀛樹腑鎼滅储缁欏畾鐨勮璇両D roletup = SearchSysCache1(AUTHOID, ObjectIdGetDatum(authid)); if (HeapTupleIsValid(roletup)) { - ReleaseSysCache(roletup); - return true; + ReleaseSysCache(roletup); // 閲婃斁绯荤粺缂撳瓨 + return true; // 璁よ瘉ID鏈夋晥锛岃繑鍥瀟rue } else { - return false; + return false; // 璁よ瘉ID鏃犳晥锛岃繑鍥瀎alse } } @@ -3936,14 +4478,14 @@ bool CheckUserExist(Oid userId, bool removeCount) } return isExist; } -#define UPDATE_SQL_COUNT(count, elapseTime) \ - do { \ - TimestampTz duration = GetCurrentTimestamp() - GetCurrentStatementLocalStartTimestamp(); \ - duration = (duration == 0) ? 1 : duration; \ - pg_atomic_fetch_add_u64(&(count), 1); \ - pg_atomic_fetch_add_u64(&((elapseTime).total_time), duration); \ - updateMaxValueForAtomicType(duration, &((elapseTime).max_time)); \ - updateMinValueForAtomicType(duration, &((elapseTime).min_time)); \ +#define UPDATE_SQL_COUNT(count, elapseTime) \ + do { \ + TimestampTz duration = GetCurrentTimestamp() - GetCurrentStatementLocalStartTimestamp(); \ + duration = (duration == 0) ? 1 : duration; \ + pg_atomic_fetch_add_u64(&(count), 1); \ + pg_atomic_fetch_add_u64(&((elapseTime).total_time), duration); \ + updateMaxValueForAtomicType(duration, &((elapseTime).max_time)); \ + updateMinValueForAtomicType(duration, &((elapseTime).min_time)); \ } while (0) /* * @Description: according to wait_event_info to add sql count for user, @@ -3954,7 +4496,7 @@ bool CheckUserExist(Oid userId, bool removeCount) void pgstat_report_wait_count(unsigned int wait_event_info) { Oid userid; - WaitCountHashValue* WaitCountIdx = NULL; + WaitCountHashValue *WaitCountIdx = NULL; int dataid; int listNodeid; uint32 classId = wait_event_info & 0xFF000000; @@ -3968,11 +4510,11 @@ void pgstat_report_wait_count(unsigned int wait_event_info) } userid = GetUserId(); - WaitCountIdx = (WaitCountHashValue*)hash_search(g_instance.stat_cxt.WaitCountHashTbl, &userid, HASH_FIND, NULL); + WaitCountIdx = (WaitCountHashValue *)hash_search(g_instance.stat_cxt.WaitCountHashTbl, &userid, HASH_FIND, NULL); /* check if find the user in hashtable */ if (WaitCountIdx == NULL) { - ereport(LOG, - (errcode(ERRCODE_WARNING), (errmsg("can not find the user in sql count hashtable: userid %u", userid)))); + ereport(LOG, (errcode(ERRCODE_WARNING), + (errmsg("can not find the user in sql count hashtable: userid %u", userid)))); LWLockRelease(WaitCountHashLock); /* return if user does not exist */ @@ -3981,20 +4523,21 @@ void pgstat_report_wait_count(unsigned int wait_event_info) } LWLockAcquire(WaitCountHashLock, LW_EXCLUSIVE); - WaitCountIdx = (WaitCountHashValue*)hash_search(g_instance.stat_cxt.WaitCountHashTbl, &userid, HASH_FIND, NULL); + WaitCountIdx = + (WaitCountHashValue *)hash_search(g_instance.stat_cxt.WaitCountHashTbl, &userid, HASH_FIND, NULL); if (WaitCountIdx == NULL) { initWaitCount(userid); - ereport(LOG, - (errcode(ERRCODE_WARNING), - (errmsg("success to insert user into WaitCountHashTbl: userid %u!", userid)))); + ereport(LOG, (errcode(ERRCODE_WARNING), + (errmsg("success to insert user into WaitCountHashTbl: userid %u!", userid)))); } LWLockRelease(WaitCountHashLock); LWLockAcquire(WaitCountHashLock, LW_SHARED); - WaitCountIdx = (WaitCountHashValue*)hash_search(g_instance.stat_cxt.WaitCountHashTbl, &userid, HASH_FIND, NULL); + WaitCountIdx = + (WaitCountHashValue *)hash_search(g_instance.stat_cxt.WaitCountHashTbl, &userid, HASH_FIND, NULL); if (WaitCountIdx == NULL) { ereport(WARNING, - (errcode(ERRCODE_WARNING), - (errmsg("failed to insert user into WaitCountHashTbl: userid %u!, sql count failed!", userid)))); + (errcode(ERRCODE_WARNING), + (errmsg("failed to insert user into WaitCountHashTbl: userid %u!, sql count failed!", userid)))); LWLockRelease(WaitCountHashLock); return; } @@ -4003,11 +4546,11 @@ void pgstat_report_wait_count(unsigned int wait_event_info) /* Get the location of the user in g_instance.stat_cxt.WaitCountStatusList */ dataid = WaitCountIdx->idx % WAIT_COUNT_ARRAY_SIZE; listNodeid = WaitCountIdx->idx / WAIT_COUNT_ARRAY_SIZE; - ListCell* lc = NULL; - PgStat_WaitCountStatusCell* WaitCountStatusCell = NULL; + ListCell *lc = NULL; + PgStat_WaitCountStatusCell *WaitCountStatusCell = NULL; lc = list_nth_cell(g_instance.stat_cxt.WaitCountStatusList, listNodeid); - WaitCountStatusCell = (PgStat_WaitCountStatusCell*)lfirst(lc); + WaitCountStatusCell = (PgStat_WaitCountStatusCell *)lfirst(lc); /* Using pg atomic function to add count for corresponsible WaitEventSQL */ if (classId == PG_WAIT_SQL) { @@ -4015,19 +4558,19 @@ void pgstat_report_wait_count(unsigned int wait_event_info) switch (w) { case WAIT_EVENT_SQL_SELECT: { UPDATE_SQL_COUNT(WaitCountStatusCell->WaitCountArray[dataid].wc_cnt.wc_sql_select, - WaitCountStatusCell->WaitCountArray[dataid].wc_cnt.selectElapse); + WaitCountStatusCell->WaitCountArray[dataid].wc_cnt.selectElapse); } break; case WAIT_EVENT_SQL_UPDATE: { UPDATE_SQL_COUNT(WaitCountStatusCell->WaitCountArray[dataid].wc_cnt.wc_sql_update, - WaitCountStatusCell->WaitCountArray[dataid].wc_cnt.updateElapse); + WaitCountStatusCell->WaitCountArray[dataid].wc_cnt.updateElapse); } break; case WAIT_EVENT_SQL_INSERT: { UPDATE_SQL_COUNT(WaitCountStatusCell->WaitCountArray[dataid].wc_cnt.wc_sql_insert, - WaitCountStatusCell->WaitCountArray[dataid].wc_cnt.insertElapse); + WaitCountStatusCell->WaitCountArray[dataid].wc_cnt.insertElapse); } break; case WAIT_EVENT_SQL_DELETE: { UPDATE_SQL_COUNT(WaitCountStatusCell->WaitCountArray[dataid].wc_cnt.wc_sql_delete, - WaitCountStatusCell->WaitCountArray[dataid].wc_cnt.deleteElapse); + WaitCountStatusCell->WaitCountArray[dataid].wc_cnt.deleteElapse); } break; case WAIT_EVENT_SQL_MERGEINTO: pg_atomic_fetch_add_u64(&(WaitCountStatusCell->WaitCountArray[dataid].wc_cnt.wc_sql_mergeinto), 1); @@ -4058,14 +4601,25 @@ void pgstat_report_wait_count(unsigned int wait_event_info) * * ---------- */ +/* + * 鍔熻兘锛氭姤鍛婂綋鍓嶄細璇濈殑璧勬簮绛夊緟鐘舵 + * + * 鍙傛暟鍒楄〃锛 + * waiting锛氱瓑寰呯殑璧勬簮绫诲瀷锛屽彇鍊间负WorkloadManagerEnqueueState鏋氫妇鍊间箣涓 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庢姤鍛婂綋鍓嶄細璇濈殑璧勬簮绛夊緟鐘舵併傞鍏堟鏌ユ槸鍚﹀惎鐢ㄧ姸鎬佽窡韪紝濡傛灉鏈惎鐢ㄥ垯杩斿洖銆 + * 鐒跺悗灏嗚祫婧愮瓑寰呯姸鎬佽缃负鎸囧畾鐨勫硷紝骞舵牴鎹祫婧愮被鍨嬫洿鏂颁細璇濈殑绛夊緟鐘舵併 + */ void pgstat_report_waiting_on_resource(WorkloadManagerEnqueueState waiting) { - volatile PgBackendStatus* beentry = t_thrd.shemem_ptr_cxt.MyBEEntry; - + volatile PgBackendStatus *beentry = t_thrd.shemem_ptr_cxt.MyBEEntry; + // 妫鏌ユ槸鍚﹀惎鐢ㄧ姸鎬佽窡韪紝濡傛灉鏈惎鐢ㄥ垯杩斿洖 if (IS_PGSTATE_TRACK_UNDEFINE) return; - + // 灏嗚祫婧愮瓑寰呯姸鎬佽缃负鎸囧畾鐨勫 beentry->st_waiting_on_resource = waiting; + // 鏍规嵁璧勬簮绫诲瀷鏇存柊浼氳瘽鐨勭瓑寰呯姸鎬 switch (waiting) { case STATE_ACTIVE_STATEMENTS: (void)pgstat_report_waitstatus(STATE_WAIT_ACTIVE_STATEMENT); @@ -4088,17 +4642,24 @@ void pgstat_report_waiting_on_resource(WorkloadManagerEnqueueState waiting) * set current statement wlm status, include block time, cpu time. * ---------- */ +/* + * 鍔熻兘锛氭姤鍛婂綋鍓嶄細璇濈殑宸ヤ綔璐熻浇绠$悊锛圵LM锛夌姸鎬 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庢姤鍛婂綋鍓嶄細璇濈殑宸ヤ綔璐熻浇绠$悊鐘舵併傞鍏堟鏌ユ槸鍚﹀惎鐢ㄧ姸鎬佽窡韪紝濡傛灉鏈惎鐢ㄥ垯杩斿洖銆 + * 鐒跺悗璋冪敤WLMGetStatistics鍑芥暟鑾峰彇鐩稿叧鐨刉LM缁熻淇℃伅锛屽苟灏嗗叾瀛樺偍鍦≒gBackendStatus缁撴瀯涓 + */ void pgstat_report_statement_wlm_status() { - volatile PgBackendStatus* beentry = t_thrd.shemem_ptr_cxt.MyBEEntry; + volatile PgBackendStatus *beentry = t_thrd.shemem_ptr_cxt.MyBEEntry; + // 妫鏌ユ槸鍚﹀惎鐢ㄧ姸鎬佽窡韪紝濡傛灉鏈惎鐢ㄥ垯杩斿洖 if (IS_PGSTATE_TRACK_UNDEFINE) return; - /* get current workload backend state */ - WLMGetStatistics((TimestampTz*)&beentry->st_block_start_time, - (TimestampTz*)&beentry->st_elapsed_start_time, - (WLMStatistics*)&beentry->st_backstat); + // 璋冪敤WLMGetStatistics鍑芥暟鑾峰彇鐩稿叧鐨刉LM缁熻淇℃伅锛屽苟瀛樺偍鍦≒gBackendStatus缁撴瀯涓 + WLMGetStatistics((TimestampTz *)&beentry->st_block_start_time, (TimestampTz *)&beentry->st_elapsed_start_time, + (WLMStatistics *)&beentry->st_backstat); } /* ---------- @@ -4107,29 +4668,45 @@ void pgstat_report_statement_wlm_status() * refresh the block time and elapsed time for a statement state. * ---------- */ -void pgstat_refresh_statement_wlm_time(volatile PgBackendStatus* beentry) +/* + * 鍔熻兘锛氬埛鏂颁細璇濈殑宸ヤ綔璐熻浇绠$悊锛圵LM锛夋椂闂翠俊鎭 + * + * 鍙傛暟锛 + * beentry锛氭寚鍚慞gBackendStatus鐨勬寚閽堬紝鍖呭惈浼氳瘽鐘舵佷俊鎭 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庡埛鏂颁細璇濈殑宸ヤ綔璐熻浇绠$悊鏃堕棿淇℃伅銆傞鍏堟鏌ヤ紶鍏ョ殑PgBackendStatus鎸囬拡鏄惁涓篘ULL锛 + * 濡傛灉涓篘ULL鍒欒繑鍥炪傜劧鍚庢牴鎹甒LMStatistics缁撴瀯涓殑鐘舵佷俊鎭洿鏂扮浉搴旂殑鏃堕棿淇℃伅锛屽寘鎷琤locktime銆乪lapsedtime銆乵axcputime銆乼otalcputime鍜宻kewpercent銆 + */ +void pgstat_refresh_statement_wlm_time(volatile PgBackendStatus *beentry) { if (NULL != beentry) { - WLMStatistics* backstat = (WLMStatistics*)&beentry->st_backstat; + WLMStatistics *backstat = (WLMStatistics *)&beentry->st_backstat; + // 妫鏌ョ姸鎬佹槸鍚︽湁鏁堬紝濡傛灉鏃犳晥鍒欒繑鍥 if (!StringIsValid(backstat->status)) return; /* compute the block time and elapsed time */ if (strcmp(backstat->status, "pending") == 0) { + // 璁$畻blocktime backstat->blocktime = (GetCurrentTimestamp() - beentry->st_block_start_time) / USECS_PER_SEC; backstat->elapsedtime = 0; - } else if (strcmp(backstat->status, "running") == 0) + } else if (strcmp(backstat->status, "running") == 0) { + // 璁$畻elapsedtime backstat->elapsedtime = (GetCurrentTimestamp() - beentry->st_elapsed_start_time) / USECS_PER_SEC; + } WLMDataIndicator indicator; + // 鍒濆鍖朩LMDataIndicator缁撴瀯 errno_t errval = memset_s(&indicator, sizeof(indicator), 0, sizeof(indicator)); securec_check_errval(errval, , LOG); /* get cpu collect info */ - WLMGetCPUDataIndicator((PgBackendStatus*)beentry, &indicator); + WLMGetCPUDataIndicator((PgBackendStatus *)beentry, &indicator); + // 鏇存柊maxcputime銆乼otalcputime鍜宻kewpercent backstat->maxcputime = indicator.max_value / MSECS_PER_SEC; backstat->totalcputime = indicator.total_value / MSECS_PER_SEC; backstat->skewpercent = indicator.skew_percent; @@ -4153,6 +4730,12 @@ void pgstat_increase_session_spill(void) * increase current session spill size. * ---------- */ +/* + * 鍔熻兘锛氬鍔犱細璇濈殑婧㈠嚭娆℃暟缁熻 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庡鍔犱細璇濈殑婧㈠嚭娆℃暟缁熻銆傚畠浣跨敤鍘熷瓙鎿嶄綔灏嗘孩鍑烘鏁板姞1銆 + */ void pgstat_increase_session_spill_size(int64 size) { gs_atomic_add_64(&t_thrd.shemem_ptr_cxt.mySessionMemoryEntry->spillSize, size); @@ -4164,6 +4747,12 @@ void pgstat_increase_session_spill_size(int64 size) * add warning for early spill. * ---------- */ +/* + * 鍔熻兘锛氳缃細璇濈殑鏃╂湡婧㈠嚭璀﹀憡鏍囧織 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庤缃細璇濈殑鏃╂湡婧㈠嚭璀﹀憡鏍囧織銆傚畠灏嗘寚瀹氱殑鏍囧織浣嶈缃负1銆 + */ void pgstat_add_warning_early_spill() { t_thrd.shemem_ptr_cxt.mySessionMemoryEntry->warning |= (1 << WLM_WARN_EARLY_SPILL); @@ -4197,9 +4786,20 @@ void pgstat_add_warning_hash_conflict() * set backend io state. * ---------- */ +/* + * 鍔熻兘锛氳缃甀O鐘舵佸苟鏇存柊鍚庣杩涚▼鐨勭姸鎬 + * + * 鍙傛暟锛 + * iostate锛氳璁剧疆鐨処O鐘舵 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庤缃甀O鐘舵侊紝骞舵牴鎹渶瑕佹洿鏂板悗绔繘绋嬬殑鐘舵併傞鍏堟鏌ユ槸鍚﹀惎鐢ㄤ簡 + * 璺熻釜娲诲姩鐘舵佸拰褰撳墠杩涚▼鏄惁鏈夋晥銆傚鏋滄湭鍚敤鎴栬繘绋嬫棤鏁堬紝鍒欎笉鎵ц浠讳綍鎿嶄綔銆 + * 鍚﹀垯锛屽皢IO鐘舵佽缃负缁欏畾鍊硷紝骞舵洿鏂扮浉搴旂殑WLM鍙傛暟銆 + */ void pgstat_set_io_state(WorkloadManagerIOState iostate) { - volatile PgBackendStatus* beentry = t_thrd.shemem_ptr_cxt.MyBEEntry; + volatile PgBackendStatus *beentry = t_thrd.shemem_ptr_cxt.MyBEEntry; if (!u_sess->attr.attr_common.pgstat_track_activities || (beentry == NULL)) return; @@ -4215,9 +4815,18 @@ void pgstat_set_io_state(WorkloadManagerIOState iostate) * set backend statement tag. * ---------- */ +/* + * 鍔熻兘锛氳缃鍙ユ爣绛 + * + * 鍙傛暟锛 + * stmttag锛氳璁剧疆鐨勮鍙ユ爣绛 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庤缃綋鍓嶄細璇濈殑璇彞鏍囩銆傚鏋滄湭鍚敤 pgstat_track_activities 鎴栨湭鎵惧埌浼氳瘽鐨勫悗绔姸鎬侊紝鍒欎笉鎵ц浠讳綍鎿嶄綔銆 + */ void pgstat_set_stmt_tag(WorkloadManagerStmtTag stmttag) { - volatile PgBackendStatus* beentry = t_thrd.shemem_ptr_cxt.MyBEEntry; + volatile PgBackendStatus *beentry = t_thrd.shemem_ptr_cxt.MyBEEntry; if (!u_sess->attr.attr_common.pgstat_track_activities || (beentry == NULL)) return; @@ -4226,12 +4835,12 @@ void pgstat_set_stmt_tag(WorkloadManagerStmtTag stmttag) beentry->st_stmttag = stmttag; } -WaitInfo* read_current_instr_wait_info(void) +WaitInfo *read_current_instr_wait_info(void) { - volatile PgBackendStatus* beentry = NULL; + volatile PgBackendStatus *beentry = NULL; int i; errno_t rc; - WaitInfo* gsInstrWaitInfo = (WaitInfo*)palloc0(sizeof(WaitInfo) * 1); + WaitInfo *gsInstrWaitInfo = (WaitInfo *)palloc0(sizeof(WaitInfo) * 1); beentry = t_thrd.shemem_ptr_cxt.BackendStatusArray; for (i = 1; i <= BackendStatusArray_size; i++) { @@ -4248,7 +4857,7 @@ WaitInfo* read_current_instr_wait_info(void) int after_changecount; pgstat_save_changecount_before(beentry, before_changecount); - rc = memcpy_s(&waitinfo, sizeof(WaitInfo), (WaitInfo*)&beentry->waitInfo, sizeof(WaitInfo)); + rc = memcpy_s(&waitinfo, sizeof(WaitInfo), (WaitInfo *)&beentry->waitInfo, sizeof(WaitInfo)); securec_check(rc, "", ""); pgstat_save_changecount_after(beentry, after_changecount); if (before_changecount == after_changecount && (before_changecount & 1) == 0) @@ -4269,6 +4878,13 @@ WaitInfo* read_current_instr_wait_info(void) * reset current status * ---------- */ +/* + * 鍔熻兘锛氶噸缃綋鍓嶄細璇濈殑缁熻鐘舵 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庢竻闄ゅ綋鍓嶄細璇濈殑缁熻鐘舵佷俊鎭傚畠棣栧厛妫鏌ユ槸鍚﹀瓨鍦 pgStatLocalContext锛屽鏋滃瓨鍦ㄥ垯鍒犻櫎璇ュ唴瀛樹笂涓嬫枃锛岀劧鍚庡皢 + * u_sess->stat_cxt.pgStatLocalContext 鍜 u_sess->stat_cxt.localBackendStatusTable 璁剧疆涓 NULL銆 + */ void pgstat_reset_current_status(void) { if (u_sess->stat_cxt.pgStatLocalContext) { @@ -4285,6 +4901,19 @@ void pgstat_reset_current_status(void) * Return true if waiting for a lmgr lock. * ---------- */ +/* + * 鍔熻兘锛氭鏌ョ瓑寰呬簨浠朵俊鎭槸鍚﹁〃绀虹瓑寰呴攣 + * + * 鍙傛暟锛 + * wait_event_info锛氱瓑寰呬簨浠朵俊鎭 + * + * 杩斿洖鍊硷細 + * 濡傛灉绛夊緟浜嬩欢淇℃伅琛ㄧず绛夊緟閿侊紝鍒欒繑鍥 true锛涘惁鍒欒繑鍥 false銆 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庡垽鏂瓑寰呬簨浠朵俊鎭槸鍚︿笌閿佺浉鍏炽傚畠鎻愬彇绛夊緟浜嬩欢淇℃伅鐨勯珮浣嶅瓧鑺傦紝骞跺皢鍏朵笌 PG_WAIT_LOCK 鐨勯珮浣嶅瓧鑺傛瘮杈冿紝 + * 濡傛灉鐩稿悓鍒欒〃绀虹瓑寰呴攣锛岃繑鍥 true锛屽惁鍒欒繑鍥 false銆 + */ bool pgstat_get_waitlock(uint32 wait_event_info) { uint32 classId; @@ -4299,35 +4928,52 @@ bool pgstat_get_waitlock(uint32 wait_event_info) * Return a string representing the current wait event, backend is * waiting on. */ -const char* pgstat_get_wait_event(uint32 wait_event_info) +/* + * 鍔熻兘锛氭牴鎹瓑寰呬簨浠朵俊鎭幏鍙栫瓑寰呬簨浠剁殑鍚嶇О + * + * 鍙傛暟锛 + * wait_event_info锛氱瓑寰呬簨浠朵俊鎭 + * + * 杩斿洖鍊硷細 + * 杩斿洖绛夊緟浜嬩欢鐨勫悕绉帮紙瀛楃涓诧級 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁版牴鎹紶鍏ョ殑绛夊緟浜嬩欢淇℃伅锛岀‘瀹氱瓑寰呬簨浠剁殑绫诲埆锛坈lassId锛夛紝鐒跺悗鑾峰彇瀵瑰簲鐨勫悕绉板苟杩斿洖銆 + */ +const char *pgstat_get_wait_event(uint32 wait_event_info) { uint32 classId; uint16 eventId; - const char* event_name = NULL; + const char *event_name = NULL; + // 鎻愬彇绛夊緟浜嬩欢淇℃伅鐨勯珮浣嶅瓧鑺傚拰浣庝綅瀛楄妭 classId = wait_event_info & 0xFF000000; eventId = wait_event_info & 0x0000FFFF; switch (classId) { case PG_WAIT_LWLOCK: + // 濡傛灉鏄瓑寰呰交閲忕骇閿侊紙LWLock锛夛紝鑾峰彇瀵瑰簲鐨勫悕绉 event_name = GetLWLockIdentifier(classId, eventId); break; case PG_WAIT_LOCK: + // 濡傛灉鏄瓑寰呴氱敤閿侊紙Lock锛夛紝鑾峰彇瀵瑰簲鐨勫悕绉 event_name = GetLockNameFromTagType(eventId); break; case PG_WAIT_IO: { + // 濡傛灉鏄瓑寰匢/O浜嬩欢锛岃幏鍙栧搴旂殑鍚嶇О WaitEventIO w = (WaitEventIO)wait_event_info; event_name = pgstat_get_wait_io(w); break; } default: + // 濡傛灉鏄湭鐭ョ殑绛夊緟浜嬩欢绫诲埆锛岃繑鍥 "unknown wait event" event_name = "unknown wait event"; break; } return event_name; } -void LWLockReportWaitFailed(LWLock* lock) +void LWLockReportWaitFailed(LWLock *lock) { pgstat_report_wait_lock_failed(PG_WAIT_LWLOCK | lock->tranche); } @@ -4338,9 +4984,9 @@ void LWLockReportWaitFailed(LWLock* lock) * Convert WaitEventIO to string. * ---------- */ -const char* pgstat_get_wait_io(WaitEventIO w) +const char *pgstat_get_wait_io(WaitEventIO w) { - const char* event_name = "unknown wait event"; + const char *event_name = "unknown wait event"; switch (w) { case WAIT_EVENT_BUFFILE_READ: @@ -4596,10 +5242,10 @@ int pgstat_get_current_active_numbackends(void) return result_counter; } - PgBackendStatusNode* node = gs_stat_read_current_status(NULL); + PgBackendStatusNode *node = gs_stat_read_current_status(NULL); while (node != NULL) { - PgBackendStatus* beentry = node->data; + PgBackendStatus *beentry = node->data; /* * If the backend thread is valid and the state @@ -4607,7 +5253,7 @@ int pgstat_get_current_active_numbackends(void) */ if ((beentry != NULL) && beentry->st_sessionid > 0 && (beentry->st_state != STATE_IDLE && beentry->st_state != STATE_UNDEFINED && - beentry->st_state != STATE_DECOUPLED)) + beentry->st_state != STATE_DECOUPLED)) ++result_counter; node = node->next; } @@ -4620,9 +5266,9 @@ int pgstat_get_current_active_numbackends(void) } /* get the pointer to the specified backend status */ -PgBackendStatus* pgstat_get_backend_single_entry(uint64 sessionid) +PgBackendStatus *pgstat_get_backend_single_entry(uint64 sessionid) { - PgBackendStatus* beentry = NULL; + PgBackendStatus *beentry = NULL; int i = 0; beentry = t_thrd.shemem_ptr_cxt.BackendStatusArray + BackendStatusArray_size - 1; @@ -4649,7 +5295,7 @@ PgBackendStatus* pgstat_get_backend_single_entry(uint64 sessionid) * @Return: user data list * @See also: */ -List* pgstat_get_user_backend_entry(Oid userid) +List *pgstat_get_user_backend_entry(Oid userid) { // If BackendStatusArray is NULL, we will get it from other thread. if (t_thrd.shemem_ptr_cxt.BackendStatusArray == NULL) { @@ -4659,17 +5305,17 @@ List* pgstat_get_user_backend_entry(Oid userid) return NULL; } - List* entry_list = NULL; - PgBackendStatusNode* node = gs_stat_read_current_status(NULL); + List *entry_list = NULL; + PgBackendStatusNode *node = gs_stat_read_current_status(NULL); while (node != NULL) { - PgBackendStatus* beentry = node->data; + PgBackendStatus *beentry = node->data; /* * If the backend thread is valid and the user id * matched, we treat it as a active thread. */ if (beentry != NULL) { - WLMStatistics* backstat = (WLMStatistics*)&beentry->st_backstat; + WLMStatistics *backstat = (WLMStatistics *)&beentry->st_backstat; if (beentry->st_procpid <= 0 && beentry->st_sessionid == 0) { node = node->next; @@ -4685,9 +5331,9 @@ List* pgstat_get_user_backend_entry(Oid userid) (backstat->enqueue && strcmp(backstat->enqueue, "Transaction") == 0) || (backstat->enqueue && strcmp(backstat->enqueue, "StoredProc") == 0) || (backstat->status && strcmp(backstat->status, "pending") == 0 && backstat->enqueue && - (strcmp(backstat->enqueue, "None") == 0 || strcmp(backstat->enqueue, "Respool") == 0)) || + (strcmp(backstat->enqueue, "None") == 0 || strcmp(backstat->enqueue, "Respool") == 0)) || (backstat->status && strcmp(backstat->status, "finished") == 0 && backstat->enqueue && - strcmp(backstat->enqueue, "Respool") == 0)) { + strcmp(backstat->enqueue, "Respool") == 0)) { entry_list = lappend(entry_list, beentry); } } @@ -4704,7 +5350,7 @@ List* pgstat_get_user_backend_entry(Oid userid) * @Return: all thread of the user * @See also: */ -ThreadId* pgstat_get_user_io_entry(Oid userid, int* num) +ThreadId *pgstat_get_user_io_entry(Oid userid, int *num) { int idx = 0; @@ -4717,13 +5363,13 @@ ThreadId* pgstat_get_user_io_entry(Oid userid, int* num) } uint32 num_backends = 0; - PgBackendStatusNode* node = gs_stat_read_current_status(&num_backends); + PgBackendStatusNode *node = gs_stat_read_current_status(&num_backends); if (num_backends == 0) return NULL; Assert(!u_sess->stat_cxt.pgStatRunningInCollector); - ThreadId* threads = (ThreadId*)palloc0_noexcept(num_backends * sizeof(ThreadId)); + ThreadId *threads = (ThreadId *)palloc0_noexcept(num_backends * sizeof(ThreadId)); if (threads == NULL) { pgstat_reset_current_status(); ereport(LOG, (errmsg("alloc memory failed for get user io entry."))); @@ -4731,7 +5377,7 @@ ThreadId* pgstat_get_user_io_entry(Oid userid, int* num) } while (node != NULL) { - PgBackendStatus* beentry = node->data; + PgBackendStatus *beentry = node->data; /* * If the backend thread is valid and the io state @@ -4758,7 +5404,7 @@ ThreadId* pgstat_get_user_io_entry(Oid userid, int* num) * @Return: all thread with st_stmttag as write * @See also: */ -ThreadId* pgstat_get_stmttag_write_entry(int* num) +ThreadId *pgstat_get_stmttag_write_entry(int *num) { int idx = 0; @@ -4771,13 +5417,13 @@ ThreadId* pgstat_get_stmttag_write_entry(int* num) } uint32 num_backends = 0; - PgBackendStatusNode* node = gs_stat_read_current_status(&num_backends); + PgBackendStatusNode *node = gs_stat_read_current_status(&num_backends); if (num_backends == 0) return NULL; Assert(!u_sess->stat_cxt.pgStatRunningInCollector); - ThreadId* threads = (ThreadId*)palloc0_noexcept(num_backends * sizeof(ThreadId)); + ThreadId *threads = (ThreadId *)palloc0_noexcept(num_backends * sizeof(ThreadId)); if (threads == NULL) { pgstat_reset_current_status(); @@ -4786,7 +5432,7 @@ ThreadId* pgstat_get_stmttag_write_entry(int* num) } while (node != NULL) { - PgBackendStatus* beentry = node->data; + PgBackendStatus *beentry = node->data; node = node->next; /* * If the backend thread is valid and the stmt tag @@ -4799,7 +5445,7 @@ ThreadId* pgstat_get_stmttag_write_entry(int* num) beentry->st_stmttag == STMTTAG_WRITE) threads[idx++] = beentry->st_procpid; else { - WLMStatistics* backstat = (WLMStatistics*)&beentry->st_backstat; + WLMStatistics *backstat = (WLMStatistics *)&beentry->st_backstat; if (backstat->enqueue && strcmp(backstat->enqueue, "Transaction") == 0) threads[idx++] = beentry->st_procpid; } @@ -4819,7 +5465,7 @@ ThreadId* pgstat_get_stmttag_write_entry(int* num) * @OUT num: entries count * @Return: all node status which names are 'application name' */ -PgBackendStatusNode* pgstat_get_backend_status_by_appname(const char* appName, int* resultEntryNum) +PgBackendStatusNode *pgstat_get_backend_status_by_appname(const char *appName, int *resultEntryNum) { int idx = 0; @@ -4839,7 +5485,7 @@ PgBackendStatusNode* pgstat_get_backend_status_by_appname(const char* appName, i /* Get all status entries, which procpid or sessionid is valid */ uint32 numBackends = 0; - PgBackendStatusNode* node = gs_stat_read_current_status(&numBackends); + PgBackendStatusNode *node = gs_stat_read_current_status(&numBackends); /* If all entries procpid or sessionid are invalid, get numBackends is 0 and should return directly */ if (numBackends == 0) { @@ -4851,18 +5497,18 @@ PgBackendStatusNode* pgstat_get_backend_status_by_appname(const char* appName, i Assert(!u_sess->stat_cxt.pgStatRunningInCollector); /* Initialize head pointer, all nodes struct form to a list. This list does not match wich appname */ - PgBackendStatusNode* otherNodeList = (PgBackendStatusNode*)palloc(sizeof(PgBackendStatusNode)); - PgBackendStatusNode* otherNodeListHead = otherNodeList; + PgBackendStatusNode *otherNodeList = (PgBackendStatusNode *)palloc(sizeof(PgBackendStatusNode)); + PgBackendStatusNode *otherNodeListHead = otherNodeList; otherNodeList->data = NULL; otherNodeList->next = NULL; /* Initialize head pointer, all nodes struct form to a list, This list matches wich appname */ - PgBackendStatusNode* resultNodeList = (PgBackendStatusNode*)palloc(sizeof(PgBackendStatusNode)); - PgBackendStatusNode* resultNodeListHead = resultNodeList; + PgBackendStatusNode *resultNodeList = (PgBackendStatusNode *)palloc(sizeof(PgBackendStatusNode)); + PgBackendStatusNode *resultNodeListHead = resultNodeList; resultNodeList->data = NULL; resultNodeList->next = NULL; while (node != NULL) { - PgBackendStatus* beentry = node->data; + PgBackendStatus *beentry = node->data; /* If the backend thread is valid and application name of beentry equals to appName, record this thread pid */ if (beentry != NULL) { @@ -4918,9 +5564,9 @@ PgBackendStatusNode* pgstat_get_backend_status_by_appname(const char* appName, i * Note: return strings for special cases match pg_stat_get_backend_activity. * ---------- */ -const char* pgstat_get_backend_current_activity(ThreadId pid, bool checkUser) +const char *pgstat_get_backend_current_activity(ThreadId pid, bool checkUser) { - PgBackendStatus* beentry = NULL; + PgBackendStatus *beentry = NULL; int i; /* We go through BackendStatusArray from back to front. */ @@ -4936,7 +5582,7 @@ const char* pgstat_get_backend_current_activity(ThreadId pid, bool checkUser) * atomic, but let's play it safe.) We use a volatile pointer here to * ensure the compiler doesn't try to get cute. */ - volatile PgBackendStatus* vbeentry = beentry; + volatile PgBackendStatus *vbeentry = beentry; bool found = false; for (;;) { @@ -4989,9 +5635,9 @@ const char* pgstat_get_backend_current_activity(ThreadId pid, bool checkUser) * corrupted message. We also must take care not to trip on ereport(ERROR). * ---------- */ -const char* pgstat_get_crashed_backend_activity(ThreadId pid, char* buffer, int buflen) +const char *pgstat_get_crashed_backend_activity(ThreadId pid, char *buffer, int buflen) { - volatile PgBackendStatus* beentry = NULL; + volatile PgBackendStatus *beentry = NULL; int i; beentry = t_thrd.shemem_ptr_cxt.BackendStatusArray + BackendStatusArray_size - 1; @@ -5007,8 +5653,8 @@ const char* pgstat_get_crashed_backend_activity(ThreadId pid, char* buffer, int for (i = 1; i <= BackendStatusArray_size; i++) { if (beentry->st_procpid == pid) { /* Read pointer just once, so it can't change after validation */ - const char* activity = beentry->st_activity; - const char* activity_last = NULL; + const char *activity = beentry->st_activity; + const char *activity_last = NULL; /* * We mustn't access activity string before we verify that it @@ -5032,8 +5678,8 @@ const char* pgstat_get_crashed_backend_activity(ThreadId pid, char* buffer, int * problems when reporting the message; and be sure not to run off * the end of memory. */ - ascii_safe_strlcpy( - buffer, activity, Min(buflen, g_instance.attr.attr_common.pgstat_track_activity_query_size)); + ascii_safe_strlcpy(buffer, activity, + Min(buflen, g_instance.attr.attr_common.pgstat_track_activity_query_size)); return buffer; } @@ -5055,7 +5701,7 @@ const char* pgstat_get_crashed_backend_activity(ThreadId pid, char* buffer, int */ void pgstat_cancel_invalid_gtm_conn(void) { - volatile PgBackendStatus* beentry = NULL; + volatile PgBackendStatus *beentry = NULL; bool CalledByBackend = false; volatile GtmHostIndex hostindex = GTM_HOST_INVAILD; @@ -5097,10 +5743,9 @@ void pgstat_cancel_invalid_gtm_conn(void) if (gs_signal_send(beentry->st_procpid, SIGUSR2)) ereport(WARNING, (errmsg("could not send signal to thread %lu: %m", beentry->st_procpid))); else - ereport(LOG, - (errmsg("Success to send SIGUSR2 to openGauss thread: %lu in " - "pgstat_cancel_invalid_gtm_conn", - beentry->st_procpid))); + ereport(LOG, (errmsg("Success to send SIGUSR2 to openGauss thread: %lu in " + "pgstat_cancel_invalid_gtm_conn", + beentry->st_procpid))); } if (beentry->st_procpid == t_thrd.shemem_ptr_cxt.MyBEEntry->st_procpid) @@ -5125,7 +5770,7 @@ void pgstat_cancel_invalid_gtm_conn(void) * Set common header fields in a statistics message * ---------- */ -static void pgstat_setheader(PgStat_MsgHdr* hdr, StatMsgType mtype) +static void pgstat_setheader(PgStat_MsgHdr *hdr, StatMsgType mtype) { hdr->m_type = mtype; } @@ -5136,14 +5781,14 @@ static void pgstat_setheader(PgStat_MsgHdr* hdr, StatMsgType mtype) * Send out one statistics message to the collector * ---------- */ -void pgstat_send(void* msg, int len) +void pgstat_send(void *msg, int len) { int rc; if (g_instance.stat_cxt.pgStatSock == PGINVALID_SOCKET) return; - ((PgStat_MsgHdr*)msg)->m_size = len; + ((PgStat_MsgHdr *)msg)->m_size = len; /* We'll retry after EINTR, but ignore all other failures */ do { @@ -5197,11 +5842,11 @@ static void PgstatCollectThreadStatus(void) // setup a new memcontext pgstat_collect_thread_status_setup_memcxt(); - PgBackendStatusNode* node = gs_stat_read_current_status(NULL); + PgBackendStatusNode *node = gs_stat_read_current_status(NULL); while (node != NULL) { - PgBackendStatus* beentry = node->data; + PgBackendStatus *beentry = node->data; node = node->next; - char* wait_status = NULL; + char *wait_status = NULL; if (NULL == beentry) continue; @@ -5214,17 +5859,11 @@ static void PgstatCollectThreadStatus(void) // log out thread wait status from beentry. elog(LOG, - "PgstatCollectThreadStatus, node_name<%s>, datid<%u>, app_name<%s>, " - "query_id<%lu>, tid<%lu>, lwtid<%d>, parent_sessionid<%lu>, thread_level<%d>, wait_status<%s>", - g_instance.attr.attr_common.PGXCNodeName, - beentry->st_databaseid, - beentry->st_appname ? beentry->st_appname : "unnamed thread", - beentry->st_queryid, - beentry->st_procpid, - beentry->st_tid, - beentry->st_parent_sessionid, - beentry->st_thread_level, - wait_status); + "PgstatCollectThreadStatus, node_name<%s>, datid<%u>, app_name<%s>, " + "query_id<%lu>, tid<%lu>, lwtid<%d>, parent_sessionid<%lu>, thread_level<%d>, wait_status<%s>", + g_instance.attr.attr_common.PGXCNodeName, beentry->st_databaseid, + beentry->st_appname ? beentry->st_appname : "unnamed thread", beentry->st_queryid, beentry->st_procpid, + beentry->st_tid, beentry->st_parent_sessionid, beentry->st_thread_level, wait_status); pfree(wait_status); } @@ -5302,11 +5941,9 @@ void PgstatCollectorMain() u_sess->stat_cxt.pgStatRunningInCollector = true; u_sess->stat_cxt.pgStatDBHash = pgstat_read_statsfile(InvalidOid, true); - t_thrd.mem_cxt.mask_password_mem_cxt = AllocSetContextCreate(t_thrd.top_mem_cxt, - "MaskPasswordCtx", - ALLOCSET_DEFAULT_MINSIZE, - ALLOCSET_DEFAULT_INITSIZE, - ALLOCSET_DEFAULT_MAXSIZE); + t_thrd.mem_cxt.mask_password_mem_cxt = + AllocSetContextCreate(t_thrd.top_mem_cxt, "MaskPasswordCtx", ALLOCSET_DEFAULT_MINSIZE, + ALLOCSET_DEFAULT_INITSIZE, ALLOCSET_DEFAULT_MAXSIZE); /* * Loop to process messages until we get SIGQUIT or detect ungraceful * death of our parent postmaster. @@ -5325,9 +5962,8 @@ void PgstatCollectorMain() TimestampTz get_thread_status_current_time = GetCurrentTimestamp(); if (u_sess->attr.attr_common.pgstat_collect_thread_status_interval > 0 && - TimestampDifferenceExceeds(get_thread_status_start_time, - get_thread_status_current_time, - 60 * u_sess->attr.attr_common.pgstat_collect_thread_status_interval * 1000)) { + TimestampDifferenceExceeds(get_thread_status_start_time, get_thread_status_current_time, + 60 * u_sess->attr.attr_common.pgstat_collect_thread_status_interval * 1000)) { // transfer from minute into msec PgstatCollectThreadStatus(); get_thread_status_start_time = GetCurrentTimestamp(); @@ -5374,7 +6010,7 @@ void PgstatCollectorMain() #ifdef WIN32 pgwin32_noblock = 1; #endif - len = recv(g_instance.stat_cxt.pgStatSock, (char*)&msg, sizeof(PgStat_Msg), 0); + len = recv(g_instance.stat_cxt.pgStatSock, (char *)&msg, sizeof(PgStat_Msg), 0); #ifdef WIN32 pgwin32_noblock = 0; @@ -5406,103 +6042,103 @@ void PgstatCollectorMain() break; case PGSTAT_MTYPE_INQUIRY: - pgstat_recv_inquiry((PgStat_MsgInquiry*)&msg, len); + pgstat_recv_inquiry((PgStat_MsgInquiry *)&msg, len); break; case PGSTAT_MTYPE_TABSTAT: - pgstat_recv_tabstat((PgStat_MsgTabstat*)&msg, len); + pgstat_recv_tabstat((PgStat_MsgTabstat *)&msg, len); break; case PGSTAT_MTYPE_TABPURGE: - pgstat_recv_tabpurge((PgStat_MsgTabpurge*)&msg, len); + pgstat_recv_tabpurge((PgStat_MsgTabpurge *)&msg, len); break; case PGSTAT_MTYPE_DROPDB: - pgstat_recv_dropdb((PgStat_MsgDropdb*)&msg, len); + pgstat_recv_dropdb((PgStat_MsgDropdb *)&msg, len); break; case PGSTAT_MTYPE_RESETCOUNTER: - pgstat_recv_resetcounter((PgStat_MsgResetcounter*)&msg, len); + pgstat_recv_resetcounter((PgStat_MsgResetcounter *)&msg, len); break; case PGSTAT_MTYPE_RESETSHAREDCOUNTER: - pgstat_recv_resetsharedcounter((PgStat_MsgResetsharedcounter*)&msg, len); + pgstat_recv_resetsharedcounter((PgStat_MsgResetsharedcounter *)&msg, len); break; case PGSTAT_MTYPE_RESETSINGLECOUNTER: - pgstat_recv_resetsinglecounter((PgStat_MsgResetsinglecounter*)&msg, len); + pgstat_recv_resetsinglecounter((PgStat_MsgResetsinglecounter *)&msg, len); break; case PGSTAT_MTYPE_AUTOVAC_START: - pgstat_recv_autovac((PgStat_MsgAutovacStart*)&msg, len); + pgstat_recv_autovac((PgStat_MsgAutovacStart *)&msg, len); break; case PGSTAT_MTYPE_VACUUM: - pgstat_recv_vacuum((PgStat_MsgVacuum*)&msg, len); + pgstat_recv_vacuum((PgStat_MsgVacuum *)&msg, len); break; case PGSTAT_MTYPE_AUTOVAC_STAT: - pgstat_recv_autovac_stat((PgStat_MsgAutovacStat*)&msg, len); + pgstat_recv_autovac_stat((PgStat_MsgAutovacStat *)&msg, len); break; case PGSTAT_MTYPE_DATA_CHANGED: - pgstat_recv_data_changed((PgStat_MsgDataChanged*)&msg, len); + pgstat_recv_data_changed((PgStat_MsgDataChanged *)&msg, len); break; case PGSTAT_MTYPE_TRUNCATE: - pgstat_recv_truncate((PgStat_MsgTruncate*)&msg, len); + pgstat_recv_truncate((PgStat_MsgTruncate *)&msg, len); break; case PGSTAT_MTYPE_ANALYZE: - pgstat_recv_analyze((PgStat_MsgAnalyze*)&msg, len); + pgstat_recv_analyze((PgStat_MsgAnalyze *)&msg, len); break; case PGSTAT_MTYPE_BGWRITER: - pgstat_recv_bgwriter((PgStat_MsgBgWriter*)&msg, len); + pgstat_recv_bgwriter((PgStat_MsgBgWriter *)&msg, len); break; case PGSTAT_MTYPE_FUNCSTAT: - pgstat_recv_funcstat((PgStat_MsgFuncstat*)&msg, len); + pgstat_recv_funcstat((PgStat_MsgFuncstat *)&msg, len); break; case PGSTAT_MTYPE_FUNCPURGE: - pgstat_recv_funcpurge((PgStat_MsgFuncpurge*)&msg, len); + pgstat_recv_funcpurge((PgStat_MsgFuncpurge *)&msg, len); break; case PGSTAT_MTYPE_RECOVERYCONFLICT: - pgstat_recv_recoveryconflict((PgStat_MsgRecoveryConflict*)&msg); + pgstat_recv_recoveryconflict((PgStat_MsgRecoveryConflict *)&msg); break; case PGSTAT_MTYPE_DEADLOCK: - pgstat_recv_deadlock((PgStat_MsgDeadlock*)&msg); + pgstat_recv_deadlock((PgStat_MsgDeadlock *)&msg); break; case PGSTAT_MTYPE_FILE: - pgstat_recv_filestat((PgStat_MsgFile*)&msg, len); + pgstat_recv_filestat((PgStat_MsgFile *)&msg, len); break; case PGSTAT_MTYPE_TEMPFILE: - pgstat_recv_tempfile((PgStat_MsgTempFile*)&msg, len); + pgstat_recv_tempfile((PgStat_MsgTempFile *)&msg, len); break; case PGSTAT_MTYPE_MEMRESERVED: - pgstat_recv_memReserved((PgStat_MsgMemReserved*)&msg); + pgstat_recv_memReserved((PgStat_MsgMemReserved *)&msg); break; case PGSTAT_MTYPE_BADBLOCK: - pgstat_recv_badblock_stat((PgStat_MsgBadBlock*)&msg, len); + pgstat_recv_badblock_stat((PgStat_MsgBadBlock *)&msg, len); break; case PGSTAT_MTYPE_RESPONSETIME: - pgstat_recv_sql_responstime((PgStat_SqlRT*)&msg, len); + pgstat_recv_sql_responstime((PgStat_SqlRT *)&msg, len); break; case PGSTAT_MTYPE_CLEANUPHOTKEYS: - pgstat_recv_cleanup_hotkeys((PgStat_MsgCleanupHotkeys*)&msg, len); + pgstat_recv_cleanup_hotkeys((PgStat_MsgCleanupHotkeys *)&msg, len); break; case PGSTAT_MTYPE_PRUNESTAT: - PgstatRecvPrunestat((PgStat_MsgPrune*)&msg, len); + PgstatRecvPrunestat((PgStat_MsgPrune *)&msg, len); break; default: @@ -5513,9 +6149,8 @@ void PgstatCollectorMain() /* Sleep until there's something to do */ #ifndef WIN32 wr = WaitLatchOrSocket(&g_instance.stat_cxt.pgStatLatch, - WL_LATCH_SET | WL_POSTMASTER_DEATH | WL_SOCKET_READABLE | WL_TIMEOUT, - g_instance.stat_cxt.pgStatSock, - 60 * 1000L /* msec */); + WL_LATCH_SET | WL_POSTMASTER_DEATH | WL_SOCKET_READABLE | WL_TIMEOUT, + g_instance.stat_cxt.pgStatSock, 60 * 1000L /* msec */); #else /* @@ -5529,9 +6164,8 @@ void PgstatCollectorMain() * backend_read_statsfile. */ wr = WaitLatchOrSocket(&g_instance.stat_cxt.pgStatLatch, - WL_LATCH_SET | WL_POSTMASTER_DEATH | WL_SOCKET_READABLE | WL_TIMEOUT, - g_instance.stat_cxt.pgStatSock, - 2 * 1000L /* msec */); + WL_LATCH_SET | WL_POSTMASTER_DEATH | WL_SOCKET_READABLE | WL_TIMEOUT, + g_instance.stat_cxt.pgStatSock, 2 * 1000L /* msec */); #endif /* @@ -5578,15 +6212,15 @@ static void pgstat_sighup_handler(SIGNAL_ARGS) * table entry exists, initialize it, if the create parameter is true. * Else, return NULL. */ -static PgStat_StatDBEntry* pgstat_get_db_entry(Oid databaseid, bool create) +static PgStat_StatDBEntry *pgstat_get_db_entry(Oid databaseid, bool create) { - PgStat_StatDBEntry* result = NULL; + PgStat_StatDBEntry *result = NULL; bool found = false; HASHACTION action = (create ? HASH_ENTER : HASH_FIND); errno_t rc = EOK; /* Lookup or create the hash table entry for this database */ - result = (PgStat_StatDBEntry*)hash_search(u_sess->stat_cxt.pgStatDBHash, &databaseid, action, &found); + result = (PgStat_StatDBEntry *)hash_search(u_sess->stat_cxt.pgStatDBHash, &databaseid, action, &found); if (!create && !found) return NULL; @@ -5646,10 +6280,10 @@ static PgStat_StatDBEntry* pgstat_get_db_entry(Oid databaseid, bool create) * table entry exists, initialize it, if the create parameter is true. * Else, return NULL. */ -static PgStat_StatTabEntry* pgstat_get_tab_entry( - PgStat_StatDBEntry* dbentry, Oid tableoid, bool create, uint32 statFlag) +static PgStat_StatTabEntry *pgstat_get_tab_entry(PgStat_StatDBEntry *dbentry, Oid tableoid, bool create, + uint32 statFlag) { - PgStat_StatTabEntry* result = NULL; + PgStat_StatTabEntry *result = NULL; bool found = false; HASHACTION action = (create ? HASH_ENTER : HASH_FIND); PgStat_StatTabKey tabkey; @@ -5658,7 +6292,7 @@ static PgStat_StatTabEntry* pgstat_get_tab_entry( tabkey.tableid = tableoid; /* Lookup or create the hash table entry for this table */ - result = (PgStat_StatTabEntry*)hash_search(dbentry->tables, (void*)(&tabkey), action, &found); + result = (PgStat_StatTabEntry *)hash_search(dbentry->tables, (void *)(&tabkey), action, &found); if (!create && !found) return NULL; @@ -5713,13 +6347,13 @@ static void pgstat_write_statsfile(bool permanent) HASH_SEQ_STATUS hstat; HASH_SEQ_STATUS tstat; HASH_SEQ_STATUS fstat; - PgStat_StatDBEntry* dbentry = NULL; - PgStat_StatTabEntry* tabentry = NULL; - PgStat_StatFuncEntry* funcentry = NULL; - FILE* fpout = NULL; + PgStat_StatDBEntry *dbentry = NULL; + PgStat_StatTabEntry *tabentry = NULL; + PgStat_StatFuncEntry *funcentry = NULL; + FILE *fpout = NULL; int32 format_id; - const char* tmpfile = permanent ? PGSTAT_STAT_PERMANENT_TMPFILE : u_sess->stat_cxt.pgstat_stat_tmpname; - const char* statfile = permanent ? PGSTAT_STAT_PERMANENT_FILENAME : u_sess->stat_cxt.pgstat_stat_filename; + const char *tmpfile = permanent ? PGSTAT_STAT_PERMANENT_TMPFILE : u_sess->stat_cxt.pgstat_stat_tmpname; + const char *statfile = permanent ? PGSTAT_STAT_PERMANENT_FILENAME : u_sess->stat_cxt.pgstat_stat_filename; int rc; /* @@ -5727,8 +6361,8 @@ static void pgstat_write_statsfile(bool permanent) */ fpout = AllocateFile(tmpfile, PG_BINARY_W); if (fpout == NULL) { - ereport( - LOG, (errcode_for_file_access(), errmsg("could not open temporary statistics file \"%s\": %m", tmpfile))); + ereport(LOG, + (errcode_for_file_access(), errmsg("could not open temporary statistics file \"%s\": %m", tmpfile))); return; } @@ -5754,7 +6388,7 @@ static void pgstat_write_statsfile(bool permanent) * Walk through the database table. */ hash_seq_init(&hstat, u_sess->stat_cxt.pgStatDBHash); - while ((dbentry = (PgStat_StatDBEntry*)hash_seq_search(&hstat)) != NULL) { + while ((dbentry = (PgStat_StatDBEntry *)hash_seq_search(&hstat)) != NULL) { /* * Write out the DB entry including the number of live backends. We * don't write the tables or functions pointers, since they're of no @@ -5768,7 +6402,7 @@ static void pgstat_write_statsfile(bool permanent) * Walk through the database's access stats per table. */ hash_seq_init(&tstat, dbentry->tables); - while ((tabentry = (PgStat_StatTabEntry*)hash_seq_search(&tstat)) != NULL) { + while ((tabentry = (PgStat_StatTabEntry *)hash_seq_search(&tstat)) != NULL) { fputc('T', fpout); rc = fwrite(tabentry, sizeof(PgStat_StatTabEntry), 1, fpout); (void)rc; /* we'll check for error with ferror */ @@ -5778,7 +6412,7 @@ static void pgstat_write_statsfile(bool permanent) * Walk through the database's function stats table. */ hash_seq_init(&fstat, dbentry->functions); - while ((funcentry = (PgStat_StatFuncEntry*)hash_seq_search(&fstat)) != NULL) { + while ((funcentry = (PgStat_StatFuncEntry *)hash_seq_search(&fstat)) != NULL) { fputc('F', fpout); rc = fwrite(funcentry, sizeof(PgStat_StatFuncEntry), 1, fpout); (void)rc; /* we'll check for error with ferror */ @@ -5793,10 +6427,10 @@ static void pgstat_write_statsfile(bool permanent) if (g_instance.repair_cxt.global_repair_bad_block_stat != NULL) { LWLockAcquire(RepairBadBlockStatHashLock, LW_SHARED); HASH_SEQ_STATUS repairStat; - BadBlockEntry* repairEntry; + BadBlockEntry *repairEntry; // write the bad page information recorded in global_repair_bad_block_stat. hash_seq_init(&repairStat, g_instance.repair_cxt.global_repair_bad_block_stat); - while ((repairEntry = (BadBlockEntry*)hash_seq_search(&repairStat)) != NULL) { + while ((repairEntry = (BadBlockEntry *)hash_seq_search(&repairStat)) != NULL) { fputc('R', fpout); rc = fwrite(repairEntry, sizeof(BadBlockEntry), 1, fpout); (void)rc; /* we'll check for error with ferror */ @@ -5814,18 +6448,17 @@ static void pgstat_write_statsfile(bool permanent) fputc('E', fpout); if (ferror(fpout)) { - ereport( - LOG, (errcode_for_file_access(), errmsg("could not write temporary statistics file \"%s\": %m", tmpfile))); + ereport(LOG, + (errcode_for_file_access(), errmsg("could not write temporary statistics file \"%s\": %m", tmpfile))); FreeFile(fpout); unlink(tmpfile); } else if (FreeFile(fpout) < 0) { - ereport( - LOG, (errcode_for_file_access(), errmsg("could not close temporary statistics file \"%s\": %m", tmpfile))); + ereport(LOG, + (errcode_for_file_access(), errmsg("could not close temporary statistics file \"%s\": %m", tmpfile))); unlink(tmpfile); } else if (rename(tmpfile, statfile) < 0) { - ereport(LOG, - (errcode_for_file_access(), - errmsg("could not rename temporary statistics file \"%s\" to \"%s\": %m", tmpfile, statfile))); + ereport(LOG, (errcode_for_file_access(), + errmsg("could not rename temporary statistics file \"%s\" to \"%s\": %m", tmpfile, statfile))); unlink(tmpfile); } else { /* @@ -5840,8 +6473,8 @@ static void pgstat_write_statsfile(bool permanent) * message can cause more than one stats file write to occur. */ if (g_instance.stat_cxt.last_statrequest > g_instance.stat_cxt.last_statwrite) { - char* reqtime = NULL; - char* mytime = NULL; + char *reqtime = NULL; + char *mytime = NULL; /* Copy because timestamptz_to_str returns a static buffer */ reqtime = pstrdup(timestamptz_to_str(g_instance.stat_cxt.last_statrequest)); @@ -5865,24 +6498,24 @@ static void pgstat_write_statsfile(bool permanent) * databases' hash table (whose entries point to the tables' hash tables). * ---------- */ -static HTAB* pgstat_read_statsfile(Oid onlydb, bool permanent) +static HTAB *pgstat_read_statsfile(Oid onlydb, bool permanent) { - PgStat_StatDBEntry* dbentry = NULL; + PgStat_StatDBEntry *dbentry = NULL; PgStat_StatDBEntry dbbuf; - PgStat_StatTabEntry* tabentry = NULL; + PgStat_StatTabEntry *tabentry = NULL; PgStat_StatTabEntry tabbuf; PgStat_StatFuncEntry funcbuf; - PgStat_StatFuncEntry* funcentry = NULL; - BadBlockEntry* repairEntry = NULL; + PgStat_StatFuncEntry *funcentry = NULL; + BadBlockEntry *repairEntry = NULL; BadBlockEntry repairBuf; HASHCTL hash_ctl; - HTAB* dbhash = NULL; - HTAB* tabhash = NULL; - HTAB* funchash = NULL; - FILE* fpin = NULL; + HTAB *dbhash = NULL; + HTAB *tabhash = NULL; + HTAB *funchash = NULL; + FILE *fpin = NULL; int32 format_id; bool found = false; - const char* statfile = permanent ? PGSTAT_STAT_PERMANENT_FILENAME : u_sess->stat_cxt.pgstat_stat_filename; + const char *statfile = permanent ? PGSTAT_STAT_PERMANENT_FILENAME : u_sess->stat_cxt.pgstat_stat_filename; errno_t rc = EOK; /* @@ -5926,7 +6559,7 @@ static HTAB* pgstat_read_statsfile(Oid onlydb, bool permanent) if ((fpin = AllocateFile(statfile, PG_BINARY_R)) == NULL) { if (errno != ENOENT) ereport(u_sess->stat_cxt.pgStatRunningInCollector ? LOG : WARNING, - (errcode_for_file_access(), errmsg("could not open statistics file \"%s\": %m", statfile))); + (errcode_for_file_access(), errmsg("could not open statistics file \"%s\": %m", statfile))); elog(LOG, "[Pgstat] statfile %s is missing, using empty dbhash.", statfile); return dbhash; } @@ -5936,7 +6569,7 @@ static HTAB* pgstat_read_statsfile(Oid onlydb, bool permanent) */ if (fread(&format_id, 1, sizeof(format_id), fpin) != sizeof(format_id) || format_id != PGSTAT_FILE_FORMAT_ID) { ereport(u_sess->stat_cxt.pgStatRunningInCollector ? LOG : WARNING, - (errmsg("corrupted statistics file \"%s\"", statfile))); + (errmsg("corrupted statistics file \"%s\"", statfile))); goto done; } @@ -5945,7 +6578,7 @@ static HTAB* pgstat_read_statsfile(Oid onlydb, bool permanent) */ if (fread(u_sess->stat_cxt.globalStats, 1, sizeof(PgStat_GlobalStats), fpin) != sizeof(PgStat_GlobalStats)) { ereport(u_sess->stat_cxt.pgStatRunningInCollector ? LOG : WARNING, - (errmsg("corrupted statistics file \"%s\"", statfile))); + (errmsg("corrupted statistics file \"%s\"", statfile))); goto done; } @@ -5964,17 +6597,17 @@ static HTAB* pgstat_read_statsfile(Oid onlydb, bool permanent) if (fread(&dbbuf, 1, offsetof(PgStat_StatDBEntry, tables), fpin) != offsetof(PgStat_StatDBEntry, tables)) { ereport(u_sess->stat_cxt.pgStatRunningInCollector ? LOG : WARNING, - (errmsg("corrupted statistics file \"%s\"", statfile))); + (errmsg("corrupted statistics file \"%s\"", statfile))); goto done; } /* * Add to the DB hash */ - dbentry = (PgStat_StatDBEntry*)hash_search(dbhash, (void*)&dbbuf.databaseid, HASH_ENTER, &found); + dbentry = (PgStat_StatDBEntry *)hash_search(dbhash, (void *)&dbbuf.databaseid, HASH_ENTER, &found); if (found) { ereport(u_sess->stat_cxt.pgStatRunningInCollector ? LOG : WARNING, - (errmsg("corrupted statistics file \"%s\"", statfile))); + (errmsg("corrupted statistics file \"%s\"", statfile))); goto done; } @@ -5998,17 +6631,15 @@ static HTAB* pgstat_read_statsfile(Oid onlydb, bool permanent) hash_ctl.entrysize = sizeof(PgStat_StatTabEntry); hash_ctl.hash = tag_hash; hash_ctl.hcxt = u_sess->stat_cxt.pgStatLocalContext; - dbentry->tables = hash_create( - "Per-database table", PGSTAT_TAB_HASH_SIZE, &hash_ctl, HASH_ELEM | HASH_FUNCTION | HASH_CONTEXT); + dbentry->tables = hash_create("Per-database table", PGSTAT_TAB_HASH_SIZE, &hash_ctl, + HASH_ELEM | HASH_FUNCTION | HASH_CONTEXT); hash_ctl.keysize = sizeof(Oid); hash_ctl.entrysize = sizeof(PgStat_StatFuncEntry); hash_ctl.hash = oid_hash; hash_ctl.hcxt = u_sess->stat_cxt.pgStatLocalContext; - dbentry->functions = hash_create("Per-database function", - PGSTAT_FUNCTION_HASH_SIZE, - &hash_ctl, - HASH_ELEM | HASH_FUNCTION | HASH_CONTEXT); + dbentry->functions = hash_create("Per-database function", PGSTAT_FUNCTION_HASH_SIZE, &hash_ctl, + HASH_ELEM | HASH_FUNCTION | HASH_CONTEXT); /* * Arrange that following records add entries to this @@ -6032,7 +6663,7 @@ static HTAB* pgstat_read_statsfile(Oid onlydb, bool permanent) case 'T': if (fread(&tabbuf, 1, sizeof(PgStat_StatTabEntry), fpin) != sizeof(PgStat_StatTabEntry)) { ereport(u_sess->stat_cxt.pgStatRunningInCollector ? LOG : WARNING, - (errmsg("corrupted statistics file \"%s\"", statfile))); + (errmsg("corrupted statistics file \"%s\"", statfile))); goto done; } @@ -6042,11 +6673,11 @@ static HTAB* pgstat_read_statsfile(Oid onlydb, bool permanent) if (tabhash == NULL) break; - tabentry = (PgStat_StatTabEntry*)hash_search(tabhash, (void*)&(tabbuf.tablekey), HASH_ENTER, &found); + tabentry = (PgStat_StatTabEntry *)hash_search(tabhash, (void *)&(tabbuf.tablekey), HASH_ENTER, &found); if (found) { ereport(u_sess->stat_cxt.pgStatRunningInCollector ? LOG : WARNING, - (errmsg("corrupted statistics file \"%s\"", statfile))); + (errmsg("corrupted statistics file \"%s\"", statfile))); goto done; } @@ -6060,7 +6691,7 @@ static HTAB* pgstat_read_statsfile(Oid onlydb, bool permanent) case 'F': if (fread(&funcbuf, 1, sizeof(PgStat_StatFuncEntry), fpin) != sizeof(PgStat_StatFuncEntry)) { ereport(u_sess->stat_cxt.pgStatRunningInCollector ? LOG : WARNING, - (errmsg("corrupted statistics file \"%s\"", statfile))); + (errmsg("corrupted statistics file \"%s\"", statfile))); goto done; } @@ -6071,11 +6702,11 @@ static HTAB* pgstat_read_statsfile(Oid onlydb, bool permanent) break; funcentry = - (PgStat_StatFuncEntry*)hash_search(funchash, (void*)&funcbuf.functionid, HASH_ENTER, &found); + (PgStat_StatFuncEntry *)hash_search(funchash, (void *)&funcbuf.functionid, HASH_ENTER, &found); if (found) { ereport(u_sess->stat_cxt.pgStatRunningInCollector ? LOG : WARNING, - (errmsg("corrupted statistics file \"%s\"", statfile))); + (errmsg("corrupted statistics file \"%s\"", statfile))); goto done; } @@ -6096,8 +6727,8 @@ static HTAB* pgstat_read_statsfile(Oid onlydb, bool permanent) /* * Add to the DB hash */ - repairEntry = (BadBlockEntry*)hash_search(g_instance.repair_cxt.global_repair_bad_block_stat, - (void*)&(repairBuf.key), HASH_ENTER, &found); + repairEntry = (BadBlockEntry *)hash_search(g_instance.repair_cxt.global_repair_bad_block_stat, + (void *)&(repairBuf.key), HASH_ENTER, &found); if (found) { ereport(u_sess->stat_cxt.pgStatRunningInCollector ? LOG : WARNING, (errmsg("corrupted statistics file \"%s\"", statfile))); @@ -6119,7 +6750,7 @@ static HTAB* pgstat_read_statsfile(Oid onlydb, bool permanent) default: ereport(u_sess->stat_cxt.pgStatRunningInCollector ? LOG : WARNING, - (errmsg("corrupted statistics file \"%s\"", statfile))); + (errmsg("corrupted statistics file \"%s\"", statfile))); goto done; } } @@ -6140,12 +6771,12 @@ done: * Returns TRUE if successful (timestamp is stored at *ts). * ---------- */ -static bool pgstat_read_statsfile_timestamp(bool permanent, TimestampTz* ts) +static bool pgstat_read_statsfile_timestamp(bool permanent, TimestampTz *ts) { PgStat_GlobalStats myGlobalStats; - FILE* fpin = NULL; + FILE *fpin = NULL; int32 format_id; - const char* statfile = permanent ? PGSTAT_STAT_PERMANENT_FILENAME : u_sess->stat_cxt.pgstat_stat_filename; + const char *statfile = permanent ? PGSTAT_STAT_PERMANENT_FILENAME : u_sess->stat_cxt.pgstat_stat_filename; /* * Try to open the status file. As above, anything but ENOENT is worthy @@ -6154,7 +6785,7 @@ static bool pgstat_read_statsfile_timestamp(bool permanent, TimestampTz* ts) if ((fpin = AllocateFile(statfile, PG_BINARY_R)) == NULL) { if (errno != ENOENT) ereport(u_sess->stat_cxt.pgStatRunningInCollector ? LOG : WARNING, - (errcode_for_file_access(), errmsg("could not open statistics file \"%s\": %m", statfile))); + (errcode_for_file_access(), errmsg("could not open statistics file \"%s\": %m", statfile))); return false; } @@ -6163,7 +6794,7 @@ static bool pgstat_read_statsfile_timestamp(bool permanent, TimestampTz* ts) */ if (fread(&format_id, 1, sizeof(format_id), fpin) != sizeof(format_id) || format_id != PGSTAT_FILE_FORMAT_ID) { ereport(u_sess->stat_cxt.pgStatRunningInCollector ? LOG : WARNING, - (errmsg("corrupted statistics file \"%s\"", statfile))); + (errmsg("corrupted statistics file \"%s\"", statfile))); (void)FreeFile(fpin); return false; } @@ -6173,7 +6804,7 @@ static bool pgstat_read_statsfile_timestamp(bool permanent, TimestampTz* ts) */ if (fread(&myGlobalStats, 1, sizeof(myGlobalStats), fpin) != sizeof(myGlobalStats)) { ereport(u_sess->stat_cxt.pgStatRunningInCollector ? LOG : WARNING, - (errmsg("corrupted statistics file \"%s\"", statfile))); + (errmsg("corrupted statistics file \"%s\"", statfile))); (void)FreeFile(fpin); return false; } @@ -6244,9 +6875,8 @@ static void backend_read_statsfile(void) } if (count >= PGSTAT_POLL_LOOP_COUNT) - ereport(LOG, - (errmsg("using stale statistics instead of current ones " - "because stats collector is not responding"))); + ereport(LOG, (errmsg("using stale statistics instead of current ones " + "because stats collector is not responding"))); /* Autovacuum launcher and the global stats tracker want stats about all databases */ if (IsAutoVacuumLauncherProcess() || IsGlobalStatsTrackerProcess()) @@ -6258,15 +6888,15 @@ static void backend_read_statsfile(void) void pgstat_read_analyzed() { /* Similar to pgstat_read_statsfile. */ - FILE* fpin = NULL; + FILE *fpin = NULL; int32 format_id; PgStat_StatDBEntry dbbuf; PgStat_StatTabEntry tabbuf; PgStat_StatFuncEntry funcbuf; HASHCTL hash_ctl; errno_t errorno = EOK; - PgStat_AnaCheckEntry* tabentry = NULL; - const char* statfile = u_sess->stat_cxt.pgstat_stat_filename; + PgStat_AnaCheckEntry *tabentry = NULL; + const char *statfile = u_sess->stat_cxt.pgstat_stat_filename; bool need_collected = false; bool found = false; @@ -6296,9 +6926,8 @@ void pgstat_read_analyzed() } if (count >= PGSTAT_POLL_LOOP_COUNT) - ereport(LOG, - (errmsg("using stale statistics instead of current ones " - "because stats collector is not responding"))); + ereport(LOG, (errmsg("using stale statistics instead of current ones " + "because stats collector is not responding"))); /* * Similar to pgstat_read_statsfile. @@ -6323,7 +6952,7 @@ void pgstat_read_analyzed() if ((fpin = AllocateFile(statfile, PG_BINARY_R)) == NULL) { if (errno != ENOENT) ereport(u_sess->stat_cxt.pgStatRunningInCollector ? LOG : WARNING, - (errcode_for_file_access(), errmsg("could not open statistics file \"%s\": %m", statfile))); + (errcode_for_file_access(), errmsg("could not open statistics file \"%s\": %m", statfile))); elog(LOG, "[Pgstat] statfile %s is missing, using empty dbhash.", statfile); return; } @@ -6331,14 +6960,14 @@ void pgstat_read_analyzed() /* 2.Verify it's of the expected format */ if (fread(&format_id, 1, sizeof(format_id), fpin) != sizeof(format_id) || format_id != PGSTAT_FILE_FORMAT_ID) { ereport(u_sess->stat_cxt.pgStatRunningInCollector ? LOG : WARNING, - (errmsg("corrupted statistics file \"%s\"", statfile))); + (errmsg("corrupted statistics file \"%s\"", statfile))); goto done; } /* 3.Read global stats struct */ if (fread(u_sess->stat_cxt.globalStats, 1, sizeof(PgStat_GlobalStats), fpin) != sizeof(PgStat_GlobalStats)) { ereport(u_sess->stat_cxt.pgStatRunningInCollector ? LOG : WARNING, - (errmsg("corrupted statistics file \"%s\"", statfile))); + (errmsg("corrupted statistics file \"%s\"", statfile))); goto done; } @@ -6353,7 +6982,7 @@ void pgstat_read_analyzed() if (fread(&dbbuf, 1, offsetof(PgStat_StatDBEntry, tables), fpin) != offsetof(PgStat_StatDBEntry, tables)) { ereport(u_sess->stat_cxt.pgStatRunningInCollector ? LOG : WARNING, - (errmsg("corrupted statistics file \"%s\"", statfile))); + (errmsg("corrupted statistics file \"%s\"", statfile))); goto done; } @@ -6374,7 +7003,7 @@ void pgstat_read_analyzed() case 'T': if (fread(&tabbuf, 1, sizeof(PgStat_StatTabEntry), fpin) != sizeof(PgStat_StatTabEntry)) { ereport(u_sess->stat_cxt.pgStatRunningInCollector ? LOG : WARNING, - (errmsg("corrupted statistics file \"%s\"", statfile))); + (errmsg("corrupted statistics file \"%s\"", statfile))); goto done; } @@ -6382,11 +7011,11 @@ void pgstat_read_analyzed() if (!need_collected || tabbuf.tablekey.statFlag != STATFLG_RELATION) break; - tabentry = (PgStat_AnaCheckEntry*)hash_search( - u_sess->stat_cxt.analyzeCheckHash, (void*)&(tabbuf.tablekey.tableid), HASH_ENTER, &found); + tabentry = (PgStat_AnaCheckEntry *)hash_search(u_sess->stat_cxt.analyzeCheckHash, + (void *)&(tabbuf.tablekey.tableid), HASH_ENTER, &found); if (found) { ereport(u_sess->stat_cxt.pgStatRunningInCollector ? LOG : WARNING, - (errmsg("corrupted statistics file \"%s\"", statfile))); + (errmsg("corrupted statistics file \"%s\"", statfile))); goto done; } @@ -6401,7 +7030,7 @@ void pgstat_read_analyzed() case 'F': if (fread(&funcbuf, 1, sizeof(PgStat_StatFuncEntry), fpin) != sizeof(PgStat_StatFuncEntry)) { ereport(u_sess->stat_cxt.pgStatRunningInCollector ? LOG : WARNING, - (errmsg("corrupted statistics file \"%s\"", statfile))); + (errmsg("corrupted statistics file \"%s\"", statfile))); goto done; } @@ -6413,7 +7042,7 @@ void pgstat_read_analyzed() default: ereport(u_sess->stat_cxt.pgStatRunningInCollector ? LOG : WARNING, - (errmsg("corrupted statistics file \"%s\"", statfile))); + (errmsg("corrupted statistics file \"%s\"", statfile))); goto done; } } @@ -6428,16 +7057,26 @@ done: * Create u_sess->stat_cxt.pgStatLocalContext, if not already done. * ---------- */ +/* + * 鍔熻兘锛氳缃敤浜庣粺璁′俊鎭揩鐓х殑鍐呭瓨涓婁笅鏂 + * + * 娉ㄦ剰锛 + * 濡傛灉褰撳墠浼氳瘽鐨勭粺璁′俊鎭揩鐓х殑鍐呭瓨涓婁笅鏂囧皻鏈垱寤猴紙鍗充负NULL锛夛紝鍒欏垱寤轰竴涓柊鐨勫唴瀛樹笂涓嬫枃锛屽苟灏嗗叾璁剧疆涓虹粺璁′俊鎭殑鍐呭瓨涓婁笅鏂囥 + */ void pgstat_setup_memcxt(void) { if (u_sess->stat_cxt.pgStatLocalContext == NULL) - u_sess->stat_cxt.pgStatLocalContext = AllocSetContextCreate(u_sess->top_mem_cxt, - "Statistics snapshot", - ALLOCSET_SMALL_MINSIZE, - ALLOCSET_SMALL_INITSIZE, - ALLOCSET_SMALL_MAXSIZE); + u_sess->stat_cxt.pgStatLocalContext = + AllocSetContextCreate(u_sess->top_mem_cxt, "Statistics snapshot", ALLOCSET_SMALL_MINSIZE, + ALLOCSET_SMALL_INITSIZE, ALLOCSET_SMALL_MAXSIZE); } +/* + * 鍔熻兘锛氭竻鐞嗙粺璁′俊鎭揩鐓х殑鍐呭瓨涓婁笅鏂 + * + * 娉ㄦ剰锛 + * 濡傛灉褰撳墠浼氳瘽鐨勭粺璁′俊鎭揩鐓х殑鍐呭瓨涓婁笅鏂囧瓨鍦紙鍗充笉涓篘ULL锛夛紝鍒欏垹闄よ鍐呭瓨涓婁笅鏂囥 + */ void pgstat_clean_memcxt(void) { if (u_sess->stat_cxt.pgStatLocalContext != NULL) { @@ -6446,23 +7085,39 @@ void pgstat_clean_memcxt(void) } } +/* + * 鍔熻兘锛氳缃敤浜庢敹闆嗙嚎绋嬬姸鎬佺殑鍐呭瓨涓婁笅鏂 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庤缃敤浜庢敹闆嗙嚎绋嬬姸鎬佺殑鍐呭瓨涓婁笅鏂囥傞鍏堬紝瀹冧細妫鏌ュ綋鍓嶄細璇濈殑缁熻淇℃伅蹇収鐨勫唴瀛樹笂涓嬫枃鏄惁瀛樺湪锛堜笉涓篘ULL锛夛紝骞舵柇瑷杩欎竴鐐广 + * 鎺ョ潃锛屽畠浼氱‘淇濈敤浜庢敹闆嗙嚎绋嬬姸鎬佺殑鍐呭瓨涓婁笅鏂囧皻鏈垎閰嶏紙鍗硊_sess->stat_cxt.pgStatCollectThdStatusContext涓篘ULL锛夛紝 + * 濡傛灉宸插垎閰嶅垯浼氬紩鍙戞柇瑷閿欒銆 + * 鏈鍚庯紝瀹冧細閫氳繃AllocSetContextCreate鍒涘缓涓涓柊鐨勫唴瀛樹笂涓嬫枃锛屼綔涓虹嚎绋嬬姸鎬佹敹闆嗙殑鍐呭瓨涓婁笅鏂囷紝骞跺皢鍏惰缃负褰撳墠浼氳瘽鐨勭粺璁′俊鎭揩鐓х殑鍐呭瓨涓婁笅鏂囩殑瀛愪笂涓嬫枃銆 + */ static void pgstat_collect_thread_status_setup_memcxt(void) { - Assert(u_sess->stat_cxt.pgStatLocalContext); + Assert(u_sess->stat_cxt.pgStatLocalContext); // 纭繚缁熻淇℃伅蹇収鐨勫唴瀛樹笂涓嬫枃瀛樺湪 + // 鏂█绾跨▼鐘舵佹敹闆嗙殑鍐呭瓨涓婁笅鏂囧皻鏈垎閰 Assert(!u_sess->stat_cxt.pgStatCollectThdStatusContext); - - u_sess->stat_cxt.pgStatCollectThdStatusContext = AllocSetContextCreate(u_sess->stat_cxt.pgStatLocalContext, - "PgStatCollectThdStatus", - ALLOCSET_SMALL_MINSIZE, - ALLOCSET_SMALL_INITSIZE, - ALLOCSET_SMALL_MAXSIZE); + // 鍒涘缓绾跨▼鐘舵佹敹闆嗙殑鍐呭瓨涓婁笅鏂 + u_sess->stat_cxt.pgStatCollectThdStatusContext = + AllocSetContextCreate(u_sess->stat_cxt.pgStatLocalContext, "PgStatCollectThdStatus", ALLOCSET_SMALL_MINSIZE, + ALLOCSET_SMALL_INITSIZE, ALLOCSET_SMALL_MAXSIZE); } +/* + * 鍔熻兘锛氭竻鐞嗙嚎绋嬬姸鎬佹敹闆嗙浉鍏崇殑璧勬簮 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庢竻鐞嗙嚎绋嬬姸鎬佹敹闆嗙浉鍏崇殑璧勬簮銆傚畠棣栧厛鍒犻櫎鐢ㄤ簬绾跨▼鐘舵佹敹闆嗙殑鍐呭瓨涓婁笅鏂囷紙u_sess->stat_cxt.pgStatCollectThdStatusContext锛夛紝 + * 鐒跺悗灏嗚鍐呭瓨涓婁笅鏂囪缃负NULL銆傛帴鐫锛屽皢褰撳墠浼氳瘽鐨勬湰鍦板悗绔姸鎬佽〃锛坙ocalBackendStatusTable锛夊拰鏈湴鍚庣鏁扮洰锛坙ocalNumBackends锛夐兘璁剧疆涓篘ULL鎴0銆 + */ static void pgstat_collect_thread_status_clear_resource(void) { + // 鍒犻櫎鐢ㄤ簬绾跨▼鐘舵佹敹闆嗙殑鍐呭瓨涓婁笅鏂 MemoryContextDelete(u_sess->stat_cxt.pgStatCollectThdStatusContext); - /* Reset variables */ + // 灏嗙浉鍏冲彉閲忚缃负NULL鎴0 u_sess->stat_cxt.pgStatCollectThdStatusContext = NULL; u_sess->stat_cxt.localBackendStatusTable = NULL; u_sess->stat_cxt.localNumBackends = 0; @@ -6498,22 +7153,39 @@ void pgstat_clear_snapshot(void) * Process stat inquiry requests. * ---------- */ -static void pgstat_recv_inquiry(PgStat_MsgInquiry* msg, int len) +static void pgstat_recv_inquiry(PgStat_MsgInquiry *msg, int len) { if (msg->inquiry_time > g_instance.stat_cxt.last_statrequest) g_instance.stat_cxt.last_statrequest = msg->inquiry_time; } -static void inline init_tabentry_truncate(PgStat_StatTabEntry* tabentry, PgStat_TableEntry* tabmsg) +/* + * 鍔熻兘锛氬垵濮嬪寲琛ㄧ殑缁熻淇℃伅锛岀敤浜庢埅鏂搷浣 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庡垵濮嬪寲琛ㄧ殑缁熻淇℃伅锛屼富瑕佺敤浜庢埅鏂搷浣溿傚畠灏嗙粰瀹氱殑琛ㄧ粺璁′俊鎭粨鏋勪綋锛圥gStat_StatTabEntry锛夌殑瀛樻椿鍏冪粍鏁帮紙n_live_tuples锛夊拰姝讳骸鍏冪粍鏁帮紙n_dead_tuples锛夐兘璁剧疆涓0銆 + */ +static void inline init_tabentry_truncate(PgStat_StatTabEntry *tabentry, PgStat_TableEntry *tabmsg) { + // 灏嗗瓨娲诲厓缁勬暟鍜屾浜″厓缁勬暟閮借缃负0 tabentry->n_live_tuples = 0; tabentry->n_dead_tuples = 0; } +/* + * 鍔熻兘锛氭鏌ュ姞娉曟搷浣滄槸鍚︿細瀵艰嚧鏁存暟婧㈠嚭 + * + * 鍙傛暟鍒楄〃锛 + * stat_value锛氬綋鍓嶇粺璁″ + * add_value锛氳娣诲姞鍒板綋鍓嶇粺璁″肩殑鍊 + * + * 娉ㄦ剰锛 + * 濡傛灉灏 add_value 娣诲姞鍒 stat_value 浼氬鑷存暣鏁版孩鍑猴紝鍑芥暟灏嗚Е鍙戦敊璇姤鍛婂苟缁堟绋嬪簭鎵ц銆 + */ static void overflow_check(int64 stat_value, int64 add_value) { if (stat_value > LONG_LONG_MAX - add_value) { - ereport(ERROR, (errmsg("Integer overflow when update database-wid stats"))); + ereport(ERROR, (errmsg("Integer overflow when updating database-wide statistics"))); } } @@ -6523,10 +7195,10 @@ static void overflow_check(int64 stat_value, int64 add_value) * Count what the backend has done. * ---------- */ -static void pgstat_recv_tabstat(PgStat_MsgTabstat* msg, int len) +static void pgstat_recv_tabstat(PgStat_MsgTabstat *msg, int len) { - PgStat_StatDBEntry* dbentry = NULL; - PgStat_StatTabEntry* tabentry = NULL; + PgStat_StatDBEntry *dbentry = NULL; + PgStat_StatTabEntry *tabentry = NULL; int i; bool found = false; @@ -6552,13 +7224,13 @@ static void pgstat_recv_tabstat(PgStat_MsgTabstat* msg, int len) * Process all table entries in the message. */ for (i = 0; i < msg->m_nentries; i++) { - PgStat_TableEntry* tabmsg = &(msg->m_entry[i]); + PgStat_TableEntry *tabmsg = &(msg->m_entry[i]); PgStat_StatTabKey tabkey; tabkey.statFlag = tabmsg->t_statFlag; tabkey.tableid = tabmsg->t_id; - tabentry = (PgStat_StatTabEntry*)hash_search(dbentry->tables, (void*)(&tabkey), HASH_ENTER, &found); + tabentry = (PgStat_StatTabEntry *)hash_search(dbentry->tables, (void *)(&tabkey), HASH_ENTER, &found); if (!found) { /* @@ -6651,7 +7323,7 @@ static void pgstat_recv_tabstat(PgStat_MsgTabstat* msg, int len) tabkey.tableid = tabmsg->t_statFlag; tabkey.statFlag = InvalidOid; - tabentry = (PgStat_StatTabEntry*)hash_search(dbentry->tables, (void*)(&tabkey), HASH_ENTER, &found); + tabentry = (PgStat_StatTabEntry *)hash_search(dbentry->tables, (void *)(&tabkey), HASH_ENTER, &found); if (!found) { /* @@ -6717,13 +7389,13 @@ static void pgstat_recv_tabstat(PgStat_MsgTabstat* msg, int len) * Arrange for dead table removal. * ---------- */ -static void pgstat_recv_tabpurge(PgStat_MsgTabpurge* msg, int len) +static void pgstat_recv_tabpurge(PgStat_MsgTabpurge *msg, int len) { - PgStat_StatDBEntry* dbentry = NULL; + PgStat_StatDBEntry *dbentry = NULL; PgStat_StatTabKey tabkey; - PgStat_StatTabEntry* tabentry = NULL; + PgStat_StatTabEntry *tabentry = NULL; PgStat_StatTabKey parentkey; - PgStat_StatTabEntry* parententry = NULL; + PgStat_StatTabEntry *parententry = NULL; int i; dbentry = pgstat_get_db_entry(msg->m_databaseid, false); @@ -6740,13 +7412,13 @@ static void pgstat_recv_tabpurge(PgStat_MsgTabpurge* msg, int len) tabkey.statFlag = msg->m_entry[i].m_statFlag; tabkey.tableid = msg->m_entry[i].m_tableid; - tabentry = (PgStat_StatTabEntry*)hash_search(dbentry->tables, (void*)(&tabkey), HASH_FIND, NULL); + tabentry = (PgStat_StatTabEntry *)hash_search(dbentry->tables, (void *)(&tabkey), HASH_FIND, NULL); /* modify parent table's stat info if it is a patition */ if ((tabentry != NULL) && tabkey.statFlag) { parentkey.tableid = tabkey.statFlag; parentkey.statFlag = InvalidOid; - parententry = (PgStat_StatTabEntry*)hash_search(dbentry->tables, (void*)(&parentkey), HASH_FIND, NULL); + parententry = (PgStat_StatTabEntry *)hash_search(dbentry->tables, (void *)(&parentkey), HASH_FIND, NULL); if (parententry != NULL) { parententry->n_dead_tuples = Max(0, parententry->n_dead_tuples - tabentry->n_dead_tuples); parententry->n_live_tuples = Max(0, parententry->n_live_tuples - tabentry->n_live_tuples); @@ -6755,7 +7427,7 @@ static void pgstat_recv_tabpurge(PgStat_MsgTabpurge* msg, int len) } /* Remove from hashtable if present; we don't care if it's not. */ - (void*)hash_search(dbentry->tables, (void*)(&tabkey), HASH_REMOVE, NULL); + (void *)hash_search(dbentry->tables, (void *)(&tabkey), HASH_REMOVE, NULL); } } @@ -6765,9 +7437,9 @@ static void pgstat_recv_tabpurge(PgStat_MsgTabpurge* msg, int len) * Arrange for dead database removal * ---------- */ -static void pgstat_recv_dropdb(PgStat_MsgDropdb* msg, int len) +static void pgstat_recv_dropdb(PgStat_MsgDropdb *msg, int len) { - PgStat_StatDBEntry* dbentry = NULL; + PgStat_StatDBEntry *dbentry = NULL; Oid db_oid = msg->m_databaseid; /* * Lookup the database in the hashtable. @@ -6783,11 +7455,9 @@ static void pgstat_recv_dropdb(PgStat_MsgDropdb* msg, int len) if (dbentry->functions != NULL) hash_destroy(dbentry->functions); - if (hash_search(u_sess->stat_cxt.pgStatDBHash, (void*)&(db_oid), HASH_REMOVE, NULL) == NULL) { - ereport(ERROR, - (errcode(ERRCODE_DATA_CORRUPTED), - errmsg("database hash table corrupted " - "during cleanup --- abort"))); + if (hash_search(u_sess->stat_cxt.pgStatDBHash, (void *)&(db_oid), HASH_REMOVE, NULL) == NULL) { + ereport(ERROR, (errcode(ERRCODE_DATA_CORRUPTED), errmsg("database hash table corrupted " + "during cleanup --- abort"))); } } @@ -6795,7 +7465,6 @@ static void pgstat_recv_dropdb(PgStat_MsgDropdb* msg, int len) * delete database related hotkeys statistics */ g_instance.stat_cxt.lru->DeleteHotkeysInDB(db_oid); - } /* ---------- @@ -6804,10 +7473,10 @@ static void pgstat_recv_dropdb(PgStat_MsgDropdb* msg, int len) * Reset the statistics for the specified database. * ---------- */ -static void pgstat_recv_resetcounter(PgStat_MsgResetcounter* msg, int len) +static void pgstat_recv_resetcounter(PgStat_MsgResetcounter *msg, int len) { HASHCTL hash_ctl; - PgStat_StatDBEntry* dbentry = NULL; + PgStat_StatDBEntry *dbentry = NULL; errno_t rc = EOK; /* @@ -6876,7 +7545,7 @@ static void pgstat_recv_resetcounter(PgStat_MsgResetcounter* msg, int len) * Reset some shared statistics of the cluster. * ---------- */ -static void pgstat_recv_resetsharedcounter(PgStat_MsgResetsharedcounter* msg, int len) +static void pgstat_recv_resetsharedcounter(PgStat_MsgResetsharedcounter *msg, int len) { errno_t rc = EOK; @@ -6900,9 +7569,9 @@ static void pgstat_recv_resetsharedcounter(PgStat_MsgResetsharedcounter* msg, in * Reset a statistics for a single object * ---------- */ -static void pgstat_recv_resetsinglecounter(PgStat_MsgResetsinglecounter* msg, int len) +static void pgstat_recv_resetsinglecounter(PgStat_MsgResetsinglecounter *msg, int len) { - PgStat_StatDBEntry* dbentry = NULL; + PgStat_StatDBEntry *dbentry = NULL; dbentry = pgstat_get_db_entry(msg->m_databaseid, false); if (dbentry == NULL) @@ -6919,9 +7588,9 @@ static void pgstat_recv_resetsinglecounter(PgStat_MsgResetsinglecounter* msg, in tabkey.statFlag = msg->p_objectid; tabkey.tableid = msg->m_objectid; - (void)hash_search(dbentry->tables, (void*)&(tabkey), HASH_REMOVE, NULL); + (void)hash_search(dbentry->tables, (void *)&(tabkey), HASH_REMOVE, NULL); } else if (msg->m_resettype == RESET_FUNCTION) { - (void)hash_search(dbentry->functions, (void*)&(msg->m_objectid), HASH_REMOVE, NULL); + (void)hash_search(dbentry->functions, (void *)&(msg->m_objectid), HASH_REMOVE, NULL); } } @@ -6931,9 +7600,9 @@ static void pgstat_recv_resetsinglecounter(PgStat_MsgResetsinglecounter* msg, in * Process an autovacuum signalling message. * ---------- */ -static void pgstat_recv_autovac(PgStat_MsgAutovacStart* msg, int len) +static void pgstat_recv_autovac(PgStat_MsgAutovacStart *msg, int len) { - PgStat_StatDBEntry* dbentry = NULL; + PgStat_StatDBEntry *dbentry = NULL; /* * Store the last autovacuum time in the database's hashtable entry. @@ -6949,10 +7618,10 @@ static void pgstat_recv_autovac(PgStat_MsgAutovacStart* msg, int len) * Process a VACUUM message. * ---------- */ -static void pgstat_recv_vacuum(PgStat_MsgVacuum* msg, int len) +static void pgstat_recv_vacuum(PgStat_MsgVacuum *msg, int len) { - PgStat_StatDBEntry* dbentry = NULL; - PgStat_StatTabEntry* tabentry = NULL; + PgStat_StatDBEntry *dbentry = NULL; + PgStat_StatTabEntry *tabentry = NULL; /* * Store the data in the table's hashtable entry. @@ -6983,10 +7652,10 @@ static void pgstat_recv_vacuum(PgStat_MsgVacuum* msg, int len) * Process a pruning message * ---------- */ -static void PgstatRecvPrunestat(PgStat_MsgPrune* msg, int len) +static void PgstatRecvPrunestat(PgStat_MsgPrune *msg, int len) { - PgStat_StatDBEntry* dbentry = NULL; - PgStat_StatTabEntry* tabentry = NULL; + PgStat_StatDBEntry *dbentry = NULL; + PgStat_StatTabEntry *tabentry = NULL; /* * Store the data in the table's hashtable entry. @@ -6998,17 +7667,16 @@ static void PgstatRecvPrunestat(PgStat_MsgPrune* msg, int len) tabentry->total_prune_cnt += msg->m_scanned_blocks; } - /* ---------- * pgstat_recv_data_changed() - * * Process a insert/delete/update/copy/[exchange/truncate/drop] partition message. * ---------- */ -static void pgstat_recv_data_changed(PgStat_MsgDataChanged* msg, int len) +static void pgstat_recv_data_changed(PgStat_MsgDataChanged *msg, int len) { - PgStat_StatDBEntry* dbentry = NULL; - PgStat_StatTabEntry* tabentry = NULL; + PgStat_StatDBEntry *dbentry = NULL; + PgStat_StatTabEntry *tabentry = NULL; /* * Store the data in the table's hashtable entry. @@ -7026,10 +7694,10 @@ static void pgstat_recv_data_changed(PgStat_MsgDataChanged* msg, int len) * Process a autovac stat message. * ---------- */ -static void pgstat_recv_autovac_stat(PgStat_MsgAutovacStat* msg, int len) +static void pgstat_recv_autovac_stat(PgStat_MsgAutovacStat *msg, int len) { - PgStat_StatDBEntry* dbentry = NULL; - PgStat_StatTabEntry* tabentry = NULL; + PgStat_StatDBEntry *dbentry = NULL; + PgStat_StatTabEntry *tabentry = NULL; /* * Store the data in the table's hashtable entry. @@ -7048,11 +7716,11 @@ static void pgstat_recv_autovac_stat(PgStat_MsgAutovacStat* msg, int len) * Process a TRUNCATE message. * ---------- */ -static void pgstat_recv_truncate(PgStat_MsgTruncate* msg, int len) +static void pgstat_recv_truncate(PgStat_MsgTruncate *msg, int len) { - PgStat_StatDBEntry* dbentry = NULL; - PgStat_StatTabEntry* tabentry = NULL; - PgStat_StatTabEntry* parent_entry = NULL; + PgStat_StatDBEntry *dbentry = NULL; + PgStat_StatTabEntry *tabentry = NULL; + PgStat_StatTabEntry *parent_entry = NULL; /* * Store the data in the table's hashtable entry. @@ -7082,10 +7750,10 @@ static void pgstat_recv_truncate(PgStat_MsgTruncate* msg, int len) * Process an ANALYZE message. * ---------- */ -static void pgstat_recv_analyze(PgStat_MsgAnalyze* msg, int len) +static void pgstat_recv_analyze(PgStat_MsgAnalyze *msg, int len) { - PgStat_StatDBEntry* dbentry = NULL; - PgStat_StatTabEntry* tabentry = NULL; + PgStat_StatDBEntry *dbentry = NULL; + PgStat_StatTabEntry *tabentry = NULL; /* * Store the data in the table's hashtable entry. @@ -7120,7 +7788,7 @@ static void pgstat_recv_analyze(PgStat_MsgAnalyze* msg, int len) * Process a BGWRITER message. * ---------- */ -static void pgstat_recv_bgwriter(PgStat_MsgBgWriter* msg, int len) +static void pgstat_recv_bgwriter(PgStat_MsgBgWriter *msg, int len) { if (u_sess->stat_cxt.globalStats->timed_checkpoints > (INT64_MAX - msg->m_timed_checkpoints)) { ereport(ERROR, (errmsg("timed_checkpoints overflow"))); @@ -7179,9 +7847,9 @@ static void pgstat_recv_bgwriter(PgStat_MsgBgWriter* msg, int len) * Process a RECOVERYCONFLICT message. * ---------- */ -static void pgstat_recv_recoveryconflict(const PgStat_MsgRecoveryConflict* msg) +static void pgstat_recv_recoveryconflict(const PgStat_MsgRecoveryConflict *msg) { - PgStat_StatDBEntry* dbentry = NULL; + PgStat_StatDBEntry *dbentry = NULL; dbentry = pgstat_get_db_entry(msg->m_databaseid, true); @@ -7209,9 +7877,8 @@ static void pgstat_recv_recoveryconflict(const PgStat_MsgRecoveryConflict* msg) dbentry->n_conflict_startup_deadlock++; break; default: - ereport(ERROR, - (errcode(ERRCODE_CASE_NOT_FOUND), - errmsg("unrecognized bypass recovery conflict reason: %d", msg->m_reason))); + ereport(ERROR, (errcode(ERRCODE_CASE_NOT_FOUND), + errmsg("unrecognized bypass recovery conflict reason: %d", msg->m_reason))); } } @@ -7221,9 +7888,9 @@ static void pgstat_recv_recoveryconflict(const PgStat_MsgRecoveryConflict* msg) * Process a DEADLOCK message. * ---------- */ -static void pgstat_recv_deadlock(const PgStat_MsgDeadlock* msg) +static void pgstat_recv_deadlock(const PgStat_MsgDeadlock *msg) { - PgStat_StatDBEntry* dbentry = NULL; + PgStat_StatDBEntry *dbentry = NULL; dbentry = pgstat_get_db_entry(msg->m_databaseid, true); @@ -7236,16 +7903,24 @@ static void pgstat_recv_deadlock(const PgStat_MsgDeadlock* msg) * Process a TEMPFILE message. * ---------- */ -static void pgstat_recv_tempfile(PgStat_MsgTempFile* msg, int len) +static void pgstat_recv_tempfile(PgStat_MsgTempFile *msg, int len) { - PgStat_StatDBEntry* dbentry = NULL; + PgStat_StatDBEntry *dbentry = NULL; dbentry = pgstat_get_db_entry(msg->m_databaseid, true); dbentry->n_temp_bytes += msg->m_filesize; dbentry->n_temp_files += 1; } - +/* + * 鍔熻兘锛氭洿鏂板搷搴旀椂闂寸櫨鍒嗕綅鏁扮粺璁 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庢洿鏂板搷搴旀椂闂寸櫨鍒嗕綅鏁扮殑缁熻淇℃伅銆傚畠棣栧厛鑾峰彇褰撳墠璇彞鐨勫紑濮嬫椂闂达紝 + * 鐒跺悗璁$畻浠庡紑濮嬫椂闂村埌褰撳墠鏃堕棿鐨勬寔缁椂闂淬傚鏋滃綋鍓嶈妭鐐规槸鍗曡妭鐐圭郴缁燂紝 + * 瀹冧細璋冪敤 pgstat_update_responstime_singlenode 鍑芥暟鏉ユ洿鏂板搷搴旀椂闂寸粺璁′俊鎭紝 + * 鍚﹀垯锛屽畠浼氳皟鐢 pgstat_report_sql_rt 鍑芥暟鏉ユ眹鎶ュ搷搴旀椂闂寸粺璁′俊鎭 + */ void pgstate_update_percentile_responsetime(void) { if (IS_PGXC_COORDINATOR || IS_SINGLE_NODE) { @@ -7260,7 +7935,21 @@ void pgstate_update_percentile_responsetime(void) } } } - +/* + * 鍔熻兘锛氭洿鏂板崟鑺傜偣绯荤粺鐨勫搷搴旀椂闂寸粺璁′俊鎭 + * + * 鍙傛暟鍒楄〃锛 + * UniqueSQLId锛氬敮涓SQL鏍囪瘑绗 + * start_time锛歋QL璇彞鐨勫紑濮嬫椂闂 + * rt锛歋QL璇彞鐨勫搷搴旀椂闂 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庢洿鏂板崟鑺傜偣绯荤粺鐨勫搷搴旀椂闂寸粺璁′俊鎭傞鍏堬紝瀹冩鏌ユ槸鍚﹀惎鐢ㄤ簡鍝嶅簲鏃堕棿缁熻銆 + * 鐒跺悗锛屽畠妫鏌ユ槸鍚﹂渶瑕佸己鍒跺鐞嗘垨鑰 SQL 鍝嶅簲鏃堕棿淇℃伅鏁扮粍鏄惁涓 NULL銆 + * 濡傛灉闇瑕佸己鍒跺鐞嗘垨鑰呮暟缁勫凡婊★紝鍑芥暟灏嗚缃爣蹇楀苟閲婃斁閿佺劧鍚庤繑鍥炪 + * 鍚﹀垯锛屽畠灏嗚幏鍙栦竴涓柊鐨 SQL 鍝嶅簲鏃堕棿缁熻淇℃伅鐨勭储寮曪紝骞跺皢鐩稿叧淇℃伅鍐欏叆鏁扮粍涓 + * 鏈鍚庯紝瀹冮噴鏀鹃攣銆 + */ void pgstat_update_responstime_singlenode(uint64 UniqueSQLId, int64 start_time, int64 rt) { int32 sqlRTIndex; @@ -7287,51 +7976,102 @@ void pgstat_update_responstime_singlenode(uint64 UniqueSQLId, int64 start_time, LWLockRelease(PercentileLock); } -static void pgstat_recv_sql_responstime(PgStat_SqlRT* msg, int len) +/* + * 鍔熻兘锛氭帴鏀跺苟澶勭悊 SQL 鍝嶅簲鏃堕棿缁熻淇℃伅 + * + * 鍙傛暟鍒楄〃锛 + * msg锛氭帴鏀跺埌鐨勫搷搴旀椂闂寸粺璁′俊鎭 + * len锛氫俊鎭暱搴 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庢帴鏀跺拰澶勭悊 SQL 鍝嶅簲鏃堕棿缁熻淇℃伅銆 + * 棣栧厛锛屽畠妫鏌ュ綋鍓嶇郴缁熸槸鍚﹀惎鐢ㄥ搷搴旀椂闂寸粺璁★紝濡傛灉鏈惎鐢ㄥ垯鐩存帴杩斿洖銆 + * 鎺ョ潃锛屽畠鑾峰彇 SQL 鍝嶅簲鏃堕棿淇℃伅鏁扮粍鐨勫綋鍓嶇储寮 sqlRTIndex銆 + * 濡傛灉 sqlRTIndex 杈惧埌浜嗘渶澶ч檺鍒 MAX_SQL_RT_INFO_COUNT锛岃〃绀烘暟缁勫凡婊★紝 + * 閭d箞浼氭爣璁版暟缁勪负宸叉弧锛坕sFull锛夛紝骞舵牴鎹綋鍓嶈妭鐐圭被鍨嬪喅瀹氭槸鍚﹁Е鍙戝己鍒跺鐞嗭紙force_process锛夈 + * 濡傛灉褰撳墠绯荤粺鏄崗璋冭妭鐐癸紝鍒欎細璁剧疆 force_process 涓 true锛岀劧鍚庨噴鏀 LWLock 骞剁瓑寰 force_process 澶勭悊瀹屾垚銆 + * 澶勭悊瀹屾垚鍚庨噸鏂拌幏鍙 LWLock 骞堕噸缃 sqlRTIndex 涓 0銆 + * 鐒跺悗锛屽皢鎺ユ敹鍒扮殑鍝嶅簲鏃堕棿淇℃伅瀛樺偍鍒版暟缁勪腑锛屽苟灏 sqlRTIndex 鍔 1銆 + * 鏈鍚庯紝閲婃斁 LWLock銆 + */ +static void pgstat_recv_sql_responstime(PgStat_SqlRT *msg, int len) { - + // 妫鏌ユ槸鍚﹀惎鐢ㄥ搷搴旀椂闂寸粺璁★紝濡傛灉鏈惎鐢ㄥ垯鐩存帴杩斿洖 if (g_instance.stat_cxt.sql_rt_info_array == NULL) { return; } - + // 鑾峰彇 SQL 鍝嶅簲鏃堕棿淇℃伅鏁扮粍鐨勫綋鍓嶇储寮 sqlRTIndex LWLockAcquire(PercentileLock, LW_EXCLUSIVE); - int32 sqlRTIndex = g_instance.stat_cxt.sql_rt_info_array->sqlRTIndex; - + // 濡傛灉鏁扮粍宸叉弧锛屾爣璁颁负宸叉弧锛坕sFull锛夛紝鏍规嵁鑺傜偣绫诲瀷鍐冲畾鏄惁瑙﹀彂寮哄埗澶勭悊锛坒orce_process锛 if (sqlRTIndex == MAX_SQL_RT_INFO_COUNT) { - g_instance.stat_cxt.sql_rt_info_array->isFull = true; // other cn will cover the value from first one + g_instance.stat_cxt.sql_rt_info_array->isFull = true; + // 濡傛灉褰撳墠鑺傜偣鏄崗璋冭妭鐐癸紝鍒欒缃 force_process 涓 true锛屽苟閲婃斁 LWLock 鍚庣瓑寰 force_process 澶勭悊瀹屾垚 if (PgxcIsCentralCoordinator(g_instance.attr.attr_common.PGXCNodeName)) { g_instance.stat_cxt.force_process = true; LWLockRelease(PercentileLock); while (g_instance.stat_cxt.force_process) { - pg_usleep(PGSTAT_RETRY_DELAY); // CCN wait force process percentile done + pg_usleep(PGSTAT_RETRY_DELAY); // 绛夊緟鍗忚皟鑺傜偣澶勭悊寮哄埗澶勭悊璇锋眰瀹屾垚 } LWLockAcquire(PercentileLock, LW_EXCLUSIVE); } + // 閲嶇疆 sqlRTIndex 涓 0 sqlRTIndex = 0; g_instance.stat_cxt.sql_rt_info_array->sqlRTIndex = sqlRTIndex; } - + // 灏嗘帴鏀跺埌鐨勫搷搴旀椂闂翠俊鎭瓨鍌ㄥ埌鏁扮粍涓紝骞跺皢 sqlRTIndex 鍔 1 g_instance.stat_cxt.sql_rt_info_array->sqlRT[sqlRTIndex].UniqueSQLId = msg->sqlRT.UniqueSQLId; g_instance.stat_cxt.sql_rt_info_array->sqlRT[sqlRTIndex].start_time = msg->sqlRT.start_time; g_instance.stat_cxt.sql_rt_info_array->sqlRT[sqlRTIndex].rt = msg->sqlRT.rt; g_instance.stat_cxt.sql_rt_info_array->sqlRTIndex = g_instance.stat_cxt.sql_rt_info_array->sqlRTIndex + 1; + // 閲婃斁 LWLock LWLockRelease(PercentileLock); } -static int sqlRTComparator(const void* s1, const void* s2) +/* + * 鍔熻兘锛氱敤浜庢瘮杈冧袱涓 SQL 鍝嶅簲鏃堕棿淇℃伅鐨勬瘮杈冨嚱鏁 + * + * 鍙傛暟鍒楄〃锛 + * s1锛氳姣旇緝鐨勭涓涓 SQL 鍝嶅簲鏃堕棿淇℃伅鎸囬拡 + * s2锛氳姣旇緝鐨勭浜屼釜 SQL 鍝嶅簲鏃堕棿淇℃伅鎸囬拡 + * + * 杩斿洖鍊硷細 + * 濡傛灉绗竴涓 SQL 鍝嶅簲鏃堕棿淇℃伅鐨勫搷搴旀椂闂村ぇ浜庣浜屼釜锛屽垯杩斿洖 1锛 + * 濡傛灉绗竴涓皬浜庣浜屼釜锛屽垯杩斿洖 -1锛 + * 濡傛灉鐩哥瓑锛屽垯杩斿洖 0銆 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜 qsort 绛夋帓搴忓嚱鏁扮殑姣旇緝鎿嶄綔銆 + * 瀹冩瘮杈冧袱涓 SQL 鍝嶅簲鏃堕棿淇℃伅鐨勫搷搴旀椂闂村瓧娈碉紙rt锛夌殑澶у皬锛 + * 濡傛灉绗竴涓ぇ浜庣浜屼釜锛岃繑鍥 1锛 + * 濡傛灉绗竴涓皬浜庣浜屼釜锛岃繑鍥 -1锛 + * 濡傛灉鐩哥瓑锛岃繑鍥 0銆 + */ +static int sqlRTComparator(const void *s1, const void *s2) { - const SqlRTInfo* sqlRT1 = (SqlRTInfo*)s1; - const SqlRTInfo* sqlRT2 = (SqlRTInfo*)s2; - if (sqlRT1->rt > sqlRT2->rt) - return 1; - else if (sqlRT1->rt < sqlRT2->rt) - return -1; - else - return 0; -} + const SqlRTInfo *sqlRT1 = (SqlRTInfo *)s1; + const SqlRTInfo *sqlRT2 = (SqlRTInfo *)s2; -static void prepare_calculate(SqlRTInfoArray* sql_rt_info, int* counter) + if (sqlRT1->rt > sqlRT2->rt) { + return 1; + } else if (sqlRT1->rt < sqlRT2->rt) { + return -1; + } else { + return 0; + } +} +/* + * 鍔熻兘锛氬噯澶囪繘琛岀櫨鍒嗕綅璁$畻 + * + * 鍙傛暟鍒楄〃锛 + * sql_rt_info锛氬寘鍚 SQL 鍝嶅簲鏃堕棿淇℃伅鐨勬暟缁 + * counter锛氳鏁板櫒锛岀敤浜庤繑鍥炶杩涜鐧惧垎浣嶈绠楃殑 SQL 鏁伴噺 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庡噯澶囪繘琛岀櫨鍒嗕綅璁$畻锛岄鍏堣幏鍙栭攣锛岀劧鍚庢牴鎹 SQL 鍝嶅簲鏃堕棿淇℃伅鏁扮粍鐨勬儏鍐碉紝 + * 鍒濆鍖栬鏁板櫒鍜岀浉鍏虫暟鎹粨鏋勶紝鏈鍚庨噴鏀鹃攣骞惰繑鍥炶鏁板櫒鍊笺 + */ +static void prepare_calculate(SqlRTInfoArray *sql_rt_info, int *counter) { int sql_rt_info_count = 0; LWLockAcquire(PercentileLock, LW_SHARED); @@ -7351,18 +8091,14 @@ static void prepare_calculate(SqlRTInfoArray* sql_rt_info, int* counter) if (u_sess->percentile_cxt.LocalsqlRT != NULL) pfree_ext(u_sess->percentile_cxt.LocalsqlRT); - u_sess->percentile_cxt.LocalsqlRT = (SqlRTInfo*)MemoryContextAlloc( - SESS_GET_MEM_CXT_GROUP(MEMORY_CONTEXT_DFX), sql_rt_info_count * sizeof(SqlRTInfo)); + u_sess->percentile_cxt.LocalsqlRT = (SqlRTInfo *)MemoryContextAlloc(SESS_GET_MEM_CXT_GROUP(MEMORY_CONTEXT_DFX), + sql_rt_info_count * sizeof(SqlRTInfo)); - int ss_rc = memset_s(u_sess->percentile_cxt.LocalsqlRT, - sql_rt_info_count * sizeof(SqlRTInfo), - 0, - sql_rt_info_count * sizeof(SqlRTInfo)); + int ss_rc = memset_s(u_sess->percentile_cxt.LocalsqlRT, sql_rt_info_count * sizeof(SqlRTInfo), 0, + sql_rt_info_count * sizeof(SqlRTInfo)); securec_check(ss_rc, "\0", "\0"); - ss_rc = memcpy_s(u_sess->percentile_cxt.LocalsqlRT, - sql_rt_info_count * sizeof(SqlRTInfo), - sql_rt_info->sqlRT, - sql_rt_info_count * sizeof(SqlRTInfo)); + ss_rc = memcpy_s(u_sess->percentile_cxt.LocalsqlRT, sql_rt_info_count * sizeof(SqlRTInfo), sql_rt_info->sqlRT, + sql_rt_info_count * sizeof(SqlRTInfo)); securec_check(ss_rc, "\0", "\0"); sql_rt_info->isFull = false; @@ -7371,36 +8107,60 @@ static void prepare_calculate(SqlRTInfoArray* sql_rt_info, int* counter) *counter = sql_rt_info_count; qsort(u_sess->percentile_cxt.LocalsqlRT, sql_rt_info_count, sizeof(SqlRTInfo), sqlRTComparator); } - -static void prepare_calculate_single(const SqlRTInfoArray* sql_rt_info, int* counter) +/* + * 鍔熻兘锛氬噯澶囪繘琛岀櫨鍒嗕綅璁$畻锛堢敤浜庡崟鑺傜偣鎯呭喌锛 + * + * 鍙傛暟鍒楄〃锛 + * sql_rt_info锛氬寘鍚 SQL 鍝嶅簲鏃堕棿淇℃伅鐨勬暟缁 + * counter锛氳鏁板櫒锛岀敤浜庤繑鍥炶杩涜鐧惧垎浣嶈绠楃殑 SQL 鏁伴噺 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庡噯澶囪繘琛岀櫨鍒嗕綅璁$畻锛屼絾浠呴傜敤浜庡崟鑺傜偣鎯呭喌銆傞鍏堣幏鍙栧綋鍓 SQL 鍝嶅簲鏃堕棿淇℃伅 + * 鏁扮粍鐨勯暱搴︼紝濡傛灉瓒呰繃浜嗘渶澶у厑璁哥殑鏁伴噺锛屽垯灏嗗叾鎴柇涓烘渶澶у笺傜劧鍚庡垵濮嬪寲璁℃暟鍣ㄥ拰鐩 + * 鍏虫暟鎹粨鏋勶紝鎺ョ潃閲婃斁鐧惧垎浣嶉攣骞惰繑鍥炶鏁板櫒鍊笺 + */ +static void prepare_calculate_single(const SqlRTInfoArray *sql_rt_info, int *counter) { + // 鑾峰彇褰撳墠 SQL 鍝嶅簲鏃堕棿淇℃伅鏁伴噺 int32 sql_rt_info_count = g_instance.stat_cxt.sql_rt_info_array->sqlRTIndex; + // 濡傛灉鏁伴噺瓒呰繃涓婇檺锛岄檺鍒跺湪涓婇檺鍐 if (sql_rt_info_count > MAX_SQL_RT_INFO_COUNT) { sql_rt_info_count = MAX_SQL_RT_INFO_COUNT; } + // 鍒濆鍖栬鏁板櫒 *counter = 0; + + // 濡傛灉娌℃湁鏁版嵁锛岀洿鎺ヨ繑鍥 if (sql_rt_info_count == 0) { return; } - if (u_sess->percentile_cxt.LocalsqlRT != NULL) + // 濡傛灉宸茬粡瀛樺湪涓存椂鏁版嵁鏁扮粍锛岄噴鏀惧唴瀛 + if (u_sess->percentile_cxt.LocalsqlRT != NULL) { pfree_ext(u_sess->percentile_cxt.LocalsqlRT); + } - u_sess->percentile_cxt.LocalsqlRT = (SqlRTInfo*)MemoryContextAllocZero( - SESS_GET_MEM_CXT_GROUP(MEMORY_CONTEXT_DFX), sql_rt_info_count * sizeof(SqlRTInfo)); + // 鍒嗛厤鍐呭瓨骞跺皢鏁版嵁浠庡師鏁扮粍鎷疯礉鍒颁复鏃舵暟缁 + u_sess->percentile_cxt.LocalsqlRT = (SqlRTInfo *)MemoryContextAllocZero(SESS_GET_MEM_CXT_GROUP(MEMORY_CONTEXT_DFX), + sql_rt_info_count * sizeof(SqlRTInfo)); + // 鑾峰彇閿侊紝鎷疯礉鏁版嵁 LWLockAcquire(PercentileLock, LW_EXCLUSIVE); - errno_t ss_rc = memcpy_s(u_sess->percentile_cxt.LocalsqlRT, - sql_rt_info_count * sizeof(SqlRTInfo), - sql_rt_info->sqlRT, - sql_rt_info_count * sizeof(SqlRTInfo)); + errno_t ss_rc = memcpy_s(u_sess->percentile_cxt.LocalsqlRT, sql_rt_info_count * sizeof(SqlRTInfo), + sql_rt_info->sqlRT, sql_rt_info_count * sizeof(SqlRTInfo)); LWLockRelease(PercentileLock); securec_check(ss_rc, "\0", "\0"); + + // 灏嗗師濮嬫暟鎹竻闆讹紝鍑嗗璁$畻 g_instance.stat_cxt.sql_rt_info_array->sqlRTIndex = 0; g_instance.stat_cxt.force_process = false; + + // 璁剧疆璁℃暟鍣ㄤ负鏁版嵁鐨勬暟閲 *counter = sql_rt_info_count; + + // 瀵规柊鏁版嵁鏁扮粍杩涜鎺掑簭 qsort(u_sess->percentile_cxt.LocalsqlRT, sql_rt_info_count, sizeof(SqlRTInfo), sqlRTComparator); } @@ -7410,9 +8170,20 @@ static void prepare_calculate_single(const SqlRTInfoArray* sql_rt_info, int* cou * Process a reserving-memory message. * ---------- */ -static void pgstat_recv_memReserved(const PgStat_MsgMemReserved* msg) +/* + * 鍔熻兘锛氬鐞嗘帴鏀跺埌鐨勫唴瀛橀鐣欐秷鎭 + * + * 鍙傛暟鍒楄〃锛 + * msg锛氭寚鍚戞帴鏀跺埌鐨勫唴瀛橀鐣欐秷鎭殑鎸囬拡 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庡鐞嗘帴鏀跺埌鐨勫唴瀛橀鐣欐秷鎭紝鏍规嵁娑堟伅涓殑鏁版嵁搴 ID 鏌ユ壘鎴栧垱寤虹浉搴旂殑鏁版嵁搴 + * 璁板綍銆傛牴鎹秷鎭腑鐨勬搷浣滅被鍨嬶紙reserve_or_release锛夊鍔犳垨鍑忓皯鐩稿簲鏁版嵁搴撶殑鍐呭瓨棰勭暀 + * 澶у皬锛坣_mem_mbytes_reserved锛夈傚鏋滄搷浣滃悗鍐呭瓨棰勭暀澶у皬灏忎簬0锛屽垯灏嗗叾閲嶇疆涓0銆 + */ +static void pgstat_recv_memReserved(const PgStat_MsgMemReserved *msg) { - PgStat_StatDBEntry* dbentry = NULL; + PgStat_StatDBEntry *dbentry = NULL; dbentry = pgstat_get_db_entry(msg->m_databaseid, true); @@ -7431,11 +8202,11 @@ static void pgstat_recv_memReserved(const PgStat_MsgMemReserved* msg) * Count what the backend has done. * ---------- */ -static void pgstat_recv_funcstat(PgStat_MsgFuncstat* msg, int len) +static void pgstat_recv_funcstat(PgStat_MsgFuncstat *msg, int len) { - PgStat_FunctionEntry* funcmsg = &(msg->m_entry[0]); - PgStat_StatDBEntry* dbentry = NULL; - PgStat_StatFuncEntry* funcentry = NULL; + PgStat_FunctionEntry *funcmsg = &(msg->m_entry[0]); + PgStat_StatDBEntry *dbentry = NULL; + PgStat_StatFuncEntry *funcentry = NULL; int i; bool found = false; @@ -7445,7 +8216,8 @@ static void pgstat_recv_funcstat(PgStat_MsgFuncstat* msg, int len) * Process all function entries in the message. */ for (i = 0; i < msg->m_nentries; i++, funcmsg++) { - funcentry = (PgStat_StatFuncEntry*)hash_search(dbentry->functions, (void*)&(funcmsg->f_id), HASH_ENTER, &found); + funcentry = + (PgStat_StatFuncEntry *)hash_search(dbentry->functions, (void *)&(funcmsg->f_id), HASH_ENTER, &found); if (!found) { /* @@ -7472,9 +8244,9 @@ static void pgstat_recv_funcstat(PgStat_MsgFuncstat* msg, int len) * Arrange for dead function removal. * ---------- */ -static void pgstat_recv_funcpurge(PgStat_MsgFuncpurge* msg, int len) +static void pgstat_recv_funcpurge(PgStat_MsgFuncpurge *msg, int len) { - PgStat_StatDBEntry* dbentry = NULL; + PgStat_StatDBEntry *dbentry = NULL; int i; dbentry = pgstat_get_db_entry(msg->m_databaseid, false); @@ -7490,10 +8262,21 @@ static void pgstat_recv_funcpurge(PgStat_MsgFuncpurge* msg, int len) */ for (i = 0; i < msg->m_nentries; i++) { /* Remove from hashtable if present; we don't care if it's not. */ - (void)hash_search(dbentry->functions, (void*)&(msg->m_functionid[i]), HASH_REMOVE, NULL); + (void)hash_search(dbentry->functions, (void *)&(msg->m_functionid[i]), HASH_REMOVE, NULL); } } - +/* + * 鍔熻兘锛氬垵濮嬪寲鍒嗗尯鐨勭粺璁′俊鎭 + * + * 鍙傛暟鍒楄〃锛 + * part锛氭寚鍚戣鍒濆鍖栫粺璁′俊鎭殑鍒嗗尯鐨勬寚閽 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庡垵濮嬪寲鍒嗗尯鐨勭粺璁′俊鎭傞鍏堬紝瀹冩鏌ユ槸鍚﹀簲璇ヨ繘琛岀粺璁′俊鎭殑鏀堕泦銆 + * 濡傛灉涓嶅簲璇ユ敹闆嗙粺璁′俊鎭紝鍒欏皢鍒嗗尯鐨勭粺璁′俊鎭寚閽堬紙pd_pgstat_info锛夎缃负 NULL锛 + * 骞舵彁鍓嶈繑鍥炪傚惁鍒欙紝瀹冩煡鎵炬垨鍒涘缓涓庡垎鍖哄叧鑱旂殑 PgStat_TableStatus 鏉$洰锛 + * 骞跺皢鍒嗗尯鐨勭粺璁′俊鎭寚閽堟洿鏂颁负璇ユ潯鐩 + */ void pgstat_initstats_partition(Partition part) { Oid part_id = part->pd_id; @@ -7518,6 +8301,17 @@ void pgstat_initstats_partition(Partition part) /* *we calculate cpu numbers from sysfs, so we should make sure we can access this file system. */ +/* + * 鍔熻兘锛氭鏌ョ郴缁熸枃浠剁郴缁 + * + * 杩斿洖鍊硷細 + * 濡傛灉绯荤粺鏂囦欢绯荤粺鍙敤锛岃繑鍥 true锛屽惁鍒欒繑鍥 false銆 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁版鏌ョ郴缁熸枃浠剁郴缁熺殑鍙敤鎬э紝瀹冮氳繃璁块棶鏂囦欢绯荤粺璺緞鏉ュ垽鏂叾鏄惁瀛樺湪銆 + * 濡傛灉 SysFileSystemPath銆乀hreadSiblingFile銆丆oreSiblingFile 杩欎簺璺緞涓殑浠讳綍涓涓笉瀛樺湪锛 + * 鍒欒繑鍥 false锛岃〃绀虹郴缁熸枃浠剁郴缁熶笉鍙敤锛涘惁鍒欒繑鍥 true锛岃〃绀虹郴缁熸枃浠剁郴缁熷彲鐢ㄣ + */ static bool checkSysFileSystem(void) { /* Read through sysfs. */ @@ -7536,26 +8330,40 @@ static bool checkSysFileSystem(void) /* *check whether the SysCpuPath is accessable.one accessable path represented one logical cpu. */ +/* + * 鍔熻兘锛氭鏌ラ昏緫 CPU + * + * 鍙傛暟鍒楄〃锛 + * cpuNum: 瑕佹鏌ョ殑閫昏緫 CPU 缂栧彿 + * + * 杩斿洖鍊硷細 + * 濡傛灉閫昏緫 CPU 瀛樺湪锛岃繑鍥 true锛屽惁鍒欒繑鍥 false銆 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁版鏌ユ寚瀹氶昏緫 CPU 鏄惁瀛樺湪锛屽畠鏋勯犱竴涓枃浠惰矾寰勶紙pathbuf锛夋潵琛ㄧず璇 CPU锛 + * 鐒跺悗閫氳繃 access 鍑芥暟妫鏌ヨ璺緞鏄惁瀛樺湪銆傚鏋滃瓨鍦紝琛ㄧず閫昏緫 CPU 瀛樺湪锛岃繑鍥 true锛 + * 鍚﹀垯杩斿洖 false锛岃〃绀洪昏緫 CPU 涓嶅瓨鍦ㄣ + */ static bool checkLogicalCpu(uint32 cpuNum) { char pathbuf[ProcPathMax] = ""; - + // 鏋勯犻昏緫 CPU 鐨勮矾寰 errno_t ret = sprintf_s(pathbuf, sizeof(pathbuf), SysCpuPath, cpuNum); securec_check_ss(ret, "\0", "\0"); - + // 妫鏌ヨ矾寰勬槸鍚﹀瓨鍦 return access(pathbuf, F_OK) == 0; } /* count the set bit in a mapping file */ #define pg_isxdigit(c) \ (((c) >= (int)'0' && (c) <= (int)'9') || ((c) >= (int)'a' && (c) <= (int)'f') || \ - ((c) >= (int)'A' && (c) <= (int)'F')) -static uint32 parseSiblingFile(const char* path) + ((c) >= (int)'A' && (c) <= (int)'F')) +static uint32 parseSiblingFile(const char *path) { int c; uint32 result = 0; char s[2]; - FILE* fp = NULL; + FILE *fp = NULL; union { uint32 a : 4; struct { @@ -7648,12 +8456,12 @@ void getCpuNums(void) */ void getCpuTimes(void) { - const char* statPath = "/proc/stat"; - FILE* fd = NULL; - char* line = NULL; + const char *statPath = "/proc/stat"; + FILE *fd = NULL; + char *line = NULL; size_t len = 0; uint64 readTime[NumOfCpuTimeReads]; - char* temp = NULL; + char *temp = NULL; int i; /* reset the member "got" of u_sess->stat_cxt.osStatDescArray to false */ @@ -7728,10 +8536,10 @@ void getCpuTimes(void) */ void getVmStat(void) { - const char* vmStatPath = "/proc/vmstat"; + const char *vmStatPath = "/proc/vmstat"; int fd = -1; char buffer[VmStatFileReadBuffer + 1]; - char* temp = NULL; + char *temp = NULL; uint64 inPages = 0; uint64 outPages = 0; uint64 pageSize = sysconf(_SC_PAGE_SIZE); @@ -7784,10 +8592,10 @@ void getVmStat(void) */ void getTotalMem(void) { - const char* memInfoPath = "/proc/meminfo"; - FILE* fd = NULL; - char* line = NULL; - char* temp = NULL; + const char *memInfoPath = "/proc/meminfo"; + FILE *fd = NULL; + char *line = NULL; + char *temp = NULL; uint64 ret = 0; size_t len = 0; @@ -7821,9 +8629,9 @@ void getTotalMem(void) */ void getOSRunLoad(void) { - const char* loadAvgPath = "/proc/loadavg"; - FILE* fd = NULL; - char* line = NULL; + const char *loadAvgPath = "/proc/loadavg"; + FILE *fd = NULL; + char *line = NULL; size_t len = 0; /* reset the member "got" of u_sess->stat_cxt.osStatDescArray to false */ @@ -7858,35 +8666,84 @@ Datum Int32GetNumberDatum(NumericValue value) return DirectFunctionCall1(int4_numeric, Int32GetDatum(value.int32Value)); } -void getSessionID(char* sessid, pg_time_t startTime, ThreadId Threadid) +/* + * 鍔熻兘锛氳幏鍙栦細璇 ID + * + * 鍙傛暟鍒楄〃锛 + * sessid: 杈撳嚭鍙傛暟锛岀敤浜庤繑鍥炰細璇 ID + * startTime: 浼氳瘽寮濮嬫椂闂 + * Threadid: 绾跨▼ ID + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庣敓鎴愪細璇 ID锛屼細璇 ID 鏍煎紡涓 "startTime.Threadid"銆 + * 鍏堜娇鐢 snprintf_s 鍑芥暟灏 startTime 鍜 Threadid 鏍煎紡鍖栦负瀛楃涓诧紝 + * 鐒跺悗灏嗙粨鏋滃瓨鍌ㄥ湪 sessid 涓 + */ +void getSessionID(char *sessid, pg_time_t startTime, ThreadId Threadid) { int rc = 0; + // 鏂█ sessid 涓嶄负绌 Assert(NULL != sessid); + // 浣跨敤 snprintf_s 鏍煎紡鍖 startTime 鍜 Threadid 涓哄瓧绗︿覆锛屽苟灏嗙粨鏋滃瓨鍌ㄥ湪 sessid 涓 rc = snprintf_s(sessid, SESSION_ID_LEN, SESSION_ID_LEN - 1, "%ld.%lu", startTime, Threadid); securec_check_ss(rc, "\0", "\0"); } -void getThrdID(char* thrdid, pg_time_t startTime, ThreadId Threadid) +/* + * 鍔熻兘锛氳幏鍙栫嚎绋 ID + * + * 鍙傛暟鍒楄〃锛 + * thrdid: 杈撳嚭鍙傛暟锛岀敤浜庤繑鍥炵嚎绋 ID + * startTime: 绾跨▼寮濮嬫椂闂 + * Threadid: 绾跨▼ ID + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庣敓鎴愮嚎绋 ID锛岀嚎绋 ID 鏍煎紡涓 "startTime.Threadid"銆 + * 鍏堜娇鐢 snprintf_s 鍑芥暟灏 startTime 鍜 Threadid 鏍煎紡鍖栦负瀛楃涓诧紝 + * 鐒跺悗灏嗙粨鏋滃瓨鍌ㄥ湪 thrdid 涓 + */ +void getThrdID(char *thrdid, pg_time_t startTime, ThreadId Threadid) { int rc = 0; + // 鏂█ thrdid 涓嶄负绌 Assert(NULL != thrdid); + // 浣跨敤 snprintf_s 鏍煎紡鍖 startTime 鍜 Threadid 涓哄瓧绗︿覆锛屽苟灏嗙粨鏋滃瓨鍌ㄥ湪 thrdid 涓 rc = snprintf_s(thrdid, SESSION_ID_LEN, SESSION_ID_LEN - 1, "%ld.%lu", startTime, Threadid); securec_check_ss(rc, "\0", "\0"); } #ifdef ENABLE_MOT -MotSessionMemoryDetail* GetMotSessionMemoryDetail(uint32* num) +/* + * 鍔熻兘锛氳幏鍙 MOT 瀛樺偍寮曟搸鐨勪細璇濆唴瀛樿鎯 + * + * 鍙傛暟鍒楄〃锛 + * num: 杈撳嚭鍙傛暟锛岀敤浜庤繑鍥 MOT 瀛樺偍寮曟搸浼氳瘽鍐呭瓨璇︽儏鐨勬暟閲 + * + * 杩斿洖鍊硷細 + * MotSessionMemoryDetail* - 鎸囧悜 MOT 瀛樺偍寮曟搸浼氳瘽鍐呭瓨璇︽儏鏁扮粍鐨勬寚閽 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庤幏鍙 MOT 瀛樺偍寮曟搸鐨勪細璇濆唴瀛樿鎯咃紝閫氳繃澶栭儴瀛樺偍寮曟搸鎺ュ彛鑾峰彇銆 + * 棣栧厛鑾峰彇 MOT 瀛樺偍寮曟搸鐨勫閮ㄦ暟鎹寘瑁呭櫒锛團oreign Data Wrapper锛夛紝鐒跺悗 + * 鑾峰彇澶栭儴鏁版嵁鍖呰鍣ㄧ殑鎺ュ彛鍑芥暟锛屼娇鐢ㄦ帴鍙e嚱鏁拌幏鍙 MOT 瀛樺偍寮曟搸鐨勪細璇濆唴瀛樿鎯呫 + * 鍑芥暟浼氳繑鍥 MOT 瀛樺偍寮曟搸浼氳瘽鍐呭瓨璇︽儏鐨勬暟缁勬寚閽堬紝骞堕氳繃 num 鍙傛暟杩斿洖璇︽儏鏁伴噺銆 + */ +MotSessionMemoryDetail *GetMotSessionMemoryDetail(uint32 *num) { - MotSessionMemoryDetail* returnDetailArray = NULL; - ForeignDataWrapper* fdw = NULL; - FdwRoutine* fdwroutine = NULL; + MotSessionMemoryDetail *returnDetailArray = NULL; + ForeignDataWrapper *fdw = NULL; + FdwRoutine *fdwroutine = NULL; + // 鍒濆鍖栬鎯呮暟閲忎负 0 *num = 0; + // 鑾峰彇 MOT 瀛樺偍寮曟搸鐨勫閮ㄦ暟鎹寘瑁呭櫒 fdw = GetForeignDataWrapperByName(MOT_FDW, false); if (fdw != NULL) { + // 鑾峰彇澶栭儴鏁版嵁鍖呰鍣ㄧ殑鎺ュ彛鍑芥暟 fdwroutine = GetFdwRoutine(fdw->fdwhandler); if (fdwroutine) { + // 浣跨敤鎺ュ彛鍑芥暟鑾峰彇 MOT 瀛樺偍寮曟搸鐨勪細璇濆唴瀛樿鎯 returnDetailArray = fdwroutine->GetForeignSessionMemSize(num); } } @@ -7894,24 +8751,45 @@ MotSessionMemoryDetail* GetMotSessionMemoryDetail(uint32* num) return returnDetailArray; } -MotMemoryDetail* GetMotMemoryDetail(uint32* num, bool isGlobal) +/* + * 鍔熻兘锛氳幏鍙 MOT 瀛樺偍寮曟搸鐨勫唴瀛樿鎯 + * + * 鍙傛暟鍒楄〃锛 + * num: 杈撳嚭鍙傛暟锛岀敤浜庤繑鍥 MOT 瀛樺偍寮曟搸鍐呭瓨璇︽儏鐨勬暟閲 + * isGlobal: 鎸囩ず鏄惁鑾峰彇鍏ㄥ眬鍐呭瓨璇︽儏锛屽鏋滀负 true锛屽垯鑾峰彇鍏ㄥ眬鍐呭瓨璇︽儏锛屽惁鍒欒幏鍙栦細璇濆唴瀛樿鎯 + * + * 杩斿洖鍊硷細 + * MotMemoryDetail* - 鎸囧悜 MOT 瀛樺偍寮曟搸鍐呭瓨璇︽儏鏁扮粍鐨勬寚閽 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庤幏鍙 MOT 瀛樺偍寮曟搸鐨勫唴瀛樿鎯咃紝鍙互閫夋嫨鑾峰彇鍏ㄥ眬鍐呭瓨璇︽儏鎴栦細璇濆唴瀛樿鎯呫 + * 棣栧厛鑾峰彇 MOT 瀛樺偍寮曟搸鐨勫閮ㄦ暟鎹寘瑁呭櫒锛團oreign Data Wrapper锛夛紝鐒跺悗 + * 鑾峰彇澶栭儴鏁版嵁鍖呰鍣ㄧ殑鎺ュ彛鍑芥暟锛屼娇鐢ㄦ帴鍙e嚱鏁拌幏鍙 MOT 瀛樺偍寮曟搸鐨勫唴瀛樿鎯呫 + * 鍑芥暟浼氳繑鍥 MOT 瀛樺偍寮曟搸鍐呭瓨璇︽儏鐨勬暟缁勬寚閽堬紝骞堕氳繃 num 鍙傛暟杩斿洖璇︽儏鏁伴噺銆 + */ +MotMemoryDetail *GetMotMemoryDetail(uint32 *num, bool isGlobal) { - MotMemoryDetail* returnDetailArray = NULL; - ForeignDataWrapper* fdw = NULL; - FdwRoutine* fdwroutine = NULL; + MotMemoryDetail *returnDetailArray = NULL; + ForeignDataWrapper *fdw = NULL; + FdwRoutine *fdwroutine = NULL; + // 鍒濆鍖栬鎯呮暟閲忎负 0 *num = 0; + // 鑾峰彇 MOT 瀛樺偍寮曟搸鐨勫閮ㄦ暟鎹寘瑁呭櫒 fdw = GetForeignDataWrapperByName(MOT_FDW, false); if (fdw != NULL) { + // 鑾峰彇澶栭儴鏁版嵁鍖呰鍣ㄧ殑鎺ュ彛鍑芥暟 fdwroutine = GetFdwRoutine(fdw->fdwhandler); if (fdwroutine != NULL) { + // 浣跨敤鎺ュ彛鍑芥暟鑾峰彇 MOT 瀛樺偍寮曟搸鐨勫唴瀛樿鎯 returnDetailArray = fdwroutine->GetForeignMemSize(num, isGlobal); } } return returnDetailArray; } + #endif int64 getCpuTime(void) @@ -7939,34 +8817,41 @@ Size sessionTimeShmemSize(void) return mul_size(SessionTimeArraySize, sizeof(SessionTimeEntry)); } -const char* TimeInfoTypeName[TOTAL_TIME_INFO_TYPES] = {"DB_TIME", - "CPU_TIME", - "EXECUTION_TIME", - "PARSE_TIME", - "PLAN_TIME", - "REWRITE_TIME", - "PL_EXECUTION_TIME", - "PL_COMPILATION_TIME", - "NET_SEND_TIME", - "DATA_IO_TIME"}; +const char *TimeInfoTypeName[TOTAL_TIME_INFO_TYPES] = { + "DB_TIME", "CPU_TIME", "EXECUTION_TIME", "PARSE_TIME", "PLAN_TIME", + "REWRITE_TIME", "PL_EXECUTION_TIME", "PL_COMPILATION_TIME", "NET_SEND_TIME", "DATA_IO_TIME"}; +/* + * 鍔熻兘锛氬垵濮嬪寲浼氳瘽鏃堕棿缁熻鍏变韩鍐呭瓨 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庡垵濮嬪寲浼氳瘽鏃堕棿缁熻鍏变韩鍐呭瓨锛岄鍏堝皾璇曡幏鍙栧叡浜唴瀛樻寚閽堬紝濡傛灉涓嶅瓨鍦ㄥ垯鍒涘缓銆 + * 鍏变韩鍐呭瓨鐨勫ぇ灏忕敱 SessionTimeArraySize 涔樹互 SessionTimeEntry 鐨勫ぇ灏忓喅瀹氥 + * 濡傛灉鍏变韩鍐呭瓨涓嶅瓨鍦紝鍑芥暟浼氬皢鍏变韩鍐呭瓨鍒濆鍖栦负闆躲 + */ void sessionTimeShmemInit(void) { bool found = false; errno_t rc; - t_thrd.shemem_ptr_cxt.sessionTimeArray = (SessionTimeEntry*)ShmemInitStruct( + // 灏濊瘯鑾峰彇鎴栧垱寤哄悕涓 "SessionTime Array" 鐨勫叡浜唴瀛 + t_thrd.shemem_ptr_cxt.sessionTimeArray = (SessionTimeEntry *)ShmemInitStruct( "SessionTime Array", mul_size(SessionTimeArraySize, sizeof(SessionTimeEntry)), &found); if (!found) { - rc = memset_s(t_thrd.shemem_ptr_cxt.sessionTimeArray, - mul_size(SessionTimeArraySize, sizeof(SessionTimeEntry)), - 0, - mul_size(SessionTimeArraySize, sizeof(SessionTimeEntry))); + // 濡傛灉鍏变韩鍐呭瓨涓嶅瓨鍦紝鍒欏皢鍏跺垵濮嬪寲涓洪浂 + rc = memset_s(t_thrd.shemem_ptr_cxt.sessionTimeArray, mul_size(SessionTimeArraySize, sizeof(SessionTimeEntry)), + 0, mul_size(SessionTimeArraySize, sizeof(SessionTimeEntry))); securec_check(rc, "\0", "\0"); } } - +/* + * 鍔熻兘锛氬垵濮嬪寲褰撳墠浼氳瘽鏃堕棿缁熻鏁版嵁 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庡垵濮嬪寲褰撳墠浼氳瘽鏃堕棿缁熻鏁版嵁锛屾牴鎹綋鍓嶄細璇濈殑灞炴у拰涓婁笅鏂囪缃笉鍚岀殑鍊笺 + * 鍏蜂綋鍖呮嫭浼氳瘽鐨勫敮涓鏍囪瘑銆佹槸鍚︽椿鍔ㄣ佸惎鍔ㄦ椂闂寸瓑淇℃伅銆 + */ void initMySessionTimeEntry(void) { /* Initialize mySessionTimeEntry */ @@ -7976,8 +8861,8 @@ void initMySessionTimeEntry(void) if (t_thrd.proc_cxt.MyBackendId != InvalidBackendId) { Assert(t_thrd.proc_cxt.MyBackendId >= 1 && t_thrd.proc_cxt.MyBackendId <= (g_instance.attr.attr_common.enable_thread_pool - ? GLOBAL_RESERVE_SESSION_NUM - : g_instance.shmem_cxt.MaxBackends)); + ? GLOBAL_RESERVE_SESSION_NUM + : g_instance.shmem_cxt.MaxBackends)); t_thrd.shemem_ptr_cxt.mySessionTimeEntry = &t_thrd.shemem_ptr_cxt.sessionTimeArray[t_thrd.proc_cxt.MyBackendId - 1]; } else { @@ -8005,10 +8890,9 @@ void initMySessionTimeEntry(void) t_thrd.shemem_ptr_cxt.mySessionTimeEntry->myStartTime = t_thrd.proc_cxt.MyStartTime; - errno_t rc = memset_s((int64*)t_thrd.shemem_ptr_cxt.mySessionTimeEntry->array, - sizeof(t_thrd.shemem_ptr_cxt.mySessionTimeEntry->array), - 0, - sizeof(t_thrd.shemem_ptr_cxt.mySessionTimeEntry->array)); + errno_t rc = memset_s((int64 *)t_thrd.shemem_ptr_cxt.mySessionTimeEntry->array, + sizeof(t_thrd.shemem_ptr_cxt.mySessionTimeEntry->array), 0, + sizeof(t_thrd.shemem_ptr_cxt.mySessionTimeEntry->array)); securec_check(rc, "\0", "\0"); t_thrd.shemem_ptr_cxt.mySessionTimeEntry->changeCount++; @@ -8016,8 +8900,14 @@ void initMySessionTimeEntry(void) on_shmem_exit(endMySessionTimeEntry, 0); } - -static void DetachMySessionTimeEntry(volatile SessionTimeEntry* pEntry) +/* + * 鍔熻兘锛氬垎绂诲綋鍓嶄細璇濇椂闂寸粺璁℃暟鎹 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庡皢褰撳墠浼氳瘽鏃堕棿缁熻鏁版嵁鍒嗙锛屼繚瀛樺苟鏍囪涓轰笉娲诲姩鐘舵併 + * 鍏蜂綋鍖呮嫭鏇存柊鍏ㄥ眬鏃堕棿缁熻淇℃伅銆佹爣璁颁笉娲诲姩銆佷互鍙婁慨鏀硅鏁板櫒銆 + */ +static void DetachMySessionTimeEntry(volatile SessionTimeEntry *pEntry) { LWLockAcquire(InstanceTimeLock, LW_EXCLUSIVE); @@ -8040,6 +8930,17 @@ static void DetachMySessionTimeEntry(volatile SessionTimeEntry* pEntry) /* * mark t_thrd.shemem_ptr_cxt.mySessionTimeEntry closed when we shut down. */ +/* + * 鍔熻兘锛氱粨鏉熷綋鍓嶄細璇濇椂闂寸粺璁℃暟鎹 + * + * 鍙傛暟鍒楄〃锛 + * code锛氶鍑轰唬鐮侊紙鏈娇鐢級 + * arg锛氬弬鏁帮紙鏈娇鐢級 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庣粨鏉熷綋鍓嶄細璇濇椂闂寸粺璁℃暟鎹紝鍒嗙骞舵爣璁颁负涓嶆椿鍔ㄧ姸鎬侊紝鐒跺悗灏嗗綋鍓嶄細璇濇椂闂寸粺璁℃暟鎹寚閽堣缃负 NULL銆 + * 鍏蜂綋鍖呮嫭鍒嗙銆佹爣璁颁笉娲诲姩浠ュ強灏嗘暟鎹寚閽堢疆绌烘搷浣溿 + */ static void endMySessionTimeEntry(int code, Datum arg) { DetachMySessionTimeEntry(t_thrd.shemem_ptr_cxt.mySessionTimeEntry); @@ -8072,10 +8973,9 @@ void AttachMySessionTimeEntry(void) t_thrd.shemem_ptr_cxt.mySessionTimeEntry->myStartTime = timestamptz_to_time_t(u_sess->proc_cxt.MyProcPort->SessionStartTime); t_thrd.shemem_ptr_cxt.mySessionTimeEntry->sessionid = u_sess->session_id; - errno_t rc = memset_s((int64*)t_thrd.shemem_ptr_cxt.mySessionTimeEntry->array, - sizeof(t_thrd.shemem_ptr_cxt.mySessionTimeEntry->array), - 0, - sizeof(t_thrd.shemem_ptr_cxt.mySessionTimeEntry->array)); + errno_t rc = memset_s((int64 *)t_thrd.shemem_ptr_cxt.mySessionTimeEntry->array, + sizeof(t_thrd.shemem_ptr_cxt.mySessionTimeEntry->array), 0, + sizeof(t_thrd.shemem_ptr_cxt.mySessionTimeEntry->array)); securec_check(rc, "\0", "\0"); t_thrd.shemem_ptr_cxt.mySessionTimeEntry->isActive = true; } @@ -8083,7 +8983,13 @@ void AttachMySessionTimeEntry(void) t_thrd.shemem_ptr_cxt.mySessionTimeEntry->changeCount++; Assert((t_thrd.shemem_ptr_cxt.mySessionTimeEntry->changeCount & 1) == 0); } - +/* + * 鍔熻兘锛氬紑濮嬭褰曟椂闂翠俊鎭 + * + * 娉ㄦ剰锛 + * 濡傛灉鏈湴鏃堕棿淇℃伅鏁扮粍涓殑 DB_TIME 鍏冪礌涓 0锛堟湭璁板綍鏃堕棿锛夛紝鍒欏皢鍏惰缃负褰撳墠鏃堕棿鎴炽 + * 濡傛灉鍚敤浜 CPU 璁℃椂鍣紝鍒欒繕灏嗘湰鍦版椂闂翠俊鎭暟缁勪腑鐨 CPU_TIME 鍏冪礌璁剧疆涓 CPU 鏃堕棿銆 + */ void timeInfoRecordStart(void) { if (u_sess->stat_cxt.localTimeInfoArray[DB_TIME] == 0) { @@ -8092,7 +8998,18 @@ void timeInfoRecordStart(void) u_sess->stat_cxt.localTimeInfoArray[CPU_TIME] = getCpuTime(); } } - +/* + * 鍔熻兘锛氱粨鏉熻褰曟椂闂翠俊鎭 + * + * 娉ㄦ剰锛 + * 濡傛灉鏈湴鏃堕棿淇℃伅鏁扮粍涓殑 DB_TIME 鍏冪礌涓嶄负 0锛堝凡璁板綍鏃堕棿锛夛紝鍒欒繘琛屼互涓嬫搷浣滐細 + * 1. 澧炲姞褰撳墠浼氳瘽鐨 changeCount锛屼互琛ㄧず鏃堕棿淇℃伅宸叉洿鏂般 + * 2. 濡傛灉鍚敤浜 CPU 璁℃椂鍣紝璁$畻 CPU 鏃堕棿鐨勫樊鍊硷紝骞跺瓨鍌ㄥ湪鏁扮粍涓 + * 3. 璁$畻 DB 鏃堕棿鐨勫樊鍊硷紝骞跺瓨鍌ㄥ湪鏁扮粍涓 + * 4. 澧炲姞鐩稿簲绫诲瀷鐨勬椂闂翠俊鎭埌褰撳墠浼氳瘽鐨勬椂闂翠俊鎭暟缁勩 + * 5. 閲嶇疆鏈湴鏃堕棿淇℃伅鏁扮粍銆 + * 6. 濡傛灉瀛樺湪鍞竴 SQL ID 骞朵笖鍚敤浜嗗敮涓 SQL 缁熻锛屾洿鏂板敮涓 SQL 缁熻淇℃伅銆 + */ void timeInfoRecordEnd(void) { errno_t rc; @@ -8133,24 +9050,38 @@ void timeInfoRecordEnd(void) UniqueSQLStat sqlStat; sqlStat.timeInfo = u_sess->stat_cxt.localTimeInfoArray; sqlStat.netInfo = u_sess->stat_cxt.localNetInfo; + // 濡傛灉瀛樺湪鍞竴 SQL ID 骞朵笖鍚敤浜嗗敮涓 SQL 缁熻锛屾洿鏂板敮涓 SQL 缁熻淇℃伅銆 if (u_sess->unique_sql_cxt.unique_sql_id != 0 && is_unique_sql_enabled()) UpdateUniqueSQLStat(NULL, NULL, 0, NULL, &sqlStat); - rc = memset_s(u_sess->stat_cxt.localTimeInfoArray, - sizeof(int64) * TOTAL_TIME_INFO_TYPES, - 0, - sizeof(int64) * TOTAL_TIME_INFO_TYPES); + + // 閲嶇疆鏈湴鏃堕棿淇℃伅鍜岀綉缁滀俊鎭暟缁勩 + rc = memset_s(u_sess->stat_cxt.localTimeInfoArray, sizeof(int64) * TOTAL_TIME_INFO_TYPES, 0, + sizeof(int64) * TOTAL_TIME_INFO_TYPES); securec_check(rc, "\0", "\0"); - rc = memset_s(u_sess->stat_cxt.localNetInfo, - sizeof(uint64) * TOTAL_NET_INFO_TYPES, - 0, - sizeof(uint64) * TOTAL_NET_INFO_TYPES); + rc = memset_s(u_sess->stat_cxt.localNetInfo, sizeof(uint64) * TOTAL_NET_INFO_TYPES, 0, + sizeof(uint64) * TOTAL_NET_INFO_TYPES); securec_check(rc, "\0", "\0"); } } /* generate result of pv_session_time view */ +/* + * 鍔熻兘锛氳幏鍙栦細璇濇椂闂寸姸鎬佷俊鎭紝骞跺皢鍏舵彃鍏ュ埌鍏冪粍瀛樺偍涓 + * + * 鍙傛暟鍒楄〃锛 + * tupStore锛氬厓缁勫瓨鍌ㄥ璞★紝鐢ㄤ簬瀛樺偍鑾峰彇鐨勪細璇濇椂闂寸姸鎬佷俊鎭 + * tupDesc锛氬厓缁勬弿杩扮锛屾弿杩板瓨鍌ㄧ殑鍏冪粍鏍煎紡 + * insert锛氭彃鍏ュ嚱鏁帮紝灏嗕細璇濇椂闂寸姸鎬佷俊鎭彃鍏ュ厓缁勫瓨鍌 + * + * 娉ㄦ剰锛 + * 1. 鍒嗛厤涓涓湰鍦颁細璇濇椂闂寸姸鎬佷俊鎭粨鏋勪綋 localEntry銆 + * 2. 閬嶅巻浼氳瘽鏃堕棿鐘舵佷俊鎭暟缁勶紝璇诲彇姣忎釜鏉$洰 entry 骞跺皢鍏跺鍒跺埌 localEntry銆 + * 3. 濡傛灉 localEntry 涓嶆椿璺冿紙isActive 涓 false锛夛紝鍒欒烦杩囪鏉$洰銆 + * 4. 璋冪敤鎻掑叆鍑芥暟灏 localEntry 鎻掑叆鍒 tupStore 涓 + * 5. 閲婃斁鏈湴浼氳瘽鏃堕棿鐘舵佷俊鎭粨鏋勪綋 localEntry銆 + */ void getSessionTimeStatus(Tuplestorestate *tupStore, TupleDesc tupDesc, - void (*insert)(Tuplestorestate *tupStore, TupleDesc tupDesc, const SessionTimeEntry *entry)) + void (*insert)(Tuplestorestate *tupStore, TupleDesc tupDesc, const SessionTimeEntry *entry)) { SessionTimeEntry *localEntry = NULL; SessionTimeEntry *entry = NULL; @@ -8171,14 +9102,29 @@ void getSessionTimeStatus(Tuplestorestate *tupStore, TupleDesc tupDesc, } /* generate result of pv_instance_time view */ -SessionTimeEntry* getInstanceTimeStatus() +/* + * 鍔熻兘锛氳幏鍙栧疄渚嬫椂闂寸姸鎬佷俊鎭 + * + * 杩斿洖鍊硷細 + * 杩斿洖涓涓寚鍚 SessionTimeEntry 缁撴瀯浣撶殑鎸囬拡锛屽寘鍚簡瀹炰緥鐨勬椂闂寸姸鎬佷俊鎭 + * + * 娉ㄦ剰锛 + * 1. 鍒嗛厤涓涓 SessionTimeEntry 缁撴瀯浣撶殑鍐呭瓨鍧 retEntry锛屽苟鍒濆鍖栦负闆躲 + * 2. 鑾峰彇瀹炰緥鏃堕棿閿 InstanceTimeLock锛堝叡浜攣锛変互閬嶅巻浼氳瘽鏃堕棿鐘舵佷俊鎭暟缁勩 + * 3. 閬嶅巻鏁扮粍涓殑姣忎釜鏉$洰 entry銆 + * 4. 濡傛灉鏉$洰鏄椿璺冪殑锛屽皢鍏跺唴瀹瑰鍒跺埌鏈湴 localEntry锛屽苟灏嗗叾鏃堕棿淇℃伅绱姞鍒 retEntry銆 + * 5. 閬嶅巻 gInstanceTimeInfo锛屽皢瀹炰緥鐨勬椂闂翠俊鎭疮鍔犲埌 retEntry銆 + * 6. 閲婃斁瀹炰緥鏃堕棿閿 InstanceTimeLock銆 + * 7. 杩斿洖 retEntry锛屽寘鍚簡瀹炰緥鐨勬椂闂寸姸鎬佷俊鎭 + */ +SessionTimeEntry *getInstanceTimeStatus() { - SessionTimeEntry* retEntry = NULL; + SessionTimeEntry *retEntry = NULL; SessionTimeEntry localEntry; - SessionTimeEntry* entry = NULL; + SessionTimeEntry *entry = NULL; int entryIndex, idx; - retEntry = (SessionTimeEntry*)palloc0(sizeof(SessionTimeEntry)); + retEntry = (SessionTimeEntry *)palloc0(sizeof(SessionTimeEntry)); LWLockAcquire(InstanceTimeLock, LW_SHARED); for (entryIndex = 0; entryIndex < SessionTimeArraySize; entryIndex++) { entry = &(t_thrd.shemem_ptr_cxt.sessionTimeArray[entryIndex]); @@ -8198,10 +9144,23 @@ SessionTimeEntry* getInstanceTimeStatus() } PgStat_RedoEntry redoStatistics; - +/* + * 鍔熻兘锛氭姤鍛婇噸鍋氭棩蹇楀啓鍏ョ粺璁′俊鎭 + * + * 鍙傛暟鍒楄〃锛 + * blks锛氬啓鍏ョ殑鍧楁暟 + * tim锛氬啓鍏ョ殑鏃堕棿 + * + * 娉ㄦ剰锛 + * 1. 濡傛灉鍐欏叆鐨勫潡鏁板皬浜庣瓑浜庨浂锛屽垯鐩存帴杩斿洖锛屼笉杩涜缁熻銆 + * 2. 澧炲姞 writes 璁℃暟锛岀疮鍔 writeBlks銆亀riteTime銆 + * 3. 璁$畻骞冲潎 IO 鏃堕棿 avgIOTime锛屽苟鏇存柊鏈鍚庝竴娆 IO 鏃堕棿 lstIOTime銆 + * 4. 濡傛灉褰撳墠 IO 鏃堕棿灏忎簬鏈灏 IO 鏃堕棿 minIOTime 鎴 minIOTime 涓洪浂锛屾洿鏂 minIOTime銆 + * 5. 濡傛灉褰撳墠 IO 鏃堕棿澶т簬鏈澶 IO 鏃堕棿 maxIOTime锛屾洿鏂 maxIOTime銆 + */ void reportRedoWrite(PgStat_Counter blks, PgStat_Counter tim) { - PgStat_RedoEntry* entry = &redoStatistics; + PgStat_RedoEntry *entry = &redoStatistics; if (0 >= blks) { return; @@ -8227,21 +9186,32 @@ Size sessionStatShmemSize(void) { return mul_size(sizeof(SessionLevelStatistic), SessionStatArraySize); } - +/* + * 鍔熻兘锛氬垵濮嬪寲浼氳瘽绾у埆缁熻淇℃伅鐨勫叡浜唴瀛 + * + * 娉ㄦ剰锛 + * 1. 濡傛灉鍏变韩鍐呭瓨涓嶅瓨鍦紙found = false锛夛紝鍒欏皢鍏跺唴瀹瑰垵濮嬪寲涓洪浂銆 + */ void sessionStatShmemInit(void) { bool found = false; errno_t rc; t_thrd.shemem_ptr_cxt.sessionStatArray = - (SessionLevelStatistic*)ShmemInitStruct("Session Statistic Array", sessionStatShmemSize(), &found); + (SessionLevelStatistic *)ShmemInitStruct("Session Statistic Array", sessionStatShmemSize(), &found); if (!found) { rc = memset_s(t_thrd.shemem_ptr_cxt.sessionStatArray, sessionStatShmemSize(), 0, sessionStatShmemSize()); securec_check(rc, "\0", "\0"); } } - +/* + * 鍔熻兘锛氬垵濮嬪寲浼氳瘽绾у埆缁熻淇℃伅鐨勫叆鍙 + * + * 娉ㄦ剰锛 + * 1. 浼氳瘽绾у埆缁熻淇℃伅鍖呮嫭浼氳瘽鐨勫紑濮嬫椂闂淬佷細璇滻D绛夈 + * 2. 鏍规嵁绾跨▼绫诲瀷鍒濆鍖栫浉搴旂殑缁熻淇℃伅銆 + */ void initMySessionStatEntry(void) { /* Initialize mySessionStatEntry */ @@ -8251,8 +9221,8 @@ void initMySessionStatEntry(void) if (t_thrd.proc_cxt.MyBackendId != InvalidBackendId) { Assert(t_thrd.proc_cxt.MyBackendId >= 1 && t_thrd.proc_cxt.MyBackendId <= (g_instance.attr.attr_common.enable_thread_pool - ? GLOBAL_RESERVE_SESSION_NUM - : g_instance.shmem_cxt.MaxBackends)); + ? GLOBAL_RESERVE_SESSION_NUM + : g_instance.shmem_cxt.MaxBackends)); t_thrd.shemem_ptr_cxt.mySessionStatEntry = &t_thrd.shemem_ptr_cxt.sessionStatArray[t_thrd.proc_cxt.MyBackendId - 1]; } else { @@ -8261,10 +9231,8 @@ void initMySessionStatEntry(void) t_thrd.shemem_ptr_cxt.mySessionStatEntry = &t_thrd.shemem_ptr_cxt.sessionStatArray[index]; } - errno_t rc = memset_s((SessionLevelStatistic*)t_thrd.shemem_ptr_cxt.mySessionStatEntry, - sizeof(SessionLevelStatistic), - 0, - sizeof(SessionLevelStatistic)); + errno_t rc = memset_s((SessionLevelStatistic *)t_thrd.shemem_ptr_cxt.mySessionStatEntry, + sizeof(SessionLevelStatistic), 0, sizeof(SessionLevelStatistic)); securec_check(rc, "\0", "\0"); t_thrd.shemem_ptr_cxt.mySessionStatEntry->sessionStartTime = t_thrd.proc_cxt.MyStartTime; @@ -8280,7 +9248,13 @@ void initMySessionStatEntry(void) on_shmem_exit(endMySessionStatEntry, 0); } - +/* + * 鍔熻兘锛氱粨鏉熶細璇濈骇鍒粺璁′俊鎭殑鍏ュ彛 + * + * 娉ㄦ剰锛 + * 1. 浼氬皢褰撳墠浼氳瘽鐨勬湁鏁堟爣蹇楄缃负涓嶆椿璺冦 + * 2. 涓嶅啀澶勭悊姝ゅ叆鍙c + */ static void endMySessionStatEntry(int code, Datum arg) { /* mark my entry not active. */ @@ -8293,6 +9267,14 @@ static void endMySessionStatEntry(int code, Datum arg) /* * attach mySessionStatEntry to session entry */ +/* + * 鍔熻兘锛氬叧鑱斿綋鍓嶄細璇濈殑浼氳瘽绾у埆缁熻淇℃伅 + * + * 娉ㄦ剰锛 + * 1. 鍋囧畾宸茬粡瀛樺湪鍏ㄥ眬鐨勪細璇濈粺璁′俊鎭暟缁勶紙sessionStatArray锛夈 + * 2. 鍋囧畾褰撳墠浼氳瘽鐨勪細璇滻D锛坰ession_id锛夊凡缁忚璁剧疆銆 + * 3. 濡傛灉褰撳墠浼氳瘽鐨勭粺璁′俊鎭棤鏁堬紝灏嗗垵濮嬪寲浼氳瘽缁熻淇℃伅銆 + */ void AttachMySessionStatEntry(void) { Assert(t_thrd.shemem_ptr_cxt.sessionStatArray); @@ -8314,76 +9296,130 @@ void AttachMySessionStatEntry(void) } /* generate result of pv_session_stat view */ -void getSessionStatistics(Tuplestorestate* tupStore, TupleDesc tupDesc, - void (* insert)(Tuplestorestate* tupStore, TupleDesc tupDesc, const SessionLevelStatistic* entry)) +/* + * 鍔熻兘锛氳幏鍙栦細璇濈骇鍒殑缁熻淇℃伅骞舵彃鍏ュ埌鎸囧畾鐨 Tuplestore 涓 + * + * 娉ㄦ剰锛 + * 1. 鍋囧畾宸茬粡瀛樺湪鍏ㄥ眬鐨勪細璇濈骇鍒粺璁′俊鎭暟缁勶紙sessionStatArray锛夈 + * 2. 浣跨敤缁欏畾鐨 insert 鍑芥暟灏嗘瘡涓湁鏁堢殑浼氳瘽缁熻淇℃伅鎻掑叆鍒 Tuplestore 涓 + */ +void getSessionStatistics(Tuplestorestate *tupStore, TupleDesc tupDesc, + void (*insert)(Tuplestorestate *tupStore, TupleDesc tupDesc, + const SessionLevelStatistic *entry)) { - SessionLevelStatistic* entry = NULL; - SessionLevelStatistic* localEntry = NULL; - + SessionLevelStatistic *entry = NULL; + SessionLevelStatistic *localEntry = NULL; int entryIndex; errno_t rc; - localEntry = (SessionLevelStatistic*)palloc0(sizeof(SessionLevelStatistic)); + localEntry = (SessionLevelStatistic *)palloc0(sizeof(SessionLevelStatistic)); for (entryIndex = 0; entryIndex < SessionStatArraySize; entryIndex++) { entry = &(t_thrd.shemem_ptr_cxt.sessionStatArray[entryIndex]); + + // 灏 entry 澶嶅埗鍒 localEntry rc = memcpy_s(localEntry, sizeof(SessionLevelStatistic), entry, sizeof(SessionLevelStatistic)); securec_check(rc, "\0", "\0"); if (!localEntry->isValid) continue; + + // 璋冪敤 insert 鍑芥暟灏 localEntry 鎻掑叆鍒 Tuplestore 涓 insert(tupStore, tupDesc, localEntry); } + pfree(localEntry); } PgStat_FileEntry pgStatFileArray[NUM_FILES]; uint32 fileStatCount = 0; -void reportFileStat(PgStat_MsgFile* msg) +/* + * 鍔熻兘锛氬彂閫佹枃浠剁粺璁′俊鎭粰缁熻妯″潡 + * + * 鍙傛暟鍒楄〃锛 + * msg: 瑕佸彂閫佺殑鏂囦欢缁熻淇℃伅 + * + * 娉ㄦ剰锛 + * 1. 閫氳繃璁剧疆娑堟伅澶村拰娑堟伅绫诲瀷鏉ュ噯澶囪鍙戦佺殑娑堟伅銆 + * 2. 浣跨敤 pgstat_send 鍑芥暟灏嗘秷鎭彂閫佺粰缁熻妯″潡銆 + */ +void reportFileStat(PgStat_MsgFile *msg) { + // 璁剧疆娑堟伅澶村拰娑堟伅绫诲瀷 pgstat_setheader(&(msg->m_hdr), PGSTAT_MTYPE_FILE); + + // 鍙戦佹秷鎭 pgstat_send(msg, sizeof(PgStat_MsgFile)); } -static void pgstat_recv_filestat(PgStat_MsgFile* msg, int len) +/* + * 鍔熻兘锛氭帴鏀舵枃浠剁粺璁′俊鎭苟鏇存柊鏂囦欢缁熻鏁版嵁 + * + * 鍙傛暟锛 + * - msg: 瑕佹帴鏀剁殑鏂囦欢缁熻淇℃伅 + * - len: 淇℃伅鐨勯暱搴 + * + * 娉ㄦ剰锛 + * 1. 濡傛灉鎺ユ敹鍒扮殑淇℃伅涓潡鏁板皬浜庣瓑浜0锛屼笉鍋氫换浣曞鐞嗭紝鐩存帴杩斿洖銆 + * 2. 閬嶅巻鏂囦欢缁熻鏁版嵁锛屾煡鎵炬槸鍚﹀凡缁忓瓨鍦ㄤ笌鎺ユ敹鍒颁俊鎭搴旂殑鏂囦欢銆 + * 3. 濡傛灉鏂囦欢涓嶅瓨鍦紝鍒欏垱寤轰竴涓柊鐨勬枃浠剁粺璁℃潯鐩紝骞跺皢鎺ユ敹鍒扮殑淇℃伅鏇存柊鍒拌鏉$洰涓 + * 4. 濡傛灉鏂囦欢宸茬粡瀛樺湪锛屽垯灏嗘帴鏀跺埌鐨勪俊鎭洿鏂板埌宸叉湁鐨勬枃浠剁粺璁℃潯鐩腑銆 + */ +static void pgstat_recv_filestat(PgStat_MsgFile *msg, int len) { - PgStat_FileEntry* entry = NULL; + PgStat_FileEntry *entry = NULL; int i; errno_t rc; + // 濡傛灉鎺ユ敹鍒扮殑鍧楁暟灏忎簬绛変簬0锛屼笉鍋氫换浣曞鐞嗭紝鐩存帴杩斿洖 if (0 >= msg->blks) { return; } + // 鑾峰彇鏂囦欢缁熻淇℃伅閿 LWLockAcquire(FileStatLock, LW_SHARED); + + // 閬嶅巻鏂囦欢缁熻鏁扮粍锛屾煡鎵炬槸鍚﹀凡缁忓瓨鍦ㄤ笌鎺ユ敹鍒颁俊鎭搴旂殑鏂囦欢 for (i = 0; i < NUM_FILES; i++) { - entry = (PgStat_FileEntry*)&pgStatFileArray[i]; + entry = (PgStat_FileEntry *)&pgStatFileArray[i]; if (entry->fn == msg->fn || entry->fn == InvalidOid) { break; } } + + // 閲婃斁鏂囦欢缁熻淇℃伅閿 LWLockRelease(FileStatLock); + // 濡傛灉閬嶅巻瀹屾暟缁勮繕娌℃湁鎵惧埌鍖归厤鐨勬枃浠讹紝鎴栬呮壘鍒颁簡涓涓棤鏁堢殑鏂囦欢缁熻鏉$洰 if (i == NUM_FILES || entry->fn == InvalidOid) { + // 鑾峰彇鏂囦欢缁熻淇℃伅閿侊紙鐙崰妯″紡锛 LWLockAcquire(FileStatLock, LW_EXCLUSIVE); - entry = (PgStat_FileEntry*)&pgStatFileArray[fileStatCount]; - /* reset this entry */ + // 鑾峰彇涓涓柊鐨勬枃浠剁粺璁℃潯鐩 + entry = (PgStat_FileEntry *)&pgStatFileArray[fileStatCount]; + + // 閲嶇疆璇ユ枃浠剁粺璁℃潯鐩 rc = memset_s(entry, sizeof(PgStat_FileEntry), 0, sizeof(PgStat_FileEntry)); securec_check(rc, "\0", "\0"); + // 鏇存柊鏂囦欢缁熻淇℃伅 entry->dbid = msg->dbid; entry->spcid = msg->spcid; entry->fn = msg->fn; + // 鏇存柊鏂囦欢缁熻鏁版嵁璁℃暟鍣 fileStatCount = (fileStatCount + 1) % NUM_FILES; + + // 閲婃斁鏂囦欢缁熻淇℃伅閿 LWLockRelease(FileStatLock); } + // 澧炲姞鏂囦欢缁熻淇℃伅鐨勬洿鏀硅鏁板櫒 entry->changeCount++; g_instance.stat_cxt.fileIOStat->changeCount++; + // 鏍规嵁娑堟伅涓殑璇诲啓绫诲瀷鏇存柊鏂囦欢缁熻鏁版嵁 if ('r' == msg->rw) { entry->reads += msg->cnt; entry->readBlks += msg->blks; @@ -8397,29 +9433,38 @@ static void pgstat_recv_filestat(PgStat_MsgFile* msg, int len) g_instance.stat_cxt.fileIOStat->writes += msg->cnt; g_instance.stat_cxt.fileIOStat->writeBlks += msg->blks; } + + // 澧炲姞鍏ㄥ眬鏂囦欢缁熻淇℃伅鐨勬洿鏀硅鏁板櫒 g_instance.stat_cxt.fileIOStat->changeCount++; + // 鏇存柊骞冲潎IO鏃堕棿 if ((entry->reads + entry->writes) <= 0) { entry->avgIOTime = 0; } else { entry->avgIOTime = (entry->readTime + entry->writeTime) / (entry->reads + entry->writes); } + // 鏇存柊鏈鍚庝竴娆O鏃堕棿 entry->lstIOTime = msg->lsttim; + + // 鏇存柊鏈灏廔O鏃堕棿 if (entry->minIOTime > msg->mintim || 0 == entry->minIOTime) { entry->minIOTime = msg->mintim; } + + // 鏇存柊鏈澶O鏃堕棿 if (entry->maxIOTime < msg->maxtim) { entry->maxIOTime = msg->maxtim; } + // 澧炲姞鏂囦欢缁熻淇℃伅鐨勬洿鏀硅鏁板櫒 entry->changeCount++; return; } /* clear key message that may appear in core file for security */ -PgBackendStatus* GetMyBEEntry(void) +PgBackendStatus *GetMyBEEntry(void) { return t_thrd.shemem_ptr_cxt.MyBEEntry; } @@ -8431,40 +9476,59 @@ Size sessionMemoryShmemSize(void) return mul_size(sizeof(SessionLevelMemory), SessionMemoryArraySize); } +/* + * 鍔熻兘锛氬垵濮嬪寲浼氳瘽鍐呭瓨缁熻鏁版嵁鐨勫叡浜唴瀛 + * + * 娉ㄦ剰锛 + * 1. 棣栧厛灏濊瘯鑾峰彇鍏变韩鍐呭瓨锛屽鏋滄壘鍒板凡瀛樺湪鐨勫垯鐩存帴浣跨敤锛屽惁鍒欏垱寤轰竴涓柊鐨勫叡浜唴瀛樻銆 + * 2. 濡傛灉鍒涘缓浜嗘柊鐨勫叡浜唴瀛樻锛屽垯闇瑕佸皢鍏变韩鍐呭瓨娓呴浂浠ュ垵濮嬪寲銆 + */ void sessionMemoryShmemInit(void) { bool found = false; errno_t rc; + // 灏濊瘯鑾峰彇鍏变韩鍐呭瓨锛屽鏋滄壘鍒板凡瀛樺湪鐨勫垯鐩存帴浣跨敤锛屽惁鍒欏垱寤轰竴涓柊鐨勫叡浜唴瀛樻 t_thrd.shemem_ptr_cxt.sessionMemoryArray = - (SessionLevelMemory*)ShmemInitStruct("Session Memory Array", sessionMemoryShmemSize(), &found); + (SessionLevelMemory *)ShmemInitStruct("Session Memory Array", sessionMemoryShmemSize(), &found); if (!found) { + // 濡傛灉鍒涘缓浜嗘柊鐨勫叡浜唴瀛樻锛屽垯闇瑕佸皢鍏变韩鍐呭瓨娓呴浂浠ュ垵濮嬪寲 rc = memset_s(t_thrd.shemem_ptr_cxt.sessionMemoryArray, sessionMemoryShmemSize(), 0, sessionMemoryShmemSize()); securec_check(rc, "\0", "\0"); } } +/* + * 鍔熻兘锛氬垵濮嬪寲褰撳墠浼氳瘽鐨勫唴瀛樼粺璁℃暟鎹 + * + * 娉ㄦ剰锛 + * 1. 棣栧厛妫鏌ュ叡浜唴瀛樻槸鍚﹀凡缁忚鍒濆鍖栥 + * 2. 鏍规嵁褰撳墠绾跨▼绫诲瀷锛堝悗鍙扮嚎绋嬫垨杈呭姪绾跨▼锛夌‘瀹氳鍒濆鍖栫殑浼氳瘽鍐呭瓨缁熻鏁版嵁鐨勪綅缃 + * 3. 灏嗕細璇濆唴瀛樼粺璁℃暟鎹殑鍚勪釜瀛楁鍒濆鍖栦负0鎴栭粯璁ゅ笺 + * 4. 鏈鍚庢敞鍐屼竴涓洖璋冨嚱鏁帮紝鍦ㄨ繘绋嬮鍑烘椂杩涜娓呯悊銆 + */ void initMySessionMemoryEntry(void) { - /* Initialize mySessionStatEntry */ + // 妫鏌ュ叡浜唴瀛樻槸鍚﹀凡缁忚鍒濆鍖 Assert(t_thrd.shemem_ptr_cxt.sessionMemoryArray); - // backend thread + // 鏍规嵁褰撳墠绾跨▼绫诲瀷锛堝悗鍙扮嚎绋嬫垨杈呭姪绾跨▼锛夌‘瀹氳鍒濆鍖栫殑浼氳瘽鍐呭瓨缁熻鏁版嵁鐨勪綅缃 if (t_thrd.proc_cxt.MyBackendId != InvalidBackendId) { Assert(t_thrd.proc_cxt.MyBackendId >= 1 && t_thrd.proc_cxt.MyBackendId <= (g_instance.attr.attr_common.enable_thread_pool - ? GLOBAL_RESERVE_SESSION_NUM - : g_instance.shmem_cxt.MaxBackends)); + ? GLOBAL_RESERVE_SESSION_NUM + : g_instance.shmem_cxt.MaxBackends)); t_thrd.shemem_ptr_cxt.mySessionMemoryEntry = &t_thrd.shemem_ptr_cxt.sessionMemoryArray[t_thrd.proc_cxt.MyBackendId - 1]; } else { - // Auxiliary thread + // 杈呭姪绾跨▼ int index = GetAuxProcStatEntryIndex(); t_thrd.shemem_ptr_cxt.mySessionMemoryEntry = &t_thrd.shemem_ptr_cxt.sessionMemoryArray[index]; } errno_t rc = EOK; + // 灏嗕細璇濆唴瀛樼粺璁℃暟鎹殑鍚勪釜瀛楁鍒濆鍖栦负0鎴栭粯璁ゅ rc = memset_s(t_thrd.shemem_ptr_cxt.mySessionMemoryEntry, sizeof(SessionLevelMemory), 0, sizeof(SessionLevelMemory)); securec_check(rc, "\0", "\0"); @@ -8493,9 +9557,17 @@ void initMySessionMemoryEntry(void) t_thrd.shemem_ptr_cxt.mySessionMemoryEntry->dnEndTime = 0; t_thrd.shemem_ptr_cxt.mySessionMemoryEntry->isValid = true; + // 娉ㄥ唽涓涓洖璋冨嚱鏁帮紝鍦ㄨ繘绋嬮鍑烘椂杩涜娓呯悊 on_shmem_exit(endMySessionMemoryEntry, 0); } - +/* + * 鍔熻兘锛氬湪杩涚▼閫鍑烘椂缁撴潫褰撳墠浼氳瘽鐨勫唴瀛樼粺璁℃暟鎹紝閲婃斁鐩稿叧鍐呭瓨 + * + * 娉ㄦ剰锛 + * 1. 閲婃斁褰撳墠浼氳瘽鐨勫唴瀛樼粺璁℃暟鎹 + * 2. 灏嗕細璇濆唴瀛樼粺璁℃暟鎹爣璁颁负鏃犳晥銆 + * 3. 娓呯┖浼氳瘽鍐呭瓨缁熻鏁版嵁鐨勬寚閽堬紝纭繚涓嶅啀浣跨敤璇ユ暟鎹 + */ static void endMySessionMemoryEntry(int code, Datum arg) { @@ -8512,22 +9584,40 @@ static void endMySessionMemoryEntry(int code, Datum arg) /* * attach mySessionMemoryEntry to session entry */ +/* + * 鍔熻兘锛氬叧鑱斿綋鍓嶄細璇濈殑鍐呭瓨缁熻鏁版嵁 + * + * 娉ㄦ剰锛 + * 1. 纭繚浼氳瘽鍐呭瓨缁熻鏁版嵁鏁扮粍宸茬粡鍒嗛厤銆 + * 2. 纭繚褰撳墠浼氳瘽鐨勭储寮曞湪鍚堢悊鐨勮寖鍥村唴銆 + * 3. 纭繚褰撳墠浼氳瘽鐨勫悗绔 ID 涓嶆槸鏃犳晥鐨勩 + * 4. 璁剧疆浼氳瘽鍐呭瓨缁熻鏁版嵁鐨勬寚閽堬紝浣垮叾鎸囧悜褰撳墠浼氳瘽鐨勫唴瀛樼粺璁℃暟鎹 + * 5. 濡傛灉褰撳墠浼氳瘽鐨勫唴瀛樼粺璁℃暟鎹棤鏁堬紝鍒濆鍖栧畠銆 + * 6. 灏嗗綋鍓嶄細璇濈殑鍚庣 ID 鍏宠仈鍒颁細璇濆唴瀛樼粺璁℃暟鎹 + */ void AttachMySessionMemoryEntry(void) { + /* 纭繚浼氳瘽鍐呭瓨缁熻鏁版嵁鏁扮粍宸茬粡鍒嗛厤 */ Assert(t_thrd.shemem_ptr_cxt.sessionMemoryArray); + + /* 纭繚褰撳墠浼氳瘽鐨勭储寮曞湪鍚堢悊鐨勮寖鍥村唴 */ Assert(u_sess->session_ctr_index >= GLOBAL_RESERVE_SESSION_NUM && u_sess->session_ctr_index < MAX_BACKEND_SLOT); + + /* 纭繚褰撳墠浼氳瘽鐨勫悗绔 ID 涓嶆槸鏃犳晥鐨 */ Assert(t_thrd.proc_cxt.MyBackendId != InvalidBackendId); + + /* 纭繚褰撳墠浼氳瘽鐨勫唴瀛樼粺璁℃暟鎹寚閽堟槸姝g‘鐨 */ Assert(t_thrd.shemem_ptr_cxt.mySessionMemoryEntry == &t_thrd.shemem_ptr_cxt.sessionMemoryArray[t_thrd.proc_cxt.MyBackendId - 1]); - /* change stat object to session */ + /* 璁剧疆浼氳瘽鍐呭瓨缁熻鏁版嵁鐨勬寚閽堬紝浣垮叾鎸囧悜褰撳墠浼氳瘽鐨勫唴瀛樼粺璁℃暟鎹 */ t_thrd.shemem_ptr_cxt.mySessionMemoryEntry = &t_thrd.shemem_ptr_cxt.sessionMemoryArray[u_sess->session_ctr_index]; - /* initialize entry if necessary */ + /* 濡傛灉褰撳墠浼氳瘽鐨勫唴瀛樼粺璁℃暟鎹棤鏁堬紝鍒濆鍖栧畠 */ if (t_thrd.shemem_ptr_cxt.mySessionMemoryEntry->isValid == false) { errno_t rc = EOK; - rc = memset_s( - t_thrd.shemem_ptr_cxt.mySessionMemoryEntry, sizeof(SessionLevelMemory), 0, sizeof(SessionLevelMemory)); + rc = memset_s(t_thrd.shemem_ptr_cxt.mySessionMemoryEntry, sizeof(SessionLevelMemory), 0, + sizeof(SessionLevelMemory)); securec_check(rc, "\0", "\0"); t_thrd.shemem_ptr_cxt.mySessionMemoryEntry->threadStartTime = timestamptz_to_time_t(u_sess->proc_cxt.MyProcPort->SessionStartTime); @@ -8549,20 +9639,20 @@ void AttachMySessionMemoryEntry(void) t_thrd.shemem_ptr_cxt.mySessionMemoryEntry->isValid = true; } - /* worker's pgproc memory info is also related to the session */ + /* 灏嗗綋鍓嶄細璇濈殑鍚庣 ID 鍏宠仈鍒颁細璇濆唴瀛樼粺璁℃暟鎹 */ t_thrd.proc->sessMemorySessionid = u_sess->session_id; } /* generate result of pv_session_stat view */ -void getSessionMemory(Tuplestorestate* tupStore, TupleDesc tupDesc, - void (* insert)(Tuplestorestate* tupStore, TupleDesc tupDesc, const SessionLevelMemory* entry)) +void getSessionMemory(Tuplestorestate *tupStore, TupleDesc tupDesc, + void (*insert)(Tuplestorestate *tupStore, TupleDesc tupDesc, const SessionLevelMemory *entry)) { - SessionLevelMemory* localEntry = NULL; - SessionLevelMemory* entry = NULL; + SessionLevelMemory *localEntry = NULL; + SessionLevelMemory *entry = NULL; int entryIndex; errno_t rc; - localEntry = (SessionLevelMemory*)palloc0(sizeof(SessionLevelMemory)); + localEntry = (SessionLevelMemory *)palloc0(sizeof(SessionLevelMemory)); for (entryIndex = 0; entryIndex < SessionMemoryArraySize; entryIndex++) { entry = &(t_thrd.shemem_ptr_cxt.sessionMemoryArray[entryIndex]); rc = memcpy_s(localEntry, sizeof(SessionLevelMemory), entry, sizeof(SessionLevelMemory)); @@ -8577,10 +9667,10 @@ void getSessionMemory(Tuplestorestate* tupStore, TupleDesc tupDesc, pfree(localEntry); } -typedef AllocSetContext* AllocSet; +typedef AllocSetContext *AllocSet; -static void calculateThreadMemoryContextStats(const volatile PGPROC* proc, const MemoryContext context, bool isShared, - Tuplestorestate* tupStore, TupleDesc tupDesc) +static void calculateThreadMemoryContextStats(const volatile PGPROC *proc, const MemoryContext context, bool isShared, + Tuplestorestate *tupStore, TupleDesc tupDesc) { AllocSet set = (AllocSet)context; @@ -8592,10 +9682,8 @@ static void calculateThreadMemoryContextStats(const volatile PGPROC* proc, const if (proc != NULL) { threadId = proc->pid; - rc = strncpy_s(threadType, - PROC_NAME_LEN, - (proc->myProgName != NULL) ? (const char*)proc->myProgName : "", - PROC_NAME_LEN - 1); + rc = strncpy_s(threadType, PROC_NAME_LEN, (proc->myProgName != NULL) ? (const char *)proc->myProgName : "", + PROC_NAME_LEN - 1); securec_check(rc, "\0", "\0"); getSessionID(sessId, proc->myStartTime, threadId); } else { @@ -8640,8 +9728,8 @@ static void calculateThreadMemoryContextStats(const volatile PGPROC* proc, const } } -static void recursiveThreadMemoryContext(const volatile PGPROC* proc, const MemoryContext context, bool isShared, - Tuplestorestate* tupStore, TupleDesc tupDesc) +static void recursiveThreadMemoryContext(const volatile PGPROC *proc, const MemoryContext context, bool isShared, + Tuplestorestate *tupStore, TupleDesc tupDesc) { MemoryContext child; @@ -8687,7 +9775,7 @@ static void recursiveThreadMemoryContext(const volatile PGPROC* proc, const Memo * Brief : * Description : */ -void getSharedMemoryDetail(Tuplestorestate* tupStore, TupleDesc tupDesc) +void getSharedMemoryDetail(Tuplestorestate *tupStore, TupleDesc tupDesc) { recursiveThreadMemoryContext(NULL, g_instance.instance_context, true, tupStore, tupDesc); } @@ -8700,11 +9788,11 @@ void getSharedMemoryDetail(Tuplestorestate* tupStore, TupleDesc tupDesc) * Notes : * Author : */ -void getThreadMemoryDetail(Tuplestorestate* tupStore, TupleDesc tupDesc, uint32* procIdx) +void getThreadMemoryDetail(Tuplestorestate *tupStore, TupleDesc tupDesc, uint32 *procIdx) { - uint32 max_thread_count = g_instance.proc_base->allProcCount - - g_instance.attr.attr_storage.max_prepared_xacts * NUM_TWOPHASE_PARTITIONS; - volatile PGPROC* proc = NULL; + uint32 max_thread_count = + g_instance.proc_base->allProcCount - g_instance.attr.attr_storage.max_prepared_xacts * NUM_TWOPHASE_PARTITIONS; + volatile PGPROC *proc = NULL; uint32 idx = 0; PG_TRY(); @@ -8716,10 +9804,10 @@ void getThreadMemoryDetail(Tuplestorestate* tupStore, TupleDesc tupDesc, uint32* *procIdx = idx; /* lock this proc's delete MemoryContext action */ - (void)syscalllockAcquire(&((PGPROC*)proc)->deleMemContextMutex); + (void)syscalllockAcquire(&((PGPROC *)proc)->deleMemContextMutex); if (proc->topmcxt != NULL) recursiveThreadMemoryContext(proc, proc->topmcxt, false, tupStore, tupDesc); - (void)syscalllockRelease(&((PGPROC*)proc)->deleMemContextMutex); + (void)syscalllockRelease(&((PGPROC *)proc)->deleMemContextMutex); } /* get memory context detail from postmaster thread */ @@ -8732,7 +9820,7 @@ void getThreadMemoryDetail(Tuplestorestate* tupStore, TupleDesc tupDesc, uint32* { if (*procIdx < max_thread_count) { proc = g_instance.proc_base_all_procs[*procIdx]; - (void)syscalllockRelease(&((PGPROC*)proc)->deleMemContextMutex); + (void)syscalllockRelease(&((PGPROC *)proc)->deleMemContextMutex); } PG_RE_THROW(); } @@ -8742,10 +9830,10 @@ void getThreadMemoryDetail(Tuplestorestate* tupStore, TupleDesc tupDesc, uint32* //////////////////////////////////////////////////////////////////////////////// #ifdef MEMORY_CONTEXT_CHECKING -extern void dumpAllocBlock(AllocSet set, StringInfoData* buf); -extern void dumpAsanBlock(AsanSet set, StringInfoData* buf); +extern void dumpAllocBlock(AllocSet set, StringInfoData *buf); +extern void dumpAsanBlock(AsanSet set, StringInfoData *buf); -static void recursiveMemoryContextForDump(const MemoryContext context, char* ctx_name, StringInfoData* buf) +static void recursiveMemoryContextForDump(const MemoryContext context, char *ctx_name, StringInfoData *buf) { #ifndef ENABLE_MEMORY_CHECK if (!strcmp(ctx_name, context->name) && @@ -8776,15 +9864,12 @@ void DumpMemoryContext(DUMP_TYPE type) // get the path of dump file is_absolute = is_absolute_path(u_sess->attr.attr_common.Log_directory); if (is_absolute) { - ss_rc = snprintf_s( - dump_dir, sizeof(dump_dir), sizeof(dump_dir) - 1, "%s/memdump", u_sess->attr.attr_common.Log_directory); + ss_rc = snprintf_s(dump_dir, sizeof(dump_dir), sizeof(dump_dir) - 1, "%s/memdump", + u_sess->attr.attr_common.Log_directory); securec_check_ss(ss_rc, "\0", "\0"); } else { - ss_rc = snprintf_s(dump_dir, - sizeof(dump_dir), - sizeof(dump_dir) - 1, - "%s/pg_log/memdump", - g_instance.attr.attr_common.data_directory); + ss_rc = snprintf_s(dump_dir, sizeof(dump_dir), sizeof(dump_dir) - 1, "%s/pg_log/memdump", + g_instance.attr.attr_common.data_directory); securec_check_ss(ss_rc, "\0", "\0"); } @@ -8814,20 +9899,15 @@ void DumpMemoryContext(DUMP_TYPE type) char dump_file[MAX_PATH_LEN] = {0}; #ifdef ENABLE_MEMORY_CHECK pid_t pid = getpid(); - int rc = sprintf_s(dump_file, - MAX_PATH_LEN, - "%s/%s_%s_%d.log", - dump_dir, - g_instance.attr.attr_common.PGXCNodeName, - g_instance.instance_context->name, - pid); + int rc = sprintf_s(dump_file, MAX_PATH_LEN, "%s/%s_%s_%d.log", dump_dir, g_instance.attr.attr_common.PGXCNodeName, + g_instance.instance_context->name, pid); #else ThreadId tid = gs_thread_self(); - int rc = sprintf_s( - dump_file, MAX_PATH_LEN, "%s/%s_%lu_%lu.log", dump_dir, ctx_name, (unsigned long)tid, (uint64)time(NULL)); + int rc = sprintf_s(dump_file, MAX_PATH_LEN, "%s/%s_%lu_%lu.log", dump_dir, ctx_name, (unsigned long)tid, + (uint64)time(NULL)); #endif securec_check_ss(rc, "\0", "\0"); - FILE* dump_fp = fopen(dump_file, "w"); + FILE *dump_fp = fopen(dump_file, "w"); if (NULL == dump_fp) { elog(LOG, "dump_memory: Failed to create file: %s, cause: %s", dump_file, strerror(errno)); return; @@ -8877,15 +9957,15 @@ void DumpMemoryContext(DUMP_TYPE type) } #endif // MEMORY_CONTEXT_CHECKING -static void FetchLWLockInfoOfAllBackends(lwm_lwlocks** lwlockInfo, int& nBackends) +static void FetchLWLockInfoOfAllBackends(lwm_lwlocks **lwlockInfo, int &nBackends) { nBackends = BackendStatusArray_size; - *lwlockInfo = (lwm_lwlocks*)palloc0(sizeof(lwm_lwlocks) * nBackends); + *lwlockInfo = (lwm_lwlocks *)palloc0(sizeof(lwm_lwlocks) * nBackends); - lwm_lwlocks* lwlock = *lwlockInfo; + lwm_lwlocks *lwlock = *lwlockInfo; for (int n = 0; n < nBackends; ++n) { - volatile PgBackendStatus* beentry = t_thrd.shemem_ptr_cxt.BackendStatusArray + n; + volatile PgBackendStatus *beentry = t_thrd.shemem_ptr_cxt.BackendStatusArray + n; /* we must guarantee atomic for set access flag */ START_CRIT_SECTION(); @@ -8919,9 +9999,9 @@ static void FetchLWLockInfoOfAllBackends(lwm_lwlocks** lwlockInfo, int& nBackend lwlock->want_lwlock.lock = beentry->lw_want_lock; const int needSize = (sizeof(lwlock_id_mode) * lwlock->lwlocks_num); if (lwlock->held_lwlocks != NULL) { - lwlock->held_lwlocks = (lwlock_id_mode*)repalloc(lwlock->held_lwlocks, needSize); + lwlock->held_lwlocks = (lwlock_id_mode *)repalloc(lwlock->held_lwlocks, needSize); } else { - lwlock->held_lwlocks = (lwlock_id_mode*)palloc0(needSize); + lwlock->held_lwlocks = (lwlock_id_mode *)palloc0(needSize); } copy_held_lwlocks(beentry->lw_held_locks, lwlock->held_lwlocks, lwlock->lwlocks_num); @@ -8947,24 +10027,19 @@ static void FetchLWLockInfoOfAllBackends(lwm_lwlocks** lwlockInfo, int& nBackend nBackends = (lwlock - *lwlockInfo); } -static void OutLogLWLockInfoOfAllBackends(lwm_lwlocks* lwlockInfo, int nBackends) +static void OutLogLWLockInfoOfAllBackends(lwm_lwlocks *lwlockInfo, int nBackends) { StringInfoData fmtOutLog; initStringInfo(&fmtOutLog); - lwm_lwlocks* info = lwlockInfo; + lwm_lwlocks *info = lwlockInfo; for (int beIdx = 0; beIdx < nBackends; ++beIdx) { /* format lwlock info of each backend */ - appendStringInfo(&fmtOutLog, - "[LWLOCK INFO] thread %lu, required (%s), held num %d, locks(name, mode):", - info->be_tid.thread_id, - T_NAME(info->want_lwlock.lock), - info->lwlocks_num); + appendStringInfo(&fmtOutLog, "[LWLOCK INFO] thread %lu, required (%s), held num %d, locks(name, mode):", + info->be_tid.thread_id, T_NAME(info->want_lwlock.lock), info->lwlocks_num); for (int lockIdx = 0; lockIdx < info->lwlocks_num; ++lockIdx) { - appendStringInfo(&fmtOutLog, - "(%s, %d)", - T_NAME(info->held_lwlocks[lockIdx].lock_addr.lock), - info->held_lwlocks[lockIdx].lock_sx); + appendStringInfo(&fmtOutLog, "(%s, %d)", T_NAME(info->held_lwlocks[lockIdx].lock_addr.lock), + info->held_lwlocks[lockIdx].lock_sx); } /* print lwlock info of each backend */ ereport(LOG, (errmsg("%s", fmtOutLog.data))); @@ -8976,9 +10051,9 @@ static void OutLogLWLockInfoOfAllBackends(lwm_lwlocks* lwlockInfo, int nBackends pfree(fmtOutLog.data); } -static void FreeLWLockInfoOfAllBackends(lwm_lwlocks* lwlockInfo, int nBackends) +static void FreeLWLockInfoOfAllBackends(lwm_lwlocks *lwlockInfo, int nBackends) { - lwm_lwlocks* info = lwlockInfo; + lwm_lwlocks *info = lwlockInfo; for (int i = 0; i < nBackends; ++i) { pfree(info->held_lwlocks); ++info; @@ -8988,7 +10063,7 @@ static void FreeLWLockInfoOfAllBackends(lwm_lwlocks* lwlockInfo, int nBackends) void DumpLWLockInfoToServerLog(void) { - lwm_lwlocks* lwlockInfo = NULL; + lwm_lwlocks *lwlockInfo = NULL; int nBackends = 0; FetchLWLockInfoOfAllBackends(&lwlockInfo, nBackends); OutLogLWLockInfoOfAllBackends(lwlockInfo, nBackends); @@ -8998,13 +10073,13 @@ void DumpLWLockInfoToServerLog(void) /* * read light-weight detect data from backends data. */ -lwm_light_detect* pgstat_read_light_detect(void) +lwm_light_detect *pgstat_read_light_detect(void) { const int n = BackendStatusArray_size; /* reset all this memory be 0 */ - lwm_light_detect* lw_detect = (lwm_light_detect*)palloc0(sizeof(lwm_light_detect) * n); - lwm_light_detect* lw_det = lw_detect; - volatile PgBackendStatus* beentry = t_thrd.shemem_ptr_cxt.BackendStatusArray; + lwm_light_detect *lw_detect = (lwm_light_detect *)palloc0(sizeof(lwm_light_detect) * n); + lwm_light_detect *lw_det = lw_detect; + volatile PgBackendStatus *beentry = t_thrd.shemem_ptr_cxt.BackendStatusArray; for (int i = 0; i < n; i++) { lwm_light_detect ld = {0, 0}; @@ -9052,12 +10127,12 @@ lwm_light_detect* pgstat_read_light_detect(void) * these diagnosis information includes: 1) lwlock to require; 2) thread id; * 3) the number and id of lwlocks held by this thread; */ -lwm_lwlocks* pgstat_read_diagnosis_data(lwm_light_detect* light_det, const int* candidates_pos, int num_candidates) +lwm_lwlocks *pgstat_read_diagnosis_data(lwm_light_detect *light_det, const int *candidates_pos, int num_candidates) { Size need_size = sizeof(lwm_lwlocks) * (uint32)num_candidates; /* Must all these memory be reset be 0 */ - lwm_lwlocks* lwlocks = (lwm_lwlocks*)palloc0(need_size); - lwm_lwlocks* cur_lwlock = NULL; + lwm_lwlocks *lwlocks = (lwm_lwlocks *)palloc0(need_size); + lwm_lwlocks *cur_lwlock = NULL; lwm_lwlocks tmplock; errno_t errval = memset_s(&tmplock, sizeof(tmplock), 0, sizeof(tmplock)); securec_check_errval(errval, , LOG); @@ -9066,10 +10141,10 @@ lwm_lwlocks* pgstat_read_diagnosis_data(lwm_light_detect* light_det, const int* for (int i = 0; i < num_candidates; i++) { /* remember its position */ tmplock.be_idx = candidates_pos[i]; - tmplock.held_lwlocks = (lwlock_id_mode*)palloc0(get_held_lwlocks_maxnum() * sizeof(lwlock_id_mode)); + tmplock.held_lwlocks = (lwlock_id_mode *)palloc0(get_held_lwlocks_maxnum() * sizeof(lwlock_id_mode)); - volatile PgBackendStatus* beentry = t_thrd.shemem_ptr_cxt.BackendStatusArray + candidates_pos[i]; - lwm_light_detect* cur_det = light_det + candidates_pos[i]; + volatile PgBackendStatus *beentry = t_thrd.shemem_ptr_cxt.BackendStatusArray + candidates_pos[i]; + lwm_light_detect *cur_det = light_det + candidates_pos[i]; bool success = true; /* We must guarantee atomic for set access flag */ @@ -9140,7 +10215,7 @@ lwm_lwlocks* pgstat_read_diagnosis_data(lwm_light_detect* light_det, const int* /* read xact starting time of this thread */ TimestampTz pgstat_read_xact_start_tm(int be_index) { - volatile PgBackendStatus* beentry = t_thrd.shemem_ptr_cxt.BackendStatusArray + be_index; + volatile PgBackendStatus *beentry = t_thrd.shemem_ptr_cxt.BackendStatusArray + be_index; TimestampTz tmp_xact_tm = 0; /* read xact starting time from this backend */ @@ -9166,42 +10241,41 @@ TimestampTz pgstat_read_xact_start_tm(int be_index) * @return : distribution info contain function state and tuple slot. * NOTICE : the memory palloced in this function should be free outside where it was called. */ -TableDistributionInfo* getTableDataDistribution(TupleDesc tuple_desc, char* schema_name, char* table_name) +TableDistributionInfo *getTableDataDistribution(TupleDesc tuple_desc, char *schema_name, char *table_name) { StringInfoData buf; - TableDistributionInfo* distribuion_info = NULL; + TableDistributionInfo *distribuion_info = NULL; /* the memory palloced here should be free outside where it was called. */ - distribuion_info = (TableDistributionInfo*)palloc0(sizeof(TableDistributionInfo)); + distribuion_info = (TableDistributionInfo *)palloc0(sizeof(TableDistributionInfo)); initStringInfo(&buf); if (schema_name != NULL && table_name != NULL) { /* get only one table's distribution info */ appendStringInfo(&buf, - "select " - "n.nspname, " - "c.relname, " - "pg_catalog.pgxc_node_str(), " - "pg_catalog.pg_table_size(c.oid) " - "from pg_catalog.pg_class c " - "inner join pg_catalog.pg_namespace n on c.relnamespace = n.oid " - "where n.nspname = \'%s\' and c.relname=\'%s\' ", - schema_name, - table_name); + "select " + "n.nspname, " + "c.relname, " + "pg_catalog.pgxc_node_str(), " + "pg_catalog.pg_table_size(c.oid) " + "from pg_catalog.pg_class c " + "inner join pg_catalog.pg_namespace n on c.relnamespace = n.oid " + "where n.nspname = \'%s\' and c.relname=\'%s\' ", + schema_name, table_name); } else { /* get all table's distribution in current database and we only get info about user's table without catalog * table. */ appendStringInfo(&buf, - "select " - "n.nspname, " - "c.relname, " - "pg_catalog.pgxc_node_str(), " - "pg_catalog.pg_table_size(c.oid) " - "from pg_class c " - "inner join pg_catalog.pg_namespace n on c.relnamespace = n.oid " - "where c.relkind = 'r' and c.oid > %d and n.nspname <> 'cstore' and n.nspname <> 'pmk';", - FirstNormalObjectId); + "select " + "n.nspname, " + "c.relname, " + "pg_catalog.pgxc_node_str(), " + "pg_catalog.pg_table_size(c.oid) " + "from pg_class c " + "inner join pg_catalog.pg_namespace n on c.relnamespace = n.oid " + "where c.relkind = 'r' and c.oid > %d and n.nspname <> 'cstore' and n.nspname <> 'pmk';", + FirstNormalObjectId); } /* send sql and parallel fetch distribution info from all data nodes */ @@ -9211,56 +10285,53 @@ TableDistributionInfo* getTableDataDistribution(TupleDesc tuple_desc, char* sche return distribuion_info; } -TableDistributionInfo* getTableStat(TupleDesc tuple_desc, int dirty_pecent, int n_tuples, char* schema_name) +TableDistributionInfo *getTableStat(TupleDesc tuple_desc, int dirty_pecent, int n_tuples, char *schema_name) { StringInfoData buf; - TableDistributionInfo* distribuion_info = NULL; + TableDistributionInfo *distribuion_info = NULL; /* the memory palloced here should be free outside where it was called. */ - distribuion_info = (TableDistributionInfo*)palloc0(sizeof(TableDistributionInfo)); + distribuion_info = (TableDistributionInfo *)palloc0(sizeof(TableDistributionInfo)); initStringInfo(&buf); /* get all table's stat in current database and we only get info about user's table without catalog table. */ if (schema_name == NULL) appendStringInfo(&buf, - "select " - "c.relname, " - "n.nspname, " - "pg_stat_get_tuples_inserted(c.oid), " - "pg_stat_get_tuples_updated(c.oid), " - "pg_stat_get_tuples_deleted(c.oid), " - "pg_stat_get_live_tuples(c.oid) n_live_tuples, " - "pg_stat_get_dead_tuples(c.oid) n_dead_tuples " - "from pg_class c " - "left join pg_namespace n on (c.relnamespace = n.oid) " - "where c.relkind = 'r' and relpersistence <> 't' " - "and cast((n_dead_tuples)/(n_live_tuples+n_dead_tuples+0.00001) * 100 " - "as numeric(5,2)) >= %d " - "and (n_live_tuples+n_dead_tuples) >= %d " - "and n.nspname not in ('pg_toast','information_schema','cstore','pmk'); ", - dirty_pecent, - n_tuples); + "select " + "c.relname, " + "n.nspname, " + "pg_stat_get_tuples_inserted(c.oid), " + "pg_stat_get_tuples_updated(c.oid), " + "pg_stat_get_tuples_deleted(c.oid), " + "pg_stat_get_live_tuples(c.oid) n_live_tuples, " + "pg_stat_get_dead_tuples(c.oid) n_dead_tuples " + "from pg_class c " + "left join pg_namespace n on (c.relnamespace = n.oid) " + "where c.relkind = 'r' and relpersistence <> 't' " + "and cast((n_dead_tuples)/(n_live_tuples+n_dead_tuples+0.00001) * 100 " + "as numeric(5,2)) >= %d " + "and (n_live_tuples+n_dead_tuples) >= %d " + "and n.nspname not in ('pg_toast','information_schema','cstore','pmk'); ", + dirty_pecent, n_tuples); else appendStringInfo(&buf, - "select " - "c.relname, " - "n.nspname, " - "pg_stat_get_tuples_inserted(c.oid), " - "pg_stat_get_tuples_updated(c.oid), " - "pg_stat_get_tuples_deleted(c.oid), " - "pg_stat_get_live_tuples(c.oid) n_live_tuples, " - "pg_stat_get_dead_tuples(c.oid) n_dead_tuples " - "from pg_class c " - "left join pg_namespace n on (c.relnamespace = n.oid) " - "where c.relkind = 'r' and relpersistence <> 't' " - "and cast((n_dead_tuples)/(n_live_tuples+n_dead_tuples+0.00001) * 100 " - "as numeric(5,2)) >= %d " - "and (n_live_tuples+n_dead_tuples) >= %d " - "and n.nspname = \'%s\'; ", - dirty_pecent, - n_tuples, - schema_name); + "select " + "c.relname, " + "n.nspname, " + "pg_stat_get_tuples_inserted(c.oid), " + "pg_stat_get_tuples_updated(c.oid), " + "pg_stat_get_tuples_deleted(c.oid), " + "pg_stat_get_live_tuples(c.oid) n_live_tuples, " + "pg_stat_get_dead_tuples(c.oid) n_dead_tuples " + "from pg_class c " + "left join pg_namespace n on (c.relnamespace = n.oid) " + "where c.relkind = 'r' and relpersistence <> 't' " + "and cast((n_dead_tuples)/(n_live_tuples+n_dead_tuples+0.00001) * 100 " + "as numeric(5,2)) >= %d " + "and (n_live_tuples+n_dead_tuples) >= %d " + "and n.nspname = \'%s\'; ", + dirty_pecent, n_tuples, schema_name); /* send sql and parallel fetch distribution info from all data nodes */ distribuion_info->state = RemoteFunctionResultHandler(buf.data, NULL, NULL, true, EXEC_ON_DATANODES, true); @@ -9269,201 +10340,364 @@ TableDistributionInfo* getTableStat(TupleDesc tuple_desc, int dirty_pecent, int return distribuion_info; } -TableDistributionInfo* get_remote_stat_pagewriter(TupleDesc tuple_desc) +/* + * 鍔熻兘锛氳幏鍙栬繙绋婸age Writer锛堥〉鍐欏叆鍣級鑺傜偣鐨勭粺璁′俊鎭 + * + * 鍙傛暟锛 + * tuple_desc锛歍uple鎻忚堪绗︼紝鐢ㄤ簬鏋勫缓杩斿洖鐨勭粨鏋滈泦 + * + * 杩斿洖鍊硷細 + * TableDistributionInfo 缁撴瀯鐨勬寚閽堬紝鍖呭惈浠庤繙绋嬭妭鐐硅幏鍙栫殑Page Writer鑺傜偣鐨勭粺璁′俊鎭 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庡悜杩滅▼鏁版嵁鑺傜偣鍙戦丼QL鏌ヨ锛屼互鑾峰彇瀹冧滑鐨凱age Writer鑺傜偣鐨勭粺璁′俊鎭 + * 棣栧厛锛屽嚱鏁板垎閰嶅苟鍒濆鍖栦竴涓猅ableDistributionInfo缁撴瀯鐨勬寚閽坉istribuion_info锛岀敤浜庡瓨鍌ㄦ煡璇㈢粨鏋溿 + * 鐒跺悗锛屽垵濮嬪寲涓涓猄tringInfoData缁撴瀯鐨刡uf锛岀敤浜庢瀯寤篠QL鏌ヨ璇彞銆 + * 鎺ョ潃锛屼娇鐢╝ppendStringInfo灏哠QL鏌ヨ璇彞娣诲姞鍒癰uf涓 + * 鏈鍚庯紝璋冪敤RemoteFunctionResultHandler鍑芥暟鍙戦丼QL鏌ヨ鍒版墍鏈夋暟鎹妭鐐癸紝骞惰繑鍥炵粨鏋溿 + * 娉ㄦ剰锛氬湪鍑芥暟澶栭儴搴旇閲婃斁鍦ㄦ澶勫垎閰嶇殑鍐呭瓨銆 + */ +TableDistributionInfo *get_remote_stat_pagewriter(TupleDesc tuple_desc) { StringInfoData buf; - TableDistributionInfo* distribuion_info = NULL; + TableDistributionInfo *distribuion_info = NULL; - /* the memory palloced here should be free outside where it was called. */ - distribuion_info = (TableDistributionInfo*)palloc0(sizeof(TableDistributionInfo)); + // 鍒嗛厤骞跺垵濮嬪寲TableDistributionInfo缁撴瀯 + distribuion_info = (TableDistributionInfo *)palloc0(sizeof(TableDistributionInfo)); + // 鍒濆鍖朾uf锛岀敤浜庢瀯寤篠QL鏌ヨ璇彞 initStringInfo(&buf); - appendStringInfo(&buf, - "select " - "node_name, pgwr_actual_flush_total_num, pgwr_last_flush_num, remain_dirty_page_num, " - "queue_head_page_rec_lsn, queue_rec_lsn, current_xlog_insert_lsn, ckpt_redo_point " - "from local_pagewriter_stat(); "); + // 鏋勫缓SQL鏌ヨ璇彞 + appendStringInfo(&buf, "select " + "node_name, pgwr_actual_flush_total_num, pgwr_last_flush_num, remain_dirty_page_num, " + "queue_head_page_rec_lsn, queue_rec_lsn, current_xlog_insert_lsn, ckpt_redo_point " + "from local_pagewriter_stat(); "); - /* send sql and parallel fetch distribution info from all data nodes */ + // 鍙戦丼QL鏌ヨ鍒版墍鏈夋暟鎹妭鐐瑰苟杩斿洖缁撴灉 distribuion_info->state = RemoteFunctionResultHandler(buf.data, NULL, NULL, true, EXEC_ON_ALL_NODES, true); distribuion_info->slot = MakeSingleTupleTableSlot(tuple_desc); return distribuion_info; } -TableDistributionInfo* get_remote_stat_ckpt(TupleDesc tuple_desc) +/* + * 鍔熻兘锛氳幏鍙栬繙绋婥heckpoint锛堟鏌ョ偣锛夎妭鐐圭殑缁熻淇℃伅 + * + * 鍙傛暟锛 + * tuple_desc锛歍uple鎻忚堪绗︼紝鐢ㄤ簬鏋勫缓杩斿洖鐨勭粨鏋滈泦 + * + * 杩斿洖鍊硷細 + * TableDistributionInfo 缁撴瀯鐨勬寚閽堬紝鍖呭惈浠庤繙绋嬭妭鐐硅幏鍙栫殑Checkpoint鑺傜偣鐨勭粺璁′俊鎭 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庡悜杩滅▼鏁版嵁鑺傜偣鍙戦丼QL鏌ヨ锛屼互鑾峰彇瀹冧滑鐨凜heckpoint鑺傜偣鐨勭粺璁′俊鎭 + * 棣栧厛锛屽嚱鏁板垎閰嶅苟鍒濆鍖栦竴涓猅ableDistributionInfo缁撴瀯鐨勬寚閽坉istribuion_info锛岀敤浜庡瓨鍌ㄦ煡璇㈢粨鏋溿 + * 鐒跺悗锛屽垵濮嬪寲涓涓猄tringInfoData缁撴瀯鐨刡uf锛岀敤浜庢瀯寤篠QL鏌ヨ璇彞銆 + * 鎺ョ潃锛屼娇鐢╝ppendStringInfo灏哠QL鏌ヨ璇彞娣诲姞鍒癰uf涓 + * 鏈鍚庯紝璋冪敤RemoteFunctionResultHandler鍑芥暟鍙戦丼QL鏌ヨ鍒版墍鏈夋暟鎹妭鐐癸紝骞惰繑鍥炵粨鏋溿 + * 娉ㄦ剰锛氬湪鍑芥暟澶栭儴搴旇閲婃斁鍦ㄦ澶勫垎閰嶇殑鍐呭瓨銆 + */ +TableDistributionInfo *get_remote_stat_ckpt(TupleDesc tuple_desc) { StringInfoData buf; - TableDistributionInfo* distribuion_info = NULL; + TableDistributionInfo *distribuion_info = NULL; - /* the memory palloced here should be free outside where it was called. */ - distribuion_info = (TableDistributionInfo*)palloc0(sizeof(TableDistributionInfo)); + // 鍒嗛厤骞跺垵濮嬪寲TableDistributionInfo缁撴瀯 + distribuion_info = (TableDistributionInfo *)palloc0(sizeof(TableDistributionInfo)); + // 鍒濆鍖朾uf锛岀敤浜庢瀯寤篠QL鏌ヨ璇彞 initStringInfo(&buf); - appendStringInfo(&buf, - "select " - "node_name,ckpt_redo_point,ckpt_clog_flush_num,ckpt_csnlog_flush_num, " - "ckpt_multixact_flush_num,ckpt_predicate_flush_num,ckpt_twophase_flush_num " - "from local_ckpt_stat(); "); + // 鏋勫缓SQL鏌ヨ璇彞 + appendStringInfo(&buf, "select " + "node_name,ckpt_redo_point,ckpt_clog_flush_num,ckpt_csnlog_flush_num, " + "ckpt_multixact_flush_num,ckpt_predicate_flush_num,ckpt_twophase_flush_num " + "from local_ckpt_stat(); "); - /* send sql and parallel fetch distribution info from all data nodes */ + // 鍙戦丼QL鏌ヨ鍒版墍鏈夋暟鎹妭鐐瑰苟杩斿洖缁撴灉 distribuion_info->state = RemoteFunctionResultHandler(buf.data, NULL, NULL, true, EXEC_ON_ALL_NODES, true); distribuion_info->slot = MakeSingleTupleTableSlot(tuple_desc); return distribuion_info; } -TableDistributionInfo* get_remote_stat_bgwriter(TupleDesc tuple_desc) +/* + * 鍔熻兘锛氳幏鍙栬繙绋婤GWriter鑺傜偣鐨勭粺璁′俊鎭 + * + * 鍙傛暟鍒楄〃锛 + * tuple_desc锛歍uple鎻忚堪绗︼紝鐢ㄤ簬鏋勫缓杩斿洖鐨勭粨鏋滈泦 + * + * 杩斿洖鍊硷細 + * TableDistributionInfo 缁撴瀯鐨勬寚閽堬紝鍖呭惈浠庤繙绋嬭妭鐐硅幏鍙栫殑BGWriter鑺傜偣鐨勭粺璁′俊鎭 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庡悜杩滅▼鏁版嵁鑺傜偣鍙戦丼QL鏌ヨ锛屼互鑾峰彇瀹冧滑鐨凚GWriter鑺傜偣鐨勭粺璁′俊鎭 + * 棣栧厛锛屽嚱鏁板垎閰嶅苟鍒濆鍖栦竴涓猅ableDistributionInfo缁撴瀯鐨勬寚閽坉istribuion_info锛岀敤浜庡瓨鍌ㄦ煡璇㈢粨鏋溿 + * 鐒跺悗锛屽垵濮嬪寲涓涓猄tringInfoData缁撴瀯鐨刡uf锛岀敤浜庢瀯寤篠QL鏌ヨ璇彞銆 + * 鎺ョ潃锛屼娇鐢╝ppendStringInfo灏哠QL鏌ヨ璇彞娣诲姞鍒癰uf涓 + * 鏈鍚庯紝璋冪敤RemoteFunctionResultHandler鍑芥暟鍙戦丼QL鏌ヨ鍒版墍鏈夋暟鎹妭鐐癸紝骞惰繑鍥炵粨鏋溿 + * 娉ㄦ剰锛氬湪鍑芥暟澶栭儴搴旇閲婃斁鍦ㄦ澶勫垎閰嶇殑鍐呭瓨銆 + */ +TableDistributionInfo *get_remote_stat_bgwriter(TupleDesc tuple_desc) { StringInfoData buf; - TableDistributionInfo* distribuion_info = NULL; + TableDistributionInfo *distribuion_info = NULL; - /* the memory palloced here should be free outside where it was called. */ - distribuion_info = (TableDistributionInfo*)palloc0(sizeof(TableDistributionInfo)); + // 鍒嗛厤骞跺垵濮嬪寲TableDistributionInfo缁撴瀯 + distribuion_info = (TableDistributionInfo *)palloc0(sizeof(TableDistributionInfo)); + // 鍒濆鍖朾uf锛岀敤浜庢瀯寤篠QL鏌ヨ璇彞 initStringInfo(&buf); - appendStringInfo(&buf, - "select " - "node_name,bgwr_actual_flush_total_num,bgwr_last_flush_num,candidate_slots, " - "get_buffer_from_list,get_buf_clock_sweep " - "from local_bgwriter_stat(); "); + // 鏋勫缓SQL鏌ヨ璇彞 + appendStringInfo(&buf, "select " + "node_name,bgwr_actual_flush_total_num,bgwr_last_flush_num,candidate_slots, " + "get_buffer_from_list,get_buf_clock_sweep " + "from local_bgwriter_stat(); "); - /* send sql and parallel fetch distribution info from all data nodes */ + // 鍙戦丼QL鏌ヨ鍒版墍鏈夋暟鎹妭鐐瑰苟杩斿洖缁撴灉 distribuion_info->state = RemoteFunctionResultHandler(buf.data, NULL, NULL, true, EXEC_ON_ALL_NODES, true); distribuion_info->slot = MakeSingleTupleTableSlot(tuple_desc); return distribuion_info; } -TableDistributionInfo* get_remote_stat_candidate(TupleDesc tuple_desc) +/* + * 鍔熻兘锛氳幏鍙栬繙绋嬪欓夎妭鐐圭殑缁熻淇℃伅 + * + * 鍙傛暟鍒楄〃锛 + * tuple_desc锛歍uple鎻忚堪绗︼紝鐢ㄤ簬鏋勫缓杩斿洖鐨勭粨鏋滈泦 + * + * 杩斿洖鍊硷細 + * TableDistributionInfo 缁撴瀯鐨勬寚閽堬紝鍖呭惈浠庤繙绋嬭妭鐐硅幏鍙栫殑鍊欓夎妭鐐圭殑缁熻淇℃伅 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庡悜杩滅▼鏁版嵁鑺傜偣鍙戦丼QL鏌ヨ锛屼互鑾峰彇瀹冧滑鐨勫欓夎妭鐐圭殑缁熻淇℃伅銆 + * 棣栧厛锛屽嚱鏁板垎閰嶅苟鍒濆鍖栦竴涓猅ableDistributionInfo缁撴瀯鐨勬寚閽坉istribuion_info锛岀敤浜庡瓨鍌ㄦ煡璇㈢粨鏋溿 + * 鐒跺悗锛屽垵濮嬪寲涓涓猄tringInfoData缁撴瀯鐨刡uf锛岀敤浜庢瀯寤篠QL鏌ヨ璇彞銆 + * 鎺ョ潃锛屼娇鐢╝ppendStringInfo灏哠QL鏌ヨ璇彞娣诲姞鍒癰uf涓 + * 鏈鍚庯紝璋冪敤RemoteFunctionResultHandler鍑芥暟鍙戦丼QL鏌ヨ鍒版墍鏈夋暟鎹妭鐐癸紝骞惰繑鍥炵粨鏋溿 + * 娉ㄦ剰锛氬湪鍑芥暟澶栭儴搴旇閲婃斁鍦ㄦ澶勫垎閰嶇殑鍐呭瓨銆 + */ +TableDistributionInfo *get_remote_stat_candidate(TupleDesc tuple_desc) { StringInfoData buf; - TableDistributionInfo* distribuion_info = NULL; + TableDistributionInfo *distribuion_info = NULL; - /* the memory palloced here should be free outside where it was called. */ - distribuion_info = (TableDistributionInfo*)palloc0(sizeof(TableDistributionInfo)); + // 鍒嗛厤骞跺垵濮嬪寲TableDistributionInfo缁撴瀯 + distribuion_info = (TableDistributionInfo *)palloc0(sizeof(TableDistributionInfo)); + // 鍒濆鍖朾uf锛岀敤浜庢瀯寤篠QL鏌ヨ璇彞 initStringInfo(&buf); - appendStringInfo(&buf, - "select " - "node_name,candidate_slots,get_buf_from_list,get_buf_clock_sweep, " - "seg_candidate_slots,seg_get_buf_from_list,seg_get_buf_clock_sweep " - "from local_candidate_stat(); "); + // 鏋勫缓SQL鏌ヨ璇彞 + appendStringInfo(&buf, "select " + "node_name,candidate_slots,get_buf_from_list,get_buf_clock_sweep, " + "seg_candidate_slots,seg_get_buf_from_list,seg_get_buf_clock_sweep " + "from local_candidate_stat(); "); - /* send sql and parallel fetch distribution info from all data nodes */ + // 鍙戦丼QL鏌ヨ鍒版墍鏈夋暟鎹妭鐐瑰苟杩斿洖缁撴灉 distribuion_info->state = RemoteFunctionResultHandler(buf.data, NULL, NULL, true, EXEC_ON_ALL_NODES, true); distribuion_info->slot = MakeSingleTupleTableSlot(tuple_desc); return distribuion_info; } - -TableDistributionInfo* get_remote_single_flush_dw_stat(TupleDesc tuple_desc) +/* + * 鍔熻兘锛氳幏鍙栬繙绋嬪崟椤靛埛鏂扮殑鍙屽啓缁熻淇℃伅 + * + * 鍙傛暟锛 + * tuple_desc锛歍uple鎻忚堪绗︼紝鐢ㄤ簬鏋勫缓杩斿洖鐨勭粨鏋滈泦 + * + * 杩斿洖鍊硷細 + * TableDistributionInfo 缁撴瀯鐨勬寚閽堬紝鍖呭惈浠庤繙绋嬭妭鐐硅幏鍙栫殑鍗曢〉鍒锋柊鐨勫弻鍐欑粺璁′俊鎭 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庡悜杩滅▼鏁版嵁鑺傜偣鍙戦丼QL鏌ヨ锛屼互鑾峰彇瀹冧滑鐨勫崟椤靛埛鏂扮殑鍙屽啓缁熻淇℃伅銆 + * 棣栧厛锛屽嚱鏁板垎閰嶅苟鍒濆鍖栦竴涓猅ableDistributionInfo缁撴瀯鐨勬寚閽坉istribuion_info锛岀敤浜庡瓨鍌ㄦ煡璇㈢粨鏋溿 + * 鐒跺悗锛屽垵濮嬪寲涓涓猄tringInfoData缁撴瀯鐨刡uf锛岀敤浜庢瀯寤篠QL鏌ヨ璇彞銆 + * 鎺ョ潃锛屼娇鐢╝ppendStringInfo灏哠QL鏌ヨ璇彞娣诲姞鍒癰uf涓 + * 鏈鍚庯紝璋冪敤RemoteFunctionResultHandler鍑芥暟鍙戦丼QL鏌ヨ鍒版墍鏈夋暟鎹妭鐐癸紝骞惰繑鍥炵粨鏋溿 + * 娉ㄦ剰锛氬湪鍑芥暟澶栭儴搴旇閲婃斁鍦ㄦ澶勫垎閰嶇殑鍐呭瓨銆 + */ +TableDistributionInfo *get_remote_single_flush_dw_stat(TupleDesc tuple_desc) { StringInfoData buf; - TableDistributionInfo* distribuion_info = NULL; + TableDistributionInfo *distribuion_info = NULL; - /* the memory palloced here should be free outside where it was called. */ - distribuion_info = (TableDistributionInfo*)palloc0(sizeof(TableDistributionInfo)); + // 鍒嗛厤骞跺垵濮嬪寲TableDistributionInfo缁撴瀯 + distribuion_info = (TableDistributionInfo *)palloc0(sizeof(TableDistributionInfo)); + // 鍒濆鍖朾uf锛岀敤浜庢瀯寤篠QL鏌ヨ璇彞 initStringInfo(&buf); - appendStringInfo(&buf, - "SELECT node_name, curr_dwn, curr_start_page, total_writes, file_trunc_num, file_reset_num " - "FROM local_single_flush_dw_stat();"); + // 鏋勫缓SQL鏌ヨ璇彞 + appendStringInfo(&buf, "SELECT node_name, curr_dwn, curr_start_page, total_writes, file_trunc_num, file_reset_num " + "FROM local_single_flush_dw_stat();"); - /* send sql and parallel fetch distribution info from all data nodes */ + // 鍙戦丼QL鏌ヨ鍒版墍鏈夋暟鎹妭鐐瑰苟杩斿洖缁撴灉 distribuion_info->state = RemoteFunctionResultHandler(buf.data, NULL, NULL, true, EXEC_ON_ALL_NODES, true); distribuion_info->slot = MakeSingleTupleTableSlot(tuple_desc); return distribuion_info; } -TableDistributionInfo* get_remote_stat_double_write(TupleDesc tuple_desc) +/* + * 鍔熻兘锛氳幏鍙栬繙绋嬬粺璁$殑鍙屽啓淇℃伅 + * + * 鍙傛暟锛 + * tuple_desc锛歍uple鎻忚堪绗︼紝鐢ㄤ簬鏋勫缓杩斿洖鐨勭粨鏋滈泦 + * + * 杩斿洖鍊硷細 + * TableDistributionInfo 缁撴瀯鐨勬寚閽堬紝鍖呭惈浠庤繙绋嬭妭鐐硅幏鍙栫殑鍙屽啓缁熻淇℃伅 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庡悜杩滅▼鏁版嵁鑺傜偣鍙戦丼QL鏌ヨ锛屼互鑾峰彇瀹冧滑鐨勫弻鍐欑粺璁′俊鎭 + * 棣栧厛锛屽嚱鏁板垎閰嶅苟鍒濆鍖栦竴涓猅ableDistributionInfo缁撴瀯鐨勬寚閽坉istribuion_info锛岀敤浜庡瓨鍌ㄦ煡璇㈢粨鏋溿 + * 鐒跺悗锛屽垵濮嬪寲涓涓猄tringInfoData缁撴瀯鐨刡uf锛岀敤浜庢瀯寤篠QL鏌ヨ璇彞銆 + * 鎺ョ潃锛屼娇鐢╝ppendStringInfo灏哠QL鏌ヨ璇彞娣诲姞鍒癰uf涓 + * 鏈鍚庯紝璋冪敤RemoteFunctionResultHandler鍑芥暟鍙戦丼QL鏌ヨ鍒版墍鏈夋暟鎹妭鐐癸紝骞惰繑鍥炵粨鏋溿 + * 娉ㄦ剰锛氬湪鍑芥暟澶栭儴搴旇閲婃斁鍦ㄦ澶勫垎閰嶇殑鍐呭瓨銆 + */ +TableDistributionInfo *get_remote_stat_double_write(TupleDesc tuple_desc) { StringInfoData buf; - TableDistributionInfo* distribuion_info = NULL; + TableDistributionInfo *distribuion_info = NULL; - /* the memory palloced here should be free outside where it was called. */ - distribuion_info = (TableDistributionInfo*)palloc0(sizeof(TableDistributionInfo)); + // 鍒嗛厤骞跺垵濮嬪寲TableDistributionInfo缁撴瀯 + distribuion_info = (TableDistributionInfo *)palloc0(sizeof(TableDistributionInfo)); + // 鍒濆鍖朾uf锛岀敤浜庢瀯寤篠QL鏌ヨ璇彞 initStringInfo(&buf); - appendStringInfo(&buf, - "SELECT node_name, curr_dwn, curr_start_page, file_trunc_num, file_reset_num, " - "total_writes, low_threshold_writes, high_threshold_writes, " - "total_pages, low_threshold_pages, high_threshold_pages, file_id " - "FROM local_double_write_stat();"); + // 鏋勫缓SQL鏌ヨ璇彞 + appendStringInfo(&buf, "SELECT node_name, curr_dwn, curr_start_page, file_trunc_num, file_reset_num, " + "total_writes, low_threshold_writes, high_threshold_writes, " + "total_pages, low_threshold_pages, high_threshold_pages, file_id " + "FROM local_double_write_stat();"); - /* send sql and parallel fetch distribution info from all data nodes */ + // 鍙戦丼QL鏌ヨ鍒版墍鏈夋暟鎹妭鐐瑰苟杩斿洖缁撴灉 distribuion_info->state = RemoteFunctionResultHandler(buf.data, NULL, NULL, true, EXEC_ON_ALL_NODES, true); distribuion_info->slot = MakeSingleTupleTableSlot(tuple_desc); return distribuion_info; } -TableDistributionInfo* get_remote_stat_redo(TupleDesc tuple_desc) +/* + * 鍔熻兘锛氳幏鍙栬繙绋嬬粺璁$殑閲嶅仛淇℃伅 + * + * 鍙傛暟鍒楄〃锛 + * tuple_desc锛歍uple鎻忚堪绗︼紝鐢ㄤ簬鏋勫缓杩斿洖鐨勭粨鏋滈泦 + * + * 杩斿洖鍊硷細 + * TableDistributionInfo 缁撴瀯鐨勬寚閽堬紝鍖呭惈浠庤繙绋嬭妭鐐硅幏鍙栫殑閲嶅仛缁熻淇℃伅 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庡悜杩滅▼鏁版嵁鑺傜偣鍙戦丼QL鏌ヨ锛屼互鑾峰彇瀹冧滑鐨勯噸鍋氱粺璁′俊鎭 + * 棣栧厛锛屽嚱鏁板垎閰嶅苟鍒濆鍖栦竴涓猅ableDistributionInfo缁撴瀯鐨勬寚閽坉istribuion_info锛岀敤浜庡瓨鍌ㄦ煡璇㈢粨鏋溿 + * 鐒跺悗锛屽垵濮嬪寲涓涓猄tringInfoData缁撴瀯鐨刡uf锛岀敤浜庢瀯寤篠QL鏌ヨ璇彞銆 + * 鎺ョ潃锛屼娇鐢╝ppendStringInfo灏哠QL鏌ヨ璇彞娣诲姞鍒癰uf涓 + * 鏈鍚庯紝璋冪敤RemoteFunctionResultHandler鍑芥暟鍙戦丼QL鏌ヨ鍒版墍鏈夋暟鎹妭鐐癸紝骞惰繑鍥炵粨鏋溿 + * 娉ㄦ剰锛氬湪鍑芥暟澶栭儴搴旇閲婃斁鍦ㄦ澶勫垎閰嶇殑鍐呭瓨銆 + */ +TableDistributionInfo *get_remote_stat_redo(TupleDesc tuple_desc) { StringInfoData buf; - TableDistributionInfo* distribuion_info = NULL; + TableDistributionInfo *distribuion_info = NULL; - /* the memory palloced here should be free outside where it was called. */ - distribuion_info = (TableDistributionInfo*)palloc0(sizeof(TableDistributionInfo)); + // 鍒嗛厤骞跺垵濮嬪寲TableDistributionInfo缁撴瀯 + distribuion_info = (TableDistributionInfo *)palloc0(sizeof(TableDistributionInfo)); + // 鍒濆鍖朾uf锛岀敤浜庢瀯寤篠QL鏌ヨ璇彞 initStringInfo(&buf); - appendStringInfo(&buf, - "SELECT node_name, redo_start_ptr, redo_start_time, redo_done_time, curr_time, " - "min_recovery_point, read_ptr, last_replayed_read_ptr, recovery_done_ptr, " - "read_xlog_io_counter, read_xlog_io_total_dur, " - "read_data_io_counter, read_data_io_total_dur, " - "write_data_io_counter, write_data_io_total_dur, " - "process_pending_counter, process_pending_total_dur, " - "apply_counter, apply_total_dur, " - "speed, local_max_ptr, primary_flush_ptr, worker_info " - "FROM local_redo_stat();"); + // 鏋勫缓SQL鏌ヨ璇彞 + appendStringInfo(&buf, "SELECT node_name, redo_start_ptr, redo_start_time, redo_done_time, curr_time, " + "min_recovery_point, read_ptr, last_replayed_read_ptr, recovery_done_ptr, " + "read_xlog_io_counter, read_xlog_io_total_dur, " + "read_data_io_counter, read_data_io_total_dur, " + "write_data_io_counter, write_data_io_total_dur, " + "process_pending_counter, process_pending_total_dur, " + "apply_counter, apply_total_dur, " + "speed, local_max_ptr, primary_flush_ptr, worker_info " + "FROM local_redo_stat();"); - /* send sql and parallel fetch distribution info from all data nodes */ + // 鍙戦丼QL鏌ヨ鍒版墍鏈夋暟鎹妭鐐瑰苟杩斿洖缁撴灉 distribuion_info->state = RemoteFunctionResultHandler(buf.data, NULL, NULL, true, EXEC_ON_ALL_NODES, true); distribuion_info->slot = MakeSingleTupleTableSlot(tuple_desc); return distribuion_info; } -TableDistributionInfo* get_rto_stat(TupleDesc tuple_desc) +/* + * 鍔熻兘锛氳幏鍙朢TO锛圧ecovery Time Objective锛夌粺璁′俊鎭 + * + * 鍙傛暟锛 + * tuple_desc锛歍uple鎻忚堪绗︼紝鐢ㄤ簬鏋勫缓杩斿洖鐨勭粨鏋滈泦 + * + * 杩斿洖鍊硷細 + * TableDistributionInfo 缁撴瀯鐨勬寚閽堬紝鍖呭惈浠庤繙绋嬭妭鐐硅幏鍙栫殑RTO缁熻淇℃伅 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庡悜杩滅▼鏁版嵁鑺傜偣鍙戦丼QL鏌ヨ锛屼互鑾峰彇瀹冧滑鐨凴TO缁熻淇℃伅銆 + * 棣栧厛锛屽嚱鏁板垎閰嶅苟鍒濆鍖栦竴涓猅ableDistributionInfo缁撴瀯鐨勬寚閽坉istribuion_info锛岀敤浜庡瓨鍌ㄦ煡璇㈢粨鏋溿 + * 鐒跺悗锛屽垵濮嬪寲涓涓猄tringInfoData缁撴瀯鐨刡uf锛岀敤浜庢瀯寤篠QL鏌ヨ璇彞銆 + * 鎺ョ潃锛屼娇鐢╝ppendStringInfo灏哠QL鏌ヨ璇彞娣诲姞鍒癰uf涓 + * 鏈鍚庯紝璋冪敤RemoteFunctionResultHandler鍑芥暟鍙戦丼QL鏌ヨ鍒版墍鏈夋暟鎹妭鐐癸紝骞惰繑鍥炵粨鏋溿 + */ +TableDistributionInfo *get_rto_stat(TupleDesc tuple_desc) { StringInfoData buf; - TableDistributionInfo* distribuion_info = NULL; + TableDistributionInfo *distribuion_info = NULL; - /* the memory palloced here should be free outside where it was called. */ - distribuion_info = (TableDistributionInfo*)palloc0(sizeof(TableDistributionInfo)); + // 鍒嗛厤骞跺垵濮嬪寲TableDistributionInfo缁撴瀯 + distribuion_info = (TableDistributionInfo *)palloc0(sizeof(TableDistributionInfo)); + // 鍒濆鍖朾uf锛岀敤浜庢瀯寤篠QL鏌ヨ璇彞 initStringInfo(&buf); + // 鏋勫缓SQL鏌ヨ璇彞 appendStringInfo(&buf, "SELECT node_name, rto_info FROM local_rto_stat();"); - /* send sql and parallel fetch distribution info from all data nodes */ + // 鍙戦丼QL鏌ヨ鍒版墍鏈夋暟鎹妭鐐瑰苟杩斿洖缁撴灉 distribuion_info->state = RemoteFunctionResultHandler(buf.data, NULL, NULL, true, EXEC_ON_ALL_NODES, true); distribuion_info->slot = MakeSingleTupleTableSlot(tuple_desc); return distribuion_info; } -TableDistributionInfo* get_recovery_stat(TupleDesc tuple_desc) +/* + * 鍔熻兘锛氳幏鍙栨仮澶嶇姸鎬佷俊鎭 + * + * 鍙傛暟锛 + * tuple_desc锛歍uple鎻忚堪绗︼紝鐢ㄤ簬鏋勫缓杩斿洖鐨勭粨鏋滈泦 + * + * 杩斿洖鍊硷細 + * TableDistributionInfo 缁撴瀯鐨勬寚閽堬紝鍖呭惈浠庤繙绋嬭妭鐐硅幏鍙栫殑鎭㈠鐘舵佷俊鎭 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庡悜杩滅▼鏁版嵁鑺傜偣鍙戦丼QL鏌ヨ锛屼互鑾峰彇瀹冧滑鐨勬仮澶嶇姸鎬佷俊鎭 + * 棣栧厛锛屽嚱鏁板垎閰嶅苟鍒濆鍖栦竴涓猅ableDistributionInfo缁撴瀯鐨勬寚閽坉istribuion_info锛岀敤浜庡瓨鍌ㄦ煡璇㈢粨鏋溿 + * 鐒跺悗锛屽垵濮嬪寲涓涓猄tringInfoData缁撴瀯鐨刡uf锛岀敤浜庢瀯寤篠QL鏌ヨ璇彞銆 + * 鎺ョ潃锛屼娇鐢╝ppendStringInfo灏哠QL鏌ヨ璇彞娣诲姞鍒癰uf涓 + * 鏈鍚庯紝璋冪敤RemoteFunctionResultHandler鍑芥暟鍙戦丼QL鏌ヨ鍒版墍鏈夋暟鎹妭鐐癸紝骞惰繑鍥炵粨鏋溿 + */ +TableDistributionInfo *get_recovery_stat(TupleDesc tuple_desc) { StringInfoData buf; - TableDistributionInfo* distribuion_info = NULL; + TableDistributionInfo *distribuion_info = NULL; /* the memory palloced here should be free outside where it was called. */ - distribuion_info = (TableDistributionInfo*)palloc0(sizeof(TableDistributionInfo)); + // 鍒嗛厤骞跺垵濮嬪寲TableDistributionInfo缁撴瀯 + distribuion_info = (TableDistributionInfo *)palloc0(sizeof(TableDistributionInfo)); + // 鍒濆鍖朾uf锛岀敤浜庢瀯寤篠QL鏌ヨ璇彞 initStringInfo(&buf); - appendStringInfo(&buf, + // 鏋勫缓SQL鏌ヨ璇彞 + appendStringInfo( + &buf, "SELECT node_name, standby_node_name, source_ip, source_port, dest_ip, dest_port, current_rto, target_rto, " "current_sleep_time FROM " "local_recovery_status();"); @@ -9475,21 +10709,21 @@ TableDistributionInfo* get_recovery_stat(TupleDesc tuple_desc) return distribuion_info; } -TableDistributionInfo* streaming_hadr_get_recovery_stat(TupleDesc tuple_desc) +TableDistributionInfo *streaming_hadr_get_recovery_stat(TupleDesc tuple_desc) { StringInfoData buf; - TableDistributionInfo* distribuion_info = NULL; + TableDistributionInfo *distribuion_info = NULL; /* the memory palloced here should be free outside where it was called. */ - distribuion_info = (TableDistributionInfo*)palloc0(sizeof(TableDistributionInfo)); + distribuion_info = (TableDistributionInfo *)palloc0(sizeof(TableDistributionInfo)); initStringInfo(&buf); appendStringInfo(&buf, - "SELECT hadr_sender_node_name, hadr_receiver_node_name, " - "source_ip, source_port, dest_ip, dest_port, current_rto, target_rto, current_rpo, target_rpo, " - "rto_sleep_time, rpo_sleep_time FROM " - "gs_hadr_local_rto_and_rpo_stat();"); + "SELECT hadr_sender_node_name, hadr_receiver_node_name, " + "source_ip, source_port, dest_ip, dest_port, current_rto, target_rto, current_rpo, target_rpo, " + "rto_sleep_time, rpo_sleep_time FROM " + "gs_hadr_local_rto_and_rpo_stat();"); /* send sql and parallel fetch distribution info from all data nodes */ distribuion_info->state = RemoteFunctionResultHandler(buf.data, NULL, NULL, true, EXEC_ON_ALL_NODES, true); @@ -9497,17 +10731,34 @@ TableDistributionInfo* streaming_hadr_get_recovery_stat(TupleDesc tuple_desc) return distribuion_info; } - -TableDistributionInfo* get_remote_node_xid_csn(TupleDesc tuple_desc) +/* + * 鍔熻兘锛氳幏鍙栬繙绋嬭妭鐐圭殑XID鍜孋SN淇℃伅 + * + * 鍙傛暟锛 + * tuple_desc锛歍uple鎻忚堪绗︼紝鐢ㄤ簬鏋勫缓杩斿洖鐨勭粨鏋滈泦 + * + * 杩斿洖鍊硷細 + * TableDistributionInfo 缁撴瀯鐨勬寚閽堬紝鍖呭惈浠庤繙绋嬭妭鐐硅幏鍙栫殑XID鍜孋SN淇℃伅 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庡悜杩滅▼鏁版嵁鑺傜偣鍙戦丼QL鏌ヨ锛屼互鑾峰彇瀹冧滑鐨刋ID鍜孋SN淇℃伅銆 + * 棣栧厛锛屽嚱鏁板垎閰嶅苟鍒濆鍖栦竴涓猅ableDistributionInfo缁撴瀯鐨勬寚閽坉istribuion_info锛岀敤浜庡瓨鍌ㄦ煡璇㈢粨鏋溿 + * 鐒跺悗锛屽垵濮嬪寲涓涓猄tringInfoData缁撴瀯鐨刡uf锛岀敤浜庢瀯寤篠QL鏌ヨ璇彞銆 + * 鎺ョ潃锛屼娇鐢╝ppendStringInfo灏哠QL鏌ヨ璇彞娣诲姞鍒癰uf涓 + * 鏈鍚庯紝璋冪敤RemoteFunctionResultHandler鍑芥暟鍙戦丼QL鏌ヨ鍒版墍鏈夋暟鎹妭鐐癸紝骞惰繑鍥炵粨鏋溿 + */ +TableDistributionInfo *get_remote_node_xid_csn(TupleDesc tuple_desc) { StringInfoData buf; - TableDistributionInfo* distribuion_info = NULL; + TableDistributionInfo *distribuion_info = NULL; /* the memory palloced here should be free outside where it was called.*/ - distribuion_info = (TableDistributionInfo*)palloc0(sizeof(TableDistributionInfo)); + distribuion_info = (TableDistributionInfo *)palloc0(sizeof(TableDistributionInfo)); + // 鍒濆鍖朾uf锛岀敤浜庢瀯寤篠QL鏌ヨ璇彞 initStringInfo(&buf); + // 鏋勫缓SQL鏌ヨ璇彞 appendStringInfo(&buf, "select node_name, next_xid, next_csn FROM gs_get_next_xid_csn();"); /* send sql and parallel fetch distribution info from all data nodes */ @@ -9518,21 +10769,23 @@ TableDistributionInfo* get_remote_node_xid_csn(TupleDesc tuple_desc) } #ifdef ENABLE_MULTIPLE_NODES -TableDistributionInfo* get_remote_index_status(TupleDesc tuple_desc, const char *schname, const char *idxname) +TableDistributionInfo *get_remote_index_status(TupleDesc tuple_desc, const char *schname, const char *idxname) { StringInfoData buf; - TableDistributionInfo* distribuion_info = NULL; + TableDistributionInfo *distribuion_info = NULL; /* the memory palloced here should be free outside where it was called.*/ - distribuion_info = (TableDistributionInfo*)palloc0(sizeof(TableDistributionInfo)); + distribuion_info = (TableDistributionInfo *)palloc0(sizeof(TableDistributionInfo)); initStringInfo(&buf); - appendStringInfo(&buf, "select a.node_name::text, b.indisready, b.indisvalid from pg_index b " - "left join pgxc_node a on b.xc_node_id = a.node_id " - "where indexrelid = (select oid from pg_class where relnamespace = " - "(select oid from pg_namespace where nspname = %s) " - "and relname = %s);", quote_literal_cstr(schname), quote_literal_cstr(idxname)); + appendStringInfo(&buf, + "select a.node_name::text, b.indisready, b.indisvalid from pg_index b " + "left join pgxc_node a on b.xc_node_id = a.node_id " + "where indexrelid = (select oid from pg_class where relnamespace = " + "(select oid from pg_namespace where nspname = %s) " + "and relname = %s);", + quote_literal_cstr(schname), quote_literal_cstr(idxname)); /* send sql and parallel fetch distribution info from all nodes */ distribuion_info->state = RemoteFunctionResultHandler(buf.data, NULL, NULL, true, EXEC_ON_ALL_NODES, true); @@ -9551,7 +10804,7 @@ TableDistributionInfo* get_remote_index_status(TupleDesc tuple_desc, const char * update by pgstat_recv_badblock_stat() */ MemoryContext global_bad_block_mcxt = NULL; -HTAB* global_bad_block_stat = NULL; +HTAB *global_bad_block_stat = NULL; /* * Record a statistics of bad block: @@ -9571,12 +10824,9 @@ void initGlobalBadBlockStat() /* global bad block statistics */ /* in g_instance.instance_context */ if (global_bad_block_mcxt == NULL) { - global_bad_block_mcxt = AllocSetContextCreate((MemoryContext)g_instance.instance_context, - "bad block stat global memory context", - ALLOCSET_DEFAULT_MINSIZE, - ALLOCSET_DEFAULT_INITSIZE, - ALLOCSET_DEFAULT_MAXSIZE, - SHARED_CONTEXT); + global_bad_block_mcxt = AllocSetContextCreate( + (MemoryContext)g_instance.instance_context, "bad block stat global memory context", + ALLOCSET_DEFAULT_MINSIZE, ALLOCSET_DEFAULT_INITSIZE, ALLOCSET_DEFAULT_MAXSIZE, SHARED_CONTEXT); } LWLockAcquire(BadBlockStatHashLock, LW_EXCLUSIVE); @@ -9608,11 +10858,9 @@ void initLocalBadBlockStat() /* local thread bad block statistics */ /* in t_thrd.top_mem_cxt */ if (t_thrd.stat_cxt.local_bad_block_mcxt == NULL) { - t_thrd.stat_cxt.local_bad_block_mcxt = AllocSetContextCreate((MemoryContext)t_thrd.top_mem_cxt, - "bad block session memory context", - ALLOCSET_DEFAULT_MINSIZE, - ALLOCSET_DEFAULT_INITSIZE, - ALLOCSET_DEFAULT_MAXSIZE); + t_thrd.stat_cxt.local_bad_block_mcxt = + AllocSetContextCreate((MemoryContext)t_thrd.top_mem_cxt, "bad block session memory context", + ALLOCSET_DEFAULT_MINSIZE, ALLOCSET_DEFAULT_INITSIZE, ALLOCSET_DEFAULT_MAXSIZE); } if (t_thrd.stat_cxt.local_bad_block_stat == NULL) { @@ -9636,7 +10884,7 @@ void initLocalBadBlockStat() * @IN forknum: forknum for page/cu * @See also: */ -void addBadBlockStat(const RelFileNode* relfilenode, ForkNumber forknum) +void addBadBlockStat(const RelFileNode *relfilenode, ForkNumber forknum) { if (t_thrd.stat_cxt.local_bad_block_stat == NULL || relfilenode == NULL) { return; @@ -9655,8 +10903,8 @@ void addBadBlockStat(const RelFileNode* relfilenode, ForkNumber forknum) bool found = false; /* insert if not find, if out of memory return NULL */ - BadBlockHashEnt* entry = - (BadBlockHashEnt*)hash_search(t_thrd.stat_cxt.local_bad_block_stat, &hash_key, HASH_ENTER, &found); + BadBlockHashEnt *entry = + (BadBlockHashEnt *)hash_search(t_thrd.stat_cxt.local_bad_block_stat, &hash_key, HASH_ENTER, &found); if (entry != NULL) { if (!found) { @@ -9717,19 +10965,19 @@ static void pgstat_send_badblock_stat(void) PgStat_MsgBadBlock msg; HASH_SEQ_STATUS hash_seq; - BadBlockHashEnt* badblock_entry = NULL; + BadBlockHashEnt *badblock_entry = NULL; pgstat_setheader(&msg.m_hdr, PGSTAT_MTYPE_BADBLOCK); msg.m_nentries = 0; hash_seq_init(&hash_seq, t_thrd.stat_cxt.local_bad_block_stat); - while ((badblock_entry = (BadBlockHashEnt*)hash_seq_search(&hash_seq)) != NULL) { + while ((badblock_entry = (BadBlockHashEnt *)hash_seq_search(&hash_seq)) != NULL) { /* jump empty */ if (badblock_entry->error_count == 0) continue; - BadBlockHashEnt* m_ent = &msg.m_entry[msg.m_nentries]; + BadBlockHashEnt *m_ent = &msg.m_entry[msg.m_nentries]; errno_t rc = memcpy_s(m_ent, sizeof(BadBlockHashEnt), badblock_entry, sizeof(BadBlockHashEnt)); securec_check(rc, "", ""); @@ -9754,13 +11002,13 @@ static void pgstat_send_badblock_stat(void) * @IN len: without use * @See also: */ -static void pgstat_recv_badblock_stat(PgStat_MsgBadBlock* msg, int /* len */) +static void pgstat_recv_badblock_stat(PgStat_MsgBadBlock *msg, int /* len */) { if (global_bad_block_stat == NULL || msg == NULL) { return; } - BadBlockHashEnt* badblock_entry = &(msg->m_entry[0]); + BadBlockHashEnt *badblock_entry = &(msg->m_entry[0]); LWLockAcquire(BadBlockStatHashLock, LW_EXCLUSIVE); @@ -9771,10 +11019,11 @@ static void pgstat_recv_badblock_stat(PgStat_MsgBadBlock* msg, int /* len */) for (int i = 0; i < msg->m_nentries; i++, badblock_entry++) { bool found = false; - BadBlockHashKey* badblock_key = &(badblock_entry->key); + BadBlockHashKey *badblock_key = &(badblock_entry->key); /* insert if not find, if out of memory return NULL */ - BadBlockHashEnt* entry = (BadBlockHashEnt*)hash_search(global_bad_block_stat, badblock_key, HASH_ENTER, &found); + BadBlockHashEnt *entry = + (BadBlockHashEnt *)hash_search(global_bad_block_stat, badblock_key, HASH_ENTER, &found); if (entry != NULL) { if (!found) { @@ -9794,20 +11043,32 @@ static void pgstat_recv_badblock_stat(PgStat_MsgBadBlock* msg, int /* len */) /* * get current total counter */ -void GetCurrentTotalTableCounter(PgStat_TableCounts* total_table_counter) +/* + * 鍔熻兘锛氳幏鍙栧綋鍓嶆昏〃鏍艰鏁板櫒 + * + * 鍙傛暟锛 + * total_table_counter锛氭寚鍚慞gStat_TableCounts缁撴瀯鐨勬寚閽堬紝鐢ㄤ簬瀛樺偍鎬昏〃鏍艰鏁板櫒鐨勭粨鏋溿 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庤幏鍙栧綋鍓嶆昏〃鏍艰鏁板櫒锛屽寘鎷〃鏍肩殑鍚勭璁℃暟淇℃伅銆 + * 棣栧厛锛屽嚱鏁板垵濮嬪寲涓涓猅abStatusArray鎸囬拡tsa锛岀敤浜庨亶鍘嗚〃鏍肩姸鎬佹暟缁剈_sess->stat_cxt.pgStatTabList銆 + * 鐒跺悗锛屼娇鐢ㄥ惊鐜亶鍘嗘瘡涓〃鏍肩姸鎬佹暟缁勪腑鐨勮〃鏍肩姸鎬佹潯鐩甈gStat_TableStatus銆 + * 瀵逛簬姣忎釜琛ㄦ牸鐘舵佹潯鐩紝灏嗗叾璁℃暟淇℃伅绱姞鍒皌otal_table_counter涓紝閫氳繃璋冪敤UniqueSQLSumTableStatCounter()鍑芥暟瀹炵幇銆 + * 鎺ョ潃锛岄亶鍘嗚〃鏍肩姸鎬佹潯鐩腑鐨勪簨鍔$姸鎬侀摼琛≒gStat_TableXactStatus锛屽皢浜嬪姟鐩稿叧鐨勮鏁颁俊鎭篃绱姞鍒皌otal_table_counter涓 + * 鏈鍚庯紝鍑芥暟杩斿洖鎬昏〃鏍艰鏁板櫒鐨勭粨鏋溿 + */ +void GetCurrentTotalTableCounter(PgStat_TableCounts *total_table_counter) { - TabStatusArray* tsa = NULL; - + TabStatusArray *tsa = NULL; + // 閬嶅巻琛ㄦ牸鐘舵佹暟缁 for (tsa = u_sess->stat_cxt.pgStatTabList; tsa != NULL; tsa = tsa->tsa_next) { for (int i = 0; i < tsa->tsa_used; i++) { - PgStat_TableStatus* entry = &tsa->tsa_entries[i]; - PgStat_TableXactStatus* trans = NULL; - + PgStat_TableStatus *entry = &tsa->tsa_entries[i]; + PgStat_TableXactStatus *trans = NULL; if (entry != NULL) { - // get total table counts stat + // 绱姞琛ㄦ牸璁℃暟淇℃伅鍒皌otal_table_counter UniqueSQLSumTableStatCounter((*total_table_counter), entry->t_counts); - - // get sub xact counter(IUD counters are in PgStat_TableXactStatus) + // 閬嶅巻浜嬪姟鐘舵侀摼琛紝绱姞浜嬪姟鐩稿叧鐨勮鏁颁俊鎭 for (trans = entry->trans; trans != NULL; trans = trans->upper) { total_table_counter->t_tuples_inserted += trans->tuples_inserted; total_table_counter->t_tuples_updated += trans->tuples_updated; @@ -9830,7 +11091,7 @@ void GetCurrentTotalTableCounter(PgStat_TableCounts* total_table_counter) * * return true if current_table_counter has values */ -bool CalcSQLRowStatCounter(PgStat_TableCounts* last_total_counter, PgStat_TableCounts* current_sql_table_counter) +bool CalcSQLRowStatCounter(PgStat_TableCounts *last_total_counter, PgStat_TableCounts *current_sql_table_counter) { Assert(current_sql_table_counter && last_total_counter); @@ -9845,9 +11106,8 @@ bool CalcSQLRowStatCounter(PgStat_TableCounts* last_total_counter, PgStat_TableC if (u_sess->storage_cxt.twoPhaseCommitInProgress) return false; - ereport(DEBUG1, - (errmodule(MOD_INSTR), - errmsg("[UniqueSQL] unique id: %lu, calc row stat counter", u_sess->unique_sql_cxt.unique_sql_id))); + ereport(DEBUG1, (errmodule(MOD_INSTR), errmsg("[UniqueSQL] unique id: %lu, calc row stat counter", + u_sess->unique_sql_cxt.unique_sql_id))); PrintPgStatTableCounter('L', last_total_counter); @@ -9883,69 +11143,151 @@ bool CalcSQLRowStatCounter(PgStat_TableCounts* last_total_counter, PgStat_TableC } } +/* + * 鍔熻兘锛氳幏鍙朣QL杩愯鏃堕棿淇℃伅璁℃暟鍣 + * + * 杩斿洖鍊硷細 + * 杩斿洖鏈湴璁℃暟鍣╱_sess->percentile_cxt.LocalCounter鐨勫硷紝琛ㄧず宸茶幏鍙栫殑SQL杩愯鏃堕棿淇℃伅鐨勬暟閲忋 + * 濡傛灉娌℃湁鍙敤鐨勪俊鎭紝璁℃暟鍣ㄥ皢涓洪浂銆 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庤幏鍙朣QL杩愯鏃堕棿淇℃伅鐨勮鏁板櫒銆傞鍏堬紝瀹冩鏌ュ叏灞SQL杩愯鏃堕棿淇℃伅鏁扮粍g_instance.stat_cxt.sql_rt_info_array鏄惁涓篘ULL銆 + * 濡傛灉鏁扮粍涓嶄负NULL锛屽嚱鏁板皢鏍规嵁鑺傜偣绫诲瀷閫夋嫨閫傚綋鐨勫嚱鏁拌繘琛屽噯澶囪绠椼 + * 濡傛灉鏄崟鑺傜偣妯″紡(IS_SINGLE_NODE)锛屽皢璋冪敤prepare_calculate_single()鍑芥暟銆 + * 鍚﹀垯锛屽皢璋冪敤prepare_calculate()鍑芥暟銆 + * 鍑嗗璁$畻鍑芥暟灏嗘牴鎹叏灞鏁扮粍鐨勫唴瀹硅绠楁湰鍦拌鏁板櫒u_sess->percentile_cxt.LocalCounter鐨勫硷紝琛ㄧず宸茶幏鍙栫殑SQL杩愯鏃堕棿淇℃伅鐨勬暟閲忋 + * 鏈鍚庯紝鍑芥暟杩斿洖璁℃暟鍣ㄧ殑鍊笺 + */ int pgstat_fetch_sql_rt_info_counter(void) { + // 妫鏌ュ叏灞SQL杩愯鏃堕棿淇℃伅鏁扮粍鏄惁涓篘ULL if (g_instance.stat_cxt.sql_rt_info_array != NULL) { + // 濡傛灉鏄崟鑺傜偣妯″紡锛岃皟鐢╬repare_calculate_single()鍑芥暟 if (IS_SINGLE_NODE) { prepare_calculate_single(g_instance.stat_cxt.sql_rt_info_array, &u_sess->percentile_cxt.LocalCounter); } else { + // 鍚﹀垯锛岃皟鐢╬repare_calculate()鍑芥暟 prepare_calculate(g_instance.stat_cxt.sql_rt_info_array, &u_sess->percentile_cxt.LocalCounter); } } + // 杩斿洖鏈湴璁℃暟鍣ㄧ殑鍊硷紝琛ㄧず宸茶幏鍙栫殑SQL杩愯鏃堕棿淇℃伅鐨勬暟閲 return u_sess->percentile_cxt.LocalCounter; } -void pgstat_fetch_sql_rt_info_internal(SqlRTInfo* sqlrt) +/* + * 鍔熻兘锛氬唴閮ㄥ嚱鏁帮紝鐢ㄤ簬鑾峰彇SQL杩愯鏃堕棿淇℃伅 + * + * 鍙傛暟鍒楄〃锛 + * sqlrt锛氬瓨鍌⊿QL杩愯鏃堕棿淇℃伅鐨勭洰鏍囩粨鏋 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庤幏鍙朣QL杩愯鏃堕棿淇℃伅銆傞鍏堬紝瀹冩鏌ヤ紶鍏ョ殑鍙傛暟sqlrt鏄惁涓篘ULL浠ュ強鏈湴璁℃暟鍣ㄥ拰鐧惧垎浣嶆暟鏁版嵁鏄惁鏈夋晥銆 + * 濡傛灉鏈変换浣曚竴涓潯浠朵笉婊¤冻锛屽嚱鏁板皢鐩存帴杩斿洖锛屼笉鎵ц浠讳綍鎿嶄綔銆 + * 濡傛灉婊¤冻鏉′欢锛屽嚱鏁拌皟鐢╩emcpy_s()鍑芥暟灏嗙櫨鍒嗕綅鏁版暟鎹畊_sess->percentile_cxt.LocalsqlRT鎷疯礉鍒扮洰鏍囩粨鏋剆qlrt涓 + * 鏈鍚庯紝鍑芥暟閲婃斁鐧惧垎浣嶆暟鏁版嵁鐨勫唴瀛樸 + */ +void pgstat_fetch_sql_rt_info_internal(SqlRTInfo *sqlrt) { + // 妫鏌ヤ紶鍏ョ殑鍙傛暟sqlrt鏄惁涓篘ULL浠ュ強鏈湴璁℃暟鍣ㄥ拰鐧惧垎浣嶆暟鏁版嵁鏄惁鏈夋晥 if (sqlrt == NULL || u_sess->percentile_cxt.LocalCounter == 0 || u_sess->percentile_cxt.LocalsqlRT == NULL) return; - errno_t rc = memcpy_s(sqlrt, - u_sess->percentile_cxt.LocalCounter * sizeof(SqlRTInfo), - u_sess->percentile_cxt.LocalsqlRT, - u_sess->percentile_cxt.LocalCounter * sizeof(SqlRTInfo)); + // 浣跨敤memcpy_s()灏嗙櫨鍒嗕綅鏁版暟鎹嫹璐濆埌鐩爣缁撴瀯sqlrt涓 + errno_t rc = memcpy_s(sqlrt, u_sess->percentile_cxt.LocalCounter * sizeof(SqlRTInfo), + u_sess->percentile_cxt.LocalsqlRT, u_sess->percentile_cxt.LocalCounter * sizeof(SqlRTInfo)); securec_check(rc, "\0", "\0"); + // 閲婃斁鐧惧垎浣嶆暟鏁版嵁鐨勫唴瀛 pfree_ext(u_sess->percentile_cxt.LocalsqlRT); } +/* + * 鍔熻兘锛氬洖澶嶇櫨鍒嗕綅鏁拌褰曡鏁 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮殑鍔熻兘鏄洖澶嶇櫨鍒嗕綅鏁拌褰曠殑璁℃暟銆傞鍏堬紝瀹冨垱寤轰竴涓敤浜庡瓨鍌ㄦ秷鎭殑StringInfoData缂撳啿鍖恒 + * 鐒跺悗锛屽畠灏唃_instance.stat_cxt.calculate_on_other_cn璁剧疆涓簍rue锛岃〃绀洪渶瑕佽繘琛屽叾浠栬绠椼 + * 鎺ョ潃锛屽畠璋冪敤pgstat_fetch_sql_rt_info_counter()鍑芥暟锛岃鍑芥暟鐢ㄤ簬鑾峰彇鐧惧垎浣嶆暟璁板綍鐨勮鏁颁俊鎭 + * 鎺ョ潃锛屽嚱鏁板垱寤哄苟鍙戦佷竴鏉$被鍨嬩负'c'鐨勬秷鎭紝娑堟伅涓寘鎷湰鍦拌鏁板櫒u_sess->percentile_cxt.LocalCounter鐨勫笺 + * 鐒跺悗锛屽嚱鏁板垱寤哄苟鍙戦佷竴鏉$被鍨嬩负'f'鐨勬秷鎭紝琛ㄧず缁撴潫銆傛渶鍚庯紝鍑芥暟閫氳繃pq_flush()灏嗘墍鏈夋秷鎭埛鏂板埌鎺ユ敹鏂广 + */ void pgstat_reply_percentile_record_count() { StringInfoData buf; + // 璁剧疆calculate_on_other_cn涓簍rue锛岃〃绀洪渶瑕佽繘琛屽叾浠栬绠 g_instance.stat_cxt.calculate_on_other_cn = true; - + // 璋冪敤pgstat_fetch_sql_rt_info_counter()鑾峰彇鐧惧垎浣嶆暟璁板綍鐨勮鏁颁俊鎭 (void)pgstat_fetch_sql_rt_info_counter(); - + // 寮濮嬩竴涓秷鎭 pq_beginmessage(&buf, 'c'); + // 鍚戞秷鎭腑娣诲姞鏈湴璁℃暟鍣╱_sess->percentile_cxt.LocalCounter鐨勫 pq_sendint(&buf, u_sess->percentile_cxt.LocalCounter, sizeof(int)); + // 缁撴潫娑堟伅 pq_endmessage(&buf); + // 寮濮嬩竴涓粨鏉熸秷鎭 pq_beginmessage(&buf, 'f'); pq_endmessage(&buf); + // 鍒锋柊鎵鏈夋秷鎭埌鎺ユ敹鏂 pq_flush(); } +/* + * 鍔熻兘锛氬洖澶嶇櫨鍒嗕綅鏁拌褰 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮殑鍔熻兘鏄洖澶嶇櫨鍒嗕綅鏁拌褰曘傞鍏堬紝瀹冨垱寤轰竴涓敤浜庡瓨鍌ㄦ秷鎭殑StringInfoData缂撳啿鍖恒 + * 鐒跺悗锛屽畠妫鏌ユ湰鍦扮殑鐧惧垎浣嶆暟璁℃暟鍣╱_sess->percentile_cxt.LocalCounter鏄惁涓篘ULL銆 + * 濡傛灉涓嶄负NULL锛屽畠杩涘叆涓涓惊鐜紝涓烘瘡涓櫨鍒嗕綅鏁拌鏁板櫒鍒涘缓涓鏉℃秷鎭紝骞跺皢娑堟伅鍙戦佺粰鎺ユ敹鏂广 + * 杩欎簺娑堟伅鍖呮嫭UniqueSQLId鍜宺t涓や釜鏁存暟銆傚畬鎴愭秷鎭殑鍙戦佸悗锛岄噴鏀緐_sess->percentile_cxt.LocalsqlRT鐨勫唴瀛樸 + * 鎺ョ潃锛屽嚱鏁板垱寤哄苟鍙戦佷竴鏉$被鍨嬩负'f'鐨勬秷鎭紝琛ㄧず缁撴潫銆傛渶鍚庯紝鍑芥暟灏唃_instance.stat_cxt.calculate_on_other_cn + * 璁剧疆涓篺alse锛屼互鎸囩ず涓嶅啀杩涜鍏朵粬璁$畻銆傛渶缁堬紝鍑芥暟閫氳繃pq_flush()灏嗘墍鏈夋秷鎭埛鏂板埌鎺ユ敹鏂广 + */ void pgstat_reply_percentile_record() { StringInfoData buf; + + // 妫鏌ユ湰鍦扮殑鐧惧垎浣嶆暟璁℃暟鍣ㄦ槸鍚︿负NULL if (u_sess->percentile_cxt.LocalsqlRT != NULL) { + // 閬嶅巻鐧惧垎浣嶆暟璁℃暟鍣ㄦ暟缁 for (int i = 0; i < u_sess->percentile_cxt.LocalCounter; i++) { + // 寮濮嬩竴涓秷鎭 pq_beginmessage(&buf, 'r'); + + // 鍚戞秷鎭腑娣诲姞UniqueSQLId鍜宺t涓や釜鏁存暟 pq_sendint64(&buf, u_sess->percentile_cxt.LocalsqlRT[i].UniqueSQLId); pq_sendint64(&buf, u_sess->percentile_cxt.LocalsqlRT[i].rt); + + // 缁撴潫娑堟伅 pq_endmessage(&buf); } + // 閲婃斁鐧惧垎浣嶆暟璁℃暟鍣ㄦ暟缁勭殑鍐呭瓨 pfree_ext(u_sess->percentile_cxt.LocalsqlRT); } + // 寮濮嬩竴涓粨鏉熸秷鎭 pq_beginmessage(&buf, 'f'); pq_endmessage(&buf); + // 璁剧疆calculate_on_other_cn涓篺alse锛岃〃绀轰笉鍐嶈繘琛屽叾浠栬绠 g_instance.stat_cxt.calculate_on_other_cn = false; + // 鍒锋柊鎵鏈夋秷鎭埌鎺ユ敹鏂 pq_flush(); } +/* + * pgstat_release_session_memory_entry: Release session-level memory entry. + * + * This function is responsible for releasing memory associated with the + * session-level memory entry, including the query plan and query plan issue + * strings. + */ void pgstat_release_session_memory_entry() { + // Check if the session memory entry is not NULL if (t_thrd.shemem_ptr_cxt.mySessionMemoryEntry != NULL) { + // Free memory associated with the query plan if it exists pfree_ext(t_thrd.shemem_ptr_cxt.mySessionMemoryEntry->query_plan); + + // Reset the plan_size to 0 t_thrd.shemem_ptr_cxt.mySessionMemoryEntry->plan_size = 0; + + // Free memory associated with the query plan issue if it exists pfree_ext(t_thrd.shemem_ptr_cxt.mySessionMemoryEntry->query_plan_issue); } -} - +} \ No newline at end of file diff --git a/src/gausskernel/process/postmaster/rbcleaner.cpp b/src/gausskernel/process/postmaster/rbcleaner.cpp index 729dd7396..26aaaee99 100644 --- a/src/gausskernel/process/postmaster/rbcleaner.cpp +++ b/src/gausskernel/process/postmaster/rbcleaner.cpp @@ -68,6 +68,14 @@ const int RBCLEANER_INTERVAL_MS = 3000; * RbCleanerShmemSize * Size of Rbcleaner related shared memory */ + +/* + * 鍔熻兘锛 璁$畻 Rbcleaner 鐩稿叧鍏变韩鍐呭瓨鐨勫ぇ灏 + * + * 鍙傛暟锛氭棤 + * + * 杩斿洖鍊硷細鍏变韩鍐呭瓨鐨勫ぇ灏 + */ Size RbCleanerShmemSize() { return sizeof(RbCleanerShmemStruct); @@ -77,92 +85,147 @@ Size RbCleanerShmemSize() * RbCleanerShmemInit * Allocate and initialize Rbcleanr -related shared memory */ + +/* + * 鍔熻兘锛 鍒嗛厤鍜屽垵濮嬪寲涓 Rbcleaner 鐩稿叧鐨勫叡浜唴瀛 + * + * 鍙傛暟锛氭棤 + * + * 杩斿洖鍊硷細鏃 + */ void RbCleanerShmemInit(void) { - bool found = false; - + bool found = false; // 鐢ㄤ簬鏍囪鏄惁鎵惧埌浜嗙幇鏈夌殑鍏变韩鍐呭瓨 + // 鑾峰彇鍏变韩鍐呭瓨娈碉紝骞惰繑鍥炴寚鍚戝叡浜唴瀛樼殑鎸囬拡 + // 濡傛灉鎵惧埌鐜版湁鐨勫叡浜唴瀛橈紝鍒欏皢 found 璁剧疆涓 true t_thrd.rbcleaner_cxt.RbCleanerShmem = (RbCleanerShmemStruct *)ShmemInitStruct("RbCleaner Data", sizeof(RbCleanerShmemStruct), &found); - if (!found) { + if (!found) { // 濡傛灉鍏变韩鍐呭瓨灏氫笉瀛樺湪 /* * First time through, so initialize. Note that we zero the whole * requests array; this is so that CompactCheckpointerRequestQueue * can assume that any pad bytes in the request structs are zeroes. */ + // 灏嗗叡浜唴瀛樼殑鍐呭鍒濆鍖栦负闆 errno_t ret = memset_s(t_thrd.rbcleaner_cxt.RbCleanerShmem, sizeof(RbCleanerShmemStruct), 0, sizeof(RbCleanerShmemStruct)); securec_check(ret, "\0", "\0"); - + // 鍒濆鍖栦笌 Rbcleaner 鐩稿叧鐨勯槦鍒楁垨鏁版嵁缁撴瀯 RbQueueInit(&t_thrd.rbcleaner_cxt.RbCleanerShmem->queue); } return; } +/* + * 鍔熻兘锛 妫鏌bcleaner杩涚▼鏄惁瀛樻椿 + * + * 鍙傛暟锛氭棤 + * + * 杩斿洖鍊硷細bool绫诲瀷锛屽瓨娲诲垯杩斿洖true + */ static bool RbCleanerIsAlive() { + // 璇诲彇Rbcleaner鍏变韩鍐呭瓨缁撴瀯浣撲腑鐨 rbCleanerPid 瀛楁鐨勫硷紝骞舵鏌ュ叾鏄惁涓嶇瓑浜0 + // 涓嶇瓑浜0锛屽嚱鏁拌繑鍥 true锛岃〃绀篟bcleaner姝e湪杩愯 return pg_atomic_read_u64(&t_thrd.rbcleaner_cxt.RbCleanerShmem->rbCleanerPid) != 0; } +/* + * 鍔熻兘锛 绛夊緟Rbcleaner鍚姩 + * + * 鍙傛暟锛氭棤 + * + * 杩斿洖鍊硷細鏃 + */ static void RbCleanerAlive() { - int ntries; - int maxtries = 50; + int ntries; // 鐢ㄤ簬璁板綍灏濊瘯鐨勬鏁 + int maxtries = 50; // 琛ㄧず鏈澶氱瓑寰50娆 /* Wait 5s until rbcleaner startup. */ for (ntries = 0;; ntries++) { + // 妫鏌 rbCleanerPid 鏄惁涓嶇瓑浜0锛屽鏋滄槸锛屽垯琛ㄧずRbcleaner宸茬粡鍚姩锛屽惊鐜細缁撴潫 if (pg_atomic_read_u64(&t_thrd.rbcleaner_cxt.RbCleanerShmem->rbCleanerPid) != 0) { break; } + // 濡傛灉 ntries 杈惧埌浜 maxtries锛屽嵆绛夊緟娆℃暟杈惧埌涓婇檺 if (ntries >= maxtries) { + // 鎶ュ憡涓涓敊璇紝琛ㄧずRbcleaner鏈兘鍚姩 ereport(ERROR, (errmsg("rbcleaner not running"))); } + // 濡傛灉灏氭湭鍚姩锛岃褰曚竴鏉℃棩蹇楁秷鎭紝琛ㄧず姝e湪閲嶈瘯绛夊緟Rbcleaner鍚姩 elog(LOG, "retry to wait rbcleaner started"); /* wait 0.1 sec, then retry */ - pg_usleep(100000L); + pg_usleep(100000L); // 浼戠湢0.1绉 } } +/* + * 鍔熻兘锛 鍞ら啋Rbcleaner杩涚▼ + * + * 鍙傛暟锛氭棤 + * + * 杩斿洖鍊硷細鏃 + */ static void RbCltWakeupCleaner() { SetLatch(t_thrd.rbcleaner_cxt.RbCleanerShmem->rbCleanerLatch); } +/* + * 鍔熻兘锛 鍚戞秷鎭槦鍒楁彁浜urge娑堟伅 + * + * 鍙傛暟锛 + * localMsg锛氭寚鍚 PurgeMsg 缁撴瀯浣撶殑鎸囬拡锛屽寘鍚簡瑕佹彁浜ょ殑Purge娑堟伅鐨勪俊鎭 + * wait锛氳〃绀哄鏋滄秷鎭槦鍒楀凡婊℃椂鏄惁绛夊緟 + * + * 杩斿洖鍊硷細 + * uint32绫诲瀷锛岃繑鍥炲凡鎻愪氦娑堟伅鐨処D鎴栨棤鏁圛D + */ static uint32 RbCltSubmit(PurgeMsg *localMsg, bool wait = true) { - PurgeMsgQueue *msgQue = RbGetQueue(); + PurgeMsgQueue *msgQue = RbGetQueue(); // 鑾峰彇鎸囧悜娑堟伅闃熷垪鐨勬寚閽 PurgeMsg *prMsg = NULL; uint64 currMsgId; - while (true) { + while (true) { // 寰幆锛岀洿鍒版秷鎭槦鍒椾笉鍐嶆弧涓烘 + // 浣跨敤鑷棆閿 SpinLockAcquire 鏉ヨ幏鍙栨秷鎭槦鍒楃殑浜掓枼閿 SpinLockAcquire(&msgQue->mutex); + // 妫鏌ユ秷鎭槦鍒楁槸鍚﹀凡婊 if (!RbQueueIsFull(msgQue)) { - break; + break; // 濡傛灉娑堟伅闃熷垪涓嶆弧锛岃烦鍑哄惊鐜 } - SpinLockRelease(&msgQue->mutex); + SpinLockRelease(&msgQue->mutex); // 閲婃斁閿 if (wait) { /* wait 0.01 sec, then retry */ + // wait涓簍rue锛屾彁浜ゆ秷鎭 elog(LOG, "purge message queue is full, try again."); - pg_usleep(10000L); + pg_usleep(10000L); // 绛夊緟涓娈垫椂闂 } else { + // 鍚﹀垯锛岃褰曚竴鏉℃棩蹇楁秷鎭 elog(LOG, "purge message queue is full, ignore."); - return RB_INVALID_MSGID; + return RB_INVALID_MSGID;- // 杩斿洖涓涓壒娈婄殑鏃犳晥娑堟伅ID } } - prMsg = RbQueueNext(msgQue); + prMsg = RbQueueNext(msgQue); // 涓鏃︽秷鎭槦鍒椾笉鍐嶆弧锛岃幏鍙栦笅涓涓彲鐢ㄧ殑娑堟伅鎸囬拡 - SpinLockAcquire(&prMsg->mutex); + SpinLockAcquire(&prMsg->mutex); // 浣跨敤鑷棆閿 SpinLockAcquire 鏉ヨ幏鍙 prMsg 鐨勪簰鏂ラ攣 /* Set id. */ - currMsgId = RbGetNextMsgId(); + currMsgId = RbGetNextMsgId(); // 璁剧疆褰撳墠娑堟伅鐨処D涓轰笅涓涓彲鐢ㄧ殑娑堟伅ID + // 纭繚瀹冩槸闃熷垪涓殑涓嬩竴涓綅缃 Assert((currMsgId % RB_MAX_MSGQ_SIZE) == msgQue->tail); + // 濡傛灉 prMsg 鐨処D涓嶆槸鏃犳晥娑堟伅ID if (prMsg->id != RB_INVALID_MSGID) { + // 浼氬彂鍑鸿鍛婃秷鎭紝琛ㄧず褰撳墠娑堟伅灏嗚鐩栧凡瀛樺湪鐨勬秷鎭 elog(WARNING, "purge message %lu was overrided by %lu", prMsg->id, currMsgId); } + // 璁剧疆 prMsg 鐨処D銆佽姹傘佸搷搴斾互鍙婃爣璁 prMsg->id = currMsgId; /* Set req. */ RbMsgCopyReq(&prMsg->req, &localMsg->req); @@ -171,77 +234,121 @@ static uint32 RbCltSubmit(PurgeMsg *localMsg, bool wait = true) /* Set Latch. */ InitLatch(&prMsg->latch); - RbQueuePush(msgQue); + RbQueuePush(msgQue); // 灏嗘秷鎭帹鍏ユ秷鎭槦鍒 + // 浣跨敤鑷棆閿 SpinLockRelease 閲婃斁 prMsg 鍜屾秷鎭槦鍒楃殑浜掓枼閿 SpinLockRelease(&prMsg->mutex); SpinLockRelease(&msgQue->mutex); - return prMsg->id; + return prMsg->id; // 杩斿洖宸叉彁浜ゆ秷鎭殑ID } +/* + * 鍔熻兘锛 灏哖urge娑堟伅鎻愪氦鍒版秷鎭槦鍒 + * + * 鍙傛暟锛 + * localMsg锛氭寚鍚 PurgeMsg 缁撴瀯浣撶殑鎸囬拡锛屽寘鍚簡瑕佹彁浜ょ殑Purge娑堟伅鐨勪俊鎭 + * + * 杩斿洖鍊硷細 + * uint32绫诲瀷锛岃繑鍥炲凡鎻愪氦娑堟伅鐨処D鎴栨棤鏁圛D + */ static uint32 RbCltPushMsg(PurgeMsg *localMsg) { uint32 id; /* Make sure rbcleaner alive. */ - RbCleanerAlive(); + RbCleanerAlive(); // 纭繚Rbcleaner姝e湪杩愯 /* Submit a purge message. */ - id = RbCltSubmit(localMsg); + id = RbCltSubmit(localMsg); // 鎻愪氦Purge娑堟伅锛屽苟灏嗚繑鍥炵殑娑堟伅ID /* Wakeup cleaner to process a new prMsg. */ - RbCltWakeupCleaner(); + RbCltWakeupCleaner(); // 鍞ら啋Rbcleaner锛屼互渚垮鐞嗘柊鐨凱urge娑堟伅 - return id; + return id; // 杩斿洖鍒氬垰鎻愪氦鐨勬秷鎭殑ID } +/* + * 鍔熻兘锛 鍙栨秷鎸囧畾ID鐨凱urge娑堟伅 + * + * 鍙傛暟锛 + * id锛歅urge娑堟伅鐨処D + * + * 杩斿洖鍊硷細鏃 + */ static void RbCltCancel(uint64 id) { - PurgeMsg *rbMsg = RbMsg(id); - SpinLockAcquire(&rbMsg->mutex); + PurgeMsg *rbMsg = RbMsg(id); // 鐢ㄦ秷鎭疘D鑾峰彇鎸囧悜鐩稿簲娑堟伅鐨勬寚閽 + SpinLockAcquire(&rbMsg->mutex); // 鑾峰彇娑堟伅鐨勪簰鏂ラ攣 + // 妫鏌ユ秷鎭殑鍝嶅簲鐘舵佹槸鍚︿负 PURGE_MSG_STATUS_OVERRIDE if (rbMsg->res.status != PURGE_MSG_STATUS_OVERRIDE) { + // 濡傛灉涓嶆槸锛屽垯灏嗘秷鎭殑 cancel 鏍囧織璁剧疆涓 true rbMsg->req.cancel = true; } - SpinLockRelease(&rbMsg->mutex); + SpinLockRelease(&rbMsg->mutex); // 閲婃斁娑堟伅鐨勪簰鏂ラ攣 } +/* + * 鍔熻兘锛 澶勭悊杩涚▼涓柇 + * + * 鍙傛暟锛 + * rc锛氱瓑寰匧atch鐨勭粨鏋滐紝鍏朵腑鍖呮嫭鏍囧織浣嶏紝鎸囩ず鏄惁鏈夎繘绋嬩腑鏂瓑淇℃伅 + * id锛歅urge娑堟伅鐨処D + * + * 杩斿洖鍊硷細鏃 + */ void RbCltProcInterrupts(int rc, uint64 id) { + // 妫鏌 rc 涓殑鏍囧織浣嶏紝浠ョ‘瀹氭槸鍚︽湁杩涚▼涓柇 if (((unsigned int)rc) & WL_POSTMASTER_DEATH) { + // 濡傛灉妫娴嬪埌 "WL_POSTMASTER_DEATH" 鏍囧織浣嶏紝琛ㄧず涓昏繘绋嬪凡缁忕粓姝 + // 鍛婁竴涓棩蹇楁秷鎭紝琛ㄧず杩炴帴灏嗚缁堟 ereport(LOG, (errmsg("terminating connection due to postmaster death."))); - proc_exit(1); + proc_exit(1); // 閫鍑哄綋鍓嶈繘绋 } - + // 濡傛灉鏈夎繘绋嬮鍑烘垨绠$悊鍛樺懡浠 if (t_thrd.int_cxt.ProcDiePending || t_thrd.proc_cxt.proc_exit_inprogress) { - RbCltCancel(id); + RbCltCancel(id); // 鍙栨秷绛夊緟鐨勬秷鎭 + // 鎶ュ憡涓涓嚧鍛介敊璇秷鎭 ereport(FATAL, (errcode(ERRCODE_ADMIN_SHUTDOWN), errmsg("canceling the wait for rbcleaner response and " "terminating connection due to administrator command"))); } - + // 濡傛灉鐢ㄦ埛鍙戝嚭浜嗗彇娑堟煡璇㈢殑璇锋眰 if (t_thrd.int_cxt.QueryCancelPending) { - RbCltCancel(id); + RbCltCancel(id); // 鍙栨秷绛夊緟鐨勬秷鎭 + // 鎶ュ憡涓涓敊璇秷鎭 ereport(ERROR, (errmsg("canceling wait for rbcleaner response due to user request"))); } - if (!RbCleanerIsAlive()) { - ereport(ERROR, (errmsg("rbcleaner not running"))); + if (!RbCleanerIsAlive()) { // 濡傛灉Rbcleaner鏈湪杩愯涓 + ereport(ERROR, (errmsg("rbcleaner not running"))); // 鎶ュ憡涓涓敊璇秷鎭 } } + +/* + * 鍔熻兘锛 绛夊緟Rbcleaner杩涚▼瀵规彁浜ょ殑Purge娑堟伅鍋氬嚭鍝嶅簲 + * + * 鍙傛暟锛 + * id锛歅urge娑堟伅鐨処D + * localMsg锛氭寚鍚 PurgeMsg 缁撴瀯浣撶殑鎸囬拡锛屽寘鍚簡瑕佹彁浜ょ殑Purge娑堟伅鐨勪俊鎭 + * + * 杩斿洖鍊硷細鏃 + */ static void RbCltWaitMsg(uint64 id, PurgeMsg *localMsg) { - PurgeMsg *rbMsg = RbMsg(id); - uint32 totalTimes = 300; - uint32 retryNums = 0; - + PurgeMsg *rbMsg = RbMsg(id); // 鑾峰彇鍒版寚鍚戠浉搴擯urge娑堟伅鐨勬寚閽 + uint32 totalTimes = 300; // 琛ㄧず鏈澶х瓑寰匯bcleaner鍝嶅簲鐨勬鏁 + uint32 retryNums = 0; // 璁板綍宸茬粡閲嶈瘯鐨勬鏁 + // 寰幆锛屼竴鐩寸瓑寰匯bcleaner鐨勫搷搴旓紝鎴栬呭湪杈惧埌鏈澶х瓑寰呮鏁板悗閫鍑 while (true) { int rc; /* Clear any already-pending wakeups */ - ResetLatch(&rbMsg->latch); + ResetLatch(&rbMsg->latch); // 娓呴櫎宸叉寕璧风殑 rbMsg 鐨 latch锛屼互鍑嗗绛夊緟涓嬩竴娆$殑鍝嶅簲 /* Wait latch for a maximum of 1 sec for a rbcleaner response. */ rc = WaitLatch(&rbMsg->latch, WL_LATCH_SET | WL_TIMEOUT | WL_POSTMASTER_DEATH, 1000L); @@ -251,25 +358,35 @@ static void RbCltWaitMsg(uint64 id, PurgeMsg *localMsg) /* Check rbcleaner response. */ RbMsgGetRes(id, &localMsg->res, true); + // 妫鏌ユ秷鎭殑鍝嶅簲鐘舵佹槸鍚﹁〃绀烘秷鎭凡缁忓畬鎴 if (RbMsgIsDone(localMsg->res.status)) { - break; + break; // 濡傛灉鏄垯閫鍑哄惊鐜 } /* Break if rbcleaner not response in a maximum of 300 seconds. */ if (retryNums > totalTimes) { - RbCltCancel(id); + RbCltCancel(id); // 鍙栨秷绛夊緟鐨勬秷鎭 + // 鍝嶅簲鐘舵佽缃负閿欒鐘舵侊紝骞舵彁渚涚浉搴旂殑閿欒淇℃伅 RbMsgSetStatusErrLocal(&localMsg->res, PURGE_MSG_STATUS_ERROR, ERRCODE_INTERNAL_ERROR, "wait response from rbcleaner timeout over 300 seconds"); break; } - retryNums++; + retryNums++; // 澧炲姞 retryNums 閲嶈瘯鐨勬鏁拌鏁板櫒 } } +/* + * 鍔熻兘锛 鎵цPurge娑堟伅鐨勬彁浜ゅ拰绛夊緟锛屼互纭繚娑堟伅琚鐞嗭紝鍚屾椂澶勭悊鍙兘鐨勫搷搴旇鐩栨儏鍐 + * + * 鍙傛暟锛 + * localMsg锛氭寚鍚 PurgeMsg 缁撴瀯浣撶殑鎸囬拡锛屽寘鍚簡瑕佹彁浜ょ殑Purge娑堟伅鐨勪俊鎭 + * + * 杩斿洖鍊硷細鏃 + */ static void RbCltExec(PurgeMsg *localMsg) { int ntries; - int maxtries = 10; + int maxtries = 10; // 鏈澶氶噸璇 maxtries 娆 for (ntries = 0;; ntries++) { uint32 id; @@ -282,25 +399,43 @@ static void RbCltExec(PurgeMsg *localMsg) /* 3. Break if res not overrided. */ if (localMsg->res.status != PURGE_MSG_STATUS_OVERRIDE) { - return; + return; // 琛ㄧず鍝嶅簲娌℃湁琚鐩栵紝鍑芥暟浼氳繑鍥 } + // 鍝嶅簲琚鐩栦簡锛岃褰曚竴鏉℃棩蹇楁秷鎭 elog(LOG, "purge message \"%u\" result overrided, try again", id); } - + // 娑堟伅鐨勫搷搴旂姸鎬佷竴鐩磋瑕嗙洊锛岃秴杩囦簡鏈澶ч噸璇曟鏁帮紝璁板綍涓涓敊璇秷鎭 elog(ERROR, "purge message result overrided over \"%d\" times", maxtries); } +/* + * 鍔熻兘锛 鎶ュ憡鐢变簬閿佸啿绐佽屽鑷寸殑閿欒鎯呭喌 + * + * 鍙傛暟锛 + * res锛氭寚鍚 PurgeMsgRes 缁撴瀯浣撶殑鎸囬拡锛屽寘鍚湁鍏砅urge娑堟伅鍝嶅簲鐨勪俊鎭 + * + * 杩斿洖鍊硷細鏃 + */ static void RbErrReportLockConflict(const PurgeMsgRes *res) { const char *rbErrFormatLockConflict = "autopurge failed due to lock conflict: %s. " "DETAIL: %d objects purged, %d objects lock conflicted, " "%d objects not exist."; + // 鎶ュ憡涓涓敊璇 ereport(ERROR, (errcode(ERRCODE_RBIN_LOCK_NOT_AVAILABLE), errmsg(rbErrFormatLockConflict, res->errMsg, res->purgedNum, res->skippedNum, res->undefinedNum))); } +/* + * 鍔熻兘锛 鎶ュ憡鎰忓閿欒鎯呭喌 + * + * 鍙傛暟锛 + * res锛氭寚鍚 PurgeMsgRes 缁撴瀯浣撶殑鎸囬拡锛屽寘鍚湁鍏砅urge娑堟伅鍝嶅簲鐨勪俊鎭 + * + * 杩斿洖鍊硷細鏃 + */ static void RbErrReport(PurgeMsgRes *res) { const char *rbErrFormatError = "autopurge failed due to unexpected error: %s. " @@ -312,181 +447,304 @@ static void RbErrReport(PurgeMsgRes *res) res->skippedNum, res->undefinedNum))); } +/* + * 鍔熻兘锛 澶勭悊Purge娑堟伅鐨勫畬鎴愭儏鍐碉紝鍖呮嫭妫鏌ユ槸鍚︽湁閿欒銆侀攣鍐茬獊浠ュ強DML鎿嶄綔鐨勭粨鏋 + * + * 鍙傛暟锛 + * msg锛氭寚鍚 PurgeMsg 缁撴瀯浣撶殑鎸囬拡锛屽寘鍚簡鏈夊叧Purge娑堟伅鐨勪俊鎭 + * isDML锛氳〃绀烘槸鍚︽槸DML锛堟暟鎹搷浣滆瑷锛夌被鍨嬬殑Purge娑堟伅 + * purged锛氱敤浜庡瓨鍌―ML鎿嶄綔鏄惁鎴愬姛娓呯悊浜嗗璞 + * + * 杩斿洖鍊硷細鏃 + */ static void RbCltDone(PurgeMsg *msg, bool isDML = false, bool *purged = NULL) { - if (RbResIsError(msg->res.errCode)) { - RbErrReport(&msg->res); + if (RbResIsError(msg->res.errCode)) { // 濡傛灉Purge娑堟伅鐨勫搷搴斾腑鍖呭惈閿欒 + RbErrReport(&msg->res); // 鎶ュ憡閿欒 } /* non-DML purge cmds */ - if (!isDML) { - if (msg->res.skippedNum > 0) { - RbErrReportLockConflict(&msg->res); + if (!isDML) { // 濡傛灉涓嶆槸DML绫诲瀷鐨凱urge娑堟伅 + if (msg->res.skippedNum > 0) { // 濡傛灉娑堟伅涓瓨鍦ㄩ攣鍐茬獊瀵硅薄 + RbErrReportLockConflict(&msg->res); // 鎶ュ憡閿佸啿绐侀敊璇 } - return; + return; // 鍚﹀垯锛岀洿鎺ヨ繑鍥 } - + // 濡傛灉鏄疍ML绫诲瀷鐨凱urge娑堟伅 + // 鏍规嵁娓呯悊鐨勫璞℃暟閲忓拰閿佸啿绐佺殑鎯呭喌鏉ョ‘瀹氭槸鍚︽垚鍔熸竻鐞嗕簡瀵硅薄 /* DML purge cmd */ + + // 濡傛灉宸叉竻鐞嗙殑瀵硅薄鏁伴噺澶т簬0 if (msg->res.purgedNum + msg->res.undefinedNum > 0) { - *purged = true; + *purged = true; // 琛ㄧず鎴愬姛娓呯悊浜嗗璞 } else if (msg->res.skippedNum == 0) { - *purged = false; + // 濡傛灉娌℃湁閿佸啿绐佸璞 + *purged = false; // 琛ㄧず娌℃湁鎴愬姛娓呯悊瀵硅薄 } else { - RbErrReportLockConflict(&msg->res); + RbErrReportLockConflict(&msg->res); // 鎶ュ憡閿佸啿绐佺殑閿欒 } } +/* + * 鍔熻兘锛 娓呯悊鎸囧畾绌洪棿锛堣〃绌洪棿锛変腑鐨凞ML鎿嶄綔鐢熸垚鐨勫瀮鍦炬暟鎹 + * + * 鍙傛暟锛 + * spcId锛氳娓呯悊鐨勮〃绌洪棿鐨凮ID + * + * 杩斿洖鍊硷細 + * bool绫诲瀷锛岃〃绀烘槸鍚︽垚鍔熸竻鐞嗕簡鍨冨溇鏁版嵁 + */ bool RbCltPurgeSpaceDML(Oid spcId) { - if (!TcapFeatureAvail()) { - return false; + if (!TcapFeatureAvail()) { // 妫鏌ユ槸鍚︽敮鎸乀cap鐗规 + return false; // 濡傛灉涓嶆敮鎸侊紝鍒欒繑鍥 false锛岃〃绀烘竻鐞嗘搷浣滃け璐 } - PurgeMsg prMsg; + PurgeMsg prMsg; // 鐢ㄤ簬浼犻掓竻鐞嗘搷浣滅殑鐩稿叧淇℃伅 bool purged = false; - if (TrRbIsEmptySpc(spcId)) { - return false; + if (TrRbIsEmptySpc(spcId)) { // 妫鏌ユ寚瀹氳〃绌洪棿 spcId 鏄惁涓虹┖ + return false; // 濡傛灉涓虹┖锛屽垯杩斿洖 false锛岃〃绀烘竻鐞嗘搷浣滃け璐 } - + // 鍒濆鍖 + // 璁剧疆娓呯悊娑堟伅绫诲瀷涓篋ML锛屾寚瀹氳娓呯悊鐨勮〃绌洪棿 spcId锛屼互鍙婂綋鍓嶆暟鎹簱鐨処D RbMsgInit(&prMsg, PURGE_MSG_TYPE_DML, spcId, u_sess->proc_cxt.MyDatabaseId); - RbCltExec(&prMsg); - RbCltDone(&prMsg, true, &purged); + RbCltExec(&prMsg); // 鎻愪氦娓呯悊娑堟伅锛屽苟绛夊緟澶勭悊 + RbCltDone(&prMsg, true, &purged); // 澶勭悊娓呯悊娑堟伅鐨勭粨鏋 - return purged; + return purged; // 杩斿洖purged锛岃〃绀烘槸鍚︽垚鍔熸竻鐞嗕簡鍨冨溇鏁版嵁 } +/* + * 鍔熻兘锛 娓呯悊鎸囧畾绌洪棿锛堣〃绌洪棿锛変腑鐨勫洖鏀剁珯鏁版嵁锛屼絾鍓嶆彁鏄病鏈夊叾浠栧洖鏀剁珯瀵硅薄渚濊禆浜庤绌洪棿 + * + * 鍙傛暟锛 + * spcId锛氳娓呯悊鐨勮〃绌洪棿鐨凮ID + * + * 杩斿洖鍊硷細鏃 + */ void RbCltPurgeSpace(Oid spcId) { - if (!TcapFeatureAvail()) { - return; + if (!TcapFeatureAvail()) { // 妫鏌ユ槸鍚︽敮鎸乀cap鐗规 + return; // 濡傛灉涓嶆敮鎸侊紝鍒欒繑鍥 } - if (!TrRbIsEmptySpc(spcId)) { + if (!TrRbIsEmptySpc(spcId)) { // 妫鏌ユ寚瀹氳〃绌洪棿 spcId 鏄惁涓虹┖ + // 濡傛灉涓嶄负绌猴紝琛ㄧず鏈夊叾浠栧洖鏀剁珯瀵硅薄渚濊禆浜庤绌洪棿 + // 鎶ュ憡閿欒娑堟伅锛屾寚绀烘棤娉曟墽琛屾竻鐞嗘搷浣 elog(ERROR, "cannot execute this command because other recycle objects depend on the object, " "use \"purge recyclebin\" to clean recyclebin then try again."); } } +/* + * 鍔熻兘锛 娓呯悊鏁版嵁搴撳洖鏀剁珯涓殑鏁版嵁锛屼互鍒犻櫎涓嶅啀闇瑕佺殑瀵硅薄 + * + * 鍙傛暟锛氭棤 + * + * 杩斿洖鍊硷細鏃 + */ void RbCltPurgeRecyclebin() { - if (!TcapFeatureAvail()) { - return; + if (!TcapFeatureAvail()) { // 妫鏌ユ槸鍚︽敮鎸乀cap鐗规 + return; // 濡傛灉涓嶆敮鎸侊紝鍒欒繑鍥 } PurgeMsg prMsg; - + // 妫鏌ュ綋鍓嶆暟鎹簱鐨勫洖鏀剁珯鏄惁涓虹┖ if (TrRbIsEmptyDb(u_sess->proc_cxt.MyDatabaseId)) { - return; + return; // 濡傛灉涓虹┖锛岃〃绀烘病鏈夐渶瑕佹竻鐞嗙殑瀵硅薄锛岃繑鍥 } - + // 鍒濆鍖 + // 璁剧疆娓呯悊娑堟伅绫诲瀷涓篟ECYCLEBIN锛屾寚瀹氳娓呯悊鐨勬暟鎹簱锛屽嵆褰撳墠鏁版嵁搴 RbMsgInit(&prMsg, PURGE_MSG_TYPE_RECYCLEBIN, InvalidOid, u_sess->proc_cxt.MyDatabaseId); - RbCltExec(&prMsg); - RbCltDone(&prMsg); + RbCltExec(&prMsg); // 鎻愪氦娓呯悊娑堟伅锛屽苟绛夊緟澶勭悊 + RbCltDone(&prMsg); // 澶勭悊娓呯悊娑堟伅鐨勭粨鏋 } +/* + * 鍔熻兘锛 娓呯悊鎸囧畾鐨勬暟鎹簱妯″紡锛坰chema锛変腑鐨勫洖鏀剁珯鏁版嵁 + * 鍓嶆彁鏄病鏈夊叾浠栧洖鏀剁珯瀵硅薄渚濊禆浜庤妯″紡 + * + * 鍙傛暟锛 + * nspId锛氳娓呯悊鐨勬暟鎹簱妯″紡鐨凮ID + * + * 杩斿洖鍊硷細鏃 + */ void RbCltPurgeSchema(Oid nspId) { - if (!TcapFeatureAvail()) { - return; + if (!TcapFeatureAvail()) { // 妫鏌ユ槸鍚︽敮鎸乀cap鐗规 + return; // 濡傛灉涓嶆敮鎸侊紝鍒欒繑鍥 } - if (!TrRbIsEmptySchema(nspId)) { + if (!TrRbIsEmptySchema(nspId)) { // 妫鏌ユ寚瀹氭ā寮 nspId 鏄惁涓虹┖ + // 濡傛灉涓嶄负绌猴紝琛ㄧず鏈夊叾浠栧洖鏀剁珯瀵硅薄渚濊禆浜庤妯″紡 + // 鎶ュ憡閿欒娑堟伅锛屾寚绀烘棤娉曟墽琛屾竻鐞嗘搷浣 elog(ERROR, "cannot execute this command because other recycle objects depend on the object, " "use \"purge recyclebin\" to clean recyclebin then try again."); return; } } +/* + * 鍔熻兘锛 娓呯悊鎸囧畾鐨勭敤鎴疯鑹诧紙user role锛夌浉鍏崇殑鍥炴敹绔欐暟鎹 + * 鍓嶆彁鏄病鏈夊叾浠栧洖鏀剁珯瀵硅薄渚濊禆浜庤鐢ㄦ埛瑙掕壊 + * + * 鍙傛暟锛 + * nspId锛氳娓呯悊鐨勬暟鎹簱妯″紡鐨凮ID + * + * 杩斿洖鍊硷細鏃 + */ void RbCltPurgeUser(Oid roleId) { - if (!TcapFeatureAvail()) { - return; + if (!TcapFeatureAvail()) { // 妫鏌ユ槸鍚︽敮鎸乀cap鐗规 + return; // 濡傛灉涓嶆敮鎸侊紝鍒欒繑鍥 } - if (!TrRbIsEmptyUser(roleId)) { + if (!TrRbIsEmptyUser(roleId)) { // 妫鏌ユ寚瀹氱敤鎴疯鑹 roleId 鏄惁涓虹┖ + // 濡傛灉涓嶄负绌猴紝琛ㄧず鏈夊叾浠栧洖鏀剁珯瀵硅薄渚濊禆浜庤鐢ㄦ埛瑙掕壊 + // 鎶ュ憡閿欒娑堟伅锛屾寚绀烘棤娉曟墽琛屾竻鐞嗘搷浣 elog(ERROR, "cannot execute this command because other recycle objects depend on the object, " "use \"purge recyclebin\" to clean recyclebin then try again."); } } +/* + * 鍔熻兘锛 娓呯悊鎸囧畾鐨勬暟鎹簱涓殑鍥炴敹绔欐暟鎹 + * 鍓嶆彁鏄病鏈夊叾浠栧洖鏀剁珯瀵硅薄渚濊禆浜庤鏁版嵁搴 + * + * 鍙傛暟锛 + * dbId锛氳娓呯悊鐨勬暟鎹簱鐨凮ID + * + * 杩斿洖鍊硷細鏃 + */ void RbCltPurgeDatabase(Oid dbId) { - if (!TcapFeatureAvail()) { - return; + if (!TcapFeatureAvail()) { // 妫鏌ユ槸鍚︽敮鎸乀cap鐗规 + return; // 濡傛灉涓嶆敮鎸侊紝鍒欒繑鍥 } - if (!TrRbIsEmptyDb(dbId)) { + if (!TrRbIsEmptyDb(dbId)) { // 妫鏌ユ寚瀹氭暟鎹簱 dbId 鏄惁涓虹┖ + // 濡傛灉涓嶄负绌猴紝琛ㄧず鏈夊叾浠栧洖鏀剁珯瀵硅薄渚濊禆浜庤鏁版嵁搴 + // 鎶ュ憡閿欒娑堟伅锛屾寚绀烘棤娉曟墽琛屾竻鐞嗘搷浣 elog(ERROR, "cannot execute this command because other recycle objects depend on the object, " "use \"purge recyclebin\" to clean recyclebin then try again."); } } +/* + * 鍔熻兘锛 鍚姩鍥炴敹绔欐竻鐞嗚繘绋 + * + * 鍙傛暟锛氭棤 + * + * 杩斿洖鍊硷細鏃 + */ ThreadId StartRbCleaner(void) { - if (!IsPostmasterEnvironment) { + if (!IsPostmasterEnvironment) { // 妫鏌ユ槸鍚﹀浜嶱ostmaster鐜涓 return 0; } - if (canAcceptConnections(false) == CAC_OK) { - return initialize_util_thread(RBCLEANER); + if (canAcceptConnections(false) == CAC_OK) { // 妫鏌ユ槸鍚﹀彲浠ユ帴鍙楁柊杩炴帴 + return initialize_util_thread(RBCLEANER); // 濡傛灉鍙互锛屽惎鍔ㄥ洖鏀剁珯娓呯悊杩涚▼ } - + // 濡傛灉鏃犳硶鎺ュ彈鏂拌繛鎺ワ紝璁板綍涓鏉℃棩蹇楁秷鎭紝鎸囩ず灏氭湭鍑嗗濂藉惎鍔ㄥ洖鏀剁珯娓呯悊杩涚▼ ereport(LOG, (errmsg("not ready to start recyclebin cleaner."))); return 0; } +/* + * 鍔熻兘锛 妫鏌ュ綋鍓嶈繘绋嬫槸鍚︿负鍥炴敹绔欐竻鐞嗚繘绋 + * + * 鍙傛暟锛氭棤 + * + * 杩斿洖鍊硷細 + * bool绫诲瀷锛屽鏋滃綋鍓嶈繘绋嬫槸鍥炴敹绔欐竻鐞嗚繘绋嬶紝鍒欒繑鍥 true锛屽惁鍒欒繑鍥 false + */ bool IsRbCleanerProcess(void) { return t_thrd.role == RBCLEANER; } +/* + * 鍔熻兘锛 妫鏌ュ洖鏀剁珯宸ヤ綔杩涚▼鏄惁瀛樻椿 + * + * 鍙傛暟锛氭棤 + * + * 杩斿洖鍊硷細 + * bool绫诲瀷锛屽瓨娲诲垯杩斿洖 true锛屽惁鍒欒繑鍥 false + */ static bool RbWorkerIsAlive() { - RbWorkerInfo *workInfo = RbGetWorkerInfo(); + RbWorkerInfo *workInfo = RbGetWorkerInfo(); // 鑾峰彇鍥炴敹绔欏伐浣滆繘绋嬩俊鎭 int ntries; int maxtries = 500; /* Wait 5s until rbcleaner stopped. */ + // 浣跨敤寰幆绛夊緟鐨勬柟寮忔鏌ュ洖鏀剁珯宸ヤ綔杩涚▼鐨勭姸鎬 for (ntries = 0;; ntries++) { + // 濡傛灉宸ヤ綔杩涚▼鐨凱ID涓0 if (pg_atomic_read_u64(&workInfo->rbworkerPid) == 0) { - return false; + return false; // 琛ㄧず宸ヤ綔杩涚▼宸茬粡鍋滄 } + // 濡傛灉瓒呰繃閲嶈瘯娆℃暟 if (ntries >= maxtries) { - return true; + return true; // 琛ㄧず宸ヤ綔杩涚▼浠嶇劧瀛樻椿 } /* wait 0.01 sec, then retry */ - pg_usleep(10000L); + pg_usleep(10000L); // 濡傛灉宸ヤ綔杩涚▼鐨凱ID涓嶄负0锛岀瓑寰呬竴娈垫椂闂村悗鍐嶆妫鏌 } return true; } /* SIGHUP: set flag to re-read config file at next convenient time */ + +/* + *鍔熻兘锛氬鐞 SIGHUP 淇″彿锛岀敤浜庨噸鏂拌鍙栭厤缃枃浠 + * + * 鍙傛暟: + * SIGNAL_ARGS: 淇″彿澶勭悊绋嬪簭鐨勫弬鏁板垪琛紝鎻愪緵鍏充簬瑙﹀彂淇″彿鐨勪笂涓嬫枃淇℃伅 + * + * 杩斿洖鍊: + * 鏃 + */ static void RbSighupHandler(SIGNAL_ARGS) { - int saveErrno = errno; + int saveErrno = errno; // 淇濆瓨褰撳墠鐨勯敊璇爜 - t_thrd.rbcleaner_cxt.got_SIGHUP = true; + t_thrd.rbcleaner_cxt.got_SIGHUP = true; // 琛ㄧず鎺ユ敹鍒 SIGHUP 淇″彿 - SetLatch(&t_thrd.proc->procLatch); + SetLatch(&t_thrd.proc->procLatch); // 璁剧疆璇ョ嚎绋嬬殑latch - errno = saveErrno; + errno = saveErrno; // 鎭㈠涔嬪墠淇濆瓨鐨勯敊璇爜 - elog(LOG, "rbcleaner signaled: SIGHUP"); + elog(LOG, "rbcleaner signaled: SIGHUP"); // 璁板綍娑堟伅 } +/* + *鍔熻兘锛氬彂閫丼IGINT淇″彿鏉ュ彇娑堝洖鏀剁珯宸ヤ綔杩涚▼ + * + * 鍙傛暟:鏃 + * + * 杩斿洖鍊: + * 鏃 + */ static void RbCancelRbworker() { - RbWorkerInfo *workInfo = RbGetWorkerInfo(); + RbWorkerInfo *workInfo = RbGetWorkerInfo(); // 鑾峰彇鍥炴敹绔欏伐浣滆繘绋嬩俊鎭 + // 鑾峰彇宸ヤ綔杩涚▼鐨凱ID ThreadId rbworkerPid = pg_atomic_read_u64(&workInfo->rbworkerPid); + // 濡傛灉宸ヤ綔杩涚▼鐨凱ID涓嶄负0锛岃〃绀哄伐浣滆繘绋嬪瓨鍦 + // 鍚戝伐浣滆繘绋嬪彂閫丼IGINT淇″彿锛屽鏋滃彂閫佷俊鍙峰け璐 if (rbworkerPid != 0 && gs_signal_send(rbworkerPid, SIGINT)) { + // 鎶ュ憡涓涓敊璇秷鎭紝鎸囩ず鏃犳硶鍙戦丼IGINT淇″彿缁欏伐浣滆繘绋 ereport(ERROR, (errmsg("could not send SIGINT signal to rbworker %lu: %m", rbworkerPid))); } - + // 璁板綍涓鏉℃棩蹇楁秷鎭紝鎸囩ず宸插悜宸ヤ綔杩涚▼鍙戦佷簡SIGINT淇″彿 elog(LOG, "rbcleaner: send SIGINT to rbworker %lu", rbworkerPid); } @@ -494,30 +752,43 @@ static void RbCancelRbworker() * Query-cancel signal from postmaster: abort current transaction * at soonest convenient time */ + +/* + *鍔熻兘锛氬鐞嗘潵鑷狿ostmaster鐨凷IGINT淇″彿锛屼互涓柇褰撳墠浜嬪姟骞跺彇娑堝洖鏀剁珯宸ヤ綔杩涚▼ + * + * 鍙傛暟: + * SIGNAL_ARGS: 淇″彿澶勭悊绋嬪簭鐨勫弬鏁板垪琛紝鎻愪緵鍏充簬瑙﹀彂淇″彿鐨勪笂涓嬫枃淇℃伅 + * + * 杩斿洖鍊: + * 鏃 + */ void RbSigintHandler(SIGNAL_ARGS) { - int saveErrno = errno; + int saveErrno = errno; // 淇濆瓨褰撳墠鐨勯敊璇爜 - RbCancelRbworker(); + RbCancelRbworker(); // 鍙戦丼IGINT淇″彿浠ュ彇娑堝洖鏀剁珯宸ヤ綔杩涚▼ /* * Don't joggle the elbow of proc_exit */ + // 妫鏌ユ槸鍚︽鍦ㄦ墽琛 proc_exit 鍑芥暟 if (!t_thrd.proc_cxt.proc_exit_inprogress) { - InterruptPending = true; - t_thrd.int_cxt.QueryCancelPending = true; + // 濡傛灉涓嶅湪 proc_exit + InterruptPending = true; // 琛ㄧず鏈変腑鏂姹 + t_thrd.int_cxt.QueryCancelPending = true; // 琛ㄧず鏈夊彇娑堣姹 /* * in libcomm interrupt is not allow, * gs_r_cancel will signal libcomm and * libcomm will then check for interrupt. */ - gs_r_cancel(); + gs_r_cancel(); // 閫氱煡 libcomm 搴撴鏌ユ槸鍚︽湁涓柇璇锋眰 /* * If it's safe to interrupt, and we're waiting for input or a lock, * service the interrupt immediately */ + // 妫鏌ユ槸鍚﹀彲浠ョ珛鍗冲鐞嗕腑鏂紝鏄惁鍏朵粬涓柇鎸傝捣锛屼互鍙婃槸鍚﹁繘鍏ュ叧閿尯鍩 if (t_thrd.int_cxt.ImmediateInterruptOK && t_thrd.int_cxt.InterruptHoldoffCount == 0 && t_thrd.int_cxt.CritSectionCount == 0) { /* bump holdoff count to make ProcessInterrupts() a no-op */ @@ -525,41 +796,64 @@ void RbSigintHandler(SIGNAL_ARGS) t_thrd.int_cxt.InterruptHoldoffCount++; LockErrorCleanup(); /* prevent CheckDeadLock from running */ t_thrd.int_cxt.InterruptHoldoffCount--; - ProcessInterrupts(); + ProcessInterrupts(); // 澶勭悊涓柇鎿嶄綔 } } /* If we're still here, waken anything waiting on the process latch */ if (t_thrd.proc) - SetLatch(&t_thrd.proc->procLatch); + SetLatch(&t_thrd.proc->procLatch); // 鍞ら啋璇ヨ繘绋嬬殑杩涚▼鏍囪 - errno = saveErrno; + errno = saveErrno; // 鎭㈠閿欒鐮 } /* SIGTERM: time to die */ + +/* + *鍔熻兘锛氬鐞 SIGTERM 淇″彿锛岀敤浜庢甯搁鍑 + * + * 鍙傛暟: + * SIGNAL_ARGS: 淇″彿澶勭悊绋嬪簭鐨勫弬鏁板垪琛紝鎻愪緵鍏充簬瑙﹀彂淇″彿鐨勪笂涓嬫枃淇℃伅 + * + * 杩斿洖鍊: + * 鏃 + */ static void RbSigtermHander(SIGNAL_ARGS) { - int saveErrno = errno; + int saveErrno = errno; // 淇濆瓨褰撳墠鐨勯敊璇爜 - t_thrd.rbcleaner_cxt.got_SIGTERM = true; + t_thrd.rbcleaner_cxt.got_SIGTERM = true; // 琛ㄧず璇锋眰姝e父閫鍑 - SetLatch(&t_thrd.proc->procLatch); + SetLatch(&t_thrd.proc->procLatch); // 璁剧疆璇ョ嚎绋嬬殑latch - errno = saveErrno; + errno = saveErrno; // 鎭㈠涔嬪墠淇濆瓨鐨勯敊璇爜 elog(LOG, "rbcleaner signaled: SIGTERM"); } +/* + *鍔熻兘锛氭敹鍒 SIGQUIT 淇″彿鏃讹紝鎵ц涓浜涙竻鐞嗘搷浣滐紝骞跺皢褰撳墠绾跨▼鏍囪涓洪鍑虹姸鎬 + * 鐒跺悗璁板綍鏃ュ織娑堟伅浠ユ寚绀 SIGQUIT 淇″彿鐨勫彂鐢 + * + * 鍙傛暟: + * SIGNAL_ARGS: 淇″彿澶勭悊绋嬪簭鐨勫弬鏁板垪琛紝鎻愪緵鍏充簬瑙﹀彂淇″彿鐨勪笂涓嬫枃淇℃伅 + * + * 杩斿洖鍊: + * 鏃 + */ static void RbSigquitHandler(SIGNAL_ARGS) { + // 灏 SIGQUIT 淇″彿娣诲姞鍒板悕涓 BlockSig 鐨勪俊鍙烽泦涓紝闃叉宓屽璋冪敤 sigaddset(&t_thrd.libpq_cxt.BlockSig, SIGQUIT); /* prevent nested calls */ + // 灏嗗綋鍓嶇嚎绋嬬殑淇″彿鎺╃爜璁剧疆涓 BlockSig 涓畾涔夌殑淇″彿鎺╃爜 + // 纭繚鍦ㄥ鐞 SIGQUIT 淇″彿鏈熼棿锛屽彧鏈 SIGQUIT 淇″彿琚樆濉烇紝鑰屽叾浠栦俊鍙蜂粛鐒跺彲浠ヨЕ鍙 gs_signal_setmask(&t_thrd.libpq_cxt.BlockSig, NULL); - on_exit_reset(); + on_exit_reset(); // 鎵ц涓浜涗笌閫鍑烘搷浣滅浉鍏崇殑娓呯悊宸ヤ綔 - gs_thread_exit(2); + gs_thread_exit(2); // 灏嗗綋鍓嶇嚎绋嬫爣璁颁负閫鍑虹姸鎬侊紝骞朵紶閫掑弬鏁 2 浣滀负閫鍑轰唬鐮 - elog(LOG, "rbcleaner signaled: SIGQUIT"); + elog(LOG, "rbcleaner signaled: SIGQUIT"); // 璁板綍涓鏉℃棩蹇楁秷鎭 } /* @@ -567,87 +861,138 @@ static void RbSigquitHandler(SIGNAL_ARGS) */ /* SIGUSR2: there is some message to purge the tablespace */ + +/* + *鍔熻兘锛氬鐞 SIGUSR2 淇″彿 + * + * 鍙傛暟: + * SIGNAL_ARGS: 淇″彿澶勭悊绋嬪簭鐨勫弬鏁板垪琛紝鎻愪緵鍏充簬瑙﹀彂淇″彿鐨勪笂涓嬫枃淇℃伅 + * + * 杩斿洖鍊: + * 鏃 + */ static void RbSigusr2Hander(SIGNAL_ARGS) { - int saveErrno = errno; + int saveErrno = errno; // 淇濆瓨閿欒鐮 - SetLatch(&t_thrd.proc->procLatch); + SetLatch(&t_thrd.proc->procLatch); // 璁剧疆褰撳墠杩涚▼鐨勮繘绋嬫爣璁帮紝浠ュ敜閱掔瓑寰呰鏍囪鐨勭嚎绋 - errno = saveErrno; + errno = saveErrno; // 鎭㈠閿欒鐮 - elog(LOG, "rbcleaner signaled: SIGUSR2"); + elog(LOG, "rbcleaner signaled: SIGUSR2"); // 璁板綍涓鏉℃棩蹇楁秷鎭 } +/* + *鍔熻兘锛氭墽琛屾竻鐞嗘搷浣 + * + * 鍙傛暟: + * code锛氶鍑轰唬鐮 + * arg锛氬弬鏁 + * 杩斿洖鍊: + * 鏃 + */ static void RbCleanerQuitAndClean(int code, Datum arg) { pg_atomic_write_u64(&t_thrd.rbcleaner_cxt.RbCleanerShmem->rbCleanerPid, 0); } +/* + *鍔熻兘锛氳幏鍙栦笌缁欏畾娑堟伅ID鐩稿叧鐨勬暟鎹簱鍒楄〃 + * + * 鍙傛暟: + * id锛氳澶勭悊鐨勬秷鎭疘D + * + * 杩斿洖鍊: + * 鑾峰彇鍒扮殑鏁版嵁搴撳垪琛 + */ static List *RbGetDbList(uint64 id) { - PurgeMsg *msg = RbMsg(id); - List *l = NIL; + PurgeMsg *msg = RbMsg(id); // 鑾峰彇娑堟伅ID瀵瑰簲鐨勬秷鎭璞 + List *l = NIL; // 鐢ㄤ簬瀛樺偍鏁版嵁搴撳垪琛 - if (msg->req.dbId != InvalidOid) { + if (msg->req.dbId != InvalidOid) { // 濡傛灉璇锋眰涓寚瀹氫簡鐗瑰畾鐨勬暟鎹簱 char *dbname = NULL; + // 鑾峰彇璇ユ暟鎹簱鐨勫悕绉 dbname = get_database_name(msg->req.dbId); + // 濡傛灉鎸囧畾鐨勬暟鎹簱涓嶅瓨鍦 if (dbname == NULL) { + // 鐢熸垚涓涓敊璇姤鍛婂苟鎶涘嚭涓涓敊璇紝鎸囩ず鏁版嵁搴撲笉瀛樺湪 ereport(ERROR, (errcode(ERRCODE_UNDEFINED_DATABASE), errmsg("database \"%u\" does not exist", msg->req.dbId))); } - return lappend(l, dbname); + return lappend(l, dbname); // 灏 dbname 娣诲姞鍒版暟鎹簱鍒楄〃 l 涓紝骞跺皢璇ュ垪琛ㄤ綔涓哄嚱鏁扮殑杩斿洖鍊 } - Assert(id == msg->id); + Assert(id == msg->id); // 妫鏌 id 鏄惁绛変簬娑堟伅瀵硅薄涓殑 msg->id + // 鎹秷鎭姹傜殑绫诲瀷鎵ц涓嶅悓鐨勬搷浣 switch (msg->req.type) { case PURGE_MSG_TYPE_DML: case PURGE_MSG_TYPE_TABLESPACE: case PURGE_MSG_TYPE_CAS_TABLESPACE: - l = TrGetDbListSpc(msg->req.objId); + l = TrGetDbListSpc(msg->req.objId); // 鑾峰彇涓庢寚瀹氳〃绌洪棿鐩稿叧鐨勬暟鎹簱鍒楄〃锛屽苟灏嗙粨鏋滆祴缁欏垪琛 l break; case PURGE_MSG_TYPE_RECYCLEBIN: - l = TrGetDbListRcy(); + l = TrGetDbListRcy(); // 鑾峰彇涓庡洖鏀剁珯鐩稿叧鐨勬暟鎹簱鍒楄〃锛屽苟灏嗙粨鏋滆祴缁欏垪琛 l break; case PURGE_MSG_TYPE_CAS_SCHEMA: - l = TrGetDbListSchema(msg->req.objId); + l = TrGetDbListSchema(msg->req.objId); // 鑾峰彇涓庢寚瀹氭ā寮忕浉鍏崇殑鏁版嵁搴撳垪琛紝骞跺皢缁撴灉璧嬬粰鍒楄〃 l break; case PURGE_MSG_TYPE_CAS_USER: - l = TrGetDbListUser(msg->req.objId); + l = TrGetDbListUser(msg->req.objId); // 鑾峰彇涓庢寚瀹氱敤鎴风浉鍏崇殑鏁版嵁搴撳垪琛紝骞跺皢缁撴灉璧嬬粰鍒楄〃 l break; case PURGE_MSG_TYPE_AUTO: - l = TrGetDbListAuto(); + l = TrGetDbListAuto(); // 鑾峰彇涓庤嚜鍔ㄦ竻鐞嗙浉鍏崇殑鏁版嵁搴撳垪琛紝骞跺皢缁撴灉璧嬬粰鍒楄〃 l break; default: elog(ERROR, "unknown purge message type: %d", msg->req.type); break; } - return l; + return l; // 杩斿洖鑾峰彇鍒扮殑鏁版嵁搴撳垪琛 l } +/* + *鍔熻兘锛氬畬鎴愭秷鎭殑娓呯悊杩囩▼锛屽苟璁剧疆娑堟伅鐨勬渶缁堢姸鎬 + * + * 鍙傛暟: + * id锛氳澶勭悊鐨勬秷鎭疘D + * + * 杩斿洖鍊:鏃 + */ static void RbCleanerPurgeFinal(uint64 id) { - int errCode = *(volatile int *)&RbMsg(id)->res.errCode; - + int errCode = *(volatile int *)&RbMsg(id)->res.errCode; // 鑾峰彇娑堟伅鐨勯敊璇唬鐮 + // 鏍规嵁 errCode 鏄惁琛ㄧず閿欒锛屽嚱鏁拌缃秷鎭殑鏈缁堢姸鎬 PurgeMsgStatus status = RbResIsError(errCode) ? PURGE_MSG_STATUS_ERROR : PURGE_MSG_STATUS_SUCCESS; - RbMsgSetStatus(id, status, true); + RbMsgSetStatus(id, status, true); // 璁剧疆娑堟伅鐨勭姸鎬 return; } +/* + *鍔熻兘锛氭鏌ユ秷鎭殑姝ラ缁撴灉鏄惁婊¤冻鏌愪簺鏉′欢 + * + * 鍙傛暟: + * id锛氳澶勭悊鐨勬秷鎭疘D + * + * 杩斿洖鍊: + * bool绫诲瀷锛屾弧瓒宠繑鍥瀟rue锛屽惁鍒欒繑鍥瀎alse + */ static bool RbMsgStepRes(uint64 id) { - PurgeMsg *rbMsg = RbMsg(id); + PurgeMsg *rbMsg = RbMsg(id); // 鑾峰彇娑堟伅瀵硅薄 PurgeMsgRes localRes; - Assert(id == rbMsg->id); + Assert(id == rbMsg->id); // 纭繚娑堟伅鐨処D鍜屾秷鎭璞$殑ID鐩稿尮閰 RbMsgGetRes(id, &localRes); + // 妫鏌 localRes.status 鏄惁涓 PURGE_MSG_STATUS_STEPDONE Assert(localRes.status == PURGE_MSG_STATUS_STEPDONE); + // 濡傛灉 localRes.errCode 琛ㄧず閿欒锛屾垨鑰 localRes.skippedNum 澶т簬 0 if (RbResIsError(localRes.errCode) || localRes.skippedNum > 0) { - return true; + return true; // 琛ㄧず娑堟伅闇瑕佽繘涓姝ュ鐞 } if (rbMsg->req.type == PURGE_MSG_TYPE_DML) { return localRes.purgedNum > 0; @@ -655,21 +1000,30 @@ static bool RbMsgStepRes(uint64 id) return localRes.skippedNum > 0; } +/* + *鍔熻兘锛氬鐞嗘潵鑷搷浣滅郴缁熸垨鍏朵粬缁勪欢鐨勪腑鏂拰淇″彿 + * + * 鍙傛暟: + * rc 鏄紶閫掔粰鍑芥暟鐨勪腑鏂爣蹇椾綅 + * id锛氳澶勭悊鐨勬秷鎭疘D + * + * 杩斿洖鍊:鏃 + */ static void RbCleanerProcInterrupts(int rc, uint64 id = RB_INVALID_MSGID) { /* Process sinval catchup interrupts that happened while sleeping */ - ProcessCatchupInterrupt(); + ProcessCatchupInterrupt(); // 澶勭悊 SINVAL涓柇 /* * Emergency bailout if postmaster has died. This is to avoid the * necessity for manual cleanup of all postmaster children. */ - if (((unsigned int)rc) & WL_POSTMASTER_DEATH) { + if (((unsigned int)rc) & WL_POSTMASTER_DEATH) { // 琛ㄧず postmaster 宸茬粡缁堟 proc_exit(1); } /* the normal shutdown case */ - if (t_thrd.rbcleaner_cxt.got_SIGTERM) { + if (t_thrd.rbcleaner_cxt.got_SIGTERM) { // 琛ㄧず rbcleaner 姝e湪鍏抽棴 elog(LOG, "rbcleaner is shutting down."); proc_exit(0); } @@ -677,12 +1031,13 @@ static void RbCleanerProcInterrupts(int rc, uint64 id = RB_INVALID_MSGID) /* * reload the postgresql.conf */ - if (t_thrd.rbcleaner_cxt.got_SIGHUP) { + if (t_thrd.rbcleaner_cxt.got_SIGHUP) { // 琛ㄧず鏀跺埌浜 SIGHUP 淇″彿 t_thrd.rbcleaner_cxt.got_SIGHUP = false; ProcessConfigFile(PGC_SIGHUP); } /* Process rbclt cancel message. */ + // 濡傛灉 id 涓嶇瓑浜 RB_INVALID_MSGID 骞朵笖娑堟伅琚彇娑 if ((id != RB_INVALID_MSGID && RbMsgCanceled(id))) { RbCancelRbworker(); ereport(ERROR, @@ -691,50 +1046,70 @@ static void RbCleanerProcInterrupts(int rc, uint64 id = RB_INVALID_MSGID) /* Process rbclt cancel message. */ if (t_thrd.int_cxt.QueryCancelPending) { - ProcessInterrupts(); + ProcessInterrupts(); // 澶勭悊涓柇 } } +/* + * 鍔熻兘锛氭鏌 rbworker 杩涚▼鏄惁鍦ㄤ竴瀹氭椂闂村唴鍚姩 + * + * 鍙傛暟: + * launchTime锛 rbworker 杩涚▼鍚姩鐨勬椂闂存埑 + * + * 杩斿洖鍊: + * bool绫诲瀷 + * 璁$畻褰撳墠鏃堕棿涓庡惎鍔ㄦ椂闂翠箣闂寸殑鏃堕棿宸紝濡傛灉鏃堕棿宸秴杩30绉掞紝鍑芥暟杩斿洖 true 琛ㄧず瓒呮椂 + */ static bool RbStartWorkerTimeout(TimestampTz launchTime) { /* The rbcleaner waits for a maximum of 30 seconds for the rbworker to start. */ return TimestampDifferenceExceeds(launchTime, GetCurrentTimestamp(), 30000); } +/* + * 鍔熻兘锛氭墽琛屾秷鎭殑娓呯悊杩囩▼ + * + * 鍙傛暟: + * id 锛氳澶勭悊鐨勬秷鎭殑 ID + * + * 杩斿洖鍊:鏃 + */ static void RbCleanerPurgeImpl(uint64 id) { List *l = NULL; ListCell *cell = NULL; const long int rbCleanerPurgeIntervalMs = 1000L; - RbCleanerProcInterrupts(0, id); + RbCleanerProcInterrupts(0, id); // 澶勭悊涓柇鍜屼俊鍙 - StartTransactionCommand(); - l = RbGetDbList(id); - foreach (cell, l) { + StartTransactionCommand(); // 寮濮嬩竴涓簨鍔 + l = RbGetDbList(id); // 鑾峰彇闇瑕佸鐞嗙殑鏁版嵁搴撳垪琛 + foreach (cell, l) { // 閬嶅巻姣忎釜鏁版嵁搴 RbWorkerInfo *workerInfo = NULL; TimestampTz launchTime; - + // 妫鏌ユ槸鍚﹀凡缁忓瓨鍦ㄦ椿鍔ㄧ殑 rbworker 杩涚▼ if (RbWorkerIsAlive()) { + // 濡傛灉瀛樺湪锛屽垯鎶涘嚭閿欒 elog(ERROR, "start rbworker failed: rbworker already exists!"); } - + // 鍒濆鍖 RbWorkerInfo 缁撴瀯浣 workerInfo = RbInitWorkerInfo(id, (char *)lfirst(cell)); + // 鍚姩 rbworker 杩涚▼ SendPostmasterSignal(PMSIGNAL_START_RB_WORKER); - launchTime = GetCurrentTimestamp(); - while (true) { + launchTime = GetCurrentTimestamp(); // 璁板綍 rbworker 杩涚▼鍚姩鐨勬椂闂存埑 + while (true) { // 寰幆绛夊緟 rbworker 杩涚▼鐨勫搷搴旓紝鏈闀跨瓑寰呮椂闂翠负1绉 int rc; /* Clear any already-pending wakeups */ - ResetLatch(&workerInfo->latch); + ResetLatch(&workerInfo->latch); // 娓呴櫎浠讳綍宸茬粡鎸傝捣鐨勭瓑寰咃紝纭繚浠庡ご寮濮嬬瓑寰 rbworker 鐨勫搷搴 /* Wait latch for a maximum of 1 sec for a rbworker response. */ rc = WaitLatch(&workerInfo->latch, WL_LATCH_SET | WL_TIMEOUT | WL_POSTMASTER_DEATH, rbCleanerPurgeIntervalMs); - RbCleanerProcInterrupts(rc, id); + RbCleanerProcInterrupts(rc, id); // 澶勭悊鍙兘鍙戠敓鐨勪腑鏂 /* * We raise an ERROR if rbworker not enter PURGE_MSG_STATUS_STEPIN as soon, @@ -746,87 +1121,111 @@ static void RbCleanerPurgeImpl(uint64 id) break; } - if (RbMsgStepDone(id)) { + if (RbMsgStepDone(id)) { // 濡傛灉rbworker 杩涚▼宸茬粡瀹屾垚浜嗘秷鎭殑澶勭悊 break; } } - if (RbMsgStepRes(id)) { - break; + if (RbMsgStepRes(id)) { // 濡傛灉娑堟伅鐨勫鐞嗙粨鏋滄弧瓒虫潯浠 + break; // 琛ㄧず闇瑕佽繘涓姝ュ鐞嗭紝閫鍑哄惊鐜 } } - list_free_deep(l); + list_free_deep(l); // 閲婃斁鏁版嵁搴撳垪琛ㄧ殑鍐呭瓨 l = NULL; - CommitTransactionCommand(); + CommitTransactionCommand(); // 鎻愪氦浜嬪姟 - RbCleanerPurgeFinal(id); + RbCleanerPurgeFinal(id); // 璁剧疆娑堟伅鐨勬渶缁堢姸鎬 } +/* + * 鍔熻兘锛氫粠闃熷垪涓彇鍑轰换鍔″苟鎵ц + * + * 鍙傛暟:鏃 + * + * 杩斿洖鍊:鏃 + */ static void RbCleanerPurge() { - PurgeMsgQueue *msqQue = RbGetQueue(); - while (!RbQueueIsEmpty(msqQue)) { - uint64 id = RbQueueFront(msqQue)->id; - PG_TRY(); + PurgeMsgQueue *msqQue = RbGetQueue(); // 鑾峰彇寰呭鐞嗙殑娑堟伅闃熷垪 + while (!RbQueueIsEmpty(msqQue)) { // 鎸佺画澶勭悊娑堟伅闃熷垪涓殑浠诲姟锛岀洿鍒伴槦鍒椾负绌 + uint64 id = RbQueueFront(msqQue)->id; // 浠庨槦鍒楀ご閮ㄥ彇鍑轰换鍔$殑鍞竴鏍囪瘑 + PG_TRY(); // 寮傚父澶勭悊鍧 { - RbCleanerPurgeImpl(id); + RbCleanerPurgeImpl(id); // 澶勭悊鍏蜂綋鐨勬竻鐞嗘搷浣 } PG_CATCH(); { + // 濡傛灉鍙戠敓寮傚父锛屾崟鑾峰紓甯稿悗灏嗕换鍔$殑鐘舵佽缃负閿欒 RbMsgSetStatusErr(id, PURGE_MSG_STATUS_ERROR, geterrcode(), Geterrmsg(), true); - RbQueuePop(msqQue); + RbQueuePop(msqQue); // 浠庨槦鍒椾腑绉婚櫎璇ヤ换鍔 PG_RE_THROW(); - } - PG_END_TRY(); - RbQueuePop(msqQue); + } + PG_END_TRY(); // 缁撴潫寮傚父澶勭悊鍧 + RbQueuePop(msqQue); // 浠庨槦鍒椾腑绉婚櫎璇ヤ换鍔 } } +/* + * 鍔熻兘锛氬悜闃熷垪涓坊鍔犳柊鐨勮嚜鍔ㄦ竻鐞嗕换鍔 + * + * 鍙傛暟:鏃 + * + * 杩斿洖鍊:鏃 + */ static void RbAutoPurge() { PurgeMsg prMsg; - + // 鍒濆鍖栦负鑷姩娓呯悊绫诲瀷鐨勬秷鎭 RbMsgInit(&prMsg, PURGE_MSG_TYPE_AUTO, InvalidOid, InvalidOid); - (void)RbCltSubmit(&prMsg, false); + (void)RbCltSubmit(&prMsg, false); // 灏嗚嚜鍔ㄦ竻鐞嗕换鍔℃彁浜ゅ埌娑堟伅闃熷垪涓紝浣嗕笉绛夊緟浠诲姟瀹屾垚 } +/* + * 鍔熻兘锛歳bcleaner 杩涚▼鐨勪富瑕佹墽琛屽嚱鏁 + * + * 鍙傛暟:鏃 + * + * 杩斿洖鍊:鏃 + */ NON_EXEC_STATIC void RbCleanerMain() { - sigjmp_buf localSigjmpBuf; + sigjmp_buf localSigjmpBuf; // 鐢ㄤ簬澶勭悊寮傚父璺宠浆 bool lastError = false; TimestampTz nextTimestamp; /* we are a postmaster subprocess now */ - IsUnderPostmaster = true; - t_thrd.role = RBCLEANER; + IsUnderPostmaster = true; // 琛ㄧず褰撳墠杩涚▼鏄湪 postmaster 杩涚▼涓嬭繍琛岀殑 + t_thrd.role = RBCLEANER; // 鏍囪瘑绾跨▼ /* tell datasender we update the values. */ - pg_memory_barrier(); + pg_memory_barrier();// 鎵ц鍐呭瓨灞忛殰鎿嶄綔锛岀敤浜庣‘淇濆墠闈㈢殑鍐欐搷浣滃鍏朵粬绾跨▼鍙 /* reset t_thrd.proc_cxt.MyProcPid */ - t_thrd.proc_cxt.MyProcPid = gs_thread_self(); + t_thrd.proc_cxt.MyProcPid = gs_thread_self(); // 姝g‘鏍囪瘑绾跨▼ /* record Start Time for logging */ - t_thrd.proc_cxt.MyStartTime = time(NULL); + t_thrd.proc_cxt.MyStartTime = time(NULL); // 璁板綍浜嗗綋鍓嶇嚎绋嬬殑鍚姩鏃堕棿 - t_thrd.proc_cxt.MyProgName = "RbCleaner"; + t_thrd.proc_cxt.MyProgName = "RbCleaner"; // 璁剧疆浜嗗綋鍓嶇嚎绋嬬殑绋嬪簭鍚嶇О /* Identify myself via ps */ - init_ps_display("rbcleaner process", "", "", ""); + init_ps_display("rbcleaner process", "", "", "");// 鍒濆鍖栬繘绋嬬姸鎬佹樉绀 /* save the pid & latch into share memory */ pg_atomic_write_u64(&t_thrd.rbcleaner_cxt.RbCleanerShmem->rbCleanerPid, t_thrd.proc_cxt.MyProcPid); t_thrd.rbcleaner_cxt.RbCleanerShmem->rbCleanerLatch = &t_thrd.proc->procLatch; ereport(LOG, (errmsg("rbcleaner started"))); - + // 妫鏌ユ槸鍚﹂厤缃簡 PostAuthDelay if (u_sess->attr.attr_security.PostAuthDelay) { + // 濡傛灉閰嶇疆浜嗗欢杩熸椂闂达紝閭d箞宸ヤ綔杩涚▼灏嗕紤鐪犵浉搴旂殑鏃堕棿 pg_usleep(u_sess->attr.attr_security.PostAuthDelay * 1000000L); } - SetProcessingMode(InitProcessing); - + SetProcessingMode(InitProcessing); // 璁剧疆澶勭悊妯″紡涓哄垵濮嬪寲澶勭悊妯″紡 + + // 璁剧疆淇″彿澶勭悊绋嬪簭 (void)gspqsignal(SIGHUP, RbSighupHandler); (void)gspqsignal(SIGINT, RbSigintHandler); /* Cancel signal */ (void)gspqsignal(SIGTERM, RbSigtermHander); @@ -849,95 +1248,107 @@ NON_EXEC_STATIC void RbCleanerMain() BaseInit(); #ifndef EXEC_BACKEND + // 涓嶅湪鎵ц鍚庡彴鎯呭喌涓嬶紝鍒涘缓浜嗕竴涓 PGPROC 缁撴瀯浣擄紝骞跺鍏惰繘琛屽垵濮嬪寲 InitProcess(); #endif on_proc_exit(RbCleanerQuitAndClean, 0); - + // 璁剧疆褰撳墠杩涚▼鐨勬暟鎹簱鍜岀敤鎴蜂俊鎭 t_thrd.proc_cxt.PostInit->SetDatabaseAndUser((char*)pstrdup(DEFAULT_DATABASE), InvalidOid, NULL); t_thrd.proc_cxt.PostInit->InitRbCleaner(); + // 璁剧疆褰撳墠杩涚▼鐨勫鐞嗘ā寮忎负 "NormalProcessing"锛岃〃绀烘甯哥殑澶勭悊妯″紡 SetProcessingMode(NormalProcessing); - + // 鍒涘缓涓涓唴瀛樹笂涓嬫枃 MemoryContext workMxt = AllocSetContextCreate( t_thrd.top_mem_cxt, "RbCleaner", ALLOCSET_DEFAULT_INITSIZE, ALLOCSET_DEFAULT_INITSIZE, ALLOCSET_DEFAULT_MAXSIZE); - (void)MemoryContextSwitchTo(workMxt); + (void)MemoryContextSwitchTo(workMxt); // 鍒囨崲鍒拌涓婁笅鏂 + // 澶勭悊寮傚父鎯呭喌 int curTryCounter = 0; int* oldTryCounter = NULL; if (sigsetjmp(localSigjmpBuf, 1) != 0) { + // 鍏抽棴鎵鏈夋墦寮鐨勬枃浠 gstrace_tryblock_exit(true, oldTryCounter); /* Since not using PG_TRY, must reset error stack by hand */ - t_thrd.log_cxt.error_context_stack = NULL; + t_thrd.log_cxt.error_context_stack = NULL; // 鎵嬪姩閲嶇疆閿欒鍫嗘爤 - t_thrd.log_cxt.call_stack = NULL; + t_thrd.log_cxt.call_stack = NULL; // 娓呯┖璋冪敤鏍 /* Prevent interrupts while cleaning up */ - HOLD_INTERRUPTS(); + HOLD_INTERRUPTS(); // 鍦ㄦ墽琛屾竻鐞嗘搷浣滄湡闂寸姝腑鏂 /* Forget any pending QueryCancel request */ - t_thrd.int_cxt.QueryCancelPending = false; - (void)disable_sig_alarm(true); + t_thrd.int_cxt.QueryCancelPending = false; // 琛ㄧず鍙栨秷璇锋眰涓嶅啀鎸傝捣 + (void)disable_sig_alarm(true); // 绂佺敤淇″彿闂归挓锛岀‘淇濅笉浼氬湪閿欒澶勭悊鏈熼棿瑙﹀彂瓒呮椂淇″彿 t_thrd.int_cxt.QueryCancelPending = false; /* Report the error to the server log */ - EmitErrorReport(); + EmitErrorReport(); // 鎶ュ憡閿欒鍒版湇鍔″櫒鏃ュ織 /* * Abort the current transaction in order to recover. */ + // 涓褰撳墠浜嬪姟浠ヨ繘琛屾仮澶嶏紝浠讳綍鏈彁浜ょ殑鏇存敼灏嗚鍥炴粴锛屼互纭繚鏁版嵁搴撶殑涓鑷存 AbortCurrentTransaction(); /* release resource held by lsc */ - AtEOXact_SysDBCache(false); + AtEOXact_SysDBCache(false); // 閲婃斁鐢辩郴缁熸暟鎹簱缂撳瓨鎸佹湁鐨勮祫婧 - LWLockReleaseAll(); + LWLockReleaseAll(); // 閲婃斁閿 /* * Now return to normal top-level context and clear ErrorContext for * next time. */ - (void)MemoryContextSwitchTo(workMxt); + (void)MemoryContextSwitchTo(workMxt); // 鍒囨崲绋嬪簭鐨勫唴瀛樹笂涓嬫枃 + // 娓呴櫎閿欒鐘舵侊紝灏嗕箣鍓嶅彲鑳借褰曠殑閿欒淇℃伅鍜岀姸鎬侀噸缃负绌 FlushErrorState(); /* Flush any leaked data in the top-level context */ + // 閲嶇疆骞跺垹闄や簡涔嬪墠鍒涘缓鐨勫唴瀛樹笂涓嬫枃 workMxt 鍙婂叾鎵鏈夊瓙涓婁笅鏂 + // 纭繚鍦ㄥ紓甯稿鐞嗗畬鎴愬悗閲婃斁宸插垎閰嶇殑鍐呭瓨锛屼互閬垮厤鍐呭瓨娉勬紡 MemoryContextResetAndDeleteChildren(workMxt); /* Now we can allow interrupts again */ - RESUME_INTERRUPTS(); + RESUME_INTERRUPTS(); // 鍏佽涓柇淇″彿鍐嶆琚崟鑾 /* if in shutdown mode, no need for anything further; just go away */ if (t_thrd.rbcleaner_cxt.got_SIGTERM) { goto shutdown; } - lastError = true; + lastError = true; // 琛ㄧず涓婁竴娆℃墽琛岀殑鎿嶄綔鍑虹幇浜嗛敊璇 } - + // 璁板綍褰撳墠鐨勯敊璇鐞嗗爢鏍堣鏁板櫒 oldTryCounter = gstrace_tryblock_entry(&curTryCounter); /* We can now handle ereport(ERROR) */ + // 灏嗛敊璇鐞嗙殑璺宠浆缂撳啿鍖鸿缃负褰撳墠绾跨▼鐨勯敊璇鐞嗗爢鏍 t_thrd.log_cxt.PG_exception_stack = &localSigjmpBuf; /* * Unblock signals (they were blocked when the postmaster forked us) */ + // 瑙i櫎淇″彿灞忚斀锛屽厑璁镐俊鍙峰啀娆¤鎹曡幏 gs_signal_setmask(&t_thrd.libpq_cxt.UnBlockSig, NULL); + // 瑙i櫎瀵 SIGUSR2 淇″彿鐨勫睆钄斤紝鍏佽鎺ユ敹 SIGUSR2 淇″彿 (void)gs_signal_unblock_sigusr2(); nextTimestamp = GetCurrentTimestamp() + USECS_PER_MINUTE; /* loop until shutdown request */ + // 寰幆鐩村埌鏀跺埌浜嗗叧闂姹傛垨Tcap 鐗堟湰涓嶅啀鍙敤 while (!t_thrd.rbcleaner_cxt.got_SIGTERM && ENABLE_TCAP_RECYCLEBIN) { int rc; /* Clear any already-pending wakeups */ - ResetLatch(&t_thrd.proc->procLatch); + ResetLatch(&t_thrd.proc->procLatch); // 娓呴櫎浠讳綍宸茬粡鎸傝捣鐨勭瓑寰 /* * Wait until 3s naptime expires or we get some type of signal (all the @@ -946,29 +1357,36 @@ NON_EXEC_STATIC void RbCleanerMain() * Note: If an error occurred during the last message processing, we will * wait less time 10ms to continue the next process message quickly. */ + + // 绛夊緟淇″彿鎴栬秴鏃 绛夊緟浠ヤ笅鏉′欢涔嬩竴鍙戠敓锛 + // 鏀跺埌浜 WL_LATCH_SET 淇″彿锛岃〃绀虹瓑寰呮爣蹇楀凡缁忚璁剧疆銆 + // 鏀跺埌浜 WL_TIMEOUT 淇″彿锛岃〃绀虹粡杩囦簡涓娈垫椂闂达紙鐢 SNAP_CAPTURE_INTERVAL 鎺у埗锛夈 + // 鏀跺埌浜 WL_POSTMASTER_DEATH 淇″彿锛岃〃绀 postmaster 杩涚▼宸茬粡閫鍑恒 rc = WaitLatch(&t_thrd.proc->procLatch, WL_LATCH_SET | WL_TIMEOUT | WL_POSTMASTER_DEATH, lastError ? RBCLEANER_INTERVAL_QUICK_MS : RBCLEANER_INTERVAL_MS); lastError = false; - + // 澶勭悊涓嶅悓鐨勪腑鏂儏鍐碉紝鏍规嵁浼犲叆鐨勮繑鍥炵爜 rc 鎵ц鐩稿簲鐨勬搷浣 RbCleanerProcInterrupts(rc); - if (TcapFeatureAvail()) { + if (TcapFeatureAvail()) { // 妫鏌ユ槸鍚︽敮鎸 TcapFeature /* Do the hard work. */ - RbCleanerPurge(); + RbCleanerPurge(); // 鎵ц瀹為檯娓呯悊宸ヤ綔 /* Do auto purge. */ - TimestampTz now = GetCurrentTimestamp(); + TimestampTz now = GetCurrentTimestamp(); // 鑾峰彇褰撳墠鐨勬椂闂存埑 + // 妫鏌ュ綋鍓嶆椂闂存槸鍚︽弧瓒虫煇浜涙潯浠讹紝鎺у埗鑷姩娓呯悊鐨勯鐜 if (now >= nextTimestamp || now + USECS_PER_MINUTE < nextTimestamp) { - nextTimestamp = now + USECS_PER_MINUTE; - RbAutoPurge(); + nextTimestamp = now + USECS_PER_MINUTE; // 鏇存柊鏃堕棿鎴 + RbAutoPurge(); // 鎵ц鑷姩娓呯悊浠诲姟 } } - + // 閲嶇疆骞跺垹闄や簡涔嬪墠鍒涘缓鐨勫唴瀛樹笂涓嬫枃 workMxt 鍙婂叾鎵鏈夊瓙涓婁笅鏂 MemoryContextResetAndDeleteChildren(workMxt); } shutdown: + // 璁板綍涓鏉¤皟璇曠骇鍒殑鏃ュ織娑堟伅锛屾寚绀 rbcleaner 杩涚▼姝e湪鍏抽棴 elog(LOG, "rbcleaner is shutting down."); proc_exit(0); @@ -978,90 +1396,138 @@ shutdown: * Recyclebin Cleaner WorkerMain Code ********************************************************************/ +/* + * 鍔熻兘锛氬垽鏂綋鍓嶈繘绋嬫槸鍚︽槸 Recyclebin Cleaner Worker 杩涚▼ + * + * 鍙傛暟:鏃 + * + * 杩斿洖鍊: + * bool绫诲瀷 + * 閫氳繃妫鏌 t_thrd.role 鐨勫兼潵纭畾杩涚▼鐨勮鑹叉槸鍚︿负 RBWORKER + * 濡傛灉鏄紝鍒欒繑鍥 true锛岃〃绀哄綋鍓嶈繘绋嬫槸 Worker 杩涚▼锛屽惁鍒欒繑鍥 false + */ bool IsRbWorkerProcess(void) { return t_thrd.role == RBWORKER; } +/* + * 鍔熻兘锛歋IGQUIT 淇″彿澶勭悊鍑芥暟 + * + * 鍙傛暟: + * SIGNAL_ARGS: 淇″彿澶勭悊绋嬪簭鐨勫弬鏁板垪琛紝鎻愪緵鍏充簬瑙﹀彂淇″彿鐨勪笂涓嬫枃淇℃伅 + * + * 杩斿洖鍊:鏃 + */ static void RbWorkerSigquitHandler(SIGNAL_ARGS) { + // 灏 SIGQUIT 娣诲姞鍒伴樆姝㈢殑淇″彿闆嗭紝浠ラ槻姝㈠祵濂楄皟鐢 sigaddset(&t_thrd.libpq_cxt.BlockSig, SIGQUIT); /* prevent nested calls */ gs_signal_setmask(&t_thrd.libpq_cxt.BlockSig, NULL); - on_exit_reset(); + on_exit_reset(); // 娓呴櫎浠讳綍宸叉敞鍐岀殑閫鍑哄洖璋 - gs_thread_exit(2); + gs_thread_exit(2); // 閫鍑 - elog(LOG, "rbworker signaled: SIGQUIT"); + elog(LOG, "rbworker signaled: SIGQUIT"); // 璁板綍涓鏉℃秷鎭紝鎸囩ず宸ヤ綔鑰呰繘绋嬫帴鏀跺埌 SIGQUIT 淇″彿 } +/* + * 鍔熻兘锛氬湪宸ヤ綔鑰呰繘绋嬮鍑烘椂鎵ц娓呯悊鎿嶄綔 + * + * 鍙傛暟: + * code锛氶鍑轰唬鐮 + * arg锛氭湭浣跨敤鐨勫弬鏁 + * + * 杩斿洖鍊:鏃 + */ static void RbWorkerQuitAndClean(int code, Datum arg) { - RbWorkerInfo *workerInfo = RbGetWorkerInfo(); + RbWorkerInfo *workerInfo = RbGetWorkerInfo(); // 鑾峰彇宸ヤ綔鑰呰繘绋嬬殑 RbWorkerInfo 缁撴瀯 + // 鏈夋晥鍦版爣璁颁簡宸ヤ綔鑰呰繘绋嬩笉鍐嶅浜庢椿鍔ㄧ姸鎬佹垨姝e湪杩愯 pg_atomic_write_u64(&workerInfo->rbworkerPid, 0); } +/* + * 鍔熻兘锛氭牴鎹彁渚涚殑娑堟伅 ID (id) 鎵ц瀹為檯鐨勬竻鐞嗕换鍔 + * + * 鍙傛暟: + * id锛氭秷鎭殑鍞竴鏍囪瘑绗 + * + * 杩斿洖鍊:鏃 + */ static void RbWorkerPurge(int64 id) { - PurgeMsgType type = RbMsg(id)->req.type; + PurgeMsgType type = RbMsg(id)->req.type; // 鑾峰彇娑堟伅绫诲瀷 + // 鏍规嵁娑堟伅绫诲瀷鎵ц涓嶅悓鐨勬竻鐞嗘搷浣 switch (type) { case PURGE_MSG_TYPE_DML: - TrPurgeTablespaceDML(id); + TrPurgeTablespaceDML(id); // 鎵ц娓呯悊琛ㄧ┖闂寸殑鎿嶄綔 break; case PURGE_MSG_TYPE_TABLESPACE: case PURGE_MSG_TYPE_CAS_TABLESPACE: - TrPurgeTablespace(id); + TrPurgeTablespace(id); // 鎵ц鐩稿簲鐨勮〃绌洪棿娓呯悊鎿嶄綔 break; case PURGE_MSG_TYPE_RECYCLEBIN: - TrPurgeRecyclebin(id); + TrPurgeRecyclebin(id); // 鎵ц鍥炴敹绔欐竻鐞嗘搷浣 break; case PURGE_MSG_TYPE_CAS_SCHEMA: - TrPurgeSchema(id); + TrPurgeSchema(id); // 鎵ц妯″紡娓呯悊 break; case PURGE_MSG_TYPE_CAS_USER: - TrPurgeUser(id); + TrPurgeUser(id); // 鎵ц鐢ㄦ埛娓呯悊鎿嶄綔 break; case PURGE_MSG_TYPE_AUTO: - TrPurgeAuto(id); + TrPurgeAuto(id); // 鎵ц鑷姩娓呯悊鎿嶄綔 break; default: elog(ERROR, "unknown purge message type: %d", type); break; } - + // 璁剧疆娑堟伅鐨勭姸鎬侊紝琛ㄧず娓呯悊鎿嶄綔宸插畬鎴 RbMsgSetStatus(id, PURGE_MSG_STATUS_STEPDONE, false); + // 璁剧疆浜嗗伐浣滆呰繘绋嬬殑Latch锛屼互閫氱煡涓绘竻鐞嗚繘绋嬶紙鍥炴敹绔欐竻鐞嗗櫒锛夊凡瀹屾垚娓呯悊浠诲姟 SetLatch(&t_thrd.rbcleaner_cxt.RbCleanerShmem->workerInfo.latch); } +/* + * 鍔熻兘锛歳bcleaner 杩涚▼鐨勪富瑕佹墽琛屽嚱鏁 + * + * 鍙傛暟:鏃 + * + * 杩斿洖鍊:鏃 + */ NON_EXEC_STATIC void RbWorkerMain() { - sigjmp_buf localSigjmpBuf; - RbWorkerInfo *workInfo = RbGetWorkerInfo(); + sigjmp_buf localSigjmpBuf; // 鐢ㄤ簬澶勭悊寮傚父璺宠浆 + RbWorkerInfo *workInfo = RbGetWorkerInfo(); // 鑾峰彇宸ヤ綔鑰呰繘绋嬬殑淇℃伅 + // 浣跨敤鍘熷瓙鎿嶄綔灏嗗綋鍓嶈繘绋嬬殑杩涚▼ID锛圥ID锛夊啓鍏ュ伐浣滆呰繘绋嬩俊鎭腑鐨 rbworkerPid 瀛楁 pg_atomic_write_u64(&workInfo->rbworkerPid, t_thrd.proc_cxt.MyProcPid); /* we are a postmaster subprocess now */ - IsUnderPostmaster = true; - t_thrd.role = RBWORKER; + IsUnderPostmaster = true; // 琛ㄧず褰撳墠杩涚▼鏄湪 postmaster 杩涚▼涓嬭繍琛岀殑 + t_thrd.role = RBWORKER; // 鏍囪瘑绾跨▼ /* tell datasender we update the values. */ - pg_memory_barrier(); + pg_memory_barrier();// 鎵ц鍐呭瓨灞忛殰鎿嶄綔锛岀敤浜庣‘淇濆墠闈㈢殑鍐欐搷浣滃鍏朵粬绾跨▼鍙 /* reset t_thrd.proc_cxt.MyProcPid */ - t_thrd.proc_cxt.MyProcPid = gs_thread_self(); + t_thrd.proc_cxt.MyProcPid = gs_thread_self(); // 姝g‘鏍囪瘑绾跨▼ /* record Start Time for logging */ - t_thrd.proc_cxt.MyStartTime = time(NULL); + t_thrd.proc_cxt.MyStartTime = time(NULL); // 璁板綍浜嗗綋鍓嶇嚎绋嬬殑鍚姩鏃堕棿 - t_thrd.proc_cxt.MyProgName = "RbWorker"; + t_thrd.proc_cxt.MyProgName = "RbWorker"; // 璁剧疆浜嗗綋鍓嶇嚎绋嬬殑绋嬪簭鍚嶇О /* Identify myself via ps */ - init_ps_display("rbworker process", "", "", ""); + init_ps_display("rbworker process", "", "", ""); // 鍒濆鍖栬繘绋嬬姸鎬佹樉绀 ereport(DEBUG1, (errmsg("rbworker started"))); - SetProcessingMode(InitProcessing); + SetProcessingMode(InitProcessing); // 璁剧疆澶勭悊妯″紡涓哄垵濮嬪寲澶勭悊妯″紡 + // 璁剧疆淇″彿澶勭悊绋嬪簭 (void)gspqsignal(SIGHUP, SIG_IGN); (void)gspqsignal(SIGINT, StatementCancelHandler); (void)gspqsignal(SIGTERM, die); @@ -1084,100 +1550,113 @@ NON_EXEC_STATIC void RbWorkerMain() BaseInit(); #ifndef EXEC_BACKEND + // 涓嶅湪鎵ц鍚庡彴鎯呭喌涓嬶紝鍒涘缓浜嗕竴涓 PGPROC 缁撴瀯浣擄紝骞跺鍏惰繘琛屽垵濮嬪寲 InitProcess(); #endif - on_proc_exit(RbWorkerQuitAndClean, 0); - + on_proc_exit(RbWorkerQuitAndClean, 0); // 娉ㄥ唽涓涓繘绋嬮鍑烘椂鐨勫洖璋冨嚱鏁 + // 璁剧疆褰撳墠杩涚▼鐨勬暟鎹簱鍜岀敤鎴蜂俊鎭 t_thrd.proc_cxt.PostInit->SetDatabaseAndUser((char*)pstrdup(NameStr(workInfo->dbName)), InvalidOid, NULL); t_thrd.proc_cxt.PostInit->InitRbWorker(); - + // 璁剧疆褰撳墠杩涚▼鐨勫鐞嗘ā寮忎负 "NormalProcessing"锛岃〃绀烘甯哥殑澶勭悊妯″紡 SetProcessingMode(NormalProcessing); - + // 鍒涘缓涓涓唴瀛樹笂涓嬫枃 MemoryContext workMxt = AllocSetContextCreate( t_thrd.top_mem_cxt, "RbWorker", ALLOCSET_DEFAULT_INITSIZE, ALLOCSET_DEFAULT_INITSIZE, ALLOCSET_DEFAULT_MAXSIZE); - (void)MemoryContextSwitchTo(workMxt); - + (void)MemoryContextSwitchTo(workMxt); // 鍒囨崲鍒拌涓婁笅鏂 + // 澶勭悊寮傚父鎯呭喌 int curTryCounter; int* oldTryCounter = NULL; if (sigsetjmp(localSigjmpBuf, 1) != 0) { + // 鍏抽棴鎵鏈夋墦寮鐨勬枃浠 gstrace_tryblock_exit(true, oldTryCounter); /* Since not using PG_TRY, must reset error stack by hand */ - t_thrd.log_cxt.error_context_stack = NULL; + t_thrd.log_cxt.error_context_stack = NULL; // 鎵嬪姩閲嶇疆閿欒鍫嗘爤 - t_thrd.log_cxt.call_stack = NULL; + t_thrd.log_cxt.call_stack = NULL; // 娓呯┖璋冪敤鏍 /* Prevent interrupts while cleaning up */ - HOLD_INTERRUPTS(); + HOLD_INTERRUPTS(); // 鍦ㄦ墽琛屾竻鐞嗘搷浣滄湡闂寸姝腑鏂 /* Forget any pending QueryCancel request */ - t_thrd.int_cxt.QueryCancelPending = false; - (void)disable_sig_alarm(true); + t_thrd.int_cxt.QueryCancelPending = false; // 琛ㄧず鍙栨秷璇锋眰涓嶅啀鎸傝捣 + (void)disable_sig_alarm(true); // 绂佺敤淇″彿闂归挓锛岀‘淇濅笉浼氬湪閿欒澶勭悊鏈熼棿瑙﹀彂瓒呮椂淇″彿 t_thrd.int_cxt.QueryCancelPending = false; /* Report the error to the server log */ - EmitErrorReport(); + EmitErrorReport(); // 鎶ュ憡閿欒鍒版湇鍔″櫒鏃ュ織 /* Report the error to rbcleaner */ + // 璁剧疆娑堟伅鐨勯敊璇姸鎬侊紝灏嗛敊璇俊鎭缃负娑堟伅鐨勭姸鎬侊紝鐢ㄤ簬閫氱煡涓绘竻鐞嗚繘绋 RbMsgSetStatusErr(workInfo->id, PURGE_MSG_STATUS_STEPDONE, geterrcode(), Geterrmsg()); + // 璁剧疆宸ヤ綔鑰呰繘绋嬬殑Latch锛屼互閫氱煡涓绘竻鐞嗚繘绋嬫秷鎭凡澶勭悊瀹屾瘯 SetLatch(&t_thrd.rbcleaner_cxt.RbCleanerShmem->workerInfo.latch); /* * Abort the current transaction in order to recover. */ + // 涓褰撳墠浜嬪姟浠ヨ繘琛屾仮澶嶏紝浠讳綍鏈彁浜ょ殑鏇存敼灏嗚鍥炴粴锛屼互纭繚鏁版嵁搴撶殑涓鑷存 AbortCurrentTransaction(); /* release resource held by lsc */ - AtEOXact_SysDBCache(false); + AtEOXact_SysDBCache(false); // 閲婃斁鐢辩郴缁熸暟鎹簱缂撳瓨鎸佹湁鐨勮祫婧 - LWLockReleaseAll(); + LWLockReleaseAll(); // 閲婃斁閿 /* * Now return to normal top-level context and clear ErrorContext for * next time. */ - (void)MemoryContextSwitchTo(workMxt); + (void)MemoryContextSwitchTo(workMxt); // 鍒囨崲绋嬪簭鐨勫唴瀛樹笂涓嬫枃 + // 娓呴櫎閿欒鐘舵侊紝灏嗕箣鍓嶅彲鑳借褰曠殑閿欒淇℃伅鍜岀姸鎬侀噸缃负绌 FlushErrorState(); /* Flush any leaked data in the top-level context */ + // 閲嶇疆骞跺垹闄や簡涔嬪墠鍒涘缓鐨勫唴瀛樹笂涓嬫枃 workMxt 鍙婂叾鎵鏈夊瓙涓婁笅鏂 + // 纭繚鍦ㄥ紓甯稿鐞嗗畬鎴愬悗閲婃斁宸插垎閰嶇殑鍐呭瓨锛屼互閬垮厤鍐呭瓨娉勬紡 MemoryContextResetAndDeleteChildren(workMxt); /* Now we can allow interrupts again */ - RESUME_INTERRUPTS(); + RESUME_INTERRUPTS(); // 鍏佽涓柇淇″彿鍐嶆琚崟鑾 /* just go away */ goto shutdown; } RbMsgSetStatus(workInfo->id, PURGE_MSG_STATUS_STEPIN); - + // 璁板綍褰撳墠鐨勯敊璇鐞嗗爢鏍堣鏁板櫒 oldTryCounter = gstrace_tryblock_entry(&curTryCounter); /* We can now handle ereport(ERROR) */ + // 灏嗛敊璇鐞嗙殑璺宠浆缂撳啿鍖鸿缃负褰撳墠绾跨▼鐨勯敊璇鐞嗗爢鏍 t_thrd.log_cxt.PG_exception_stack = &localSigjmpBuf; /* * Unblock signals (they were blocked when the postmaster forked us) */ + // 瑙i櫎淇″彿灞忚斀锛屽厑璁镐俊鍙峰啀娆¤鎹曡幏 gs_signal_setmask(&t_thrd.libpq_cxt.UnBlockSig, NULL); + // 瑙i櫎瀵 SIGUSR2 淇″彿鐨勫睆钄斤紝鍏佽鎺ユ敹 SIGUSR2 淇″彿 (void)gs_signal_unblock_sigusr2(); /* Set lockwait_timeout/update_lockwait_timeout to 30s avoid unexpected suspend. */ + // 璁剧疆閰嶇疆閫夐」锛屽皢閿佺瓑寰呰秴鏃舵椂闂磋缃负 30 绉掞紝浠ラ伩鍏嶆剰澶栫殑鎸傝捣 SetConfigOption("lockwait_timeout", "30s", PGC_SUSET, PGC_S_OVERRIDE); SetConfigOption("update_lockwait_timeout", "30s", PGC_SUSET, PGC_S_OVERRIDE); /* Do the hard work */ RbWorkerPurge(workInfo->id); - + // 閲嶇疆骞跺垹闄や簡涔嬪墠鍒涘缓鐨勫唴瀛樹笂涓嬫枃 workMxt 鍙婂叾鎵鏈夊瓙涓婁笅鏂 MemoryContextResetAndDeleteChildren(workMxt); shutdown: + // 璁板綍涓鏉¤皟璇曠骇鍒殑鏃ュ織娑堟伅锛屾寚绀 rbworker 杩涚▼姝e湪鍏抽棴 elog(DEBUG1, "rbworker is shutting down."); proc_exit(0); diff --git a/src/gausskernel/process/postmaster/snapcapturer.cpp b/src/gausskernel/process/postmaster/snapcapturer.cpp index 9f46cbf60..b33293f1c 100644 --- a/src/gausskernel/process/postmaster/snapcapturer.cpp +++ b/src/gausskernel/process/postmaster/snapcapturer.cpp @@ -68,6 +68,14 @@ static const int SNAP_CAPTURE_INTERVAL = 3; * TxnSnapCapShmemSize * Size of TxnSnapCapturer related shared memory */ + +/* + * 鍔熻兘锛氳绠楀苟杩斿洖涓嶵xnSnapCapturer缁勪欢鐩稿叧鐨勫叡浜唴瀛樺ぇ灏 + * + * 鍙傛暟锛氭棤 + * + * 杩斿洖鍊硷細杩斿洖涓嶵xnSnapCapturer缁勪欢鐩稿叧鐨勫叡浜唴瀛樺ぇ灏 + */ Size TxnSnapCapShmemSize() { return sizeof(TxnSnapCapShmemStruct); @@ -77,19 +85,28 @@ Size TxnSnapCapShmemSize() * TxnSnapCapShmemInit * Allocate and initialize TxnSnapCapturer -related shared memory */ + +/* + * 鍔熻兘锛氬垵濮嬪寲涓嶵xnSnapCapturer缁勪欢鐩稿叧鐨勫叡浜唴瀛 + * + * 鍙傛暟锛氭棤 + * + * 杩斿洖鍊硷細鏃 + */ void TxnSnapCapShmemInit(void) { bool found = false; - + // 妫鏌ュ悕涓 "TxnSnapCapturer Data" 鐨勫叡浜唴瀛樻槸鍚﹀凡瀛樺湪銆傚鏋滃瓨鍦紝鍒欏皢 found 鍙橀噺璁剧疆涓 true t_thrd.snapcapturer_cxt.snapCapShmem = (TxnSnapCapShmemStruct *)ShmemInitStruct("TxnSnapCapturer Data", sizeof(TxnSnapCapShmemStruct), &found); - if (!found) { + if (!found) { // 濡傛灉鍏变韩鍐呭瓨涓嶅瓨鍦 /* * First time through, so initialize. Note that we zero the whole * requests array; this is so that CompactCheckpointerRequestQueue * can assume that any pad bytes in the request structs are zeroes. */ + // 鍒濆鍖栧叡浜唴瀛 errno_t ret = memset_s(t_thrd.snapcapturer_cxt.snapCapShmem, sizeof(TxnSnapCapShmemStruct), 0, sizeof(TxnSnapCapShmemStruct)); securec_check(ret, "\0", "\0"); @@ -103,181 +120,312 @@ void TxnSnapCapShmemInit(void) */ /* SIGHUP: set flag to re-read config file at next convenient time */ + +/* + *鍔熻兘锛氬鐞 SIGHUP 淇″彿锛岀敤浜庨噸鏂拌鍙栭厤缃枃浠 + * + * 鍙傛暟: + * SIGNAL_ARGS: 淇″彿澶勭悊绋嬪簭鐨勫弬鏁板垪琛紝鎻愪緵鍏充簬瑙﹀彂淇″彿鐨勪笂涓嬫枃淇℃伅 + * + * 杩斿洖鍊: + * 鏃 + */ static void TxnSnapSighupHandler(SIGNAL_ARGS) { - int saveErrno = errno; + int saveErrno = errno; // 淇濆瓨褰撳墠鐨勯敊璇爜 - t_thrd.snapcapturer_cxt.got_SIGHUP = true; + t_thrd.snapcapturer_cxt.got_SIGHUP = true; // 琛ㄧず鎺ユ敹鍒 SIGHUP 淇″彿 - if (t_thrd.proc) - SetLatch(&t_thrd.proc->procLatch); + if (t_thrd.proc) // 濡傛灉瀛樺湪杩涚▼ + SetLatch(&t_thrd.proc->procLatch); // 璁剧疆璇ヨ繘绋嬬殑杩涚▼latch - errno = saveErrno; + errno = saveErrno; // 鎭㈠涔嬪墠淇濆瓨鐨勯敊璇爜 } +/* + *鍔熻兘锛氬惎鍔ㄤ簨鍔″揩鐓ф崟鑾峰櫒绾跨▼骞惰繑鍥炵嚎绋嬬殑鏍囪瘑绗 + * + * 鍙傛暟:鏃 + * + * 杩斿洖鍊: + * 杩斿洖绾跨▼鐨勬爣璇嗙 ThreadId + */ ThreadId StartTxnSnapCapturer(void) { - if (!IsPostmasterEnvironment) { + if (!IsPostmasterEnvironment) { // 妫鏌ユ槸鍚﹀浜嶱ostmaster鐜 return 0; } - - if (canAcceptConnections(false) == CAC_OK) { + // 妫鏌ュ綋鍓嶆槸鍚﹀彲浠ユ帴鍙楁暟鎹簱杩炴帴 (鍙鏌ユ槸鍚﹀彲浠ユ帴鍙楄繛鎺ワ紝鑰屼笉瀹為檯鎺ュ彈杩炴帴) + if (canAcceptConnections(false) == CAC_OK) { + // 濡傛灉鍙互鎺ュ彈杩炴帴锛岃繑鍥炰竴涓〃绀烘柊绾跨▼鐨 ThreadId return initialize_util_thread(TXNSNAP_CAPTURER); } - + // 鐢熸垚涓涓狶OG娑堟伅绾у埆鐨勬棩蹇楁秷鎭紝琛ㄧず涓嶅噯澶囧惎鍔ㄥ揩鐓ф崟鑾峰櫒 ereport(LOG, (errmsg("not ready to start snapshot capturer."))); return 0; } +/* + *鍔熻兘锛氭鏌ュ綋鍓嶈繘绋嬫槸鍚︿负浜嬪姟蹇収鎹曡幏鍣ㄨ繘绋 + * + * 鍙傛暟:鏃 + * + * 杩斿洖鍊: + * bool绫诲瀷锛屾槸鍒欒繑鍥瀟rue锛岃〃绀哄綋鍓嶈繘绋嬫槸浜嬪姟蹇収鎹曡幏鍣ㄨ繘绋嬶紱鍚﹀垯杩斿洖true + */ bool IsTxnSnapCapturerProcess(void) { + // 姣旇緝鍏ㄥ眬鍙橀噺 t_thrd.role 鐨勫间笌 TXNSNAP_CAPTURER 甯搁噺鏉ョ‘瀹氬綋鍓嶈繘绋嬬殑瑙掕壊 return t_thrd.role == TXNSNAP_CAPTURER; } +/* + *鍔熻兘锛氭鏌ュ綋鍓嶈繘绋嬫槸鍚︿负浜嬪姟蹇収宸ヤ綔杩涚▼ + * + * 鍙傛暟:鏃 + * + * 杩斿洖鍊: + * 鏄垯杩斿洖 true锛岃〃绀哄綋鍓嶈繘绋嬫槸浜嬪姟蹇収宸ヤ綔杩涚▼锛屽惁鍒欒繑鍥 false + */ bool IsTxnSnapWorkerProcess(void) { + // 閫氳繃姣旇緝鍏ㄥ眬鍙橀噺 t_thrd.role 鐨勫间笌 TXNSNAP_WORKER 甯搁噺鏉ョ‘瀹氬綋鍓嶈繘绋嬬殑瑙掕壊 return t_thrd.role == TXNSNAP_WORKER; } +/* + *鍔熻兘锛氫粠鏂囨湰涓В鏋愬嚭涓涓 GTM_Timeline 鍊 + * + * 鍙傛暟: + * prefix锛氳鍖归厤鐨勫墠缂瀛楃涓 + * s锛氭寚鍚戣緭鍏ユ枃鏈殑鎸囬拡 + * + * 杩斿洖鍊: + * 杩斿洖瑙f瀽鍑虹殑 GTM_Timeline 鍊 + */ static GTM_Timeline TxnSnapParseTimelineFromText(const char* prefix, char** s) { char* ptr = *s; int prefixlen = strlen(prefix); GTM_Timeline val; - + // 妫鏌ヨ緭鍏ユ枃鏈槸鍚︿互 prefix 寮澶 if (strncmp(ptr, prefix, prefixlen) != 0) { + // 濡傛灉涓嶆槸锛屼細鐢熸垚涓涓敊璇秷鎭苟鎶涘嚭寮傚父 ereport(ERROR, (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), errmsg("invalid snapshot data in gs_txn_snapshot"))); } - + // 灏嗘寚閽 ptr 鍚戝墠绉诲姩锛岃烦杩囧凡鍖归厤鐨勫墠缂閮ㄥ垎 ptr += prefixlen; + // 浠庢枃鏈腑鎻愬彇涓涓棤绗﹀彿鏁存暟 GTM_Timeline if (sscanf_s(ptr, "%u", &val) != 1) { + // 濡傛灉鎻愬彇澶辫触锛屼細鐢熸垚閿欒娑堟伅骞舵姏鍑哄紓甯 ereport(ERROR, (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), errmsg("invalid snapshot data in gs_txn_snapshot"))); } - + // 鍦ㄦ枃鏈腑鏌ユ壘涓嬩竴涓崲琛岀鐨勪綅缃紝骞跺皢 ptr 鎸囧悜璇ヤ綅缃 ptr = strchr(ptr, '\n'); if (ptr == NULL) { + // 濡傛灉鎵句笉鍒版崲琛岀锛岀敓鎴愪竴涓敊璇秷鎭苟鎶涘嚭寮傚父 ereport(ERROR, (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), errmsg("invalid snapshot data in gs_txn_snapshot"))); } - *s = ptr + 1; - return val; + *s = ptr + 1; // 灏 s 鎸囬拡鎸囧悜涓嬩竴琛岀殑寮澶达紝浠ヤ究鍦ㄤ笅娆¤皟鐢ㄦ椂澶勭悊涓嬩竴琛岀殑鏂囨湰 + return val; // 杩斿洖瑙f瀽鍑虹殑 GTM_Timeline 鍊 } +/* + *鍔熻兘锛氫粠鏂囨湰涓В鏋愬嚭涓涓 TransactionId锛堜簨鍔℃爣璇嗙锛 + * + * 鍙傛暟: + * prefix锛氳鍖归厤鐨勫墠缂瀛楃涓 + * s锛氭寚鍚戣緭鍏ユ枃鏈殑鎸囬拡 + * + * 杩斿洖鍊: + * 杩斿洖瑙f瀽鍑虹殑 TransactionId 鍊 + */ static TransactionId TxnSnapParseXidFromText(const char* prefix, char** s) { char* ptr = *s; - int prefixlen = strlen(prefix); + int prefixlen = strlen(prefix); // 璁$畻 prefix 瀛楃涓茬殑闀垮害 TransactionId val; - + // 妫鏌ユ枃鏈槸鍚︿互鎸囧畾鐨勫墠缂瀛楃涓 prefix 寮澶 if (strncmp(ptr, prefix, prefixlen) != 0) { + // 濡傛灉涓嶆槸锛岀敓鎴愪竴涓敊璇秷鎭苟鎶涘嚭寮傚父 ereport(ERROR, (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), errmsg("invalid snapshot data in gs_txn_snapshot"))); } - + // 灏嗘寚閽 ptr 鍚戝墠绉诲姩锛岃烦杩囧凡鍖归厤鐨勫墠缂閮ㄥ垎 ptr += prefixlen; + // 瑙f瀽涓涓簨鍔℃爣璇嗙 if (sscanf_s(ptr, XID_FMT, &val) != 1) { + // 濡傛灉瑙f瀽澶辫触锛岀敓鎴愪竴涓敊璇秷鎭苟鎶涘嚭寮傚父 ereport(ERROR, (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), errmsg("invalid snapshot data in gs_txn_snapshot"))); } - + // 鏌ユ壘涓嬩竴涓崲琛岀鐨勪綅缃紝骞跺皢 ptr 鎸囧悜璇ヤ綅缃 ptr = strchr(ptr, '\n'); if (ptr == NULL) { + // 濡傛灉鎵句笉鍒版崲琛岀锛岀敓鎴愪竴涓敊璇秷鎭苟鎶涘嚭寮傚父 ereport(ERROR, (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), errmsg("invalid snapshot data in gs_txn_snapshot"))); } - + // 灏 s 鎸囬拡鎸囧悜涓嬩竴琛岀殑寮澶达紝浠ヤ究鍦ㄤ笅娆¤皟鐢ㄦ椂澶勭悊涓嬩竴琛岀殑鏂囨湰 *s = ptr + 1; - return val; + return val; // 杩斿洖瑙f瀽鍑虹殑 TransactionId 鍊 } +/* + *鍔熻兘锛氫粠鏂囨湰涓В鏋愬嚭涓涓暣鏁板煎苟杩斿洖 + * + * 鍙傛暟: + * prefix锛氳鍖归厤鐨勫墠缂瀛楃涓 + * s锛氭寚鍚戣緭鍏ユ枃鏈殑鎸囬拡 + * + * 杩斿洖鍊: + * 杩斿洖瑙f瀽鍑虹殑鏁存暟鍊 + */ static int TxnSnapParseIntFromText(const char* prefix, char** s) { char* ptr = *s; - int prefixlen = strlen(prefix); + int prefixlen = strlen(prefix); // 璁$畻 prefix 瀛楃涓茬殑闀垮害 int val; - + // 妫鏌ユ枃鏈槸鍚︿互鎸囧畾鐨勫墠缂瀛楃涓 prefix 寮澶 if (strncmp(ptr, prefix, prefixlen) != 0) + // 濡傛灉涓嶆槸锛岀敓鎴愪竴涓敊璇秷鎭苟鎶涘嚭寮傚父 ereport(ERROR, (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), errmsg("invalid snapshot data in gs_txn_snapshot"))); + // 灏嗘寚閽 ptr 鍚戝墠绉诲姩锛岃烦杩囧凡鍖归厤鐨勫墠缂閮ㄥ垎 ptr += prefixlen; + // 瑙f瀽涓涓簨鍔℃爣璇嗙 if (sscanf_s(ptr, "%d", &val) != 1) + // 濡傛灉瑙f瀽澶辫触锛岀敓鎴愪竴涓敊璇秷鎭苟鎶涘嚭寮傚父 ereport(ERROR, (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), errmsg("invalid snapshot data in gs_txn_snapshot"))); + // 鏌ユ壘涓嬩竴涓崲琛岀鐨勪綅缃紝骞跺皢 ptr 鎸囧悜璇ヤ綅缃 ptr = strchr(ptr, '\n'); if (ptr == NULL) + // 濡傛灉鎵句笉鍒版崲琛岀锛岀敓鎴愪竴涓敊璇秷鎭苟鎶涘嚭寮傚父 ereport(ERROR, (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), errmsg("invalid snapshot data in gs_txn_snapshot"))); + // 灏 s 鎸囬拡鎸囧悜涓嬩竴琛岀殑寮澶达紝浠ヤ究鍦ㄤ笅娆¤皟鐢ㄦ椂澶勭悊涓嬩竴琛岀殑鏂囨湰 *s = ptr + 1; - return val; + return val; // 杩斿洖瑙f瀽鍑虹殑鏁存暟鍊 } +/* + *鍔熻兘锛氬皢蹇収淇℃伅搴忓垪鍖栧埌涓涓瓧绗︿覆缂撳啿鍖 + * + * 鍙傛暟: + * Snapshot snap锛氳〃绀鸿搴忓垪鍖栫殑蹇収 + * StringInfo buf锛氳〃绀虹敤浜庡瓨鍌ㄥ簭鍒楀寲缁撴灉鐨勫瓧绗︿覆缂撳啿鍖 + * + * 杩斿洖鍊:鏃 + */ static void TxnSnapSerialize(Snapshot snap, StringInfo buf) { + // 灏嗗瓧绗︿覆杩藉姞鍒 buf 涓 + // 灏 xmin 鐨勫兼牸寮忓寲涓哄甫鏈夊墠缂 "xmin:" 鍜屾崲琛岀鐨勫瓧绗︿覆锛岀劧鍚庤拷鍔犲埌缂撳啿鍖轰腑 appendStringInfo(buf, "xmin:" XID_FMT "\n", snap->xmin); + // 灏 xmax 鐨勫兼牸寮忓寲涓哄甫鏈夊墠缂 "xmax:" 鍜屾崲琛岀鐨勫瓧绗︿覆锛岀劧鍚庤拷鍔犲埌缂撳啿鍖轰腑 appendStringInfo(buf, "xmax:" XID_FMT "\n", snap->xmax); + // 灏 snapshotcsn 鐨勫兼牸寮忓寲涓哄甫鏈夊墠缂 "snapshotcsn:" 鍜屾崲琛岀鐨勫瓧绗︿覆锛岀劧鍚庤拷鍔犲埌缂撳啿鍖轰腑 appendStringInfo(buf, "snapshotcsn:" XID_FMT "\n", snap->snapshotcsn); + // 灏 timeline 鐨勫兼牸寮忓寲涓哄甫鏈夊墠缂 "timeline:" 鍜屾崲琛岀鐨勫瓧绗︿覆锛岀劧鍚庤拷鍔犲埌缂撳啿鍖轰腑 appendStringInfo(buf, "timeline:%u\n", snap->timeline); + // 灏 takenDuringRecovery 鐨勫兼牸寮忓寲涓哄甫鏈夊墠缂 "rec:" 鍜屾崲琛岀鐨勫瓧绗︿覆锛岀劧鍚庤拷鍔犲埌缂撳啿鍖轰腑 appendStringInfo(buf, "rec:%u\n", snap->takenDuringRecovery); - buf->data[buf->len] = '\0'; + buf->data[buf->len] = '\0'; // 鍦ㄧ紦鍐插尯鐨勬湯灏炬坊鍔犱竴涓┖瀛楃 } +/* + *鍔熻兘锛氫粠鏂囨湰涓弽搴忓垪鍖栧揩鐓т俊鎭紝骞跺皢瑙f瀽鍑虹殑鍊煎瓨鍌ㄥ埌 Snapshot 缁撴瀯浣撲腑 + * 鐢ㄤ簬浠庢枃鏈腑杩樺師鏁版嵁缁撴瀯 + * + * 鍙傛暟: + * buf锛氳〃绀哄寘鍚簭鍒楀寲鏁版嵁鐨勬枃鏈瓧绗︿覆 + * snap锛氳〃绀鸿瀛樺偍瑙f瀽缁撴灉鐨勫揩鐓х粨鏋勪綋 + * + * 杩斿洖鍊:鏃 + */ void TxnSnapDeserialize(char *buf, Snapshot snap) { - char *tmpBuf = buf; + char *tmpBuf = buf; // 鐢ㄤ簬杩借釜鏂囨湰鐨勮В鏋愪綅缃 + // 瑙f瀽浠 "xmin:" 寮澶寸殑鏂囨湰锛屽皢缁撴灉瀛樺偍鍒 snap->xmin 涓 snap->xmin = TxnSnapParseXidFromText("xmin:", &tmpBuf); + // 瑙f瀽浠 "xmax:" 寮澶寸殑鏂囨湰锛屽皢缁撴灉瀛樺偍鍒 snap->xmax 涓 snap->xmax = TxnSnapParseXidFromText("xmax:", &tmpBuf); + // 瑙f瀽浠 "snapshotcsn:" 寮澶寸殑鏂囨湰锛屽皢缁撴灉瀛樺偍鍒 snap->snapshotcsn 涓 snap->snapshotcsn = TxnSnapParseXidFromText("snapshotcsn:", &tmpBuf); + // 瑙f瀽浠 "timeline:" 寮澶寸殑鏂囨湰锛屽皢缁撴灉瀛樺偍鍒 snap->timeline 涓 snap->timeline = TxnSnapParseTimelineFromText("timeline:", &tmpBuf); + // 瑙f瀽浠 "rec:" 寮澶寸殑鏂囨湰锛屽皢缁撴灉瀛樺偍鍒 snap->takenDuringRecovery 涓 snap->takenDuringRecovery = TxnSnapParseIntFromText("rec:", &tmpBuf); } /* * Get the current snapshot and record to pg_snapshot. */ + +/* + *鍔熻兘锛氬皢褰撳墠蹇収淇℃伅鎻掑叆鍒版暟鎹簱鐨 pg_snapshot 琛ㄤ腑 + * + * 鍙傛暟:鏃 + * + * 杩斿洖鍊:鏃 + */ static void TxnSnapInsert(void) { - Relation rel; - HeapTuple tup; - bool nulls[Natts_pg_snapshot] = { false }; - Datum values[Natts_pg_snapshot] = { 0 }; - Snapshot snap = (Snapshot)palloc0(sizeof(SnapshotData)); - StringInfoData buf; + Relation rel; // 鐢ㄤ簬琛ㄧず瑕佹彃鍏ユ暟鎹殑鏁版嵁搴撹〃 + HeapTuple tup; // 鐢ㄤ簬琛ㄧず瑕佹彃鍏ョ殑鏁版嵁琛 + // 鐢ㄤ簬琛ㄧず鎻掑叆鏁版嵁琛屼腑鍚勫垪鐨勭┖鍊兼儏鍐 false琛ㄧず娌℃湁绌哄 + bool nulls[Natts_pg_snapshot] = { false }; + Datum values[Natts_pg_snapshot] = { 0 }; // 鐢ㄤ簬瀛樺偍瑕佹彃鍏ョ殑鏁版嵁琛岀殑鍚勪釜鍒楃殑鍊 + Snapshot snap = (Snapshot)palloc0(sizeof(SnapshotData)); // 鐢ㄤ簬瀛樺偍蹇収淇℃伅 + StringInfoData buf; // 鐢ㄤ簬瀛樺偍搴忓垪鍖栧悗鐨勫揩鐓т俊鎭殑鏂囨湰 - (void)GetSnapshotData(snap, false); + (void)GetSnapshotData(snap, false); // 鑾峰彇褰撳墠蹇収鐨勬暟鎹 - initStringInfo(&buf); - TxnSnapSerialize(snap, &buf); + initStringInfo(&buf); // 鍒濆鍖 buf锛屼互渚垮湪鍚庣画姝ラ涓皢搴忓垪鍖栫殑蹇収淇℃伅杩藉姞鍒板叾涓 + TxnSnapSerialize(snap, &buf); // 灏嗗揩鐓т俊鎭簭鍒楀寲骞惰拷鍔犲埌 buf 涓 + // 璁剧疆鏁版嵁琛岀殑鍚勫垪鍊 + // 璁剧疆涓哄綋鍓嶆椂闂存埑 values[Anum_pg_snapshot_snptime - 1] = TimestampTzGetDatum(GetCurrentTimestamp()); + // 璁剧疆涓 snap->xmin 鐨勫 values[Anum_pg_snapshot_snpxmin - 1] = Int64GetDatum(snap->xmin); + // 璁剧疆涓 snap->snapshotcsn 鐨勫 values[Anum_pg_snapshot_snpcsn - 1] = Int64GetDatum(snap->snapshotcsn); + // 璁剧疆涓 buf.data 鐨勫硷紝杩欐槸搴忓垪鍖栧悗鐨勫揩鐓т俊鎭 values[Anum_pg_snapshot_snpsnapshot - 1] = CStringGetTextDatum(buf.data); + // 鎵撳紑鏁版嵁搴撲腑鐨 pg_snapshot 琛紝骞跺皢鍏跺叧绯诲璞¤祴鍊 rel = heap_open(SnapshotRelationId, RowExclusiveLock); + // 浣跨敤缁欏畾鐨勫垪鎻忚堪绗︺佸垪鍊煎拰绌哄间俊鎭垱寤轰竴涓爢鍏冪粍 tup = heap_form_tuple(RelationGetDescr(rel), values, nulls); - (void)simple_heap_insert(rel, tup); - CatalogUpdateIndexes(rel, tup); + (void)simple_heap_insert(rel, tup); // 灏嗗垱寤虹殑鏁版嵁琛屾彃鍏ュ埌鏁版嵁搴撹〃涓 + CatalogUpdateIndexes(rel, tup); // 鏇存柊鏁版嵁搴撹〃鐨勭储寮 - heap_close(rel, RowExclusiveLock); + heap_close(rel, RowExclusiveLock); // 鍏抽棴鏁版嵁搴撹〃 + // 閲婃斁涔嬪墠鍒嗛厤鐨 snap 缁撴瀯浣撶殑鍐呭瓨锛屽寘鎷叾娣卞眰娆$殑鍐呭瓨 FreeSnapshotDeepForce(snap); + // 閲婃斁搴忓垪鍖栫紦鍐插尯 buf 鐨勫唴瀛 pfree(buf.data); + // 閲婃斁鍫嗗厓缁 tup 鐨勫唴瀛 heap_freetuple_ext(tup); return; @@ -287,30 +435,45 @@ static void TxnSnapInsert(void) * Delete the out-date snapshots, that is, * DELETE FROM pg_snapshot WHERE snptime <= now() - '3 days'; */ + +/* + *鍔熻兘锛氬垹闄よ繃鏈熺殑蹇収鏁版嵁 + * + * 鍙傛暟:鏃 + * + * 杩斿洖鍊:鏃 + */ static void TxnSnapDelete(void) { -#define TXNSNAP_EXTRA_RETRNTION_TIME 900 - Relation rel; - ScanKeyData skey[2]; - SysScanDesc sd; - HeapTuple tup; +#define TXNSNAP_EXTRA_RETRNTION_TIME 900 // 灏嗛澶栫殑淇濈暀鏃堕棿璁剧疆涓 900 绉 + Relation rel; // 鐢ㄤ簬琛ㄧず瑕佹彃鍏ユ暟鎹殑鏁版嵁搴撹〃 + ScanKeyData skey[2]; // 鐢ㄤ簬瀹氫箟鎵弿鏉′欢 + SysScanDesc sd; // 鐢ㄤ簬鎵ц绯荤粺琛ㄦ壂鎻 + HeapTuple tup; // 鐢ㄤ簬琛ㄧず瑕佹彃鍏ョ殑鏁版嵁琛 /* Retent snapshots for up to undo_retention_time + 15min. */ + // 璁$畻浜嗗揩鐓х殑鏈澶т繚鐣欐椂闂 + // 鍖呮嫭浜嗛厤缃殑 undo_retention_time 鍜岄澶栫殑 15 鍒嗛挓锛900 绉掞級 const int64 snapRetentionMs = 1000L * (u_sess->attr.attr_storage.undo_retention_time + TXNSNAP_EXTRA_RETRNTION_TIME); + // 琛ㄧず瑕佸垹闄ょ殑蹇収鐨勬渶鏃╀繚鐣欐椂闂寸偣锛屽嵆褰撳墠鏃堕棿鍑忓幓鏈澶т繚鐣欐椂闂 TimestampTz ft = TimestampTzPlusMilliseconds(GetCurrentTimestamp(), snapRetentionMs * -1); + // 鎵撳紑鏁版嵁搴撲腑鐨 pg_snapshot 琛紝骞跺皢鍏跺叧绯诲璞¤祴鍊 rel = heap_open(SnapshotRelationId, RowExclusiveLock); + // 鍒濆鍖栨壂鎻忛敭 skey锛岀敤浜庢煡鎵惧皬浜庢垨绛変簬 ft 鐨勫揩鐓ф暟鎹 ScanKeyInit(&skey[0], Anum_pg_snapshot_snptime, BTLessEqualStrategyNumber, F_TIMESTAMP_LE, TimestampTzGetDatum(ft)); + // 浣跨敤瀹氫箟鐨勬壂鎻忔潯浠 skey锛屽紑濮嬪鏁版嵁搴撹〃鐨勭郴缁熸壂鎻 sd = systable_beginscan(rel, SnapshotTimeCsnIndexId, true, NULL, 1, skey); + // 閬嶅巻婊¤冻鎵弿鏉′欢鐨勫揩鐓ф暟鎹 閫氳繃 systable_getnext 鑾峰彇涓嬩竴涓鍚堟潯浠剁殑鏁版嵁琛 while ((tup = systable_getnext(sd)) != NULL) { - simple_heap_delete(rel, &tup->t_self); + simple_heap_delete(rel, &tup->t_self); // 鍒犻櫎浜嗗綋鍓嶅惊鐜腑鎸囧畾鐨勬暟鎹 } - systable_endscan(sd); - heap_close(rel, RowExclusiveLock); + systable_endscan(sd); // 缁撴潫绯荤粺琛ㄦ壂鎻 + heap_close(rel, RowExclusiveLock); // 鍏抽棴鏁版嵁搴撹〃 } /* @@ -318,63 +481,98 @@ static void TxnSnapDelete(void) * * maintains the sys table pg_snapshot. */ + +/* + *鍔熻兘锛氱淮鎶や簨鍔″揩鐓у伐浣滆繘绋 + * + * 鍙傛暟:鏃 + * + * 杩斿洖鍊:鏃 + */ static void TxnSnapWorkerImpl(void) { - int retentionTime = u_sess->attr.attr_storage.undo_retention_time; - TimestampTz result; + int retentionTime = u_sess->attr.attr_storage.undo_retention_time; // 琛ㄧず淇濈暀浜嬪姟蹇収鐨勬椂闂 + TimestampTz result; // 鐢ㄤ簬瀛樺偍璁$畻鍚庣殑鏃堕棿鎴冲 - StartTransactionCommand(); + StartTransactionCommand(); // 鍚姩涓涓柊鐨勪簨鍔 - TxnSnapInsert(); + TxnSnapInsert(); // 灏嗗綋鍓嶅揩鐓т俊鎭彃鍏ュ埌鏁版嵁搴撹〃 - TxnSnapDelete(); + TxnSnapDelete(); // 鍒犻櫎杩囨湡鐨勫揩鐓т俊鎭 +// 鏍规嵁鏄惁瀹氫箟浜 HAVE_INT64_TIMESTAMP 瀹忔潵鎵ц涓嶅悓鐨勫垎鏀 #ifdef HAVE_INT64_TIMESTAMP + // 璁$畻鏃堕棿鎴筹紝浠 int64 绫诲瀷琛ㄧず result = GetCurrentTimestamp() - retentionTime * (INT64CONST(1000000)); #else result = GetCurrentTimestamp() - retentionTime; #endif + // 灏嗚绠楃殑鏃堕棿鐐瑰瓨鍌ㄥ湪鍏ㄥ眬鍙橀噺涓 g_instance.flashback_cxt.oldestXminInFlashback = TvFetchSnpxminRecycle(result); - CommitTransactionCommand(); + CommitTransactionCommand(); // 鎻愪氦褰撳墠鐨勪簨鍔 } +/* + * 鍔熻兘锛氱敤浜庡揩鐓у伐浣滆繘绋嬬殑閫鍑哄拰娓呯悊鎿嶄綔 + * + * 鍙傛暟: + * code锛氳〃绀洪鍑轰唬鐮 + * arg锛氳〃绀洪檮鍔犵殑鏁版嵁 + * + * 杩斿洖鍊:鏃 + */ static void TxnSnapWorkerQuitAndClean(int code, Datum arg) { + // 鑾峰彇鍏变韩鍐呭瓨涓殑蹇収宸ヤ綔杩涚▼淇℃伅 TxnSnapWorkerInfo *workInfo = &t_thrd.snapcapturer_cxt.snapCapShmem->workerInfo; + // 浣跨敤鍘熷瓙鎿嶄綔灏嗗揩鐓у伐浣滆繘绋嬬殑杩涚▼ID璁剧疆涓 0锛岃〃绀烘病鏈夋鍦ㄨ繍琛岀殑宸ヤ綔杩涚▼ pg_atomic_write_u64(&workInfo->snapworkerPid, 0); + // 灏嗗揩鐓у伐浣滆繘绋嬬殑鐘舵佽缃负 TXNWORKER_DONE 琛ㄧず宸ヤ綔杩涚▼宸茬粡瀹屾垚鍏朵换鍔 *(volatile TxnWorkerStatus *)&workInfo->status = TXNWORKER_DONE; } +/* + * 鍔熻兘锛氫簨鍔″揩鐓у伐浣滆繘绋嬬殑涓昏鎵ц閫昏緫 + * + * 鍙傛暟:鏃 + * + * 杩斿洖鍊:鏃 + */ NON_EXEC_STATIC void TxnSnapWorkerMain() { - sigjmp_buf localSigjmpBuf; + sigjmp_buf localSigjmpBuf; // 鐢ㄤ簬澶勭悊寮傚父璺宠浆 + // 鑾峰彇鍏变韩鍐呭瓨涓殑蹇収宸ヤ綔杩涚▼淇℃伅 TxnSnapWorkerInfo *workInfo = &t_thrd.snapcapturer_cxt.snapCapShmem->workerInfo; + // 浣跨敤鍘熷瓙鎿嶄綔灏嗗綋鍓嶅伐浣滆繘绋嬬殑杩涚▼ID璁剧疆鍒 snapworkerPid 瀛楁涓紝鏍囪瘑褰撳墠宸ヤ綔杩涚▼ pg_atomic_write_u64(&workInfo->snapworkerPid, t_thrd.proc_cxt.MyProcPid); /* we are a postmaster subprocess now */ - IsUnderPostmaster = true; - t_thrd.role = TXNSNAP_WORKER; + IsUnderPostmaster = true; // 琛ㄧず褰撳墠杩涚▼鏄湪 postmaster 杩涚▼涓嬭繍琛岀殑 + t_thrd.role = TXNSNAP_WORKER; // 琛ㄧず瀹冩槸浜嬪姟蹇収宸ヤ綔杩涚▼ /* tell datasender we update the values. */ - pg_memory_barrier(); + pg_memory_barrier(); // 鎵ц鍐呭瓨灞忛殰鎿嶄綔锛岀敤浜庣‘淇濆墠闈㈢殑鍐欐搷浣滃鍏朵粬绾跨▼鍙 /* reset t_thrd.proc_cxt.MyProcPid */ - t_thrd.proc_cxt.MyProcPid = gs_thread_self(); + t_thrd.proc_cxt.MyProcPid = gs_thread_self(); // 姝g‘鏍囪瘑绾跨▼ /* record Start Time for logging */ - t_thrd.proc_cxt.MyStartTime = time(NULL); + t_thrd.proc_cxt.MyStartTime = time(NULL); // 璁板綍浜嗗綋鍓嶈繘绋嬬殑鍚姩鏃堕棿 - t_thrd.proc_cxt.MyProgName = "TxnSnapWorker"; + t_thrd.proc_cxt.MyProgName = "TxnSnapWorker"; // 璁剧疆浜嗗綋鍓嶈繘绋嬬殑绋嬪簭鍚嶇О /* Identify myself via ps */ - init_ps_display("txnsnapworker process", "", "", ""); + init_ps_display("txnsnapworker process", "", "", ""); // 鍒濆鍖栬繘绋嬬姸鎬佹樉绀 + // 璁板綍浜嗚皟璇曠骇鍒殑鏃ュ織锛岃〃绀哄揩鐓у伐浣滆繘绋嬪凡缁忓惎鍔 elog(DEBUG1, "txnsnapworker started(%s)", NameStr(workInfo->dbName)); + // 妫鏌ユ槸鍚﹂厤缃簡 PostAuthDelay if (u_sess->attr.attr_security.PostAuthDelay) + // 濡傛灉閰嶇疆浜嗗欢杩熸椂闂达紝閭d箞宸ヤ綔杩涚▼灏嗕紤鐪犵浉搴旂殑鏃堕棿 pg_usleep(u_sess->attr.attr_security.PostAuthDelay * 1000000L); - SetProcessingMode(InitProcessing); + SetProcessingMode(InitProcessing); // 璁剧疆澶勭悊妯″紡涓哄垵濮嬪寲澶勭悊妯″紡 /* * Properly accept or ignore signals the postmaster might send us @@ -384,26 +582,27 @@ NON_EXEC_STATIC void TxnSnapWorkerMain() * want to wait for the backends to exit, whereupon the postmaster will * tell us it's okay to shut down (via SIGUSR2). */ - (void)gspqsignal(SIGINT, StatementCancelHandler); - (void)gspqsignal(SIGTERM, die); - (void)gspqsignal(SIGQUIT, quickdie); - (void)gspqsignal(SIGALRM, SIG_IGN); - (void)gspqsignal(SIGPIPE, SIG_IGN); + // 璁剧疆淇″彿澶勭悊绋嬪簭 + (void)gspqsignal(SIGINT, StatementCancelHandler); // 鐢ㄤ簬澶勭悊涓柇淇″彿 + (void)gspqsignal(SIGTERM, die); // 鐢ㄤ簬澶勭悊缁堟淇″彿 姝e父缁堟杩涚▼ + (void)gspqsignal(SIGQUIT, quickdie); // 鐢ㄤ簬澶勭悊閫鍑轰俊鍙 + (void)gspqsignal(SIGALRM, SIG_IGN); // 蹇界暐 + (void)gspqsignal(SIGPIPE, SIG_IGN); // 蹇界暐 (void)gspqsignal(SIGUSR1, procsignal_sigusr1_handler); - (void)gspqsignal(SIGUSR2, SIG_IGN); - (void)gspqsignal(SIGFPE, FloatExceptionHandler); - (void)gspqsignal(SIGCHLD, SIG_DFL); - (void)gspqsignal(SIGHUP, TxnSnapSighupHandler); - (void)gspqsignal(SIGTTIN, SIG_DFL); - (void)gspqsignal(SIGTTOU, SIG_DFL); - (void)gspqsignal(SIGCONT, SIG_DFL); - (void)gspqsignal(SIGWINCH, SIG_DFL); + (void)gspqsignal(SIGUSR2, SIG_IGN); // 蹇界暐 + (void)gspqsignal(SIGFPE, FloatExceptionHandler); // 鐢ㄤ簬澶勭悊娴偣寮傚父淇″彿 + (void)gspqsignal(SIGCHLD, SIG_DFL); // 鎭㈠榛樿琛屼负 + (void)gspqsignal(SIGHUP, TxnSnapSighupHandler); // 鐢ㄤ簬澶勭悊缁堢鎸傛柇鎴栭厤缃枃浠堕噸鏂板姞杞戒俊鍙 + (void)gspqsignal(SIGTTIN, SIG_DFL); // 鎭㈠榛樿琛屼负 + (void)gspqsignal(SIGTTOU, SIG_DFL); // 鎭㈠榛樿琛屼负 + (void)gspqsignal(SIGCONT, SIG_DFL); // 鎭㈠榛樿琛屼负 + (void)gspqsignal(SIGWINCH, SIG_DFL); // 鎭㈠榛樿琛屼负 /* We allow SIGQUIT (quickdie) at all times */ (void)sigdelset(&t_thrd.libpq_cxt.BlockSig, SIGQUIT); /* Early initialization */ - BaseInit(); + BaseInit(); // 鏃╂湡鍒濆鍖 /* * Create a per-backend PGPROC struct in shared memory, except in the @@ -412,14 +611,17 @@ NON_EXEC_STATIC void TxnSnapWorkerMain() * had to do some stuff with LWLocks). */ #ifndef EXEC_BACKEND + // 涓嶅湪鎵ц鍚庡彴鎯呭喌涓嬶紝鍒涘缓浜嗕竴涓 PGPROC 缁撴瀯浣擄紝骞跺鍏惰繘琛屽垵濮嬪寲 InitProcess(); #endif - on_proc_exit(TxnSnapWorkerQuitAndClean, 0); + on_proc_exit(TxnSnapWorkerQuitAndClean, 0); // 娉ㄥ唽鍦ㄨ繘绋嬮鍑烘椂鎵ц鐨勬竻鐞嗗嚱鏁 + // 璁剧疆褰撳墠杩涚▼鐨勬暟鎹簱鍜岀敤鎴蜂俊鎭 t_thrd.proc_cxt.PostInit->SetDatabaseAndUser((char*)pstrdup(NameStr(workInfo->dbName)), InvalidOid, NULL); t_thrd.proc_cxt.PostInit->InitTxnSnapWorker(); + // 璁剧疆褰撳墠杩涚▼鐨勫鐞嗘ā寮忎负 "NormalProcessing"锛岃〃绀烘甯哥殑澶勭悊妯″紡 SetProcessingMode(NormalProcessing); /* @@ -427,12 +629,14 @@ NON_EXEC_STATIC void TxnSnapWorkerMain() * that we can reset the context during error recovery and thereby avoid * possible memory leaks. */ + // 鍒涘缓涓涓唴瀛樹笂涓嬫枃 MemoryContext workMxt = AllocSetContextCreate( t_thrd.top_mem_cxt, "TxnSnapWorker", ALLOCSET_DEFAULT_INITSIZE, ALLOCSET_DEFAULT_INITSIZE, ALLOCSET_DEFAULT_MAXSIZE); + // 鍒囨崲鍒拌涓婁笅鏂 (void)MemoryContextSwitchTo(workMxt); /* @@ -440,36 +644,42 @@ NON_EXEC_STATIC void TxnSnapWorkerMain() * * See notes in postgres.c about the design of this coding. */ + // 澶勭悊寮傚父鎯呭喌 int curTryCounter = 0; int* oldTryCounter = NULL; if (sigsetjmp(localSigjmpBuf, 1) != 0) { + // 鍏抽棴鎵鏈夋墦寮鐨勬枃浠 gstrace_tryblock_exit(true, oldTryCounter); /* Since not using PG_TRY, must reset error stack by hand */ + // 鎵嬪姩閲嶇疆閿欒鍫嗘爤 t_thrd.log_cxt.error_context_stack = NULL; - t_thrd.log_cxt.call_stack = NULL; + t_thrd.log_cxt.call_stack = NULL; // 娓呯┖璋冪敤鏍 /* Prevent interrupts while cleaning up */ - HOLD_INTERRUPTS(); + HOLD_INTERRUPTS(); // 鍦ㄦ墽琛屾竻鐞嗘搷浣滄湡闂寸姝腑鏂 /* Forget any pending QueryCancel request */ - t_thrd.int_cxt.QueryCancelPending = false; - (void)disable_sig_alarm(true); + t_thrd.int_cxt.QueryCancelPending = false; // 琛ㄧず鍙栨秷璇锋眰涓嶅啀鎸傝捣 + (void)disable_sig_alarm(true); // 绂佺敤淇″彿闂归挓锛岀‘淇濅笉浼氬湪閿欒澶勭悊鏈熼棿瑙﹀彂瓒呮椂淇″彿 t_thrd.int_cxt.QueryCancelPending = false; /* Report the error to the server log */ - EmitErrorReport(); + EmitErrorReport(); // 鎶ュ憡閿欒鍒版湇鍔″櫒鏃ュ織 /* Notify txnsnapworker done in time */ + // 璁剧疆 latch 鏉ラ氱煡 txnsnapworker 杩涚▼宸插畬鎴 SetLatch(&t_thrd.snapcapturer_cxt.snapCapShmem->workerInfo.latch); /* * Abort the current transaction in order to recover. */ + // 涓褰撳墠浜嬪姟浠ヨ繘琛屾仮澶嶏紝浠讳綍鏈彁浜ょ殑鏇存敼灏嗚鍥炴粴锛屼互纭繚鏁版嵁搴撶殑涓鑷存 AbortCurrentTransaction(); /* release resource held by lsc */ + // 閲婃斁鐢辩郴缁熸暟鎹簱缂撳瓨鎸佹湁鐨勮祫婧 AtEOXact_SysDBCache(false); /* Notice: at the most time it isn't necessary to call because @@ -478,94 +688,125 @@ NON_EXEC_STATIC void TxnSnapWorkerMain() * example the following InitMultinodeExecutor() calling ) * maybe hold LWLocks unused. */ - LWLockReleaseAll(); + LWLockReleaseAll(); // 閲婃斁閿 /* * Now return to normal top-level context and clear ErrorContext for * next time. */ + // 鍒囨崲绋嬪簭鐨勫唴瀛樹笂涓嬫枃 (void)MemoryContextSwitchTo(workMxt); + // 娓呴櫎閿欒鐘舵侊紝灏嗕箣鍓嶅彲鑳借褰曠殑閿欒淇℃伅鍜岀姸鎬侀噸缃负绌 FlushErrorState(); /* Flush any leaked data in the top-level context */ + // 閲嶇疆骞跺垹闄や簡涔嬪墠鍒涘缓鐨勫唴瀛樹笂涓嬫枃 workMxt 鍙婂叾鎵鏈夊瓙涓婁笅鏂 + // 纭繚鍦ㄥ紓甯稿鐞嗗畬鎴愬悗閲婃斁宸插垎閰嶇殑鍐呭瓨锛屼互閬垮厤鍐呭瓨娉勬紡 MemoryContextResetAndDeleteChildren(workMxt); /* Now we can allow interrupts again */ - RESUME_INTERRUPTS(); + RESUME_INTERRUPTS(); // 鍏佽涓柇淇″彿鍐嶆琚崟鑾 /* just go away */ goto shutdown; } - + // 灏嗗綋鍓嶈繘绋嬬姸鎬佽缃负 TXNWORKER_STARTED *(volatile TxnWorkerStatus *)&workInfo->status = TXNWORKER_STARTED; - + // 璁板綍褰撳墠鐨勯敊璇鐞嗗爢鏍堣鏁板櫒 oldTryCounter = gstrace_tryblock_entry(&curTryCounter); /* We can now handle ereport(ERROR) */ + // 灏嗛敊璇鐞嗙殑璺宠浆缂撳啿鍖鸿缃负褰撳墠绾跨▼鐨勯敊璇鐞嗗爢鏍 t_thrd.log_cxt.PG_exception_stack = &localSigjmpBuf; /* * Unblock signals (they were blocked when the postmaster forked us) */ + // 瑙i櫎淇″彿灞忚斀锛屽厑璁镐俊鍙峰啀娆¤鎹曡幏 gs_signal_setmask(&t_thrd.libpq_cxt.UnBlockSig, NULL); + // 瑙i櫎瀵 SIGUSR2 淇″彿鐨勫睆钄斤紝鍏佽鎺ユ敹 SIGUSR2 淇″彿 (void)gs_signal_unblock_sigusr2(); /* Set lockwait_timeout/update_lockwait_timeout to 30s avoid unexpected suspend. */ + // 璁剧疆閿佺瓑寰呰秴鏃舵椂闂 浠ラ伩鍏嶅湪绛夊緟閿佺殑杩囩▼涓彂鐢熸剰澶栫殑鎸傝捣 SetConfigOption("lockwait_timeout", "30s", PGC_SUSET, PGC_S_OVERRIDE); SetConfigOption("update_lockwait_timeout", "30s", PGC_SUSET, PGC_S_OVERRIDE); /* Do the hard work */ - if (TcapFeatureAvail()) { - TxnSnapWorkerImpl(); + if (TcapFeatureAvail()) { // 妫鏌ユ槸鍚︽敮鎸 TcapFeature + TxnSnapWorkerImpl(); // 鎵ц瀹為檯鐨勫伐浣 } - + // 閲嶇疆骞跺垹闄や簡涔嬪墠鍒涘缓鐨勫唴瀛樹笂涓嬫枃 workMxt 鍙婂叾鎵鏈夊瓙涓婁笅鏂 MemoryContextResetAndDeleteChildren(workMxt); shutdown: + // 璁板綍涓鏉¤皟璇曠骇鍒殑鏃ュ織娑堟伅锛屾寚绀 txnsnapworker 杩涚▼姝e湪鍏抽棴 elog(DEBUG1, "txnsnapworker shutting down(%s)", NameStr(workInfo->dbName)); proc_exit(0); } +/* + * 鍔熻兘锛氬垵濮嬪寲浜嬪姟蹇収宸ヤ綔杩涚▼淇℃伅缁撴瀯浣 TxnSnapWorkerInfo + * + * 鍙傛暟: + * dbName锛氭暟鎹簱鍚嶇О + * + * 杩斿洖鍊: + * 杩斿洖鎸囧悜鍒濆鍖栧悗鐨 workerInfo 缁撴瀯浣撶殑鎸囬拡 + */ static inline TxnSnapWorkerInfo *TxnSnapWorkerInfoInit(char *dbName) { TxnSnapWorkerInfo *workerInfo = &t_thrd.snapcapturer_cxt.snapCapShmem->workerInfo; errno_t rc; - workerInfo->status = TXNWORKER_DEFAULT; - + workerInfo->status = TXNWORKER_DEFAULT; // 璁剧疆榛樿鐘舵 + // 璁剧疆宸ヤ綔杩涚▼鎵灞炵殑鏁版嵁搴撳悕绉 rc = strcpy_s(NameStr(workerInfo->dbName), NAMEDATALEN, dbName); securec_check_c(rc, "\0", "\0"); - + // 鍒濆鍖 workerInfo 缁撴瀯浣撲腑鐨 latch锛岀敤浜庡疄鐜扮嚎绋嬩箣闂寸殑鍚屾鍜岄氫俊 InitLatch(&workerInfo->latch); - return workerInfo; + return workerInfo; // 杩斿洖鎸囧悜鍒濆鍖栧悗鐨 workerInfo 缁撴瀯浣撶殑鎸囬拡 } +/* + * 鍔熻兘锛氬鐞嗕笉鍚岀被鍨嬬殑杩涚▼涓柇淇″彿 + * + * 鍙傛暟: + * rc锛氳〃绀轰紶閫掔粰鍑芥暟鐨勪腑鏂爣蹇椾綅锛岀敤浜庣‘瀹氬彂鐢熶簡鍝簺绫诲瀷鐨勪腑鏂 + * + * 杩斿洖鍊:鏃 + */ static void TxnSnapCapProcInterrupts(int rc) { /* Process sinval catchup interrupts that happened while sleeping */ - ProcessCatchupInterrupt(); + ProcessCatchupInterrupt(); // 澶勭悊 sinval catchup 涓柇 /* * Emergency bailout if postmaster has died. This is to avoid the * necessity for manual cleanup of all postmaster children. */ + // 濡傛灉 rc 涓寘鍚 WL_POSTMASTER_DEATH 鏍囧織浣嶏紝琛ㄧず postmaster 杩涚▼宸茬粡缁堟 if (((unsigned int)rc) & WL_POSTMASTER_DEATH) { + // 绱фユ儏鍐碉紝缁堟褰撳墠杩涚▼锛屼互閬垮厤闇瑕佹墜鍔ㄦ竻鐞嗘墍鏈 postmaster 鐨勫瓙杩涚▼ proc_exit(1); } /* the normal shutdown case */ + // 濡傛灉鎺ユ敹鍒颁簡 SIGTERM 淇″彿 if (t_thrd.snapcapturer_cxt.got_SIGTERM) { + // 璁板綍涓鏉℃棩蹇楁秷鎭 elog(LOG, "txnsnapcapturer is shutting down."); - proc_exit(0); + proc_exit(0); // 姝e父閫鍑鸿繘绋 } /* * reload the postgresql.conf */ + // 濡傛灉鎺ユ敹鍒颁簡 SIGHUP 淇″彿 if (t_thrd.snapcapturer_cxt.got_SIGHUP) { - t_thrd.snapcapturer_cxt.got_SIGHUP = false; - ProcessConfigFile(PGC_SIGHUP); + t_thrd.snapcapturer_cxt.got_SIGHUP = false; // 琛ㄧず宸插鐞 + ProcessConfigFile(PGC_SIGHUP); // 閲嶆柊鍔犺浇閰嶇疆鏂囦欢 postgresql.conf } } @@ -573,164 +814,213 @@ static void TxnSnapCapProcInterrupts(int rc) * TxnGetDatabaseList * Return a list of all databases found in pg_database. */ + +/* + * 鍔熻兘锛氳幏鍙栫郴缁熶腑鎵鏈夋暟鎹簱鐨勫垪琛 + * + * 鍙傛暟:鏃 + * + * 杩斿洖鍊: + * 杩斿洖瀛樺偍浜嗘暟鎹簱鍚嶇殑 dblist 鍒楄〃 + */ static List* TxnGetDatabaseList(void) { - List* dblist = NIL; - Relation rel; - SysScanDesc sd; - HeapTuple tup; + List* dblist = NIL; // 鐢ㄤ簬瀛樺偍鏁版嵁搴撳悕鐨勫垪琛 + Relation rel; // 鐢ㄤ簬琛ㄧず鏁版嵁搴撳叧绯 + SysScanDesc sd; // 鐢ㄤ簬绯荤粺鎵弿琛 + HeapTuple tup; // 鐢ㄤ簬琛ㄧず琛ㄤ腑鐨勫厓缁 + // 鎵撳紑 pg_database 琛紝骞惰幏鍙栦竴涓叡浜攣 rel = heap_open(DatabaseRelationId, AccessShareLock); + // 寮濮嬬郴缁熸壂鎻 pg_database 琛 sd = systable_beginscan(rel, InvalidOid, false, NULL, 0, NULL); - + // 閬嶅巻琛ㄤ腑鐨勬瘡涓厓缁 while ((tup = systable_getnext(sd)) != NULL) { Form_pg_database pgdatabase = (Form_pg_database)GETSTRUCT(tup); + // 妫鏌ユ暟鎹簱鍚嶆槸鍚︿负 "template0" 鎴 "template1" if (strcmp(NameStr(pgdatabase->datname), "template0") == 0 || strcmp(NameStr(pgdatabase->datname), "template1") == 0) { - continue; + continue; // 濡傛灉鏄紝鍒欒烦杩囦笉澶勭悊 } + // 鍚﹀垯灏嗗叾澶嶅埗涓 C 瀛楃涓诧紝骞跺皢鍏舵坊鍔犲埌 dblist 鍒楄〃涓 dblist = lappend(dblist, pstrdup(NameStr(pgdatabase->datname))); } - systable_endscan(sd); - heap_close(rel, AccessShareLock); + systable_endscan(sd); // 缁撴潫绯荤粺鎵弿 + heap_close(rel, AccessShareLock); // 闂 pg_database 琛紝骞堕噴鏀惧叡浜攣 - return dblist; + return dblist; // 杩斿洖瀛樺偍浜嗘暟鎹簱鍚嶇殑 dblist 鍒楄〃 } +/* + * 鍔熻兘锛氭鏌ヤ簨鍔″揩鐓у伐浣滆繘绋嬫槸鍚︿粛鐒跺瓨娲 + * + * 鍙傛暟:鏃 + * + * 杩斿洖鍊: + * bool绫诲瀷锛屽瓨娲诲垯杩斿洖true锛屽惁鍒欒繑鍥瀎alse + */ static bool TxnSnapWorkerIsAlive() { + // 鑾峰彇褰撳墠浜嬪姟蹇収宸ヤ綔杩涚▼鐨勪俊鎭 TxnSnapWorkerInfo *workInfo = &t_thrd.snapcapturer_cxt.snapCapShmem->workerInfo; - int ntries; - const int maxtries = 500; + int ntries; // 鐢ㄤ簬璁板綍寰幆鐨勫皾璇曟鏁 + const int maxtries = 500; // 琛ㄧず鏈澶у皾璇曟鏁 /* Wait 5s until txnsnapworker stopped. */ for (ntries = 0; ; ntries++) { + // 妫鏌ュ綋鍓嶅伐浣滆繘绋嬬殑杩涚▼ID鏄惁绛変簬0 if (pg_atomic_read_u64(&workInfo->snapworkerPid) == 0) { - return false; + return false; // 濡傛灉杩涚▼ID涓0锛岃〃绀哄伐浣滆繘绋嬪凡缁忓仠姝 } - if (ntries >= maxtries) { + if (ntries >= maxtries) { // 妫鏌ュ惊鐜殑灏濊瘯娆℃暟鏄惁澶т簬鎴栫瓑浜 maxtries + // 濡傛灉灏濊瘯娆℃暟杈惧埌涓婇檺锛屽嚱鏁拌繑鍥 true锛岃〃绀哄伐浣滆繘绋嬩粛鐒跺瓨娲 return true; } /* wait 0.01 sec, then retry */ - pg_usleep(10000L); + pg_usleep(10000L); // 绛夊緟 0.01 绉 } - return true; + return true; // 琛ㄧず宸ヤ綔杩涚▼浠嶇劧瀛樻椿 } +/* + * 鍔熻兘锛氬惎鍔ㄤ簨鍔″揩鐓у伐浣滆繘绋嬶紝骞剁洃鎺у叾鐘舵侊紝浠ョ‘淇濆叾姝e父鍚姩鍜岃繍琛 + * + * 鍙傛暟:鏃 + * + * 杩斿洖鍊:鏃 + */ static void TxnSnapCapImpl(void) { - List *dblist; + List *dblist; // 鐢ㄤ簬瀛樺偍鏁版嵁搴撳垪琛 ListCell* cell = NULL; - const long int snapcapIntervalMs = 10L; - const long int snapcapStartThreshMs = 30000L; + const long int snapcapIntervalMs = 10L; // 琛ㄧず蹇収鎹曡幏鐨勬椂闂撮棿闅 + const long int snapcapStartThreshMs = 30000L; // 琛ㄧず绛夊緟蹇収鎹曡幏寮濮嬬殑鏈澶ф椂闂撮槇鍊 - StartTransactionCommand(); + StartTransactionCommand(); // 鍚姩涓涓柊鐨勪簨鍔 + // 杩斿洖鎵鏈夊湪 pg_database 涓壘鍒扮殑鏁版嵁搴撳垪琛紝骞跺皢鍏跺瓨鍌 dblist = TxnGetDatabaseList(); - + // 閬嶅巻鏁版嵁搴撳垪琛ㄤ腑鐨勬瘡涓暟鎹簱 foreach (cell, dblist) { - TimestampTz launchTime; - TxnSnapWorkerInfo *workInfo; + TimestampTz launchTime; // 鐢ㄤ簬璁板綍浜嬪姟蹇収宸ヤ綔杩涚▼鍚姩鐨勬椂闂 + TxnSnapWorkerInfo *workInfo; // 鐢ㄤ簬瀛樺偍浜嬪姟蹇収宸ヤ綔杩涚▼鐨勪俊鎭 + // 妫鏌ユ槸鍚﹀凡缁忓瓨鍦ㄦ椿鍔ㄧ殑浜嬪姟蹇収宸ヤ綔杩涚▼ if (TxnSnapWorkerIsAlive()) { + // 濡傛灉宸插瓨鍦紝浼氳Е鍙戜竴涓敊璇秷鎭紝琛ㄧず鍚姩浜嬪姟蹇収宸ヤ綔杩涚▼澶辫触 elog(ERROR, "start txnsnapworker failed: txnsnapworker already exists!"); } - + // 鍒濆鍖 workInfo = TxnSnapWorkerInfoInit((char *)lfirst(cell)); - + // 鍙戦佷竴涓俊鍙风粰 postmaster 杩涚▼锛屼互鍚姩浜嬪姟蹇収宸ヤ綔杩涚▼ SendPostmasterSignal(PMSIGNAL_START_TXNSNAPWORKER); - + // 璁板綍褰撳墠鏃堕棿鎴筹紝琛ㄧず浜嬪姟蹇収宸ヤ綔杩涚▼鐨勫惎鍔ㄦ椂闂 launchTime = GetCurrentTimestamp(); + while (true) { /* Clear any already-pending wakeups */ - ResetLatch(&workInfo->latch); + ResetLatch(&workInfo->latch); // 娓呴櫎浠讳綍宸茬粡鎸傝捣鐨 latch /* Wait latch for a maximum of 10ms for a snapworker done. */ + // 绛夊緟 latch 鐨勮缃 int rc = WaitLatch(&workInfo->latch, WL_LATCH_SET | WL_TIMEOUT | WL_POSTMASTER_DEATH, snapcapIntervalMs); - TxnSnapCapProcInterrupts(rc); + TxnSnapCapProcInterrupts(rc); // 澶勭悊涓柇 /* * We raise an ERROR if txnsnapworker not started as soon during to * unexcepted error or hang in initialization. */ + // 濡傛灉 workInfo 鐨勭姸鎬佷负 TXNWORKER_STARTED + // 涓斾粠鍚姩鍒板綋鍓嶆椂闂寸殑鏃堕棿宸秴杩囦簡 snapcapStartThreshMs if (*(volatile TxnWorkerStatus *)&workInfo->status < TXNWORKER_STARTED && TimestampDifferenceExceeds(launchTime, GetCurrentTimestamp(), snapcapStartThreshMs)) { + // 瑙﹀彂涓涓敊璇秷鎭紝琛ㄧず浜嬪姟蹇収宸ヤ綔杩涚▼鍚姩鏃堕棿杩囬暱 ereport(ERROR, (errcode(ERRCODE_INTERNAL_ERROR), errmsg("txnsnapworker took too long to start over 30 seconds."))); break; } - + // 濡傛灉 workInfo 鐨勭姸鎬佸彉涓 TXNWORKER_DONE 鍒欓鍑哄惊鐜 if (*(volatile TxnWorkerStatus *)&workInfo->status == TXNWORKER_DONE) { break; } } } - list_free_deep(dblist); - CommitTransactionCommand(); + list_free_deep(dblist); // 閲婃斁鏁版嵁搴撳垪琛ㄦ墍鍗犵敤鐨勫唴瀛 + CommitTransactionCommand(); // 鎻愪氦褰撳墠浜嬪姟 } +/* + * 鍔熻兘锛氫簨鍔″揩鐓ф崟鑾疯繘绋嬬殑涓昏鍏ュ彛鍑芥暟锛岀敤浜庢崟鑾锋暟鎹簱鐨勫揩鐓 + * + * 鍙傛暟:鏃 + * + * 杩斿洖鍊:鏃 + */ NON_EXEC_STATIC void TxnSnapCapturerMain() { - sigjmp_buf localSigjmpBuf; + sigjmp_buf localSigjmpBuf; // 鐢ㄤ簬澶勭悊寮傚父璺宠浆 /* we are a postmaster subprocess now */ - IsUnderPostmaster = true; - t_thrd.role = TXNSNAP_CAPTURER; + IsUnderPostmaster = true; // 琛ㄧず褰撳墠杩涚▼鏄湪 postmaster 杩涚▼涓嬭繍琛岀殑 + t_thrd.role = TXNSNAP_CAPTURER; // 琛ㄧず瀹冩槸浜嬪姟蹇収鎹曡幏杩涚▼ /* tell datasender we update the values. */ - pg_memory_barrier(); + pg_memory_barrier();// 鎵ц鍐呭瓨灞忛殰鎿嶄綔锛岀敤浜庣‘淇濆墠闈㈢殑鍐欐搷浣滃鍏朵粬绾跨▼鍙 /* reset t_thrd.proc_cxt.MyProcPid */ - t_thrd.proc_cxt.MyProcPid = gs_thread_self(); + t_thrd.proc_cxt.MyProcPid = gs_thread_self(); // 姝g‘鏍囪瘑绾跨▼ /* record Start Time for logging */ - t_thrd.proc_cxt.MyStartTime = time(NULL); + t_thrd.proc_cxt.MyStartTime = time(NULL); // 璁板綍浜嗗綋鍓嶇嚎绋嬬殑鍚姩鏃堕棿 - t_thrd.proc_cxt.MyProgName = "TxnSnapCapturer"; + t_thrd.proc_cxt.MyProgName = "TxnSnapCapturer"; // 璁剧疆浜嗗綋鍓嶇嚎绋嬬殑绋嬪簭鍚嶇О /* Identify myself via ps */ - init_ps_display("txnsnapcapturer process", "", "", ""); - + init_ps_display("txnsnapcapturer process", "", "", ""); // 鍒濆鍖栬繘绋嬬姸鎬佹樉绀 + // 璁板綍浜嗚皟璇曠骇鍒殑鏃ュ織锛岃〃绀哄揩鐓ф崟鑾疯繘绋嬪凡缁忓惎鍔 ereport(LOG, (errmsg("txnsnapcapturer started"))); - + // 妫鏌ユ槸鍚﹂厤缃簡 PostAuthDelay if (u_sess->attr.attr_security.PostAuthDelay) + // 濡傛灉閰嶇疆浜嗗欢杩熸椂闂达紝閭d箞宸ヤ綔杩涚▼灏嗕紤鐪犵浉搴旂殑鏃堕棿 pg_usleep(u_sess->attr.attr_security.PostAuthDelay * 1000000L); - SetProcessingMode(InitProcessing); + SetProcessingMode(InitProcessing); // 璁剧疆澶勭悊妯″紡涓哄垵濮嬪寲澶勭悊妯″紡 - (void)gspqsignal(SIGINT, StatementCancelHandler); - (void)gspqsignal(SIGTERM, die); - (void)gspqsignal(SIGQUIT, quickdie); - (void)gspqsignal(SIGALRM, SIG_IGN); - (void)gspqsignal(SIGPIPE, SIG_IGN); + // 璁剧疆淇″彿澶勭悊绋嬪簭 + (void)gspqsignal(SIGINT, StatementCancelHandler); // 鐢ㄤ簬澶勭悊涓柇淇″彿 + (void)gspqsignal(SIGTERM, die); // 鐢ㄤ簬澶勭悊缁堟淇″彿 姝e父缁堟杩涚▼ + (void)gspqsignal(SIGQUIT, quickdie); // 鐢ㄤ簬澶勭悊閫鍑轰俊鍙 + (void)gspqsignal(SIGALRM, SIG_IGN); // 蹇界暐 + (void)gspqsignal(SIGPIPE, SIG_IGN); // 蹇界暐 (void)gspqsignal(SIGUSR1, procsignal_sigusr1_handler); - (void)gspqsignal(SIGUSR2, SIG_IGN); - (void)gspqsignal(SIGFPE, FloatExceptionHandler); - (void)gspqsignal(SIGCHLD, SIG_DFL); - (void)gspqsignal(SIGHUP, TxnSnapSighupHandler); - (void)gspqsignal(SIGTTIN, SIG_DFL); - (void)gspqsignal(SIGTTOU, SIG_DFL); - (void)gspqsignal(SIGCONT, SIG_DFL); - (void)gspqsignal(SIGWINCH, SIG_DFL); + (void)gspqsignal(SIGUSR2, SIG_IGN); // 蹇界暐 + (void)gspqsignal(SIGFPE, FloatExceptionHandler); // 鐢ㄤ簬澶勭悊娴偣寮傚父淇″彿 + (void)gspqsignal(SIGCHLD, SIG_DFL); // 鎭㈠榛樿琛屼负 + (void)gspqsignal(SIGHUP, TxnSnapSighupHandler); // 鐢ㄤ簬澶勭悊缁堢鎸傛柇鎴栭厤缃枃浠堕噸鏂板姞杞戒俊鍙 + (void)gspqsignal(SIGTTIN, SIG_DFL); // 鎭㈠榛樿琛屼负 + (void)gspqsignal(SIGTTOU, SIG_DFL); // 鎭㈠榛樿琛屼负 + (void)gspqsignal(SIGCONT, SIG_DFL); // 鎭㈠榛樿琛屼负 + (void)gspqsignal(SIGWINCH, SIG_DFL); // 鎭㈠榛樿琛屼负 /* We allow SIGQUIT (quickdie) at all times */ (void)sigdelset(&t_thrd.libpq_cxt.BlockSig, SIGQUIT); /* Early initialization */ - BaseInit(); + BaseInit(); // 鏃╂湡鍒濆鍖 #ifndef EXEC_BACKEND + // 涓嶅湪鎵ц鍚庡彴鎯呭喌涓嬶紝鍒涘缓浜嗕竴涓 PGPROC 缁撴瀯浣擄紝骞跺鍏惰繘琛屽垵濮嬪寲 InitProcess(); #endif - + // 璁剧疆褰撳墠杩涚▼鐨勬暟鎹簱鍜岀敤鎴蜂俊鎭 t_thrd.proc_cxt.PostInit->SetDatabaseAndUser((char*)pstrdup(DEFAULT_DATABASE), InvalidOid, NULL); t_thrd.proc_cxt.PostInit->InitTxnSnapCapturer(); - + // 璁剧疆褰撳墠杩涚▼鐨勫鐞嗘ā寮忎负 "NormalProcessing"锛岃〃绀烘甯哥殑澶勭悊妯″紡 SetProcessingMode(NormalProcessing); /* @@ -738,57 +1028,65 @@ NON_EXEC_STATIC void TxnSnapCapturerMain() * that we can reset the context during error recovery and thereby avoid * possible memory leaks. */ + // 鍒涘缓涓涓唴瀛樹笂涓嬫枃 MemoryContext workMxt = AllocSetContextCreate( t_thrd.top_mem_cxt, "TxnSnapCapturer", ALLOCSET_DEFAULT_INITSIZE, ALLOCSET_DEFAULT_INITSIZE, ALLOCSET_DEFAULT_MAXSIZE); + // 鍒囨崲鍒拌涓婁笅鏂 (void)MemoryContextSwitchTo(workMxt); + // 澶勭悊寮傚父鎯呭喌 int curTryCounter = 0; int* oldTryCounter = NULL; if (sigsetjmp(localSigjmpBuf, 1) != 0) { + // 鍏抽棴鎵鏈夋墦寮鐨勬枃浠 gstrace_tryblock_exit(true, oldTryCounter); /* Since not using PG_TRY, must reset error stack by hand */ - t_thrd.log_cxt.error_context_stack = NULL; + t_thrd.log_cxt.error_context_stack = NULL; // 鎵嬪姩閲嶇疆閿欒鍫嗘爤 - t_thrd.log_cxt.call_stack = NULL; + t_thrd.log_cxt.call_stack = NULL; // 娓呯┖璋冪敤鏍 /* Prevent interrupts while cleaning up */ - HOLD_INTERRUPTS(); + HOLD_INTERRUPTS(); // 鍦ㄦ墽琛屾竻鐞嗘搷浣滄湡闂寸姝腑鏂 /* Forget any pending QueryCancel request */ - t_thrd.int_cxt.QueryCancelPending = false; - (void)disable_sig_alarm(true); + t_thrd.int_cxt.QueryCancelPending = false; // 琛ㄧず鍙栨秷璇锋眰涓嶅啀鎸傝捣 + (void)disable_sig_alarm(true); // 绂佺敤淇″彿闂归挓锛岀‘淇濅笉浼氬湪閿欒澶勭悊鏈熼棿瑙﹀彂瓒呮椂淇″彿 t_thrd.int_cxt.QueryCancelPending = false; /* Report the error to the server log */ - EmitErrorReport(); + EmitErrorReport(); // 鎶ュ憡閿欒鍒版湇鍔″櫒鏃ュ織 /* * Abort the current transaction in order to recover. */ + // 涓褰撳墠浜嬪姟浠ヨ繘琛屾仮澶嶏紝浠讳綍鏈彁浜ょ殑鏇存敼灏嗚鍥炴粴锛屼互纭繚鏁版嵁搴撶殑涓鑷存 AbortCurrentTransaction(); /* release resource held by lsc */ - AtEOXact_SysDBCache(false); + AtEOXact_SysDBCache(false); // 閲婃斁鐢辩郴缁熸暟鎹簱缂撳瓨鎸佹湁鐨勮祫婧 - LWLockReleaseAll(); + LWLockReleaseAll(); // 閲婃斁閿 /* * Now return to normal top-level context and clear ErrorContext for * next time. */ - (void)MemoryContextSwitchTo(workMxt); + (void)MemoryContextSwitchTo(workMxt); // 鍒囨崲绋嬪簭鐨勫唴瀛樹笂涓嬫枃 + // 娓呴櫎閿欒鐘舵侊紝灏嗕箣鍓嶅彲鑳借褰曠殑閿欒淇℃伅鍜岀姸鎬侀噸缃负绌 FlushErrorState(); /* Flush any leaked data in the top-level context */ + // 閲嶇疆骞跺垹闄や簡涔嬪墠鍒涘缓鐨勫唴瀛樹笂涓嬫枃 workMxt 鍙婂叾鎵鏈夊瓙涓婁笅鏂 + // 纭繚鍦ㄥ紓甯稿鐞嗗畬鎴愬悗閲婃斁宸插垎閰嶇殑鍐呭瓨锛屼互閬垮厤鍐呭瓨娉勬紡 MemoryContextResetAndDeleteChildren(workMxt); /* Now we can allow interrupts again */ - RESUME_INTERRUPTS(); + RESUME_INTERRUPTS(); // 鍏佽涓柇淇″彿鍐嶆琚崟鑾 /* if in shutdown mode, no need for anything further; just go away */ if (t_thrd.snapcapturer_cxt.got_SIGTERM) { @@ -801,46 +1099,56 @@ NON_EXEC_STATIC void TxnSnapCapturerMain() */ pg_usleep(1000000L); } - + // 璁板綍褰撳墠鐨勯敊璇鐞嗗爢鏍堣鏁板櫒 oldTryCounter = gstrace_tryblock_entry(&curTryCounter); /* We can now handle ereport(ERROR) */ + // 灏嗛敊璇鐞嗙殑璺宠浆缂撳啿鍖鸿缃负褰撳墠绾跨▼鐨勯敊璇鐞嗗爢鏍 t_thrd.log_cxt.PG_exception_stack = &localSigjmpBuf; /* * Unblock signals (they were blocked when the postmaster forked us) */ + // 瑙i櫎淇″彿灞忚斀锛屽厑璁镐俊鍙峰啀娆¤鎹曡幏 gs_signal_setmask(&t_thrd.libpq_cxt.UnBlockSig, NULL); + // 瑙i櫎瀵 SIGUSR2 淇″彿鐨勫睆钄斤紝鍏佽鎺ユ敹 SIGUSR2 淇″彿 (void)gs_signal_unblock_sigusr2(); /* loop until shutdown request */ + // 寰幆鐩村埌鏀跺埌浜嗗叧闂姹傛垨Tcap 鐗堟湰涓嶅啀鍙敤 while (!t_thrd.snapcapturer_cxt.got_SIGTERM && ENABLE_TCAP_VERSION) { int rc; - CHECK_FOR_INTERRUPTS(); + CHECK_FOR_INTERRUPTS(); // 妫鏌ユ槸鍚︽敹鍒颁簡涓柇璇锋眰 /* Clear any already-pending wakeups */ - ResetLatch(&t_thrd.proc->procLatch); + ResetLatch(&t_thrd.proc->procLatch); // 娓呴櫎浠讳綍宸茬粡鎸傝捣鐨勭瓑寰 /* * Wait until naptime expires or we get some type of signal (all the * signal handlers will wake us by calling SetLatch). */ + // 绛夊緟淇″彿鎴栬秴鏃 绛夊緟浠ヤ笅鏉′欢涔嬩竴鍙戠敓锛 + // 鏀跺埌浜 WL_LATCH_SET 淇″彿锛岃〃绀虹瓑寰呮爣蹇楀凡缁忚璁剧疆銆 + // 鏀跺埌浜 WL_TIMEOUT 淇″彿锛岃〃绀虹粡杩囦簡涓娈垫椂闂达紙鐢 SNAP_CAPTURE_INTERVAL 鎺у埗锛夈 + // 鏀跺埌浜 WL_POSTMASTER_DEATH 淇″彿锛岃〃绀 postmaster 杩涚▼宸茬粡閫鍑恒 rc = WaitLatch(&t_thrd.proc->procLatch, WL_LATCH_SET | WL_TIMEOUT | WL_POSTMASTER_DEATH, SNAP_CAPTURE_INTERVAL * 1000L); + // 澶勭悊涓嶅悓鐨勪腑鏂儏鍐碉紝鏍规嵁浼犲叆鐨勮繑鍥炵爜 rc 鎵ц鐩稿簲鐨勬搷浣 TxnSnapCapProcInterrupts(rc); /* Do the hard work. */ - if (TcapFeatureAvail()) { - TxnSnapCapImpl(); + if (TcapFeatureAvail()) { // 妫鏌ユ槸鍚︽敮鎸 TcapFeature + TxnSnapCapImpl(); // 鎵ц瀹為檯鐨勫伐浣 } - + // 閲嶇疆骞跺垹闄や簡涔嬪墠鍒涘缓鐨勫唴瀛樹笂涓嬫枃 workMxt 鍙婂叾鎵鏈夊瓙涓婁笅鏂 MemoryContextResetAndDeleteChildren(workMxt); } shutdown: + // 璁板綍涓鏉¤皟璇曠骇鍒殑鏃ュ織娑堟伅锛屾寚绀 txnsnapcapturer 杩涚▼姝e湪鍏抽棴 elog(LOG, "txnsnapcapturer shutting down"); proc_exit(0); } diff --git a/src/gausskernel/process/postmaster/startup.cpp b/src/gausskernel/process/postmaster/startup.cpp index a6fa6b8e8..20a3bda57 100755 --- a/src/gausskernel/process/postmaster/startup.cpp +++ b/src/gausskernel/process/postmaster/startup.cpp @@ -1,3 +1,5 @@ +// startup鍚姩杩涚▼璐熻矗鍒濆鍖栨湇鍔″櫒骞舵墽琛屾仮澶嶆搷浣溿備竴鏃﹀垵濮嬪寲瀹屾垚锛屽惎鍔ㄨ繘绋嬪氨浼氱粨鏉 + /* * * startup.cpp @@ -60,9 +62,19 @@ static void SetStaticConnNum(void); * Some backend has bought the farm, * so we need to stop what we're doing and exit. */ +/* + *鍔熻兘锛氬鐞嗗揩閫熺粓姝俊鍙(褰撲富杩涚▼鍙戝嚭SIGQUIT淇″彿) + * 绱фラ鍑烘搷浣滐紝涓嶄細瑙﹀彂姝e父鐨勬竻鐞嗗拰鍏抽棴姝ラ锛屽洜涓哄叡浜唴瀛樺彲鑳藉凡鎹熷潖 + * + * 鍙傛暟: + * SIGNAL_ARGS: 淇″彿澶勭悊绋嬪簭鐨勫弬鏁板垪琛紝鎻愪緵鍏充簬瑙﹀彂淇″彿鐨勪笂涓嬫枃淇℃伅 + * + * 杩斿洖鍊: + * 鏃 + */ static void startupproc_quickdie(SIGNAL_ARGS) { - gs_signal_setmask(&t_thrd.libpq_cxt.BlockSig, NULL); + gs_signal_setmask(&t_thrd.libpq_cxt.BlockSig, NULL); // 瑙i櫎瀵逛俊鍙风殑闃诲 /* * We DO NOT want to run proc_exit() callbacks -- we're here because @@ -72,7 +84,7 @@ static void startupproc_quickdie(SIGNAL_ARGS) * things by calling exit() directly, we have to reset the callbacks * explicitly to make this work as intended. */ - on_exit_reset(); + on_exit_reset(); // 閲嶇疆杩涚▼閫鍑烘椂鐨勫洖璋冨嚱鏁 /* * Note we do exit(2) not exit(0). This is to force the postmaster into a @@ -82,40 +94,62 @@ static void startupproc_quickdie(SIGNAL_ARGS) * should ensure the postmaster sees this as a crash, too, but no harm in * being doubly sure.) */ - exit(2); + exit(2); // 浠ョ姸鎬佺爜 2 閫鍑鸿繘绋嬶紝琛ㄧず杩涚▼寮傚父閫鍑 } /* SIGUSR1: let latch facility handle the signal */ +/* + *鍔熻兘锛 澶勭悊 SIGUSR1 淇″彿锛岀敤浜庡敜閱掕繘绋嬩腑鐨勭瓑寰呮搷浣 + * + * 鍙傛暟: + * SIGNAL_ARGS: 淇″彿澶勭悊绋嬪簭鐨勫弬鏁板垪琛紝鎻愪緵鍏充簬瑙﹀彂淇″彿鐨勪笂涓嬫枃淇℃伅 + * + * 杩斿洖鍊: + * 鏃 + */ static void StartupProcSigUsr1Handler(SIGNAL_ARGS) { - int save_errno = errno; + int save_errno = errno; // 淇濆瓨褰撳墠鐨勯敊璇爜 - latch_sigusr1_handler(); + latch_sigusr1_handler(); // 澶勭悊 SIGUSR1 淇″彿 - errno = save_errno; + errno = save_errno; // 鎭㈠涔嬪墠淇濆瓨鐨勯敊璇爜 } -#ifndef ENABLE_MULTIPLE_NODES +#ifndef ENABLE_MULTIPLE_NODES // 鍙湪鏈惎鐢ㄥ鑺傜偣鍔熻兘鏃舵墠浼氱紪璇戝拰鎵ц浠ヤ笅浠g爜鍧 +/* + * 鍔熻兘锛氱瓑寰 DCF 锛堝垎甯冨紡浜嬪姟涓鑷存ф鏋讹級鏃ュ織鐨勫簲鐢 + * 濡傛灉鎴愬姛搴旂敤鎵鏈 DCF 鏃ュ織锛屽皢鍙栨秷褰撳墠绾跨▼鐨 DCF 棰嗗鑰呮爣璁帮紝骞剁敓鎴愮浉搴旂殑鏃ュ織娑堟伅 + * 濡傛灉搴旂敤澶辫触锛屽皢鐢熸垚涓涓嚧鍛介敊璇秷鎭 + * + * 鍙傛暟锛氭棤 + * + * 杩斿洖鍊硷細鏃 + */ static void WaitApplyAllDCFLog(void) { unsigned int all_applied = 0; // Check if walreceiver has written all DCF log into xlog + // 妫鏌ユ槸鍚﹀惎鐢ㄤ簡 DCF锛屼互鍙婂綋鍓嶇嚎绋嬫槸鍚﹁鏍囪涓 DCF 棰嗗鑰 if (g_instance.attr.attr_storage.dcf_attr.enable_dcf && t_thrd.dcf_cxt.dcfCtxInfo->dcf_to_be_leader) { - ereport(LOG, (errmsg("Begin to wait read xlog from DCF!"))); + ereport(LOG, (errmsg("Begin to wait read xlog from DCF!"))); // 鐢熸垚鏃ュ織娑堟伅锛圠OG绾у埆锛 琛ㄧず寮濮嬬瓑寰呬粠 DCF 璇诲彇 xlog /* Check if all the dcf log has been applied to xlog every 10 milliseconds. */ - int ret = 0; + int ret = 0; // 鐢ㄤ簬瀛樺偍鍚庣画鍑芥暟璋冪敤鐨勮繑鍥炲 + // 妫鏌ユ槸鍚︽墍鏈 DCF 鏃ュ織閮藉凡搴旂敤鍒 xlog while ((ret = dcf_check_if_all_logs_applied(1, &all_applied)) == 0) { + // 濡傛灉宸插簲鐢ㄧ殑鏃ュ織鏁伴噺涓嶇瓑浜0锛岃〃绀烘墍鏈 DCF 鏃ュ織閮藉凡缁忚搴旂敤 if (all_applied != 0) { - t_thrd.dcf_cxt.dcfCtxInfo->dcf_to_be_leader = false; - ereport(LOG, (errmsg("All DCF log has been applied!"))); - return; + t_thrd.dcf_cxt.dcfCtxInfo->dcf_to_be_leader = false; // 褰撳墠绾跨▼涓嶅啀琚爣璁颁负 DCF 棰嗗鑰 + ereport(LOG, (errmsg("All DCF log has been applied!"))); // 鐢熸垚鏃ュ織娑堟伅锛圠OG绾у埆锛夛紝琛ㄧず鎵鏈 DCF 鏃ュ織閮藉凡缁忚搴旂敤 + return; // 鍑芥暟杩斿洖锛岀粨鏉熷惊鐜 } - pg_usleep(10000L); /* 10 milliseconds */ + pg_usleep(10000L); /* 10 milliseconds */ // 濡傛灉鏈簲鐢ㄧ殑鏃ュ織鏁伴噺浠嶇劧涓0锛屽嚱鏁颁細浼戠湢10姣缁х画寰幆 } + // 濡傛灉ret涓嶄负0锛岃〃绀哄簲鐢 DCF 鏃ュ織澶辫触 if (ret) { - t_thrd.dcf_cxt.dcfCtxInfo->dcf_to_be_leader = false; - ereport(FATAL, (errmsg("Apply all DCF log failed for dcf return false!"))); + t_thrd.dcf_cxt.dcfCtxInfo->dcf_to_be_leader = false; // 褰撳墠绾跨▼涓嶅啀琚爣璁颁负 DCF 棰嗗鑰 + ereport(FATAL, (errmsg("Apply all DCF log failed for dcf return false!"))); // 鐢熸垚涓涓嚧鍛介敊璇棩蹇楁秷鎭紙FATAL绾у埆锛夛紝琛ㄧず DCF 鏃ュ織鐨勫簲鐢ㄥけ璐 } } } @@ -128,158 +162,243 @@ static void WaitApplyAllDCFLog(void) * When the SIGUSR2 is receiverd, then check the reason of the SIGUSR2 * and do the corresponding operations */ +/* + * 鍔熻兘锛氬鐞 SIGUSR2 淇″彿锛屾牴鎹笉鍚岀殑閫氱煡淇″彿閲囧彇鐩稿簲鐨勬搷浣 + * + * 鍙傛暟: + * SIGNAL_ARGS: 淇″彿澶勭悊绋嬪簭鐨勫弬鏁板垪琛紝鎻愪緵鍏充簬瑙﹀彂淇″彿鐨勪笂涓嬫枃淇℃伅 + * + * 杩斿洖鍊: + * 鏃 + */ static void StartupProcSigusr2Handler(SIGNAL_ARGS) { - int save_errno = errno; - + int save_errno = errno; // 淇濆瓨褰撳墠鐨勯敊璇爜 + // 妫鏌ュ彉閲 dummyStandbyMode 鏄惁涓虹湡锛屽嵆妫鏌ユ槸鍚﹀浜庤櫄鎷熷鐢ㄦā寮 if (dummyStandbyMode) - return; + return; // 濡傛灉鏄紝杩斿洖 - if (CheckNotifySignal(NOTIFY_PRIMARY)) { - t_thrd.startup_cxt.primary_triggered = true; - } else if (CheckNotifySignal(NOTIFY_STANDBY)) { - t_thrd.startup_cxt.standby_triggered = true; + if (CheckNotifySignal(NOTIFY_PRIMARY)) { // 妫鏌ユ槸鍚︽敹鍒 NOTIFY_PRIMARY 閫氱煡淇″彿 + t_thrd.startup_cxt.primary_triggered = true; // 琛ㄧず涓绘湇鍔″櫒瑙﹀彂浜嗘煇涓簨浠 + } else if (CheckNotifySignal(NOTIFY_STANDBY)) { // 妫鏌ユ槸鍚︽敹鍒 NOTIFY_STANDBY 閫氱煡淇″彿 + t_thrd.startup_cxt.standby_triggered = true; // 琛ㄧず澶囩敤鏈嶅姟鍣ㄨЕ鍙戜簡鏌愪釜浜嬩欢 + // 妫鏌ユ晠闅滃垏鎹㈡槸鍚﹀凡缁忚Е鍙戜互鍙婂綋鍓嶆湇鍔″櫒鏄惁鏄珮鍙敤鎬у拰鐏鹃毦鎭㈠锛圚ADR锛夌郴缁熺殑涓诲妯″紡涓殑涓绘湇鍔″櫒 if (t_thrd.startup_cxt.failover_triggered && t_thrd.postmaster_cxt.HaShmData->is_hadr_main_standby) { - t_thrd.startup_cxt.failover_triggered = false; + t_thrd.startup_cxt.failover_triggered = false; // 閲嶇疆鏁呴殰鍒囨崲瑙﹀彂鏍囧織锛岄伩鍏嶅娆¤Е鍙戞晠闅滃垏鎹㈤昏緫锛岀‘淇濆彧鏈変竴涓湇鍔″櫒琚変负涓绘湇鍔″櫒 } - } else if (CheckNotifySignal(NOTIFY_CASCADE_STANDBY)) { - t_thrd.startup_cxt.standby_triggered = true; - } else if (CheckNotifySignal(NOTIFY_FAILOVER)) { - t_thrd.startup_cxt.failover_triggered = true; -#ifndef ENABLE_MULTIPLE_NODES - WaitApplyAllDCFLog(); + } else if (CheckNotifySignal(NOTIFY_CASCADE_STANDBY)) { // 妫鏌ユ槸鍚︽敹鍒 NOTIFY_CASCADE_STANDBY 閫氱煡淇″彿 + t_thrd.startup_cxt.standby_triggered = true; // 琛ㄧず绾ц仈澶囩敤鏈嶅姟鍣ㄨЕ鍙戜簡鏌愪釜浜嬩欢 + } else if (CheckNotifySignal(NOTIFY_FAILOVER)) { // 妫鏌ユ槸鍚︽敹鍒 NOTIFY_FAILOVER 閫氱煡淇″彿 + t_thrd.startup_cxt.failover_triggered = true; // 琛ㄧず鍙戠敓浜嗘晠闅滃垏鎹 +#ifndef ENABLE_MULTIPLE_NODES // 濡傛灉鏈惎鐢ㄥ鑺傜偣鍔熻兘 + WaitApplyAllDCFLog(); // 绛夊緟鎵鏈 DCF 鏃ュ織鐨勫簲鐢 #endif - WakeupRecovery(); - } else if (CheckNotifySignal(NOTIFY_SWITCHOVER)) { - t_thrd.startup_cxt.switchover_triggered = true; -#ifndef ENABLE_MULTIPLE_NODES - WaitApplyAllDCFLog(); + WakeupRecovery(); // 鍞ら啋鎭㈠杩涚▼ + } else if (CheckNotifySignal(NOTIFY_SWITCHOVER)) { // 妫鏌ユ槸鍚︽敹鍒 NOTIFY_SWITCHOVER 閫氱煡淇″彿 + t_thrd.startup_cxt.switchover_triggered = true; // 琛ㄧず鍙戠敓浜嗗垏鎹 +#ifndef ENABLE_MULTIPLE_NODES // 濡傛灉鏈惎鐢ㄥ鑺傜偣鍔熻兘 + WaitApplyAllDCFLog(); // 绛夊緟鎵鏈 DCF 鏃ュ織鐨勫簲鐢 #endif - WakeupRecovery(); + WakeupRecovery(); // 鍞ら啋鎭㈠杩涚▼ } - errno = save_errno; + errno = save_errno; // 鎭㈠涔嬪墠淇濆瓨鐨勯敊璇爜 } /* SIGHUP: set flag to re-read config file at next convenient time */ +/* + *鍔熻兘锛氬鐞 SIGHUP 淇″彿锛岀敤浜庨噸鏂拌鍙栭厤缃枃浠 + * + * 鍙傛暟: + * SIGNAL_ARGS: 淇″彿澶勭悊绋嬪簭鐨勫弬鏁板垪琛紝鎻愪緵鍏充簬瑙﹀彂淇″彿鐨勪笂涓嬫枃淇℃伅 + * + * 杩斿洖鍊: + * 鏃 + */ static void StartupProcSigHupHandler(SIGNAL_ARGS) { - int save_errno = errno; + int save_errno = errno; // 淇濆瓨褰撳墠鐨勯敊璇爜 - t_thrd.startup_cxt.got_SIGHUP = true; - WakeupRecovery(); + t_thrd.startup_cxt.got_SIGHUP = true; // 琛ㄧず鎺ユ敹鍒 SIGHUP 淇″彿 + WakeupRecovery(); // 鍞ら啋鎭㈠杩涚▼ - errno = save_errno; + errno = save_errno; // 鎭㈠涔嬪墠淇濆瓨鐨勯敊璇爜 } /* SIGINT: set flag to check repair page */ +/* + *鍔熻兘锛氬鐞 SIGINT 淇″彿 璇锋眰杩涚▼缁堟 + * + * 鍙傛暟: + * SIGNAL_ARGS: 淇″彿澶勭悊绋嬪簭鐨勫弬鏁板垪琛紝鎻愪緵鍏充簬瑙﹀彂淇″彿鐨勪笂涓嬫枃淇℃伅 + * + * 杩斿洖鍊: + * 鏃 + */ static void StartupProcSigIntHandler(SIGNAL_ARGS) { - int save_errno = errno; + int save_errno = errno; // 淇濆瓨褰撳墠鐨勯敊璇爜 - t_thrd.startup_cxt.check_repair = true; + t_thrd.startup_cxt.check_repair = true; // 琛ㄧず鎺ユ敹鍒 SIGINT 淇″彿鍚庨渶瑕佽繘琛屾鏌ヤ慨澶嶆搷浣 - errno = save_errno; + errno = save_errno; // 鎭㈠涔嬪墠淇濆瓨鐨勯敊璇爜 } /* SIGTERM: set flag to abort redo and exit */ +/* + *鍔熻兘锛氬鐞 SIGTERM 淇″彿锛岀敤浜庢甯搁鍑 + * + * 鍙傛暟: + * SIGNAL_ARGS: 淇″彿澶勭悊绋嬪簭鐨勫弬鏁板垪琛紝鎻愪緵鍏充簬瑙﹀彂淇″彿鐨勪笂涓嬫枃淇℃伅 + * + * 杩斿洖鍊: + * 鏃 + */ static void StartupProcShutdownHandler(SIGNAL_ARGS) { - int save_errno = errno; + int save_errno = errno; // 淇濆瓨褰撳墠鐨勯敊璇爜 - if (t_thrd.startup_cxt.in_restore_command) - proc_exit(1); + if (t_thrd.startup_cxt.in_restore_command) // 妫鏌ュ綋鍓嶆槸鍚︽鍦ㄦ墽琛屾仮澶嶅懡浠 + proc_exit(1); // 鍚姩杩涚▼閫鍑 else - t_thrd.startup_cxt.shutdown_requested = true; + t_thrd.startup_cxt.shutdown_requested = true; // 琛ㄧず宸茬粡鏀跺埌浜嗗叧闂姹 - WakeupRecovery(); + WakeupRecovery(); // 鍞ら啋鎭㈠杩涚▼ - errno = save_errno; + errno = save_errno; // 鎭㈠涔嬪墠淇濆瓨鐨勯敊璇爜 } +/* + * 鍔熻兘锛氬鐞嗗惎鍔ㄨ繃绋嬩腑鐨勯〉闈慨澶 + * + * 鍙傛暟锛 + * key锛氫竴涓〃绀轰慨澶嶅潡鐨勫叧閿俊鎭殑缁撴瀯鎴栨爣璇 + * pblk锛氫竴涓〃绀虹墿鐞嗗潡鐨勬爣璇嗘垨淇℃伅 + * + * 杩斿洖鍊硷細鏃 + */ void HandleStartupPageRepair(RepairBlockKey key, XLogPhyBlock pblk) { - XLogReaderState *record = g_instance.startup_cxt.current_record; + XLogReaderState *record = g_instance.startup_cxt.current_record; // 鐢ㄤ簬瑙f瀽鍜屽鐞 WAL璁板綍锛岃幏鍙栧綋鍓嶆鍦ㄥ鐞嗙殑 WAL 璁板綍 + // 璁板綍鍧忓潡淇℃伅骞跺皢鍏舵帹閫佸埌杩滅▼浣嶇疆 + // 鍙傛暟锛歳ecord-褰撳墠鐨 WAL 璁板綍锛沰ey-淇鍧楃殑鍏抽敭淇℃伅锛汣RC_CHECK_FAIL-琛ㄧず CRC 鏍¢獙澶辫触 + // InvalidXLogRecPtr-琛ㄧず鏃犳晥鐨 XLog 璁板綍浣嶇疆锛沺blk-琛ㄧず鐗╃悊鍧楃殑鏍囪瘑鎴栦俊鎭 parallel_recovery::RecordBadBlockAndPushToRemote(record, key, CRC_CHECK_FAIL, InvalidXLogRecPtr, pblk); return; } /* Handle SIGHUP and SIGTERM signals of startup process */ +/* + * 鍔熻兘锛氬鐞嗗惎鍔ㄨ繘绋嬫帴鏀跺埌鐨凷IGHUP 鍜 SIGTERM 淇″彿 + * -澶勭悊 SIGHUP 淇″彿锛岄噸鏂拌鍙栭厤缃枃浠 + * -鎵ц鍧楁鏌ュ拰淇鎿嶄綔 + * -澶勭悊鍏抽棴璇锋眰锛屼絾閬垮厤鍦ㄦ櫤鑳藉叧闂姸鎬佷笅閫鍑 + * -绱фラ鍑哄惎鍔ㄨ繘绋嬶紙褰撲笉鏄 Postmaster 杩涚▼鎴 Postmaster 杩涚▼宸茬粡缁堟锛 + * + * 鍙傛暟锛氭棤 + * + * 杩斿洖鍊硷細鏃 + */ void HandleStartupProcInterrupts(void) { /* * Check if we were requested to re-read config file. */ - if (t_thrd.startup_cxt.got_SIGHUP) { + if (t_thrd.startup_cxt.got_SIGHUP) { // 妫鏌ユ槸鍚︽敹鍒 SIGHUP 淇″彿 t_thrd.startup_cxt.got_SIGHUP = false; - ProcessConfigFile(PGC_SIGHUP); + ProcessConfigFile(PGC_SIGHUP); // 閲嶆柊璇诲彇閰嶇疆鏂囦欢 } - if (t_thrd.startup_cxt.check_repair) { + if (t_thrd.startup_cxt.check_repair) { // 妫鏌ユ槸鍚﹂渶瑕佹墽琛屽潡妫鏌ュ拰淇鎿嶄綔 + // 濡傛灉褰撳墠涓嶅浜庢瀬绔噸鍋氫笖涓嶆槸骞惰閲嶅仛 if (!IsExtremeRedo() && !IsParallelRedo()) { - parallel_recovery::SeqCheckRemoteReadAndRepairPage(); + parallel_recovery::SeqCheckRemoteReadAndRepairPage(); // 鎵ц鍧楁鏌ュ拰淇鎿嶄綔 } - t_thrd.startup_cxt.check_repair = false; + t_thrd.startup_cxt.check_repair = false; // 琛ㄧず妫鏌ュ拰淇鎿嶄綔宸插畬鎴 } /* * Check if we were requested to exit without finishing recovery. */ + // 妫鏌ユ槸鍚︽敹鍒颁簡鍏抽棴璇锋眰涓旈潪鏅鸿兘鍏抽棴锛堥伩鍏嶅湪鏅鸿兘鍏抽棴杩囩▼涓己鍒堕鍑猴級 if (t_thrd.startup_cxt.shutdown_requested && SmartShutdown != g_instance.status) { - proc_exit(1); + proc_exit(1); // 绱фラ鍑哄惎鍔ㄨ繘绋 } /* * Emergency bailout if postmaster has died. This is to avoid the * necessity for manual cleanup of all postmaster children. */ + // 妫鏌ユ槸鍚﹀浜 Postmaster 杩涚▼涓嬶紝浠ュ強Postmaster 鏄惁杩樺瓨娲 if (IsUnderPostmaster && !PostmasterIsAlive()) - gs_thread_exit(1); + gs_thread_exit(1); // 寮哄埗閫鍑 } +/* + * 鍔熻兘锛氬湪鍚姩杩囩▼涓噴鏀炬墍鏈夐攣 + * 閿姣佸搱甯岃〃锛堝鏋滃瓨鍦級銆 + * 鏍规嵁褰撳墠鐨勭儹澶囨ā寮忕姸鎬侊紝閲婃斁鏍囧噯閿佸拰鐢ㄦ埛绾у埆鐨勯攣銆 + * 鍦ㄩ渶瑕佹椂娓呯悊涓庨攣鐩稿叧鐨勯敊璇姸鎬併 + * + * 鍙傛暟锛 + * code銆乤rg锛氭湭琚娇鐢紝鍙兘鏄嚱鏁扮殑鍘嗗彶鍘熷洜鎴栨湭鏉ユ墿灞曟ц冭檻鑰屽瓨鍦ㄧ殑 + * + * 杩斿洖鍊硷細鏃 + */ static void StartupReleaseAllLocks(int code, Datum arg) { - Assert(t_thrd.proc != NULL); + Assert(t_thrd.proc != NULL); // 纭繚褰撳墠绾跨▼鐨 proc 缁撴瀯涓嶄负绌 - if (g_instance.startup_cxt.badPageHashTbl != NULL) { - hash_destroy(g_instance.startup_cxt.badPageHashTbl); - g_instance.startup_cxt.badPageHashTbl = NULL; + if (g_instance.startup_cxt.badPageHashTbl != NULL) { // 妫鏌ュ搱甯岃〃鏄惁涓嶄负绌 + hash_destroy(g_instance.startup_cxt.badPageHashTbl); // 閿姣佸搱甯岃〃锛岄噴鏀惧搱甯岃〃涓殑鍐呭瓨 + g_instance.startup_cxt.badPageHashTbl = NULL; // 琛ㄧず鍝堝笇琛ㄥ凡琚攢姣 } /* Do nothing if we're not in hot standby mode */ + // 妫鏌ュ綋鍓嶇嚎绋嬬殑 standbyState 鏄惁绛変簬 STANDBY_DISABLED锛屽嵆妫鏌ュ綋鍓嶆槸鍚﹀浜庣儹澶囨ā寮 if (t_thrd.xlog_cxt.standbyState == STANDBY_DISABLED) - return; + return; // 涓嶅浜庡垯杩斿洖 /* If waiting, get off wait queue (should only be needed after error) */ - LockErrorCleanup(); + LockErrorCleanup(); // 娓呯悊涓庨攣鐩稿叧鐨勯敊璇姸鎬 /* Release standard locks, including session-level if aborting */ - LockReleaseAll(DEFAULT_LOCKMETHOD, true); + LockReleaseAll(DEFAULT_LOCKMETHOD, true); // 閲婃斁鎵鏈夋爣鍑嗛攣锛堥粯璁ら攣瀹氭柟娉曪級骞剁‘淇濆畠浠湪浜嬪姟缁堟鏃惰閲婃斁锛岄槻姝㈤攣瀹氳祫婧愭硠婕忔垨姝婚攣 /* * User locks are not released by transaction end, so be sure to release * them explicitly. */ - LockReleaseAll(USER_LOCKMETHOD, true); + LockReleaseAll(USER_LOCKMETHOD, true); // 閲婃斁鎵鏈夌敤鎴风骇鍒殑閿 骞剁‘淇濆畠浠湪浜嬪姟缁撴潫鏃惰閲婃斁 } +/* + * 鍔熻兘锛氬湪闆嗙兢澶囩敤妯″紡涓嬪垹闄や竴涓枃浠跺鏋滄枃浠朵笉瀛樺湪鎴栧垹闄ゅけ璐ワ紝浼氱敓鎴愮浉搴旂殑璀﹀憡娑堟伅銆 + * + * + * 鍙傛暟锛氭棤 + * + * 杩斿洖鍊硷細鏃 + */ void DeleteDisConnFileInClusterStandby() { - if (!IS_SHARED_STORAGE_MODE) { + if (!IS_SHARED_STORAGE_MODE) { // 妫鏌ユ槸鍚﹀浜庡叡浜瓨鍌ㄦā寮 return; } - struct stat st; - if (stat(disable_conn_file, &st) < 0) { + struct stat st; // 鐢ㄤ簬瀛樺偍鏂囦欢鐘舵佷俊鎭 + if (stat(disable_conn_file, &st) < 0) { // 濡傛灉鑾峰彇鏂囦欢鐘舵佷俊鎭け璐 return; } - int ret = unlink(disable_conn_file); - if (ret < 0) { + int ret = unlink(disable_conn_file); // 灏濊瘯鍒犻櫎鎸囧畾鐨勬枃浠讹紝濡傛灉鍒犻櫎鎴愬姛锛屽垯杩斿洖鍊间负0锛屽惁鍒欎负-1 + if (ret < 0) { // 濡傛灉鍒犻櫎鏂囦欢澶辫触 + // 杈撳嚭涓鏉¤鍛婃秷鎭紝琛ㄧず鏃犳硶鍒犻櫎鏂囦欢锛屽苟鍖呭惈閿欒娑堟伅 ereport(WARNING, (errcode_for_file_access(), errmsg("cluster standby mode, could not remove file \"%s\": %m", disable_conn_file))); - } else { + } else { // 濡傛灉鍒犻櫎鏂囦欢鎴愬姛 + // 杈撳嚭涓鏉℃棩蹇楁秷鎭紝琛ㄧず鏂囦欢鍒犻櫎鎴愬姛 ereport(LOG, (errcode_for_file_access(), errmsg("removed file \"%s\" success.", disable_conn_file))); } } @@ -289,6 +408,13 @@ void DeleteDisConnFileInClusterStandby() * Startup Process main entry point * ---------------------------------- */ +/* + * 鍔熻兘锛氬惎鍔ㄨ繘绋嬬殑涓昏鍏ュ彛鍑芥暟 StartupProcessMain锛岃礋璐e惎鍔ㄨ繘绋嬬殑鍒濆鍖栧拰鎵ц + * + * 鍙傛暟锛氭棤 + * + * 杩斿洖鍊硷細鏃 + */ void StartupProcessMain(void) { /* @@ -301,77 +427,90 @@ void StartupProcessMain(void) /* * Reset some signals that are accepted by postmaster but not here */ - (void)gspqsignal(SIGHUP, StartupProcSigHupHandler); /* reload config file */ - (void)gspqsignal(SIGINT, StartupProcSigIntHandler); /* check repair page and file */ - (void)gspqsignal(SIGTERM, StartupProcShutdownHandler); /* request shutdown */ + (void)gspqsignal(SIGHUP, StartupProcSigHupHandler); /* reload config file */ // 閲嶆柊鍔犺浇閰嶇疆鏂囦欢 + (void)gspqsignal(SIGINT, StartupProcSigIntHandler); /* check repair page and file */ // 妫鏌ヤ慨澶嶉〉鍜屾枃浠 + (void)gspqsignal(SIGTERM, StartupProcShutdownHandler); /* request shutdown */ // 璇锋眰鍏抽棴 (void)gspqsignal(SIGQUIT, startupproc_quickdie); /* hard crash time */ - if (g_instance.attr.attr_storage.EnableHotStandby) - (void)gspqsignal(SIGALRM, handle_standby_sig_alarm); /* ignored unless + if (g_instance.attr.attr_storage.EnableHotStandby) // 妫鏌ユ槸鍚﹀惎鐢ㄤ簡鐑妯″紡 + (void)gspqsignal(SIGALRM, handle_standby_sig_alarm); /* ignored unless // 濡傛灉鍚敤浜嗙儹澶囨ā寮忥紝璁剧疆SIGALRM鐨勪俊鍙峰鐞嗗嚱鏁 * InHotStandby */ else - (void)gspqsignal(SIGALRM, SIG_IGN); + (void)gspqsignal(SIGALRM, SIG_IGN); // 鍚﹀垯蹇界暐璇ヤ俊鍙 - (void)gspqsignal(SIGPIPE, SIG_IGN); - (void)gspqsignal(SIGUSR1, StartupProcSigUsr1Handler); + (void)gspqsignal(SIGPIPE, SIG_IGN); // 蹇界暐SIGPIPE + (void)gspqsignal(SIGUSR1, StartupProcSigUsr1Handler); // 璁剧疆淇″彿澶勭悊鍑芥暟 (void)gspqsignal(SIGUSR2, StartupProcSigusr2Handler); /* * Reset some signals that are accepted by postmaster but not here */ + // 璁剧疆淇″彿澶勭悊鍑芥暟涓洪粯璁よ涓 (void)gspqsignal(SIGCHLD, SIG_DFL); (void)gspqsignal(SIGTTIN, SIG_DFL); (void)gspqsignal(SIGTTOU, SIG_DFL); (void)gspqsignal(SIGCONT, SIG_DFL); (void)gspqsignal(SIGWINCH, SIG_DFL); + // 娉ㄥ唽鍥炶皟鍑芥暟锛屼互澶勭悊閲嶅仛鏈熼棿鐨勪腑鏂拰椤甸潰淇鎿嶄綔 (void)RegisterRedoInterruptCallBack(HandleStartupProcInterrupts); (void)RegisterRedoPageRepairCallBack(HandleStartupPageRepair); /* * Unblock signals (they were blocked when the postmaster forked us) */ - gs_signal_setmask(&t_thrd.libpq_cxt.UnBlockSig, NULL); - (void)gs_signal_unblock_sigusr2(); + gs_signal_setmask(&t_thrd.libpq_cxt.UnBlockSig, NULL); // 瑙i櫎淇″彿鐨勯樆濉炵姸鎬侊紝鍏佽淇″彿浼犻 + (void)gs_signal_unblock_sigusr2(); // 瑙i櫎瀵 SIGUSR2 淇″彿鐨勯樆濉 + // 鍒涘缓浜嗚祫婧愭嫢鏈夎咃紝鐢ㄤ簬璺熻釜鍜岀鐞嗚祫婧愮殑鍒嗛厤鍜岄噴鏀撅紝纭繚鍦ㄥ惎鍔ㄨ繘绋嬫墽琛屾湡闂村璧勬簮鐨勬纭鐞 t_thrd.utils_cxt.CurrentResourceOwner = ResourceOwnerCreate(NULL, "StartupXLOG", THREAD_GET_MEM_CXT_GROUP(MEMORY_CONTEXT_STORAGE)); - SetStaticConnNum(); - pgstat_report_appname("Startup"); - pgstat_report_activity(STATE_IDLE, NULL); + SetStaticConnNum(); // 璁剧疆闈欐佽繛鎺ユ暟锛岀敤浜庨厤缃惎鍔ㄨ繘绋嬬殑杩炴帴姹犲弬鏁 + pgstat_report_appname("Startup"); // 璁剧疆杩涚▼鐨勫簲鐢ㄧ▼搴忓悕绉 + pgstat_report_activity(STATE_IDLE, NULL); // 璁剧疆杩涚▼鐨勬椿鍔ㄧ姸鎬佷负 "STATE_IDLE"锛岃〃绀鸿繘绋嬪綋鍓嶅浜庣┖闂茬姸鎬 - if (dummyStandbyMode) { - StartupDummyStandby(); + if (dummyStandbyMode) { // 妫鏌ユ槸鍚﹀浜庤櫄鎷熷鐢ㄦā寮 + StartupDummyStandby(); // 濡傛灉澶勪簬铏氭嫙澶囩敤妯″紡锛屾墽琛岃櫄鎷熷鐢ㄦā寮忎笅鐨勬搷浣 } else { - on_shmem_exit(StartupReleaseAllLocks, 0); + on_shmem_exit(StartupReleaseAllLocks, 0); // 娉ㄥ唽涓涓湪鍏变韩鍐呭瓨閫鍑烘椂鎵ц鐨勫洖璋冨嚱鏁帮紝鐢ㄤ簬閲婃斁鎵鏈夐攣 -#ifdef ENABLE_MOT +#ifdef ENABLE_MOT // 妫鏌ユ槸鍚﹀惎鐢ㄤ簡 MOT 瀛樺偍寮曟搸 +// 濡傛灉鍚敤浜 鎵ц浠ヤ笅浠g爜鍧 /* * Init MOT first */ - InitMOT(); + InitMOT(); // 杩涜 MOT 瀛樺偍寮曟搸鐨勫垵濮嬪寲 /* * MOT recovery is part of StartupXlog */ #endif - DeleteDisConnFileInClusterStandby(); - if (!dummyStandbyMode) { + DeleteDisConnFileInClusterStandby(); // 鍒犻櫎闆嗙兢澶囩敤妯″紡涓嬬殑杩炴帴鏂囦欢锛堝鏋滃瓨鍦級 + if (!dummyStandbyMode) { // 妫鏌ユ槸鍚﹀浜庤櫄鎷熷鐢ㄦā寮 + // 濡傛灉涓嶆槸 NULL锛岃〃绀鸿琛ㄥ凡缁忓瓨鍦紝鍙戠敓閿欒銆傜‘淇濆湪鍒涘缓涔嬪墠娌℃湁閬楃暀鐨勬暟鎹粨鏋 Assert(g_instance.startup_cxt.badPageHashTbl == NULL); + // 鍒涘缓涓涓潖鍧楀搱甯岃〃锛岀敤浜庤褰曞潖鍧楃殑淇℃伅锛屽湪鎭㈠杩囩▼涓窡韪潖鍧楃殑鐘舵 g_instance.startup_cxt.badPageHashTbl = parallel_recovery::BadBlockHashTblCreate(); } - StartupXLOG(); + StartupXLOG(); // 澶勭悊浜嬪姟鏃ュ織鍜屾墽琛屾暟鎹簱鎭㈠ } /* * Exit normally. Exit code 0 tells postmaster that we completed recovery * successfully. */ - proc_exit(0); + proc_exit(0); // 姝e父閫鍑鸿繘绋嬨傞鍑虹爜涓0琛ㄧず鎴愬姛瀹屾垚鎭㈠杩囩▼锛岄氱煡涓昏繘绋嬫仮澶嶆垚鍔 } +/* + * 鍔熻兘锛氬湪鎵ц鎭㈠鍛戒护涔嬪墠杩涜涓浜涢澶勭悊鎿嶄綔 + * + * 鍙傛暟锛氭棤 + * + * 杩斿洖鍊硷細鏃 + */ void PreRestoreCommand(void) { /* @@ -380,37 +519,53 @@ void PreRestoreCommand(void) * Check if we had already received the signal, so that we don't miss a * shutdown request received just before this. */ - t_thrd.startup_cxt.in_restore_command = true; + t_thrd.startup_cxt.in_restore_command = true; // 琛ㄧず鍚姩杩涚▼姝e湪鎵ц鎭㈠鍛戒护 - if (t_thrd.startup_cxt.shutdown_requested) { - proc_exit(1); + if (t_thrd.startup_cxt.shutdown_requested) { // 妫鏌ユ槸鍚︽敹鍒板叧闂姹傦紝 浠ュ厤閿欒繃鍦ㄦ墽琛屾仮澶嶅懡浠ゅ墠绔嬪嵆閫鍑虹殑鏈轰細 + proc_exit(1); // 濡傛灉鏀跺埌鍏抽棴璇锋眰锛岄鍑 } } void PostRestoreCommand(void) { - t_thrd.startup_cxt.in_restore_command = false; + t_thrd.startup_cxt.in_restore_command = false; // 閫鍑烘仮澶嶅懡浠ょ姸鎬 } +/* + * 鍔熻兘锛氭鏌ユ槸鍚﹁Е鍙戜簡鏁呴殰鍒囨崲淇″彿 + * + * 鍙傛暟锛氭棤 + * + * 杩斿洖鍊硷細bool绫诲瀷 锛屽鏋滆Е鍙戜簡鍒欒繑鍥 true锛屽惁鍒欒繑鍥 false銆 + */ bool IsFailoverTriggered(void) { - if (AmStartupProcess()) { - return t_thrd.startup_cxt.failover_triggered; + if (AmStartupProcess()) { // 妫鏌ュ綋鍓嶆槸鍚﹀浜庡惎鍔ㄨ繘绋 + return t_thrd.startup_cxt.failover_triggered; // 杩斿洖锛岃〃绀烘晠闅滃垏鎹俊鍙峰凡瑙﹀彂 } else { - uint32 tgigger = pg_atomic_read_u32(&(extreme_rto::g_startupTriggerState)); - if (tgigger == (uint32)extreme_rto::TRIGGER_FAILOVER) { + uint32 tgigger = pg_atomic_read_u32(&(extreme_rto::g_startupTriggerState)); // 閫氳繃鍘熷瓙鎿嶄綔璇诲彇鍏ㄥ眬鍙橀噺锛屼互纭繚绾跨▼瀹夊叏 + // 妫鏌ヨ鍙栫殑鍊兼槸鍚︾瓑浜 extreme_rto::TRIGGER_FAILOVER锛屽鏋滅浉绛夛紝琛ㄧず鏁呴殰鍒囨崲淇″彿宸茶Е鍙 + if (tgigger == (uint32)extreme_rto::TRIGGER_FAILOVER) { return true; } } return false; } +/* + * 鍔熻兘锛氭鏌ユ槸鍚﹁Е鍙戜簡鍒囨崲淇″彿 + * + * 鍙傛暟锛氭棤 + * + * 杩斿洖鍊硷細bool绫诲瀷锛屽鏋滆Е鍙戜簡鍒欒繑鍥 true锛屽惁鍒欒繑鍥 false銆 + */ bool IsSwitchoverTriggered(void) { - if (AmStartupProcess()) { - return t_thrd.startup_cxt.switchover_triggered; + if (AmStartupProcess()) { // 妫鏌ュ綋鍓嶆槸鍚﹀浜庡惎鍔ㄨ繘绋 + return t_thrd.startup_cxt.switchover_triggered; // 杩斿洖锛岃〃绀哄垏鎹俊鍙峰凡瑙﹀彂 } else { - uint32 tgigger = pg_atomic_read_u32(&(extreme_rto::g_startupTriggerState)); + uint32 tgigger = pg_atomic_read_u32(&(extreme_rto::g_startupTriggerState)); // 閫氳繃鍘熷瓙鎿嶄綔璇诲彇鍏ㄥ眬鍙橀噺锛屼互纭繚绾跨▼瀹夊叏 + // 妫鏌ヨ鍙栫殑鍊兼槸鍚︾瓑浜 extreme_rto::TRIGGER_SWITCHOVER锛屽鏋滅浉绛夛紝琛ㄧず鍒囨崲淇″彿宸茶Е鍙 if (tgigger == (uint32)extreme_rto::TRIGGER_SWITCHOVER) { return true; } @@ -418,12 +573,20 @@ bool IsSwitchoverTriggered(void) return false; } +/* + * 鍔熻兘锛氭鏌ユ槸鍚﹁Е鍙戜簡涓昏妭鐐逛俊鍙 + * + * 鍙傛暟锛氭棤 + * + * 杩斿洖鍊硷細bool绫诲瀷锛屽鏋滆Е鍙戜簡鍒欒繑鍥 true锛屽惁鍒欒繑鍥 false銆 + */ bool IsPrimaryTriggered(void) { - if (AmStartupProcess()) { - return t_thrd.startup_cxt.primary_triggered; + if (AmStartupProcess()) { // 妫鏌ュ綋鍓嶆槸鍚﹀浜庡惎鍔ㄨ繘绋 + return t_thrd.startup_cxt.primary_triggered; // 杩斿洖锛岃〃绀轰富鑺傜偣淇″彿宸茶Е鍙 } else { - uint32 tgigger = pg_atomic_read_u32(&(extreme_rto::g_startupTriggerState)); + uint32 tgigger = pg_atomic_read_u32(&(extreme_rto::g_startupTriggerState)); // 閫氳繃鍘熷瓙鎿嶄綔璇诲彇鍏ㄥ眬鍙橀噺锛屼互纭繚绾跨▼瀹夊叏 + // 妫鏌ヨ鍙栫殑鍊兼槸鍚︾瓑浜 extreme_rto::TRIGGER_PRIMARY锛屽鏋滅浉绛夛紝琛ㄧず涓昏妭鐐逛俊鍙峰凡瑙﹀彂 if (tgigger == (uint32)extreme_rto::TRIGGER_PRIMARY) { return true; } @@ -431,12 +594,20 @@ bool IsPrimaryTriggered(void) return false; } +/* + * 鍔熻兘锛氭鏌ユ槸鍚﹁Е鍙戜簡澶囩敤鑺傜偣淇″彿 + * + * 鍙傛暟锛氭棤 + * + * 杩斿洖鍊硷細bool绫诲瀷锛屽鏋滆Е鍙戜簡鍒欒繑鍥 true锛屽惁鍒欒繑鍥 false銆 + */ bool IsStandbyTriggered(void) { - if (AmStartupProcess()) { - return t_thrd.startup_cxt.standby_triggered; + if (AmStartupProcess()) { // 妫鏌ュ綋鍓嶆槸鍚﹀浜庡惎鍔ㄨ繘绋 + return t_thrd.startup_cxt.standby_triggered; // 杩斿洖锛岃〃绀哄鐢ㄨ妭鐐逛俊鍙峰凡瑙﹀彂 } else { - uint32 tgigger = pg_atomic_read_u32(&(extreme_rto::g_startupTriggerState)); + uint32 tgigger = pg_atomic_read_u32(&(extreme_rto::g_startupTriggerState)); // 閫氳繃鍘熷瓙鎿嶄綔璇诲彇鍏ㄥ眬鍙橀噺锛屼互纭繚绾跨▼瀹夊叏 + // 妫鏌ヨ鍙栫殑鍊兼槸鍚︾瓑浜 extreme_rto::TRIGGER_STADNBY锛屽鏋滅浉绛夛紝琛ㄧず澶囩敤鑺傜偣淇″彿宸茶Е鍙 if (tgigger == (uint32)extreme_rto::TRIGGER_STADNBY) { return true; } @@ -444,44 +615,92 @@ bool IsStandbyTriggered(void) return false; } +// 閲嶇疆瑙﹀彂淇″彿鐨勭姸鎬佸彉閲 + +/* + * 鍔熻兘锛氶噸缃晠闅滃垏鎹俊鍙疯Е鍙戠姸鎬 + * + * 鍙傛暟锛氭棤 + * + * 杩斿洖鍊硷細鏃 + */ void ResetFailoverTriggered(void) { - t_thrd.startup_cxt.failover_triggered = false; + t_thrd.startup_cxt.failover_triggered = false; // 琛ㄧず鏁呴殰鍒囨崲淇″彿鏈Е鍙 } +/* + * 鍔熻兘锛氶噸缃垏鎹俊鍙疯Е鍙戠姸鎬 + * + * 鍙傛暟锛氭棤 + * + * 杩斿洖鍊硷細鏃 + */ void ResetSwitchoverTriggered(void) { - t_thrd.startup_cxt.switchover_triggered = false; + t_thrd.startup_cxt.switchover_triggered = false; // 琛ㄧず鍒囨崲淇″彿鏈Е鍙 } +/* + * 鍔熻兘锛氶噸缃富鑺傜偣淇″彿瑙﹀彂鐘舵 + * + * 鍙傛暟锛氭棤 + * + * 杩斿洖鍊硷細鏃 + */ void ResetPrimaryTriggered(void) { - t_thrd.startup_cxt.primary_triggered = false; + t_thrd.startup_cxt.primary_triggered = false; // 琛ㄧず涓昏妭鐐逛俊鍙锋湭瑙﹀彂 } +/* + * 鍔熻兘锛氶噸缃鐢ㄨ妭鐐逛俊鍙疯Е鍙戠姸鎬 + * + * 鍙傛暟锛氭棤 + * + * 杩斿洖鍊硷細鏃 + */ void ResetStandbyTriggered(void) { - t_thrd.startup_cxt.standby_triggered = false; + t_thrd.startup_cxt.standby_triggered = false; // 琛ㄧず澶囩敤鑺傜偣淇″彿鏈Е鍙 } +// 绠$悊鍏变韩鍐呭瓨涓殑閫氱煡淇″彿鏁版嵁 + +/* + * 鍔熻兘锛氳绠楅氱煡淇″彿鏁版嵁缁撴瀯鐨勫ぇ灏 + * + * 鍙傛暟锛氭棤 + * + * 杩斿洖鍊硷細Size绫诲瀷锛岃繑鍥為氱煡淇″彿鏁版嵁缁撴瀯鐨勫ぇ灏 + */ Size NotifySignalShmemSize(void) { Size size = 0; - size = add_size(size, sizeof(NotifySignalData)); + size = add_size(size, sizeof(NotifySignalData)); // 鑾峰彇閫氱煡淇″彿鏁版嵁缁撴瀯 NotifySignalData 鐨勫ぇ灏忥紝骞舵坊鍔犲埌 size 鍙橀噺涓 return size; } +/* + * 鍔熻兘锛氬垵濮嬪寲閫氱煡淇″彿鏁版嵁缁撴瀯鐨勫叡浜唴瀛 + * + * 鍙傛暟锛氭棤 + * + * 杩斿洖鍊硷細鏃 + */ void NotifySignalShmemInit(void) { - bool found = false; - errno_t rc = 0; + bool found = false; // 鐢ㄤ簬琛ㄧず鍦ㄥ叡浜唴瀛樹腑鏄惁宸茬粡鎵惧埌閫氱煡淇″彿鏁版嵁缁撴瀯 + errno_t rc = 0; // 鐢ㄤ簬澶勭悊閿欒鐮 + // 鑾峰彇閫氱煡淇″彿鏁版嵁缁撴瀯鐨勫叡浜唴瀛樻寚閽堬紝鑾峰彇鎴愬姛 found->true t_thrd.startup_cxt.NotifySigState = (NotifySignalData*)ShmemInitStruct("NotifySignalState", NotifySignalShmemSize(), &found); - if (!found) { + if (!found) { // 濡傛灉鍦ㄥ叡浜唴瀛樹腑娌℃湁鎵惧埌閫氱煡淇″彿鏁版嵁缁撴瀯 + // 灏嗛氱煡淇″彿鏁版嵁缁撴瀯鐨勫唴瀛樺尯鍩熷垵濮嬪寲涓0锛屼互纭繚鏁版嵁鐨勫垵濮嬬姸鎬佹槸娓呴浂鐨 rc = memset_s(t_thrd.startup_cxt.NotifySigState, NotifySignalShmemSize(), 0, NotifySignalShmemSize()); securec_check(rc, "", ""); } @@ -490,11 +709,23 @@ void NotifySignalShmemInit(void) /* * Set the reason in notify signal share memory, and send the SIGUSR2 to the process */ + +/* + * 鍔熻兘锛氬彂閫侀氱煡淇″彿骞惰Е鍙戠浉搴旀搷浣 + * + * 鍙傛暟锛 + * ProcPid-杩涚▼鐨勭嚎绋嬫爣璇 + * + * 杩斿洖鍊硷細鏃 + */ void SendNotifySignal(NotifyReason reason, ThreadId ProcPid) { + // 鏍规嵁鎸囧畾鐨勯氱煡鍘熷洜 reason 灏嗘暟缁勪腑鐩稿簲鐨勬爣蹇楄缃负 true锛岃〃绀烘煇涓壒瀹氫簨浠舵垨鏉′欢宸茬粡鍙戠敓 t_thrd.startup_cxt.NotifySigState->NotifySignalFlags[reason] = true; + // 浣跨敤 gs_signal_send 鍑芥暟鍚戞寚瀹氱殑杩涚▼锛堢敱 ProcPid 鍙傛暟鎸囧畾锛夊彂閫 SIGUSR2 淇″彿 if (0 != gs_signal_send(ProcPid, SIGUSR2)) { + // 濡傛灉鍙戦佷俊鍙峰け璐ワ紝鐢熸垚涓涓鍛婃秷鎭紝鎸囩ず淇″彿鍙戦佸け璐 ereport(WARNING, (errmsg("Send signal failed"))); } } @@ -502,10 +733,22 @@ void SendNotifySignal(NotifyReason reason, ThreadId ProcPid) /* * Check the notify sinal share memory, and find the reason of the signal. */ + +/* + * 鍔熻兘锛氭鏌ラ氱煡淇″彿 + * + * 鍙傛暟锛 + * reason-瑕佹鏌ョ殑閫氱煡鍘 + * + * 杩斿洖鍊硷細 + * bool绫诲瀷锛屽鏋滈氱煡淇″彿宸茶Е鍙戯紝杩斿洖true锛涘惁鍒欙紝杩斿洖false + */ bool CheckNotifySignal(NotifyReason reason) { /* Careful here --- don't clear flag if we haven't seen it set */ + // 鏍规嵁鎸囧畾鐨勯氱煡鍘熷洜 reason 妫鏌ユ暟缁勪腑鐩稿簲鐨勬爣蹇楁槸鍚︿负 true锛屽嵆鏌愪釜鐗瑰畾浜嬩欢鎴栨潯浠舵槸鍚﹀凡缁忓彂鐢 if (t_thrd.startup_cxt.NotifySigState->NotifySignalFlags[reason]) { + // 閲嶆柊璁剧疆涓篺alse锛岃〃绀洪氱煡淇″彿宸茶澶勭悊 t_thrd.startup_cxt.NotifySigState->NotifySignalFlags[reason] = false; return true; } @@ -515,19 +758,29 @@ bool CheckNotifySignal(NotifyReason reason) /* * Updata the static connection numbers in HaSHmData */ + +/* + * 鍔熻兘锛氭洿鏂板搱甯屽叡浜唴瀛樻暟鎹粨鏋勪腑鐨勯潤鎬佽繛鎺ユ暟 + * + * 鍙傛暟锛氭棤 + * + * 杩斿洖鍊硷細鏃 + */ static void SetStaticConnNum(void) { - volatile HaShmemData* hashmdata = t_thrd.postmaster_cxt.HaShmData; + volatile HaShmemData* hashmdata = t_thrd.postmaster_cxt.HaShmData; // 鐢ㄤ簬瀛樺偍涓庨珮鍙敤鐩稿叧鐨勫叡浜俊鎭 int i = 0; - int repl_list_num = 0; + int repl_list_num = 0; // 鐢ㄤ簬缁熻杩炴帴鏁 - for (i = 1; i < MAX_REPLNODE_NUM; i++) { + for (i = 1; i < MAX_REPLNODE_NUM; i++) { // 寰幆妫鏌ヨ繛鎺ユ暟缁勪腑鐨勬瘡涓厓绱 + // 妫鏌 ReplConnArray 鏁扮粍涓殑鍏冪礌鏄惁涓虹┖鎸囬拡锛屽鏋滀笉涓虹┖鍒欏鍔 repl_list_num 璁℃暟鍣ㄧ殑鍊 repl_list_num = (t_thrd.postmaster_cxt.ReplConnArray[i] != NULL) ? (repl_list_num + 1) : repl_list_num; + // 妫鏌 CrossClusterReplConnArray 鏁扮粍涓殑鍏冪礌鏄惁涓虹┖鎸囬拡锛屽鏋滀笉涓虹┖鍒欏鍔 repl_list_num 璁℃暟鍣ㄧ殑鍊 repl_list_num = (t_thrd.postmaster_cxt.CrossClusterReplConnArray[i] != NULL) ? (repl_list_num + 1) : repl_list_num; - SpinLockAcquire(&hashmdata->mutex); - hashmdata->repl_list_num = repl_list_num; - SpinLockRelease(&hashmdata->mutex); + SpinLockAcquire(&hashmdata->mutex); // 鑾峰彇鍝堝笇鍏变韩鍐呭瓨鏁版嵁缁撴瀯涓殑浜掓枼閿 + hashmdata->repl_list_num = repl_list_num; // 鏇存柊璁$畻寰楀埌鐨勮繛鎺ユ暟鍊 + SpinLockRelease(&hashmdata->mutex); // 閲婃斁浜掓枼閿 } } diff --git a/src/gausskernel/process/postmaster/syslogger.cpp b/src/gausskernel/process/postmaster/syslogger.cpp index fdb776080..db06f8aa9 100644 --- a/src/gausskernel/process/postmaster/syslogger.cpp +++ b/src/gausskernel/process/postmaster/syslogger.cpp @@ -47,7 +47,7 @@ #include "utils/timestamp.h" #include "gssignal/gs_signal.h" - +// 瀹氫箟鏃ュ織杞崲鐨勫ぇ灏忛槇鍊硷紝褰撴棩蹇楁枃浠跺ぇ灏忚揪鍒版垨瓒呰繃20MB鏃讹紝灏嗚Е鍙戞棩蹇楄疆鎹 #define PROFILE_LOG_ROTATE_SIZE ((long)20 * 1024 * 1024L) /* @@ -55,6 +55,8 @@ * not have it, and interprets _IOLBF as _IOFBF (bozos). So use _IONBF * instead on Windows. */ +// 鏍规嵁鎿嶄綔绯荤粺绫诲瀷瀹氫箟浜嗙敤浜庢棩蹇楁枃浠惰緭鍑虹殑缂撳啿妯″紡銆 +// 鍦╓indows涓婁娇鐢╛IONBF缂撳啿妯″紡锛屽叾浠栨搷浣滅郴缁熶娇鐢╛IOLBF #ifdef WIN32 #define LBF_MODE _IONBF #else @@ -66,15 +68,19 @@ * left after processing can be moved down to the front and we'll still have * room to read a full chunk. */ +// 瀹氫箟鐢ㄤ簬璇诲彇鏃ュ織娑堟伅鐨勭紦鍐插尯澶у皬锛屾槸LOGPIPE_CHUNK_SIZE[绯荤粺绠¢亾鐨勬渶澶у師瀛愬啓鍏ュぇ灏忥細512]鐨勪袱鍊 #define READ_BUF_SIZE (2 * LOGPIPE_CHUNK_SIZE) +// 瀹氫箟鐢ㄤ簬淇濆瓨閿欒娑堟伅鐨勭紦鍐插尯澶у皬锛屼负1024瀛楄妭 #define ERROR_BUF_SIZE 1024 +// 瀹氫箟鐢ㄤ簬瀛樺偍鏃跺尯銆佷富鏈哄悕鍜岃妭鐐瑰悕鐨勫瓧绗︽暟缁 static char logCtlTimeZone[TZ_STRLEN_MAX + 1] = {0}; static char logCtlHostName[LOG_MAX_NODENAME_LEN] = {0}; static char logCtlNodeName[LOG_MAX_NODENAME_LEN] = {0}; /* put all LogControlData of all log types into this array */ +// 瀹氫箟鏁扮粍锛岀敤浜庡瓨鍌ㄤ笉鍚屾棩蹇楃被鍨嬬殑LogControlData缁撴瀯 static LogControlData* allLogCtl[LOG_TYPE_MAXVALID + 1] = { NULL, /* LOG_TYPE_ELOG */ NULL, /* LOG_TYPE_PLOG */ @@ -84,6 +90,7 @@ static LogControlData* allLogCtl[LOG_TYPE_MAXVALID + 1] = { }; /* exclude error log in this FOR loop */ +// 鐢ㄤ簬寰幆澶勭悊鏃ュ織鎺у埗鏁版嵁鐨勮凯浠e櫒锛屾帓闄や簡閿欒鏃ュ織绫诲瀷 #define foreach_logctl(_logctl) for (int i = LOG_TYPE_ELOG + 1; ((_logctl) = allLogCtl[i]) != NULL; ++i) /* @@ -97,18 +104,21 @@ static LogControlData* allLogCtl[LOG_TYPE_MAXVALID + 1] = { * An inactive buffer is not removed from its list, just held for re-use. * An inactive buffer has pid == 0 and undefined contents of data. */ +// 鐢ㄤ簬淇濆瓨鏉ヨ嚜涓嶅悓鍚庣杩涚▼鐨勯儴鍒嗘秷鎭 +// 鏈夋晥鍦扮鐞嗘潵鑷涓悗绔繘绋嬬殑閮ㄥ垎娑堟伅锛屽噺灏戝鐞嗘瘡涓紶鍏ユ秷鎭椂闇瑕佹鏌ョ殑鏉$洰鏁伴噺锛屼互渚垮湪閫傚綋鐨勬椂鍊欏皢瀹冧滑缁勮鎴愬畬鏁寸殑娑堟伅骞惰繘琛岃褰 typedef struct { - ThreadId pid; /* PID of source process */ - StringInfoData data; /* accumulated data, as a StringInfo */ + ThreadId pid; /* PID of source process */ // 婧愯繘绋嬬殑杩涚▼ID锛屽浜庣浉鍚岀殑婧愯繘绋婸ID锛屼笉鍏佽瀛樺湪澶氫釜缂撳啿鍖烘潯鐩 + StringInfoData data; /* accumulated data, as a StringInfo */ // 鐢ㄤ簬瀛樺偍绱Н鐨勬暟鎹 } save_buffer; /* These must be exported for EXEC_BACKEND case ... annoying */ #ifndef WIN32 #else -HANDLE syslogPipe[2] = {0, 0}; +HANDLE syslogPipe[2] = {0, 0}; // 鐢ㄤ簬鍦╓indows涓嬪鐞嗙郴缁熸棩蹇楃殑绠¢亾 #endif +// 鐢ㄤ簬澶勭悊澶氱嚎绋嬫搷浣 #ifdef WIN32 static HANDLE threadHandle = 0; static CRITICAL_SECTION sysloggerSection; @@ -118,15 +128,20 @@ static CRITICAL_SECTION sysloggerSection; * Flags set by interrupt handlers for later service in the main loop. */ /* Local subroutines */ +// 鐢ㄤ簬璁剧疆syslogger鐨勬枃浠舵弿杩扮锛屼互鎸囧畾灏嗘棩蹇楀啓鍏ョ殑鐩爣鏂囦欢鎴栫閬 static void syslogger_setfd(int fd); +// 鐢ㄤ簬澶勭悊浠庣閬撲腑璇诲彇鐨勬棩蹇楄緭鍏ワ紝灏嗗叾瀛樺偍鍦ㄧ紦鍐插尯涓 static void process_pipe_input(char* logbuffer, int* bytes_in_logbuffer); +// 鐢ㄤ簬鍒锋柊绠¢亾杈撳叆缂撳啿鍖轰腑鐨勫唴瀹 static void flush_pipe_input(char* logbuffer, int* bytes_in_logbuffer); +// 鐢ㄤ簬鎵撳紑CSV鏍煎紡鐨勬棩蹇楁枃浠讹紝浠ュ噯澶囪褰曟棩蹇楁秷鎭 static void open_csvlogfile(void); #ifdef ENABLE_UT #define static #endif +// 鐢ㄤ簬鎵撳紑鎸囧畾鐨勬棩蹇楁枃浠讹紝鎺ュ彈鏂囦欢鍚嶃佹ā寮忓拰鏄惁鍏佽閿欒浣滀负鍙傛暟 static FILE* logfile_open(const char* filename, const char* mode, bool allow_errors); #if defined(ENABLE_UT) && defined(static) @@ -134,14 +149,23 @@ static FILE* logfile_open(const char* filename, const char* mode, bool allow_err #endif #ifdef WIN32 +// 浠呭湪Windows涓嬪畾涔夛紝鐢ㄤ簬澶勭悊绠¢亾杈撳叆鐨勭嚎绋 static unsigned int __stdcall pipeThread(void* arg); #endif +// 鐢ㄤ簬鎵ц鏃ュ織鏂囦欢鐨勮疆鎹㈡搷浣滐紝鍙互鍩轰簬鏃堕棿鎴栧ぇ灏忚Е鍙 static void logfile_rotate(bool time_based_rotation, int size_rotation_for); +// 鐢ㄤ簬鐢熸垚鏃ュ織鏂囦欢鐨勫悕绉帮紝鎺ュ彈鏃堕棿鎴炽佸悗缂銆佹棩蹇楃洰褰曞拰鏂囦欢鍚嶄綔涓哄弬鏁 static char* logfile_getname(pg_time_t timestamp, const char* suffix, const char* logdir, const char* filename); +// 鐢ㄤ簬璁剧疆涓嬩竴娆℃棩蹇楁枃浠惰疆鎹㈢殑鏃堕棿 static void set_next_rotation_time(void); +// 鐢ㄤ簬澶勭悊SIGHUP鍜孲IGUSR1淇″彿 static void sigHupHandler(SIGNAL_ARGS); static void sigUsr1Handler(SIGNAL_ARGS); +// 鐢ㄤ簬绠$悊鏃ュ織鎺у埗鏁版嵁鐨勪竴缁勫嚱鏁 +// 璁剧疆鍏ㄥ眬鍚嶇О銆佽缃椂鍖恒佽幏鍙栨棩蹇楃洰褰曘 +// 鍒涘缓鏃ュ織鐩綍銆佸啓鍏ユ枃浠跺ご銆佹鏌ユ槸鍚﹂渶瑕佽疆鎹㈡棩蹇楁枃浠躲 +// 鍒锋柊缂撳啿鍖恒佽幏鍙栨枃浠跺悕妯″紡浠ュ強澶勭悊杈撳叆娑堟伅 static void LogCtlSetGlobalNames(void); static void LogCtlSetTimeZone(void); static char* LogCtlGetLogDirectory(const char* logid, bool include_nodename); @@ -151,6 +175,7 @@ static void LogCtlRotateLogFileIfNeeded(LogControlData*, bool); static void LogCtlFlushBuf(LogControlData* logctl); static char* LogCtlGetFilenamePattern(const char* post_suffix); static void LogCtlProcessInput(LogControlData* logctl, const char* msg, int len); +// 鐢ㄤ簬鍒濆鍖栨棩蹇楁帶鍒舵暟鎹互鍙婄壒瀹氭棩蹇楃被鍨嬬殑杞崲鎿嶄綔鐨勪竴缁勫嚱鏁 static void PLogCtlInit(void); static void slow_query_logfile_rotate(bool time_based_rotation, int size_rotation_for); static void asp_logfile_rotate(bool time_based_rotation, int size_rotation_for); @@ -159,35 +184,45 @@ static void asp_logfile_rotate(bool time_based_rotation, int size_rotation_for); * Main entry point for syslogger process * argc/argv parameters are valid only in EXEC_BACKEND case. */ +/* + * 鍔熻兘锛歴yslogger杩涚▼鐨勪富瑕佸叆鍙g偣鍑芥暟 + * + * 鍙傛暟锛 + * fd锛氬湪 EXEC_BACKEND 鎯呭喌涓嬫墠鏈夋晥锛岀敤浜庢寚瀹氭棩蹇楀啓鍏ョ殑鏂囦欢鎻忚堪绗 + * + * 杩斿洖鍊硷細鏃 + */ NON_EXEC_STATIC void SysLoggerMain(int fd) { #ifndef WIN32 - char logbuffer[READ_BUF_SIZE]; - int bytes_in_logbuffer = 0; + char logbuffer[READ_BUF_SIZE]; // 鐢ㄤ簬缂撳啿鏃ュ織娑堟伅 + int bytes_in_logbuffer = 0; // 鐢ㄤ簬璺熻釜缂撳啿鍖轰腑鐨勫瓧鑺傛暟 #endif - LogControlData* logctl = NULL; + LogControlData* logctl = NULL; // 鐢ㄤ簬绠$悊鏃ュ織鎺у埗鏁版嵁鐨勬寚閽 + // 鐢ㄤ簬璺熻釜褰撳墠鏃ュ織鐩綍銆佹枃浠跺悕鍜岃疆鎹㈠勾榫勭殑鍙橀噺 char* currentLogDir = NULL; char* currentLogFilename = NULL; int currentLogRotationAge; + // 褰撳墠鏃堕棿鐨勬椂闂存埑 pg_time_t now; DISABLE_MEMORY_PROTECT(); - + IsUnderPostmaster = true; /* we are a postmaster subprocess now */ - + // 璁剧疆涓哄綋鍓嶇嚎绋嬬殑PID t_thrd.proc_cxt.MyProcPid = gs_thread_self(); /* reset t_thrd.proc_cxt.MyProcPid */ - + // 璁板綍syslogger鍚姩鏃堕棿 t_thrd.proc_cxt.MyStartTime = time(NULL); /* set our start time in case we call elog */ now = t_thrd.proc_cxt.MyStartTime; - + // 鏍囪瘑syslogger鐨勮繘绋嬪悕 t_thrd.proc_cxt.MyProgName = "syslogger"; - + // 鏍囪瘑syslogger鐨勯昏緫绾跨▼ID t_thrd.myLogicTid = noProcLogicTid + SYSLOGGER_LID; - + // 璁剧疆syslogger鐨勬枃浠舵弿杩扮锛屾寚瀹氬皢鏃ュ織鍐欏叆鐨勭洰鏍囨枃浠舵垨绠¢亾 syslogger_setfd(fd); - t_thrd.role = SYSLOGGER; - + t_thrd.role = SYSLOGGER; // 琛ㄧずsyslogger鐨勮鑹 + // 鍒濆鍖栬繘绋嬬姸鎬佹樉绀猴紝璁剧疆杩涚▼鐨勫悕绉 init_ps_display("logger process", "", "", ""); /* @@ -197,6 +232,7 @@ NON_EXEC_STATIC void SysLoggerMain(int fd) */ #ifdef WIN32 else + // 鍦╓indows鐜涓嬶紝灏嗘爣鍑嗛敊璇殑妯″紡璁剧疆涓烘枃鏈ā寮 _setmode(_fileno(stderr), _O_TEXT); #endif @@ -206,14 +242,16 @@ NON_EXEC_STATIC void SysLoggerMain(int fd) * case, the postmaster already did this.) */ #ifndef WIN32 + // 鍏抽棴鍐欏叆绔殑绠¢亾鎻忚堪绗︼紝鐢ㄤ簬纭繚鍙互姝g‘妫娴嬬閬撶殑EOF t_thrd.postmaster_cxt.syslogPipe[1] = -1; #else syslogPipe[1] = 0; #endif - + // 鍒濆鍖朙atch鏀寔锛岀敤浜庣瓑寰呬簨浠 InitializeLatchSupport(); /* needed for latch waits */ /* Initialize private latch for use by signal handlers */ + // 鍒濆鍖杝ysLoggerLatch锛岀敤浜庣瓑寰呬俊鍙峰鐞嗙▼搴 InitLatch(&t_thrd.logger.sysLoggerLatch); /* @@ -226,6 +264,9 @@ NON_EXEC_STATIC void SysLoggerMain(int fd) /* * Reset some signals that are accepted by postmaster but not here */ + // 璁剧疆淇″彿澶勭悊绋嬪簭 + // 鍏朵腑 SIGHUP 鐢ㄤ簬閲嶆柊鍔犺浇閰嶇疆鏂囦欢锛孲IGUSR1 鐢ㄤ簬璇锋眰鏃ュ織杞崲 + // 鍏朵綑淇″彿蹇界暐 (void)gspqsignal(SIGHUP, sigHupHandler); /* set flag to read config file */ (void)gspqsignal(SIGINT, SIG_IGN); (void)gspqsignal(SIGTERM, SIG_IGN); @@ -238,37 +279,51 @@ NON_EXEC_STATIC void SysLoggerMain(int fd) /* * Reset some signals that are accepted by postmaster but not here */ + // 璁剧疆瀵瑰瓙杩涚▼鐘舵佹敼鍙樼瓑淇″彿鐨勫鐞嗘柟寮忥紝鎭㈠榛樿琛屼负 (void)gspqsignal(SIGCHLD, SIG_DFL); (void)gspqsignal(SIGTTIN, SIG_DFL); (void)gspqsignal(SIGTTOU, SIG_DFL); (void)gspqsignal(SIGCONT, SIG_DFL); (void)gspqsignal(SIGWINCH, SIG_DFL); + // 璁剧疆淇″彿鎺╃爜锛岀‘淇漇IGUSR2淇″彿涓嶈闃诲 gs_signal_setmask(&t_thrd.libpq_cxt.UnBlockSig, NULL); (void)gs_signal_unblock_sigusr2(); #ifdef WIN32 /* Fire up separate data transfer thread */ + // 鍒濆鍖栦竴涓复鐣屽尯锛岀敤浜庣‘淇濆涓嚎绋嬩笉浼氬悓鏃惰闂叧閿儴鍒嗙殑浠g爜锛屼互閬垮厤绔炴佹潯浠 InitializeCriticalSection(&sysloggerSection); + // 杩涘叆涓寸晫鍖猴紝鏍囧織鐫褰撳墠绾跨▼瑕佹墽琛屽叧閿儴鍒嗙殑浠g爜 EnterCriticalSection(&sysloggerSection); - + // 鍦 Windows 涓嬪垱寤轰竴涓柊鐨勭嚎绋嬶紝鐢ㄤ簬鏁版嵁浼犺緭 + // pipeThread 鏄嚎绋嬬殑鍏ュ彛鐐瑰嚱鏁 threadHandle = (HANDLE)_beginthreadex(NULL, 0, pipeThread, NULL, 0, NULL); - if (threadHandle == 0) + if (threadHandle == 0) // 妫鏌ョ嚎绋嬪垱寤烘槸鍚︽垚鍔 + // 濡傛灉绾跨▼鍒涘缓澶辫触锛屾姤鍛婅嚧鍛介敊璇苟閫鍑鸿繘绋 ereport(FATAL, (errmsg("could not create syslogger data transfer thread: %m"))); #endif /* WIN32 */ - PLogCtlInit(); + PLogCtlInit(); // 鍒濆鍖栨棩蹇楁帶鍒舵暟鎹紝鐢ㄤ簬绠$悊涓嶅悓绫诲瀷鐨勬棩蹇 /* create slow query directory */ + // 妫鏌ラ厤缃枃浠朵腑鏄惁鎸囧畾浜嗘參鏌ヨ鏃ュ織鐩綍 if (g_instance.attr.attr_common.query_log_directory == NULL) { + // 濡傛灉娌℃湁鎸囧畾锛屽垯璋冪敤 init_instr_log_directory 鍒涘缓榛樿鐨勭洰褰 init_instr_log_directory(true, SLOWQUERY_LOG_TAG); } else { + // 濡傛灉鎸囧畾浜嗙洰褰曪紝鍒欎娇鐢 pg_mkdir_p 鍑芥暟鍒涘缓鐩綍 + // 璁剧疆鍏舵潈闄愪负 S_IRWXU锛堢敤鎴峰彲璇汇佸彲鍐欍佸彲鎵ц锛 (void)pg_mkdir_p(g_instance.attr.attr_common.query_log_directory, S_IRWXU); } /* create asp directory */ + // 妫鏌ラ厤缃枃浠朵腑鏄惁鎸囧畾浜咥SP 鏃ュ織鐩綍 if (g_instance.attr.attr_common.asp_log_directory == NULL) { + // 濡傛灉娌℃湁鎸囧畾锛屽垯璋冪敤 init_instr_log_directory 鍒涘缓榛樿鐨勭洰褰 init_instr_log_directory(true, ASP_LOG_TAG); } else { + // 濡傛灉鎸囧畾浜嗙洰褰曪紝鍒欎娇鐢 pg_mkdir_p 鍑芥暟鍒涘缓鐩綍 + // 璁剧疆鍏舵潈闄愪负 S_IRWXU锛堢敤鎴峰彲璇汇佸彲鍐欍佸彲鎵ц锛 (void)pg_mkdir_p(g_instance.attr.attr_common.asp_log_directory, S_IRWXU); } @@ -278,12 +333,16 @@ NON_EXEC_STATIC void SysLoggerMain(int fd) * time because passing down just the pg_time_t is a lot cheaper than * passing a whole file path in the EXEC_BACKEND case. */ + // 璁板綍褰撳墠娲昏穬鐨勬棩蹇楁枃浠剁殑鍚嶇О + // 鑺傜渷鍦 EXEC_BACKEND 鎯呭喌涓嬩紶閫掓暣涓枃浠惰矾寰勭殑寮閿 t_thrd.logger.last_file_name = logfile_getname(t_thrd.logger.first_syslogger_file_time, NULL, u_sess->attr.attr_common.Log_directory, u_sess->attr.attr_common.Log_filename); + // 鎵撳紑褰撳墠娲昏穬鐨勬棩蹇楁枃浠讹紝浣跨敤 "a" 妯″紡鎵撳紑鏂囦欢浠ヨ拷鍔犲啓鍏 + // false 琛ㄧず涓嶅厑璁稿湪鍙戠敓閿欒鏃舵姤鍛婇敊璇 t_thrd.logger.syslogFile = logfile_open(t_thrd.logger.last_file_name, "a", false); - + // 寰幆澶勭悊鍏朵粬绫诲瀷鐨勬棩蹇楁枃浠 foreach_logctl(logctl) { /* * fd leaking maybe happens when syslogger thread is @@ -291,23 +350,28 @@ NON_EXEC_STATIC void SysLoggerMain(int fd) * maybe include switch over case. * if the thread restarted, the original memory context must be deleted and need not free the memory */ + // 璁$畻褰撳墠鏃ュ織鏂囦欢鐨勫悕绉 logctl->now_file_name = logfile_getname(t_thrd.logger.first_syslogger_file_time, NULL, logctl->log_dir, logctl->filename_pattern); - + // 濡傛灉褰撳墠鏃ュ織鏂囦欢鐨勬枃浠舵弿杩扮涓嶄负 NULL锛屽垯鍏抽棴鏂囦欢 if (logctl->now_file_fd != NULL) { (void)fclose(logctl->now_file_fd); logctl->now_file_fd = NULL; } + // 鎵撳紑褰撳墠鏃ュ織鏂囦欢锛屼娇鐢 "a" 妯″紡杩藉姞鍐欏叆 + // false 琛ㄧず涓嶅厑璁稿湪鍙戠敓閿欒鏃舵姤鍛婇敊璇 logctl->now_file_fd = logfile_open(logctl->now_file_name, "a", false); + // 鍐欏叆鏂囦欢澶撮儴淇℃伅 LogCtlWriteFileHeader(logctl); } /* remember active logfile parameters */ + // 璁板綍褰撳墠娲昏穬鐨勬棩蹇楁枃浠剁殑鐩綍銆佹枃浠跺悕鍜岃疆鎹㈠勾榫 currentLogDir = pstrdup(u_sess->attr.attr_common.Log_directory); currentLogFilename = pstrdup(u_sess->attr.attr_common.Log_filename); currentLogRotationAge = u_sess->attr.attr_common.Log_RotationAge; /* set next planned rotation time */ - set_next_rotation_time(); + set_next_rotation_time(); // 璁剧疆涓嬩竴娆¤鍒掕疆鎹㈢殑鏃堕棿 /* main worker loop */ for (;;) { @@ -321,39 +385,46 @@ NON_EXEC_STATIC void SysLoggerMain(int fd) #endif /* Clear any already-pending wakeups */ - ResetLatch(&t_thrd.logger.sysLoggerLatch); + ResetLatch(&t_thrd.logger.sysLoggerLatch); // 娓呴櫎浠讳綍宸茬粡鍙戠敓鐨勭瓑寰呬簨浠 /* * Process any requests or signals received recently. */ - if (t_thrd.logger.got_SIGHUP) { - t_thrd.logger.got_SIGHUP = false; - ProcessConfigFile(PGC_SIGHUP); + if (t_thrd.logger.got_SIGHUP) { // 濡傛灉鎺ユ敹鍒 SIGHUP 淇″彿 + t_thrd.logger.got_SIGHUP = false; // 娓呴櫎鏍囧織 got_SIGHUP + ProcessConfigFile(PGC_SIGHUP); // 澶勭悊閰嶇疆鏂囦欢鐨勫彉鍖 /* * Check if the log directory or filename pattern changed in * postgresql.conf. If so, force rotation to make sure we're * writing the logfiles in the right place. */ + // 濡傛灉閰嶇疆鏂囦欢涓殑鏃ュ織鐩綍 Log_directory 鍙戠敓浜嗗彉鍖 if (strcmp(u_sess->attr.attr_common.Log_directory, currentLogDir) != 0) { - pfree(currentLogDir); + pfree(currentLogDir); // 閲婃斁涔嬪墠鐨勭洰褰曞瓧绗︿覆 + // 閲嶆柊鍒嗛厤涓涓柊鐨勶紝浠ュ弽鏄犳柊鐨勭洰褰 currentLogDir = pstrdup(u_sess->attr.attr_common.Log_directory); - t_thrd.logger.rotation_requested = true; + t_thrd.logger.rotation_requested = true; // 琛ㄧず闇瑕佹墽琛屾棩蹇楄疆鎹 /* not affect pLogCtl's Log_directory */ /* * Also, create new directory if not present; ignore errors */ + // 濡傛灉鏂扮殑鐩綍涓嶅瓨鍦紝鍒欏垱寤轰竴涓柊鐩綍锛屾潈闄愯缃负 S_IRWXU锛堢敤鎴峰彲璇汇佸彲鍐欍佸彲鎵ц锛 mkdir(u_sess->attr.attr_common.Log_directory, S_IRWXU); } + // 濡傛灉閰嶇疆鏂囦欢涓殑鏃ュ織鏂囦欢鍚 Log_filename 鍙戠敓浜嗗彉鍖 if (strcmp(u_sess->attr.attr_common.Log_filename, currentLogFilename) != 0) { - pfree(currentLogFilename); + pfree(currentLogFilename); // 閲婃斁涔嬪墠鐨勭洰褰曞瓧绗︿覆 + // 閲嶆柊鍒嗛厤涓涓柊鐨勶紝浠ュ弽鏄犳柊鐨勭洰褰 currentLogFilename = pstrdup(u_sess->attr.attr_common.Log_filename); - t_thrd.logger.rotation_requested = true; - foreach_logctl(logctl) { + t_thrd.logger.rotation_requested = true; // 琛ㄧず闇瑕佹墽琛屾棩蹇楄疆鎹 + foreach_logctl(logctl) { // 閬嶅巻姣忎釜鏃ュ織绫诲瀷 + // 濡傛灉鍏舵枃浠跺悕妯″紡 filename_pattern 涓嶄负绌 if (logctl->filename_pattern != NULL) { - pfree_ext(logctl->filename_pattern); + pfree_ext(logctl->filename_pattern); // 閲婃斁涔嬪墠鐨勬ā寮忓瓧绗︿覆 } /* recompute log file pattern */ + // 閲嶆柊璁$畻鏂扮殑妯″紡 logctl->filename_pattern = LogCtlGetFilenamePattern(logctl->file_suffix); logctl->rotation_requested = true; } @@ -363,8 +434,10 @@ NON_EXEC_STATIC void SysLoggerMain(int fd) * If rotation time parameter changed, reset next rotation time, * but don't immediately force a rotation. */ + // 濡傛灉閰嶇疆鏂囦欢涓殑鏃ュ織杞崲鏃堕棿鍙傛暟 Log_RotationAge 鍙戠敓浜嗗彉鍖 if (currentLogRotationAge != u_sess->attr.attr_common.Log_RotationAge) { currentLogRotationAge = u_sess->attr.attr_common.Log_RotationAge; + // 閲嶆柊璁$畻涓嬩竴娆¤鍒掕疆鎹㈢殑鏃堕棿锛屼絾涓嶄細绔嬪嵆寮哄埗鎵ц鏃ュ織杞崲 set_next_rotation_time(); } @@ -372,49 +445,70 @@ NON_EXEC_STATIC void SysLoggerMain(int fd) * If we had a rotation-disabling failure, re-enable rotation * attempts after SIGHUP, and force one immediately. */ + // 濡傛灉涔嬪墠鍥犱负鏌愮鍘熷洜绂佺敤浜嗘棩蹇楄疆鎹 if (t_thrd.logger.rotation_disabled) { t_thrd.logger.rotation_disabled = false; - t_thrd.logger.rotation_requested = true; + t_thrd.logger.rotation_requested = true; // 閲嶆柊鍚敤杞崲 + // 瀵规瘡涓棩蹇楃被鍨嬫爣璁颁负闇瑕佽疆鎹 foreach_logctl(logctl) { /* keep the same step with error log, and rotate this log file */ logctl->rotation_requested = true; } } } - + // 澶勭悊鏃堕棿鍜屽ぇ灏忓鑷寸殑鏃ュ織杞崲 + // 濡傛灉鍚敤浜嗗熀浜庢椂闂寸殑鏃ュ織杞崲涓旀湭琚鐢紝浼氭鏌ユ槸鍚﹀簲璇ヨ繘琛屾椂闂村鑷寸殑杞崲 if (u_sess->attr.attr_common.Log_RotationAge > 0 && !t_thrd.logger.rotation_disabled) { /* Do a logfile rotation if it's time */ - now = (pg_time_t)time(NULL); + now = (pg_time_t)time(NULL); // 鑾峰彇褰撳墠鏃堕棿 + // 姣旇緝鏄惁瓒呰繃浜嗕笅涓娆¤鍒掕疆鎹㈢殑鏃堕棿 next_rotation_time if (now >= t_thrd.logger.next_rotation_time) { + // 濡傛灉瓒呰繃浜嗭紝鍒欐爣璁伴渶瑕佹墽琛屾椂闂磋疆鎹 t_thrd.logger.rotation_requested = time_based_rotation = true; + // 瀵规瘡涓棩蹇楃被鍨嬫爣璁伴渶瑕佽疆鎹 foreach_logctl(logctl) { /* share the same rotation age */ logctl->rotation_requested = true; } } } - + // 濡傛灉娌℃湁浠讳綍杞崲璇锋眰锛屼笖鍚敤浜嗗熀浜庡ぇ灏忕殑鏃ュ織杞崲涓旀湭琚鐢紝浼氭鏌ユ槸鍚﹀簲璇ヨ繘琛屽ぇ灏忓鑷寸殑杞崲 if (!t_thrd.logger.rotation_requested && u_sess->attr.attr_common.Log_RotationSize > 0 && !t_thrd.logger.rotation_disabled) { /* Do a rotation if file is too big */ + // ftell鍑芥暟鐢ㄤ簬鑾峰彇褰撳墠鎵撳紑鏂囦欢鐨勪綅缃寚閽堬紝涔熷氨鏄綋鍓嶆枃浠剁殑澶у皬锛堜互瀛楄妭涓哄崟浣嶏級 + // u_sess->attr.attr_common.Log_RotationSize 鏄厤缃枃浠朵腑璁剧疆鐨勬棩蹇楀ぇ灏忚疆鎹㈤槇鍊硷紝浠ュ崈瀛楄妭涓哄崟浣 + // 妫鏌ュ綋鍓嶆棩蹇楁枃浠剁殑澶у皬鏄惁瓒呰繃浜嗛厤缃枃浠朵腑璁剧疆鐨勮疆鎹㈠ぇ灏 if (ftell(t_thrd.logger.syslogFile) >= u_sess->attr.attr_common.Log_RotationSize * 1024L) { + // 濡傛灉瓒呰繃浜嗭紝鍒欐爣璁伴渶瑕佹墽琛屽ぇ灏忚疆鎹 t_thrd.logger.rotation_requested = true; + // 鎸囩ず鏍囧噯閿欒鏃ュ織闇瑕佽繘琛岃疆鎹 size_rotation_for |= LOG_DESTINATION_STDERR; } + // 绫讳技鐨勬鏌ラ拡瀵瑰叾浠栨棩蹇楃被鍨嬶紝CSV 鏃ュ織銆佹煡璇㈡棩蹇楀拰 ASP 鏃ュ織 + // 妫鏌ュ綋鍓嶆棩蹇楁枃浠剁殑澶у皬鏄惁瓒呰繃浜嗛厤缃枃浠朵腑璁剧疆鐨勮疆鎹㈠ぇ灏 if (t_thrd.logger.csvlogFile != NULL && ftell(t_thrd.logger.csvlogFile) >= u_sess->attr.attr_common.Log_RotationSize * 1024L) { + // 濡傛灉瓒呰繃浜嗭紝鍒欐爣璁伴渶瑕佹墽琛屽ぇ灏忚疆鎹 t_thrd.logger.rotation_requested = true; + // 鎸囩ず鏍囧噯閿欒鏃ュ織闇瑕佽繘琛岃疆鎹 size_rotation_for |= LOG_DESTINATION_CSVLOG; } + // 妫鏌ュ綋鍓嶆棩蹇楁枃浠剁殑澶у皬鏄惁瓒呰繃浜嗛厤缃枃浠朵腑璁剧疆鐨勮疆鎹㈠ぇ灏 if (t_thrd.logger.querylogFile != NULL && ftell(t_thrd.logger.querylogFile) >= u_sess->attr.attr_common.Log_RotationSize * 1024L) { + // 濡傛灉瓒呰繃浜嗭紝鍒欐爣璁伴渶瑕佹墽琛屽ぇ灏忚疆鎹 t_thrd.logger.rotation_requested = true; + // 鎸囩ず鏍囧噯閿欒鏃ュ織闇瑕佽繘琛岃疆鎹 size_rotation_for |= LOG_DESTINATION_QUERYLOG; } + // 妫鏌ュ綋鍓嶆棩蹇楁枃浠剁殑澶у皬鏄惁瓒呰繃浜嗛厤缃枃浠朵腑璁剧疆鐨勮疆鎹㈠ぇ灏 if (t_thrd.logger.asplogFile != NULL && ftell(t_thrd.logger.asplogFile) >= u_sess->attr.attr_common.Log_RotationSize * 1024L) { + // 濡傛灉瓒呰繃浜嗭紝鍒欐爣璁伴渶瑕佹墽琛屽ぇ灏忚疆鎹 t_thrd.logger.rotation_requested = true; + // 鎸囩ず鏍囧噯閿欒鏃ュ織闇瑕佽繘琛岃疆鎹 size_rotation_for |= LOG_DESTINATION_ASPLOG; } } @@ -424,21 +518,28 @@ NON_EXEC_STATIC void SysLoggerMain(int fd) * logfile_rotate() will change t_thrd.logger.next_rotation_time value by calling * set_next_rotation_time(). */ + // 閬嶅巻涓嶅悓绫诲瀷鐨勬棩蹇 foreach_logctl(logctl) { + // 妫鏌ョ壒瀹氱被鍨嬫棩蹇楁枃浠舵槸鍚﹂渶瑕佽繘琛岃疆鎹㈡搷浣 + // logctl 鏄綋鍓嶆鍦ㄦ鏌ョ殑鏃ュ織绫诲瀷鐨勬帶鍒剁粨鏋勶紝time_based_rotation 鏄竴涓爣蹇楋紝鎸囩ず鏄惁鍩轰簬鏃堕棿鎵ц杞崲 LogCtlRotateLogFileIfNeeded(logctl, time_based_rotation); } - if (t_thrd.logger.rotation_requested) { + if (t_thrd.logger.rotation_requested) { // 妫鏌ユ槸鍚﹂渶瑕佹墽琛屾棩蹇楄疆鎹 /* * Force rotation when both values are zero. It means the request * was sent by pg_rotate_logfile. */ + // 濡傛灉鏃笉鏄熀浜庢椂闂寸殑杞崲涔熸病鏈夌壒瀹氱殑澶у皬杞崲瑕佹眰锛岄偅涔堝己鍒舵墽琛岃疆鎹 if (!time_based_rotation && size_rotation_for == 0) size_rotation_for = LOG_DESTINATION_STDERR | LOG_DESTINATION_CSVLOG | LOG_DESTINATION_QUERYLOG | LOG_DESTINATION_ASPLOG; + // 鎵ц ASP鏃ュ織鐨勮疆鎹㈡搷浣 asp_logfile_rotate(time_based_rotation, size_rotation_for); + // 鎵ц鎱㈡煡璇㈡棩蹇楃殑杞崲鎿嶄綔 slow_query_logfile_rotate(time_based_rotation, size_rotation_for); /* only last one can recalculate next_rotation_time */ + // 鎵ц閿欒鏃ュ織鐨勮疆鎹㈡搷浣 logfile_rotate(time_based_rotation, size_rotation_for); } @@ -454,17 +555,18 @@ NON_EXEC_STATIC void SysLoggerMain(int fd) * could be more than INT_MAX msec in the future. In that case we'll * wait no more than INT_MAX msec, and try again. */ + // 妫鏌ユ槸鍚﹀惎鐢ㄤ簡鏃堕棿杞崲涓旀湭绂佺敤杞崲 if (u_sess->attr.attr_common.Log_RotationAge > 0 && !t_thrd.logger.rotation_disabled) { pg_time_t delay; - + // 璁$畻璺濈涓嬩竴娆℃椂闂磋疆鎹㈢殑鍓╀綑鏃堕棿 delay = t_thrd.logger.next_rotation_time - now; - if (delay > 0) { - if (delay > INT_MAX / 1000) - delay = INT_MAX / 1000; - cur_timeout = delay * 1000L; /* msec */ - } else - cur_timeout = 0; - cur_flags = WL_TIMEOUT; + if (delay > 0) { // 濡傛灉杩橀渶瑕佺瓑寰呬竴娈垫椂闂存墠鑳借繘琛屾椂闂磋疆鎹 + if (delay > INT_MAX / 1000) // 濡傛灉鍓╀綑鏃堕棿瓒呰繃浜 INT_MAX 姣 + delay = INT_MAX / 1000; // 閬垮厤鏁存暟婧㈠嚭 + cur_timeout = delay * 1000L; /* msec */ // 灏嗗墿浣欐椂闂磋浆鎹负姣锛屼互渚垮湪浼戠湢鏃朵娇鐢 + } else // 琛ㄧず涓嬩竴娆¤疆鎹㈠凡鍒版湡 + cur_timeout = 0; // 浠ヤ究绔嬪嵆鍞ら啋杩涚▼ + cur_flags = WL_TIMEOUT; // 鏍规嵁绛夊緟瓒呮椂鏃堕棿璁剧疆鏍囧織锛岃〃绀哄彧绛夊緟瓒呮椂浜嬩欢 } else { cur_timeout = -1L; cur_flags = 0; @@ -474,25 +576,30 @@ NON_EXEC_STATIC void SysLoggerMain(int fd) * Sleep until there's something to do */ #ifndef WIN32 + // 浣跨敤 WaitLatchOrSocket 鍑芥暟绛夊緟澶氫釜浜嬩欢 + // 鍖呮嫭 WL_LATCH_SET锛堢瓑寰呬簨浠讹級銆乄L_SOCKET_READABLE锛堝鎺ュ瓧鍙浜嬩欢锛夊拰 cur_flags锛堣秴鏃朵簨浠讹級 rc = WaitLatchOrSocket(&t_thrd.logger.sysLoggerLatch, WL_LATCH_SET | WL_SOCKET_READABLE | cur_flags, t_thrd.postmaster_cxt.syslogPipe[0], cur_timeout); - if (rc & WL_SOCKET_READABLE) { + if (rc & WL_SOCKET_READABLE) { // 濡傛灉濂楁帴瀛楀彲璇讳簨浠跺彂鐢 int bytesRead; - + // 浠庣閬撹鍙栨暟鎹苟璋冪敤 process_pipe_input 澶勭悊鏁版嵁 bytesRead = read(t_thrd.postmaster_cxt.syslogPipe[0], logbuffer + bytes_in_logbuffer, sizeof(logbuffer) - bytes_in_logbuffer); - if (bytesRead < 0) { - if (errno != EINTR) + if (bytesRead < 0) { // 濡傛灉璇诲彇鐨勫瓧鑺傛暟灏忎簬闆 + if (errno != EINTR) // 濡傛灉 errno 涓嶆槸 EINTR + // 璁板綍涓鏉℃棩蹇 ereport(LOG, (errcode_for_socket_access(), errmsg("could not read from logger pipe: %m"))); } else if (bytesRead > 0) { + // 濡傛灉璇诲彇鐨勫瓧鑺傛暟澶т簬闆讹紝琛ㄧず绠¢亾涓湁鏂扮殑鏁版嵁 bytes_in_logbuffer += bytesRead; process_pipe_input(logbuffer, &bytes_in_logbuffer); - continue; + continue; // 缁х画澶勭悊 } else { + // 濡傛灉璇诲彇鐨勫瓧鑺傛暟绛変簬闆讹紝琛ㄧず绠¢亾宸插叧闂 /* * ELSE branch is never executed forever in multi-thread mode * @@ -501,9 +608,10 @@ NON_EXEC_STATIC void SysLoggerMain(int fd) * with the pipe write end open. Therefore, the postmaster * and all backends are shut down, and we are done. */ - t_thrd.logger.pipe_eof_seen = true; + t_thrd.logger.pipe_eof_seen = true; // 琛ㄧず鏃ュ織瀛愯繘绋嬪凡閫鍑 /* if there's any data left then force it out now */ + // 寮哄埗鍒锋柊绠¢亾涓殑鍓╀綑鏁版嵁 flush_pipe_input(logbuffer, &bytes_in_logbuffer); } } @@ -518,18 +626,20 @@ NON_EXEC_STATIC void SysLoggerMain(int fd) * of the threads is active at a time by entering the critical section * whenever we're not sleeping. */ + // 绂诲紑涓寸晫鍖猴紝琛ㄧず涓嶅啀鍗犵敤鍏变韩璧勬簮 LeaveCriticalSection(&sysloggerSection); - + // 绛夊緟浜嬩欢鐨勫彂鐢 (void)WaitLatch(&t_thrd.logger.sysLoggerLatch, WL_LATCH_SET | cur_flags, cur_timeout); - + // 閲嶆柊杩涘叆涓寸晫鍖猴紝缁х画鍗犵敤鍏变韩璧勬簮 EnterCriticalSection(&sysloggerSection); #endif /* WIN32 */ - if (t_thrd.logger.pipe_eof_seen) { + if (t_thrd.logger.pipe_eof_seen) { // 妫鏌ユ槸鍚︾湅鍒颁簡绠¢亾宸插叧闂殑鏍囧織 /* * seeing this message on the real stderr is annoying - so we make * it DEBUG1 to suppress in normal use. */ + // 濡傛灉鏄紝璁板綍涓鏉 DEBUG1 绾у埆鐨勬棩蹇楋紝琛ㄧず鏃ュ織瀛愯繘绋嬫鍦ㄥ叧闂 ereport(DEBUG1, (errmsg("logger shutting down"))); /* @@ -547,12 +657,20 @@ NON_EXEC_STATIC void SysLoggerMain(int fd) /* * Postmaster subroutine to start a syslogger subprocess. */ +/* + * 鍔熻兘锛氬惎鍔ㄧ郴缁熸棩蹇楃鐞嗚繘绋 + * + * 鍙傛暟锛氭棤 + * + * 杩斿洖鍊硷細ThreadId绫诲瀷锛岃〃绀烘柊鍒涘缓鐨勫瓙杩涚▼鐨勭嚎绋 ID + */ ThreadId SysLogger_Start(void) { - ThreadId sysloggerPid; - char* filename = NULL; - + ThreadId sysloggerPid; // 鐢ㄤ簬瀛樺偍鏂板垱寤虹殑瀛愯繘绋嬬殑绾跨▼ ID + char* filename = NULL; // 鐢ㄤ簬瀛樺偍鏃ュ織鏂囦欢鍚 + // 妫鏌ラ厤缃弬鏁 Logging_collector 鏄惁涓哄亣 if (!g_instance.attr.attr_common.Logging_collector) + // 濡傛灉涓哄亣锛屽垯鐩存帴杩斿洖 0锛岃〃绀轰笉鍚姩鏃ュ織鏀堕泦杩涚▼ return 0; /* @@ -568,21 +686,25 @@ ThreadId SysLogger_Start(void) * is a bit klugy but we have little choice. */ #ifndef WIN32 - if (t_thrd.postmaster_cxt.syslogPipe[0] < 0) { + if (t_thrd.postmaster_cxt.syslogPipe[0] < 0) { // 妫鏌ョ閬撴槸鍚﹀凡缁忓垱寤 + // 濡傛灉绠¢亾灏氭湭鍒涘缓锛屽垯鍒涘缓 if (pipe(t_thrd.postmaster_cxt.syslogPipe) < 0) + // 濡傛灉鍒涘缓澶辫触锛屽皢瑙﹀彂鑷村懡閿欒锛岀郴缁熸棤娉曠户缁墽琛 ereport(FATAL, (errcode_for_socket_access(), (errmsg("could not create pipe for syslog: %m")))); } #else - if (!t_thrd.postmaster_cxt.syslogPipe[0]) { + if (!t_thrd.postmaster_cxt.syslogPipe[0]) { // 妫鏌ョ閬撴槸鍚﹀凡鍒涘缓 SECURITY_ATTRIBUTES sa; - + // 鍒濆鍖 errno_t rc = memset_s(&sa, sizeof(SECURITY_ATTRIBUTES), 0, sizeof(SECURITY_ATTRIBUTES)); securec_check_c(rc, "\0", "\0"); - + // 璁剧疆缁撴瀯浣撶殑闀垮害鍜屽厑璁哥户鎵垮彞鏌勭殑鏍囧織 sa.nLength = sizeof(SECURITY_ATTRIBUTES); sa.bInheritHandle = TRUE; + // 鍒涘缓绠¢亾锛屼繚瀛樿鍙栫鍜屽啓鍏ョ鐨勫彞鏌 if (!CreatePipe(&t_thrd.postmaster_cxt.syslogPipe[0], &t_thrd.postmaster_cxt.syslogPipe[1], &sa, 32768)) + // 濡傛灉鍒涘缓澶辫触锛屽皢瑙﹀彂鑷村懡閿欒锛岀郴缁熸棤娉曠户缁墽琛 ereport(FATAL, (errcode_for_file_access(), (errmsg("could not create pipe for syslog: %m")))); } #endif @@ -590,13 +712,14 @@ ThreadId SysLogger_Start(void) /* * Create log directory if not present; ignore errors */ + // 濡傛灉鐩綍涓嶅瓨鍦紝鍒涘缓鏃ュ織鐩綍锛涘鏋滅洰褰曞凡缁忓瓨鍦ㄦ垨鑰呭垱寤哄け璐ワ紝浼氬拷鐣ラ敊璇 (void)pg_mkdir_p(u_sess->attr.attr_common.Log_directory, S_IRWXU); /* create log directory */ - LogCtlCreateLogParentDirectory(); + LogCtlCreateLogParentDirectory(); // 鍒涘缓鏃ュ織鐨勭埗鐩綍 /* set global names from postmaster */ - LogCtlSetGlobalNames(); + LogCtlSetGlobalNames(); // 璁剧疆鍏ㄥ眬鐨勬棩蹇楁枃浠跺悕鍜屾枃浠跺悗缂 /* set time zone from postmaster */ - LogCtlSetTimeZone(); + LogCtlSetTimeZone(); // 璁剧疆鏃ュ織鐨勬椂鍖 /* * The initial logfile is created right in the postmaster, to verify that @@ -610,31 +733,42 @@ ThreadId SysLogger_Start(void) * is consistent with the normal rules, because by definition this is not * a time-based rotation. */ + // 鍒涘缓鍒濆鐨勬棩蹇楁枃浠讹紝浠ラ獙璇佹棩蹇楃洰褰曟槸鍚﹀彲鍐欍 + // 鍑芥暟璁板綍浜嗗垱寤鸿繖涓枃浠剁殑鏃堕棿鎴筹紝浠ヤ緵鍚庣画鐨勭郴缁熸棩蹇楃鐞嗚繘绋嬩娇鐢 t_thrd.logger.first_syslogger_file_time = time(NULL); + // 鐢熸垚鏃ュ織鏂囦欢鐨勫悕绉帮紝骞跺皢鍏跺瓨鍌 filename = logfile_getname(t_thrd.logger.first_syslogger_file_time, NULL, u_sess->attr.attr_common.Log_directory, u_sess->attr.attr_common.Log_filename); - pfree(filename); + pfree(filename); // 閲婃斁鍐呭瓨 - sysloggerPid = initialize_util_thread(SYSLOGGER); + sysloggerPid = initialize_util_thread(SYSLOGGER); // 鍚姩syslogger绾跨▼ /* success, in postmaster */ if (sysloggerPid != 0) { + // 濡傛灉鎴愬姛鍚姩浜嗙郴缁熸棩蹇楃鐞嗚繘绋 /* now we redirect stderr, if not done already */ if (!t_thrd.postmaster_cxt.redirection_done) { #ifndef WIN32 - fflush(stdout); + // 鍦ㄩ潪 Windows 骞冲彴涓婇噸瀹氬悜 stderr 杈撳嚭 + fflush(stdout); // 鍒锋柊鏍囧噯杈撳嚭缂撳啿鍖猴紝浠ョ‘淇濅换浣曞緟杈撳嚭鐨勫唴瀹归兘琚啓鍏 + // 浣跨敤 dup2 鍑芥暟灏嗙閬撶殑鍐欏叆绔鍒跺埌鏍囧噯杈撳嚭鐨勬枃浠舵弿杩扮 if (dup2(t_thrd.postmaster_cxt.syslogPipe[1], fileno(stdout)) < 0) + // 濡傛灉澶嶅埗澶辫触锛屼細瑙﹀彂鑷村懡閿欒 ereport(FATAL, (errcode_for_file_access(), errmsg("could not redirect stdout: %m"))); - fflush(stderr); + fflush(stderr); // 鍒锋柊鏍囧噯閿欒杈撳嚭缂撳啿鍖猴紝浠ョ‘淇濅换浣曞緟杈撳嚭鐨勯敊璇俊鎭兘琚啓鍏 + // 浣跨敤 dup2 鍑芥暟灏嗙閬撶殑鍐欏叆绔鍒跺埌鏍囧噯閿欒杈撳嚭鐨勬枃浠舵弿杩扮 if (dup2(t_thrd.postmaster_cxt.syslogPipe[1], fileno(stderr)) < 0) + // 濡傛灉澶嶅埗澶辫触锛屼細瑙﹀彂鑷村懡閿欒 ereport(FATAL, (errcode_for_file_access(), errmsg("could not redirect stderr: %m"))); /* Now we are done with the write end of the pipe. */ + // 鍏抽棴绠¢亾鐨勫啓鍏ョ锛屽洜涓烘爣鍑嗚緭鍑哄拰鏍囧噯閿欒杈撳嚭宸茬粡閲嶅畾鍚戝埌浜嗚绠¢亾 close(t_thrd.postmaster_cxt.syslogPipe[1]); t_thrd.postmaster_cxt.syslogPipe[1] = -1; #else + // 鍦 Windows 骞冲彴涓婇噸瀹氬悜 stderr 杈撳嚭 int fd; /* @@ -658,9 +792,9 @@ ThreadId SysLogger_Start(void) #endif t_thrd.postmaster_cxt.redirection_done = true; } - + // 琛ㄧず璇ヨ繘绋嬪凡缁忓紑濮嬬鐞嗘棩蹇 t_thrd.logger.syslogFile = NULL; - return sysloggerPid; + return sysloggerPid; // 杩斿洖鏂板垱寤虹殑瀛愯繘绋嬬殑绾跨▼ ID } /* we should never reach here */ @@ -668,11 +802,19 @@ ThreadId SysLogger_Start(void) } /* close the t_thrd.logger.syslogFile */ +/* + * 鍔熻兘锛氬叧闂 syslogger 杩涚▼涓殑鏃ュ織鏂囦欢 + * + * 鍙傛暟锛氭棤 + * + * 杩斿洖鍊硷細鏃 + */ void SysLoggerClose(void) { - if (t_thrd.logger.syslogFile) { + if (t_thrd.logger.syslogFile) { // 妫鏌ュ綋鍓嶇嚎绋嬫槸鍚﹀凡缁忔墦寮浜嗕竴涓棩蹇楁枃浠 + // 濡傛灉宸茬粡鎵撳紑浜嗘棩蹇楁枃浠讹紝鍒欏叧闂鏂囦欢銆傚皢鏂囦欢缂撳啿鍖轰腑鐨勬暟鎹啓鍏ョ鐩橈紝骞堕噴鏀剧浉鍏崇殑璧勬簮 fclose(t_thrd.logger.syslogFile); - t_thrd.logger.syslogFile = NULL; + t_thrd.logger.syslogFile = NULL; // 琛ㄧず鏃ュ織鏂囦欢宸茬粡鍏抽棴 } } @@ -683,25 +825,36 @@ void SysLoggerClose(void) * * print error in syslogger thread */ + +/* + * 鍔熻兘锛氬皢鏃ュ織淇℃伅鍐欏叆鎸囧畾鐨勬枃浠 + * + * 鍙傛暟锛 + * file锛氱敤浜庢寚瀹氳鍐欏叆鐨勬枃浠 + * buffer锛氱敤浜庢寚瀹氳鍐欏叆鐨勫唴瀹 + * + * 杩斿洖鍊硷細鏃 + */ static void syslogger_erewrite(FILE* file, const char* buffer) { - int tryTimes = 0; - for (;;) { + int tryTimes = 0; // 鐢ㄤ簬璁板綍閲嶈瘯鐨勬鏁 + for (;;) { // 鏃犻檺寰幆锛岀敤浜庡娆″皾璇曞啓鍏ュ唴瀹 /* clear errno before calling IO write */ - errno = 0; - int buffer_len = (int)strlen(buffer); - int rc = fwrite(buffer, 1, buffer_len, file); + errno = 0; // 娓呴櫎涔嬪墠鍙兘瀛樺湪鐨勯敊璇俊鎭 + int buffer_len = (int)strlen(buffer); // 璁$畻瑕佸啓鍏ョ殑鍐呭 buffer 鐨勯暱搴 + int rc = fwrite(buffer, 1, buffer_len, file); // 灏 buffer 涓殑鍐呭鍐欏叆鍒版寚瀹氱殑鏂囦欢 + // 妫鏌ュ啓鍏ユ搷浣滄槸鍚﹀彂鐢熶簡閿欒鎴栨湭瀹屽叏鍐欏叆 if ((errno != 0) || (rc != buffer_len)) { - tryTimes++; - if (tryTimes >= 3) - break; + tryTimes++; // 澧炲姞 tryTimes 璁℃暟鍣紝琛ㄧず灏濊瘯娆℃暟鍔犱竴 + if (tryTimes >= 3) // 濡傛灉灏濊瘯娆℃暟杈惧埌 3 娆★紝琛ㄧず宸茬粡灏濊瘯浜嗗娆″啓鍏ヤ絾浠嶇劧澶辫触 + break; // 閫鍑哄惊鐜 /* * if no disk space, we will retry, * and we can not report a log, because there is not space to write. */ - if (errno == ENOSPC) { - break; + if (errno == ENOSPC) { // 濡傛灉閿欒浠g爜 errno 琛ㄧず纾佺洏绌洪棿涓嶈冻 + break; // 閫鍑哄惊鐜紝鍥犱负鍦ㄦ病鏈夎冻澶熺鐩樼┖闂寸殑鎯呭喌涓嬶紝鏃犳硶缁х画鍐欏叆鏃ュ織淇℃伅 } } break; @@ -713,15 +866,26 @@ static void syslogger_erewrite(FILE* file, const char* buffer) * * Extract data from the arglist for exec'ed syslogger process */ + +/* + * 鍔熻兘锛氫粠鍙傛暟涓彁鍙栨枃浠舵弿杩扮锛屽苟涓哄叾鍒涘缓鏂囦欢娴 + * + * 鍙傛暟锛 + * fd锛氳〃绀烘枃浠舵弿杩扮 + * + * 杩斿洖鍊硷細鏃 + */ static void syslogger_setfd(int fd) { - if (fd != -1) { + if (fd != -1) { // 妫鏌ユ槸鍚﹀瓨鍦ㄦ湁鏁堢殑鏂囦欢鎻忚堪绗 + // 灏嗘枃浠舵弿杩扮 fd 鎵撳紑涓烘枃浠舵祦锛屽苟灏嗘枃浠舵祦鎸囬拡璧嬪 t_thrd.logger.syslogFile = fdopen(fd, "a"); - if (t_thrd.logger.syslogFile == NULL) { + if (t_thrd.logger.syslogFile == NULL) { // 妫鏌ユ枃浠舵祦鏄惁鍒涘缓鎴愬姛 + // 濡傛灉涓虹┖琛ㄧず鍒涘缓澶辫触,鐢熸垚閿欒鎶ュ憡 ereport(ERROR, (errcode_for_file_access(), errmsg("syslogger could not open file %d: %m,exit\n", fd))); proc_exit(1); } - + // 璁剧疆鏂囦欢娴佺紦鍐叉柟寮忎负涓嶄娇鐢ㄧ紦鍐诧紙_IONBF锛夛紝鍙傛暟 0 琛ㄧず涓嶈缃紦鍐插ぇ灏 setvbuf(t_thrd.logger.syslogFile, NULL, LBF_MODE, 0); } } @@ -732,15 +896,34 @@ static void syslogger_setfd(int fd) * * check whether p has the features of a LogPipeProtoHeader */ + +/* + * 鍔熻兘锛氭鏌ョ粰瀹氱殑鏁版嵁缁撴瀯 LogPipeProtoHeader 鏄惁绗﹀悎涓瀹氱殑鐗瑰緛 + * + * 鍙傛暟锛 + * P锛歀ogPipeProtoHeader 缁撴瀯浣 + * + * 杩斿洖鍊硷細bool绫诲瀷锛岃〃绀烘槸鍚︾鍚堢壒瀹氱壒寰 + * 濡傛灉绗﹀悎鐗瑰緛锛岃繑鍥 true锛岃〃绀洪氳繃妫鏌ワ紱 + * 鍚﹀垯杩斿洖 false锛岃〃绀烘湭閫氳繃妫鏌 + */ static bool CheckPipeProtoHeader(const LogPipeProtoHeader p) { + /* 妫鏌ョ粨鏋勪綋 p 鏄惁绗﹀悎: + * 缁撴瀯浣撶殑鍓嶄袱涓瓧鑺傛槸鍚﹂兘涓 NULL 瀛楃锛'\0'锛夛紝琛ㄧず瀛楃涓茬粨鏉熺 + * 缁撴瀯浣撶殑 len 瀛楁鏄惁澶т簬 0 涓斾笉瓒呰繃 LOGPIPE_MAX_PAYLOAD锛宭en 琛ㄧず鏁版嵁璐熻浇鐨勫ぇ灏 + * 缁撴瀯浣撶殑 pid 瀛楁鏄惁涓嶇瓑浜 0锛宲id 琛ㄧず杩涚▼鐨 ID + * 缁撴瀯浣撶殑 is_last 瀛楁鏄惁涓烘寚瀹氱殑瀛楃 + * 缁撴瀯浣撶殑 logtype 瀛楁鏄惁鍦ㄦ寚瀹氳寖鍥村唴锛宭ogtype 琛ㄧず鏃ュ織绫诲瀷 + * 缁撴瀯浣撶殑 magic 瀛楁鏄惁绛変簬鎸囧畾鐨勯瓟鏈暟瀛 PROTO_HEADER_MAGICNUM + */ if (p.nuls[0] == '\0' && p.nuls[1] == '\0' && p.len > 0 && p.len <= LOGPIPE_MAX_PAYLOAD && p.pid != 0 && (p.is_last == 't' || p.is_last == 'f' || p.is_last == 'T' || p.is_last == 'F') && p.logtype >= LOG_TYPE_ELOG && p.logtype < LOG_TYPE_MAXVALID && p.magic == PROTO_HEADER_MAGICNUM) - return true; - return false; + return true; // 绗﹀悎涓婅堪鐗瑰緛锛岃繑鍥 true锛岃〃绀洪氳繃妫鏌 + return false; // 杩斿洖 false锛岃〃绀烘湭閫氳繃妫鏌 } /* -------------------------------- * pipe protocol handling @@ -769,70 +952,97 @@ static bool CheckPipeProtoHeader(const LogPipeProtoHeader p) * of bytes present. On exit, any not-yet-eaten data is left-justified in * logbuffer, and *bytes_in_logbuffer is updated. */ + +/* + * 鍔熻兘锛氬鐞嗛氳繃 syslogger 绠¢亾鎺ユ敹鍒扮殑鏁版嵁锛屽苟鏍规嵁鏃ュ織绠¢亾鍗忚灏嗘棩蹇楁秷鎭粍瑁呰捣鏉 + * + * 鍙傛暟锛 + * logbuffer锛氭暟鎹緭鍏ョ紦鍐插尯 + * bytes_in_logbuffer锛氱紦鍐插尯涓殑瀛楄妭鏁 + * + * 杩斿洖鍊硷細bool绫诲瀷锛岃〃绀烘槸鍚︾鍚堢壒瀹氱壒寰 + * 濡傛灉绗﹀悎鐗瑰緛锛岃繑鍥 true锛岃〃绀洪氳繃妫鏌ワ紱 + * 鍚﹀垯杩斿洖 false锛岃〃绀烘湭閫氳繃妫鏌 + */ static void process_pipe_input(char* logbuffer, int* bytes_in_logbuffer) { char* cursor = logbuffer; - int count = *bytes_in_logbuffer; - int dest = LOG_DESTINATION_STDERR; + int count = *bytes_in_logbuffer; // 琛ㄧず鏁版嵁杈撳叆缂撳啿鍖轰腑鐨勫瓧鑺傛暟 + int dest = LOG_DESTINATION_STDERR; // 琛ㄧず鏃ュ織鐨勭洰鏍囷紝鍒濆鍊间负鏍囧噯閿欒杈撳嚭 /* While we have enough for a header, process data... */ + // 杩涘叆涓涓惊鐜紝鍙鏁版嵁杈撳叆缂撳啿鍖轰腑鐨勫瓧鑺傛暟瓒冲瑙f瀽涓涓棩蹇楃閬撳崗璁殑澶撮儴锛屽氨缁х画澶勭悊鏁版嵁 while (count >= (int)sizeof(LogPipeProtoHeader)) { - LogPipeProtoHeader p; + LogPipeProtoHeader p; // 鐢ㄤ簬瀛樺偍鏃ュ織绠¢亾鍗忚鐨勫ご閮 int chunklen; /* Do we have a valid header? */ errno_t rcs = memcpy_s(&p, sizeof(LogPipeProtoHeader), cursor, sizeof(LogPipeProtoHeader)); securec_check(rcs, "\0", "\0"); - + // 妫鏌 p 鏄惁绗﹀悎鏃ュ織绠¢亾鍗忚鐨勫ご閮ㄧ壒寰 if (CheckPipeProtoHeader(p) == true) { + // 濡傛灉鏄紝鍒欒繘鍏ュ鐞嗗崗璁秷鎭殑鍒嗘敮 List* buffer_list = NULL; ListCell* cell = NULL; save_buffer* existing_slot = NULL; save_buffer* free_slot = NULL; StringInfo str; - + // 璁$畻鍗忚娑堟伅鐨勬婚暱搴︼紝鍖呮嫭澶撮儴澶у皬鍜屾暟鎹礋杞藉ぇ灏 chunklen = LOGPIPE_HEADER_SIZE + p.len; /* Fall out of loop if we don't have the whole chunk yet */ + // 濡傛灉鏁版嵁杈撳叆缂撳啿鍖轰腑鐨勫瓧鑺傛暟涓嶈冻浠ュ畬鏁存帴鏀跺綋鍓嶆秷鎭紝鍒欒烦鍑哄惊鐜瓑寰呮洿澶氭暟鎹 if (count < chunklen) break; - + // 濡傛灉娑堟伅鐨勬棩蹇楃被鍨嬩负閿欒鏃ュ織銆佹煡璇㈣鍒掓棩蹇楁垨鎱㈡煡璇㈡棩蹇楋紝鍒欒繘鍏ュ鐞嗚繖浜涙棩蹇楃殑鍒嗘敮 if (p.logtype == LOG_TYPE_ELOG || p.logtype == LOG_TYPE_PLAN_LOG || p.logtype == LOG_TYPE_ASP_LOG) { - if (p.logtype == LOG_TYPE_PLAN_LOG) - dest = LOG_DESTINATION_QUERYLOG; + if (p.logtype == LOG_TYPE_PLAN_LOG) + dest = LOG_DESTINATION_QUERYLOG; // 琛ㄧず灏嗘棩蹇楀啓鍏ユ煡璇㈡棩蹇 else if (p.logtype == LOG_TYPE_ASP_LOG) - dest = LOG_DESTINATION_ASPLOG; + dest = LOG_DESTINATION_ASPLOG; // 琛ㄧず灏嗘棩蹇楀啓鍏ユ參鏌ヨ鏃ュ織 else + // 鏍规嵁 p.is_last 鐨勫兼潵纭畾 dest 鐨勫 + // 'T' 鎴 'F'锛屽垯灏 dest 璁剧疆涓 LOG_DESTINATION_CSVLOG锛岃〃绀哄皢鏃ュ織鍐欏叆 CSV 鏃ュ織鏂囦欢锛 + // 鍚﹀垯锛屽皢 dest 璁剧疆涓 LOG_DESTINATION_STDERR锛岃〃绀哄皢鏃ュ織鍐欏叆鏍囧噯閿欒杈撳嚭 dest = (p.is_last == 'T' || p.is_last == 'F') ? LOG_DESTINATION_CSVLOG : LOG_DESTINATION_STDERR; /* Locate any existing buffer for this source pid */ + // 鏌ユ壘鏄惁瀛樺湪宸蹭繚瀛樿鏉ユ簮杩涚▼鐨勬棩蹇楃紦鍐插尯 buffer_list = t_thrd.logger.buffer_lists[p.pid % NBUFFER_LISTS]; + // 璁块棶鐩稿簲 pid 瀵瑰簲鐨勭紦鍐插尯鍒楄〃锛屽苟閬嶅巻鍒楄〃涓殑姣忎釜缂撳啿鍖 foreach (cell, buffer_list) { save_buffer* buf = (save_buffer*)lfirst(cell); - + // 鏌ユ壘涓庡綋鍓嶆秷鎭潵婧愯繘绋 pid 鍖归厤鐨勭紦鍐插尯 if (buf->pid == p.pid) { + // 濡傛灉鎵惧埌鍖归厤鐨勭紦鍐插尯锛屽氨浼氫繚瀛樿缂撳啿鍖虹殑寮曠敤 existing_slot = buf; break; } + // 濡傛灉娌℃湁鎵惧埌鍖归厤鐨勭紦鍐插尯锛屽苟涓旇繕娌℃湁鍒嗛厤绌洪棽鐨勭紦鍐插尯 if (buf->pid == 0 && free_slot == NULL) - free_slot = buf; + free_slot = buf; // 鍒涘缓涓涓柊鐨勭紦鍐插尯 } - + // 濡傛灉褰撳墠娑堟伅涓嶆槸鏈鍚庝竴涓秷鎭殑鍒嗙墖锛屽皢娑堟伅鐨勬暟鎹坊鍔犲埌鐩稿簲鐨勭紦鍐插尯 if (p.is_last == 'f' || p.is_last == 'F') { /* * Save a complete non-final chunk in a per-pid buffer */ + // 濡傛灉娑堟伅鍧椾笉鏄渶鍚庝竴涓 + // 濡傛灉宸茬粡瀛樺湪涓庢潵婧愯繘绋 pid 鍖归厤鐨勭紦鍐插尯 if (existing_slot != NULL) { /* Add chunk to data from preceding chunks */ + // 灏嗗綋鍓嶆秷鎭潡娣诲姞鍒颁箣鍓嶅凡淇濆瓨鐨勬秷鎭暟鎹腑 str = &(existing_slot->data); appendBinaryStringInfo(str, cursor + LOGPIPE_HEADER_SIZE, p.len); } else { /* First chunk of message, save in a new buffer */ + // 濡傛灉娌℃湁宸插瓨鍦ㄧ殑缂撳啿鍖猴紝鍒欏垱寤轰竴涓柊鐨勭紦鍐插尯 if (free_slot == NULL) { /* * Need a free slot, but there isn't one in the list, * so create a new one and extend the list with it. */ + // 灏嗗綋鍓嶆秷鎭潡淇濆瓨鍒拌缂撳啿鍖轰腑锛岀劧鍚庡皢璇ョ紦鍐插尯娣诲姞鍒扮浉搴旂殑缂撳啿鍖哄垪琛ㄤ腑 free_slot = (save_buffer*)palloc(sizeof(save_buffer)); buffer_list = lappend(buffer_list, free_slot); t_thrd.logger.buffer_lists[p.pid % NBUFFER_LISTS] = buffer_list; @@ -843,33 +1053,44 @@ static void process_pipe_input(char* logbuffer, int* bytes_in_logbuffer) appendBinaryStringInfo(str, cursor + LOGPIPE_HEADER_SIZE, p.len); } } else { + // 濡傛灉娑堟伅鍧楁槸鏈鍚庝竴涓 /* * Final chunk --- add it to anything saved for that pid, and * either way write the whole thing out. */ + // 濡傛灉宸茬粡瀛樺湪涓庢潵婧愯繘绋 pid 鍖归厤鐨勭紦鍐插尯 if (existing_slot != NULL) { + // 灏嗗綋鍓嶆秷鎭潡娣诲姞鍒颁箣鍓嶅凡淇濆瓨鐨勬秷鎭暟鎹腑 str = &(existing_slot->data); appendBinaryStringInfo(str, cursor + LOGPIPE_HEADER_SIZE, p.len); + // 灏嗘暣涓秷鎭啓鍏ユ棩蹇楁枃浠 write_syslogger_file(str->data, str->len, dest); /* Mark the buffer unused, and reclaim string storage */ existing_slot->pid = 0; pfree(str->data); } else { + // 濡傛灉娌℃湁宸插瓨鍦ㄧ殑缂撳啿鍖猴紝璇存槑鏁翠釜娑堟伅灏辨槸涓涓潡 /* The whole message was one chunk, evidently. */ + // 鐩存帴灏嗘秷鎭潡鍐欏叆鏃ュ織鏂囦欢 write_syslogger_file(cursor + LOGPIPE_HEADER_SIZE, p.len, dest); } } - } else if (p.logtype < LOG_TYPE_MAXVALID) { + } else if (p.logtype < LOG_TYPE_MAXVALID) { // 濡傛灉娑堟伅鐨勬棩蹇楃被鍨嬪皬浜 LOG_TYPE_MAXVALID Assert(LOG_TYPE_MAXVALID <= LOG_TYPE_UPLIMIT); + // 澶勭悊娑堟伅鍧楁暟鎹紝鏍规嵁娑堟伅鐨勭被鍨嬪皢娑堟伅浼犻掑埌鐩稿簲鐨勬棩蹇楁枃浠 LogCtlProcessInput(allLogCtl[(int)p.logtype], cursor + LOGPIPE_HEADER_SIZE, p.len); } else { + // 濡傛灉娑堟伅鐨勬棩蹇楃被鍨嬭秴鍑轰簡 LOG_TYPE_MAXVALID 鐨勪笂闄 + // 瑙﹀彂鏂█澶辫触锛岃〃绀哄彂鐜颁簡涓嶆敮鎸佺殑鏃ュ織绫诲瀷 Assert(0); } /* Finished processing this chunk */ + // 鏇存柊娓告爣浣嶇疆鍜屽墿浣欏瓧鑺傛暟 cursor += chunklen; count -= chunklen; } else { + // 濡傛灉娑堟伅澶翠笉绗﹀悎鏃ュ織绠¢亾鍗忚鐨勬牸寮 /* Process non-protocol data */ /* * Look for the start of a protocol header. If found, dump data @@ -880,7 +1101,11 @@ static void process_pipe_input(char* logbuffer, int* bytes_in_logbuffer) * message will arrive all in one read(), and we want to respect * the read() boundary if possible.) */ + // 閬嶅巻鏌ユ壘闈炲崗璁暟鎹殑娑堟伅澶磋捣濮嬩綅缃 for (chunklen = 1; chunklen < count; chunklen++) { + // 濡傛灉鎵惧埌浜嗘秷鎭ご璧峰浣嶇疆锛屽垯鎴彇鍒版秷鎭ご鍓嶇殑鏁版嵁骞剁户缁惊鐜鐞 + // 鍚﹀垯灏嗘墍鏈夐潪鍗忚鏁版嵁鍐欏叆鏍囧噯閿欒鏃ュ織鏂囦欢 + // 纭繚闈炲崗璁秷鎭湪鍐欏叆鏃ュ織鏂囦欢鏃朵笉浼氳鎴柇锛屽敖閲忎繚鎸佸畬鏁存 if (cursor[chunklen] == '\0') break; } @@ -892,11 +1117,13 @@ static void process_pipe_input(char* logbuffer, int* bytes_in_logbuffer) } /* We don't have a full chunk, so left-align what remains in the buffer */ + // 濡傛灉鍓╀綑鏁版嵁涓嶈冻浠ョ粍鎴愪竴涓畬鏁寸殑娑堟伅鍧 if (count > 0 && cursor != logbuffer) { + // 灏嗗墿浣欐暟鎹乏绉讳互瑕嗙洊鍓嶉潰宸插鐞嗙殑鏁版嵁锛屼互渚夸笅涓娆″鐞 errno_t rc = memmove_s(logbuffer, count, cursor, count); securec_check_c(rc, "\0", "\0"); } - *bytes_in_logbuffer = count; + *bytes_in_logbuffer = count; // 鏇存柊鍓╀綑瀛楄妭鏁 } /* @@ -905,25 +1132,40 @@ static void process_pipe_input(char* logbuffer, int* bytes_in_logbuffer) * This is currently used only at syslogger shutdown, but could perhaps be * useful at other times, so it is careful to leave things in a clean state. */ + +/* + * 鍔熻兘锛氬己鍒跺皢浠讳綍缂撳啿鐨勬暟鎹緭鍑哄埌鏃ュ織鏂囦欢 + * + * 鍙傛暟锛 + * logbuffer锛氱敤浜庡瓨鍌ㄥ緟杈撳嚭鏁版嵁鐨勭紦鍐插尯 + * bytes_in_logbuffer锛氱紦鍐插尯涓殑瀛楄妭鏁 + * + * 杩斿洖鍊硷細bool绫诲瀷锛岃〃绀烘槸鍚︾鍚堢壒瀹氱壒寰 + * 濡傛灉绗﹀悎鐗瑰緛锛岃繑鍥 true锛岃〃绀洪氳繃妫鏌ワ紱 + * 鍚﹀垯杩斿洖 false锛岃〃绀烘湭閫氳繃妫鏌 + */ static void flush_pipe_input(char* logbuffer, int* bytes_in_logbuffer) { int i; /* Dump any incomplete protocol messages */ + // 閬嶅巻涓嶅悓鏉ユ簮杩涚▼鐨勭紦鍐插尯鍒楄〃锛屽鐞嗕笉瀹屾暣鐨勫崗璁秷鎭 for (i = 0; i < NBUFFER_LISTS; i++) { + // 鑾峰彇褰撳墠鏉ユ簮杩涚▼鐨勭紦鍐插尯鍒楄〃锛屼互鍙婅鍒楄〃鐨勫厓绱犺凯浠e櫒 List* list = t_thrd.logger.buffer_lists[i]; ListCell* cell = NULL; foreach (cell, list) { save_buffer* buf = (save_buffer*)lfirst(cell); - if (buf->pid != 0) { + if (buf->pid != 0) { // 妫鏌ョ紦鍐插尯鏄惁鍖呭惈鏁版嵁 + // 濡傛灉缂撳啿鍖轰腑鍖呭惈鏁版嵁锛屽皢鏁版嵁鍐欏叆鏍囧噯閿欒鏃ュ織鏂囦欢 + // 鑾峰彇缂撳啿鍖轰腑鐨勬暟鎹瓧绗︿覆 str锛屽苟浣跨敤鍏朵腑鐨勬暟鎹拰闀垮害鏉ュ啓鍏ユ棩蹇 StringInfo str = &(buf->data); - write_syslogger_file(str->data, str->len, LOG_DESTINATION_STDERR); /* Mark the buffer unused, and reclaim string storage */ - buf->pid = 0; - pfree(str->data); + buf->pid = 0; // 鏍囪缂撳啿鍖烘湭浣跨敤 + pfree(str->data); // 閲婃斁缂撳啿鍖轰腑鐨勫瓧绗︿覆瀛樺偍绌洪棿锛屼互渚块噸鐢 } } } @@ -932,9 +1174,10 @@ static void flush_pipe_input(char* logbuffer, int* bytes_in_logbuffer) * Force out any remaining pipe data as-is; we don't bother trying to * remove any protocol headers that may exist in it. */ - if (*bytes_in_logbuffer > 0) + if (*bytes_in_logbuffer > 0) // 妫鏌ョ紦鍐插尯涓槸鍚︽湁鍓╀綑鐨勬暟鎹 + // 濡傛灉鏈夊垯灏嗗叾鍐欏叆鏍囧噯閿欒鏃ュ織鏂囦欢 write_syslogger_file(logbuffer, *bytes_in_logbuffer, LOG_DESTINATION_STDERR); - *bytes_in_logbuffer = 0; + *bytes_in_logbuffer = 0; // 琛ㄧず缂撳啿鍖虹幇鍦ㄤ负绌 } /* -------------------------------- @@ -948,15 +1191,31 @@ static void flush_pipe_input(char* logbuffer, int* bytes_in_logbuffer) * This allows the syslogger process to record elog messages of its own, * even though its stderr does not point at the syslog pipe. */ + +/* + * 鍔熻兘锛氬皢鏂囨湰鍐欏叆褰撳墠鎵撳紑鐨勬棩蹇楁枃浠 + * + * 鍙傛暟锛 + * buffer锛氬寘鍚鍐欏叆鏃ュ織鏂囦欢鐨勬枃鏈暟鎹殑缂撳啿鍖 + * count锛氳鍐欏叆鐨勫瓧鑺傛暟 + * destination锛氭寚绀哄啓鍏ョ殑鏃ュ織鏂囦欢鐨勭洰鏍囷紝鍙互鏄互涓嬮夐」涔嬩竴锛 + * LOG_DESTINATION_STDERR锛氭爣鍑嗛敊璇棩蹇楁枃浠躲 + * LOG_DESTINATION_CSVLOG锛欳SV 鏃ュ織鏂囦欢銆 + * LOG_DESTINATION_QUERYLOG锛氭煡璇㈡棩蹇楁枃浠躲 + * LOG_DESTINATION_ASPLOG锛氭椿鍔ㄤ細璇濆垎鏋愭棩蹇楁枃浠 + * + * 杩斿洖鍊硷細鏃 + */ void write_syslogger_file(char* buffer, int count, int destination) { int rc; - FILE* logfile = NULL; - bool doOpen = false; - + FILE* logfile = NULL; // 鐢ㄤ簬琛ㄧず褰撳墠瑕佸啓鍏ョ殑鏃ュ織鏂囦欢 + bool doOpen = false; // 鐢ㄤ簬琛ㄧず鏄惁闇瑕佹墦寮鏃ュ織鏂囦欢 + // 妫鏌ョ洰鏍囨槸鍚︿负 CSV 鏃ュ織锛屽苟涓斿綋鍓 CSV 鏃ュ織鏂囦欢鏈墦寮 if (destination == LOG_DESTINATION_CSVLOG && t_thrd.logger.csvlogFile == NULL) - open_csvlogfile(); - + open_csvlogfile(); // 濡傛灉鏄紝鍒欐墦寮 CSV 鏃ュ織鏂囦欢 + + // 鏍规嵁鐩爣纭畾瑕佸啓鍏ョ殑鏃ュ織鏂囦欢锛屽苟鏍规嵁闇瑕佹墦寮璇ユ枃浠 if (destination == LOG_DESTINATION_QUERYLOG) logfile = (FILE *)SQMOpenLogFile(&doOpen); else if (destination == LOG_DESTINATION_ASPLOG) @@ -966,20 +1225,23 @@ void write_syslogger_file(char* buffer, int count, int destination) errno = 0; - rc = fwrite(buffer, 1, count, logfile); + rc = fwrite(buffer, 1, count, logfile); // 灏嗘寚瀹氭暟閲忕殑瀛楄妭浠 buffer 鍐欏叆 logfile /* can't use ereport here because of possible recursion */ - if (rc != count) { + if (rc != count) { // 妫鏌ュ啓鍏ョ殑瀛楄妭鏁版槸鍚︿笌鎸囧畾鐨勫瓧鑺傛暟鐩哥瓑锛屼互纭畾鍐欏叆鏄惁鎴愬姛 /* * if no disk space, we will retry, * and we can not report a log, because there is not space to write. */ + // 濡傛灉鍐欏叆澶辫触鐨勫師鍥犳槸纾佺洏绌洪棿涓嶈冻 if (errno == ENOSPC) { - return; + return; // 鍑芥暟杩斿洖锛屼笉杩涜閿欒澶勭悊 } + // 鏋勯犻敊璇秷鎭瓧绗︿覆 errorbuf锛屽寘鍚敊璇俊鎭拰鎻忚堪淇℃伅 char errorbuf[ERROR_BUF_SIZE] = {'\0'}; rc = sprintf_s(errorbuf, ERROR_BUF_SIZE, "ERROR: could not write to log file: %s\n", gs_strerror(errno)); securec_check_ss_c(rc, "\0", "\0"); + // 灏嗛敊璇秷鎭啓鍏ユ棩蹇楁枃浠朵互璁板綍閿欒淇℃伅 syslogger_erewrite(logfile, errorbuf); } } @@ -993,18 +1255,30 @@ void write_syslogger_file(char* buffer, int count, int destination) * unnamed pipes: it always reports "signaled", so the blocking ReadFile won't * allow for SIGHUP; and select is for sockets only. */ + +/* + * 鍔熻兘锛氬己鍒跺埛鏂扮閬撲腑鐨勭紦鍐叉暟鎹 + * 涓嶆柇浠庣閬撲腑璇诲彇鏁版嵁锛屽鐞嗘暟鎹苟鍐欏叆鏃ュ織鏂囦欢锛岀洿鍒版娴嬪埌绠¢亾宸插叧闂 + * 濡傛灉褰撳墠鏃ュ織鏂囦欢澶у皬杈惧埌浜嗘棩蹇楄疆鎹㈢殑澶у皬闄愬埗锛屼細瑙﹀彂涓荤嚎绋嬫墽琛屾棩蹇楄疆鎹㈡搷浣 + * + * 鍙傛暟锛 + * char* logbuffer锛氭寚鍚戝寘鍚暟鎹殑缂撳啿鍖虹殑鎸囬拡 + * int* bytes_in_logbuffer锛氭寚鍚戣〃绀虹紦鍐插尯涓瓧鑺傛暟鐨勬暣鏁版寚閽 + * + * 杩斿洖鍊硷細鏃 + */ static unsigned int __stdcall pipeThread(void* arg) { - char logbuffer[READ_BUF_SIZE]; - int bytes_in_logbuffer = 0; - - for (;;) { - DWORD bytesRead; - BOOL result = false; + char logbuffer[READ_BUF_SIZE]; // 瀹氫箟涓涓紦鍐插尯鐢ㄤ簬瀛樺偍浠庣閬撲腑璇诲彇鐨勬暟鎹 + int bytes_in_logbuffer = 0; // 璁板綍缂撳啿鍖轰腑褰撳墠鐨勫瓧鑺傛暟 + for (;;) { // 寰幆閬嶅巻澶氫釜缂撳啿鍖哄垪琛 涓嶆柇浠庣閬撲腑璇诲彇鏁版嵁 + DWORD bytesRead; // 鐢ㄤ簬璁板綍浠庣閬撲腑瀹為檯璇诲彇鐨勫瓧鑺傛暟 + BOOL result = false; // 鐢ㄤ簬璁板綍ReadFile鍑芥暟鐨勬墽琛岀粨鏋 + // 浠庣閬撲腑璇诲彇鏁版嵁鍒發ogbuffer涓 result = ReadFile(t_thrd.postmaster_cxt.syslogPipe[0], - logbuffer + bytes_in_logbuffer, - sizeof(logbuffer) - bytes_in_logbuffer, + logbuffer + bytes_in_logbuffer, // // 灏嗘暟鎹拷鍔犲埌缂撳啿鍖虹殑鏈熬 + sizeof(logbuffer) - bytes_in_logbuffer, // // 鍓╀綑缂撳啿鍖哄ぇ灏 &bytesRead, 0); @@ -1014,23 +1288,25 @@ static unsigned int __stdcall pipeThread(void* arg) * palloc()/pfree() in particular are not safe outside the critical * section. */ + // 杩涘叆涓寸晫鍖猴紝淇濇姢鍚庣画鎿嶄綔涓嶈鍏朵粬绾跨▼骞叉壈 EnterCriticalSection(&sysloggerSection); if (!result) { DWORD error = GetLastError(); - + // 澶勭悊浠庣閬撲腑璇诲彇鏁版嵁鏃跺嚭鐜扮殑閿欒 if (error == ERROR_HANDLE_EOF || error == ERROR_BROKEN_PIPE) - break; + break; // 绠¢亾宸插叧闂紝閫鍑哄惊鐜 _dosmaperr(error); ereport(LOG, (errcode_for_file_access(), errmsg("could not read from logger pipe: %m"))); } else if (bytesRead > 0) { - bytes_in_logbuffer += bytesRead; - process_pipe_input(logbuffer, &bytes_in_logbuffer); + bytes_in_logbuffer += bytesRead; // 鏇存柊缂撳啿鍖轰腑鐨勫瓧鑺傛暟 + process_pipe_input(logbuffer, &bytes_in_logbuffer); // 澶勭悊浠庣閬撲腑璇诲彇鐨勬暟鎹 } /* * If we've filled the current logfile, nudge the main thread to do a * log rotation. */ + // 濡傛灉褰撳墠鏃ュ織鏂囦欢杈惧埌浜嗘棩蹇楄疆鎹㈢殑澶у皬闄愬埗锛屽垯閫氱煡涓荤嚎绋嬫墽琛屾棩蹇楄疆鎹 if (u_sess->attr.attr_common.Log_RotationSize > 0) { if (ftell(t_thrd.logger.syslogFile) >= u_sess->attr.attr_common.Log_RotationSize * 1024L || (t_thrd.logger.querylogFile != NULL && @@ -1039,21 +1315,21 @@ static unsigned int __stdcall pipeThread(void* arg) ftell(t_thrd.logger.asplogFile) >= u_sess->attr.attr_common.Log_RotationSize * 1024L) || (t_thrd.logger.csvlogFile != NULL && ftell(t_thrd.logger.csvlogFile) >= u_sess->attr.attr_common.Log_RotationSize * 1024L)) - SetLatch(&t_thrd.logger.sysLoggerLatch); + SetLatch(&t_thrd.logger.sysLoggerLatch); // 璁剧疆淇″彿閲忥紝閫氱煡涓荤嚎绋嬫墽琛屾棩蹇楄疆鎹 } - LeaveCriticalSection(&sysloggerSection); + LeaveCriticalSection(&sysloggerSection); // 閫鍑轰复鐣屽尯 } /* We exit the above loop only upon detecting pipe EOF */ - t_thrd.logger.pipe_eof_seen = true; + t_thrd.logger.pipe_eof_seen = true; // 琛ㄧず绠¢亾宸插叧闂 /* if there's any data left then force it out now */ flush_pipe_input(logbuffer, &bytes_in_logbuffer); /* set the latch to waken the main thread, which will quit */ - SetLatch(&t_thrd.logger.sysLoggerLatch); + SetLatch(&t_thrd.logger.sysLoggerLatch); // 璁剧疆淇″彿閲忥紝閫氱煡涓荤嚎绋嬮鍑 - LeaveCriticalSection(&sysloggerSection); + LeaveCriticalSection(&sysloggerSection); // 閫鍑虹嚎绋 _endthread(); return 0; } @@ -1067,18 +1343,30 @@ static unsigned int __stdcall pipeThread(void* arg) * process, not during rotations. As with opening the main log file, we * always append in this situation. */ + +/* + * 鍔熻兘锛氭墦寮CSV鏍煎紡鐨勬棩蹇楁枃浠讹紝浣嗘槸鍙湁鍦ㄧ涓娆℃墦寮璇ユ枃浠舵椂鎵嶆墽琛岋紝涓嶄細鍦ㄦ棩蹇楄疆鎹㈡椂鎵ц + * 鏋勫缓CSV鏃ュ織鏂囦欢鐨勬枃浠跺悕锛岀劧鍚庝互杩藉姞妯″紡鎵撳紑鏂囦欢 + * + * 鍙傛暟锛氭棤 + * + * 杩斿洖鍊硷細鏃 + */ static void open_csvlogfile(void) { - char* filename = NULL; - + char* filename = NULL; // 鐢ㄤ簬瀛樺偍CSV鏃ュ織鏂囦欢鐨勬枃浠跺悕 + // 鏋勫缓CSV鏃ュ織鏂囦欢鐨勬枃浠跺悕 filename = logfile_getname( time(NULL), ".csv", u_sess->attr.attr_common.Log_directory, u_sess->attr.attr_common.Log_filename); - + + // 鎵撳紑CSV鏃ュ織鏂囦欢锛屼互杩藉姞妯″紡鎵撳紑 t_thrd.logger.csvlogFile = logfile_open(filename, "a", false); - + + // 濡傛灉涓婁竴娆℃墦寮鐨凜SV鏃ュ織鏂囦欢鍚嶄笉涓虹┖锛屽垯閲婃斁鍏跺唴瀛 if (t_thrd.logger.last_csv_file_name != NULL) /* probably shouldn't happen */ pfree(t_thrd.logger.last_csv_file_name); - + + // 璁板綍褰撳墠鎵撳紑鐨凜SV鏃ュ織鏂囦欢鍚 t_thrd.logger.last_csv_file_name = filename; } @@ -1092,26 +1380,40 @@ static void open_csvlogfile(void) * (with errno still correct for the fopen failure). * Otherwise, errors are treated as fatal. */ + +/* + * 鍔熻兘锛氫互鎸囧畾鐨勬ā寮忔墦寮涓涓柊鐨勬棩蹇楁枃浠讹紝骞惰缃傚綋鐨勬潈闄愬拰缂撳啿閫夐」 + * + * 鍙傛暟锛 + * filename锛氳鎵撳紑鐨勬枃浠剁殑璺緞鍜屽悕绉 + * mode锛氭墦寮鏂囦欢鐨勬ā寮忥紝濡 "r"銆"w"銆"a" 绛 + * allow_errors锛氭槸鍚﹀厑璁稿嚭鐜伴敊璇紝濡傛灉涓 true锛屽垯鍙褰曢敊璇紝涓嶄細寮曞彂鑷村懡閿欒 + * + * 杩斿洖鍊硷細 + * 濡傛灉鎴愬姛鎵撳紑鏂囦欢锛屽垯杩斿洖鎸囧悜鏂囦欢鐨勬寚閽堬紙鏂囦欢鍙ユ焺锛夛紝濡傛灉澶辫触锛屽垯杩斿洖 NULL + */ static FILE* logfile_open(const char* filename, const char* mode, bool allow_errors) { - FILE* fh = NULL; - struct stat checkdir; - bool dirIsExist = false; + FILE* fh = NULL; // 鏂囦欢鍙ユ焺 + struct stat checkdir; // 鐢ㄤ簬妫鏌ョ洰褰曟槸鍚﹀瓨鍦ㄧ殑缁撴瀯浣 + bool dirIsExist = false; // 鏍囧織鐩綍鏄惁瀛樺湪 /* * Note we do not let Log_file_mode disable IWUSR, since we certainly want * to be able to write the files ourselves. */ + // 濡傛灉 filename 涓 NULL锛屾姤閿欙紝鍚﹀垯缁х画鎵ц if (filename == NULL) { ereport(ERROR, (errcode(ERRCODE_UNEXPECTED_NULL_VALUE), errmsg("group_name can not be NULL "))); } - + // 妫鏌ユ枃浠舵垨鐩綍鏄惁瀛樺湪 if (stat(filename, &checkdir) == 0) { dirIsExist = true; } - + // 鎵撳紑鏂囦欢锛屼娇鐢ㄦ寚瀹氱殑妯″紡 fh = fopen(filename, mode); if (fh != NULL) { + // 濡傛灉鎴愬姛鎵撳紑锛岃缃枃浠剁殑缂撳啿妯″紡 setvbuf(fh, NULL, LBF_MODE, 0); #ifdef WIN32 @@ -1122,6 +1424,7 @@ static FILE* logfile_open(const char* filename, const char* mode, bool allow_err int save_errno = errno; if (allow_errors) { + // 濡傛灉鍏佽鍑虹幇閿欒锛岃褰曟墦寮鏂囦欢澶辫触鐨勯敊璇俊鎭 ereport(LOG, (errcode_for_file_access(), errmsg("could not open log file \"%s\": %m", filename))); errno = save_errno; } else { @@ -1129,12 +1432,13 @@ static FILE* logfile_open(const char* filename, const char* mode, bool allow_err * If open file failed, we can not write any log to file, make the * system crash is safe. */ + // 濡傛灉鎵撳紑鏂囦欢澶辫触涓斾笉鍏佽閿欒锛屽垯灏嗙郴缁熺疆涓哄穿婧冪姸鎬侊紝鎶ラ敊 ereport(WARNING, (errcode_for_file_access(), errmsg("failed to open log file \"%s\": %m", filename))); - + // 绂佹绔嬪嵆涓柇 t_thrd.int_cxt.ImmediateInterruptOK = false; - fflush(stdout); - fflush(stderr); - abort(); + fflush(stdout); // 鍒锋柊鏍囧噯杈撳嚭娴侊紝纭繚浠讳綍鍦ㄨ緭鍑虹紦鍐插尯涓殑鏁版嵁閮借鍐欏叆鍒版爣鍑嗚緭鍑 + fflush(stderr); // 鍒锋柊鏍囧噯閿欒娴侊紝纭繚浠讳綍鍦ㄩ敊璇紦鍐插尯涓殑鏁版嵁閮借鍐欏叆鍒版爣鍑嗛敊璇 + abort(); // 鐢ㄤ簬琛ㄧず鍙戠敓浜嗕弗閲嶉敊璇紝闇瑕佺珛鍗冲仠姝㈢▼搴忕殑鎵ц } } @@ -1142,18 +1446,22 @@ static FILE* logfile_open(const char* filename, const char* mode, bool allow_err * Note we do not let Log_file_mode disable IWUSR, since we certainly want * to be able to write the files ourselves. */ + // 濡傛灉鐩綍涓嶅瓨鍦紝鍒欒缃枃浠剁殑鏉冮檺 if (!dirIsExist) { + // 妫鏌 chmod 璋冪敤鏄惁鎴愬姛锛屽皢鏃ュ織鏂囦欢鐨勬潈闄愯缃负鍏佽鏂囦欢鐨勬嫢鏈夎呭啓鍏ワ紝骞剁‘淇濅笉鍏佽鎵ц鏂囦欢 + // chmod鍑芥暟鏄竴涓郴缁熻皟鐢紝鐢ㄤ簬鏇存敼鏂囦欢鐨勬潈闄愭ā寮 + // 鍙傛暟锛氳淇敼鏉冮檺鐨勬枃浠剁殑璺緞 filename 鍜屾柊鐨勬潈闄愭ā寮 if (chmod(filename, (((mode_t)u_sess->attr.attr_common.Log_file_mode | S_IWUSR) & (~S_IXUSR) & (~S_IXOTH) & (~S_IXGRP))) < 0) { - int save_errno = errno; - + int save_errno = errno; // 淇濆瓨閿欒鐮 + // 璁板綍鏇存敼鏂囦欢鏉冮檺澶辫触鐨勯敊璇俊鎭 ereport(allow_errors ? LOG : FATAL, (errcode_for_file_access(), errmsg("could not chmod log file \"%s\": %m", filename))); - errno = save_errno; + errno = save_errno; // 鎭㈠閿欒鐮 } } - return fh; + return fh; // 杩斿洖鏂囦欢鍙ユ焺 } #if defined(ENABLE_UT) && defined(static) #undef static @@ -1162,27 +1470,41 @@ static FILE* logfile_open(const char* filename, const char* mode, bool allow_err /* * perform logfile rotation */ + +/* + * 鍔熻兘锛氭墽琛屾棩蹇楁枃浠剁殑杞崲 + * + * 鍙傛暟锛 + * time_based_rotation锛氫竴涓竷灏斿硷紝鎸囩ず鏄惁鍩轰簬鏃堕棿杩涜杞崲 + * size_rotation_for锛氫竴涓暣鏁帮紝鎸囩ず鏄惁鏍规嵁鏂囦欢澶у皬杩涜杞崲鐨勬爣蹇 + * + * 杩斿洖鍊硷細鏃 + */ static void logfile_rotate(bool time_based_rotation, int size_rotation_for) { - char* filename = NULL; - char* csvfilename = NULL; - pg_time_t fntime; - FILE* fh = NULL; + char* filename = NULL; // 鐢ㄤ簬瀛樺偍鏂版棩蹇楁枃浠剁殑鏂囦欢鍚 + char* csvfilename = NULL; // 鐢ㄤ簬瀛樺偍鏂扮殑 CSV 鏃ュ織鏂囦欢鐨勬枃浠跺悕 + pg_time_t fntime; // 鐢ㄤ簬瀛樺偍杞崲鐨勬椂闂存埑 + FILE* fh = NULL; // 鐢ㄤ簬鎵撳紑鏂扮殑鏃ュ織鏂囦欢 - t_thrd.logger.rotation_requested = false; + t_thrd.logger.rotation_requested = false; // 琛ㄧず涓嶉渶瑕佹墽琛屾棩蹇楁枃浠惰疆鎹 /* * When doing a time-based rotation, invent the new logfile name based on * the planned rotation time, not current time, to avoid "slippage" in the * file name when we don't do the rotation immediately. */ + // 濡傛灉time_based_rotation 涓 true if (time_based_rotation) + // 浣跨敤棰勫畾鐨勮疆鎹㈡椂闂磋屼笉鏄綋鍓嶆椂闂达紝浠ラ伩鍏嶆枃浠跺悕鐨勨滄粦鍔ㄢ fntime = t_thrd.logger.next_rotation_time; else - fntime = time(NULL); + fntime = time(NULL); // 鍚﹀垯锛屼娇鐢ㄥ綋鍓嶆椂闂 + // 鏋勯犳柊鏃ュ織鏂囦欢鐨勬枃浠跺悕锛屽寘鎷洰褰曘佹枃浠跺悕鍓嶇紑绛変俊鎭 filename = logfile_getname(fntime, NULL, u_sess->attr.attr_common.Log_directory, u_sess->attr.attr_common.Log_filename); - if (t_thrd.logger.csvlogFile != NULL) + if (t_thrd.logger.csvlogFile != NULL) // 濡傛灉瀛樺湪 CSV 鏃ュ織鏂囦欢 + // 鏋勯 CSV 鏂囦欢鐨勬枃浠跺悕 csvfilename = logfile_getname( fntime, ".csv", u_sess->attr.attr_common.Log_directory, u_sess->attr.attr_common.Log_filename); @@ -1194,77 +1516,87 @@ static void logfile_rotate(bool time_based_rotation, int size_rotation_for) * * Note: t_thrd.logger.last_file_name should never be NULL here, but if it is, append. */ + // 濡傛灉鏄熀浜庢椂闂寸殑杞崲鎴栭渶瑕佽疆鎹㈠埌鏍囧噯閿欒鏃ュ織 if (time_based_rotation || (size_rotation_for & LOG_DESTINATION_STDERR)) { + // 濡傛灉閰嶇疆涓厑璁稿湪杞崲鏃舵埅鏂棩蹇楁枃浠讹紝骞朵笖杞崲鏄熀浜庢椂闂磋Е鍙戠殑锛屼笖鏂扮殑鏂囦欢鍚嶄笌涓婃涓嶅悓 if (u_sess->attr.attr_common.Log_truncate_on_rotation && time_based_rotation && t_thrd.logger.last_file_name != NULL && strcmp(filename, t_thrd.logger.last_file_name) != 0) + // 鎵撳紑鏂扮殑鏃ュ織鏂囦欢浠ヨ繘琛屽啓鍏ユ搷浣滐紝濡傛灉鏂囦欢宸插瓨鍦紝灏嗗叾鎴柇涓虹┖鏂囦欢 fh = logfile_open(filename, "w", true); else + // 鎵撳紑鏂扮殑鏃ュ織鏂囦欢浠ヨ繘琛岃拷鍔犲啓鍏ユ搷浣滐紝涓嶆埅鏂凡瀛樺湪鐨勬枃浠跺唴瀹 fh = logfile_open(filename, "a", true); - if (fh == NULL) { + if (fh == NULL) { // 濡傛灉鎵撳紑鏂扮殑鏃ュ織鏂囦欢澶辫触 /* * ENFILE/EMFILE are not too surprising on a busy system; just * keep using the old file till we manage to get a new one. * Otherwise, assume something's wrong with Log_directory and stop * trying to create files. */ + // 濡傛灉閿欒浠g爜涓嶆槸 ENFILE 鎴 EMFILE锛屽垯琛ㄧず鍙兘瀛樺湪鏇翠弗閲嶇殑闂 if (errno != ENFILE && errno != EMFILE) { + // 鍙戝嚭涓涓棩蹇楄褰曟秷鎭紝绂佺敤鑷姩杞崲锛屼互闃叉缁х画灏濊瘯鍒涘缓鏂版枃浠 ereport(LOG, (errmsg("disabling automatic rotation (use SIGHUP to re-enable)"))); t_thrd.logger.rotation_disabled = true; } if (filename != NULL) - pfree(filename); + pfree(filename); // 閲婃斁鍒嗛厤鐨勬枃浠跺悕鍐呭瓨锛屼互閬垮厤鍐呭瓨娉勬紡 if (csvfilename != NULL) - pfree(csvfilename); - return; + pfree(csvfilename); // 閲婃斁鍒嗛厤鐨 CSV 鏂囦欢鍚嶅唴瀛 + return; // 涓嶆墽琛屽悗缁殑鏃ュ織杞崲鎿嶄綔 } - fclose(t_thrd.logger.syslogFile); + fclose(t_thrd.logger.syslogFile); // 鍏抽棴鍏堝墠鐨勬棩蹇楁枃浠讹紝纭繚灏嗘棩蹇楀啓鍏ユ柊鏂囦欢 t_thrd.logger.syslogFile = fh; /* instead of pfree'ing filename, remember it for next time */ if (t_thrd.logger.last_file_name != NULL) - pfree(t_thrd.logger.last_file_name); + pfree(t_thrd.logger.last_file_name); // 閲婃斁涓婁竴娆$殑鏂囦欢鍚嶅唴瀛橈紝浠ラ伩鍏嶅唴瀛樻硠婕 t_thrd.logger.last_file_name = filename; - filename = NULL; + filename = NULL; // 浠ラ伩鍏嶉噸澶嶉噴鏀惧唴瀛 } /* Same as above, but for csv file. */ + // 濡傛灉 t_thrd.logger.csvlogFile 涓嶄负 NULL锛 + // 涓 杞崲鍩轰簬鏃堕棿瑙﹀彂鎴栬疆鎹㈠熀浜庢枃浠跺ぇ灏忚Е鍙戞垨褰撳墠鏃ュ織鐩殑鍦板寘鎷 CSV 鏃ュ織 if (t_thrd.logger.csvlogFile != NULL && (time_based_rotation || (size_rotation_for & LOG_DESTINATION_CSVLOG)) && ((unsigned int)t_thrd.log_cxt.Log_destination & LOG_DESTINATION_CSVLOG)) { if (u_sess->attr.attr_common.Log_truncate_on_rotation && time_based_rotation && t_thrd.logger.last_csv_file_name != NULL && strcmp(csvfilename, t_thrd.logger.last_csv_file_name) != 0) - fh = logfile_open(csvfilename, "w", true); + fh = logfile_open(csvfilename, "w", true); // 浠ヨ鐩栨ā寮忔垨杩藉姞妯″紡鎵撳紑 CSV 鏃ュ織鏂囦欢 else fh = logfile_open(csvfilename, "a", true); - if (fh == NULL) { + if (fh == NULL) { // 濡傛灉鏂囦欢鎵撳紑澶辫触 /* * ENFILE/EMFILE are not too surprising on a busy system; just * keep using the old file till we manage to get a new one. * Otherwise, assume something's wrong with Log_directory and stop * trying to create files. */ + // 濡傛灉閿欒鐮佷笉鏄 ENFILE 鎴 EMFILE if (errno != ENFILE && errno != EMFILE) { + // 鍙戝嚭涓鏉℃棩蹇楁秷鎭紝閫氱煡绂佺敤鑷姩杞崲 ereport(LOG, (errmsg("disabling automatic rotation (use SIGHUP to re-enable)"))); - t_thrd.logger.rotation_disabled = true; + t_thrd.logger.rotation_disabled = true; // 琛ㄦ槑鑷姩杞崲宸茬鐢 } if (filename != NULL) - pfree(filename); + pfree(filename); // 閲婃斁鍒嗛厤鐨勬枃浠跺悕鍐呭瓨 if (csvfilename != NULL) pfree(csvfilename); return; } - fclose(t_thrd.logger.csvlogFile); + fclose(t_thrd.logger.csvlogFile); // 鍏抽棴涔嬪墠鐨勬棩蹇楁枃浠 t_thrd.logger.csvlogFile = fh; /* instead of pfree'ing filename, remember it for next time */ if (t_thrd.logger.last_csv_file_name != NULL) - pfree(t_thrd.logger.last_csv_file_name); - t_thrd.logger.last_csv_file_name = csvfilename; + pfree(t_thrd.logger.last_csv_file_name); // 閲婃斁涓婁竴娆$殑鏂囦欢鍚嶅唴瀛 + t_thrd.logger.last_csv_file_name = csvfilename; // 灏嗘柊鐨勬枃浠跺悕璧嬪硷紝浠ュ涓嬩竴娆¤疆鎹㈡搷浣滀娇鐢 csvfilename = NULL; } @@ -1273,7 +1605,7 @@ static void logfile_rotate(bool time_based_rotation, int size_rotation_for) if (csvfilename != NULL) pfree(csvfilename); - set_next_rotation_time(); + set_next_rotation_time(); // 璁剧疆涓嬩竴娆$殑鏃ュ織杞崲鏃堕棿 } /* @@ -1284,35 +1616,59 @@ static void logfile_rotate(bool time_based_rotation, int size_rotation_for) * * Result is palloc'd. */ + +/* + * 鍔熻兘锛氭瀯寤烘棩蹇楁枃浠剁殑鏂囦欢鍚 + * + * 鍙傛暟锛 + * timestamp锛氭椂闂存埑 + * suffix锛氭枃浠跺悕鍚庣紑 + * logdir锛氭棩蹇楃洰褰 + * filename_pattern锛氭枃浠跺悕妯″紡 + * + * 杩斿洖鍊硷細鍔ㄦ佸垎閰嶇殑瀛楃涓诧紝鍖呭惈鏋勫缓鐨勬枃浠跺悕 + */ static char* logfile_getname(pg_time_t timestamp, const char* suffix, const char* logdir, const char* filename_pattern) { char* filename = NULL; int len = 0; int ret = 0; - filename = (char*)palloc(MAXPGPATH); - + filename = (char*)palloc(MAXPGPATH); // 鍒嗛厤鍐呭瓨 + // 灏 logdir 鐨勫唴瀹规牸寮忓寲骞跺鍒跺埌 filename 涓 ret = snprintf_s(filename, MAXPGPATH, MAXPGPATH - 1, "%s/", logdir); securec_check_ss(ret, "", ""); - len = strlen(filename); + len = strlen(filename); // 璁$畻 filename 瀛楃涓茬殑闀垮害 /* treat Log_filename as a strftime pattern */ + // 灏嗘牸寮忓寲鏃堕棿淇℃伅闄勫姞鍒 filename 鐨勬湯灏 pg_strftime(filename + len, MAXPGPATH - len, filename_pattern, pg_localtime(×tamp, log_timezone)); - + + // 妫鏌ユ槸鍚︽彁渚涗簡鏂囦欢鍚嶅悗缂 if (suffix != NULL) { - len = strlen(filename); + len = strlen(filename); // 璁$畻 filename 瀛楃涓茬殑闀垮害 + // 妫鏌ユ枃浠跺悕鏄惁浠 ".log" 缁撳熬 if (len > 4 && (strcmp(filename + (len - 4), ".log") == 0)) - len -= 4; + len -= 4; // 濡傛灉鏄紝灏嗕粠鏂囦欢鍚嶄腑绉婚櫎 ".log" + // 灏嗗悗缂 suffix 澶嶅埗鍒 filename 鐨勬湯灏撅紝纭繚涓嶄細瓒呭嚭鏂囦欢鍚嶇殑鏈澶ч暱搴 MAXPGPATH - len strlcpy(filename + len, suffix, MAXPGPATH - len); } - return filename; + return filename; // 杩斿洖鏋勫缓鐨勬枃浠跺悕瀛楃涓 } /* * Determine the next planned rotation time, and store in t_thrd.logger.next_rotation_time. */ + +/* + * 鍔熻兘锛氱‘瀹氫笅涓娆¤鍒掔殑鏃ュ織鏂囦欢杞崲鏃堕棿 + * + * 鍙傛暟锛氭棤 + * + * 杩斿洖鍊硷細鏃 + */ static void set_next_rotation_time(void) { pg_time_t now; @@ -1320,8 +1676,9 @@ static void set_next_rotation_time(void) int rotinterval; /* nothing to do if time-based rotation is disabled */ + // 妫鏌ユ槸鍚︾鐢ㄤ簡鍩轰簬鏃堕棿鐨勬棩蹇楄疆鎹 if (u_sess->attr.attr_common.Log_RotationAge <= 0) - return; + return; // 绂佺敤z闃胯繑鍥 /* * The requirements here are to choose the next time > now that is a @@ -1329,16 +1686,22 @@ static void set_next_rotation_time(void) * fairly loosely. In this version we align to log_timezone rather than * GMT. */ + // 璁$畻鏃ュ織杞崲鐨勬椂闂撮棿闅 rotinterval = u_sess->attr.attr_common.Log_RotationAge * SECS_PER_MINUTE; /* convert to seconds */ - now = (pg_time_t)time(NULL); - tm_t = pg_localtime(&now, log_timezone); - if (NULL == tm_t) { - return; + now = (pg_time_t)time(NULL); // 鑾峰彇褰撳墠鏃堕棿 + tm_t = pg_localtime(&now, log_timezone); // 灏嗗綋鍓嶆椂闂 now 杞崲涓烘湰鍦版椂闂 + if (NULL == tm_t) { // 妫鏌ユ槸鍚︽垚鍔熻幏鍙栨湰鍦版椂闂 + return; // 濡傛灉鑾峰彇澶辫触锛岀洿鎺ヨ繑鍥 } + // 灏嗗綋鍓嶆椂闂磋皟鏁翠负 GMT 鍋忕Щ閲忕殑鏃堕棿锛屼互渚垮榻愬埌鏃ュ織杞崲鐨勬椂闂撮棿闅 now += tm_t->tm_gmtoff; + // 璁$畻 now 涓庤疆鎹㈡椂闂撮棿闅旂殑妯★紝骞跺皢鍏跺噺鍘伙紝浠ュ緱鍒颁笅涓涓疆鎹㈡椂闂寸殑璧风偣 now -= now % rotinterval; + // 灏嗚鍒掔殑杞崲鏃堕棿澧炲姞涓涓畬鏁寸殑杞崲鏃堕棿闂撮殧锛屼互寰楀埌涓嬩竴娆¤鍒掔殑杞崲鏃堕棿 now += rotinterval; + // 灏嗚鍒掔殑杞崲鏃堕棿璋冩暣鍥炴湰鍦版椂闂达紝浠ュ緱鍒版渶缁堢殑璁″垝杞崲鏃堕棿 now -= tm_t->tm_gmtoff; + // 灏嗚鍒掔殑杞崲鏃堕棿瀛樺偍鍦ㄥ叏灞鍙橀噺涓紝浠ヤ緵鏃ュ織杞崲鏃朵娇鐢 t_thrd.logger.next_rotation_time = now; } @@ -1347,43 +1710,72 @@ static void set_next_rotation_time(void) * -------------------------------- */ /* SIGHUP: set flag to reload config file */ + +/* + *鍔熻兘锛氬鐞 SIGHUP 淇″彿锛岀敤浜庨噸鏂拌鍙栭厤缃枃浠 + * + * 鍙傛暟: + * SIGNAL_ARGS: 淇″彿澶勭悊绋嬪簭鐨勫弬鏁板垪琛紝鎻愪緵鍏充簬瑙﹀彂淇″彿鐨勪笂涓嬫枃淇℃伅 + * + * 杩斿洖鍊: + * 鏃 + */ static void sigHupHandler(SIGNAL_ARGS) { - int save_errno = errno; + int save_errno = errno; // 淇濆瓨褰撳墠鐨勯敊璇爜 - t_thrd.logger.got_SIGHUP = true; - SetLatch(&t_thrd.logger.sysLoggerLatch); + t_thrd.logger.got_SIGHUP = true; // 琛ㄧず鎺ユ敹鍒 SIGHUP 淇″彿 + SetLatch(&t_thrd.logger.sysLoggerLatch); // 璁剧疆璇ヨ繘绋嬬殑杩涚▼latch - errno = save_errno; + errno = save_errno; // 鎭㈠涔嬪墠淇濆瓨鐨勯敊璇爜 } /* SIGUSR1: set flag to rotate logfile */ + +/* + *鍔熻兘锛 澶勭悊 SIGUSR1 淇″彿锛岀敤浜庡埛鏂扮紦鍐插尯璇锋眰锛屼互鍙婃棩蹇楁枃浠剁殑杞崲璇锋眰 + * + * 鍙傛暟: + * SIGNAL_ARGS: 淇″彿澶勭悊绋嬪簭鐨勫弬鏁板垪琛紝鎻愪緵鍏充簬瑙﹀彂淇″彿鐨勪笂涓嬫枃淇℃伅 + * + * 杩斿洖鍊: + * 鏃 + */ static void sigUsr1Handler(SIGNAL_ARGS) { - int save_errno = errno; + int save_errno = errno; // 淇濆瓨褰撳墠鐨勯敊璇爜 LogControlData* logctl = NULL; - + // 妫鏌ユ槸鍚︽湁鍒锋柊缂撳啿鍖虹殑璇锋眰 if (g_instance.flush_buf_requested) { + // 濡傛灉鏈夛紝閬嶅巻鎵鏈夌殑 LogControlData 缁撴瀯浣 foreach_logctl(logctl) { /* request to flush buffer data */ - logctl->flush_requested = true; + logctl->flush_requested = true; // 琛ㄧず闇瑕佸埛鏂扮紦鍐插尯涓殑鏁版嵁 } /* reset this request */ - g_instance.flush_buf_requested = false; + g_instance.flush_buf_requested = false; // 閲嶇疆鏍囧織锛岃〃绀哄埛鏂扮紦鍐插尯璇锋眰宸茬粡琚鐞 } else { - t_thrd.logger.rotation_requested = true; + // 濡傛灉娌℃湁鍒锋柊缂撳啿鍖虹殑璇锋眰 + t_thrd.logger.rotation_requested = true; // 琛ㄧず闇瑕佽繘琛屾棩蹇楁枃浠剁殑杞崲 /* all log should be rotation requested */ foreach_logctl(logctl) { - logctl->rotation_requested = true; + logctl->rotation_requested = true; // 琛ㄧず闇瑕佽繘琛屾棩蹇楁枃浠剁殑杞崲 } } - SetLatch(&t_thrd.logger.sysLoggerLatch); - errno = save_errno; + SetLatch(&t_thrd.logger.sysLoggerLatch); // 璁剧疆璇ヨ繘绋嬬殑杩涚▼latch + errno = save_errno; // 鎭㈠涔嬪墠淇濆瓨鐨勯敊璇爜 } +/* + * 鍔熻兘锛氳缃竴涓叏灞鏍囧織锛岃〃绀鸿姹傚埛鏂扮紦鍐插尯 + * + * 鍙傛暟锛氭棤 + * + * 杩斿洖鍊硷細鏃 + */ void set_flag_to_flush_buffer(void) { - g_instance.flush_buf_requested = true; + g_instance.flush_buf_requested = true; // 琛ㄧず瑕佹眰鍒锋柊缂撳啿鍖 } /* @@ -1395,10 +1787,12 @@ void set_flag_to_flush_buffer(void) */ static char* LogCtlGetLogDirectory(const char* logid, bool include_nodename) { - char path[MAXPGPATH] = {0}; - char* rootdir = gs_getenv_r("GAUSSLOG"); - char log_rootdir[PATH_MAX + 1] = {'\0'}; + char path[MAXPGPATH] = {0}; // 鐢ㄤ簬瀛樺偍鏈缁堢殑鏃ュ織鐩綍璺緞 + char* rootdir = gs_getenv_r("GAUSSLOG"); // 鑾峰彇鐜鍙橀噺 $GAUSSLOG 鐨勫 + char log_rootdir[PATH_MAX + 1] = {'\0'};// 瀛樺偍 $GAUSSLOG 鐜鍙橀噺鐨勮В鏋愬悗鐨勭粷瀵硅矾寰 + // 妫鏌ョ幆澧冨彉閲 $GAUSSLOG 鏄惁鏈夋晥 if (rootdir == NULL || realpath(rootdir, log_rootdir) == NULL) { + // 濡傛灉鏃犳晥鍒欏彂鍑鸿鍛婃秷鎭 ereport(WARNING, (errmodule(MOD_EXECUTOR), errcode(ERRCODE_EXTERNAL_ROUTINE_INVOCATION_EXCEPTION), errmsg("Failed to obtain environment value $GAUSSLOG!"), @@ -1406,46 +1800,65 @@ static char* LogCtlGetLogDirectory(const char* logid, bool include_nodename) errcause("Incorrect environment value."), erraction("Please refer to backend log for more details."))); } - rootdir = NULL; - int rc = 0; + rootdir = NULL; // 閲婃斁 rootdir 鍐呭瓨 + int rc = 0; // 瀛樺偍鍑芥暟璋冪敤鐨勮繑鍥炲兼垨閿欒鐮 /* * $GAUSSLOG env must not be an empty string. * if so, log directory will be under root dir '/' and permition denied. */ if (*log_rootdir != '\0') { - check_backend_env(log_rootdir); + check_backend_env(log_rootdir); // 妫鏌ユ寚瀹氳矾寰勬槸鍚﹀彲鐢 + // 鎷兼帴瑙f瀽鍚庣殑 $GAUSSLOG 鐜鍙橀噺璺緞鍒 path 涓 rc = strcat_s(path, MAXPGPATH, log_rootdir); securec_check_c(rc, "\0", "\0"); + // 鍦 path 鍚庨潰娣诲姞鏂滄潬锛屽舰鎴愯矾寰勫垎闅旂 rc = strcat_s(path, MAXPGPATH, "/"); securec_check_c(rc, "\0", "\0"); } /* if GAUSSLOG not set, create directory under node rootdir */ + // 灏 logid 鍙傛暟鎸囧畾鐨勬棩蹇楃被鍨嬫坊鍔犲埌 path 涓 rc = strcat_s(path, MAXPGPATH, logid); securec_check_c(rc, "\0", "\0"); - rc = strcat_s(path, MAXPGPATH, "/"); + rc = strcat_s(path, MAXPGPATH, "/"); // 鍦 path 鍚庨潰鍐嶆娣诲姞鏂滄潬 securec_check_c(rc, "\0", "\0"); if (include_nodename) { rc = strcat_s(path, MAXPGPATH, g_instance.attr.attr_common.PGXCNodeName); securec_check_c(rc, "\0", "\0"); } - return pstrdup(path); + return pstrdup(path); // 杩斿洖鏈缁堢殑鏃ュ織鐩綍璺緞鐨勫鍒 } /* copy name of src to dst whose max capacity is LOG_MAX_NODENAME_LEN */ + +/* + * 鍔熻兘锛氬皢婧愬瓧绗︿覆 src 澶嶅埗鍒扮洰鏍囧瓧绗︿覆 dst 涓 + * 浣嗚纭繚鐩爣瀛楃涓 dst 鐨勬渶澶у閲忎笉瓒呰繃 LOG_MAX_NODENAME_LEN銆 + * 濡傛灉婧愬瓧绗︿覆 src 鐨勯暱搴﹁秴杩囦簡 LOG_MAX_NODENAME_LEN锛屽垯浼氳繘琛屾埅鏂鐞 + * + * 鍙傛暟锛 + * src锛氭簮瀛楃涓 + * dst锛氱洰鏍囧瓧绗︿覆 + * + * 杩斿洖鍊硷細鏃 + */ static void copy_name(const char* src, char* dst) { - size_t len = strlen(src); + size_t len = strlen(src); // 璁$畻婧愬瓧绗︿覆 src 鐨勯暱搴 + // 妫鏌ユ簮瀛楃涓茬殑闀垮害鏄惁瓒呰繃浜嗙洰鏍囧瓧绗︿覆鐨勬渶澶у閲 if (len >= LOG_MAX_NODENAME_LEN) { /* truncate this name */ + // 濡傛灉闀垮害瓒呰繃浜嗘渶澶у閲忥紝灏嗛暱搴﹂檺鍒朵负 LOG_MAX_NODENAME_LEN - 1 + // 浠ョ‘淇濈洰鏍囧瓧绗︿覆鏈熬鍙互娣诲姞缁堟绗0 len = LOG_MAX_NODENAME_LEN - 1; } + // 灏嗘簮瀛楃涓茬殑鍐呭澶嶅埗鍒扮洰鏍囧瓧绗︿覆涓 int rc = memcpy_s(dst, LOG_MAX_NODENAME_LEN, src, len + 1); securec_check(rc, "\0", "\0"); - dst[len] = '\0'; + dst[len] = '\0'; // 鎵嬪姩娣诲姞缁堟绗0锛屼互纭繚鐩爣瀛楃涓茬殑姝g‘缁堟 } /* @@ -1453,18 +1866,26 @@ static void copy_name(const char* src, char* dst) * it's a pity that PGXCNodeName is null in syslog thread, * so we have to set this global information from postmaster thread. */ + +/* + * 鍔熻兘锛氬垵濮嬪寲鍏ㄥ眬鍙橀噺 logCtlNodeName 鍜 logCtlHostName + * + * 鍙傛暟锛氭棤 + * + * 杩斿洖鍊硷細鏃 + */ static void LogCtlSetGlobalNames(void) { - if (0 == logCtlNodeName[0]) { + if (0 == logCtlNodeName[0]) { // 妫鏌 logCtlNodeName 鏄惁宸茬粡琚垵濮嬪寲 copy_name(g_instance.attr.attr_common.PGXCNodeName, logCtlNodeName); } - if (0 == logCtlHostName[0]) { - const char* hostname = gs_getenv_r("HOSTNAME"); - if (NULL == hostname) { + if (0 == logCtlHostName[0]) { // 妫鏌 logCtlHostName 鏄惁宸茬粡琚垵濮嬪寲 + const char* hostname = gs_getenv_r("HOSTNAME"); // 鑾峰彇鐜鍙橀噺 HOSTNAME 鐨勫硷紝鍗充富鏈哄悕 + if (NULL == hostname) { // 妫鏌ヨ幏鍙栧埌鐨勪富鏈哄悕鏄惁涓 NULL /* just set a default hostname */ - hostname = "UnknownHostname"; + hostname = "UnknownHostname"; // 璁剧疆涓涓粯璁ょ殑涓绘満鍚 } - check_backend_env(hostname); + check_backend_env(hostname); // 妫鏌ヤ富鏈哄悕鏄惁绗﹀悎涓浜涜姹 copy_name(hostname, logCtlHostName); } } @@ -1474,9 +1895,18 @@ static void LogCtlSetGlobalNames(void) * it's a pity that log_timezone is null in syslog thread, * so we have to set this global information from postmaster thread. */ + +/* + * 鍔熻兘锛氬垵濮嬪寲鍏ㄥ眬鍙橀噺 logCtlTimeZone + * + * 鍙傛暟锛氭棤 + * + * 杩斿洖鍊硷細鏃 + */ static void LogCtlSetTimeZone(void) { - if (log_timezone) { + if (log_timezone) { // 妫鏌 log_timezone 鏄惁宸茬粡琚垵濮嬪寲 + // 澶嶅埗鏃跺尯鍚嶇О骞剁‘淇濆畨鍏ㄦ int rc = memcpy_s(logCtlTimeZone, TZ_STRLEN_MAX + 1, pg_get_timezone_name(log_timezone), TZ_STRLEN_MAX + 1); securec_check(rc, "\0", "\0"); } @@ -1490,16 +1920,18 @@ static void LogCtlSetTimeZone(void) */ static void LogCtlWriteFileHeader(LogControlData* logctl) { + // 鑾峰彇涓绘満鍚嶃佽妭鐐瑰悕鍜屾椂鍖哄瓧绗︿覆鐨勯暱搴︼紝鍖呮嫭鏈熬鐨0 size_t hostname_len = strlen(logCtlHostName) + 1; /* including tail 0 */ size_t nodename_len = strlen(logCtlNodeName) + 1; /* including tail 0 */ size_t timezone_len = strlen(logCtlTimeZone) + 1; /* including tail 0 */ + // 璁$畻澶撮儴鏁版嵁鐨勬婚暱搴 size_t total_len = sizeof(LogFileHeader) + hostname_len + nodename_len + timezone_len; int rc = 0; - total_len = MAXALIGN(total_len); - Assert(total_len <= BLCKSZ); + total_len = MAXALIGN(total_len); // 瀵归綈澶撮儴鏁版嵁闀垮害 + Assert(total_len <= BLCKSZ); // 纭繚澶撮儴鏁版嵁闀垮害涓嶈秴杩囧潡澶у皬 - char* buf = (char*)palloc0(total_len); + char* buf = (char*)palloc0(total_len); // 鍒嗛厤鍐呭瓨缂撳啿鍖虹敤浜庡瓨鍌ㄥご閮ㄦ暟鎹 int off = 0; /* the first magic data */ @@ -1541,15 +1973,17 @@ static void LogCtlWriteFileHeader(LogControlData* logctl) Assert(total_len - off >= sizeof(unsigned long)); *(unsigned long*)(buf + total_len - sizeof(unsigned long)) = LOG_MAGICNUM; - Assert(logctl->now_file_fd); + Assert(logctl->now_file_fd); // 纭繚鏂囦欢鎻忚堪绗﹀瓨鍦 errno = 0; /* clear errno before disk write */ + // 鍐欏叆澶撮儴鏁版嵁鍒版枃浠 size_t ret_len = fwrite(buf, 1, total_len, logctl->now_file_fd); - + // 妫鏌ュ啓鍏ユ槸鍚︽垚鍔 if ((errno != 0) || (ret_len != total_len)) { char errorbuf[ERROR_BUF_SIZE] = {'\0'}; rc = sprintf_s( errorbuf, ERROR_BUF_SIZE, "ERROR: could not write file head for binary log: %s\n", gs_strerror(errno)); securec_check_ss_c(rc, "\0", "\0"); + // 鍐欏叆閿欒娑堟伅鍒扮郴缁熸棩蹇 syslogger_erewrite(logctl->now_file_fd, errorbuf); } pfree(buf); @@ -1564,9 +1998,10 @@ static void LogCtlWriteFileHeader(LogControlData* logctl) */ static void LogCtlRotateFile(LogControlData* logctl, bool time_based_rotation) { - logctl->rotation_requested = false; - + logctl->rotation_requested = false; // 鏍囪涓轰笉闇瑕佽疆鎹 + // 鑾峰彇鏃嬭浆鏃剁殑鏃堕棿鎴 pg_time_t fntime = time_based_rotation ? t_thrd.logger.next_rotation_time : time(NULL); + // 鏋勫缓鏂版棩蹇楁枃浠剁殑鍚嶇О char* filename = logfile_getname(fntime, NULL, logctl->log_dir, logctl->filename_pattern); /* @@ -1580,11 +2015,11 @@ static void LogCtlRotateFile(LogControlData* logctl, bool time_based_rotation) char* write_mode = NULL; if (u_sess->attr.attr_common.Log_truncate_on_rotation && time_based_rotation && logctl->now_file_name && strcmp(filename, logctl->now_file_name) != 0) { - write_mode = "w"; + write_mode = "w"; // 瑕嗙洊鏂囦欢 } else { - write_mode = "a"; + write_mode = "a"; // 杩藉姞鍐呭 } - FILE* fh = logfile_open(filename, write_mode, true); + FILE* fh = logfile_open(filename, write_mode, true); // 鎵撳紑鏂扮殑鏃ュ織鏂囦欢 if (fh == NULL) { if (errno != ENFILE && errno != EMFILE) { @@ -1597,8 +2032,8 @@ static void LogCtlRotateFile(LogControlData* logctl, bool time_based_rotation) return; } - fclose(logctl->now_file_fd); - logctl->now_file_fd = fh; + fclose(logctl->now_file_fd); // 鍏抽棴褰撳墠鐨勬棩蹇楁枃浠 + logctl->now_file_fd = fh; // 鏇存柊褰撳墠鐨勬棩蹇楁枃浠跺彞鏌勪负鏂扮殑鏂囦欢 /* instead of pfree'ing filename, remember it for next time */ if (logctl->now_file_name != NULL) { @@ -1693,12 +2128,12 @@ static void LogCtlFlushBuf(LogControlData* logctl) static void LogCtlProcessInput(LogControlData* logctl, const char* msg, int len) { if (logctl->cur_len + len > logctl->max_len) { - LogCtlFlushBuf(logctl); + LogCtlFlushBuf(logctl); // 濡傛灉缂撳啿鍖哄嵆灏嗘弧锛屽厛鍒锋柊缂撳啿鍖 } - + // 灏嗚緭鍏ョ殑鏃ュ織娑堟伅澶嶅埗鍒扮紦鍐插尯 int rc = memcpy_s(logctl->log_buf + logctl->cur_len, logctl->max_len, msg, len); securec_check(rc, "\0", "\0"); - logctl->cur_len += len; + logctl->cur_len += len; // 鏇存柊褰撳墠缂撳啿鍖洪暱搴 } /* @@ -1744,12 +2179,15 @@ static char* LogCtlGetFilenamePattern(const char* post_suffix) static void PLogCtlInit(void) { t_thrd.log_cxt.pLogCtl = (LogControlData*)palloc0(sizeof(LogControlData)); - t_thrd.log_cxt.pLogCtl->ver = PROFILE_LOG_VERSION; - t_thrd.log_cxt.pLogCtl->rotation_requested = false; - t_thrd.log_cxt.pLogCtl->flush_requested = false; + // 璁剧疆鎬ц兘鏃ュ織鎺у埗鏁版嵁鐨勫悇涓瓧娈 + t_thrd.log_cxt.pLogCtl->ver = PROFILE_LOG_VERSION; // 璁剧疆鎬ц兘鏃ュ織鐗堟湰鍙 + t_thrd.log_cxt.pLogCtl->rotation_requested = false; // 鍒濆鍖栨棩蹇楁棆杞姹傛爣蹇椾负鍋 + t_thrd.log_cxt.pLogCtl->flush_requested = false; // 鍒濆鍖栨棩蹇楀埛鏂拌姹傛爣蹇椾负鍋 if (NULL == t_thrd.log_cxt.pLogCtl->log_dir) { + // 濡傛灉鏃ュ織鐩綍灏氭湭璁剧疆锛屽垯鑾峰彇鏃ュ織鐩綍 t_thrd.log_cxt.pLogCtl->log_dir = LogCtlGetLogDirectory(PROFILE_LOG_TAG, true); + // 鍒涘缓鏃ュ織鐩綍锛屽鏋滅洰褰曚笉瀛樺湪 if (0 == mkdir(t_thrd.log_cxt.pLogCtl->log_dir, S_IRWXU) || (EEXIST == errno)) { /* make sure dir permition is 700 */ (void)chmod(t_thrd.log_cxt.pLogCtl->log_dir, S_IRWXU); @@ -1764,6 +2202,7 @@ static void PLogCtlInit(void) } if (NULL == t_thrd.log_cxt.pLogCtl->filename_pattern) { + // 濡傛灉鏃ュ織鏂囦欢鍚嶆ā寮忓皻鏈缃紝鍒欒幏鍙栨棩蹇楁枃浠跺悕妯″紡 t_thrd.log_cxt.pLogCtl->file_suffix = PROFILE_LOG_SUFFIX; /* plog file pattern should be the same with error log, but post suffix */ t_thrd.log_cxt.pLogCtl->filename_pattern = LogCtlGetFilenamePattern(PROFILE_LOG_SUFFIX); @@ -1772,6 +2211,7 @@ static void PLogCtlInit(void) } if (NULL == t_thrd.log_cxt.pLogCtl->log_buf) { + // 濡傛灉鏃ュ織缂撳啿鍖哄皻鏈垎閰嶏紝鍒欏垎閰嶄竴涓柊鐨勭紦鍐插尯 t_thrd.log_cxt.pLogCtl->log_buf = (char*)palloc(READ_BUF_SIZE); t_thrd.log_cxt.pLogCtl->max_len = READ_BUF_SIZE; t_thrd.log_cxt.pLogCtl->cur_len = 0; @@ -1779,7 +2219,7 @@ static void PLogCtlInit(void) /* do the last two steps */ t_thrd.log_cxt.pLogCtl->inited = true; - allLogCtl[LOG_TYPE_PLOG] = t_thrd.log_cxt.pLogCtl; + allLogCtl[LOG_TYPE_PLOG] = t_thrd.log_cxt.pLogCtl; // 灏嗘ц兘鏃ュ織鎺у埗鏁版嵁缁撴瀯娣诲姞鍒板叏灞鏁扮粍涓 } /* @@ -1845,38 +2285,69 @@ void LogCtlLastFlushBeforePMExit(void) } } +/* + * 鍔熻兘锛氱敤浜庢墦寮AS锛圓daptive Server锛夋ц兘鏃ュ織鏂囦欢 + * + * 鍙傛暟锛 + * doOpen:鎸囧悜甯冨皵鍊肩殑鎸囬拡锛岀敤浜庢寚绀烘槸鍚﹂渶瑕佹墦寮鏂扮殑鏃ュ織鏂囦欢 + * + * 杩斿洖鍊硷細杩斿洖鎸囧悜鎵撳紑鐨凙S鎬ц兘鏃ュ織鏂囦欢鐨勬寚閽 + * 濡傛灉doOpen鍙傛暟涓嶄负NULL涓旈渶瑕佹墦寮鏂版枃浠讹紝鍒欒缃负true锛 + * 鍚﹀垯锛岃缃负false + */ void* ASPOpenLogFile(bool *doOpen) { - if (doOpen != NULL) { - *doOpen = false; + if (doOpen != NULL) { // 妫鏌ユ槸鍚︿紶閫掍簡doOpen鎸囬拡 + *doOpen = false; // 濡傛灉鏈夌殑璇濓紝灏嗗叾璁剧疆涓篺alse锛岃〃绀轰笉闇瑕佹墦寮鏂扮殑鏃ュ織鏂囦欢 } - + // 妫鏌ュ叏灞鍙橀噺t_thrd.logger.asplogFile鏄惁涓篘ULL if (t_thrd.logger.asplogFile == NULL) { + // 濡傛灉涓篘ULL锛岃〃绀哄綋鍓嶆病鏈夋墦寮鐨凙S鎬ц兘鏃ュ織鏂囦欢 + // 鐢熸垚涓涓柊鐨凙S鎬ц兘鏃ュ織鏂囦欢鐨勬枃浠跺悕 char *filename = logfile_getname(time(NULL), ".log", g_instance.attr.attr_common.asp_log_directory, u_sess->attr.attr_common.asp_log_filename); + // 浣跨敤鐢熸垚鐨勬枃浠跺悕鍜屽啓鍏ユā寮"a" 鎵撳紑AS鎬ц兘鏃ュ織鏂囦欢 t_thrd.logger.asplogFile = logfile_open(filename, "a", false); - + // 妫鏌ュ叏灞鍙橀噺t_thrd.logger.last_asp_file_name if (t_thrd.logger.last_asp_file_name != NULL) /* probably shouldn't happen */ - pfree(t_thrd.logger.last_asp_file_name); - t_thrd.logger.last_asp_file_name = filename; - if (doOpen != NULL) { - *doOpen = true; + pfree(t_thrd.logger.last_asp_file_name); // 閲婃斁鍏跺唴瀛 + t_thrd.logger.last_asp_file_name = filename; // 璁剧疆鏂扮敓鎴愮殑鏂囦欢鍚嶏紝浠ヤ究鍦ㄤ笅娆℃墦寮鏂囦欢鏃惰浣忎笂涓涓枃浠剁殑鍚嶇О + if (doOpen != NULL) { // 濡傛灉浼犻掍簡doOpen鎸囬拡 + *doOpen = true; // 璁剧疆涓簍rue锛岃〃绀哄凡缁忔墦寮浜嗘柊鐨凙S鎬ц兘鏃ュ織鏂囦欢 } } - return (void *)t_thrd.logger.asplogFile; + return (void *)t_thrd.logger.asplogFile; // 杩斿洖鎸囧悜鎵撳紑鐨凙S鎬ц兘鏃ュ織鏂囦欢鐨勬寚閽 } +/* + * 鍔熻兘锛氬叧闂瑼S锛圓daptive Server锛夋ц兘鏃ュ織鏂囦欢 + * + * 鍙傛暟锛氭棤 + * + * 杩斿洖鍊硷細鏃 + */ void ASPCloseLogFile() { + // 妫鏌ュ叏灞鍙橀噺t_thrd.logger.asplogFile鏄惁涓篘ULL锛屼互纭繚宸茬粡鎵撳紑浜咥S鎬ц兘鏃ュ織鏂囦欢 if (t_thrd.logger.asplogFile != NULL) { - fclose(t_thrd.logger.asplogFile); - t_thrd.logger.asplogFile = NULL; + fclose(t_thrd.logger.asplogFile); // 濡傛灉AS鎬ц兘鏃ュ織鏂囦欢宸茬粡鎵撳紑锛屽叧闂鏂囦欢 + t_thrd.logger.asplogFile = NULL; // 琛ㄧずAS鎬ц兘鏃ュ織鏂囦欢宸茬粡鍏抽棴 } } /* * * perform logfile rotation * */ + +/* + * 鍔熻兘锛欰S鎬ц兘鏃ュ織鏂囦欢杞崲 + * + * 鍙傛暟锛 + * time_based_rotation:琛ㄧず鏄惁鍩轰簬鏃堕棿杩涜鏃ュ織鏂囦欢鐨勮疆鎹 + * size_rotation_for锛氳〃绀虹敤浜庡喅瀹氭槸鍚﹁繘琛屾棩蹇楁枃浠舵棆杞殑鏉′欢 + * + * 杩斿洖鍊硷細鏃 + */ static void asp_logfile_rotate(bool time_based_rotation, int size_rotation_for) { char* aspFilename = NULL; @@ -1890,10 +2361,12 @@ static void asp_logfile_rotate(bool time_based_rotation, int size_rotation_for) * the planned rotation time, not current time, to avoid "slippage" in the * file name when we don't do the rotation immediately. */ + // 濡傛灉鏄熀浜庢椂闂寸殑杞崲 if (time_based_rotation) - fntime = t_thrd.logger.next_rotation_time; + fntime = t_thrd.logger.next_rotation_time; // 浣跨敤璁″垝鐨勮疆鎹㈡椂闂 else - fntime = time(NULL); + fntime = time(NULL); // 鍚﹀垯浣跨敤褰撳墠鏃堕棿 + // 鐢熸垚鏂扮殑AS鎬ц兘鏃ュ織鏂囦欢鍚 aspFilename = logfile_getname(time(NULL), ".log", g_instance.attr.attr_common.asp_log_directory, @@ -1906,20 +2379,22 @@ static void asp_logfile_rotate(bool time_based_rotation, int size_rotation_for) * * Note: t_thrd.logger.last_file_name should never be NULL here, but if it is, append. */ + if ((time_based_rotation || (size_rotation_for & LOG_DESTINATION_ASPLOG)) && pmState == PM_RUN) { if (u_sess->attr.attr_common.Log_truncate_on_rotation && time_based_rotation && t_thrd.logger.asplogFile != NULL && strcmp(aspFilename, t_thrd.logger.last_asp_file_name) != 0) { - fh = logfile_open(aspFilename, "w", true); + fh = logfile_open(aspFilename, "w", true); // 瑕嗙洊 } else { - fh = logfile_open(aspFilename, "a", true); + fh = logfile_open(aspFilename, "a", true); // 杩藉姞鍐欏叆 } - if (fh == NULL) { + if (fh == NULL) { // 濡傛灉鏃犳硶鎵撳紑鏂扮殑AS鎬ц兘鏃ュ織鏂囦欢 /* * ENFILE/EMFILE are not too surprising on a busy system; just * keep using the old file till we manage to get a new one. * Otherwise, assume something's wrong with Log_directory and stop * trying to create files. */ + // 鍙戝嚭涓浜涢敊璇秷鎭紝绂佺敤鑷姩杞崲 if (errno != ENFILE && errno != EMFILE) { ereport(LOG, (errmsg("disabling automatic rotation (use SIGHUP to re-enable)"))); t_thrd.logger.rotation_disabled = true; @@ -1929,7 +2404,7 @@ static void asp_logfile_rotate(bool time_based_rotation, int size_rotation_for) pfree(aspFilename); return; } - + // 濡傛灉鏂扮殑鏂囦欢鎵撳紑鎴愬姛锛屽叧闂棫鐨凙S鎬ц兘鏃ュ織鏂囦欢骞跺皢鏂囦欢鍙ユ焺鍒囨崲鍒版柊鏂囦欢 if (t_thrd.logger.asplogFile != NULL) { fclose(t_thrd.logger.asplogFile); } @@ -1938,7 +2413,7 @@ static void asp_logfile_rotate(bool time_based_rotation, int size_rotation_for) /* instead of pfree'ing filename, remember it for next time */ if (t_thrd.logger.last_asp_file_name != NULL) - pfree(t_thrd.logger.last_asp_file_name); + pfree(t_thrd.logger.last_asp_file_name); // 閲婃斁鏂版枃浠跺悕鐨勫唴瀛 t_thrd.logger.last_asp_file_name = aspFilename; aspFilename = NULL; } @@ -1948,37 +2423,69 @@ static void asp_logfile_rotate(bool time_based_rotation, int size_rotation_for) } } +/* + * 鍔熻兘锛氱敤浜庢墦寮AS锛圓daptive Server锛夋ц兘鏃ュ織鏂囦欢 + * + * 鍙傛暟锛 + * doOpen:鎸囧悜甯冨皵鍊肩殑鎸囬拡锛岀敤浜庢寚绀烘槸鍚﹂渶瑕佹墦寮鏂扮殑鏃ュ織鏂囦欢 + * + * 杩斿洖鍊硷細杩斿洖鏌ヨ鏃ュ織鏂囦欢鐨勬枃浠舵寚閽 + */ void* SQMOpenLogFile(bool *doOpen) { - if (doOpen != NULL) + if (doOpen != NULL) // 妫鏌ヤ紶鍏ョ殑doOpen鎸囬拡鏄惁涓篘ULL *doOpen = false; - if (t_thrd.logger.querylogFile == NULL) { + if (t_thrd.logger.querylogFile == NULL) { // 妫鏌ュ叏灞鍙橀噺t_thrd.logger.querylogFile鏄惁涓虹┖ + // 濡傛灉涓虹┖锛岃〃绀烘病鏈夊凡缁忔墦寮鐨勬煡璇㈡棩蹇楁枃浠讹紝闇瑕佹墦寮涓涓柊鐨勬枃浠 + // 鏋勯犳煡璇㈡棩蹇楁枃浠剁殑鍚嶇О锛屽寘鎷椂闂存埑銆佸悗缂绛変俊鎭 char *filename = logfile_getname(time(NULL), ".log", g_instance.attr.attr_common.query_log_directory, u_sess->attr.attr_common.query_log_file); + // 鎵撳紑鏌ヨ鏃ュ織鏂囦欢锛屼娇鐢ㄩ檮鍔犳ā寮忥紙"a"锛夛紝鍏佽鍒涘缓鏂版枃浠 t_thrd.logger.querylogFile = logfile_open(filename, "a", false); - pfree(filename); + pfree(filename); // 閲婃斁鏋勯犳枃浠跺悕鏃跺垎閰嶇殑鍐呭瓨 if (doOpen != NULL) { - *doOpen = true; + *doOpen = true; // 琛ㄧず鎴愬姛鎵撳紑浜嗘煡璇㈡棩蹇楁枃浠 } } - return (void *)t_thrd.logger.querylogFile; + return (void *)t_thrd.logger.querylogFile; // 杩斿洖鏌ヨ鏃ュ織鏂囦欢鐨勬枃浠舵寚閽 } +/* + * 鍔熻兘锛氬叧闂璖QL Monitor锛圫QM锛夋煡璇㈡棩蹇楁枃浠 + * + * 鍙傛暟锛氭棤 + * + * 杩斿洖鍊硷細鏃 + */ void SQMCloseLogFile() { if (t_thrd.logger.querylogFile != NULL) { + // 濡傛灉涓嶄负绌猴紝琛ㄧず鏈変竴涓凡缁忔墦寮鐨勬煡璇㈡棩蹇楁枃浠堕渶瑕佸叧闂 + // 鍏抽棴鏌ヨ鏃ュ織鏂囦欢锛岀‘淇濅换浣曟湭鍒锋柊鐨勬暟鎹鍒锋柊鍒扮鐩 fclose(t_thrd.logger.querylogFile); - t_thrd.logger.querylogFile = NULL; + t_thrd.logger.querylogFile = NULL; // 琛ㄧず鏌ヨ鏃ュ織鏂囦欢宸叉垚鍔熷叧闂 } } +/* + * 鍔熻兘锛氭墽琛屾參鏌ヨ鏃ュ織鏂囦欢鐨勮疆鎹㈡搷浣 + * + * 鍙傛暟锛 + * time_based_rotation:琛ㄧず鏄惁鍩轰簬鏃堕棿杩涜杞崲 + * size_rotation_for锛氳〃绀烘棩蹇楁枃浠惰疆鎹㈢殑鍘熷洜锛屽彲浠ユ槸浠ヤ笅鍑犵涔嬩竴锛 + * LOG_DESTINATION_QUERYLOG锛氳〃绀哄熀浜庢參鏌ヨ鏃ュ織澶у皬杩涜杞崲銆 + * LOG_DESTINATION_SYSLOG锛氳〃绀哄熀浜庣郴缁熸棩蹇楀ぇ灏忚繘琛岃疆鎹€ + * LOG_DESTINATION_CSVLOG锛氳〃绀哄熀浜嶤SV鏃ュ織澶у皬杩涜杞崲 + * + * 杩斿洖鍊硷細鏃 + */ static void slow_query_logfile_rotate(bool time_based_rotation, int size_rotation_for) { - char* queryFilename = NULL; - pg_time_t fntime; - FILE* fh = NULL; + char* queryFilename = NULL; // 鐢ㄤ簬瀛樺偍鏂版棩蹇楁枃浠剁殑鏂囦欢鍚 + pg_time_t fntime; // 瀛樺偍璁″垝鐨勮疆鎹㈡椂闂存垨褰撳墠鏃堕棿 + FILE* fh = NULL; // 鏂囦欢鍙ユ焺锛岀敤浜庢墦寮鏂扮殑鏃ュ織鏂囦欢 t_thrd.logger.rotation_requested = false; @@ -1987,10 +2494,11 @@ static void slow_query_logfile_rotate(bool time_based_rotation, int size_rotatio * the planned rotation time, not current time, to avoid "slippage" in the * file name when we don't do the rotation immediately. */ + // 鏍规嵁杞崲绫诲瀷閫夋嫨璁″垝鐨勮疆鎹㈡椂闂存垨褰撳墠鏃堕棿锛屼互璁$畻鏂版棩蹇楁枃浠跺悕 if (time_based_rotation) - fntime = t_thrd.logger.next_rotation_time; + fntime = t_thrd.logger.next_rotation_time; // 鍩轰簬鏃堕棿鐨勮疆鎹紝浣跨敤璁″垝鐨勮疆鎹㈡椂闂 else - fntime = time(NULL); + fntime = time(NULL); // 闈炴椂闂村熀纭杞崲锛屼娇鐢ㄥ綋鍓嶆椂闂 queryFilename = logfile_getname(time(NULL), ".log", g_instance.attr.attr_common.query_log_directory, u_sess->attr.attr_common.query_log_file); /* @@ -2001,12 +2509,13 @@ static void slow_query_logfile_rotate(bool time_based_rotation, int size_rotatio * * Note: t_thrd.logger.last_file_name should never be NULL here, but if it is, append. */ + // 鍒ゆ柇鏄惁闇瑕佽鐩栨垨杩藉姞鍒版棩蹇楁枃浠 if ((time_based_rotation || (size_rotation_for & LOG_DESTINATION_QUERYLOG)) && pmState == PM_RUN) { if (u_sess->attr.attr_common.Log_truncate_on_rotation && time_based_rotation && t_thrd.logger.querylogFile != NULL && strcmp(queryFilename, t_thrd.logger.last_query_log_file_name) != 0) { - fh = logfile_open(queryFilename, "w", true); + fh = logfile_open(queryFilename, "w", true); // 瑕嗙洊妯″紡 } else { - fh = logfile_open(queryFilename, "a", true); + fh = logfile_open(queryFilename, "a", true); // 杩藉姞妯″紡 } if (fh == NULL) { @@ -2016,39 +2525,51 @@ static void slow_query_logfile_rotate(bool time_based_rotation, int size_rotatio * Otherwise, assume something's wrong with Log_directory and stop * trying to create files. */ + // 澶勭悊鏂囦欢鎵撳紑澶辫触鐨勬儏鍐 if (errno != ENFILE && errno != EMFILE) { ereport(LOG, (errmsg("disabling automatic rotation (use SIGHUP to re-enable)"))); t_thrd.logger.rotation_disabled = true; } if (queryFilename != NULL) - pfree(queryFilename); + pfree(queryFilename); // 閲婃斁鍒嗛厤鐨勬枃浠跺悕鍐呭瓨 return; } if (t_thrd.logger.querylogFile != NULL) { - fclose(t_thrd.logger.querylogFile); + fclose(t_thrd.logger.querylogFile); // 鍏抽棴褰撳墠鏃ュ織鏂囦欢 } - t_thrd.logger.querylogFile = fh; + t_thrd.logger.querylogFile = fh; // 璁剧疆鏂扮殑鏃ュ織鏂囦欢鍙ユ焺 /* instead of pfree'ing filename, remember it for next time */ + // 璁板綍鏂扮殑鏃ュ織鏂囦欢鍚 if (t_thrd.logger.last_query_log_file_name != NULL) - pfree(t_thrd.logger.last_query_log_file_name); - t_thrd.logger.last_query_log_file_name = queryFilename; + pfree(t_thrd.logger.last_query_log_file_name); // 閲婃斁涓婁竴涓棩蹇楁枃浠跺悕鐨勫唴瀛 + t_thrd.logger.last_query_log_file_name = queryFilename; // 璁板綍鏂扮殑鏃ュ織鏂囦欢鍚 queryFilename = NULL; } if (queryFilename != NULL) - pfree(queryFilename); + pfree(queryFilename); // 閲婃斁鍐呭瓨 } +/* + * 鍔熻兘锛氬垵濮嬪寲鎸囧畾绫诲瀷鐨勬棩蹇楃洰褰曪紝骞舵牴鎹渶瑕佽缃叏灞鍙橀噺浠ユ寚瀹氭棩蹇楃洰褰曠殑璺緞 + * + * 鍙傛暟锛 + * include_nodename:鎸囩ず鏄惁搴旇鍦ㄦ棩蹇楃洰褰曡矾寰勪腑鍖呮嫭鑺傜偣鍚嶇О + * logid锛氳〃绀鸿鍒濆鍖栫殑鏃ュ織绫诲瀷銆 + * 鏍规嵁浼犲叆鐨勫硷紝鍙互鏄 "ASPY"銆"SLOWQUERY" 鎴 "PERF_JOB" + * + * 杩斿洖鍊硷細鏃 + */ void init_instr_log_directory(bool include_nodename, const char* logid) { /* create directory for aspy & slow query log */ - char* logdir = NULL; - logdir = LogCtlGetLogDirectory(logid, include_nodename); - + char* logdir = NULL; // 鐢ㄤ簬瀛樺偍鏃ュ織鐩綍璺緞 + logdir = LogCtlGetLogDirectory(logid, include_nodename); // 鑾峰彇鏃ュ織鐩綍璺緞 + // 妫鏌ユ槸鍚︽垚鍔熷垱寤烘棩蹇楃洰褰曟垨鐩綍宸插瓨鍦 if (pg_mkdir_p(logdir, S_IRWXU) == 0 || (errno == EEXIST)) { /* * make sure dir permition is 700. @@ -2056,26 +2577,28 @@ void init_instr_log_directory(bool include_nodename, const char* logid) * chmod() may be called by many process, and it maybe failed. * ignore its returned value of this case. */ - (void)chmod(logdir, S_IRWXU); + (void)chmod(logdir, S_IRWXU); // 璁剧疆鐩綍鏉冮檺 } else { /* this directory may be created already, don't care this case */ if (errno != EEXIST) { - pfree(logdir); + pfree(logdir); // 閲婃斁鍒嗛厤鐨勫唴瀛 ereport(FATAL, (errmsg( "ERROR: could not create instr log directory \"%s\": %s\n", logid, gs_strerror(errno)))); } } - if (include_nodename) { + if (include_nodename) { // 濡傛灉鍖呮嫭鑺傜偣鍚嶇О + // 鏍规嵁鏃ュ織ID璁剧疆涓嶅悓鐨勫叏灞鐩綍璺緞 if (strcmp(logid, ASP_LOG_TAG) == 0) { - g_instance.attr.attr_common.asp_log_directory = logdir; + g_instance.attr.attr_common.asp_log_directory = logdir; // 璁剧疆aspy鏃ュ織鐩綍璺緞 } else if (strcmp(logid, SLOWQUERY_LOG_TAG) == 0) { - g_instance.attr.attr_common.query_log_directory = logdir; + g_instance.attr.attr_common.query_log_directory = logdir; // 璁剧疆鎱㈡煡璇㈡棩蹇楃洰褰曡矾寰 } else if (strcmp(logid, PERF_JOB_TAG) == 0) { - g_instance.attr.attr_common.Perf_directory = logdir; + g_instance.attr.attr_common.Perf_directory = logdir; // 璁剧疆鎬ц兘鏃ュ織鐩綍璺緞 } } else { - pfree(logdir); + pfree(logdir); // 閲婃斁鍒嗛厤鐨勫唴瀛 + } } diff --git a/src/gausskernel/process/postmaster/twophasecleaner.cpp b/src/gausskernel/process/postmaster/twophasecleaner.cpp index 4b2d357b4..015a17a42 100644 --- a/src/gausskernel/process/postmaster/twophasecleaner.cpp +++ b/src/gausskernel/process/postmaster/twophasecleaner.cpp @@ -46,32 +46,32 @@ #include "utils/memutils.h" #include "utils/timestamp.h" -#define PGXC_CLEAN_LOG_FILE "gs_clean.log" -#define PGXC_CLEAN "gs_clean" -#define CM_STATIC_CONFIG_FILE "cluster_static_config" -#define MAX_PATH_LEN 1024 +#define PGXC_CLEAN_LOG_FILE "gs_clean.log" // 鎸囧畾鏃ュ織鏂囦欢鐨勫悕绉 +#define PGXC_CLEAN "gs_clean" // 鎸囧畾浠g爜涓殑鏌愪釜杩涚▼鎴栨ā鍧楃殑鍚嶇О +#define CM_STATIC_CONFIG_FILE "cluster_static_config" // 鎸囧畾浠g爜涓殑鏌愪釜閰嶇疆鏂囦欢鐨勫悕绉 +#define MAX_PATH_LEN 1024 // 鏈澶ч暱搴 bool bSyncXactsCallGsclean = false; PGPROC* twoPhaseCleanerProc = NULL; -#ifndef ENABLE_MULTIPLE_NODES -#define MAX_ERRMSG_LENGTH 1024 +#ifndef ENABLE_MULTIPLE_NODES // 妫鏌ュ畯 ENABLE_MULTIPLE_NODES 鏄惁鏈畾涔 +#define MAX_ERRMSG_LENGTH 1024 // 鏈澶ч敊璇秷鎭暱搴 -typedef struct DatabaseNames { +typedef struct DatabaseNames { // 鍦ㄩ摼琛ㄤ腑瀛樺偍鏁版嵁搴撳悕绉 struct DatabaseNames* next; char* databaseName; } DatabaseNames; -typedef struct TempSchemaInfo { +typedef struct TempSchemaInfo { // 鍦ㄩ摼琛ㄤ腑瀛樺偍涓存椂妯″紡鍚嶇О struct TempSchemaInfo* next; char* tempSchemaName; } TempSchemaInfo; -typedef struct ActiveBackendInfo { +typedef struct ActiveBackendInfo { // 鍦ㄩ摼琛ㄤ腑瀛樺偍鏈夊叧娲诲姩鍚庣鐨勪俊鎭 struct ActiveBackendInfo* next; - int64 sessionID; - uint32 tempID; - uint32 timeLineID; + int64 sessionID; // 浼氳瘽ID + uint32 tempID; // 涓存椂ID + uint32 timeLineID; // 鏃堕棿绾縄D } ActiveBackendInfo; #endif @@ -79,39 +79,49 @@ typedef struct ActiveBackendInfo { static void TwoPCSigHupHandler(SIGNAL_ARGS); static void TwoPCShutdownHandler(SIGNAL_ARGS); #ifdef ENABLE_MULTIPLE_NODES -static int get_prog_path(const char* argv0); +static int get_prog_path(const char* argv0); // 鑾峰彇绋嬪簭鐨勮矾寰 #endif #ifndef ENABLE_MULTIPLE_NODES -static bool DropTempNamespace(); +static bool DropTempNamespace(); // 鍒犻櫎涓存椂鍛藉悕绌洪棿 #endif #ifdef ENABLE_MULTIPLE_NODES +// 鑾峰彇涓涓瓧绗︿覆 static const char* getGsCleanLogLevel() { + // 濡傛灉 MOD_GSCLEAN 妯″潡鐨勬棩蹇楄褰曟槸寮鍚殑 if (module_logging_is_on(MOD_GSCLEAN)) { - return "DEBUG"; + return "DEBUG"; // 琛ㄧず鏃ュ織绾у埆涓鸿皟璇 } else { - return "LOG"; + return "LOG"; // 琛ㄧず鏃ュ織绾у埆涓烘櫘閫氭棩蹇 } } #endif +/* + * 鍔熻兘锛歵wophasecleaner杩涚▼鐨勪富瑕佸叆鍙e嚱鏁帮紝鐢ㄤ簬鑷姩娓呯悊鏁版嵁搴撲腑鐨勪袱闃舵浜嬪姟 + * + * 鍙傛暟锛氭棤 + * + * 杩斿洖鍊硷細鏃 + */ NON_EXEC_STATIC void TwoPhaseCleanerMain() { - sigjmp_buf local_sigjmp_buf; - MemoryContext twopc_context; - bool clean_successed = false; + sigjmp_buf local_sigjmp_buf; // 寮傚父璺宠浆鐐 + MemoryContext twopc_context; // 鍒涘缓鍐呭瓨涓婁笅鏂 + bool clean_successed = false; // 鐢ㄤ簬璺熻釜娓呯悊鏄惁鎴愬姛 int rc; /* we are a postmaster subprocess now */ - IsUnderPostmaster = true; + IsUnderPostmaster = true; // 琛ㄧず褰撳墠杩涚▼鏄 postmaster 瀛愯繘绋 t_thrd.proc_cxt.MyProcPid = gs_thread_self(); - twoPhaseCleanerProc = t_thrd.proc; - + twoPhaseCleanerProc = t_thrd.proc; // 鏍囪瘑褰撳墠绾跨▼鎵鍦ㄧ殑杩涚▼ + // 璁板綍璋冭瘯绾у埆鐨勬棩蹇楁秷鎭紝琛ㄧずtwophasecleaner杩涚▼宸茬粡鍚姩锛屽苟鏄剧ず杩涚▼鐨凱ID ereport(DEBUG5, (errmsg("twophasecleaner process is started: %lu", t_thrd.proc_cxt.MyProcPid))); + // 璁剧疆淇″彿澶勭悊鍑芥暟 (void)gspqsignal(SIGHUP, TwoPCSigHupHandler); /* set flag to read config file */ (void)gspqsignal(SIGINT, TwoPCShutdownHandler); /* request shutdown */ (void)gspqsignal(SIGTERM, TwoPCShutdownHandler); /* request shutdown */ @@ -122,6 +132,7 @@ NON_EXEC_STATIC void TwoPhaseCleanerMain() (void)gspqsignal(SIGUSR2, SIG_IGN); /* not used */ /* Reset some signals that are accepted by postmaster but not here */ + // 鎭㈠淇″彿榛樿琛屼负 (void)gspqsignal(SIGCHLD, SIG_DFL); (void)gspqsignal(SIGTTIN, SIG_DFL); (void)gspqsignal(SIGTTOU, SIG_DFL); @@ -129,6 +140,7 @@ NON_EXEC_STATIC void TwoPhaseCleanerMain() (void)gspqsignal(SIGWINCH, SIG_DFL); /* We allow SIGQUIT (quickdie) at all times */ + // 鍏佽 SIGQUIT 淇″彿鍦ㄤ换浣曟椂鍊欓兘鍙互琚鐞 (void)sigdelset(&t_thrd.libpq_cxt.BlockSig, SIGQUIT); /* @@ -137,11 +149,13 @@ NON_EXEC_STATIC void TwoPhaseCleanerMain() * possible memory leaks. Formerly this code just ran in * t_thrd.top_mem_cxt, but resetting that would be a really bad idea. */ + // 鍒涘缓鍐呭瓨涓婁笅鏂 twopc_context = AllocSetContextCreate(t_thrd.top_mem_cxt, "TwoPhase Cleaner", ALLOCSET_DEFAULT_MINSIZE, ALLOCSET_DEFAULT_INITSIZE, ALLOCSET_DEFAULT_MAXSIZE); + // 鍒囨崲鍐呭瓨涓婁笅鏂 (void)MemoryContextSwitchTo(twopc_context); /* @@ -151,64 +165,72 @@ NON_EXEC_STATIC void TwoPhaseCleanerMain() */ int curTryCounter; int* oldTryCounter = NULL; + // 璁剧疆寮傚父澶勭悊璺宠浆鐐 if (sigsetjmp(local_sigjmp_buf, 1) != 0) { + // 鍏抽棴鎵鏈夋墦寮鐨勬枃浠 gstrace_tryblock_exit(true, oldTryCounter); /* Prevents interrupts while cleaning up */ - HOLD_INTERRUPTS(); + HOLD_INTERRUPTS(); // 鍦ㄦ墽琛屾竻鐞嗘搷浣滄湡闂寸姝腑鏂 /* Report the error to the server log */ - EmitErrorReport(); + EmitErrorReport(); // 鎶ュ憡閿欒鍒版湇鍔″櫒鏃ュ織 /* release resource held by lsc */ - AtEOXact_SysDBCache(false); + AtEOXact_SysDBCache(false); // 閲婃斁绯荤粺鏁版嵁搴撶紦瀛樿祫婧 /* * Now return to normal top-level context and clear ErrorContext for * next time. */ + // 鍒囨崲绋嬪簭鐨勫唴瀛樹笂涓嬫枃 (void)MemoryContextSwitchTo(twopc_context); - + // 娓呴櫎閿欒鐘舵侊紝灏嗕箣鍓嶅彲鑳借褰曠殑閿欒淇℃伅鍜岀姸鎬侀噸缃负绌 FlushErrorState(); /* Flush any leaked data in the top-level context */ + // 閲嶇疆 twopc_context 涓婁笅鏂囧苟鍒犻櫎鍏舵墍鏈夊瓙绾т笂涓嬫枃 + // 纭繚鍦ㄥ紓甯稿鐞嗗畬鎴愬悗閲婃斁宸插垎閰嶇殑鍐呭瓨锛屼互閬垮厤鍐呭瓨娉勬紡 MemoryContextResetAndDeleteChildren(twopc_context); /* Now we can allow interrupts again */ - RESUME_INTERRUPTS(); + RESUME_INTERRUPTS(); // 鍏佽涓柇淇″彿鍐嶆琚崟鑾 } - oldTryCounter = gstrace_tryblock_entry(&curTryCounter); + oldTryCounter = gstrace_tryblock_entry(&curTryCounter); // 璁板綍褰撳墠鐨勯敊璇鐞嗗爢鏍堣鏁板櫒 /* We can now handle ereport(ERROR) */ - t_thrd.log_cxt.PG_exception_stack = &local_sigjmp_buf; + t_thrd.log_cxt.PG_exception_stack = &local_sigjmp_buf; // 灏嗛敊璇鐞嗙殑璺宠浆缂撳啿鍖鸿缃负褰撳墠绾跨▼鐨勯敊璇鐞嗗爢鏍 /* Unblock signals (they were blocked when the postmaster forked us) */ - gs_signal_setmask(&t_thrd.libpq_cxt.UnBlockSig, NULL); - (void)gs_signal_unblock_sigusr2(); + gs_signal_setmask(&t_thrd.libpq_cxt.UnBlockSig, NULL); // 瑙i櫎淇″彿灞忚斀锛屽厑璁镐俊鍙峰啀娆¤鎹曡幏 + (void)gs_signal_unblock_sigusr2(); // 瑙i櫎瀵 SIGUSR2 淇″彿鐨勫睆钄斤紝鍏佽鎺ユ敹 SIGUSR2 淇″彿 TimestampTz gs_clean_start_time = GetCurrentTimestamp(); TimestampTz gs_clean_start_time_gtm_val = GetCurrentTimestamp(); - pgstat_report_appname("TwoPhase Cleaner"); - pgstat_report_activity(STATE_IDLE, NULL); + pgstat_report_appname("TwoPhase Cleaner"); // 鎶ュ憡 twophasecleaner 杩涚▼鐨勫簲鐢ㄧ▼搴忓悕绉帮紝鐢ㄤ簬鎬ц兘缁熻鍜岀洃鎺 + pgstat_report_activity(STATE_IDLE, NULL); // 鎶ュ憡 twophasecleaner 杩涚▼鐨勬椿鍔ㄧ姸鎬佷负 "STATE_IDLE"锛岃〃绀哄綋鍓嶈繘绋嬪浜庣┖闂茬姸鎬 for (;;) { - TimestampTz gs_clean_current_time = GetCurrentTimestamp(); + TimestampTz gs_clean_current_time = GetCurrentTimestamp(); // 鑾峰彇褰撳墠鏃堕棿 /* Clear any already-pending wakeups */ - ResetLatch(&t_thrd.proc->procLatch); + ResetLatch(&t_thrd.proc->procLatch); // 娓呴櫎褰撳墠杩涚▼鐨勪簨浠舵爣蹇楋紝浠ヤ究绛夊緟鏂颁簨浠 /* Process any requests or signals received recently. */ + // 濡傛灉鏀跺埌浜 SIGHUP 淇″彿 if (t_thrd.tpcleaner_cxt.got_SIGHUP) { t_thrd.tpcleaner_cxt.got_SIGHUP = false; - ProcessConfigFile(PGC_SIGHUP); + ProcessConfigFile(PGC_SIGHUP); // 閲嶆柊璇诲彇閰嶇疆鏂囦欢 } - + // 濡傛灉鏀跺埌浜嗗叧闂姹 if (t_thrd.tpcleaner_cxt.shutdown_requested) { /* Normal exit from the twophasecleaner is here */ - proc_exit(0); + proc_exit(0); // 姝e父閫鍑 } /* + * 鎻忚堪鍦ㄥ垎甯冨紡 Gaussdb 涓殑娓呯悊琛屼负浠ュ強鍦 opengauss 涓殑鏇夸唬娓呯悊琛屼负 + * * In distributed Gaussdb, we call gs_clean to clean the prepared * transaction every gs_clean_timeout second. * Remark: After the process is started, wait 60s to call @@ -219,6 +241,9 @@ NON_EXEC_STATIC void TwoPhaseCleanerMain() * In opengauss, instead of calling gs_clean, we use twophasecleaner * to clean up the temporary table every gs_clean_timeout second. */ + // 濡傛灉闇瑕佺珛鍗宠皟鐢 gs_clean 杩涜娓呯悊 + // 鎴 鍚敤浜嗘竻鐞嗗姛鑳戒笖涓婁竴娆$殑娓呯悊鎿嶄綔澶辫触 涓 鏃堕棿宸秴杩60s + // 鎴 鏃堕棿瓒呰繃闃堝 if (bSyncXactsCallGsclean || (u_sess->attr.attr_storage.gs_clean_timeout && ((!clean_successed && @@ -226,16 +251,18 @@ NON_EXEC_STATIC void TwoPhaseCleanerMain() TimestampDifferenceExceeds(gs_clean_start_time, gs_clean_current_time, u_sess->attr.attr_storage.gs_clean_timeout * 1000)))) { -#ifdef ENABLE_MULTIPLE_NODES +#ifdef ENABLE_MULTIPLE_NODES // 濡傛灉绯荤粺宸插惎鐢ㄥ鑺傜偣妯″紡 int status = 0; char cmd[MAX_PATH_LEN]; - status = get_prog_path("gaussdb"); - if (status < 0) { + status = get_prog_path("gaussdb"); // 鑾峰彇 gaussdb 鍙墽琛屾枃浠剁殑璺緞 + if (status < 0) { // 濡傛灉鑾峰彇澶辫触 + // 杈撳嚭鏃ュ織娑堟伅 ereport(DEBUG5, (errmsg("failed to invoke get_prog_path()"))); } else { /* if we find explicit cn listen address, we use tcp connection instead of unix socket */ -#ifdef USE_ASSERT_CHECKING +#ifdef USE_ASSERT_CHECKING // 濡傛灉鍚敤浜嗘柇瑷妫鏌 + // 鍛戒护瀛楃涓蹭腑鍖呮嫭璇︾粏鐨勬棩蹇楄緭鍑猴紝骞跺皢杈撳嚭杩藉姞鍒版寚瀹氱殑鏃ュ織鏂囦欢 rc = sprintf_s(cmd, sizeof(cmd), "gs_clean -a -p %d -h localhost -v -r -j %d -l %s >> %s 2>&1", @@ -245,6 +272,7 @@ NON_EXEC_STATIC void TwoPhaseCleanerMain() t_thrd.tpcleaner_cxt.pgxc_clean_log_path); securec_check_ss(rc, "\0", "\0"); #else + // 鍛戒护瀛楃涓蹭腑鍙皢鏍囧噯杈撳嚭鍜屾爣鍑嗛敊璇緭鍑洪噸瀹氬悜鍒 /dev/null锛屽嵆涓嶈繘琛岃缁嗙殑鏃ュ織璁板綍 rc = sprintf_s(cmd, sizeof(cmd), "gs_clean -a -p %d -h localhost -v -r -j %d -l %s > /dev/null 2>&1", @@ -253,31 +281,38 @@ NON_EXEC_STATIC void TwoPhaseCleanerMain() getGsCleanLogLevel()); securec_check_ss(rc, "\0", "\0"); #endif - socket_close_on_exec(); - + socket_close_on_exec(); // 鍏抽棴褰撳墠杩涚▼涓婄殑鏂囦欢鎻忚堪绗 + // 鎶ュ憡褰撳墠杩涚▼鐨勭姸鎬佷负 STATE_RUNNING锛屼互渚跨洃鎺у拰缁熻 pgstat_report_activity(STATE_RUNNING, NULL); status = system(cmd); - if (status == 0) { + if (status == 0) { // 濡傛灉鍛戒护鎵ц鎴愬姛 + // 鍦ㄦ棩蹇椾腑杈撳嚭涓鏉¤皟璇曚俊鎭〃绀烘竻鐞嗘搷浣滄垚鍔 ereport(DEBUG5, (errmsg("clean up 2pc transactions succeed"))); + // 璁剧疆鏍囧織锛岃〃绀烘竻鐞嗘搷浣滃凡鎴愬姛鎵ц clean_successed = true; bSyncXactsCallGsclean = false; } else { + // 璁剧疆鏍囧織锛岃〃绀烘竻鐞嗘搷浣滄湭鎴愬姛鎵ц clean_successed = false; + // 鍦ㄦ棩蹇椾腑杈撳嚭涓鏉¤鍛婁俊鎭〃绀烘竻鐞嗘搷浣滃け璐 ereport(WARNING, (errmsg("clean up 2pc transactions failed"))); } } #else - if (DropTempNamespace()) { + if (DropTempNamespace()) { // 濡傛灉鎴愬姛鎵ц娓呯悊鎿嶄綔 + // 鍦ㄦ棩蹇椾腑杈撳嚭涓鏉¤皟璇曚俊鎭〃绀烘竻鐞嗘搷浣滄垚鍔 ereport(DEBUG5, (errmsg("clean up temp schemas succeed"))); + // 琛ㄧず娓呯悊鎿嶄綔宸叉垚鍔熸墽琛 clean_successed = true; bSyncXactsCallGsclean = false; } else { + // 琛ㄧず娓呯悊鎿嶄綔鏈垚鍔熸墽琛 clean_successed = false; ereport(WARNING, (errmsg("clean up temp schemas failed"))); } #endif - gs_clean_start_time = GetCurrentTimestamp(); + gs_clean_start_time = GetCurrentTimestamp(); // 鏇存柊褰撳墠鏃堕棿锛屼互鐢ㄤ簬涓嬩竴杞竻鐞嗘搷浣滅殑鏃堕棿璁$畻 } /* @@ -286,86 +321,122 @@ NON_EXEC_STATIC void TwoPhaseCleanerMain() * * Remark: set gtm_conn_check_interval to ZERO to disable this function. */ + // 濡傛灉鍚敤浜 GTM 杩炴帴妫鏌ュ姛鑳 涓 褰撳墠鏃堕棿涓庝笂娆℃鏌ョ殑鏃堕棿闂撮殧澶т簬绛変簬 gtm_conn_check_interval 鎸囧畾鐨勭鏁 if (u_sess->attr.attr_storage.gtm_conn_check_interval && TimestampDifferenceExceeds(gs_clean_start_time_gtm_val, gs_clean_current_time, u_sess->attr.attr_storage.gtm_conn_check_interval * 1000)) { - pgstat_cancel_invalid_gtm_conn(); + // 鍙栨秷閭d簺姝e湪杩愯鐨勫悗绔繛鎺ュ埌宸查檷绾х殑 GTM鐨勬煡璇 + pgstat_cancel_invalid_gtm_conn(); + // // 鏇存柊褰撳墠鏃堕棿锛屼互鐢ㄤ簬涓嬩竴杞竻鐞嗘搷浣滅殑鏃堕棿璁$畻 gs_clean_start_time_gtm_val = GetCurrentTimestamp(); } - pgstat_report_activity(STATE_IDLE, NULL); + pgstat_report_activity(STATE_IDLE, NULL); // 鎶ュ憡褰撳墠绾跨▼鐨勬椿鍔ㄧ姸鎬佷负绌洪棽鐘舵 + // 绛夊緟浜嬩欢鍙戠敓 rc = WaitLatch(&t_thrd.proc->procLatch, WL_LATCH_SET | WL_TIMEOUT | WL_POSTMASTER_DEATH, (long)10000 /* 10s */); - + // 閲嶇疆鍜屽垹闄ゅ綋鍓嶇嚎绋嬬殑鍐呭瓨涓婁笅鏂囦腑鐨勫瓙涓婁笅鏂囷紝浠ラ噴鏀句笉鍐嶉渶瑕佺殑鍐呭瓨璧勬簮 MemoryContextResetAndDeleteChildren(twopc_context); /* * Emergency bailout if postmaster has died. This is to avoid the * necessity for manual cleanup of all postmaster children. */ + // 濡傛灉postmaster 宸茬粡缁堟 if (((unsigned int)rc) & WL_POSTMASTER_DEATH) - gs_thread_exit(1); + gs_thread_exit(1); // 閫鍑哄綋鍓嶇嚎绋 } } /* SIGHUP: set flag to re-read config file at next convenient time */ +/* + *鍔熻兘锛氬鐞 SIGHUP 淇″彿锛岀敤浜庨噸鏂拌鍙栭厤缃枃浠 + * + * 鍙傛暟: + * SIGNAL_ARGS: 淇″彿澶勭悊绋嬪簭鐨勫弬鏁板垪琛紝鎻愪緵鍏充簬瑙﹀彂淇″彿鐨勪笂涓嬫枃淇℃伅 + * + * 杩斿洖鍊: + * 鏃 + */ static void TwoPCSigHupHandler(SIGNAL_ARGS) { - int save_errno = errno; + int save_errno = errno; // 淇濆瓨褰撳墠鐨勯敊璇爜 - t_thrd.tpcleaner_cxt.got_SIGHUP = true; + t_thrd.tpcleaner_cxt.got_SIGHUP = true; // 琛ㄧず鎺ユ敹鍒 SIGHUP 淇″彿 - if (t_thrd.proc) - SetLatch(&t_thrd.proc->procLatch); + if (t_thrd.proc) // 濡傛灉瀛樺湪杩涚▼ + SetLatch(&t_thrd.proc->procLatch); // 璁剧疆璇ヨ繘绋嬬殑杩涚▼latch - errno = save_errno; + errno = save_errno; // 鎭㈠涔嬪墠淇濆瓨鐨勯敊璇爜 } /* SIGTERM: set flag to exit normally */ +/* + *鍔熻兘锛氬鐞 SIGTERM 淇″彿锛岀敤浜庢甯搁鍑 + * + * 鍙傛暟: + * SIGNAL_ARGS: 淇″彿澶勭悊绋嬪簭鐨勫弬鏁板垪琛紝鎻愪緵鍏充簬瑙﹀彂淇″彿鐨勪笂涓嬫枃淇℃伅 + * + * 杩斿洖鍊: + * 鏃 + */ static void TwoPCShutdownHandler(SIGNAL_ARGS) { - int save_errno = errno; + int save_errno = errno; // 淇濆瓨褰撳墠鐨勯敊璇爜 - t_thrd.tpcleaner_cxt.shutdown_requested = true; + t_thrd.tpcleaner_cxt.shutdown_requested = true; // 琛ㄧず璇锋眰姝e父閫鍑 - if (t_thrd.proc) - SetLatch(&t_thrd.proc->procLatch); + if (t_thrd.proc) // 濡傛灉瀛樺湪杩涚▼ + SetLatch(&t_thrd.proc->procLatch); // 璁剧疆璇ヨ繘绋嬬殑杩涚▼latch - errno = save_errno; + errno = save_errno; // 鎭㈠涔嬪墠淇濆瓨鐨勯敊璇爜 } #ifdef ENABLE_MULTIPLE_NODES +/* + * 鍔熻兘锛 鑾峰彇鎵ц绋嬪簭璺緞鍜岃缃棩蹇楁枃浠惰矾寰 + * + * 鍙傛暟锛 + * argv0-鐢ㄤ簬浼犻掔▼搴忕殑鍚嶇О鎴栬矾寰 + * + * 杩斿洖鍊硷細 + * 濡傛灉鎴愬姛鎵ц骞朵笖鑾峰彇浜嗘墽琛岀▼搴忕殑璺緞浠ュ強璁剧疆浜嗘棩蹇楁枃浠惰矾寰勶紝杩斿洖 0锛岃〃绀烘垚鍔 + * 鍚﹀垯杩斿洖-1锛岃〃绀哄け璐 + */ static int get_prog_path(const char* argv0) { - char* exec_path = NULL; - char* gausslog_dir = NULL; - char log_dir[MAX_PATH_LEN] = {0}; - char env_gausshome_val[MAX_PATH_LEN] = {0}; + char* exec_path = NULL; // 鐢ㄤ簬瀛樺偍鎵ц绋嬪簭鐨勮矾寰 + char* gausslog_dir = NULL; // 鐢ㄤ簬瀛樺偍鏃ュ織鏂囦欢鐨勬牴鐩綍璺緞 + char log_dir[MAX_PATH_LEN] = {0}; // 鐢ㄤ簬瀛樺偍鏈缁堢殑鏃ュ織鏂囦欢璺緞 + char env_gausshome_val[MAX_PATH_LEN] = {0}; // 鐢ㄤ簬瀛樺偍鐜鍙橀噺鐨勫 char env_gausslog_val[MAX_PATH_LEN] = {0}; - char gaussdb_bin_path[MAX_PATH_LEN] = {0}; + char gaussdb_bin_path[MAX_PATH_LEN] = {0}; // 鐢ㄤ簬瀛樺偍鎵ц绋嬪簭鐨勮矾寰勭殑澶囦唤 errno_t errorno = EOK; int rc; - + // 娓呯┖ errorno = memset_s(t_thrd.tpcleaner_cxt.pgxc_clean_log_path, MAX_PATH_LEN, 0, MAX_PATH_LEN); securec_check_c(errorno, "\0", "\0"); - exec_path = gs_getenv_r("GAUSSHOME"); - - if (NULL == exec_path) { + exec_path = gs_getenv_r("GAUSSHOME"); // 妫鏌ョ幆澧冨彉閲 GAUSSHOME 鏄惁宸茶缃 + // 濡傛灉宸茶缃紝灏 exec_path 璁剧疆涓 GAUSSHOME 鐨勫 + if (NULL == exec_path) { // 濡傛灉鏈缃 + // 鏌ユ壘褰撳墠鍙墽琛岀▼搴忕殑璺緞 if (find_my_exec(argv0, gaussdb_bin_path) < 0) { ereport(WARNING, (errmsg("%s: could not locate my own executable path", argv0))); return -1; } - exec_path = gaussdb_bin_path; - check_backend_env(exec_path); + exec_path = gaussdb_bin_path; // 璁剧疆涓哄彲鎵ц绋嬪簭鎵鍦ㄧ洰褰曠殑璺緞 + check_backend_env(exec_path); // 妫鏌ュ悗绔殑鐜鍙橀噺璁剧疆 + // 鍒犻櫎 exec_path 涓殑鍙墽琛岀▼搴忓悕绉帮紝浠ヨ幏寰楁墽琛岀▼搴忔墍鍦ㄧ洰褰曠殑璺緞 get_parent_directory(exec_path); /* remove my executable name */ } - Assert(NULL != exec_path); + Assert(NULL != exec_path); // 纭繚 exec_path 涓嶄负 NULL { char realExecPath[PATH_MAX + 1] = {'\0'}; - if (realpath(exec_path, realExecPath) == NULL) { + if (realpath(exec_path, realExecPath) == NULL) { // 鑾峰彇鐪熷疄璺緞锛屽鏋滆幏鍙栧け璐 + // 杈撳嚭璀﹀憡淇℃伅 ereport(WARNING, (errmodule(MOD_TRANS_XACT), errcode(ERRCODE_EXTERNAL_ROUTINE_INVOCATION_EXCEPTION), errmsg("Failed to obtain environment value $GAUSSHOME!"), @@ -374,13 +445,17 @@ static int get_prog_path(const char* argv0) erraction("Please refer to backend log for more details."))); return -1; } - exec_path = NULL; - check_backend_env(realExecPath); + exec_path = NULL; // 璁剧疆涓 NULL锛屼互纭繚鍚庣画涓嶅啀浣跨敤 + check_backend_env(realExecPath); // 妫鏌ュ悗绔殑鐜鍙橀噺璁剧疆 + // 澶囦唤鐪熷疄鐨勬墽琛岃矾寰 rc = snprintf_s(env_gausshome_val, sizeof(env_gausshome_val), MAX_PATH_LEN - 1, "%s", realExecPath); securec_check_ss(rc, "\0", "\0"); - gausslog_dir = gs_getenv_r("GAUSSLOG"); + gausslog_dir = gs_getenv_r("GAUSSLOG"); // 灏濊瘯鑾峰彇鐜鍙橀噺 $GAUSSLOG 鐨勫 + // 妫鏌 gausslog_dir 鏄惁涓 NULL 鎴栬呬负绌哄瓧绗︿覆 if ((NULL == gausslog_dir) || ('\0' == gausslog_dir[0])) { + // 杈撳嚭璀﹀憡淇℃伅 ereport(WARNING, (errmsg("environment variable $GAUSSLOG is not set"))); + // 琛ㄧず鏈缁堢殑鏃ュ織鏂囦欢璺緞 rc = snprintf_s(t_thrd.tpcleaner_cxt.pgxc_clean_log_path, sizeof(t_thrd.tpcleaner_cxt.pgxc_clean_log_path), MAX_PATH_LEN - 1, @@ -390,7 +465,9 @@ static int get_prog_path(const char* argv0) g_instance.attr.attr_common.PGXCNodeName); securec_check_ss(rc, "\0", "\0"); } else { + // 瀛樺偍 $GAUSSLOG 鐜鍙橀噺鐨勭湡瀹炶矾寰 char realGausslogDir[PATH_MAX + 1] = {'\0'}; + // 鑾峰彇 gausslog_dir 鐨勭湡瀹炶矾寰勶紝濡傛灉鑾峰彇澶辫触 if (realpath(gausslog_dir, realGausslogDir) == NULL) { ereport(WARNING, (errmodule(MOD_TRANS_XACT), errcode(ERRCODE_EXTERNAL_ROUTINE_INVOCATION_EXCEPTION), @@ -401,18 +478,23 @@ static int get_prog_path(const char* argv0) return -1; } gausslog_dir = NULL; - check_backend_env(realGausslogDir); + check_backend_env(realGausslogDir); // 妫鏌ュ悗绔殑鐜鍙橀噺璁剧疆 + // 澶囦唤鐪熷疄鐨勬墽琛岃矾寰 rc = snprintf_s(env_gausslog_val, sizeof(env_gausslog_val), MAX_PATH_LEN - 1, "%s", realGausslogDir); securec_check_ss(rc, "\0", "\0"); rc = snprintf_s(log_dir, sizeof(log_dir), MAX_PATH_LEN - 1, "%s/bin/%s", env_gausslog_val, PGXC_CLEAN); securec_check_ss(rc, "\0", "\0"); /* log_dir not exist, create log_dir path */ + // 妫鏌 log_dir 鏄惁瀛樺湪 + // 濡傛灉涓嶅瓨鍦紝鍒欎娇鐢 mkdir 鍑芥暟鍒涘缓璇ョ洰褰 if (0 != mkdir(log_dir, S_IRWXU)) { - if (EEXIST != errno) { + if (EEXIST != errno) { // 濡傛灉鍒涘缓鐩綍澶辫触 + // 杈撳嚭涓鏉¤鍛婁俊鎭 ereport(WARNING, (errmsg("could not create directory %s: %m", log_dir))); return -1; } } + // 鏈缁堢殑鏃ュ織鏂囦欢璺緞 rc = snprintf_s(t_thrd.tpcleaner_cxt.pgxc_clean_log_path, sizeof(t_thrd.tpcleaner_cxt.pgxc_clean_log_path), MAX_PATH_LEN - 1, @@ -430,6 +512,21 @@ static int get_prog_path(const char* argv0) #endif #ifndef ENABLE_MULTIPLE_NODES +/* + * 鍔熻兘锛氭竻闄ゆ暟鎹簱涓殑涓存椂妯″紡鍜岀浉鍏崇殑琛 + * + * 鍙傛暟锛 + * host-鎺ュ彈涓绘満鍚 + * port-绔彛鍙 + * user-鐢ㄦ埛鍚 + * password-瀵嗙爜 + * dbname-鏁版嵁搴撳悕绉 + * progname-绋嬪簭鍚嶇О + * encoding-缂栫爜鏂瑰紡 + * + * 杩斿洖鍊硷細 + * 鎸囧悜 PGconn 缁撴瀯鐨勬寚閽堬紝琛ㄧず涓庢暟鎹簱鐨勮繛鎺 + */ static PGconn* LoginDatabase(char* host, int port, char* user, char* password, char* dbname, const char* progname, char* encoding) { @@ -440,11 +537,12 @@ static PGconn* LoginDatabase(char* host, int port, char* user, char* password, const char* values[PARAMS_ARRAY_SIZE]; int count = 0; int retryNum = 10; - int rc; - + int rc; // 瀛樺偍鍑芥暟璋冪敤鐨勮繑鍥炲 + // 灏嗙鍙e彿 port 鏍煎紡鍖栨垚瀛楃涓 rc = sprintf_s(portValue, sizeof(portValue), "%d", port); securec_check_ss_c(rc, "\0", "\0"); + // 璁剧疆杩炴帴鏁版嵁搴撴椂鐨勫弬鏁板叧閿瓧鍜屽搴旂殑鍊硷紝鐢ㄤ簬閰嶇疆鏁版嵁搴撹繛鎺ョ殑鍚勭鍙傛暟 keywords[0] = "host"; values[0] = host; keywords[1] = "port"; @@ -467,29 +565,34 @@ static PGconn* LoginDatabase(char* host, int port, char* user, char* password, keywords[9] = NULL; values[9] = NULL; -retry: +retry: // 鍒涘缓涓涓繛鎺ラ噸璇曠殑寰幆 /* try to connect to database */ - conn = PQconnectdbParams(keywords, values, true); + conn = PQconnectdbParams(keywords, values, true); // 灏濊瘯杩炴帴鍒版暟鎹簱 + // 妫鏌ヨ繛鎺ョ殑鐘舵佹槸鍚︿笉绛変簬 CONNECTION_OK锛岃〃绀鸿繛鎺ュけ璐 if (PQstatus(conn) != CONNECTION_OK) { + // 澧炲姞杩炴帴灏濊瘯娆℃暟骞舵鏌ユ槸鍚﹀皬浜庢渶澶ч噸璇曟鏁 if (++count < retryNum) { + // 璁板綍鏃ュ織淇℃伅锛岃〃绀鸿繛鎺ユ暟鎹簱澶辫触锛屽苟鎻愪緵閿欒淇℃伅 ereport(LOG, (errmsg("Could not connect to the %s, the connection info : %s", dbname, PQerrorMessage(conn)))); - PQfinish(conn); - conn = NULL; + PQfinish(conn); // 鍏抽棴鏁版嵁搴撹繛鎺 + conn = NULL; // 灏嗚繛鎺ユ寚閽堣缃负 NULL /* sleep 0.1 s */ - pg_usleep(100000L); - goto retry; + pg_usleep(100000L); // 浼戠湢 + goto retry; // 璺宠浆鍒版爣绛撅紝杩涜涓嬩竴娆¤繛鎺ュ皾璇 } char connErrorMsg[MAX_ERRMSG_LENGTH] = {0}; errno_t rc; + // 灏嗚繛鎺ラ敊璇秷鎭浆鎹负瀛楃涓插舰寮忓苟瀛樺偍涓嬫潵 rc = snprintf_s(connErrorMsg, MAX_ERRMSG_LENGTH, MAX_ERRMSG_LENGTH - 1, "%s", PQerrorMessage(conn)); securec_check_ss(rc, "\0", "\0"); - PQfinish(conn); + PQfinish(conn); // 鍏抽棴鏁版嵁搴撹繛鎺ワ紝閲婃斁鐩稿叧璧勬簮 conn = NULL; + // 鎶ュ憡杩炴帴鏁版嵁搴撳け璐ョ殑閿欒 ereport(ERROR, (errcode(ERRCODE_CONNECTION_TIMED_OUT), (errmsg("Could not connect to the %s, " "we have tried %d times, the connection info: %s", @@ -499,43 +602,67 @@ retry: return (conn); } +/* + * 鍔熻兘锛氬皢鏁版嵁搴撳悕绉版坊鍔犲埌鏁版嵁搴撳悕绉伴摼琛ㄤ腑 + * + * 鍙傛暟锛 + * dbList-鐢ㄤ簬鏇存柊閾捐〃澶 + * dbName-瑕佹坊鍔犵殑鏁版嵁搴撳悕绉 + * + * 杩斿洖鍊硷細鏃 + */ static void AddDatabaseInfo(DatabaseNames** dbList, char* dbName) { - DatabaseNames* tempDatabase = NULL; - + DatabaseNames* tempDatabase = NULL; // 鐢ㄤ簬涓存椂瀛樺偍瑕佹坊鍔犵殑鏁版嵁搴撲俊鎭 + // 鍒嗛厤鍐呭瓨锛岀敤浜庡瓨鍌ㄦ暟鎹簱淇℃伅 tempDatabase = (DatabaseNames*)palloc(sizeof(DatabaseNames)); - tempDatabase->next = NULL; + tempDatabase->next = NULL; // 鍒濆鍖 + // 淇濆瓨鏁版嵁搴撳悕绉扮殑鍓湰 tempDatabase->databaseName = pstrdup(dbName); - if (*dbList == NULL) { - *dbList = tempDatabase; + if (*dbList == NULL) { // 妫鏌ヤ紶鍏ョ殑鏁版嵁搴撳悕绉板垪琛ㄦ槸鍚︿负绌 + *dbList = tempDatabase; // 鎸囧悜浜嗘柊娣诲姞鐨勬暟鎹簱淇℃伅 } else { + // 灏嗘柊鐨勬暟鎹簱淇℃伅鎻掑叆鍒板垪琛ㄧ殑澶撮儴 tempDatabase->next = (*dbList)->next; (*dbList)->next = tempDatabase; } } +/* + * 鍔熻兘锛氱敤浜庤幏鍙栨暟鎹簱鍒楄〃 + * + * 鍙傛暟锛 + * conn-鎸囬拡锛岃〃绀烘暟鎹簱杩炴帴 + * dbList-鎸囬拡鐨勬寚閽堬紝琛ㄧず鏁版嵁搴撳悕绉伴摼琛 + * + * 杩斿洖鍊硷細鏃 + */ static void GetDatabaseList(PGconn* conn, DatabaseNames** dbList) { - int databaseCount; - PGresult* res = NULL; - char* dbName = NULL; + int databaseCount; // 瀛樺偍浠庢暟鎹簱涓幏鍙栫殑鏁版嵁搴撴暟閲 + PGresult* res = NULL; // 瀛樺偍鎵ц SQL 鏌ヨ鍚庣殑缁撴灉闆 + char* dbName = NULL; // 瀛樺偍浠庣粨鏋滈泦涓彁鍙栫殑鏁版嵁搴撳悕绉 /* SQL Statement */ + // 瀹氫箟涓涓 SQL 鏌ヨ璇彞锛岀敤浜庝粠绯荤粺琛 PG_DATABASE 涓夋嫨鏁版嵁搴撳悕绉 static const char* STMT_GET_DATABASE_LIST = "SELECT DATNAME FROM PG_DATABASE;"; /* Get database list. */ + // 鑾峰彇鏁版嵁搴撳悕绉板垪琛 res = PQexec(conn, STMT_GET_DATABASE_LIST); + // 妫鏌ユ煡璇㈢粨鏋滄槸鍚︿负 NULL 鎴栬呮煡璇㈡墽琛屾槸鍚︽垚鍔 if (res == NULL || PQresultStatus(res) != PGRES_TUPLES_OK) { - char resErrorMsg[MAX_ERRMSG_LENGTH] = {0}; + char resErrorMsg[MAX_ERRMSG_LENGTH] = {0}; // 鐢ㄤ簬瀛樺偍鏌ヨ閿欒娑堟伅 errno_t rc; + // 灏嗘煡璇㈤敊璇秷鎭鍒跺埌 resErrorMsg 涓 rc = snprintf_s(resErrorMsg, MAX_ERRMSG_LENGTH, MAX_ERRMSG_LENGTH - 1, "%s", PQresultErrorMessage(res)); securec_check_ss(rc, "\0", "\0"); - PQclear(res); - PQfinish(conn); + PQclear(res); // 娓呴櫎鏌ヨ缁撴灉瀵硅薄 res + PQfinish(conn); // 鍏抽棴鏁版嵁搴撹繛鎺 conn = NULL; ereport(ERROR, (errcode(ERRCODE_INVALID_STATUS), errmsg("Could not obtain database list: %s", @@ -543,61 +670,93 @@ static void GetDatabaseList(PGconn* conn, DatabaseNames** dbList) return; } - databaseCount = PQntuples(res); + databaseCount = PQntuples(res); // 鑾峰彇鏌ヨ缁撴灉涓殑琛屾暟锛屽嵆鏁版嵁搴撴暟閲 + // 寰幆閬嶅巻鏌ヨ缁撴灉鐨勬瘡涓琛 for (int i = 0; i < databaseCount; i++) { - dbName = PQgetvalue(res, i, 0); + dbName = PQgetvalue(res, i, 0); // 鑾峰彇褰撳墠琛岀殑绗竴涓瓧娈电殑鍊硷紝涔熷氨鏄暟鎹簱鍚嶇О + // 妫鏌ユ暟鎹簱鍚嶇О鏄惁涓 "template0" 鎴 "template1" if (strcmp(dbName, "template0") == 0 || strcmp(dbName, "template1") == 0) { /* Skip template0 and template1 database */ + // 濡傛灉鏄紝琛ㄧず杩欐槸绯荤粺榛樿鐨勬ā鏉挎暟鎹簱锛屼笉闇瑕佸皢鍏舵坊鍔犲埌鍒楄〃涓 continue; } - AddDatabaseInfo(dbList, dbName); + AddDatabaseInfo(dbList, dbName); // 灏嗘暟鎹簱鍚嶇О娣诲姞鍒版暟鎹簱鍚嶇О鍒楄〃涓 } - PQclear(res); + PQclear(res); //娓呴櫎鏌ヨ缁撴灉瀵硅薄锛岄噴鏀捐祫婧 } +/* + * 鍔熻兘锛氭竻闄ゆ暟鎹簱鍚嶇О閾捐〃鍜岀浉鍏崇殑鍐呭瓨 + * + * 鍙傛暟锛 + * dbList-鎸囬拡鐨勬寚閽堬紝琛ㄧず鏁版嵁搴撳悕绉伴摼琛 + * + * 杩斿洖鍊硷細鏃 + */ static void CleanDatabaseList(DatabaseNames** dbList) { DatabaseNames* database = *dbList; - + // 寰幆閬嶅巻鏁版嵁搴 while (database != NULL) { DatabaseNames* savedDatabase = database; - database = database->next; - pfree_ext(savedDatabase->databaseName); + database = database->next; // 杩唬 + pfree_ext(savedDatabase->databaseName); // 閲婃斁鍐呭瓨 pfree_ext(savedDatabase); } *dbList = NULL; } +/* + * 鍔熻兘锛氬皢涓存椂妯″紡鍚嶇О娣诲姞鍒颁复鏃舵ā寮忓悕绉伴摼琛ㄤ腑 + * + * 鍙傛暟锛 + * tempSchemaList-鎸囬拡鐨勬寚閽堬紝鐢ㄤ簬鏇存柊閾捐〃澶 + * tempSchemaName-瑕佹坊鍔犵殑涓存椂妯″紡鍚嶇О + * + * 杩斿洖鍊硷細鏃 + */ static void AddTempSchemaInfo(TempSchemaInfo** tempSchemaList, char* tempSchemaName) { - TempSchemaInfo* tempSchema = NULL; - + TempSchemaInfo* tempSchema = NULL; // 鐢ㄤ簬鍒涘缓鏂扮殑涓存椂妯″紡淇℃伅鑺傜偣 + // 鍒嗛厤鍐呭瓨 tempSchema = (TempSchemaInfo*)palloc(sizeof(TempSchemaInfo)); tempSchema->next = NULL; - tempSchema->tempSchemaName = pstrdup(tempSchemaName); + tempSchema->tempSchemaName = pstrdup(tempSchemaName); // 淇濆瓨涓存椂妯″紡鍚嶇О鐨勫壇鏈 - if (*tempSchemaList == NULL) { + if (*tempSchemaList == NULL) { // 妫鏌ラ摼琛ㄥご鎸囬拡 *tempSchemaList 鏄惁涓虹┖ + // 灏嗛摼琛ㄥご鎸囬拡 *tempSchemaList 璁剧疆涓烘寚鍚戞柊鍒涘缓鐨 tempSchema 鑺傜偣 *tempSchemaList = tempSchema; } else { + // 灏嗘柊鐨勪复鏃舵ā寮忎俊鎭彃鍏ュ埌鍒楄〃鐨勫ご閮 tempSchema->next = (*tempSchemaList)->next; (*tempSchemaList)->next = tempSchema; } } +/* + * 鍔熻兘锛氳幏鍙栦复鏃舵ā寮忓垪琛 + * + * 鍙傛暟锛 + * conn-缁撴瀯浣撴寚閽堬紝鏁版嵁搴撹繛鎺 + * tempSchemaList-鎸囧悜涓存椂妯″紡鍚嶇О閾捐〃鐨勬寚閽 + * + * 杩斿洖鍊硷細鏃 + */ static void GetTempSchemaList(PGconn* conn, TempSchemaInfo** tempSchemaList) { - int tempSchemaCount; - PGresult* res = NULL; - char* nspname = NULL; + int tempSchemaCount; // 鐢ㄤ簬瀛樺偍涓存椂妯″紡鐨勬暟閲 + PGresult* res = NULL; // 鐢ㄤ簬瀛樺偍鏌ヨ缁撴灉 + char* nspname = NULL; // 鐢ㄤ簬瀛樺偍涓存椂妯″紡鐨勫悕绉 int rc; /* SQL Statement */ + // 鐢ㄤ簬瀛樺偍 SQL 鏌ヨ璇彞 char STMT_GET_TEMP_SCHEMA_LIST[NAMEDATALEN + 128] = {0}; - + // 鏋勫缓 SQL 鏌ヨ璇彞 rc = snprintf_s(STMT_GET_TEMP_SCHEMA_LIST, sizeof(STMT_GET_TEMP_SCHEMA_LIST), sizeof(STMT_GET_TEMP_SCHEMA_LIST) - 1, @@ -605,26 +764,31 @@ static void GetTempSchemaList(PGconn* conn, TempSchemaInfo** tempSchemaList) securec_check_ss_c(rc, "\0", "\0"); /* Get temp schema list. */ + // 浣跨敤缁欏畾鐨勬暟鎹簱杩炴帴 conn 鎵ц SQL 鏌ヨ璇彞 res = PQexec(conn, STMT_GET_TEMP_SCHEMA_LIST); + // 妫鏌ユ煡璇㈡槸鍚︽垚鍔熶互鍙婅繑鍥炵粨鏋滄槸鍚﹀寘鍚厓缁勬暟鎹 if (res == NULL || PQresultStatus(res) != PGRES_TUPLES_OK) { + // 濡傛灉鏌ヨ澶辫触鎴栫粨鏋滀笉鍖呭惈鍏冪粍鏁版嵁 char resErrorMsg[MAX_ERRMSG_LENGTH] = {0}; errno_t rc; rc = snprintf_s(resErrorMsg, MAX_ERRMSG_LENGTH, MAX_ERRMSG_LENGTH - 1, "%s", PQresultErrorMessage(res)); securec_check_ss(rc, "\0", "\0"); - PQclear(res); - PQfinish(conn); + PQclear(res); // 娓呯悊鏌ヨ缁撴灉 + PQfinish(conn); // 鍏抽棴鏁版嵁搴撹繛鎺 conn = NULL; ereport(ERROR, (errcode(ERRCODE_INVALID_STATUS), errmsg("Could not obtain temp schema list: %s", resErrorMsg))); return; } - + // 瀛樺偍鏌ヨ缁撴灉 tempSchemaCount = PQntuples(res); + // 閬嶅巻鏌ヨ缁撴灉 for (int i = 0; i < tempSchemaCount; i++) { - nspname = PQgetvalue(res, i, 0); + nspname = PQgetvalue(res, i, 0); // 鑾峰彇绗 i 琛岀殑绗竴涓瓧娈碉紙涓存椂妯″紡鍚嶇О锛夌殑鍊 + // 妫鏌ヤ复鏃舵ā寮忓悕绉版槸鍚︾鍚堥鏈熺殑鏍煎紡瑕佹眰 if (strchr(&nspname[7], '_') == NULL) { char resErrorMsg[MAX_ERRMSG_LENGTH] = {0}; errno_t rc; @@ -632,8 +796,8 @@ static void GetTempSchemaList(PGconn* conn, TempSchemaInfo** tempSchemaList) "%s", PQresultErrorMessage(res)); securec_check_ss(rc, "\0", "\0"); - PQclear(res); - PQfinish(conn); + PQclear(res); // 娓呯悊鏌ヨ缁撴灉 + PQfinish(conn); // 鍏抽棴鏁版嵁搴撹繛鎺 conn = NULL; ereport(ERROR, (errcode(ERRCODE_INVALID_STATUS), errmsg("Error when parse schema name: %s", @@ -641,59 +805,91 @@ static void GetTempSchemaList(PGconn* conn, TempSchemaInfo** tempSchemaList) return; } - AddTempSchemaInfo(tempSchemaList, nspname); + AddTempSchemaInfo(tempSchemaList, nspname); // 灏嗚幏鍙栧埌鐨勪复鏃舵ā寮忓悕绉版坊鍔犲埌 TempSchemaInfo 閾捐〃涓 } - PQclear(res); + PQclear(res); // 娓呯悊鏌ヨ缁撴灉 } +/* + * 鍔熻兘锛氭竻闄や复鏃舵ā寮忓悕绉伴摼琛ㄥ拰鐩稿叧鐨勫唴瀛 + * + * 鍙傛暟锛 + * tempSchemaList-鎸囬拡鐨勬寚閽堬紝琛ㄧず涓存椂妯″紡鍚嶇О閾捐〃 + * + * 杩斿洖鍊硷細鏃 + */ static void CleanTempSchemaList(TempSchemaInfo** tempSchemaList) { TempSchemaInfo* tempSchema = *tempSchemaList; - + // 寰幆閬嶅巻涓存椂妯″紡 while (tempSchema != NULL) { TempSchemaInfo* savedTempSchema = tempSchema; - tempSchema = tempSchema->next; - pfree_ext(savedTempSchema->tempSchemaName); + tempSchema = tempSchema->next; // 杩唬 + pfree_ext(savedTempSchema->tempSchemaName); // 閲婃斁鍐呭瓨 pfree_ext(savedTempSchema); } *tempSchemaList = NULL; } +/* + * 鍔熻兘锛氬皢娲昏穬鍚庣淇℃伅娣诲姞鍒版椿璺冨悗绔俊鎭摼琛ㄤ腑 + * + * 鍙傛暟锛 + * activeBackednList-鎸囬拡鐨勬寚閽堬紝鐢ㄤ簬鏇存柊閾捐〃澶 + * sessionID-浼氳瘽ID + * tempID-涓存椂ID + * timeLineID-鏃堕棿绾縄D + * + * 杩斿洖鍊硷細鏃 + */ static void AddActiveBackendInfo(ActiveBackendInfo** activeBackednList, int64 sessionID, uint32 tempID, uint32 timeLineID) { ActiveBackendInfo* tempActiveBackend = NULL; - + // 鍒嗛厤鍐呭瓨 tempActiveBackend = (ActiveBackendInfo*)palloc(sizeof(ActiveBackendInfo)); tempActiveBackend->next = NULL; - tempActiveBackend->sessionID = sessionID; - tempActiveBackend->tempID = tempID; - tempActiveBackend->timeLineID = timeLineID; + tempActiveBackend->sessionID = sessionID; // 瀛樺偍浼氳瘽鐨勫敮涓鏍囪瘑 + tempActiveBackend->tempID = tempID; // 瀛樺偍涓存椂鏍囪瘑绗 + tempActiveBackend->timeLineID = timeLineID; // 瀛樺偍鏃堕棿绾挎爣璇嗙 if (*activeBackednList == NULL) { + // 濡傛灉涓虹┖锛岃〃绀哄垪琛ㄤ腑娌℃湁浠讳綍娲诲姩鍚庣淇℃伅 + // 鎴愪负鍒楄〃鐨勭涓涓妭鐐 *activeBackednList = tempActiveBackend; } else { + // 灏嗘柊鑺傜偣鎻掑叆鍒板綋鍓嶅垪琛ㄧ殑寮澶 tempActiveBackend->next = (*activeBackednList)->next; (*activeBackednList)->next = tempActiveBackend; } } +/* + * 鍔熻兘锛氳幏鍙栨椿璺冨悗绔俊鎭垪琛 + * + * 鍙傛暟锛 + * conn-鎸囬拡锛岃〃绀烘暟鎹簱杩炴帴 + * activeBackendList-娲昏穬鍚庣淇℃伅閾捐〃 + * + * 杩斿洖鍊硷細鏃 + */ static void GetActiveBackendList(PGconn* conn, ActiveBackendInfo** activeBackendList) { - int activeBackendCount; - PGresult* res = NULL; + int activeBackendCount; // 鐢ㄤ簬瀛樺偍娲诲姩鍚庣鐨勬暟閲 + PGresult* res = NULL; // 鐢ㄤ簬瀛樺偍鎵ц SQL 鏌ヨ鍚庣殑缁撴灉闆 int64 sessionID; uint32 tempID; uint32 timeLineID; int rc; /* SQL Statement */ + // 鐢ㄤ簬瀛樺偍 SQL 鏌ヨ璇彞 char STMT_ACTIVE_BACKEND_LIST[2 * NAMEDATALEN + 128] = {0}; - + // 鏋勫缓 SQL 鏌ヨ璇彞骞跺瓨鍌 rc = sprintf_s(STMT_ACTIVE_BACKEND_LIST, sizeof(STMT_ACTIVE_BACKEND_LIST), "SELECT SESSIONID, TEMPID, TIMELINEID FROM PG_DATABASE D, " @@ -703,7 +899,9 @@ static void GetActiveBackendList(PGconn* conn, ActiveBackendInfo** activeBackend securec_check_ss_c(rc, "\0", "\0"); /* Get active backend list. */ + // 鎵ц SQL 鏌ヨ锛屽皢缁撴灉瀛樺偍鍦 res 涓 res = PQexec(conn, STMT_ACTIVE_BACKEND_LIST); + // 濡傛灉 res 涓虹┖鎴栨煡璇㈢粨鏋滅殑鐘舵佷笉鏄 PGRES_TUPLES_OK 琛ㄧず鏌ヨ澶辫触 if (res == NULL || PQresultStatus(res) != PGRES_TUPLES_OK) { char resErrorMsg[MAX_ERRMSG_LENGTH] = {0}; errno_t rc; @@ -711,8 +909,8 @@ static void GetActiveBackendList(PGconn* conn, ActiveBackendInfo** activeBackend "%s", PQresultErrorMessage(res)); securec_check_ss(rc, "\0", "\0"); - PQclear(res); - PQfinish(conn); + PQclear(res); // 娓呯悊鏌ヨ缁撴灉闆 + PQfinish(conn); // 鍏抽棴鏁版嵁搴撹繛鎺 conn = NULL; ereport(ERROR, (errcode(ERRCODE_INVALID_STATUS), errmsg("Could not obtain active backend list: %s", @@ -720,45 +918,66 @@ static void GetActiveBackendList(PGconn* conn, ActiveBackendInfo** activeBackend return; } - activeBackendCount = PQntuples(res); + activeBackendCount = PQntuples(res); // 鑾峰彇鏌ヨ缁撴灉鐨勫厓缁勬暟閲 + // 閬嶅巻鏌ヨ缁撴灉 for (int i = 0; i < activeBackendCount; i++) { + // 鑾峰彇鍏冪粍涓暟鎹苟鍋氶傚綋杞崲 char* result = PQgetvalue(res, i, 0); sessionID = atoll(result); result = PQgetvalue(res, i, 1); tempID = atoi(result); result = PQgetvalue(res, i, 2); timeLineID = atoi(result); - + // 灏嗚幏鍙栫殑娲诲姩鍚庣淇℃伅娣诲姞鍒颁紶鍏ョ殑 activeBackendList 鍒楄〃涓 AddActiveBackendInfo(activeBackendList, sessionID, tempID, timeLineID); } - PQclear(res); + PQclear(res); // 娓呯悊鏌ヨ缁撴灉闆 } +/* + * 鍔熻兘锛 娓呴櫎娲昏穬鍚庣淇℃伅閾捐〃鍜岀浉鍏崇殑鍐呭瓨 + * + * 鍙傛暟锛 + * activeBackendList-娲昏穬鍚庣淇℃伅閾捐〃 + * + * 杩斿洖鍊硷細鏃 + */ static void CleanActiveBackendList(ActiveBackendInfo** activeBackendList) { ActiveBackendInfo* activeBackend = *activeBackendList; + // 寰幆閬嶅巻娲昏穬鍚庣淇℃伅 while (activeBackend != NULL) { ActiveBackendInfo* savedActiveBackend = activeBackend; - activeBackend = activeBackend->next; - pfree_ext(savedActiveBackend); + activeBackend = activeBackend->next; // 杩唬 + pfree_ext(savedActiveBackend); // 閲婃斁鍐呭瓨 } *activeBackendList = NULL; } +/* + * 鍔熻兘锛氬垹闄ゆ寚瀹氱殑涓存椂妯″紡 + * + * 鍙傛暟锛 + * conn-鎸囬拡锛岃〃绀烘暟鎹簱杩炴帴 + * nspname-瑕佸垹闄ょ殑涓存椂妯″紡鍚嶇О + * + * 杩斿洖鍊硷細鏃 + */ static void DropTempSchema(PGconn* conn, char* nspname) { - PGresult* res = NULL; + PGresult* res = NULL; // 鐢ㄤ簬瀛樺偍鎵ц SQL 鍛戒护鍚庣殑缁撴灉闆 int rc; - char toastnspName[NAMEDATALEN] = {0}; + char toastnspName[NAMEDATALEN] = {0};- // 鐢ㄤ簬瀛樺偍鐢熸垚鐨 toast 妯″紡鐨勫悕绉 /* SQL Statement */ + // 鐢ㄤ簬瀛樺偍 SQL 鍒犻櫎涓存椂妯″紡鐨勮鍙 char STMT_DROP_TEMP_SCHEMA[2 * NAMEDATALEN + 64] = {0}; rc = snprintf_s(toastnspName, NAMEDATALEN, strlen(nspname) + 7, "pg_toast_temp_%s", nspname + 8); securec_check_ss_c(rc, "\0", "\0"); - + // 鏋勫缓鐩稿叧鍙橀噺锛岀敤浜庡垹闄ゆ寚瀹氫复鏃舵ā寮忓強鍏跺叧鑱旂殑 toast 妯″紡鐨 SQL 璇彞 rc = snprintf_s(STMT_DROP_TEMP_SCHEMA, sizeof(STMT_DROP_TEMP_SCHEMA), 2 * strlen(nspname) + 30, @@ -766,100 +985,123 @@ static void DropTempSchema(PGconn* conn, char* nspname) nspname, toastnspName); securec_check_ss_c(rc, "\0", "\0"); - + // 鎵ц SQL 鍒犻櫎涓存椂妯″紡鐨勫懡浠わ紝灏嗙粨鏋滃瓨鍌ㄥ湪 res 涓 res = PQexec(conn, STMT_DROP_TEMP_SCHEMA); /* If exec is not success, give an log and go on. */ + // 妫鏌ュ懡浠ゆ槸鍚︽墽琛屾垚鍔 if (res == NULL || PQresultStatus(res) != PGRES_COMMAND_OK) { + // 濡傛灉鍒犻櫎鎿嶄綔澶辫触 char resErrorMsg[MAX_ERRMSG_LENGTH] = {0}; errno_t rc; rc = snprintf_s(resErrorMsg, MAX_ERRMSG_LENGTH, MAX_ERRMSG_LENGTH - 1, "%s", PQresultErrorMessage(res)); securec_check_ss(rc, "\0", "\0"); - PQclear(res); - PQfinish(conn); + PQclear(res); // 娓呯悊鏌ヨ缁撴灉闆 + PQfinish(conn); // 鍏抽棴鏁版嵁搴撹繛鎺 conn = NULL; ereport(ERROR, (errcode(ERRCODE_INVALID_STATUS), errmsg("Could not drop temp schema %s, %s: %s", nspname, toastnspName, resErrorMsg))); } - PQclear(res); + PQclear(res); // 娓呯悊鏌ヨ缁撴灉闆 } +/* + * 鍔熻兘锛 鍒犻櫎涓嶅睘浜庢椿璺冨悗绔殑涓存椂妯″紡 + * + * 鍙傛暟锛 + * conn-鎸囬拡锛岃〃绀烘暟鎹簱杩炴帴 + * + * 杩斿洖鍊硷細鏃 + */ static void DropTempSchemas(PGconn* conn) { /* Store temp schema names selected from DN. */ - TempSchemaInfo* tempSchemaList = NULL; + TempSchemaInfo* tempSchemaList = NULL; // 鐢ㄤ簬瀛樺偍浠庢暟鎹簱涓幏鍙栫殑涓存椂妯″紡鐨勫垪琛 /* Store current active backend pid to decide which temp schema should be dropped. */ - ActiveBackendInfo* activeBackendList = NULL; + ActiveBackendInfo* activeBackendList = NULL; // 鐢ㄤ簬瀛樺偍褰撳墠娲诲姩鐨勫悗绔繘绋嬩俊鎭垪琛 - GetTempSchemaList(conn, &tempSchemaList); - GetActiveBackendList(conn, &activeBackendList); + GetTempSchemaList(conn, &tempSchemaList); // 浠庢暟鎹簱涓幏鍙栦复鏃舵ā寮忕殑鍒楄〃 + GetActiveBackendList(conn, &activeBackendList); // 鑾峰彇褰撳墠娲诲姩鐨勫悗绔繘绋嬩俊鎭垪琛 TempSchemaInfo* tempSchema = tempSchemaList; ActiveBackendInfo* activeBackend = NULL; char tempBuffer[NAMEDATALEN] = {0}; char tempBuffer2[NAMEDATALEN] = {0}; errno_t rc; + // 妫鏌ヤ复鏃舵ā寮忓垪琛ㄥ拰鍚庣杩涚▼淇℃伅鍒楄〃鏄惁涓虹┖ if (tempSchemaList == NULL || activeBackendList == NULL) return; + // 閬嶅巻涓存椂妯″紡鍒楄〃 while (tempSchema != NULL) { /* * Get sessionID, tempID, timelineID from end to start. * Temp schema name is pg_temp_%s_%u_%u_%lu. * These items are DN'name, timelineID, tempID, sessionID. - */ + */ const char* lastPos = strrchr(tempSchema->tempSchemaName, '_'); + // 濡傛灉涓存椂鍛藉悕绌洪棿鍚嶇О涓嶇鍚堥鏈熸牸寮 if (lastPos == NULL) { - PQfinish(conn); + PQfinish(conn); // 鍏抽棴鏁版嵁搴撹繛鎺 conn = NULL; elog(ERROR, "strrchr failed, can't find '%c' in '%s'\n", '_', tempSchema->tempSchemaName); } + // 鑾峰彇浼氳瘽ID int64 sessionID = strtoll(lastPos + 1, NULL, 10); + // 澶囦唤 + // 灏嗕粠瀛楃涓茶捣濮嬩綅缃埌 lastPos 涔嬮棿鐨勫瓙瀛楃涓插鍒跺埌 tempBuffer 鍙橀噺 rc = strncpy_s(tempBuffer, sizeof(tempBuffer), tempSchema->tempSchemaName, lastPos - tempSchema->tempSchemaName); securec_check_c(rc, "\0", "\0"); const char* secondLastPos = strrchr(tempBuffer, '_'); + // 涓存椂妯″紡鍚嶇О涓嶇鍚堥鏈熸牸寮 if (secondLastPos == NULL) { - PQfinish(conn); + PQfinish(conn); // 鍏抽棴鏁版嵁搴撹繛鎺 conn = NULL; elog(ERROR, "strrchr failed, can't find '%c' in '%s'\n", '_', tempBuffer); } + // 鑾峰彇涓存椂ID uint32 tempID = strtol(secondLastPos + 1, NULL, 10); rc = strncpy_s(tempBuffer2, sizeof(tempBuffer2), tempBuffer, secondLastPos - tempBuffer); securec_check_c(rc, "\0", "\0"); const char* thirdLastPos = strrchr(tempBuffer2, '_'); + // 涓存椂妯″紡鍚嶇О涓嶇鍚堥鏈熸牸寮 if (thirdLastPos == NULL) { - PQfinish(conn); + PQfinish(conn); // 鍏抽棴鏁版嵁搴撹繛鎺 conn = NULL; elog(ERROR, "strrchr failed, can't find '%c' in '%s'\n", '_', tempBuffer2); } + // 鑾峰彇鏃堕棿绾縄D uint32 timeLineID = strtol(thirdLastPos + 1, NULL, 10); - activeBackend = activeBackendList; + activeBackend = activeBackendList; // 鍒濆鍖栨寚鍚戞椿鍔ㄥ悗绔俊鎭垪琛ㄧ殑鎸囬拡 /* * Thus, We use sessionID, timeLineID and tempID together * to judge which session a temp table belongs to, instead of sessionID only. */ + // 閬嶅巻娲诲姩鍚庣鍒楄〃 while (activeBackend != NULL) { + // 鏌ヨID鏄惁鍖归厤锛屽嵆涓存椂妯″紡鏄惁浠嶇劧鍦ㄤ娇鐢ㄤ腑 if (sessionID == activeBackend->sessionID && tempID == activeBackend->tempID && timeLineID == activeBackend->timeLineID) break; activeBackend = activeBackend->next; } - if (activeBackend == NULL) { + if (activeBackend == NULL) { // 娌℃湁鎵惧埌鍖归厤鐨勬椿鍔ㄥ悗绔 /* * Now it is not an active backend, furthermore, we need to drop it; */ + // 鍒犻櫎璇ヤ复鏃舵ā寮 DropTempSchema(conn, tempSchema->tempSchemaName); } - tempSchema = tempSchema->next; + tempSchema = tempSchema->next; // 杩唬 } - CleanTempSchemaList(&tempSchemaList); - CleanActiveBackendList(&activeBackendList); + CleanTempSchemaList(&tempSchemaList); // 娓呯悊瀛樺偍涓存椂妯″紡淇℃伅鐨勯摼琛 + CleanActiveBackendList(&activeBackendList); // 娓呯悊瀛樺偍娲诲姩鍚庣淇℃伅鐨勯摼琛 } /* @@ -867,28 +1109,41 @@ static void DropTempSchemas(PGconn* conn) * @in: void * @return: the result of cleaning temporary schemas */ +/* + * 鍔熻兘锛氫緷娆″鐞嗘瘡涓暟鎹簱涓殑涓存椂妯″紡 + * + * 鍙傛暟锛氭棤 + * + * 杩斿洖鍊硷細 + * bool绫诲瀷 + * 濡傛灉鎴愬姛鎵ц骞跺畬鎴愪簡娓呯悊宸ヤ綔锛岃繑鍥 true锛岃〃绀烘竻鐞嗘搷浣滄垚鍔燂紱 + * 鍚﹀垯锛岃繑鍥瀎alse + */ static bool DropTempNamespace() { DatabaseNames* dbList = NULL; DatabaseNames* curDatabase = NULL; PGconn* conn = NULL; + // 杩炴帴鍒伴粯璁ゆ暟鎹簱 conn = LoginDatabase("localhost", g_instance.attr.attr_network.PostPortNumber, NULL, NULL, DEFAULT_DATABASE, PGXC_CLEAN, "auto"); /* Get database list. */ - GetDatabaseList(conn, &dbList); + GetDatabaseList(conn, &dbList); // 鑾峰彇鏁版嵁搴撳垪琛 - PQfinish(conn); + PQfinish(conn); // 鍏抽棴鏁版嵁搴撹繛鎺 conn = NULL; - if (dbList != NULL) { + if (dbList != NULL) { // 濡傛灉宸叉垚鍔熻幏鍙栦簡鏁版嵁搴撳垪琛 + // 閬嶅巻姣忎釜鏁版嵁搴 for (curDatabase = dbList; curDatabase != NULL; curDatabase = curDatabase->next) { + // 杩炴帴鍒板綋鍓嶅惊鐜凯浠g殑鏁版嵁搴 conn = LoginDatabase("localhost", g_instance.attr.attr_network.PostPortNumber, NULL, NULL, curDatabase->databaseName, PGXC_CLEAN, "auto"); - if (conn == NULL) { - PQfinish(conn); + if (conn == NULL) { // 濡傛灉杩炴帴澶辫触 + PQfinish(conn); // 鍏抽棴鏁版嵁搴撹繛鎺 conn = NULL; ereport(ERROR, (errcode(ERRCODE_INVALID_STATUS), (errmsg("Could not connect to the database %s.", @@ -896,16 +1151,16 @@ static bool DropTempNamespace() return false; } - DropTempSchemas(conn); + DropTempSchemas(conn); // 娓呯悊褰撳墠鏁版嵁搴撶殑涓存椂妯″紡 ereport(DEBUG5, (errmsg("Drop temp namespace for database \"%s\" finished.", curDatabase->databaseName))); - PQfinish(conn); + PQfinish(conn); // 鍏抽棴鏁版嵁搴撹繛鎺 conn = NULL; } } - CleanDatabaseList(&dbList); + CleanDatabaseList(&dbList); // 娓呯悊鏁版嵁搴撳垪琛ㄧ殑閾捐〃 return true; } #endif diff --git a/src/gausskernel/process/postmaster/walwriter.cpp b/src/gausskernel/process/postmaster/walwriter.cpp index f24da1b3a..8491da04a 100755 --- a/src/gausskernel/process/postmaster/walwriter.cpp +++ b/src/gausskernel/process/postmaster/walwriter.cpp @@ -62,16 +62,18 @@ #include "utils/resowner.h" #include "gssignal/gs_signal.h" - +// 鐢ㄤ簬灏嗘绉掑拰绉掕浆鎹负绾崇鐨勫父閲忓 #define NANOSECONDS_PER_MILLISECOND 1000000L #define NANOSECONDS_PER_SECOND 1000000000L /* Signal handlers */ +// 澹版槑淇″彿澶勭悊鍑芥暟 static void wal_quickdie(SIGNAL_ARGS); static void WalSigHupHandler(SIGNAL_ARGS); static void WalShutdownHandler(SIGNAL_ARGS); static void walwriter_sigusr1_handler(SIGNAL_ARGS); +// 琛ㄧずWAL writer鐨勭潯鐪犺秴鏃舵椂闂 THR_LOCAL const int g_sleep_timeout_ms = 300; /* WAL writer sleep timeout in millisecond. */ /* @@ -80,20 +82,32 @@ THR_LOCAL const int g_sleep_timeout_ms = 300; /* WAL writer sleep timeout in mil * This is invoked from AuxiliaryProcessMain, which has already created the * basic execution environment, but not enabled signals yet. */ +/* + * 鍔熻兘锛 涓昏鍏ュ彛鍑芥暟锛屽畠璐熻矗WAL鍐欏叆鍜岀浉鍏充换鍔$殑澶勭悊 + * + * 鍙傛暟锛氭棤 + * + * 杩斿洖鍊硷細鏃 + */ void WalWriterMain(void) { - sigjmp_buf local_sigjmp_buf; - MemoryContext walwriter_context; - sigset_t old_sig_mask; - bool wrote_something = true; - long times_wrote_nothing = 0; - struct timespec time_to_wait; - int sleep_times_counter = 0; - int time_out_counter = 0; + sigjmp_buf local_sigjmp_buf; // 鐢ㄤ簬瀹炵幇寮傚父璺宠浆鐐 + MemoryContext walwriter_context; // 鐢ㄤ簬鍒涘缓WAL writer杩涚▼鐨勫伐浣滃唴瀛樹笂涓嬫枃 + sigset_t old_sig_mask; // 鐢ㄤ簬淇濆瓨鍑芥暟涓殑淇″彿灞忚斀鐘舵 + bool wrote_something = true; // 鐢ㄤ簬璺熻釜WAL writer鏄惁鍦ㄥ綋鍓嶅惊鐜腑鍐欏叆浜嗕换浣曞唴瀹 + long times_wrote_nothing = 0; // 鐢ㄤ簬璁$畻WAL writer鍦ㄨ繛缁惊鐜腑娌℃湁鍐欏叆浠讳綍WAL璁板綍鐨勬鏁 + struct timespec time_to_wait; // 鐢ㄤ簬琛ㄧず鏃堕棿闂撮殧 + int sleep_times_counter = 0; // 鐢ㄤ簬璁$畻WAL writer鎵ц浼戠湢鎿嶄綔鐨勬鏁 + int time_out_counter = 0; // 鐢ㄤ簬璁$畻WAL writer鍦ㄧ瓑寰呮煇涓潯浠舵椂瓒呮椂鐨勬鏁 - load_server_mode(); + load_server_mode(); // 鍔犺浇WAL writer杩涚▼鐨勬湇鍔″櫒妯″紡 + // 妫鏌ュ綋鍓嶆暟鎹簱鏈嶅姟鍣ㄧ殑杩愯妯″紡 + // 濡傛灉鏈嶅姟鍣ㄦā寮忔槸涓绘湇鍔″櫒妯″紡鎴栨甯告ā寮 if (t_thrd.xlog_cxt.server_mode == PRIMARY_MODE || t_thrd.xlog_cxt.server_mode == NORMAL_MODE) { + // 瑙i噴鍦ㄤ綍绉嶆儏鍐典細灏 isWalWriterUp 鏍囧織璁剧疆涓 true + // isWalWriterUp 鐢ㄤ簬琛ㄧずWAL writer绾跨▼涓嶄粎琚垱寤轰互鍙婂皢WAL鏃ュ織浠嶹AL缂撳啿鍖哄啓鍏ュ埌纾佺洏涓 + // 鐢ㄤ簬鍛婅瘔鍏朵粬绾跨▼WAL writer姝e湪杩愯骞朵笖姝e湪鍒锋柊WAL缂撳啿鍖 /* * Different from WalWriterPID, isWalWriterUp is used to signal that * the WAL writer thread is not only created, it is also created to @@ -107,16 +121,22 @@ void WalWriterMain(void) */ g_instance.wal_cxt.isWalWriterUp = true; } - + // 鐢熸垚鏃ュ織娑堟伅锛岃〃鏄嶹AL writer宸茬粡鍚姩 ereport(LOG, (errmsg("walwriter started"))); - + // 妫鏌ラ厤缃弬鏁 walwriter_cpu_bind 鏄惁澶т簬绛変簬闆 + // 璇存槑瑕佷负WAL writer鎸囧畾CPU鏍稿績 if (g_instance.attr.attr_storage.walwriter_cpu_bind >= 0) { - cpu_set_t walWriterSet; - CPU_ZERO(&walWriterSet); + cpu_set_t walWriterSet; // 鐢ㄤ簬琛ㄧずCPU浜插拰鎬ф帺鐮 + CPU_ZERO(&walWriterSet); // 鍒濆鍖栦负涓涓┖鐨凜PU浜插拰鎬ф帺鐮 + // 灏嗘寚瀹氱殑CPU鏍稿績娣诲姞鍒 walWriterSet 涓 + // 鎸囧畾浜哤AL writer杩涚▼搴旇缁戝畾鍒扮殑CPU鏍稿績 + // 灏哤AL writer闄愬埗鍦ㄨ繖涓壒瀹氱殑鏍稿績涓婅繍琛 CPU_SET(g_instance.attr.attr_storage.walwriter_cpu_bind, &walWriterSet); - + // 灏哤AL writer杩涚▼缁戝畾鍒癈PU鏍稿績 int rc = sched_setaffinity(0, sizeof(cpu_set_t), &walWriterSet); + // 濡傛灉缁戝畾澶辫触 if (rc == -1) { + // 閿欒鎶ュ憡 ereport(FATAL, (errcode(ERRCODE_OPERATE_INVALID_PARAM), errmsg("Invalid attribute for thread pool."), errdetail("Current thread num %d is out of range.", g_instance.attr.attr_storage.walwriter_cpu_bind))); } @@ -129,18 +149,26 @@ void WalWriterMain(void) * * Reset some signals that are accepted by postmaster but not here. */ + // 璁剧疆淇″彿澶勭悊绋嬪簭 + // SIGHUP 閲嶆柊鍔犺浇閰嶇疆鏂囦欢 (void)gspqsignal(SIGHUP, WalSigHupHandler); /* set flag to read config file */ + // SIGINT SIGTERM 璇锋眰杩涚▼姝e父缁堟鎴栧叧闂 (void)gspqsignal(SIGINT, WalShutdownHandler); /* request shutdown */ (void)gspqsignal(SIGTERM, WalShutdownHandler); /* request shutdown */ + // SIGQUIT 璇锋眰杩涚▼绔嬪嵆缁堟 (void)gspqsignal(SIGQUIT, wal_quickdie); /* hard crash time */ + // SIGALRM SIGPIPE 蹇界暐 (void)gspqsignal(SIGALRM, SIG_IGN); (void)gspqsignal(SIGPIPE, SIG_IGN); + // SIGUSR1 鐢ㄤ簬鑷畾涔夌敤閫 (void)gspqsignal(SIGUSR1, walwriter_sigusr1_handler); + // SIGUSR2 蹇界暐 (void)gspqsignal(SIGUSR2, SIG_IGN); /* not used */ /* * Reset some signals that are accepted by postmaster but not here. */ + // 閲嶇疆榛樿鍊硷紝浠ヤ笅淇″彿鍦╓AL writer杩涚▼涓笉闇瑕佺壒娈婂鐞 (void)gspqsignal(SIGCHLD, SIG_DFL); (void)gspqsignal(SIGTTIN, SIG_DFL); (void)gspqsignal(SIGTTOU, SIG_DFL); @@ -148,12 +176,14 @@ void WalWriterMain(void) (void)gspqsignal(SIGWINCH, SIG_DFL); /* We allow SIGQUIT (quickdie) at all times */ + // 淇濊瘉鍦ㄩ渶瑕佺殑鎯呭喌涓嬭兘澶熺珛鍗崇粓姝㈣繘绋 sigdelset(&t_thrd.libpq_cxt.BlockSig, SIGQUIT); /* * Create a resource owner to keep track of our resources (not clear that * we need this, but may as well have one). */ + // 鍒涘缓璧勬簮绠$悊鍣 t_thrd.utils_cxt.CurrentResourceOwner = ResourceOwnerCreate(NULL, "Wal Writer", THREAD_GET_MEM_CXT_GROUP(MEMORY_CONTEXT_STORAGE)); @@ -163,11 +193,13 @@ void WalWriterMain(void) * possible memory leaks. Formerly this code just ran in * t_thrd.top_mem_cxt, but resetting that would be a really bad idea. */ + // 鍒涘缓鍐呭瓨涓婁笅鏂囷紝鐢ㄤ簬鎵цWAL writer杩涚▼鐨勬墍鏈夊伐浣 walwriter_context = AllocSetContextCreate(t_thrd.top_mem_cxt, "Wal Writer", ALLOCSET_DEFAULT_MINSIZE, ALLOCSET_DEFAULT_INITSIZE, ALLOCSET_DEFAULT_MAXSIZE); + // 鍒囨崲鍒版柊鐨勫唴瀛樹笂涓嬫枃 (void)MemoryContextSwitchTo(walwriter_context); /* @@ -177,61 +209,75 @@ void WalWriterMain(void) */ int curTryCounter; int* oldTryCounter = NULL; + // 璁剧疆寮傚父璺宠浆鐐 if (sigsetjmp(local_sigjmp_buf, 1) != 0) { /* * Close all open files after any error. This is helpful on Windows, * where holding deleted files open causes various strange errors. * It's not clear we need it elsewhere, but shouldn't hurt. */ + // 鍏抽棴鎵鏈夋墦寮鐨勬枃浠 gstrace_tryblock_exit(true, oldTryCounter); /* We need restore the signal mask of current thread. */ + // 鎭㈠涔嬪墠淇濆瓨鐨勪俊鍙锋帺鐮侊紝浠ョ‘淇濅俊鍙峰鐞嗘仮澶嶅埌涔嬪墠鐨勭姸鎬 pthread_sigmask(SIG_SETMASK, &old_sig_mask, NULL); /* Since not using PG_TRY, must reset error stack by hand */ + // 鎵嬪姩閲嶇疆閿欒鍫嗘爤 t_thrd.log_cxt.error_context_stack = NULL; - t_thrd.log_cxt.call_stack = NULL; + t_thrd.log_cxt.call_stack = NULL; // 娓呯┖璋冪敤鏍 /* Prevent interrupts while cleaning up */ - HOLD_INTERRUPTS(); + HOLD_INTERRUPTS(); // 鍦ㄦ墽琛屾竻鐞嗘搷浣滄湡闂寸姝腑鏂 /* Report the error to the server log */ - EmitErrorReport(); + EmitErrorReport(); // 鎶ュ憡閿欒鍒版湇鍔″櫒鏃ュ織 /* abort async io, must before LWlock release */ - AbortAsyncListIO(); + AbortAsyncListIO(); // 涓寮傛I/O鎿嶄綔 /* release resource held by lsc */ - AtEOXact_SysDBCache(false); + AtEOXact_SysDBCache(false); // 閲婃斁绯荤粺鏁版嵁搴撶紦瀛樿祫婧 /* * These operations are really just a minimal subset of * AbortTransaction(). We don't have very many resources to worry * about in walwriter, but we do have LWLocks, and perhaps buffers? */ - LWLockReleaseAll(); - pgstat_report_waitevent(WAIT_EVENT_END); - AbortBufferIO(); - UnlockBuffers(); + LWLockReleaseAll(); // 閲婃斁閿 + pgstat_report_waitevent(WAIT_EVENT_END); // 鎶ュ憡绛夊緟浜嬩欢缁撴潫锛岀敤浜庢ц兘缁熻鍜岃瘖鏂 + AbortBufferIO(); // 涓缂撳啿鍖篒/O鎿嶄綔鐨勫嚱鏁拌皟鐢 + UnlockBuffers(); // 瑙i攣缂撳啿鍖,纭繚鍦ㄥ紓甯告儏鍐典笅涓嶄細淇濈暀鏈В閿佺殑缂撳啿鍖 /* buffer pins are released here: */ + // 閲婃斁璧勬簮锛屽寘鎷祫婧愭墍鏈夎呮寔鏈夌殑璧勬簮 ResourceOwnerRelease(t_thrd.utils_cxt.CurrentResourceOwner, RESOURCE_RELEASE_BEFORE_LOCKS, false, true); /* we needn't bother with the other ResourceOwnerRelease phases */ + // 澶勭悊浜嬪姟缁撴潫鐨勫嚱鏁拌皟鐢 涓庣紦鍐插尯鐩稿叧鐨勬竻鐞嗗伐浣 AtEOXact_Buffers(false); + // 澶勭悊浜嬪姟缁撴潫鐨勫嚱鏁拌皟鐢 涓庡瓨鍌ㄧ鐞嗗櫒鐩稿叧鐨勬竻鐞嗗伐浣 AtEOXact_SMgr(); + // 澶勭悊浜嬪姟缁撴潫鐨勫嚱鏁拌皟鐢 鐢ㄤ簬鍏抽棴涓庢枃浠舵搷浣滅浉鍏崇殑璧勬簮 AtEOXact_Files(); + // 澶勭悊浜嬪姟缁撴潫鐨勫嚱鏁拌皟鐢 鐢ㄤ簬娓呯悊鍝堝笇琛ㄥ拰鐩稿叧鏁版嵁缁撴瀯 AtEOXact_HashTables(false); /* * Now return to normal top-level context and clear ErrorContext for * next time. */ + // 鍒囨崲绋嬪簭鐨勫唴瀛樹笂涓嬫枃 (void)MemoryContextSwitchTo(walwriter_context); + // 娓呴櫎閿欒鐘舵侊紝灏嗕箣鍓嶅彲鑳借褰曠殑閿欒淇℃伅鍜岀姸鎬侀噸缃负绌 FlushErrorState(); /* Flush any leaked data in the top-level context */ + // 閲嶇疆 walwriter_context 涓婁笅鏂囧苟鍒犻櫎鍏舵墍鏈夊瓙绾т笂涓嬫枃 + // 纭繚鍦ㄥ紓甯稿鐞嗗畬鎴愬悗閲婃斁宸插垎閰嶇殑鍐呭瓨锛屼互閬垮厤鍐呭瓨娉勬紡 MemoryContextResetAndDeleteChildren(walwriter_context); /* Now we can allow interrupts again */ + // 鍏佽涓柇淇″彿鍐嶆琚崟鑾 RESUME_INTERRUPTS(); /* @@ -239,78 +285,97 @@ void WalWriterMain(void) * to be repeated, and we don't want to be filling the error logs as * fast as we can. */ - pg_usleep(1000000L); + pg_usleep(1000000L); // 浼戠湢 } + // 璁板綍褰撳墠鐨勯敊璇鐞嗗爢鏍堣鏁板櫒 oldTryCounter = gstrace_tryblock_entry(&curTryCounter); /* We can now handle ereport(ERROR) */ + // 灏嗛敊璇鐞嗙殑璺宠浆缂撳啿鍖鸿缃负褰撳墠绾跨▼鐨勯敊璇鐞嗗爢鏍 t_thrd.log_cxt.PG_exception_stack = &local_sigjmp_buf; /* * Unblock signals (they were blocked when the postmaster forked us) */ + // 瑙i櫎淇″彿灞忚斀锛屽厑璁镐俊鍙峰啀娆¤鎹曡幏 gs_signal_setmask(&t_thrd.libpq_cxt.UnBlockSig, NULL); + // 瑙i櫎瀵 SIGUSR2 淇″彿鐨勫睆钄斤紝鍏佽鎺ユ敹 SIGUSR2 淇″彿 (void)gs_signal_unblock_sigusr2(); /* * Reset hibernation state after any error. */ + // 璁剧疆 walwriter 杩涚▼鐨勪紤鐪犵姸鎬佷负涓嶄紤鐪 SetWalWriterSleeping(false); /* * Advertise our latch that backends can use to wake us up while we're * sleeping. */ + // 灏 walwriter 杩涚▼鐨勬爣璇嗚缃负褰撳墠绾跨▼鐨勬爣璇 + // 鍏佽鍏朵粬鍚庡彴杩涚▼浣跨敤鏍囪瘑鍞ら啋 walwriter 杩涚▼ g_instance.proc_base->walwriterLatch = &t_thrd.proc->procLatch; - + // 鎶ュ憡 walwriter 杩涚▼鐨勫簲鐢ㄧ▼搴忓悕绉帮紝鐢ㄤ簬鎬ц兘缁熻鍜岀洃鎺 pgstat_report_appname("Wal Writer"); + // 鎶ュ憡 walwriter 杩涚▼鐨勬椿鍔ㄧ姸鎬佷负 "STATE_IDLE"锛岃〃绀哄綋鍓嶈繘绋嬪浜庣┖闂茬姸鎬 pgstat_report_activity(STATE_IDLE, NULL); /* * Loop forever */ for (;;) { + // 鎶ュ憡褰撳墠娲诲姩鐘舵佷负 "STATE_RUNNING"锛岃〃绀鸿繘绋嬫鍦ㄦ墽琛 pgstat_report_activity(STATE_RUNNING, NULL); /* * Process any requests or signals received recently. */ + // 濡傛灉鏀跺埌浜 SIGHUP 淇″彿 if (t_thrd.walwriter_cxt.got_SIGHUP) { t_thrd.walwriter_cxt.got_SIGHUP = false; - ProcessConfigFile(PGC_SIGHUP); + ProcessConfigFile(PGC_SIGHUP); // 閲嶆柊璇诲彇閰嶇疆鏂囦欢 } - + // 濡傛灉鏀跺埌浜嗗叧闂姹 if (t_thrd.walwriter_cxt.shutdown_requested) { /* Normal exit from the walwriter is here */ - proc_exit(0); /* done */ + proc_exit(0); /* done */ // 姝e父閫鍑 } - LWLockAcquire(WALWriteLock, LW_EXCLUSIVE); - wrote_something = XLogBackgroundFlush(); - LWLockRelease(WALWriteLock); - + LWLockAcquire(WALWriteLock, LW_EXCLUSIVE); // 鑾峰彇 WAL 鍐欓攣 + wrote_something = XLogBackgroundFlush(); // 鎵ц鍚庡彴鐨 WAL 鍒锋柊鎿嶄綔 + LWLockRelease(WALWriteLock); // 閲婃斁 WAL 鍐欓攣锛屽厑璁稿叾浠栬繘绋嬭闂 WAL 鏃ュ織 + // 妫鏌ユ槸鍚﹀凡缁忚繛缁竴娈垫椂闂存病鏈夊啓鍏ユ柊鐨 WAL 璁板綍锛屽苟涓旇秴杩囦簡閰嶇疆鐨勯槇鍊 if (!wrote_something && ++times_wrote_nothing > g_instance.attr.attr_storage.walwriter_sleep_threshold) { /* * Wait for the first entry after last flushed entry to be updated */ + // 鑾峰彇涓婃鍒锋柊鐨 WAL 璁板綍浣嶇疆 int lastFlushedEntry = g_instance.wal_cxt.lastWalStatusEntryFlushed; + // 璁$畻涓嬩竴涓妫鏌ョ殑 WAL 璁板綍鐨勪綅缃紝浠ユ煡鐪嬫槸鍚﹀凡缁忚澶嶅埗 int nextStatusEntry = GET_NEXT_STATUS_ENTRY(g_instance.attr.attr_storage.wal_insert_status_entries_power, lastFlushedEntry); volatile WalInsertStatusEntry *pCriticalEntry = &g_instance.wal_cxt.walInsertStatusTable[nextStatusEntry]; + // 濡傛灉 walwriter 杩涚▼澶勪簬娲诲姩鐘舵侊紝骞朵笖涓嬩竴涓 WAL 璁板綍鐨勭姸鎬佷负鏈鍒 if (g_instance.wal_cxt.isWalWriterUp && pCriticalEntry->status == WAL_NOT_COPIED) { - sleep_times_counter++; + sleep_times_counter++; // 澧炲姞璁℃暟鍣 + // 鑾峰彇涓寸晫鍖虹殑浜掓枼閿 (void)pthread_mutex_lock(&g_instance.wal_cxt.criticalEntryMutex); - g_instance.wal_cxt.isWalWriterSleeping = true; + g_instance.wal_cxt.isWalWriterSleeping = true; // 琛ㄧず walwriter 杩涚▼姝e湪浼戠湢 + // 寰幆绛夊緟涓嬩竴涓 WAL 璁板綍琚鍒讹紝鎴栬呯瓑寰呭叧闂姹 while (pCriticalEntry->status == WAL_NOT_COPIED && !t_thrd.walwriter_cxt.shutdown_requested) { - (void)clock_gettime(CLOCK_MONOTONIC, &time_to_wait); + (void)clock_gettime(CLOCK_MONOTONIC, &time_to_wait); // 鑾峰彇褰撳墠鐨勬椂闂 + // 璁$畻绛夊緟鏃堕棿 time_to_wait.tv_nsec += g_sleep_timeout_ms * NANOSECONDS_PER_MILLISECOND; + // 妫鏌ョ瓑寰呮椂闂存槸鍚﹁秴杩囦簡涓绉 if (time_to_wait.tv_nsec >= NANOSECONDS_PER_SECOND) { - time_to_wait.tv_nsec -= NANOSECONDS_PER_SECOND; + time_to_wait.tv_nsec -= NANOSECONDS_PER_SECOND; // 鍑忓幓涓绉掔殑绾崇閮ㄥ垎 time_to_wait.tv_sec += 1; } + // 鐢ㄦ潯浠跺彉閲忚繘琛岀瓑寰咃紝濡傛灉鍦ㄨ瀹氱殑鏃堕棿鍐呮病鏈夎鍞ら啋锛屽皢杩斿洖 res 鍊 int res = pthread_cond_timedwait(&g_instance.wal_cxt.criticalEntryCV, &g_instance.wal_cxt.criticalEntryMutex, &time_to_wait); + // 濡傛灉绛夊緟鎴愬姛 if (res == 0) { /* * We should not break out here because we may be notified by an @@ -318,24 +383,28 @@ void WalWriterMain(void) * entry status is WAL_NOT_COPIED. */ continue; - } else if (res == ETIMEDOUT) { - time_out_counter++; - } else { + } else if (res == ETIMEDOUT) { // 濡傛灉绛夊緟瓒呮椂 + time_out_counter++; // 澧炲姞瓒呮椂璁℃暟鍣 + } else { // 濡傛灉绛夊緟鍑虹幇閿欒 + // 鎶ュ憡閿欒淇℃伅 ereport(WARNING, (errmsg("WAL writer pthread_cond_timedwait returned error code = %d.", errno))); } /* wakeup other producer if possible to avoid hang */ + // 鍞ら啋鍏朵粬鍙兘姝e湪绛夊緟鐨勭嚎绋嬶紝浠ラ槻姝㈠嚭鐜版閿 WakeupWalSemaphore(&g_instance.wal_cxt.walFlushWaitLock->l.sem); + // 鍞ら啋鍏朵粬鍙兘姝e湪绛夊緟鐨勭嚎绋嬶紝浠ラ槻姝㈠嚭鐜版閿 WakeupWalSemaphore(&g_instance.wal_cxt.walBufferInitWaitLock->l.sem); - CHECK_FOR_INTERRUPTS(); + CHECK_FOR_INTERRUPTS(); // 妫鏌ユ槸鍚︽湁涓柇璇锋眰 } g_instance.wal_cxt.isWalWriterSleeping = false; + // 閲婃斁涓寸晫鍖虹殑浜掓枼閿 (void)pthread_mutex_unlock(&g_instance.wal_cxt.criticalEntryMutex); - time_out_counter = 0; + time_out_counter = 0; // 閲嶇疆瓒呮椂璁℃暟鍣 } - times_wrote_nothing = 0; + times_wrote_nothing = 0; // 閲嶇疆 璺熻釜杩炵画鍐欏叆WAL璁板綍鐨勬鏁 } - + // 鎶ュ憡娲诲姩鐘舵 琛ㄧず walwriter 杩涚▼鐩墠澶勪簬绌洪棽鐘舵 pgstat_report_activity(STATE_IDLE, NULL); } } @@ -350,13 +419,24 @@ void WalWriterMain(void) * Some backend has bought the farm, * so we need to stop what we're doing and exit. */ +/* + *鍔熻兘锛氬鐞嗗揩閫熺粓姝俊鍙(褰撲富杩涚▼鍙戝嚭SIGQUIT淇″彿) + * 绱фラ鍑烘搷浣滐紝涓嶄細瑙﹀彂姝e父鐨勬竻鐞嗗拰鍏抽棴姝ラ锛屽洜涓哄叡浜唴瀛樺彲鑳藉凡鎹熷潖 + * + * 鍙傛暟: + * SIGNAL_ARGS: 淇″彿澶勭悊绋嬪簭鐨勫弬鏁板垪琛紝鎻愪緵鍏充簬瑙﹀彂淇″彿鐨勪笂涓嬫枃淇℃伅 + * + * 杩斿洖鍊: + * 鏃 + */ static void wal_quickdie(SIGNAL_ARGS) { - gs_signal_setmask(&t_thrd.libpq_cxt.BlockSig, NULL); + gs_signal_setmask(&t_thrd.libpq_cxt.BlockSig, NULL); // 瑙i櫎瀵逛俊鍙风殑闃诲 - g_instance.wal_cxt.isWalWriterUp = false; - pg_memory_barrier(); + g_instance.wal_cxt.isWalWriterUp = false; // 琛ㄧず WAL Writer 杩涚▼涓嶅啀澶勪簬杩愯鐘舵 + pg_memory_barrier(); // 鎵ц鍐呭瓨灞忛殰鎿嶄綔浠ョ‘淇濆鍏变韩鍐呭瓨鐨勪慨鏀瑰緱鍒版纭悓姝 /* Stop WalWriterAuxiliary from waiting. */ + // 鍞ら啋绛夊緟鍦╣_instance.wal_cxt.walInitSegLock->l.sem 淇″彿閲忎笂鐨勪换浣曡繘绋 WakeupWalSemaphore(&g_instance.wal_cxt.walInitSegLock->l.sem); /* @@ -367,7 +447,7 @@ static void wal_quickdie(SIGNAL_ARGS) * things by calling exit() directly, we have to reset the callbacks * explicitly to make this work as intended. */ - on_exit_reset(); + on_exit_reset(); // 閲嶇疆杩涚▼閫鍑烘椂鐨勫洖璋冨嚱鏁 /* * Note we do exit(2) not exit(0). This is to force the postmaster into a @@ -377,47 +457,76 @@ static void wal_quickdie(SIGNAL_ARGS) * should ensure the postmaster sees this as a crash, too, but no harm in * being doubly sure.) */ - exit(2); + exit(2); // 浠ョ姸鎬佺爜 2 閫鍑鸿繘绋嬶紝琛ㄧず杩涚▼寮傚父閫鍑 } /* SIGHUP: set flag to re-read config file at next convenient time */ +/* + *鍔熻兘锛氬鐞 SIGHUP 淇″彿锛岀敤浜庨噸鏂拌鍙栭厤缃枃浠 + * + * 鍙傛暟: + * SIGNAL_ARGS: 淇″彿澶勭悊绋嬪簭鐨勫弬鏁板垪琛紝鎻愪緵鍏充簬瑙﹀彂淇″彿鐨勪笂涓嬫枃淇℃伅 + * + * 杩斿洖鍊: + * 鏃 + */ static void WalSigHupHandler(SIGNAL_ARGS) { - int save_errno = errno; + int save_errno = errno; // 淇濆瓨褰撳墠鐨勯敊璇爜 - t_thrd.walwriter_cxt.got_SIGHUP = true; + t_thrd.walwriter_cxt.got_SIGHUP = true; // 琛ㄧず鎺ユ敹鍒 SIGHUP 淇″彿 - if (t_thrd.proc) - SetLatch(&t_thrd.proc->procLatch); + if (t_thrd.proc) // 濡傛灉瀛樺湪杩涚▼ + SetLatch(&t_thrd.proc->procLatch); // 璁剧疆璇ヨ繘绋嬬殑杩涚▼latch - errno = save_errno; + errno = save_errno; // 鎭㈠涔嬪墠淇濆瓨鐨勯敊璇爜 } /* SIGTERM: set flag to exit normally */ +/* + *鍔熻兘锛氬鐞 SIGTERM 淇″彿锛岀敤浜庢甯搁鍑 + * + * 鍙傛暟: + * SIGNAL_ARGS: 淇″彿澶勭悊绋嬪簭鐨勫弬鏁板垪琛紝鎻愪緵鍏充簬瑙﹀彂淇″彿鐨勪笂涓嬫枃淇℃伅 + * + * 杩斿洖鍊: + * 鏃 + */ static void WalShutdownHandler(SIGNAL_ARGS) { - int save_errno = errno; + int save_errno = errno; // 淇濆瓨褰撳墠鐨勯敊璇爜 - t_thrd.walwriter_cxt.shutdown_requested = true; + t_thrd.walwriter_cxt.shutdown_requested = true; // 琛ㄧず璇锋眰姝e父閫鍑 - if (t_thrd.proc) - SetLatch(&t_thrd.proc->procLatch); + if (t_thrd.proc) // 濡傛灉瀛樺湪杩涚▼ + SetLatch(&t_thrd.proc->procLatch); // 璁剧疆璇ヨ繘绋嬬殑杩涚▼latch - errno = save_errno; + errno = save_errno; // 鎭㈠涔嬪墠淇濆瓨鐨勯敊璇爜 - g_instance.wal_cxt.isWalWriterUp = false; - pg_memory_barrier(); + g_instance.wal_cxt.isWalWriterUp = false; // 琛ㄧず WAL Writer 杩涚▼涓嶅啀澶勪簬杩愯鐘舵 + pg_memory_barrier(); // 鎵ц鍐呭瓨灞忛殰鎿嶄綔浠ョ‘淇濆鍏变韩鍐呭瓨鐨勪慨鏀瑰緱鍒版纭悓姝 /* Stop WalWriterAuxiliary from waiting. */ + // 鍞ら啋绛夊緟鍦 g_instance.wal_cxt.walInitSegLock->l.sem 淇″彿閲忎笂鐨勪换浣曡繘绋 WakeupWalSemaphore(&g_instance.wal_cxt.walInitSegLock->l.sem); } /* SIGUSR1: used for latch wakeups */ +/* + *鍔熻兘锛 澶勭悊 SIGUSR1 淇″彿锛岀敤浜庡敜閱掕繘绋嬩腑鐨勭瓑寰呮搷浣 + * + * 鍙傛暟: + * SIGNAL_ARGS: 淇″彿澶勭悊绋嬪簭鐨勫弬鏁板垪琛紝鎻愪緵鍏充簬瑙﹀彂淇″彿鐨勪笂涓嬫枃淇℃伅 + * + * 杩斿洖鍊: + * 鏃 + */ static void walwriter_sigusr1_handler(SIGNAL_ARGS) { - int save_errno = errno; + int save_errno = errno; // 淇濆瓨褰撳墠鐨勯敊璇爜 - latch_sigusr1_handler(); - errno = save_errno; + latch_sigusr1_handler(); // 澶勭悊 SIGUSR1 淇″彿 + + errno = save_errno; // 鎭㈠涔嬪墠淇濆瓨鐨勯敊璇爜 } diff --git a/src/gausskernel/process/postmaster/walwriterauxiliary.cpp b/src/gausskernel/process/postmaster/walwriterauxiliary.cpp index 10e7eb9b0..0490be47c 100755 --- a/src/gausskernel/process/postmaster/walwriterauxiliary.cpp +++ b/src/gausskernel/process/postmaster/walwriterauxiliary.cpp @@ -54,13 +54,21 @@ static void walwriterauxiliary_sigusr1_handler(SIGNAL_ARGS); * This is invoked from AuxiliaryProcessMain, which has already created the * basic execution environment, but not enabled signals yet. */ +/* + * 鍔熻兘锛 + * + * 鍙傛暟锛氭棤 + * + * 杩斿洖鍊硷細鏃 + */ void WalWriterAuxiliaryMain(void) { - sigjmp_buf local_sigjmp_buf; - MemoryContext walwriterauxiliary_context; - sigset_t old_sig_mask; + sigjmp_buf local_sigjmp_buf; // 鐢ㄤ簬寮傚父璺宠浆鐐 + MemoryContext walwriterauxiliary_context; // 澹版槑鍐呭瓨涓婁笅鏂 + sigset_t old_sig_mask; // 鐢ㄤ簬淇濆瓨鏃т俊鍙锋帺鐮佺殑鍙橀噺 - t_thrd.role = WALWRITERAUXILIARY; + t_thrd.role = WALWRITERAUXILIARY; // 灏嗗綋鍓嶇嚎绋嬬殑瑙掕壊璁剧疆涓 WAL Writer 杈呭姪杩涚▼ + // 琛ㄧず WAL Writer 杈呭姪杩涚▼宸插惎鍔 ereport(LOG, (errmsg("walwriterauxiliary started"))); /* @@ -71,6 +79,7 @@ void WalWriterAuxiliaryMain(void) * * Reset some signals that are accepted by postmaster but not here. */ + // 璁剧疆涓嶅悓鐨勪俊鍙峰鐞嗗嚱鏁 (void)gspqsignal(SIGHUP, WalwriterauxiliarySigHupHandler); /* set flag to read config file */ (void)gspqsignal(SIGINT, WalwriterauxiliaryShutdownHandler); /* request shutdown */ (void)gspqsignal(SIGTERM, WalwriterauxiliaryShutdownHandler); /* request shutdown */ @@ -86,12 +95,14 @@ void WalWriterAuxiliaryMain(void) (void)gspqsignal(SIGWINCH, SIG_DFL); /* We allow SIGQUIT (quickdie) at all times */ + // 绉婚櫎 SIGQUIT 淇″彿锛屽厑璁稿湪浠讳綍鏃跺欐帴鏀 SIGQUIT 淇″彿 (void)sigdelset(&t_thrd.libpq_cxt.BlockSig, SIGQUIT); /* * Create a resource owner to keep track of our resources (not clear that * we need this, but may as well have one). */ + // 鍒涘缓涓涓祫婧愭墍鏈夎咃紝鐢ㄤ簬璺熻釜鏈繘绋嬬殑璧勬簮 t_thrd.utils_cxt.CurrentResourceOwner = ResourceOwnerCreate(NULL, "Wal Writer Auxiliary", THREAD_GET_MEM_CXT_GROUP(MEMORY_CONTEXT_STORAGE)); @@ -101,8 +112,10 @@ void WalWriterAuxiliaryMain(void) * possible memory leaks. Formerly this code just ran in * t_thrd.top_mem_cxt, but resetting that would be a really bad idea. */ + // 涓 WAL Writer 杈呭姪杩涚▼鍒涘缓涓涓唴瀛樹笂涓嬫枃 walwriterauxiliary_context = AllocSetContextCreate(t_thrd.top_mem_cxt, "Wal Writer Auxiliary", ALLOCSET_DEFAULT_MINSIZE, ALLOCSET_DEFAULT_INITSIZE, ALLOCSET_DEFAULT_MAXSIZE); + // 鍒囨崲涓婁笅鏂 (void)MemoryContextSwitchTo(walwriterauxiliary_context); /* @@ -110,55 +123,68 @@ void WalWriterAuxiliaryMain(void) * * This code is heavily based on bgwriter.c, q.v. */ + // 寮傚父璺宠浆鐐 if (sigsetjmp(local_sigjmp_buf, 1) != 0) { /* We need restore the signal mask of current thread */ + // 鎭㈠褰撳墠绾跨▼鐨勪俊鍙锋帺鐮佷负涔嬪墠淇濆瓨鐨勬棫淇″彿鎺╃爜 (void)pthread_sigmask(SIG_SETMASK, &old_sig_mask, NULL); /* Since not using PG_TRY, must reset error stack by hand */ + // 鎵嬪姩閲嶇疆閿欒鍫嗘爤 t_thrd.log_cxt.error_context_stack = NULL; - t_thrd.log_cxt.call_stack = NULL; + t_thrd.log_cxt.call_stack = NULL; // 娓呯┖璋冪敤鏍 /* Prevent interrupts while cleaning up */ - HOLD_INTERRUPTS(); + HOLD_INTERRUPTS(); // 鍦ㄦ墽琛屾竻鐞嗘搷浣滄湡闂寸姝腑鏂 /* Report the error to the server log */ - EmitErrorReport(); + EmitErrorReport(); // 鎶ュ憡閿欒鍒版湇鍔″櫒鏃ュ織 /* abort async io, must before LWlock release */ - AbortAsyncListIO(); + AbortAsyncListIO(); // 涓寮傛I/O鎿嶄綔 /* release resource held by lsc */ - AtEOXact_SysDBCache(false); + AtEOXact_SysDBCache(false); // 閲婃斁绯荤粺鏁版嵁搴撶紦瀛樿祫婧 /* * These operations are really just a minimal subset of * AbortTransaction(). We don't have very many resources to worry * about in walwriterauxiliary, but we do have LWLocks, and perhaps buffers? */ - LWLockReleaseAll(); - pgstat_report_waitevent(WAIT_EVENT_END); - AbortBufferIO(); - UnlockBuffers(); + LWLockReleaseAll(); // 閲婃斁閿 + pgstat_report_waitevent(WAIT_EVENT_END); // 鎶ュ憡绛夊緟浜嬩欢缁撴潫锛岀敤浜庢ц兘缁熻鍜岃瘖鏂 + AbortBufferIO(); // 涓缂撳啿鍖篒/O鎿嶄綔鐨勫嚱鏁拌皟鐢 + UnlockBuffers(); // 瑙i攣缂撳啿鍖,纭繚鍦ㄥ紓甯告儏鍐典笅涓嶄細淇濈暀鏈В閿佺殑缂撳啿鍖 /* buffer pins are released here: */ + // 閲婃斁璧勬簮锛屽寘鎷祫婧愭墍鏈夎呮寔鏈夌殑璧勬簮 ResourceOwnerRelease(t_thrd.utils_cxt.CurrentResourceOwner, RESOURCE_RELEASE_BEFORE_LOCKS, false, true); /* we needn't bother with the other ResourceOwnerRelease phases */ + // 澶勭悊浜嬪姟缁撴潫鐨勫嚱鏁拌皟鐢 涓庣紦鍐插尯鐩稿叧鐨勬竻鐞嗗伐浣 AtEOXact_Buffers(false); + // 澶勭悊浜嬪姟缁撴潫鐨勫嚱鏁拌皟鐢 涓庡瓨鍌ㄧ鐞嗗櫒鐩稿叧鐨勬竻鐞嗗伐浣 AtEOXact_SMgr(); + // 澶勭悊浜嬪姟缁撴潫鐨勫嚱鏁拌皟鐢 鐢ㄤ簬鍏抽棴涓庢枃浠舵搷浣滅浉鍏崇殑璧勬簮 AtEOXact_Files(); + // 澶勭悊浜嬪姟缁撴潫鐨勫嚱鏁拌皟鐢 鐢ㄤ簬娓呯悊鍝堝笇琛ㄥ拰鐩稿叧鏁版嵁缁撴瀯 AtEOXact_HashTables(false); /* * Now return to normal top-level context and clear ErrorContext for * next time. */ + // 鍒囨崲绋嬪簭鐨勫唴瀛樹笂涓嬫枃 (void)MemoryContextSwitchTo(walwriterauxiliary_context); + // 娓呴櫎閿欒鐘舵侊紝灏嗕箣鍓嶅彲鑳借褰曠殑閿欒淇℃伅鍜岀姸鎬侀噸缃负绌 FlushErrorState(); /* Flush any leaked data in the top-level context */ + // 閲嶇疆 walwriter_context 涓婁笅鏂囧苟鍒犻櫎鍏舵墍鏈夊瓙绾т笂涓嬫枃 + // 纭繚鍦ㄥ紓甯稿鐞嗗畬鎴愬悗閲婃斁宸插垎閰嶇殑鍐呭瓨锛屼互閬垮厤鍐呭瓨娉勬紡 MemoryContextResetAndDeleteChildren(walwriterauxiliary_context); /* Now we can allow interrupts again */ + // 鍏佽涓柇淇″彿鍐嶆琚崟鑾 RESUME_INTERRUPTS(); /* @@ -166,29 +192,34 @@ void WalWriterAuxiliaryMain(void) * to be repeated, and we don't want to be filling the error logs as * fast as we can. */ - pg_usleep(1000000L); + pg_usleep(1000000L); // 浼戠湢 /* * Close all open files after any error. This is helpful on Windows, * where holding deleted files open causes various strange errors. * It's not clear we need it elsewhere, but shouldn't hurt. */ - smgrcloseall(); + smgrcloseall(); // 鍏抽棴鎵鏈夋墦寮鐨勬枃浠 } /* We can now handle ereport(ERROR) */ + // 璁剧疆寮傚父澶勭悊鏍 t_thrd.log_cxt.PG_exception_stack = &local_sigjmp_buf; /* * Unblock signals (they were blocked when the postmaster forked us) */ + // 瑙i櫎淇″彿鎺╃爜锛屽厑璁告帴鏀朵俊鍙 gs_signal_setmask(&t_thrd.libpq_cxt.UnBlockSig, NULL); + // 瑙i櫎瀵 SIGUSR2 淇″彿鐨勯樆濉烇紝鍏佽鎺ユ敹姝や俊鍙 (void)gs_signal_unblock_sigusr2(); /* * Use the recovery target timeline ID during recovery */ + // v濡傛灉姝e湪杩涜鎭㈠鎿嶄綔 if (RecoveryInProgress()) { + // 璁剧疆褰撳墠绾跨▼鐨勬椂闂寸嚎ID涓烘仮澶嶇洰鏍囩殑鏃堕棿绾縄D t_thrd.xlog_cxt.ThisTimeLineID = GetRecoveryTargetTLI(); } @@ -196,50 +227,62 @@ void WalWriterAuxiliaryMain(void) * Advertise our latch that backends can use to wake us up while we're * sleeping. */ + // 灏嗗綋鍓嶇嚎绋嬬殑杩涚▼Latch涓 walwriterauxiliaryLatch 鐩稿叧鑱 + // 浠ヤ究鍏朵粬鍚庡彴杩涚▼鍙互浣跨敤姝atch鍞ら啋 WalWriterAuxiliary 杩涚▼ g_instance.proc_base->walwriterauxiliaryLatch = &t_thrd.proc->procLatch; - + // 鎶ュ憡杩涚▼鐨勫簲鐢ㄧ▼搴忓悕绉颁负 "Wal Writer Auxiliary"锛岀敤浜庢ц兘缁熻 pgstat_report_appname("Wal Writer Auxiliary"); + // 鎶ュ憡杩涚▼鐨勬椿鍔ㄧ姸鎬佷负 "STATE_IDLE"锛岀敤浜庢ц兘缁熻 pgstat_report_activity(STATE_IDLE, NULL); /* * Loop forever */ for (;;) { + // 鑾峰彇绛夊緟瓒呮椂鐨勬椂闂 long curTimeout = u_sess->attr.attr_storage.WalWriterDelay; - int rc = 0; + int rc = 0; // 鐢ㄤ簬瀛樺偍绛夊緟缁撴灉 /* Clear any already-pending wakeups */ + // 娓呴櫎浠讳綍宸茬粡鎸傝捣鐨凩atch锛屼互鍑嗗鎺ユ敹鏂扮殑Latch閫氱煡 ResetLatch(&t_thrd.proc->procLatch); /* * Process any requests or signals received recently. */ + // 澶勭悊浠讳綍鏈杩戞帴鏀跺埌鐨勮姹傛垨淇″彿 if (t_thrd.walwriterauxiliary_cxt.got_SIGHUP) { t_thrd.walwriterauxiliary_cxt.got_SIGHUP = false; - ProcessConfigFile(PGC_SIGHUP); + ProcessConfigFile(PGC_SIGHUP); // 閲嶆柊璇诲彇閰嶇疆鏂囦欢 } - + // 濡傛灉鎺ユ敹鍒颁簡 shutdown_requested 鏍囧織 if (t_thrd.walwriterauxiliary_cxt.shutdown_requested) { /* Normal exit from the walwriterauxiliary is here. */ - proc_exit(0); /* done */ + proc_exit(0); /* done */ // 姝e父閫鍑 } - + // 妫鏌 Wal Writer 杩涚▼鏄惁姝e湪杩愯 if (g_instance.wal_cxt.isWalWriterUp) { + // 绛夊緟涓昏妭鐐瑰垵濮嬪寲Xlog鏂囦欢鐨勪俊鍙 PGSemaphoreLock(&g_instance.wal_cxt.walInitSegLock->l.sem, true); + // 鎵ц涓庝富鑺傜偣鐩稿叧鐨勫垵濮嬪寲鎿嶄綔 PreInitXlogFileForPrimary(g_instance.attr.attr_storage.wal_file_init_num); } else { + // 濡傛灉鍒濆鍖栫殑Xlog鏂囦欢鏁伴噺澶т簬0涓斿綋鍓嶇殑杩愯妯″紡涓 STANDBY_MODE + // 涓斿綋鍓嶇殑 Postmaster 鐘舵佷负 PM_RECOVERY 鎴 PM_HOT_STANDBY + // 涓斿嚱鏁版鏌ュ凡瀹屾垚鎭㈠鎿嶄綔 if (g_instance.attr.attr_storage.advance_xlog_file_num > 0 && t_thrd.postmaster_cxt.HaShmData->current_mode == STANDBY_MODE && (pmState == PM_RECOVERY || pmState == PM_HOT_STANDBY) && IsRecoveryDone()) { + // 璇诲彇鏈湴鏈澶SN锛岃〃绀哄綋鍓嶅鑺傜偣宸茬粡鎭㈠鐨勮繘搴 XLogRecPtr curMaxLsn = pg_atomic_read_u64(&g_instance.comm_cxt.predo_cxt.redoPf.local_max_lsn); - PreInitXlogFileForStandby(curMaxLsn); + PreInitXlogFileForStandby(curMaxLsn); // 鎵ц涓庡鑺傜偣鐩稿叧鐨勫垵濮嬪寲鎿嶄綔 } } - + // 绛夊緟鏂扮殑Latch閫氱煡鎴栬秴鏃 rc = WaitLatch(&t_thrd.proc->procLatch, WL_LATCH_SET | WL_TIMEOUT | WL_POSTMASTER_DEATH, curTimeout); - if (rc & WL_POSTMASTER_DEATH) { - gs_thread_exit(1); + if (rc & WL_POSTMASTER_DEATH) { // 鎺ユ敹鍒 Postmaster 缁堟淇″彿 + gs_thread_exit(1); // 閫鍑虹嚎绋 } } } @@ -255,9 +298,19 @@ void WalWriterAuxiliaryMain(void) * Some backend has bought the farm, * so we need to stop what we're doing and exit. */ +/* + *鍔熻兘锛氬鐞嗗揩閫熺粓姝俊鍙(褰撲富杩涚▼鍙戝嚭SIGQUIT淇″彿) + * 绱фラ鍑烘搷浣滐紝涓嶄細瑙﹀彂姝e父鐨勬竻鐞嗗拰鍏抽棴姝ラ锛屽洜涓哄叡浜唴瀛樺彲鑳藉凡鎹熷潖 + * + * 鍙傛暟: + * SIGNAL_ARGS: 淇″彿澶勭悊绋嬪簭鐨勫弬鏁板垪琛紝鎻愪緵鍏充簬瑙﹀彂淇″彿鐨勪笂涓嬫枃淇℃伅 + * + * 杩斿洖鍊: + * 鏃 + */ static void walwriterauxiliary_quickdie(SIGNAL_ARGS) { - gs_signal_setmask(&t_thrd.libpq_cxt.BlockSig, NULL); + gs_signal_setmask(&t_thrd.libpq_cxt.BlockSig, NULL); // 瑙i櫎瀵逛俊鍙风殑闃诲 /* * We DO NOT want to run proc_exit() callbacks -- we're here because @@ -267,7 +320,7 @@ static void walwriterauxiliary_quickdie(SIGNAL_ARGS) * things by calling exit() directly, we have to reset the callbacks * explicitly to make this work as intended. */ - on_exit_reset(); + on_exit_reset(); // 閲嶇疆杩涚▼閫鍑烘椂鐨勫洖璋冨嚱鏁 /* * Note we do exit(2) not exit(0). This is to force the postmaster into a @@ -277,41 +330,68 @@ static void walwriterauxiliary_quickdie(SIGNAL_ARGS) * should ensure the postmaster sees this as a crash, too, but no harm in * being doubly sure.) */ - exit(2); + exit(2); // 浠ョ姸鎬佺爜 2 閫鍑鸿繘绋嬶紝琛ㄧず杩涚▼寮傚父閫鍑 } /* SIGHUP: set flag to re-read config file at next convenient time */ +/* + *鍔熻兘锛氬鐞 SIGHUP 淇″彿锛岀敤浜庨噸鏂拌鍙栭厤缃枃浠 + * + * 鍙傛暟: + * SIGNAL_ARGS: 淇″彿澶勭悊绋嬪簭鐨勫弬鏁板垪琛紝鎻愪緵鍏充簬瑙﹀彂淇″彿鐨勪笂涓嬫枃淇℃伅 + * + * 杩斿洖鍊: + * 鏃 + */ static void WalwriterauxiliarySigHupHandler(SIGNAL_ARGS) { - int save_errno = errno; + int save_errno = errno; // 淇濆瓨褰撳墠鐨勯敊璇爜 - t_thrd.walwriterauxiliary_cxt.got_SIGHUP = true; + t_thrd.walwriterauxiliary_cxt.got_SIGHUP = true; // 琛ㄧず鎺ユ敹鍒 SIGHUP 淇″彿 - if (t_thrd.proc) - SetLatch(&t_thrd.proc->procLatch); + if (t_thrd.proc) // 濡傛灉瀛樺湪杩涚▼ + SetLatch(&t_thrd.proc->procLatch); // 璁剧疆璇ヨ繘绋嬬殑杩涚▼latch - errno = save_errno; + errno = save_errno; // 鎭㈠涔嬪墠淇濆瓨鐨勯敊璇爜 } /* SIGTERM: set flag to exit normally */ +/* + *鍔熻兘锛氬鐞 SIGTERM 淇″彿锛岀敤浜庢甯搁鍑 + * + * 鍙傛暟: + * SIGNAL_ARGS: 淇″彿澶勭悊绋嬪簭鐨勫弬鏁板垪琛紝鎻愪緵鍏充簬瑙﹀彂淇″彿鐨勪笂涓嬫枃淇℃伅 + * + * 杩斿洖鍊: + * 鏃 + */ static void WalwriterauxiliaryShutdownHandler(SIGNAL_ARGS) { - int save_errno = errno; + int save_errno = errno; // 淇濆瓨褰撳墠鐨勯敊璇爜 - t_thrd.walwriterauxiliary_cxt.shutdown_requested = true; + t_thrd.walwriterauxiliary_cxt.shutdown_requested = true; // 琛ㄧず璇锋眰姝e父閫鍑 - if (t_thrd.proc) - SetLatch(&t_thrd.proc->procLatch); + if (t_thrd.proc) // 濡傛灉瀛樺湪杩涚▼ + SetLatch(&t_thrd.proc->procLatch); // 璁剧疆璇ヨ繘绋嬬殑杩涚▼latch - errno = save_errno; + errno = save_errno; // 鎭㈠涔嬪墠淇濆瓨鐨勯敊璇爜 } /* SIGUSR1: used for latch wakeups */ +/* + *鍔熻兘锛 澶勭悊 SIGUSR1 淇″彿锛岀敤浜庡敜閱掕繘绋嬩腑鐨勭瓑寰呮搷浣 + * + * 鍙傛暟: + * SIGNAL_ARGS: 淇″彿澶勭悊绋嬪簭鐨勫弬鏁板垪琛紝鎻愪緵鍏充簬瑙﹀彂淇″彿鐨勪笂涓嬫枃淇℃伅 + * + * 杩斿洖鍊: + * 鏃 + */ static void walwriterauxiliary_sigusr1_handler(SIGNAL_ARGS) { - int save_errno = errno; + int save_errno = errno; // 淇濆瓨褰撳墠鐨勯敊璇爜 - latch_sigusr1_handler(); + latch_sigusr1_handler(); // 澶勭悊 SIGUSR1 淇″彿 - errno = save_errno; + errno = save_errno; // 鎭㈠涔嬪墠淇濆瓨鐨勯敊璇爜 } diff --git a/src/gausskernel/process/postmaster/鏂板缓鏂囨湰鏂囨。.bat b/src/gausskernel/process/postmaster/鏂板缓鏂囨湰鏂囨。.bat new file mode 100644 index 000000000..d055abd11 --- /dev/null +++ b/src/gausskernel/process/postmaster/鏂板缓鏂囨湰鏂囨。.bat @@ -0,0 +1 @@ +DIR *.* /B >LIST.TXT \ No newline at end of file diff --git a/src/gausskernel/process/stream/execStream.cpp b/src/gausskernel/process/stream/execStream.cpp index b054c2a1a..f1553f7a6 100755 --- a/src/gausskernel/process/stream/execStream.cpp +++ b/src/gausskernel/process/stream/execStream.cpp @@ -77,15 +77,17 @@ static void InitStreamFlow(StreamFlowCtl* ctl); #define NODENAMELEN 64 +// 妫鏌ュ綋鍓嶇嚎绋嬫槸鍚﹀湪澶勭悊娴佹暟鎹祦閫掑綊 bool IsThreadProcessStreamRecursive() { - StreamNodeGroup* stream_nodegroup = u_sess->stream_cxt.global_obj; + StreamNodeGroup* stream_nodegroup = u_sess->stream_cxt.global_obj; // 鑾峰彇鍏ㄥ眬娴佽妭鐐圭粍瀵硅薄 + // 濡傛灉涓嶆槸鍒嗗竷寮忔暟鎹妭鐐癸紝鎴栬呮祦鑺傜偣缁勪负绌猴紝鎴栬呭悓姝ユ帶鍒跺櫒鍒楄〃涓虹┖ if (!IS_PGXC_DATANODE || stream_nodegroup == NULL || stream_nodegroup->m_syncControllers == NIL) { - return false; + return false; // 杩斿洖false锛岃〃绀哄綋鍓嶇嚎绋嬩笉鍦ㄥ鐞嗘祦鏁版嵁娴侀掑綊 } - return true; + return true; // 杩斿洖true锛岃〃绀哄綋鍓嶇嚎绋嬪湪澶勭悊娴佹暟鎹祦閫掑綊 } /* @@ -94,10 +96,11 @@ bool IsThreadProcessStreamRecursive() * @param[IN] plan_tree: plan tree * @return: bool, true if is dummy */ +// 妫鏌ョ嚎绋嬫槸鍚︿负铏氭嫙绾跨▼ bool ThreadIsDummy(Plan* plan_tree) { #ifdef ENABLE_MULTIPLE_NODES - /* For top consumer, we need to check consumer_nodes if top node of plan_tree is Stream. */ + /* 瀵逛簬椤剁骇娑堣垂鑰咃紝鎴戜滑闇瑕佹鏌ヨ鍒掓爲鐨勯《绾ц妭鐐规槸鍚︿负Stream銆 */ if (IsA(plan_tree, Stream) || IsA(plan_tree, VecStream)) { Stream* streamNode = (Stream*)plan_tree; List* nodeList = streamNode->consumer_nodes->nodeList; @@ -110,35 +113,36 @@ bool ThreadIsDummy(Plan* plan_tree) #endif } +// 鑾峰彇Stream鑺傜偣鐨勫垎鍙戠被鍨嬫爣绛 const char* GetStreamTypeRedistribute(Stream* node) { const char* stream_tag = NULL; - bool isRangeListRedis = (node->consumer_nodes->boundaries != NULL); + bool isRangeListRedis = (node->consumer_nodes->boundaries != NULL); // 妫鏌ユ槸鍚︿负鑼冨洿鎴栧垪琛ㄥ垎甯 bool isRangeRedis = (isRangeListRedis) ? - (node->consumer_nodes->boundaries->locatorType == LOCATOR_TYPE_RANGE) : false; + (node->consumer_nodes->boundaries->locatorType == LOCATOR_TYPE_RANGE) : false; // 妫鏌ユ槸鍚︿负鑼冨洿鍒嗗竷 switch (node->smpDesc.distriType) { case LOCAL_DISTRIBUTE: - stream_tag = "LOCAL REDISTRIBUTE"; + stream_tag = "LOCAL REDISTRIBUTE"; // 鏈湴鍒嗗竷 break; case LOCAL_BROADCAST: - stream_tag = "LOCAL BROADCAST"; + stream_tag = "LOCAL BROADCAST"; // 鏈湴骞挎挱 break; case LOCAL_ROUNDROBIN: - stream_tag = (node->smpDesc.consumerDop == 1) ? "LOCAL GATHER" : "LOCAL ROUNDROBIN"; + stream_tag = (node->smpDesc.consumerDop == 1) ? "LOCAL GATHER" : "LOCAL ROUNDROBIN"; // 鏈湴杞鎴栬仛闆 break; case REMOTE_SPLIT_DISTRIBUTE: { if (isRangeListRedis) { if (isRangeRedis) { - stream_tag = "SPLIT RANGE REDISTRIBUTE"; + stream_tag = "SPLIT RANGE REDISTRIBUTE"; // 鑼冨洿鍒嗗竷 } else { - stream_tag = "SPLIT LIST REDISTRIBUTE"; + stream_tag = "SPLIT LIST REDISTRIBUTE"; // 鍒楄〃鍒嗗竷 } } else { - stream_tag = "SPLIT REDISTRIBUTE"; + stream_tag = "SPLIT REDISTRIBUTE"; // 鍒嗗竷 } break; } @@ -146,12 +150,12 @@ const char* GetStreamTypeRedistribute(Stream* node) default: { if (isRangeListRedis) { if (isRangeRedis) { - stream_tag = "RANGE REDISTRIBUTE"; + stream_tag = "RANGE REDISTRIBUTE"; // 鑼冨洿鍒嗗竷 } else { - stream_tag = "LIST REDISTRIBUTE"; + stream_tag = "LIST REDISTRIBUTE"; // 鍒楄〃鍒嗗竷 } } else { - stream_tag = "REDISTRIBUTE"; + stream_tag = "REDISTRIBUTE"; // 鍒嗗竷 } break; } @@ -160,47 +164,49 @@ const char* GetStreamTypeRedistribute(Stream* node) return stream_tag; } +// 鑾峰彇Hybrid绫诲瀷鐨凷tream鑺傜偣鏍囩 const char* GetStreamTypeHybrid(Stream* node) { - const char* stream_tag = NULL; - List* skew_list = node->skew_list; - ListCell* lc = NULL; - SkewStreamType sstype = PART_NONE; + const char* stream_tag = NULL; // 瀹氫箟Stream鑺傜偣鏍囩 + List* skew_list = node->skew_list; // 鑾峰彇Skew淇℃伅鍒楄〃 + ListCell* lc = NULL; // 瀹氫箟ListCell杩唬鍣 + SkewStreamType sstype = PART_NONE; // 瀹氫箟SkewStreamType鍙橀噺锛岄粯璁や负PART_NONE + + Assert(list_length(skew_list) >= 1); // 鏂█锛歋kew淇℃伅鍒楄〃鐨勯暱搴﹁嚦灏戜负1 - Assert(list_length(skew_list) >= 1); - - /* check if all qual skew share the same stream type. */ + /* 妫鏌ユ墍鏈夌殑Skew淇℃伅鏄惁鍏变韩鐩稿悓鐨勬祦绫诲瀷 */ foreach (lc, skew_list) { - QualSkewInfo* qsinfo = (QualSkewInfo*)lfirst(lc); - + QualSkewInfo* qsinfo = (QualSkewInfo*)lfirst(lc); // 鑾峰彇Skew淇℃伅 + if (sstype == PART_NONE) - sstype = qsinfo->skew_stream_type; - + sstype = qsinfo->skew_stream_type; // 濡傛灉sstype涓篜ART_NONE锛岃缃负褰撳墠Skew淇℃伅鐨勬祦绫诲瀷 + if (sstype != qsinfo->skew_stream_type) { - sstype = PART_NONE; + sstype = PART_NONE; // 濡傛灉瀛樺湪涓嶅悓鐨勬祦绫诲瀷锛屽皢sstype璁剧疆涓篜ART_NONE break; } } - + + // 鏍规嵁sstype鐨勫肩‘瀹歋tream鑺傜偣鏍囩 switch (sstype) { case PART_REDISTRIBUTE_PART_BROADCAST: - stream_tag = "PART REDISTRIBUTE PART BROADCAST"; + stream_tag = "PART REDISTRIBUTE PART BROADCAST"; // 閮ㄥ垎閲嶅垎甯冨拰閮ㄥ垎骞挎挱 break; case PART_REDISTRIBUTE_PART_ROUNDROBIN: - stream_tag = "PART REDISTRIBUTE PART ROUNDROBIN"; + stream_tag = "PART REDISTRIBUTE PART ROUNDROBIN"; // 閮ㄥ垎閲嶅垎甯冨拰閮ㄥ垎杞 break; case PART_REDISTRIBUTE_PART_LOCAL: - stream_tag = "PART REDISTRIBUTE PART LOCAL"; + stream_tag = "PART REDISTRIBUTE PART LOCAL"; // 閮ㄥ垎閲嶅垎甯冨拰閮ㄥ垎鏈湴 break; case PART_LOCAL_PART_BROADCAST: - stream_tag = "PART LOCAL PART BROADCAST"; + stream_tag = "PART LOCAL PART BROADCAST"; // 閮ㄥ垎鏈湴鍜岄儴鍒嗗箍鎾 break; default: - stream_tag = "HYBRID"; + stream_tag = "HYBRID"; // 娣峰悎绫诲瀷 break; } - return stream_tag; + return stream_tag; // 杩斿洖Stream鑺傜偣鏍囩 } @@ -210,64 +216,67 @@ const char* GetStreamTypeHybrid(Stream* node) * @param[IN] node: stream plan node * @return: string of stream type */ +// 鑾峰彇Stream鑺傜偣鐨勭被鍨嬫弿杩 const char* GetStreamType(Stream* node) { - Plan* stream_plan = (Plan*)node; - const char* vector_tag = stream_plan->vec_output ? "Vector " : ""; - const char* stream_tag = NULL; - char dop_tag[100] = {0}; - char ng_tag[NODENAMELEN * 2 + 10] = {0}; - StringInfo type = makeStringInfo(); - char* consumerGroupName = NULL; - char* producerGroupName = NULL; + Plan* stream_plan = (Plan*)node; // 灏哠tream鑺傜偣杞崲涓篜lan鑺傜偣 + const char* vector_tag = stream_plan->vec_output ? "Vector " : ""; // 鍒ゆ柇鏄惁浣跨敤鍚戦噺鍖栨墽琛岋紝璁剧疆鍚戦噺鏍囩 + const char* stream_tag = NULL; // 瀹氫箟Stream鑺傜偣鐨勭被鍨嬫爣绛 + char dop_tag[100] = {0}; // 鐢ㄤ簬瀛樺偍骞惰搴︿俊鎭殑瀛楃鏁扮粍 + char ng_tag[NODENAMELEN * 2 + 10] = {0}; // 鐢ㄤ簬瀛樺偍鑺傜偣缁勪俊鎭殑瀛楃鏁扮粍 + StringInfo type = makeStringInfo(); // 鍒涘缓StringInfo缁撴瀯浣擄紝鐢ㄤ簬瀛樺偍鑺傜偣绫诲瀷淇℃伅 + char* consumerGroupName = NULL; // 娑堣垂鑰呰妭鐐圭粍鍚嶇О + char* producerGroupName = NULL; // 鐢熶骇鑰呰妭鐐圭粍鍚嶇О - /* Set DOP tag if parallel enabled */ + /* 濡傛灉鍚敤骞惰搴︼紝璁剧疆骞惰搴︽爣绛 */ if (node->smpDesc.consumerDop > 1 || node->smpDesc.producerDop > 1) { errno_t rc = sprintf_s(dop_tag, sizeof(dop_tag), " dop: %d/%d", node->smpDesc.consumerDop, node->smpDesc.producerDop); securec_check_ss(rc, "\0", "\0"); } - /* show nodegroup shuffle infomation, ng: group1->group2 */ + /* 鏄剧ず鑺傜偣缁勬礂鐗屼俊鎭紝鏍煎紡涓猴細ng: group1->group2 */ if (ng_enable_nodegroup_explain()) { - ExecNodes* consumerNodes = node->consumer_nodes; - ExecNodes* producerNodes = node->scan.plan.exec_nodes; + ExecNodes* consumerNodes = node->consumer_nodes; // 娑堣垂鑰呰妭鐐 + ExecNodes* producerNodes = node->scan.plan.exec_nodes; // 鐢熶骇鑰呰妭鐐 + /* 濡傛灉娑堣垂鑰呰妭鐐圭粍涓庣敓浜ц呰妭鐐圭粍涓嶅悓锛岃幏鍙栬妭鐐圭粍鍚嶇О淇℃伅 */ if (!ng_is_same_group(&(consumerNodes->distribution), &(producerNodes->distribution))) { - consumerGroupName = ng_get_dist_group_name(&(consumerNodes->distribution)); - producerGroupName = ng_get_dist_group_name(&(producerNodes->distribution)); + consumerGroupName = ng_get_dist_group_name(&(consumerNodes->distribution)); // 鑾峰彇娑堣垂鑰呰妭鐐圭粍鍚嶇О + producerGroupName = ng_get_dist_group_name(&(producerNodes->distribution)); // 鑾峰彇鐢熶骇鑰呰妭鐐圭粍鍚嶇О errno_t rc = sprintf_s(ng_tag, sizeof(ng_tag), " ng: %s->%s", producerGroupName, consumerGroupName); securec_check_ss(rc, "\0", "\0"); } } + /* 鏍规嵁鑺傜偣绫诲瀷璁剧疆娴佺被鍨嬫爣绛撅紝骞跺皢鏍囩淇℃伅杩藉姞鍒皌ype缁撴瀯浣撲腑 */ switch (node->type) { case STREAM_BROADCAST: { if (node->smpDesc.distriType == REMOTE_SPLIT_BROADCAST) { - stream_tag = "SPLIT BROADCAST"; + stream_tag = "SPLIT BROADCAST"; // 鍒嗗竷寮忓垎瑁傚箍鎾 } else { - stream_tag = "BROADCAST"; + stream_tag = "BROADCAST"; // 骞挎挱 } - appendStringInfo(type, "%sStreaming(type: %s%s%s)", vector_tag, stream_tag, dop_tag, ng_tag); + appendStringInfo(type, "%sStreaming(type: %s%s%s)", vector_tag, stream_tag, dop_tag, ng_tag); // 鏍煎紡鍖栧苟杩藉姞鍒皌ype涓 } break; case STREAM_REDISTRIBUTE: { - stream_tag = GetStreamTypeRedistribute(node); - appendStringInfo(type, "%sStreaming(type: %s%s%s)", vector_tag, stream_tag, dop_tag, ng_tag); + stream_tag = GetStreamTypeRedistribute(node); // 鑾峰彇閲嶅垎甯冪被鍨 + appendStringInfo(type, "%sStreaming(type: %s%s%s)", vector_tag, stream_tag, dop_tag, ng_tag); // 鏍煎紡鍖栧苟杩藉姞鍒皌ype涓 } break; case STREAM_HYBRID: { - stream_tag = GetStreamTypeHybrid(node); - appendStringInfo(type, "%sStreaming(type: %s%s%s)", vector_tag, stream_tag, dop_tag, ng_tag); + stream_tag = GetStreamTypeHybrid(node); // 鑾峰彇娣峰悎绫诲瀷 + appendStringInfo(type, "%sStreaming(type: %s%s%s)", vector_tag, stream_tag, dop_tag, ng_tag); // 鏍煎紡鍖栧苟杩藉姞鍒皌ype涓 } break; default: - appendStringInfo(type, "UNKNOWN"); + appendStringInfo(type, "UNKNOWN"); // 鏈煡绫诲瀷 break; } - return type->data; + return type->data; // 杩斿洖Stream鑺傜偣鐨勭被鍨嬫弿杩 } void StreamSaveTxnContext(StreamTxnContext* stc) @@ -293,13 +302,16 @@ void StreamRestoreTxnContext(StreamTxnContext* stc) * @param[IN] smpIdentifier: smp identifier * @return: pointer to stream object */ +// 閫氳繃SMP鏍囪瘑鍦⊿treamObj鍒楄〃涓煡鎵維treamObj瀵硅薄 static StreamObj* FindStreamObjBySmpId(List* streamList, uint32 smpIdentifier) { ListCell* cell = NULL; StreamObj* obj = NULL; + // 閬嶅巻StreamObj鍒楄〃 foreach (cell, streamList) { obj = (StreamObj*)lfirst(cell); + // 鎵惧埌鍖归厤鐨凷MP鏍囪瘑鐨凷treamObj瀵硅薄 if (obj->getKey().smpIdentifier == smpIdentifier) break; else @@ -309,11 +321,14 @@ static StreamObj* FindStreamObjBySmpId(List* streamList, uint32 smpIdentifier) return obj; } +// 鏋勫缓鏈湴Stream涓婁笅鏂 static StreamSharedContext* buildLocalStreamContext(Stream* streamNode, PlannedStmt* pstmt) { + // 濡傛灉涓嶆槸鏈湴鑺傜偣锛屽垯杩斿洖NULL if (!STREAM_IS_LOCAL_NODE(streamNode->smpDesc.distriType)) return NULL; + // 鍒嗛厤StreamSharedContext瀵硅薄鐨勫唴瀛樼┖闂 StreamSharedContext* sharedContext = (StreamSharedContext*)palloc0(sizeof(StreamSharedContext)); MemoryContext localStreamMemoryCtx = NULL; VectorBatch*** sharedBatches = NULL; @@ -324,11 +339,13 @@ static StreamSharedContext* buildLocalStreamContext(Stream* streamNode, PlannedS int* scanLoc = NULL; char context_name[NODENAMELEN]; int rc = 0; - int consumerNum = streamNode->smpDesc.consumerDop; - int producerNum = streamNode->smpDesc.producerDop; + int consumerNum = streamNode->smpDesc.consumerDop; // 娑堣垂鑰呭苟琛屽害 + int producerNum = streamNode->smpDesc.producerDop; // 鐢熶骇鑰呭苟琛屽害 + // 鏂█锛歋tream鑺傜偣鐨勮鍒掕妭鐐笽D涓嶄负0 Assert(streamNode->scan.plan.plan_node_id != 0); - /* Set memory context name. */ + + // 璁剧疆鍐呭瓨涓婁笅鏂囩殑鍚嶇О rc = snprintf_s(context_name, NODENAMELEN, NODENAMELEN - 1, @@ -338,7 +355,7 @@ static StreamSharedContext* buildLocalStreamContext(Stream* streamNode, PlannedS streamNode->scan.plan.plan_node_id); securec_check_ss(rc, "", ""); - /* Create a shared memory context for local stream in-memory data exchange. */ + // 鍒涘缓鏈湴Stream鐨勫叡浜唴瀛樹笂涓嬫枃 localStreamMemoryCtx = AllocSetContextCreate(u_sess->stream_cxt.data_exchange_mem_cxt, context_name, ALLOCSET_DEFAULT_MINSIZE, @@ -346,11 +363,11 @@ static StreamSharedContext* buildLocalStreamContext(Stream* streamNode, PlannedS ALLOCSET_DEFAULT_MAXSIZE, SHARED_CONTEXT); + // 鍒囨崲鍒板叡浜唴瀛樹笂涓嬫枃涓 MemoryContext oldCxt = MemoryContextSwitchTo(localStreamMemoryCtx); + // 鍒嗛厤鍐呭瓨鍜屽垵濮嬪寲鍚勭鏁版嵁缁撴瀯 scanLoc = (int*)palloc0(sizeof(int) * consumerNum); - - /* Init data status. */ dataStatus = (DataStatus**)palloc0(sizeof(DataStatus*) * consumerNum); is_connect_end = (bool**)palloc0(sizeof(bool*) * consumerNum); messages = (StringInfo**)palloc0(sizeof(StringInfo*) * consumerNum); @@ -366,7 +383,7 @@ static StreamSharedContext* buildLocalStreamContext(Stream* streamNode, PlannedS } } - /* Init shared batches or tuples */ + // 鍒濆鍖栧叡浜殑鎵规鎴栧厓缁 if (IsA((Plan*)streamNode, VecStream)) { sharedBatches = (VectorBatch***)palloc0(sizeof(VectorBatch**) * consumerNum); for (int i = 0; i < consumerNum; i++) { @@ -379,6 +396,7 @@ static StreamSharedContext* buildLocalStreamContext(Stream* streamNode, PlannedS } } + // 璁剧疆鍏变韩涓婁笅鏂囩殑鍚勭灞炴 sharedContext->vectorized = IsA(&(streamNode->scan.plan), VecStream); sharedContext->localStreamMemoryCtx = localStreamMemoryCtx; sharedContext->sharedBatches = sharedBatches; @@ -388,16 +406,17 @@ static StreamSharedContext* buildLocalStreamContext(Stream* streamNode, PlannedS sharedContext->messages = messages; sharedContext->scanLoc = scanLoc; - /* Set stream key. */ + // 璁剧疆娴佺殑鍏抽敭灞炴 sharedContext->key_s.queryId = pstmt->queryId; sharedContext->key_s.planNodeId = streamNode->scan.plan.plan_node_id; sharedContext->key_s.producerSmpId = ~0; sharedContext->key_s.consumerSmpId = ~0; + // 鍒濆鍖栧叡浜唴瀛樻睜 gs_memory_init_entry(sharedContext, consumerNum, producerNum); - MemoryContextSwitchTo(oldCxt); + MemoryContextSwitchTo(oldCxt); // 鍒囨崲鍥炲師濮嬪唴瀛樹笂涓嬫枃 - return sharedContext; + return sharedContext; // 杩斿洖鏋勫缓鐨勬湰鍦癝tream涓婁笅鏂 } /* @@ -406,34 +425,41 @@ static StreamSharedContext* buildLocalStreamContext(Stream* streamNode, PlannedS * @param[IN] context: local stream context cached in consumer. * @return void */ +// 閲嶇疆鏈湴Stream涓婁笅鏂 static void resetLocalStreamContext(StreamSharedContext* context) { + // 濡傛灉涓婁笅鏂囦负绌猴紝鍒欑洿鎺ヨ繑鍥 if (context == NULL) return; + // 閲嶇疆涓婁笅鏂囦腑鐨勬暟鎹粨鏋 context->scanLoc[0] = 0; context->dataStatus[0][0] = DATA_EMPTY; context->is_connect_end[0][0] = false; resetStringInfo(context->messages[0][0]); + // 閲嶇疆鍏变韩鍏冪粍鐨勬寚閽 context->sharedTuples[0][0]->tuplePointer = 0; } +// 鑾峰彇閫掑綊鑱斿悎瀛愯鍒 static RecursiveUnion* GetRecursiveUnionSubPlan(PlannedStmt* pstmt, int subplanid) { ListCell* lc = NULL; + // 閬嶅巻璁″垝涓殑瀛愯鍒掑垪琛 foreach (lc, pstmt->subplans) { Plan* p = (Plan*)lfirst(lc); + // 濡傛灉鎵惧埌鍖归厤鐨勯掑綊鑱斿悎瀛愯鍒掞紝鍒欒繑鍥炶璁″垝 if (IsA(p, RecursiveUnion) && p->plan_node_id == subplanid) { return (RecursiveUnion*)p; } } - return NULL; + return NULL; // 濡傛灉鏈壘鍒板尮閰嶇殑閫掑綊鑱斿悎瀛愯鍒掞紝鍒欒繑鍥濶ULL } /* - * get one tuple for stream with merge sort + * 鑾峰緱涓涓厓缁勬祦涓庡綊骞舵帓搴 */ bool StreamMergeSortGetTuple(StreamState* node) { @@ -441,25 +467,34 @@ bool StreamMergeSortGetTuple(StreamState* node) } /* - * init stream with merge sort + * 鐢ㄥ綊骞舵帓搴忓垵濮嬪寲娴 */ void InitStreamMergeSort(StreamState* node) { + // 鏂█锛歋treamScan蹇呴』鏄疭canStreamByLibcomm Assert(node->StreamScan == ScanStreamByLibcomm); + // 鏂█锛歴ortstate蹇呴』涓虹┖ Assert(node->sortstate == NULL); + // 鑾峰彇鎵弿鐨凾upleTableSlot TupleTableSlot* scanslot = node->ss.ps.ps_ResultTupleSlot; + // 鑾峰彇Stream鑺傜偣涓殑鎺掑簭淇℃伅 SimpleSort* sort = ((Stream*)(node->ss.ps.plan))->sort; + // 鏂█锛氭帓搴忎笉搴旇鍐欏叆瀛樺偍 Assert(sort->sortToStore == false); + // 濡傛灉闇瑕佽幏鍙栨柊鐨勬暟鎹 if (node->need_fresh_data) { + // 浠庨昏緫杩炴帴涓婅鍙栨暟鎹 if (datanode_receive_from_logic_conn(node->conn_count, node->connections, &node->netctl, -1)) { int error_code = getStreamSocketError(gs_comm_strerror()); + // 鎶ラ敊锛氭棤娉曚粠Datanodes璇诲彇鍝嶅簲 ereport(ERROR, (errcode(error_code), errmsg("Failed to read response from Datanodes. Detail: %s\n", gs_comm_strerror()))); } } + // 鍒濆鍖栨帓搴忕姸鎬 node->sortstate = tuplesort_begin_merge(scanslot->tts_tupleDescriptor, sort->numCols, sort->sortColIdx, @@ -469,6 +504,7 @@ void InitStreamMergeSort(StreamState* node) node, u_sess->attr.attr_memory.work_mem); + // 璁剧疆StreamScan鐨勫鐞嗗嚱鏁颁负StreamMergeSortGetTuple node->StreamScan = StreamMergeSortGetTuple; } @@ -486,8 +522,9 @@ static void CheckStreamMatchInfo( StreamFlowCheckInfo checkInfo, int plan_node_id, List* consumerExecNode, int consumerDop, bool isLocalStream) { #ifdef ENABLE_MULTIPLE_NODES - /* 1.Check exec_nodes. */ + /* 1. 妫鏌ユ墽琛岃妭鐐广 */ if (checkInfo.parentProducerExecNodeList == NIL) { + // 鎶ラ敊锛歋tream鑺傜偣鐨勬墽琛岃妭鐐瑰垪琛ㄤ笉搴斾负绌 ereport(ERROR, (errcode(ERRCODE_OPERATE_INVALID_PARAM), errmsg("Stream plan check failed. Execution datanodes list of stream node[%d] should never be null.", @@ -495,11 +532,11 @@ static void CheckStreamMatchInfo( } /* - * For local stream node we do not check the exec nodes cause consumer nodes - * will be modified forcibly or will be marked as dummy thread, so just skipping. + * 瀵逛簬鏈湴Stream鑺傜偣锛屾垜浠笉妫鏌ユ墽琛岃妭鐐癸紝鍥犱负娑堣垂鑰呰妭鐐瑰皢琚己鍒朵慨鏀规垨鏍囪涓鸿櫄鎷熺嚎绋嬶紝鎵浠ュ彲浠ヨ烦杩囨鏌ャ */ if (!isLocalStream) { if (list_length(checkInfo.parentProducerExecNodeList) != list_length(consumerExecNode)) + // 鎶ラ敊锛歋tream鑺傜偣鐨勬墽琛岃妭鐐瑰垪琛ㄩ暱搴︿笉鍖归厤 ereport(ERROR, (errcode(ERRCODE_OPERATE_INVALID_PARAM), errmsg("Stream plan check failed. Execution datanodes list of stream node[%d] mismatch in parent " @@ -509,12 +546,14 @@ static void CheckStreamMatchInfo( errhint("Please use EXPLAIN VERBOSE command to see more details."))); else { + // 妫鏌ユ墽琛岃妭鐐圭殑宸紓 List* l_diff1 = list_difference_int(checkInfo.parentProducerExecNodeList, consumerExecNode); List* l_diff2 = list_difference_int(consumerExecNode, checkInfo.parentProducerExecNodeList); if (l_diff1 != NIL || l_diff2 != NIL) { list_free(l_diff1); list_free(l_diff2); + // 鎶ラ敊锛歋tream鑺傜偣鐨勬墽琛岃妭鐐瑰垪琛ㄤ笉鍖归厤 ereport(ERROR, (errcode(ERRCODE_OPERATE_INVALID_PARAM), errmsg("Stream plan check failed. Execution datanodes list of stream node[%d] mismatch in " @@ -526,8 +565,9 @@ static void CheckStreamMatchInfo( } } #endif - /* 2.Check dop. */ + /* 2. 妫鏌OP銆 */ if (SET_DOP(checkInfo.parentProducerDop) != SET_DOP(consumerDop)) + // 鎶ラ敊锛歋tream鑺傜偣鐨凞OP锛堝苟琛屽害锛変笉鍖归厤 ereport(ERROR, (errcode(ERRCODE_OPERATE_INVALID_PARAM), errmsg("Stream plan check failed. Query dop of stream node %d [dop: %d] mismatch in parent node %d " @@ -558,21 +598,23 @@ static void InitStream(StreamFlowCtl* ctl, StreamTransType transType) PlannedStmt* pstmt = ctl->pstmt; Plan* plan = ctl->plan; Stream* streamNode = (Stream*)ctl->plan; - /* May split to mutiliple consumer/producer list, m:n model. */ + /* 鍙兘浼氬垎鎴愬涓秷璐硅/鐢熶骇鑰呭垪琛紝閲囩敤m:n妯″瀷銆*/ List* consumerSMPList = NULL; List* producerSMPList = NULL; bool isLocalStream = STREAM_IS_LOCAL_NODE(streamNode->smpDesc.distriType); - /* MPP with-recursive support */ + /* MPP with-recursive 鏀寔 */ bool startall = false; List* consumer_nodeList = NIL; List* producer_nodeList = NIL; #ifndef ENABLE_MULTIPLE_NODES if (!isLocalStream) { + // 鎶ラ敊锛氬崟鑺傜偣鍙兘鏈夋湰鍦版祦鎿嶄綔绗 ereport(ERROR, (errmsg("Single Node should only has local stream operator."))); } #endif + // 鏋勫缓鏈湴娴佸叡浜笂涓嬫枃 StreamSharedContext* sharedContext = NULL; sharedContext = buildLocalStreamContext(streamNode, pstmt); @@ -580,14 +622,15 @@ static void InitStream(StreamFlowCtl* ctl, StreamTransType transType) key.planNodeId = plan->plan_node_id; /* - * MPPDB with-recursive support + * MPPDB with-recursive 鏀寔 */ bool isRecursive = EXEC_IN_RECURSIVE_MODE(plan) && !streamNode->is_recursive_local; if (isRecursive) { - /* If we are under recursive-union, we need check if P/C is not a N-N case */ + /* 濡傛灉鎴戜滑澶勪簬閫掑綊鑱旀帴涓嬶紝闇瑕佹鏌/C鏄惁涓嶆槸N-N鎯呭喌 */ Plan* producer_topplan = plan->lefttree; RecursiveUnion* ruplan = GetRecursiveUnionSubPlan(pstmt, plan->recursive_union_plan_nodeid); if (ruplan == NULL) { + // 鎶ラ敊锛歳uplan涓嶈兘涓虹┖ ereport(ERROR, (errcode(ERRCODE_OPERATE_INVALID_PARAM), errmsg("The ruplan is can not be NULL"))); } List* cteplan_nodeList = ruplan->plan.exec_nodes->nodeList; @@ -595,21 +638,17 @@ static void InitStream(StreamFlowCtl* ctl, StreamTransType transType) producer_nodeList = producer_topplan->exec_nodes->nodeList; /* - * Check if the consumer & top-producer's exec nodes is identical with - * Recursive CTE plan's nodes + * 妫鏌ユ秷璐硅呭拰椤堕儴鐢熶骇鑰呯殑鎵ц鑺傜偣鏄惁涓庨掑綊CTE璁″垝鐨勮妭鐐圭浉鍚 */ bool isEqcalConsumerAndProducer = (!equal(cteplan_nodeList, consumer_nodeList) || !equal(cteplan_nodeList, producer_nodeList)); if (isEqcalConsumerAndProducer) { - /* mark we need start all */ + /* 鏍囪闇瑕佸惎鍔ㄦ墍鏈 */ startall = true; /* - * Reset consumer and producer list, and save the original consumer_nodes - * with the plan node - * - * Note, only update the node part the other property of ExecNodes keeps - * original + * 閲嶇疆娑堣垂鑰呭拰鐢熶骇鑰呭垪琛紝骞朵繚瀛樺師濮嬬殑consumer_nodes + * 鍒楄〃鑺傜偣閮ㄥ垎鐨勫叾浠栧睘鎬т繚鎸佸師鏍 */ Assert(streamNode->origin_consumer_nodes == NULL); streamNode->origin_consumer_nodes = (ExecNodes*)copyObject(streamNode->consumer_nodes); @@ -620,183 +659,183 @@ static void InitStream(StreamFlowCtl* ctl, StreamTransType transType) plan->exec_nodes->nodeList = cteplan_nodeList; } } +} /* - * In order to print plan when the 'hang' plan occur, we do check here. - * (1) Check if current consumer nodes match parent producer exec nodes. - * (2) Check dop either. - * (3) For local stream node we do not check the exec nodes cause consumer nodes - * will be modified forcibly or will be marked as dummy thread, so just skipping. - * (4) For top node of plan tree, whether need to check consumer_nodes when it is stream node, - * there are two cases: - * 1)case one: for R8C10 we do not need to check because R8 has modified the judgment - * method of dummy thread to deal with this kind of 'hang' plan. - * 2)case two: for R7C10 we still need check to avoid hang up. - * Finally, report error when they mismatch. - * - * In case of startAll, we may make a top-plan node in current producer thread to - * full nodeList to avoid incorrect reporting 'Stream plan check failed', so just skip it + * 涓轰簡鍦'hang'璁″垝鍙戠敓鏃舵墦鍗拌鍒掞紝鎴戜滑鍦ㄨ繖閲屾鏌ャ + *(1)妫鏌ュ綋鍓嶆秷璐硅呰妭鐐规槸鍚︿笌鐖剁敓浜ц呮墽琛岃妭鐐瑰尮閰嶃 + *(2)妫鏌op銆 + *(3)瀵逛簬鏈湴娴佽妭鐐癸紝鎴戜滑涓嶆鏌ユ墽琛岃妭鐐瑰鑷存秷璐硅呰妭鐐 + *灏嗚寮哄埗淇敼鎴栬鏍囪涓鸿櫄鎷熺嚎绋嬶紝鎵浠ュ彧鏄烦杩囥 + *(4)瀵逛簬璁″垝鏍戠殑椤剁鑺傜偣锛屽綋瀹冩槸娴佽妭鐐规椂鏄惁闇瑕佹鏌onsumer_nodes; + *鏈変袱绉嶆儏鍐: + * 1)鎯呭舰涓:瀵逛簬R8C10鎴戜滑涓嶉渶瑕佹鏌ワ紝鍥犱负R8宸茬粡淇敼浜嗗垽鏂 + *铏氭嫙绾跨▼鐨勬柟娉曟潵澶勭悊杩欑鈥滄寕璧封濊鍒掋 + 鎯呭舰浜:瀵逛簬R7C10锛屾垜浠粛鐒堕渶瑕佹鏌ヤ互閬垮厤鎸傛満銆 + *鏈鍚庯紝褰撳畠浠笉鍖归厤鏃舵姤鍛婇敊璇 + *鍦╯tartAll鐨勬儏鍐典笅锛屾垜浠彲浠ュ湪褰撳墠鐨勭敓浜ц呯嚎绋嬩腑鍒涘缓涓涓猼op-plan鑺傜偣 + *瀹屾暣鐨刵odeList锛屼互閬垮厤閿欒鐨勬姤鍛'娴佽鍒掓鏌ュけ璐'锛屾墍浠ュ彧鏄烦杩囧畠 */ bool isTopStreamNode = ((IsA(ctl->pstmt->planTree, Stream) || IsA(ctl->pstmt->planTree, VecStream)) && - ctl->pstmt->planTree->plan_node_id == ctl->plan->plan_node_id) - ? true : false; - if (!isTopStreamNode && !startall) { - CheckStreamMatchInfo(ctl->checkInfo, - plan->plan_node_id, - streamNode->consumer_nodes->nodeList, - streamNode->smpDesc.consumerDop, - isLocalStream); - } + ctl->pstmt->planTree->plan_node_id == ctl->plan->plan_node_id) + ? true : false; +if (!isTopStreamNode && !startall) { + // 妫鏌tream鑺傜偣鐨勫尮閰嶄俊鎭 + CheckStreamMatchInfo(ctl->checkInfo, + plan->plan_node_id, + streamNode->consumer_nodes->nodeList, + streamNode->smpDesc.consumerDop, + isLocalStream); +} - /* Backup checkinfo (for current stream thread layer) and save checkInfo for the next node */ - List* saved_parentProducerExecNodeList = ctl->checkInfo.parentProducerExecNodeList; - int saved_parentProducerDop = streamNode->smpDesc.producerDop; - ctl->checkInfo.parentProducerExecNodeList = plan->exec_nodes->nodeList; - ctl->checkInfo.parentProducerDop = streamNode->smpDesc.producerDop; +// 澶囦唤checkinfo锛堢敤浜庡綋鍓峉tream绾跨▼灞傦級骞朵繚瀛樹笅涓涓妭鐐圭殑checkInfo +List* saved_parentProducerExecNodeList = ctl->checkInfo.parentProducerExecNodeList; +int saved_parentProducerDop = streamNode->smpDesc.producerDop; +ctl->checkInfo.parentProducerExecNodeList = plan->exec_nodes->nodeList; +ctl->checkInfo.parentProducerDop = streamNode->smpDesc.producerDop; - execNodes = plan->exec_nodes->nodeList; +execNodes = plan->exec_nodes->nodeList; #ifdef ENABLE_MULTIPLE_NODES - /* - * If local stream node, the execnode is the same of current PGXCNode, - * which is also the same of consumer_nodes. And we need to check if this - * data node is a real execute node, or we will add local stream on dummy node. - */ - if (STREAM_IS_LOCAL_NODE(streamNode->smpDesc.distriType) && - list_member_int(execNodes, u_sess->pgxc_cxt.PGXCNodeId)) { - execNodes = lappend_int(NIL, u_sess->pgxc_cxt.PGXCNodeId); - streamNode->consumer_nodes->nodeList = execNodes; - } +/* + * 濡傛灉鏄湰鍦癝tream鑺傜偣锛屽垯鎵ц鑺傜偣涓庡綋鍓峆GXCNode鐩稿悓锛 + * 杩欎篃涓巆onsumer_nodes鐩稿悓銆傛垜浠渶瑕佹鏌ユ鏁版嵁鑺傜偣鏄惁涓哄疄闄呮墽琛岃妭鐐癸紝 + * 鍚﹀垯灏嗗湪铏氭嫙鑺傜偣涓婃坊鍔犳湰鍦版祦銆 + */ +if (STREAM_IS_LOCAL_NODE(streamNode->smpDesc.distriType) && + list_member_int(execNodes, u_sess->pgxc_cxt.PGXCNodeId)) { + execNodes = lappend_int(NIL, u_sess->pgxc_cxt.PGXCNodeId); + streamNode->consumer_nodes->nodeList = execNodes; +} - Assert(execNodes != NULL); - Assert(list_length(execNodes) > 0); - Assert(streamNode->consumer_nodes->nodeList != NULL); - Assert(list_length(streamNode->consumer_nodes->nodeList) > 0); - Assert(plan->righttree == NULL); +Assert(execNodes != NULL); +Assert(list_length(execNodes) > 0); +Assert(streamNode->consumer_nodes->nodeList != NULL); +Assert(list_length(streamNode->consumer_nodes->nodeList) > 0); +Assert(plan->righttree == NULL); #endif - /* 1. Start the setup the Consumer part */ - if (ctl->dummyThread == false) { - /* Initialize the consumer object. */ - for (i = 0; i < streamNode->smpDesc.consumerDop; i++) { - consumer = New(u_sess->stream_cxt.stream_runtime_mem_cxt) StreamConsumer( - u_sess->stream_cxt.stream_runtime_mem_cxt); - /* Set smp identifier. */ - key.smpIdentifier = i; - consumer->init(key, execNodes, streamNode->smpDesc, transType, sharedContext); +/* 1. 寮濮嬭缃秷璐硅呴儴鍒 */ +if (ctl->dummyThread == false) { + /* 鍒濆鍖栨秷璐硅呭璞° */ + for (i = 0; i < streamNode->smpDesc.consumerDop; i++) { + consumer = New(u_sess->stream_cxt.stream_runtime_mem_cxt) StreamConsumer( + u_sess->stream_cxt.stream_runtime_mem_cxt); - consumerSMPList = lappend(consumerSMPList, consumer); - *(ctl->allConsumerList) = lappend(*(ctl->allConsumerList), consumer); - *(ctl->subConsumerList) = lappend(*(ctl->subConsumerList), consumer); + /* 璁剧疆smp鏍囪瘑绗︺ */ + key.smpIdentifier = i; + consumer->init(key, execNodes, streamNode->smpDesc, transType, sharedContext); - /* store its original producer node list */ - if (startall) { - consumer->m_originProducerNodeList = producer_nodeList; - } + consumerSMPList = lappend(consumerSMPList, consumer); + *(ctl->allConsumerList) = lappend(*(ctl->allConsumerList), consumer); + *(ctl->subConsumerList) = lappend(*(ctl->subConsumerList), consumer); + + /* 瀛樺偍鍏跺師濮嬬敓浜ц呰妭鐐瑰垪琛 */ + if (startall) { + consumer->m_originProducerNodeList = producer_nodeList; } } +} - /* 2. Start the setup the Producer part */ - consumerNum = list_length(streamNode->consumer_nodes->nodeList); +/* 2. 寮濮嬭缃敓浜ц呴儴鍒 */ +consumerNum = list_length(streamNode->consumer_nodes->nodeList); - /* Set connection number of producer. */ - if (STREAM_IS_LOCAL_NODE(streamNode->smpDesc.distriType)) - producerConnNum = streamNode->smpDesc.consumerDop; - else - producerConnNum = consumerNum * streamNode->smpDesc.consumerDop; +/* 璁剧疆鐢熶骇鑰呯殑杩炴帴鏁般 */ +if (STREAM_IS_LOCAL_NODE(streamNode->smpDesc.distriType)) + producerConnNum = streamNode->smpDesc.consumerDop; +else + producerConnNum = consumerNum * streamNode->smpDesc.consumerDop; - /* - * Check with lefttree is OK, because exec_nodes is the same as current Stream node. - * If lefttree is Steam, exec_nodes of current Stream node is the same as consumer_nodes - * of Stream node in lefttree. - * In addition, ThreadIsDummy routine has dealt with the case that lefttree is also a stream node. - */ - streamNode->is_dummy = ThreadIsDummy(plan->lefttree); +/* + * 閫氳繃宸︽爲妫鏌ユ槸鍚K锛屽洜涓篹xec_nodes涓庡綋鍓峉tream鑺傜偣鐩稿悓銆 + * 濡傛灉宸︽爲鏄疭team锛屽垯褰撳墠Stream鑺傜偣鐨別xec_nodes涓庡乏鏍戜腑鐨凷tream鑺傜偣鐨刢onsumer_nodes鐩稿悓銆 + * 姝ゅ锛孴hreadIsDummy渚嬬▼宸茬粡澶勭悊浜嗗乏鏍戜篃鏄竴涓猻tream鑺傜偣鐨勬儏鍐点 + */ +streamNode->is_dummy = ThreadIsDummy(plan->lefttree); - /* If not dummy, we need to establish the connection. */ - if (streamNode->is_dummy == false) { - for (i = 0; i < streamNode->smpDesc.producerDop; i++) { - /* Set smp identifier. */ - key.smpIdentifier = i; - producer = New(u_sess->stream_cxt.stream_runtime_mem_cxt) StreamProducer( - key, pstmt, streamNode, u_sess->stream_cxt.stream_runtime_mem_cxt, producerConnNum, transType); - producer->setSharedContext(sharedContext); - producer->setUniqueSQLKey(u_sess->unique_sql_cxt.unique_sql_id, - u_sess->unique_sql_cxt.unique_sql_user_id, u_sess->unique_sql_cxt.unique_sql_cn_id); - producer->setGlobalSessionId(&u_sess->globalSessionId); - producerSMPList = lappend(producerSMPList, producer); - - /* Add all producer to node group to avoid possible consumer-not-deinit */ - *(ctl->allProducerList) = lappend(*(ctl->allProducerList), producer); - *(ctl->subProducerList) = lappend(*(ctl->subProducerList), producer); - - if (startall) { - /* Store the origin list */ - producer->m_originConsumerNodeList = consumer_nodeList; - producer->m_originProducerExecNodeList = producer_nodeList; - } - } - } else { - key.smpIdentifier = 0; - producer = New(u_sess->stream_cxt.stream_runtime_mem_cxt) - StreamProducer(key, pstmt, streamNode, u_sess->stream_cxt.stream_runtime_mem_cxt, consumerNum, transType); +/* 濡傛灉涓嶆槸铏氭嫙鑺傜偣锛屾垜浠渶瑕佸缓绔嬭繛鎺ャ */ +if (streamNode->is_dummy == false) { + for (i = 0; i < streamNode->smpDesc.producerDop; i++) { + /* 璁剧疆smp鏍囪瘑绗︺ */ + key.smpIdentifier = i; + producer = New(u_sess->stream_cxt.stream_runtime_mem_cxt) StreamProducer( + key, pstmt, streamNode, u_sess->stream_cxt.stream_runtime_mem_cxt, producerConnNum, transType); + producer->setSharedContext(sharedContext); producer->setUniqueSQLKey(u_sess->unique_sql_cxt.unique_sql_id, - u_sess->unique_sql_cxt.unique_sql_user_id, u_sess->unique_sql_cxt.unique_sql_cn_id); + u_sess->unique_sql_cxt.unique_sql_user_id, u_sess->unique_sql_cxt.unique_sql_cn_id); producer->setGlobalSessionId(&u_sess->globalSessionId); producerSMPList = lappend(producerSMPList, producer); - } - StreamPair* pair = u_sess->stream_cxt.global_obj->pushStreamPair(key, producerSMPList, consumerSMPList); + /* 娣诲姞鎵鏈夌敓浜ц呬互閬垮厤鍙兘鐨勬秷璐硅呮湭閲婃斁 */ + *(ctl->allProducerList) = lappend(*(ctl->allProducerList), producer); + *(ctl->subProducerList) = lappend(*(ctl->subProducerList), producer); - Assert(pair != NULL); - List* producerList = NULL; - List* consumerList = NULL; - int subInnerThreadNum = 0; /* Number of stream nodes below current stream nodes. */ - - /* Traverse left tree. */ - StreamFlowCtl lctl = *ctl; - lctl.plan = plan->lefttree; - lctl.dummyThread = streamNode->is_dummy; - lctl.subProducerList = &producerList; - lctl.subConsumerList = &consumerList; - lctl.threadNum = &subInnerThreadNum; - /* checkInfo should be passed down. */ - InitStreamFlow(&lctl); - - /* Sub plan in the left tree, also the sub plan. */ - ListCell* l1 = NULL; - ListCell* l2 = NULL; - forboth(l1, pstmt->subplans, l2, pstmt->subplan_ids) - { - if (plan->lefttree->plan_node_id == lfirst_int(l2)) { - lctl.plan = (Plan*)lfirst(l1); - /* Set parent info as checkInfo for every init plan. */ - SetCheckInfo(&lctl.checkInfo, plan->lefttree); - InitStreamFlow(&lctl); + if (startall) { + /* 瀛樺偍鍘熷鍒楄〃 */ + producer->m_originConsumerNodeList = consumer_nodeList; + producer->m_originProducerExecNodeList = producer_nodeList; } } +} else { + key.smpIdentifier = 0; + producer = New(u_sess->stream_cxt.stream_runtime_mem_cxt) + StreamProducer(key, pstmt, streamNode, u_sess->stream_cxt.stream_runtime_mem_cxt, consumerNum, transType); + producer->setUniqueSQLKey(u_sess->unique_sql_cxt.unique_sql_id, + u_sess->unique_sql_cxt.unique_sql_user_id, u_sess->unique_sql_cxt.unique_sql_cn_id); + producer->setGlobalSessionId(&u_sess->globalSessionId); + producerSMPList = lappend(producerSMPList, producer); +} - *(ctl->threadNum) += subInnerThreadNum + streamNode->smpDesc.producerDop; - pair->expectThreadNum = subInnerThreadNum; +StreamPair* pair = u_sess->stream_cxt.global_obj->pushStreamPair(key, producerSMPList, consumerSMPList); - /* Set some args. */ - ListCell* cell = NULL; - foreach (cell, producerSMPList) { - producer = (StreamProducer*)lfirst(cell); +Assert(pair != NULL); +List* producerList = NULL; +List* consumerList = NULL; +int subInnerThreadNum = 0; /* 鍦ㄥ綋鍓峉tream鑺傜偣涓嬮潰鐨凷tream鑺傜偣鏁伴噺銆 */ - producer->setPair(pair); - producer->setSubProducerList(producerList); - producer->setSubConsumerList(consumerList); - producer->setSessionMemory(t_thrd.shemem_ptr_cxt.mySessionMemoryEntry); +/* 閬嶅巻宸︽爲銆 */ +StreamFlowCtl lctl = *ctl; +lctl.plan = plan->lefttree; +lctl.dummyThread = streamNode->is_dummy; +lctl.subProducerList = &producerList; +lctl.subConsumerList = &consumerList; +lctl.threadNum = &subInnerThreadNum; +/* checkInfo搴旇琚紶閫掍笅鏉ャ */ +InitStreamFlow(&lctl); + +/* 宸︽爲涓殑瀛愯鍒掞紝涔熸槸瀛愯鍒掋 */ +ListCell* l1 = NULL; +ListCell* l2 = NULL; +forboth (l1, pstmt->subplans, l2, pstmt->subplan_ids) { + if (plan->lefttree->plan_node_id == lfirst_int(l2)) { + lctl.plan = (Plan*)lfirst(l1); + /* 灏嗙埗鑺傜偣淇℃伅浣滀负姣忎釜init璁″垝鐨刢heckInfo銆 */ + SetCheckInfo(&lctl.checkInfo, plan->lefttree); + InitStreamFlow(&lctl); } +} - *(ctl->subProducerList) = list_union_ptr(*(ctl->subProducerList), producerList); +*(ctl->threadNum) += subInnerThreadNum + streamNode->smpDesc.producerDop; +pair->expectThreadNum = subInnerThreadNum; - /* - * After init the underlying stream workflow, we need restore parentProducerDop - * and parentProducerExecNodeList in current stream thread level - */ - ctl->checkInfo.parentProducerExecNodeList = saved_parentProducerExecNodeList; - ctl->checkInfo.parentProducerDop = saved_parentProducerDop; +/* 璁剧疆涓浜涘弬鏁般 */ +ListCell* cell = NULL; +foreach (cell, producerSMPList) { + producer = (StreamProducer*)lfirst(cell); + + producer->setPair(pair); + producer->setSubProducerList(producerList); + producer->setSubConsumerList(consumerList); + producer->setSessionMemory(t_thrd.shemem_ptr_cxt.mySessionMemoryEntry); +} + +*(ctl->subProducerList) = list_union_ptr(*(ctl->subProducerList), producerList); + +/* + * 鍒濆鍖栧簳灞傛祦宸ヤ綔娴佷箣鍚庯紝鎴戜滑闇瑕佹仮澶嶅綋鍓峉tream绾跨▼灞備腑鐨刾arentProducerDop + * 鍜宲arentProducerExecNodeList + */ +ctl->checkInfo.parentProducerExecNodeList = saved_parentProducerExecNodeList; +ctl->checkInfo.parentProducerDop = saved_parentProducerDop; } /* @@ -818,7 +857,7 @@ static void InitStreamFlow(StreamFlowCtl* ctl) foreach (lc, append->appendplans) { Plan* subplan = (Plan*)lfirst(lc); ctl->plan = subplan; - /* Set parent info as checkInfo for every sub plan. */ + /* 璁剧疆鐖惰妭鐐逛俊鎭负姣忎釜瀛愯鍒掔殑checkInfo銆 */ SetCheckInfo(&ctl->checkInfo, oldPlan); InitStreamFlow(ctl); } @@ -830,7 +869,7 @@ static void InitStreamFlow(StreamFlowCtl* ctl) foreach (lc, mt->plans) { Plan* subplan = (Plan*)lfirst(lc); ctl->plan = subplan; - /* Set parent info as checkInfo for every sub plan. */ + /* 璁剧疆鐖惰妭鐐逛俊鎭负姣忎釜瀛愯鍒掔殑checkInfo銆 */ SetCheckInfo(&ctl->checkInfo, oldPlan); InitStreamFlow(ctl); } @@ -840,7 +879,7 @@ static void InitStreamFlow(StreamFlowCtl* ctl) SubqueryScan* ss = (SubqueryScan*)oldPlan; if (ss->subplan) { ctl->plan = ss->subplan; - /* Set parent info as checkInfo for every sub plan. */ + /* 璁剧疆鐖惰妭鐐逛俊鎭负姣忎釜瀛愯鍒掔殑checkInfo銆 */ SetCheckInfo(&ctl->checkInfo, oldPlan); InitStreamFlow(ctl); } @@ -851,7 +890,7 @@ static void InitStreamFlow(StreamFlowCtl* ctl) foreach (lc, ma->mergeplans) { Plan* subplan = (Plan*)lfirst(lc); ctl->plan = subplan; - /* Set parent info as checkInfo for every sub plan. */ + /* 璁剧疆鐖惰妭鐐逛俊鎭负姣忎釜瀛愯鍒掔殑checkInfo銆 */ SetCheckInfo(&ctl->checkInfo, oldPlan); InitStreamFlow(ctl); } @@ -863,7 +902,7 @@ static void InitStreamFlow(StreamFlowCtl* ctl) foreach (lc, ba->bitmapplans) { Plan* subplan = (Plan*)lfirst(lc); ctl->plan = subplan; - /* Set parent info as checkInfo for every sub plan. */ + /* 璁剧疆鐖惰妭鐐逛俊鎭负姣忎釜瀛愯鍒掔殑checkInfo銆 */ SetCheckInfo(&ctl->checkInfo, oldPlan); InitStreamFlow(ctl); } @@ -875,7 +914,7 @@ static void InitStreamFlow(StreamFlowCtl* ctl) foreach (lc, bo->bitmapplans) { Plan* subplan = (Plan*)lfirst(lc); ctl->plan = subplan; - /* Set parent info as checkInfo for every sub plan. */ + /* 璁剧疆鐖惰妭鐐逛俊鎭负姣忎釜瀛愯鍒掔殑checkInfo銆 */ SetCheckInfo(&ctl->checkInfo, oldPlan); InitStreamFlow(ctl); } @@ -884,13 +923,13 @@ static void InitStreamFlow(StreamFlowCtl* ctl) case T_VecStream: { InitStream(ctl, STREAM_COMM); - /* Create stream controller for current stream node */ + /* 涓哄綋鍓嶆祦鑺傜偣鍒涘缓娴佹帶鍒跺櫒 */ if (NeedSetupSyncUpController(oldPlan)) { ExecSyncControllerCreate(oldPlan); } } break; case T_RecursiveUnion: { - /* Create recursive-controller for current recursive-union node */ + /* 涓哄綋鍓嶉掑綊鑱旀帴鑺傜偣鍒涘缓閫掑綊鎺у埗鍣 */ if (NeedSetupSyncUpController(oldPlan)) { ExecSyncControllerCreate(oldPlan); } @@ -898,7 +937,7 @@ static void InitStreamFlow(StreamFlowCtl* ctl) ctl->plan = oldPlan->lefttree; InitStreamFlow(ctl); - /* Before traverse the right tree, we must reset the checkInfo. */ + /* 鍦ㄩ亶鍘嗗彸鏍戜箣鍓嶏紝鎴戜滑蹇呴』閲嶇疆checkInfo銆 */ ctl->checkInfo = oldCheckInfo; ctl->plan = oldPlan->righttree; InitStreamFlow(ctl); @@ -929,14 +968,14 @@ static void InitStreamFlow(StreamFlowCtl* ctl) */ void DeinitStreamContext() { - /* Reset the stream runtime context now for next query. */ + /* 鐜板湪閲嶇疆娴佽繍琛屾椂涓婁笅鏂囷紝浠ヤ究浜庝笅娆℃煡璇€ */ if (u_sess->stream_cxt.stream_runtime_mem_cxt != NULL) { MemoryContextDelete(u_sess->stream_cxt.stream_runtime_mem_cxt); u_sess->stream_cxt.stream_runtime_mem_cxt = NULL; } if (IS_PGXC_DATANODE) { - /* Reset the shared memory context now for next query. */ + /* 鐜板湪閲嶇疆鍏变韩鍐呭瓨涓婁笅鏂囷紝浠ヤ究浜庝笅娆℃煡璇€ */ if (u_sess->stream_cxt.data_exchange_mem_cxt != NULL) { MemoryContextDelete(u_sess->stream_cxt.data_exchange_mem_cxt); u_sess->stream_cxt.data_exchange_mem_cxt = NULL; @@ -954,9 +993,11 @@ void InitStreamContext() char context_name[NAMEDATALEN] = {0}; errno_t rc = EOK; - /* Append tid to identify each openGauss thread. */ + /* 鍦ㄤ笂涓嬫枃鍚嶇О涓檮鍔犵嚎绋嬫爣璇嗕互鏍囪瘑姣忎釜OpenGauss绾跨▼銆 */ rc = snprintf_s(context_name, NAMEDATALEN, NAMEDATALEN - 1, "StreamRuntimeContext__%lu", u_sess->debug_query_id); securec_check_ss(rc, "\0", "\0"); + + /* 鍒涘缓娴佽繍琛屾椂鍐呭瓨涓婁笅鏂囥*/ u_sess->stream_cxt.stream_runtime_mem_cxt = AllocSetContextCreate(g_instance.instance_context, context_name, ALLOCSET_DEFAULT_MINSIZE, @@ -965,10 +1006,12 @@ void InitStreamContext() SHARED_CONTEXT); if (IS_PGXC_DATANODE) { - /* Append tid to identify each openGauss thread. */ + /* 濡傛灉褰撳墠浼氳瘽鏄疨GXC鏁版嵁鑺傜偣锛堝嵆鍒嗗竷寮忔暟鎹簱鐨勬暟鎹妭鐐癸級锛屽垯鍒涘缓鏁版嵁浜ゆ崲鍐呭瓨涓婁笅鏂囥*/ rc = snprintf_s( context_name, NAMEDATALEN, NAMEDATALEN - 1, "MemoryDataExchangeContext_%lu", u_sess->debug_query_id); securec_check_ss(rc, "\0", "\0"); + + /* 鍒涘缓鏁版嵁浜ゆ崲鍐呭瓨涓婁笅鏂囥*/ u_sess->stream_cxt.data_exchange_mem_cxt = AllocSetContextCreate(g_instance.instance_context, context_name, ALLOCSET_DEFAULT_MINSIZE, @@ -986,6 +1029,7 @@ void InitStreamContext() */ void BuildStreamFlow(PlannedStmt* plan) { + /* 鐢ㄤ簬淇濆瓨娑堣垂鑰呭拰鐢熶骇鑰呯殑鍒楄〃 */ List* consumerList = NIL; List* producerList = NIL; List* subProducerList = NIL; @@ -994,17 +1038,23 @@ void BuildStreamFlow(PlannedStmt* plan) StreamConsumer* consumer = NULL; StreamProducer* producer = NULL; + /* 妫鏌ヨ鍒掍腑鏄惁瀛樺湪娴佹搷浣滐紝骞朵笖鍏ㄥ眬娴佸璞″皻鏈垵濮嬪寲 */ if (plan->num_streams > 0 && u_sess->stream_cxt.global_obj == NULL) { + /* 鍒囨崲鍒版祦杩愯鏃跺唴瀛樹笂涓嬫枃 */ AutoContextSwitch streamCxtGuard(u_sess->stream_cxt.stream_runtime_mem_cxt); + + /* 鐢ㄤ簬璁$畻绾跨▼鏁伴噺鐨勫彉閲 */ int threadNum = 0; List* topConsumerList = NULL; - /* Hold interrupts during stream connection and thread initialization. */ + /* 鍦ㄦ祦杩炴帴鍜岀嚎绋嬪垵濮嬪寲鏈熼棿淇濇寔涓柇 */ HOLD_INTERRUPTS(); + /* 鍒涘缓鍏ㄥ眬娴佸璞 */ u_sess->stream_cxt.global_obj = New(u_sess->stream_cxt.stream_runtime_mem_cxt) StreamNodeGroup(); u_sess->stream_cxt.global_obj->m_streamRuntimeContext = u_sess->stream_cxt.stream_runtime_mem_cxt; + /* 鍒濆鍖栨祦鎿嶄綔鎺у埗鍙橀噺 */ StreamFlowCtl ctl; ctl.pstmt = plan; ctl.plan = plan->planTree; @@ -1014,58 +1064,62 @@ void BuildStreamFlow(PlannedStmt* plan) ctl.subConsumerList = &topConsumerList; ctl.threadNum = &threadNum; ctl.dummyThread = ThreadIsDummy(plan->planTree); - /* Init check info. */ + + /* 鍒濆鍖栨鏌ヤ俊鎭 */ SetCheckInfo(&ctl.checkInfo, plan->planTree); + /* 鍒濆鍖栨祦鎿嶄綔 */ InitStreamFlow(&ctl); + /* 鍒濆鍖栧瓙璁″垝涓殑娴佹搷浣 */ ListCell* l1 = NULL; ListCell* l2 = NULL; forboth(l1, plan->subplans, l2, plan->subplan_ids) { if (plan->planTree->plan_node_id == lfirst_int(l2)) { ctl.plan = (Plan*)lfirst(l1); - /* Set parent info as checkInfo for every init plan. */ + /* 灏嗙埗绾т俊鎭缃负姣忎釜鍒濆鍖栬鍒掔殑妫鏌ヤ俊鎭 */ SetCheckInfo(&ctl.checkInfo, plan->planTree); InitStreamFlow(&ctl); } } + /* 鍒濆鍖栧叏灞娴佸璞★紝骞跺湪鍒濆鍖栦箣鍚庢仮澶嶄腑鏂 */ u_sess->stream_cxt.global_obj->m_streamConsumerList = consumerList; u_sess->stream_cxt.global_obj->m_streamProducerList = producerList; u_sess->stream_cxt.global_obj->Init(threadNum); - - /* Resume interrupts after initialization of u_sess->stream_cxt.global_obj. */ RESUME_INTERRUPTS(); + /* 濡傛灉瀛樺湪椤剁骇娑堣垂鑰呯嚎绋嬶紝鍒欐敞鍐岄《绾ф秷璐硅呯嚎绋嬬殑娑堣垂鑰呭璞 */ if (topConsumerList != NIL) { - /* Register top consumer thread consumer object. */ foreach (consumerCell, topConsumerList) { consumer = (StreamConsumer*)lfirst(consumerCell); u_sess->stream_cxt.global_obj->registerStream(consumer); } } + /* 濡傛灉瀛樺湪鐢熶骇鑰呯嚎绋嬶紝鍒欒繛鎺ョ浉鍏崇殑娑堣垂鑰 */ if (producerList != NIL) { - /* collect connect consumer time */ + /* 璁板綍杩炴帴娑堣垂鑰呯殑鏃堕棿 */ if (plan->instrument_option) TRACK_START(-1, STREAMNET_INIT); int total_connNum = 0; int current_index = 0; - /* Connect related consumer. */ + + /* 杩炴帴鐩稿叧鐨勬秷璐硅 */ foreach (producerCell, producerList) { producer = (StreamProducer*)lfirst(producerCell); /* - * Here, total_connNum only counts for non local stream nodes. - * Because producer of local stream does not need to connect with consumer. + * 鍦ㄨ繖閲岋紝total_connNum浠呰绠楅潪鏈湴娴佽妭鐐圭殑杩炴帴鏁般 + * 鍥犱负鏈湴娴佺殑鐢熶骇鑰呬笉闇瑕佷笌娑堣垂鑰呭缓绔嬭繛鎺ャ */ if (!producer->isLocalStream()) { total_connNum += producer->getConnNum(); } } - /* We only create connection for non local stream. */ + /* 浠呬负闈炴湰鍦版祦鍒涘缓杩炴帴 */ if (total_connNum > 0) { libcomm_addrinfo** total_consumerAddr = (libcomm_addrinfo**)palloc0(total_connNum * sizeof(libcomm_addrinfo*)); @@ -1084,8 +1138,8 @@ void BuildStreamFlow(PlannedStmt* plan) TRACK_END(-1, STREAMNET_INIT); } + /* 濡傛灉瀛樺湪娑堣垂鑰呯嚎绋嬶紝鍒欑瓑寰呮墍鏈夌敓浜ц呰繛鎺ュ氨缁 */ if (consumerList != NIL) { - /* Wait for all producer connection ready. */ foreach (consumerCell, consumerList) { consumer = (StreamConsumer*)lfirst(consumerCell); IPC_PERFORMANCE_LOG_OUTPUT("BuildStreamFlow waitProducerReady start."); @@ -1103,31 +1157,36 @@ void SetupStreamRuntime(StreamState* node) StreamPair* pair = NULL; StreamConsumer* consumer = NULL; + /* 鏋勫缓娴佹搷浣滅殑鍏抽敭淇℃伅锛屽寘鎷煡璇D鍜岃鍒掕妭鐐笽D */ key.queryId = node->ss.ps.state->es_plannedstmt->queryId; key.planNodeId = streamNode->scan.plan.plan_node_id; + /* 鏂█鍏ㄥ眬娴佸璞′笉涓虹┖ */ Assert(u_sess->stream_cxt.global_obj != NULL); - pair = u_sess->stream_cxt.global_obj->popStreamPair(key); + /* 浠庡叏灞娴佸璞′腑鍙栧嚭娴佹搷浣滅殑閰嶅瀵硅薄 */ + pair = u_sess->stream_cxt.global_obj->popStreamPair(key); Assert(pair->producerList != NULL); - /* Set the current smp id. */ + /* 璁剧疆褰撳墠SMP鏍囪瘑绗 */ key.smpIdentifier = u_sess->stream_cxt.smp_id; + /* 濡傛灉閰嶅瀵硅薄涓瓨鍦ㄦ秷璐硅呭垪琛紝鍒欐牴鎹甋MP鏍囪瘑绗︽煡鎵剧浉搴旂殑娑堣垂鑰呭璞 */ if (pair->consumerList) { consumer = (StreamConsumer*)FindStreamObjBySmpId(pair->consumerList, u_sess->stream_cxt.smp_id); Assert(consumer != NULL); } - /* Set shared context in StreamState. */ + /* 鍦⊿treamState涓缃叡浜笂涓嬫枃 */ if (pair->producerList) { StreamProducer* producer = (StreamProducer*)linitial(pair->producerList); node->sharedContext = producer->getSharedContext(); } - /* Set consumer object in streamState. */ + /* 鍦╯treamState涓缃秷璐硅呭璞 */ node->consumer = consumer; + /* 娉ㄥ唽娴佸揩鐓 */ RegisterStreamSnapshots(); } @@ -1138,71 +1197,94 @@ static void StartupStreamThread(StreamState* node) ListCell* cell = NULL; uint8 smpId = 0; + /* 鏋勫缓娴佹搷浣滅殑鍏抽敭淇℃伅锛屽寘鎷煡璇D鍜岃鍒掕妭鐐笽D */ key.queryId = node->ss.ps.state->es_plannedstmt->queryId; key.planNodeId = node->ss.ps.plan->plan_node_id; + + /* 鏂█鍏ㄥ眬娴佸璞′笉涓虹┖ */ Assert(u_sess->stream_cxt.global_obj != NULL); + + /* 浠庡叏灞娴佸璞′腑鍙栧嚭涓庡叧閿俊鎭搴旂殑娴佹搷浣滈厤瀵瑰璞 */ pair = u_sess->stream_cxt.global_obj->popStreamPair(key); Assert(pair->producerList != NULL); + /* 鍒濆鍖栦簨鍔′笂涓嬫枃锛屽寘鎷簨鍔D鍜屽揩鐓т俊鎭 */ StreamTxnContext transactionCxt; transactionCxt.txnId = GetCurrentTransactionIdIfAny(); transactionCxt.snapshot = node->ss.ps.state->es_snapshot; StreamSaveTxnContext(&transactionCxt); - /* Only the Top Consumer thread can spawn multiple thread. */ + /* + * 鍙湁椤跺眰鐨勬秷璐硅呯嚎绋嬪彲浠ュ惎鍔ㄥ涓嚎绋嬨 + * 瀵逛簬姣忎釜鐢熶骇鑰呭璞★紝鍒濆鍖栧畠浠殑鐩稿叧鍙傛暟锛岀劧鍚庡湪鍏ㄥ眬娴佸璞′腑鍒濆鍖栫浉搴旂殑娴佺嚎绋嬨 + */ foreach (cell, pair->producerList) { StreamProducer* producer = (StreamProducer*)lfirst(cell); + + /* 鍒濆鍖栫敓浜ц呭璞 */ producer->init(node->ss.ps.ps_ResultTupleSlot->tts_tupleDescriptor, transactionCxt, node->ss.ps.state->es_param_list_info, u_sess->stream_cxt.producer_obj ? u_sess->stream_cxt.producer_obj->getKey().planNodeId : 0); + + /* 鍦ㄥ叏灞娴佸璞′腑鍒濆鍖栨祦绾跨▼ */ u_sess->stream_cxt.global_obj->initStreamThread(producer, smpId, pair); smpId++; } } -/* Set up Stream thread in parallel */ +/* 骞惰璁剧疆娴佺嚎绋*/ void StartUpStreamInParallel(PlannedStmt* pstmt, EState* estate) { + /* 濡傛灉涓嶆槸鏁版嵁鑺傜偣鎴栬呮病鏈夋祦鎿嶄綔锛岀洿鎺ヨ繑鍥 */ if (!IS_PGXC_DATANODE || pstmt->num_streams <= 0) { return; } + /* 濡傛灉璁″垝鏍戠殑璁″垝鑺傜偣ID澶т簬0锛屽紑濮嬭窡韪祦绾跨▼鍒濆鍖栫殑鎬ц兘 */ if (pstmt->planTree->plan_node_id > 0) { TRACK_START(pstmt->planTree->plan_node_id, DN_STREAM_THREAD_INIT); } + /* 鏂█鍏ㄥ眬娴佸璞′笉涓虹┖ */ Assert(u_sess->stream_cxt.global_obj != NULL); + /* 鑾峰彇鍏ㄥ眬娴佸璞′腑鐨勬祦鎿嶄綔閰嶅鍒楄〃 */ const List *pairList = u_sess->stream_cxt.global_obj->getStreamPairList(); ListCell *lc = NULL; foreach(lc, pairList) { + /* 瀵逛簬姣忎釜娴佹搷浣滈厤瀵癸紝鑾峰彇绗竴涓敓浜ц呭璞$殑娴佽妭鐐逛俊鎭 */ StreamPair *pair = (StreamPair*)lfirst(lc); StreamProducer *producer = (StreamProducer *)linitial(pair->producerList); const Stream *node = producer->getStream(); - /* Do not need to start up thread for dummy node. */ + /* 涓嶉渶瑕佷负铏氭嫙鑺傜偣鍚姩绾跨▼ */ if (node->is_dummy) { continue; } - /* create state to set up stream thread. */ + /* 鍒涘缓娴佺姸鎬佸璞★紝骞惰缃叾璁″垝鍜屾墽琛岀姸鎬佷俊鎭 */ StreamState *stream_state = makeNode(StreamState); stream_state->ss.ps.plan = (Plan*)node; stream_state->ss.ps.state = estate; + /* 鍒濆鍖栨祦鐘舵佸璞$殑缁撴灉鍏冪粍妲 */ ExecInitResultTupleSlot(estate, &stream_state->ss.ps); + /* 濡傛灉娴佽妭鐐圭殑璁″垝鏈夌洰鏍囧垪琛紝璁剧疆缁撴灉鍏冪粍妲界殑鎻忚堪绗 */ if (node->scan.plan.targetlist) { TupleDesc typeInfo = ExecTypeFromTL(node->scan.plan.targetlist, false); ExecSetSlotDescriptor(stream_state->ss.ps.ps_ResultTupleSlot, typeInfo); } else { - /* In case there is no target list, force its creation */ + /* 濡傛灉娌℃湁鐩爣鍒楄〃锛屽己鍒跺垱寤轰竴涓 */ ExecAssignResultTypeFromTL(&stream_state->ss.ps); } + /* 鍚姩娴佺嚎绋 */ StartupStreamThread(stream_state); + /* 閲婃斁娴佺姸鎬佸璞$殑鍐呭瓨 */ pfree(stream_state); } + /* 濡傛灉璁″垝鏍戠殑璁″垝鑺傜偣ID澶т簬0锛岀粨鏉熻窡韪祦绾跨▼鍒濆鍖栫殑鎬ц兘 */ if (pstmt->planTree->plan_node_id > 0) { TRACK_END(pstmt->planTree->plan_node_id, DN_STREAM_THREAD_INIT); } @@ -1210,13 +1292,16 @@ void StartUpStreamInParallel(PlannedStmt* pstmt, EState* estate) void StreamPrepareRequestForRecursive(StreamState* node, bool stepsync) { + /* 濡傛灉涓嶆槸閫掑綊妯″紡锛屾姏鍑洪敊璇 */ if (!EXEC_IN_RECURSIVE_MODE(node->ss.ps.plan)) { elog(ERROR, "MPP with-recursive invalid stream node status Stream[%d]", node->ss.ps.plan->plan_node_id); } int i = 0; int producerNum = 0; + /* 鑾峰彇娑堣垂鑰呯殑浼犺緭瀵硅薄鍒楄〃 */ StreamTransport** transport = node->consumer->getTransport(); + /* 鏍囪闇瑕佹柊鐨勬暟鎹 */ node->need_fresh_data = true; node->last_conn_idx = 0; StreamCOMM* scomm = NULL; @@ -1224,18 +1309,14 @@ void StreamPrepareRequestForRecursive(StreamState* node, bool stepsync) int full_conn_count = node->consumer->getConnNum(); int full_conn_index = 0; + /* 鍦ㄥ悓姝ユ楠ょ殑鎯呭喌涓嬶紝闇瑕佹帴鏀堕掑綊鑱旀帴鎵ц鑺傜偣鑼冨洿鍐呯殑鎵鏈夋暟鎹妭鐐圭殑娑堟伅 */ if (stepsync) { - /* - * In syncup case, we need receive all dn's message in recursive - * union execnode scope. - */ producerNum = node->consumer->getConnNum(); } else { /* - * In normal case, we need check if the backup producer-list is set, "not-NIL" - * indicates that there is a DN-pruning case happen where all connections is - * setup for plan-step syncup, we need logically pick up the producer connection - * do correct BROADCAST/REDISTRIBUTE + * 鍦ㄦ甯告儏鍐典笅锛岄渶瑕佹鏌ュ鐢ㄧ敓浜ц呭垪琛ㄦ槸鍚﹁缃紝 + * "涓嶄负NIL" 琛ㄧず鍙戠敓浜嗘暟鎹妭鐐瑰壀鏋濇儏鍐碉紝鎵鏈夎繛鎺ラ兘鏄负璁″垝姝ラ鍚屾鑰屽缓绔嬬殑锛 + * 鎴戜滑闇瑕侀昏緫鍦伴夋嫨鐢熶骇鑰呰繛鎺ヤ互杩涜姝g‘鐨凚ROADCAST/REDISTRIBUTE */ if (node->consumer->m_originProducerNodeList != NIL) { producerNum = list_length(node->consumer->m_originProducerNodeList); @@ -1245,19 +1326,21 @@ void StreamPrepareRequestForRecursive(StreamState* node, bool stepsync) } } - /* We should have at least one producer to receive */ + /* 鎴戜滑鑷冲皯搴旇鏈変竴涓敓浜ц呮潵鎺ユ敹鏁版嵁 */ Assert(producerNum > 0); + /* 涓烘瘡涓敓浜ц呰繛鎺ュ垎閰嶅唴瀛 */ node->connections = (PGXCNodeHandle**)palloc0(producerNum * sizeof(PGXCNodeHandle*)); node->conn_count = producerNum; + /* 鍒濆鍖 SCTP 杩炴帴鐨勭浉鍏充俊鎭 */ node->netctl.layer.sctpLayer.datamarks = (int*)palloc0(producerNum * sizeof(int)); node->netctl.layer.sctpLayer.gs_sock = (gsocket*)palloc0(producerNum * sizeof(gsocket)); node->netctl.layer.sctpLayer.poll2conn = (int*)palloc0(producerNum * sizeof(int)); - /* Loop the full datanode list and skip some of datanode when we found it is pruned */ + /* 閬嶅巻瀹屾暣鐨勬暟鎹妭鐐瑰垪琛紝骞跺湪鎵惧埌瀹冭鍓灊鏃惰烦杩 */ for (full_conn_index = 0; full_conn_index < full_conn_count; full_conn_index++) { - /* skip those do not exists in original consumer NodeList */ + /* 璺宠繃閭d簺涓嶅湪鍘熷娑堣垂鑰呰妭鐐瑰垪琛ㄤ腑鐨勮妭鐐 */ if (skip_pruned_datanode && !list_member_int(node->consumer->m_originProducerNodeList, node->consumer->getNodeIdx(transport[full_conn_index]->m_nodeName))) { @@ -1266,8 +1349,9 @@ void StreamPrepareRequestForRecursive(StreamState* node, bool stepsync) scomm = (StreamCOMM*)transport[full_conn_index]; + /* 涓鸿繛鎺ュ垎閰嶅唴瀛 */ node->connections[i] = (PGXCNodeHandle*)palloc0(sizeof(PGXCNodeHandle)); - /* Initialise Input buffer */ + /* 鍒濆鍖栬緭鍏ョ紦鍐插尯 */ node->connections[i]->inSize = STREAM_BUFFER_SIZE; node->connections[i]->inBuffer = (char*)palloc0(STREAM_BUFFER_SIZE); node->connections[i]->sock = NO_SOCKET; @@ -1280,7 +1364,7 @@ void StreamPrepareRequestForRecursive(StreamState* node, bool stepsync) node->connections[i]->tcpCtlPort = -1; node->connections[i]->listenPort = scomm->m_addr->listen_port; - /* Check if actual index exceeds the producer number */ + /* 妫鏌ュ疄闄呯殑绱㈠紩鏄惁瓒呰繃浜嗙敓浜ц呮暟閲 */ if (i >= producerNum) { elog(ERROR, "MPP with-recursive invalid connection index in DN pruning scenarios"); } @@ -1288,25 +1372,25 @@ void StreamPrepareRequestForRecursive(StreamState* node, bool stepsync) i++; } + /* 濡傛灉鏈変华琛紝涓旀祦鑺傜偣绫诲瀷涓 STREAM_BROADCAST锛屽垯璁剧疆婧㈠嚭澶у皬 */ if (node->ss.ps.instrument && node->type == STREAM_BROADCAST) node->spill_size = &node->ss.ps.instrument->sorthashinfo.spill_size; else node->spill_size = &node->recvDataLen; + /* 璁剧疆娴佽妭鐐逛负灏辩华鐘舵 */ node->isReady = true; } void StreamPrepareRequest(StreamState* node) { /* - * If we found current stream node is under recursive union node, we handle the - * stream preparation in a special way + * 濡傛灉鎴戜滑鍙戠幇褰撳墠鐨勬祦鑺傜偣浣嶄簬閫掑綊鑱旀帴鑺傜偣涓嬶紝鎴戜滑浠ヤ竴绉嶇壒娈婄殑鏂瑰紡澶勭悊娴佸噯澶 * - * MPP support with-recursive + * MPP 鏀寔 with-recursive */ if (EXEC_IN_RECURSIVE_MODE(node->ss.ps.plan)) { StreamPrepareRequestForRecursive(node, false); - return; } @@ -1314,23 +1398,28 @@ void StreamPrepareRequest(StreamState* node) int producerNum = node->consumer->getConnNum(); StreamTransport** transport = node->consumer->getTransport(); + /* 鏍囪闇瑕佹柊鐨勬暟鎹 */ node->need_fresh_data = true; node->last_conn_idx = 0; StreamCOMM* scomm = NULL; + /* 涓烘瘡涓敓浜ц呰繛鎺ュ垎閰嶅唴瀛 */ node->connections = (PGXCNodeHandle**)palloc0(producerNum * sizeof(PGXCNodeHandle*)); node->conn_count = producerNum; + /* 鍒濆鍖 SCTP 杩炴帴鐨勭浉鍏充俊鎭 */ node->netctl.layer.sctpLayer.datamarks = (int*)palloc0(producerNum * sizeof(int)); node->netctl.layer.sctpLayer.gs_sock = (gsocket*)palloc0(producerNum * sizeof(gsocket)); node->netctl.layer.sctpLayer.poll2conn = (int*)palloc0(producerNum * sizeof(int)); + /* 閬嶅巻鎵鏈夌殑杩炴帴锛屽苟涓烘瘡涓繛鎺ュ垎閰嶅唴瀛樺拰鍒濆鍖栫浉鍏充俊鎭 */ for (i = 0; i < node->conn_count; i++) { scomm = (StreamCOMM*)transport[i]; + /* 涓鸿繛鎺ュ垎閰嶅唴瀛 */ node->connections[i] = (PGXCNodeHandle*)palloc0(sizeof(PGXCNodeHandle)); - /* Initialise Input buffer */ + /* 鍒濆鍖栬緭鍏ョ紦鍐插尯 */ node->connections[i]->inSize = STREAM_BUFFER_SIZE; node->connections[i]->inBuffer = (char*)palloc0(node->connections[i]->inSize); node->connections[i]->sock = NO_SOCKET; @@ -1344,68 +1433,55 @@ void StreamPrepareRequest(StreamState* node) node->connections[i]->listenPort = scomm->m_addr->listen_port; } + /* 濡傛灉鏈変华琛紝涓旀祦鑺傜偣绫诲瀷涓 STREAM_BROADCAST锛屽垯璁剧疆婧㈠嚭澶у皬 */ if (node->ss.ps.instrument && node->type == STREAM_BROADCAST) node->spill_size = &node->ss.ps.instrument->sorthashinfo.spill_size; else node->spill_size = &node->recvDataLen; + /* 璁剧疆娴佽妭鐐逛负灏辩华鐘舵 */ node->isReady = true; } void StreamReportError(StreamState* node) { + /* 妫鏌ユ槸鍚︽湁閿欒娑堟伅闇瑕佹姤鍛 */ if (node->errorMessage) { - if (node->errorDetail != NULL && node->errorContext != NULL) + /* 妫鏌ユ槸鍚﹀悓鏃舵彁渚涗簡閿欒璇︽儏鍜岄敊璇笂涓嬫枃 */ + if (node->errorDetail != NULL && node->errorContext != NULL) { ereport(ERROR, (errcode(node->errorCode), combiner_errdata(&node->remoteErrData), errmsg("%s", node->errorMessage), errdetail("%s", node->errorDetail), errcontext("%s", node->errorContext))); - else if (node->errorDetail != NULL) + } + /* 濡傛灉鍙彁渚涗簡閿欒璇︽儏 */ + else if (node->errorDetail != NULL) { ereport(ERROR, (errcode(node->errorCode), combiner_errdata(&node->remoteErrData), errmsg("%s", node->errorMessage), errdetail("%s", node->errorDetail))); - else if (node->errorContext != NULL) + } + /* 濡傛灉鍙彁渚涗簡閿欒涓婁笅鏂 */ + else if (node->errorContext != NULL) { ereport(ERROR, (errcode(node->errorCode), combiner_errdata(&node->remoteErrData), errmsg("%s", node->errorMessage), errcontext("%s", node->errorContext))); - else + } + /* 濡傛灉娌℃湁鎻愪緵閿欒璇︽儏鎴栭敊璇笂涓嬫枃 */ + else { ereport(ERROR, - (errcode(node->errorCode), combiner_errdata(&node->remoteErrData), errmsg("%s", node->errorMessage))); + (errcode(node->errorCode), + combiner_errdata(&node->remoteErrData), + errmsg("%s", node->errorMessage))); + } } } -void AddCheckMessage(StringInfo msg_new, StringInfo msg_org, bool is_stream, unsigned int planNodeId) -{ - /* Set cursor */ - msg_new->cursor = msg_org->cursor; - - if (is_stream) { - /* Add queryId check. */ - pq_sendint64(msg_new, u_sess->debug_query_id); - /* Add planNodeId check. */ - pq_sendint(msg_new, planNodeId, 4); - } - - /* Add actual message length. */ - pq_sendint(msg_new, msg_org->len, 4); - - /* Add CRC check. */ - pg_crc32 valcrc; - INIT_CRC32(valcrc); - COMP_CRC32(valcrc, msg_org->data, msg_org->len); - FIN_CRC32(valcrc); - pq_sendint(msg_new, valcrc, 4); - - /* Add actual message. */ - appendBinaryStringInfo(msg_new, msg_org->data, msg_org->len); -} - void CheckMessages(uint64 check_query_id, uint32 check_plan_node_id, char* msg, int msg_len, bool is_stream) { uint32 plan_node_id; @@ -1416,14 +1492,13 @@ void CheckMessages(uint64 check_query_id, uint32 check_plan_node_id, char* msg, ereport(ERROR, (errmodule(MOD_GUC), errcode(ERRCODE_STRING_DATA_LENGTH_MISMATCH), - errmsg( - "message length %d is less than head length %d", msg_len, head_len))); + errmsg("message length %d is less than head length %d", msg_len, head_len))); } uint32 send_check_sum; errno_t rc = EOK; if (is_stream) { - /* Debug query ID check. */ + /* 妫鏌ヨ皟璇曟煡璇D */ rc = memcpy_s(&query_id, sizeof(uint64), msg, sizeof(uint64)); securec_check(rc, "\0", "\0"); query_id = ntohl64(query_id); @@ -1437,7 +1512,7 @@ void CheckMessages(uint64 check_query_id, uint32 check_plan_node_id, char* msg, errmsg("expected query id is %lu, actual query id is %lu", u_sess->debug_query_id, query_id))); } - /* Plan Node ID check. */ + /* 璁″垝鑺傜偣ID妫鏌 */ rc = memcpy_s(&plan_node_id, sizeof(int), msg, sizeof(int)); securec_check(rc, "\0", "\0"); plan_node_id = ntohl(plan_node_id); @@ -1449,12 +1524,11 @@ void CheckMessages(uint64 check_query_id, uint32 check_plan_node_id, char* msg, ereport(ERROR, (errmodule(MOD_GUC), errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg( - "expected plan node id is %u, actual plan node id is %u", check_plan_node_id, plan_node_id))); + errmsg("expected plan node id is %u, actual plan node id is %u", check_plan_node_id, plan_node_id))); } } - /* Message length check. */ + /* 娑堟伅闀垮害妫鏌 */ rc = memcpy_s(&actual_msg_len, sizeof(int), msg, sizeof(int)); securec_check(rc, "\0", "\0"); actual_msg_len = ntohl(actual_msg_len); @@ -1465,11 +1539,10 @@ void CheckMessages(uint64 check_query_id, uint32 check_plan_node_id, char* msg, ereport(ERROR, (errmodule(MOD_GUC), errcode(ERRCODE_STRING_DATA_LENGTH_MISMATCH), - errmsg( - "expected message length is %d, actual message length is %d", actual_msg_len, msg_len - head_len))); + errmsg("expected message length is %d, actual message length is %d", actual_msg_len, msg_len - head_len))); } - /* CRC check. */ + /* CRC鏍¢獙 */ rc = memcpy_s(&send_check_sum, sizeof(uint32), msg, sizeof(uint32)); securec_check(rc, "\0", "\0"); send_check_sum = ntohl(send_check_sum); @@ -1489,29 +1562,30 @@ void CheckMessages(uint64 check_query_id, uint32 check_plan_node_id, char* msg, errmsg("expected crc is %u, actual crc is %u", send_check_sum, valcrc))); } } + static void HandleStreamTuple(StreamState* node, char* msg, int msg_len) { errno_t rc = EOK; + /* 濡傛灉瀛樺湪閿欒娑堟伅锛岀洿鎺ヨ繑鍥 */ if (node->errorMessage) return; - /* We expect previous message is consumed */ + /* 鎴戜滑鏈熸湜鍓嶄竴涓秷鎭凡琚秷鑰 */ if (!EXEC_IN_RECURSIVE_MODE(node->ss.ps.plan)) { /* - * If stream is mark as no early free (e.g. recursive-union case), we need it - * to response for sync cluster step, we don't do assert here. + * 濡傛灉娴佹爣璁颁负涓嶅彲鎻愬墠閲婃斁锛堜緥濡傦紝閫掑綊鑱斿悎鎯呭喌锛夛紝鎴戜滑闇瑕佸畠鏉ュ搷搴斿悓姝ラ泦缇ゆ楠わ紝姝ゆ椂鎴戜滑涓嶈繘琛屾柇瑷銆 */ AssertEreport(node->buf.len == 0, MOD_OPT, "node buf len is not zero"); } - /* Check messages. */ + /* 妫鏌ユ秷鎭*/ #ifdef USE_ASSERT_CHECKING CheckMessages(node->consumer->getKey().queryId, ((PlanState*)node)->plan->plan_node_id, msg, msg_len, true); msg += STREAM_CHECKMSG_LEN; msg_len -= STREAM_CHECKMSG_LEN; #else - + /* 濡傛灉鍚敤浜嗘祦鏁版嵁妫鏌ラ夐」锛屾鏌ユ秷鎭 */ if (unlikely(anls_opt_is_on(ANLS_STREAM_DATA_CHECK))) { CheckMessages(node->consumer->getKey().queryId, ((PlanState*)node)->plan->plan_node_id, msg, msg_len, true); msg += STREAM_CHECKMSG_LEN; @@ -1519,25 +1593,28 @@ static void HandleStreamTuple(StreamState* node, char* msg, int msg_len) } #endif + /* 濡傛灉娑堟伅闀垮害灏忎簬闆讹紝鎶ュ憡閿欒銆 */ if (msg_len < 0) ereport(ERROR, (errcode(ERRCODE_DATA_EXCEPTION), errmsg("Unexpected response from remote node"))); + /* 濡傛灉娑堟伅闀垮害澶т簬缂撳啿鍖哄ぇ灏忥紝閲嶆柊鍒嗛厤缂撳啿鍖恒 */ if (msg_len > node->buf.size) { node->buf.msg = (char*)repalloc(node->buf.msg, msg_len); node->buf.size = msg_len; } + /* 灏嗘秷鎭唴瀹规嫹璐濆埌缂撳啿鍖恒 */ rc = memcpy_s(node->buf.msg, node->buf.size, msg, msg_len); securec_check(rc, "\0", "\0"); node->buf.len = msg_len; - /* Record length of all received data for network perf data. */ + /* 璁板綍鎺ユ敹鍒扮殑鎵鏈夋暟鎹殑闀垮害锛岀敤浜庣綉缁滄ц兘鏁版嵁銆 */ *node->spill_size += msg_len; } void HandleStreamError(StreamState* node, char* msg_body, int len) { - /* parse error message */ + /* 瑙f瀽閿欒娑堟伅 */ char* code = NULL; char* message = NULL; char* detail = NULL; @@ -1551,10 +1628,10 @@ void HandleStreamError(StreamState* node, char* msg_body, int len) char* mod_id = NULL; /* - * Scan until point to terminating \0 + * 鎵弿鐩村埌鎸囧悜缁堢粨绗0 */ while (((int)(offset + 1)) < len) { - /* pointer to the field message */ + /* 鎸囧悜瀛楁娑堟伅鐨勬寚閽 */ char* str = msg_body + offset + 1; switch (msg_body[offset]) { @@ -1564,7 +1641,7 @@ void HandleStreamError(StreamState* node, char* msg_body, int len) case 'C': /* code */ code = str; - /* Error Code is exactly 5 significant bytes */ + /* 閿欒鐮佹濂芥槸5涓湁鏁堝瓧鑺 */ if (code != NULL) error_code = MAKE_SQLSTATE(code[0], code[1], code[2], code[3], code[4]); break; @@ -1590,7 +1667,7 @@ void HandleStreamError(StreamState* node, char* msg_body, int len) funcname = str; break; - /* Fields not yet in use */ + /* 灏氭湭浣跨敤鐨勫瓧娈 */ case 'S': /* severity */ case 'H': /* hint */ case 'P': /* position string */ @@ -1600,16 +1677,14 @@ void HandleStreamError(StreamState* node, char* msg_body, int len) break; } - /* code, message and \0 */ + /* code, message鍜孿0 */ offset += strlen(str) + 2; } /* - * We may have special handling for some errors, default handling is to - * throw out error with the same message. We can not ereport immediately - * because we should read from this and other connections until - * ReadyForQuery is received, so we just store the error message. - * If multiple connections return errors only first one is reported. + * 瀵逛簬涓浜涚壒娈婇敊璇紝鎴戜滑鍙兘鏈夌壒娈婂鐞嗭紝 榛樿鐨勫鐞嗘柟寮忔槸鎶涘嚭鍏锋湁鐩稿悓娑堟伅鐨勯敊璇 + * 鎴戜滑涓嶈兘绔嬪嵆 ereport锛屽洜涓烘垜浠簲璇ヤ粠杩欎釜鍜屽叾浠栬繛鎺ヤ腑璇诲彇锛岀洿鍒 ReadyForQuery 琚帴鏀跺埌锛 + * 鎵浠ユ垜浠彧鏄瓨鍌ㄩ敊璇秷鎭 濡傛灉澶氫釜杩炴帴杩斿洖閿欒锛屽彧鎶ュ憡绗竴涓敊璇 */ if (node->errorMessage == NULL) { MemoryContext old_cxt = MemoryContextSwitchTo(ErrorContext); @@ -1657,20 +1732,20 @@ void HandleStreamError(StreamState* node, char* msg_body, int len) } /* - * Handle NoticeResponse ('N') message from Stream thread + * 澶勭悊鏉ヨ嚜娴佺嚎绋嬬殑notiferresponse 娑堟伅 */ void HandleStreamNotice(StreamState* node, char* msg_body, size_t len) { - /* parse error message */ + /* 瑙f瀽閿欒淇℃伅 */ char* message = NULL; char* detail = NULL; size_t offset = 0; /* - * Scan until point to terminating \0 + * 鎵弿鍒扮粓姝㈢偣 */ while (offset + 1 < len) { - /* pointer to the field message */ + /* 鎸囧悜瀛楁娑堟伅鐨勬寚閽 */ char* str = msg_body + offset + 1; switch (msg_body[offset]) { @@ -1680,7 +1755,7 @@ void HandleStreamNotice(StreamState* node, char* msg_body, size_t len) case 'D': /* details */ detail = str; break; - /* Fields not yet in use */ + /* 灏氭湭浣跨敤鐨勫瓧娈 */ case 'S': /* severity */ case 'C': /* code */ case 'R': /* routine */ @@ -1695,7 +1770,7 @@ void HandleStreamNotice(StreamState* node, char* msg_body, size_t len) break; } - /* code, message and \0 */ + /* 浠g爜銆佹秷鎭拰 \0 */ offset += strlen(str) + 2; } @@ -1708,19 +1783,24 @@ void HandleStreamNotice(StreamState* node, char* msg_body, size_t len) } /* - * MPP Recursive-Union support + * MPP閫掑綊鑱斿悎鏀寔 */ static void ParseRUSyncMsg(const char* msg, const char* key, char* value) { Assert(msg != NULL && key != NULL && value != NULL); + /* 鏌ユ壘娑堟伅涓敭鐨勮捣濮嬩綅缃 */ const char* value_startptr = (char*)strstr(msg, key) + strlen(key); + /* 鏌ユ壘閿殑缁撴潫浣嶇疆锛堥楀彿鍒嗛殧绗︿箣鍓嶏級 */ const char* value_endptr = strstr(value_startptr, ","); + /* 璁$畻閿殑闀垮害 */ int len = value_endptr - value_startptr; + /* 灏唙alue缂撳啿鍖哄垵濮嬪寲涓0 */ errno_t rc = memset_s(value, NAMEDATALEN, 0, NAMEDATALEN); securec_check(rc, "\0", "\0"); + /* 灏嗛敭鐨勫煎鍒跺埌value缂撳啿鍖轰腑 */ rc = memcpy_s(value, NAMEDATALEN, value_startptr, len); securec_check(rc, "\0", "\0"); } @@ -1743,35 +1823,35 @@ static void HandleStreamRUSyncMsg(StreamState* node, char msg_type, char* msg, i char value[NAMEDATALEN] = {0}; - /* parse node name */ + /* 瑙f瀽鑺傜偣鍚嶇О */ ParseRUSyncMsg(msg, "nodename:", value); char* nodename = pstrdup(value); - /* parse recursive step id */ + /* 瑙f瀽閫掑綊姝ラid */ ParseRUSyncMsg(msg, "rustep:", value); int rustep = atoi(value); - /* parse pgxcnodeid */ + /* 瑙f瀽pgxcnodeid */ ParseRUSyncMsg(msg, "xcnodeid:", value); int xcnodeid = atoi(value); - /* parse iteration */ + /* 瑙f瀽iteration */ ParseRUSyncMsg(msg, "iteration:", value); int iteration = atoi(value); - /* parse pgxcnodeid */ + /* 瑙f瀽pgxcnodeid */ ParseRUSyncMsg(msg, "tuple_processed:", value); int tuple_processed = atoi(value); - /* parse controller_plannodeid */ + /* 瑙f瀽controller_plannodeid */ ParseRUSyncMsg(msg, "controller_plannodeid:", value); int controller_plannodeid = atoi(value); - /* parse producer_plannodeid */ + /* 瑙f瀽producer_plannodeid */ ParseRUSyncMsg(msg, "producer_plannodeid:", value); int producer_plannodeid = atoi(value); - /* output important message */ + /* 杈撳嚭閲嶈淇℃伅 */ const char* direction = NULL; if (msg_type == 'F') { ereport(ERROR, (errcode(ERRCODE_DATA_EXCEPTION), errmsg("Unexpected msg type[%d]", msg_type))); @@ -1797,13 +1877,12 @@ static void HandleStreamRUSyncMsg(StreamState* node, char msg_type, char* msg, i producer_plannodeid, tuple_processed); - /* Mark the received datanode's xx step has finished with xx tuple processed */ + /* 鐢ㄥ凡澶勭悊鐨剎x鍏冪粍鏍囪鎺ユ敹鍒扮殑datanode鐨剎x姝ラ宸茬粡瀹屾垚 */ StreamNodeGroup* stream_nodegroup = u_sess->stream_cxt.global_obj; SyncController* controller = stream_nodegroup->GetSyncController(controller_plannodeid); /* - * Report Error when the controller for its belonging RecursiveUnion node is - * not found. + * 鎵句笉鍒版墍灞為掑綊union鑺傜偣鐨勬帶鍒跺櫒鏃舵姤鍛婇敊璇 */ if (controller == NULL) { ereport(ERROR, @@ -1835,12 +1914,12 @@ int HandleStreamResponse(PGXCNodeHandle* conn, StreamState* node) char msg_type; for (;;) { - /* hack now will improve later */ + /* Hack鐜板湪灏嗘敼杩涗互鍚 */ if (u_sess->stream_cxt.global_obj->m_syncControllers && conn->state == DN_CONNECTION_STATE_IDLE) { - /* with-recursive case */ + /* 浣跨敤閫掑綊鐨勬儏鍐 */ conn->state = DN_CONNECTION_STATE_QUERY; } else { - /* normal case */ + /* 鏅氭儏鍐 */ if (conn->state == DN_CONNECTION_STATE_IDLE) { ereport(ERROR, (errcode(ERRCODE_INVALID_OPTION), errmsg("state is DN_CONNECTION_STATE_IDLE: %d", DN_CONNECTION_STATE_IDLE))); @@ -1848,23 +1927,23 @@ int HandleStreamResponse(PGXCNodeHandle* conn, StreamState* node) } /* - * If we are in the process of shutting down, we - * may be rolling back, and the buffer may contain other messages. - * We want to avoid a procarray exception - * as well as an error stack overflow. + * 濡傛灉鎴戜滑鍦ㄥ叧闂殑杩囩▼涓紝鎴戜滑 + *鍙兘姝e湪鍥炴粴锛岀紦鍐插尯鍙兘鍖呭惈鍏朵粬娑堟伅銆 + *鎴戜滑甯屾湜閬垮厤procarray寮傚父 + *浠ュ強閿欒鍫嗘爤婧㈠嚭銆 */ if (t_thrd.proc_cxt.proc_exit_inprogress) { conn->state = DN_CONNECTION_STATE_ERROR_FATAL; elog(WARNING, "DN_CONNECTION_STATE_ERROR_FATAL2 is set when proc_exit_inprogress"); } - /* don't read from from the connection if there is a fatal error */ + /* 濡傛灉鏈夎嚧鍛介敊璇紝涓嶈浠庤繛鎺ヤ腑璇诲彇 */ if (conn->state == DN_CONNECTION_STATE_ERROR_FATAL) { elog(WARNING, "HandleStreamResponse returned with DN_CONNECTION_STATE_ERROR_FATAL"); return RESPONSE_COMPLETE; } - /* No data available, exit */ + /* 娌℃湁鍙敤鏁版嵁锛岄鍑 */ if (!HAS_MESSAGE_BUFFERED(conn)) { return RESPONSE_EOF; } @@ -1876,21 +1955,21 @@ int HandleStreamResponse(PGXCNodeHandle* conn, StreamState* node) msg_type = get_message(conn, &msg_len, &msg); #ifdef MEMORY_CONTEXT_CHECKING - /* Check all memory contexts when repalloc the memory of buffer */ + /* 褰撻噸鏂板垎閰嶇紦鍐插尯鐨勫唴瀛樻椂锛屾鏌ユ墍鏈夌殑鍐呭瓨涓婁笅鏂 */ if (conn->inSize > old_size) { MemoryContextCheck(t_thrd.top_mem_cxt, false); } #endif switch (msg_type) { - case '\0': /* Not enough data in the buffer */ + case '\0': /* 缂撳啿鍖轰腑鏁版嵁涓嶈冻 */ return RESPONSE_EOF; break; - case 'T': /* RowDescription */ - /* Stream thread should not send row desrciption. */ + case 'T': + /* 娴佺嚎绋嬩笉搴斿彂閫佽鎻忚堪. */ ereport(ERROR, (errcode(ERRCODE_UNEXPECTED_NULL_VALUE), - errmsg("Stream thread should not send row desrciption."))); + errmsg("Stream thread should not send row description."))); break; case 'B': /* VectorBatch */ case 'D': /* DataRow */ @@ -1906,22 +1985,21 @@ int HandleStreamResponse(PGXCNodeHandle* conn, StreamState* node) conn->state = DN_CONNECTION_STATE_IDLE; return RESPONSE_COMPLETE; } - case 'R': { /* distributed recursive union support */ - /* Handle Recursive Union sync-up message */ + case 'R': { /* 鍒嗗竷寮忛掑綊鑱斿悎鏀寔 */ + /* 澶勭悊閫掑綊鑱斿悎鍚屾娑堟伅 */ HandleStreamRUSyncMsg(node, 'R', msg, msg_len); return RESPONSE_RECURSIVE_SYNC_R; } default: - /* sync lost? */ ereport(ERROR, (errcode(ERRCODE_INVALID_OPTION), errmsg("Received unsupported message type: %c", msg_type))); conn->state = DN_CONNECTION_STATE_ERROR_FATAL; - /* stop reading */ + /* 鍋滄璇诲彇 */ return RESPONSE_COMPLETE; } } - /* never happen, but keep compiler quiet */ + /* 姘歌繙涓嶄細鍙戠敓锛屼絾鏄淇濇寔缂栬瘧鍣ㄧ殑瀹夐潤 */ return RESPONSE_EOF; } @@ -1930,14 +2008,22 @@ void AssembleDataRow(StreamState* node) MemoryContext oldcontext; TupleTableSlot* slot = node->ss.ps.ps_ResultTupleSlot; + // 寮濮嬬綉缁滄暟鎹弽搴忓垪鍖栬鏃 NetWorkTimeDeserializeStart(t_thrd.pgxc_cxt.GlobalNetInstr); + // 鍒囨崲鍒板悎閫傜殑鍐呭瓨涓婁笅鏂 oldcontext = MemoryContextSwitchTo(slot->tts_mcxt); + + // 鍙嶅簭鍒楀寲鏁版嵁琛屽苟瀛樺偍鍒扮粨鏋滃厓缁勬Ы涓 ExecStoreDataRowTuple(node->buf.msg, node->buf.len, InvalidOid, slot, false); - /* The data has been consumed. */ + + // 鏁版嵁宸茶娑堣垂锛岄噸缃紦鍐插尯闀垮害涓0 node->buf.len = 0; + + // 鍒囨崲鍥炲師濮嬪唴瀛樹笂涓嬫枃 MemoryContextSwitchTo(oldcontext); + // 缁撴潫缃戠粶鏁版嵁鍙嶅簭鍒楀寲璁℃椂 NetWorkTimeDeserializeEnd(t_thrd.pgxc_cxt.GlobalNetInstr); } @@ -1951,33 +2037,36 @@ static bool GetTupleFromConnBuffer(StreamState* node) int connIdx = 0; PGXCNodeHandle** connections = NULL; + // 鑾峰彇褰撳墠杩炴帴绱㈠紩鍜岃繛鎺ユ暟缁 connIdx = node->last_conn_idx; connections = node->connections; - /* Handle data from all connection. */ + // 澶勭悊鎵鏈夎繛鎺ョ殑鏁版嵁 while (connIdx < node->conn_count) { int res = HandleStreamResponse(connections[connIdx], node); switch (res) { - /* Try next run. */ + // 灏濊瘯涓嬩竴涓繛鎺 case RESPONSE_EOF: { connIdx++; } break; - /* Finish one connection. */ + // 瀹屾垚涓涓繛鎺 case RESPONSE_COMPLETE: { node->conn_count = node->conn_count - 1; - /* All finished. */ + // 鎵鏈夎繛鎺ュ凡瀹屾垚 if (node->conn_count == 0) { node->need_fresh_data = false; return false; } + // 绉诲姩杩炴帴骞剁户缁鐞 if (connIdx < node->conn_count) { connections[connIdx] = connections[node->conn_count]; } } break; + // 澶勭悊鏁版嵁琛 case RESPONSE_DATAROW: { - /* If we have message in the buffer, consume it */ + // 濡傛灉缂撳啿鍖轰腑鏈夋秷鎭紝瑙f瀽骞惰繑鍥炴暟鎹 if (node->buf.len != 0) { AssembleDataRow(node); node->need_fresh_data = false; @@ -1985,14 +2074,16 @@ static bool GetTupleFromConnBuffer(StreamState* node) return true; } } break; + // 閫掑綊鍚屾娑堟伅锛岀户缁鐞 case RESPONSE_RECURSIVE_SYNC_F: case RESPONSE_RECURSIVE_SYNC_R: continue; + // 澶勭悊鏈鏈熺殑鍝嶅簲 default: ereport(ERROR, (errcode(ERRCODE_FETCH_DATA_FAILED), - errmsg("Unexpected response %d from Datanode when get tuple from cnnection buffer.The " - "connection idx is %d and the count of active connections is %d.", + errmsg("Unexpected response %d from Datanode when getting tuple from connection buffer. " + "The connection index is %d and the count of active connections is %d.", res, connIdx, node->conn_count))); @@ -2000,6 +2091,7 @@ static bool GetTupleFromConnBuffer(StreamState* node) } } + // 纭繚杩炴帴绱㈠紩涓庢椿璺冭繛鎺ユ暟鐩哥瓑 Assert(connIdx == node->conn_count); node->need_fresh_data = true; node->last_conn_idx = 0; @@ -2015,43 +2107,58 @@ static bool GetTupleFromConnBuffer(StreamState* node) */ bool ScanStreamByLibcomm(StreamState* node) { + // 寰幆澶勭悊鎵鏈夎繛鎺ョ殑鏁版嵁 while (node->conn_count) { + // 濡傛灉闇瑕佹柊鐨勬暟鎹紝浠庨昏緫杩炴帴涓帴鏀舵暟鎹 if (node->need_fresh_data) { if (datanode_receive_from_logic_conn(node->conn_count, node->connections, &node->netctl, -1)) { int error_code = getStreamSocketError(gs_comm_strerror()); + // 鎶ュ憡閿欒骞剁粓姝 ereport(ERROR, (errcode(error_code), errmsg("Failed to read response from Datanodes. Detail: %s\n", gs_comm_strerror()))); } } + // 濡傛灉鎴愬姛瑙f瀽鏁版嵁琛岋紝杩斿洖 true if (node->StreamDeserialize(node)) return true; else { + // 濡傛灉涓嶉渶瑕佹柊鏁版嵁锛岃繑鍥 false锛涘惁鍒欑户缁惊鐜 if (node->need_fresh_data == false) return false; } + // 鎶ュ憡閿欒 StreamReportError(node); } + // 澶勭悊瀹屾墍鏈夎繛鎺ョ殑鏁版嵁锛岃繑鍥 false return false; } bool ScanMemoryStream(StreamState* node) { + // 鏂█鑺傜偣鐨勬帓搴忎俊鎭负 NULL Assert(((Stream*)(node->ss.ps.plan))->sort == NULL); + + // 寰幆澶勭悊鎵鏈夎繛鎺ョ殑鏁版嵁 while (node->conn_count) { + // 濡傛灉闇瑕佹柊鐨勬暟鎹紝浠庡唴瀛樹腑鎺ユ敹鏁版嵁 if (node->need_fresh_data) { if (gs_memory_recv(node)) { + // 鎴愬姛鎺ユ敹鏁版嵁锛岃繑鍥 true return true; } else { + // 鎺ユ敹鏁版嵁澶辫触锛屾姤鍛婇敊璇苟缁堟 StreamReportError(node); node->need_fresh_data = false; return false; } } } + + // 澶勭悊瀹屾墍鏈夎繛鎺ョ殑鏁版嵁锛岃繑鍥 false return false; } @@ -2062,7 +2169,7 @@ StreamState* BuildStreamRuntime(Stream* node, EState* estate, int eflags) { StreamState* stream_state = NULL; - /* StreamState is allocated in StreamRunTime Memory Context if we need set up controller */ + /* 濡傛灉闇瑕佽缃悓姝ユ帶鍒跺櫒锛屽垯鍦 StreamRunTime 鍐呭瓨涓婂垎閰 StreamState */ if (NeedSetupSyncUpController((Plan*)node)) { MemoryContext stream_runtime_memctx = u_sess->stream_cxt.global_obj->m_streamRuntimeContext; Assert(stream_runtime_memctx != NULL); @@ -2076,25 +2183,27 @@ StreamState* BuildStreamRuntime(Stream* node, EState* estate, int eflags) MemoryContext current_memctx = MemoryContextSwitchTo(recursive_runtime_memctx); stream_state = makeNode(StreamState); - /* Swith back to current memory context */ + /* 鍒囨崲鍥炲綋鍓嶅唴瀛樹笂涓嬫枃 */ MemoryContextSwitchTo(current_memctx); } else { stream_state = makeNode(StreamState); } + /* 璁剧疆 StreamState 鐨勫熀鏈俊鎭 */ stream_state->ss.ps.plan = (Plan*)node; stream_state->ss.ps.state = estate; + /* 鍒濆鍖栨墽琛岃妭鐐圭殑缁撴灉鍏冪粍鎻掓Ы */ ExecInitResultTupleSlot(estate, &stream_state->ss.ps); if (node->scan.plan.targetlist) { TupleDesc typeInfo = ExecTypeFromTL(node->scan.plan.targetlist, false); ExecSetSlotDescriptor(stream_state->ss.ps.ps_ResultTupleSlot, typeInfo); } else { - /* In case there is no target list, force its creation */ + /* 濡傛灉娌℃湁鐩爣鍒楄〃锛屽垯寮哄埗鍒涘缓 */ ExecAssignResultTypeFromTL(&stream_state->ss.ps); } - /* Set up underlying execution nodes on coordinator nodes */ + /* 鍦ㄥ崗璋冭妭鐐逛笂璁剧疆搴曞眰鎵ц鑺傜偣 */ #ifdef ENABLE_MULTIPLE_NODES if (IS_PGXC_COORDINATOR) { #else @@ -2106,11 +2215,11 @@ StreamState* BuildStreamRuntime(Stream* node, EState* estate, int eflags) if (outerPlan(node)) outerPlanState(stream_state) = ExecInitNode(outerPlan(node), estate, eflags); } else { - /* Right tree should be null. */ + /* 鍙冲瓙鏍戝簲璇ヤ负绌恒 */ Assert(innerPlan(node) == NULL); } - /* Stream runtime only set up on datanode. */ + /* Stream 杩愯鏃朵粎鍦ㄦ暟鎹妭鐐逛笂璁剧疆 */ if (IS_PGXC_DATANODE) SetupStreamRuntime(stream_state); @@ -2124,8 +2233,10 @@ StreamState* ExecInitStream(Stream* node, EState* estate, int eflags) { StreamState* state = NULL; + /* 鏋勫缓 StreamState 缁撴瀯 */ state = BuildStreamRuntime(node, estate, eflags); + /* 鍒嗛厤 Stream 缂撳啿鍖哄唴瀛橈紝骞跺垵濮嬪寲鐩稿叧鍙傛暟 */ state->buf.msg = (char*)palloc(STREAM_BUF_INIT_SIZE); state->buf.len = 0; state->buf.size = STREAM_BUF_INIT_SIZE; @@ -2133,12 +2244,14 @@ StreamState* ExecInitStream(Stream* node, EState* estate, int eflags) state->vector_output = false; state->StreamScan = ScanStreamByLibcomm; + /* 濡傛灉 Stream 鏄湰鍦拌妭鐐癸紝浣跨敤鍐呭瓨鎵弿鍑芥暟 */ if (STREAM_IS_LOCAL_NODE(node->smpDesc.distriType)) { state->StreamScan = ScanMemoryStream; TupleDesc typeInfo = ExecTypeFromTL(node->scan.plan.targetlist, false); + /* 鍒嗛厤 TupleVector 缁撴瀯鍜屾彃妲藉唴瀛 */ state->tempTupleVec = (TupleVector*)palloc0(sizeof(TupleVector)); - state->tempTupleVec->tupleVector = (TupleTableSlot**)palloc0(sizeof(TupleTableSlot*) * (TupleVectorMaxSize)); + state->tempTupleVec->tupleVector = (TupleTableSlot**)palloc0(sizeof(TupleTableSlot*) * TupleVectorMaxSize); for (int j = 0; j < TupleVectorMaxSize; j++) { state->tempTupleVec->tupleVector[j] = MakeTupleTableSlot(false); @@ -2146,12 +2259,13 @@ StreamState* ExecInitStream(Stream* node, EState* estate, int eflags) } } + /* 璁剧疆 StreamState 鐨勫洖璋冨嚱鏁板拰鍙傛暟 */ state->StreamDeserialize = GetTupleFromConnBuffer; state->recvDataLen = 0; state->type = node->type; state->receive_message = false; - /* create stream controller */ + /* 鍒涘缓 Stream 鎺у埗鍣 */ if (NeedSetupSyncUpController(state->ss.ps.plan)) { StreamController* controller = (StreamController*)u_sess->stream_cxt.global_obj->GetSyncController(node->scan.plan.plan_node_id); @@ -2170,10 +2284,11 @@ StreamState* ExecInitStream(Stream* node, EState* estate, int eflags) TupleTableSlot* ExecStream(StreamState* node) { + /* 濡傛灉鑺傜偣鏈噯澶囧ソ锛岃繘琛屽噯澶囧伐浣滐紝鍖呮嫭鍙戦佽姹傚拰鍒濆鍖栨帓搴 */ if (unlikely(node->isReady == false)) { StreamPrepareRequest(node); - /* merge sort */ + /* 濡傛灉鑺傜偣鏈夋帓搴忔搷浣滐紝鍒濆鍖栨帓搴 */ if (((Stream*)(node->ss.ps.plan))->sort != NULL) { InitStreamMergeSort(node); } @@ -2181,10 +2296,15 @@ TupleTableSlot* ExecStream(StreamState* node) node->receive_message = true; + /* 璋冪敤鑺傜偣鐨勬壂鎻忓嚱鏁帮紝澶勭悊鏁版嵁娴 */ if (node->StreamScan(node)) { + /* 鎵弿鎴愬姛锛岃繑鍥炵粨鏋滃厓缁勬彃妲 */ return node->ss.ps.ps_ResultTupleSlot; } else { - /* Finish receiving data from producers, can set network perf data now. */ + /* + * 鏁版嵁鎺ユ敹瀹屾垚锛屽彲浠ヨ缃綉缁滄ц兘鏁版嵁銆 + * 濡傛灉鏈夋ц兘缁熻淇℃伅锛屽垯璋冪敤鎺ュ彛璁剧疆缃戠粶鎬ц兘鏁版嵁銆 + */ if (HAS_INSTR(&node->ss, false)) { u_sess->instr_cxt.global_instr->SetNetWork(node->ss.ps.plan->plan_node_id, *node->spill_size); } @@ -2203,26 +2323,23 @@ TupleTableSlot* ExecStream(StreamState* node) */ void ExecEarlyDeinitConsumer(PlanState* node) { - /* A Coordinator has no stream thread, so do not bother about that */ + /* 鍗忚皟鑺傜偣娌℃湁娴佺嚎绋嬶紝涓嶉渶瑕佸鐞 */ if (IS_PGXC_COORDINATOR) return; - /* Exit if skip early deinit consumer */ + /* 濡傛灉璁剧疆浜嗚烦杩囨彁鍓嶉噴鏀炬秷璐硅呯殑鏍囧織锛岀洿鎺ヨ繑鍥 */ if (node->state->es_skip_early_deinit_consumer) return; + /* 鏍规嵁鑺傜偣绫诲瀷鎵ц鐩稿簲鐨勬搷浣 */ switch (nodeTag(node)) { case T_StreamState: case T_VecStreamState: { - /* - * When the consumer is responsible for sync cluster steps we do not do - * real consumer-deInit, just consumer its data length - */ + /* 濡傛灉鑺傜偣璐熻矗鍚屾闆嗙兢姝ラ锛屽垯涓嶆墽琛岀湡姝g殑娑堣垂鑰呴噴鏀炬搷浣滐紝鍙竻绌烘暟鎹暱搴 */ if (EXEC_IN_RECURSIVE_MODE(node->plan)) { ((StreamState*)node)->buf.len = 0; - /* When the StreamState node under recursive union do not execute, we should receive 'Z' message - in case the connections is blocking */ + /* 褰揝treamState鑺傜偣鍦ㄩ掑綊鑱斿悎涓嬩笉鎵ц鏃讹紝搴旇鎺ユ敹'Z'娑堟伅浠ラ槻姝㈣繛鎺ラ樆濉 */ if (!((StreamState*)node)->receive_message) { StreamNodeGroup* stream_nodegroup = u_sess->stream_cxt.global_obj; stream_nodegroup->ConsumerNodeStreamMessage((StreamState*)node); @@ -2239,6 +2356,7 @@ void ExecEarlyDeinitConsumer(PlanState* node) case T_AppendState: case T_VecAppendState: { AppendState* appendState = (AppendState*)node; + /* 閫掑綊璋冪敤鎵鏈夊瓙璁″垝鐨勬彁鍓嶉噴鏀炬搷浣 */ for (int planNo = 0; planNo < appendState->as_nplans; planNo++) { ExecEarlyDeinitConsumer(appendState->appendplans[planNo]); } @@ -2247,6 +2365,7 @@ void ExecEarlyDeinitConsumer(PlanState* node) case T_VecModifyTableState: case T_DistInsertSelectState: { ModifyTableState* mt = (ModifyTableState*)node; + /* 閫掑綊璋冪敤鎵鏈夊瓙璁″垝鐨勬彁鍓嶉噴鏀炬搷浣 */ for (int planNo = 0; planNo < mt->mt_nplans; planNo++) { ExecEarlyDeinitConsumer(mt->mt_plans[planNo]); } @@ -2259,11 +2378,13 @@ void ExecEarlyDeinitConsumer(PlanState* node) } break; case T_MergeAppendState: { MergeAppendState* ma = (MergeAppendState*)node; + /* 閫掑綊璋冪敤鎵鏈夊瓙璁″垝鐨勬彁鍓嶉噴鏀炬搷浣 */ for (int planNo = 0; planNo < ma->ms_nplans; planNo++) { ExecEarlyDeinitConsumer(ma->mergeplans[planNo]); } } break; default: + /* 閫掑綊璋冪敤澶栭儴鍜屽唴閮ㄥ瓙璁″垝鐨勬彁鍓嶉噴鏀炬搷浣 */ if (outerPlanState(node)) { ExecEarlyDeinitConsumer(outerPlanState(node)); } @@ -2275,19 +2396,79 @@ void ExecEarlyDeinitConsumer(PlanState* node) } } -void ExecEndStream(StreamState* node) +void ExecEarlyDeinitConsumer(PlanState* node) { - if (IS_PGXC_DATANODE && node->consumer) - node->consumer->deInit(); -#ifndef ENABLE_MULTIPLE_NODES - if (u_sess->stream_cxt.global_obj) { - u_sess->stream_cxt.global_obj->SigStreamThreadClose(); - } -#endif - PlanState* outer_plan = outerPlanState(node); + /* 鍗忚皟鑺傜偣娌℃湁娴佺嚎绋嬶紝涓嶉渶瑕佸鐞 */ + if (IS_PGXC_COORDINATOR) + return; - if (outer_plan != NULL) - ExecEndNode(outer_plan); + /* 濡傛灉璁剧疆浜嗚烦杩囨彁鍓嶉噴鏀炬秷璐硅呯殑鏍囧織锛岀洿鎺ヨ繑鍥 */ + if (node->state->es_skip_early_deinit_consumer) + return; + + /* 鏍规嵁鑺傜偣绫诲瀷鎵ц鐩稿簲鐨勬搷浣 */ + switch (nodeTag(node)) { + case T_StreamState: + case T_VecStreamState: { + /* 濡傛灉鑺傜偣璐熻矗鍚屾闆嗙兢姝ラ锛屽垯涓嶆墽琛岀湡姝g殑娑堣垂鑰呴噴鏀炬搷浣滐紝鍙竻绌烘暟鎹暱搴 */ + if (EXEC_IN_RECURSIVE_MODE(node->plan)) { + ((StreamState*)node)->buf.len = 0; + + /* 褰揝treamState鑺傜偣鍦ㄩ掑綊鑱斿悎涓嬩笉鎵ц鏃讹紝搴旇鎺ユ敹'Z'娑堟伅浠ラ槻姝㈣繛鎺ラ樆濉 */ + if (!((StreamState*)node)->receive_message) { + StreamNodeGroup* stream_nodegroup = u_sess->stream_cxt.global_obj; + stream_nodegroup->ConsumerNodeStreamMessage((StreamState*)node); + + ((StreamState*)node)->isReady = false; + ((StreamState*)node)->receive_message = true; + } + } else { + ((StreamState*)node)->consumer->deInit(); + } + + return; + } + case T_AppendState: + case T_VecAppendState: { + AppendState* appendState = (AppendState*)node; + /* 閫掑綊璋冪敤鎵鏈夊瓙璁″垝鐨勬彁鍓嶉噴鏀炬搷浣 */ + for (int planNo = 0; planNo < appendState->as_nplans; planNo++) { + ExecEarlyDeinitConsumer(appendState->appendplans[planNo]); + } + } break; + case T_ModifyTableState: + case T_VecModifyTableState: + case T_DistInsertSelectState: { + ModifyTableState* mt = (ModifyTableState*)node; + /* 閫掑綊璋冪敤鎵鏈夊瓙璁″垝鐨勬彁鍓嶉噴鏀炬搷浣 */ + for (int planNo = 0; planNo < mt->mt_nplans; planNo++) { + ExecEarlyDeinitConsumer(mt->mt_plans[planNo]); + } + } break; + case T_SubqueryScanState: + case T_VecSubqueryScanState: { + SubqueryScanState* ss = (SubqueryScanState*)node; + if (ss->subplan) + ExecEarlyDeinitConsumer(ss->subplan); + } break; + case T_MergeAppendState: { + MergeAppendState* ma = (MergeAppendState*)node; + /* 閫掑綊璋冪敤鎵鏈夊瓙璁″垝鐨勬彁鍓嶉噴鏀炬搷浣 */ + for (int planNo = 0; planNo < ma->ms_nplans; planNo++) { + ExecEarlyDeinitConsumer(ma->mergeplans[planNo]); + } + } break; + default: + /* 閫掑綊璋冪敤澶栭儴鍜屽唴閮ㄥ瓙璁″垝鐨勬彁鍓嶉噴鏀炬搷浣 */ + if (outerPlanState(node)) { + ExecEarlyDeinitConsumer(outerPlanState(node)); + } + + if (innerPlanState(node)) { + ExecEarlyDeinitConsumer(innerPlanState(node)); + } + break; + } } /* @@ -2298,10 +2479,10 @@ void ExecEndStream(StreamState* node) */ bool executorEarlyStop() { - /* Check if query already been stopped. */ + /* 妫鏌ユ煡璇㈡槸鍚﹀凡琚仠姝€ */ if (u_sess->exec_cxt.executorStopFlag == true) return true; - /* Check if query already canceled due to error or cancel/die signal. */ + /* 妫鏌ユ煡璇㈡槸鍚﹀洜閿欒銆佸彇娑堟垨缁堟淇″彿鑰岃鍙栨秷銆 */ else if (u_sess->stream_cxt.global_obj && u_sess->stream_cxt.global_obj->isQueryCanceled()) return true; else @@ -2339,7 +2520,7 @@ void ExecReSetStream(StreamState* node) resetLocalStreamContext(node->consumer->getSharedContext()); } - /* We dont't have to do specific operations for first level */ + /* 瀵逛簬绗竴灞傜骇鐨勬祦鑺傜偣锛屾垜浠笉闇瑕佹墽琛岀壒瀹氱殑鎿嶄綔 */ if (IsFirstLevelStreamStateNode(node)) { return; } @@ -2355,4 +2536,4 @@ void ExecReSetStream(StreamState* node) StreamNodeGroup::SyncConsumerNextPlanStep(stream_plan_nodeid, 0); } return; -} +} \ No newline at end of file diff --git a/src/gausskernel/process/stream/streamConsumer.cpp b/src/gausskernel/process/stream/streamConsumer.cpp index 85d801d56..1471b6093 100755 --- a/src/gausskernel/process/stream/streamConsumer.cpp +++ b/src/gausskernel/process/stream/streamConsumer.cpp @@ -14,7 +14,7 @@ * ------------------------------------------------------------------------- * * streamConsumer.cpp - * Support methods for class StreamConsumer. + * 鏀寔StreamConsumer鐨勬柟娉 * * IDENTIFICATION * src/gausskernel/process/stream/streamConsumer.cpp @@ -36,20 +36,22 @@ extern GlobalNodeDefinition* global_node_definition; +// 鏋勯犲嚱鏁帮紝鍒濆鍖朣treamConsumer瀵硅薄 StreamConsumer::StreamConsumer(MemoryContext context) : StreamObj(context, STREAM_CONSUMER) { - m_sharedContext = NULL; - m_originProducerNodeList = NULL; - m_ready = false; - m_expectProducer = NULL; - m_currentProducerNum = 0; + m_sharedContext = NULL; // 鍒濆鍖栧叡浜唴瀛樹笂涓嬫枃涓篘ULL + m_originProducerNodeList = NULL; // 鍒濆鍖栧師濮嬬敓浜ц呰妭鐐瑰垪琛ㄤ负NULL + m_ready = false; // 鍒濆鍖栧氨缁姸鎬佷负false + m_expectProducer = NULL; // 鍒濆鍖栭鏈熺敓浜ц呬负NULL + m_currentProducerNum = 0; // 鍒濆鍖栧綋鍓嶇敓浜ц呮暟閲忎负0 } +// 鏋愭瀯鍑芥暟锛岄噴鏀維treamConsumer瀵硅薄鐨勮祫婧 StreamConsumer::~StreamConsumer() { - m_originProducerNodeList = NULL; - m_expectProducer = NULL; - m_sharedContext = NULL; + m_originProducerNodeList = NULL; // 灏嗗師濮嬬敓浜ц呰妭鐐瑰垪琛ㄨ涓篘ULL + m_expectProducer = NULL; // 灏嗛鏈熺敓浜ц呰涓篘ULL + m_sharedContext = NULL; // 灏嗗叡浜唴瀛樹笂涓嬫枃璁句负NULL } /* @@ -61,12 +63,16 @@ StreamConsumer::~StreamConsumer() * @param[IN] transType: transport type * @return: void */ + /* + 鍑芥暟閫氳繃鍙傛暟璁剧疆浜哠treamConsumer瀵硅薄鐨勫悇涓垚鍛樺彉閲忥紝鍖呮嫭浼犺緭绫诲瀷銆佸叡浜笂涓嬫枃銆佷紶杈撳璞$瓑,杩樻牴鎹紶鍏ョ殑鎵ц鐢熶骇鑰呰妭鐐逛俊鎭紝 + 鍒濆鍖栦簡棰勬湡鐨勭敓浜ц呬俊鎭紝骞跺皢鍏跺姞鍏ュ搱甯岃〃涓 + */ void StreamConsumer::init(StreamKey key, List* execProducerNodes, ParallelDesc desc, StreamTransType transType, StreamSharedContext* sharedContext) { int i = 0; bool found = false; - + int producerNum = 0; AutoMutexLock streamLock(&m_streamInfoLock); AutoMutexLock copyLock(&nodeDefCopyLock); @@ -79,18 +85,19 @@ void StreamConsumer::init(StreamKey key, List* execProducerNodes, ParallelDesc d Assert(producerNum > 0); - m_parallel_desc = desc; - m_currentProducerNum = 0; - m_connNum = producerNum; - m_key = key; - m_ready = false; - m_transtype = transType; - m_sharedContext = sharedContext; - m_transport = (StreamTransport**)MemoryContextAllocZero(m_memoryCxt, producerNum * sizeof(StreamTransport*)); - m_expectProducer = (StreamConnInfo*)MemoryContextAllocZero(m_memoryCxt, producerNum * sizeof(StreamConnInfo)); + m_parallel_desc = desc; // 璁剧疆骞惰鎻忚堪绗 + m_currentProducerNum = 0; // 褰撳墠鐢熶骇鑰呮暟閲忕疆闆 + m_connNum = producerNum; // 杩炴帴鏁伴噺绛変簬鐢熶骇鑰呮暟閲 + m_key = key; // 璁剧疆StreamKey + m_ready = false; // 鍒濆鐘舵佷负鏈氨缁 + m_transtype = transType; // 璁剧疆浼犺緭绫诲瀷 + m_sharedContext = sharedContext; // 鍏变韩涓婁笅鏂 + m_transport = (StreamTransport**)MemoryContextAllocZero(m_memoryCxt, producerNum * sizeof(StreamTransport*)); // 鍒嗛厤浼犺緭瀵硅薄鏁扮粍鍐呭瓨 + m_expectProducer = (StreamConnInfo*)MemoryContextAllocZero(m_memoryCxt, producerNum * sizeof(StreamConnInfo)); // 鍒嗛厤棰勬湡鐢熶骇鑰呬俊鎭唴瀛 - /* Initialize the origin nodelist */ + /* 鍒濆鍖栧師濮嬬敓浜ц呰妭鐐瑰垪琛 */ m_originProducerNodeList = NIL; + #ifdef ENABLE_MULTIPLE_NODES copyLock.lock(); ListCell* nodelistCell = NULL; @@ -112,6 +119,8 @@ void StreamConsumer::init(StreamKey key, List* execProducerNodes, ParallelDesc d } copyLock.unLock(); #endif + + // 鍒濆鍖栦紶杈撳璞℃暟缁 for (i = 0; i < producerNum; i++) { int nodeNameLen = 0; libcommaddrinfo* libcommaddr = NULL; @@ -131,7 +140,7 @@ void StreamConsumer::init(StreamKey key, List* execProducerNodes, ParallelDesc d scomm->m_addr->streamKey.consumerSmpId = m_key.smpIdentifier; } - HOLD_INTERRUPTS(); /* Add this macro for double safety. */ + HOLD_INTERRUPTS(); // 鍔犲叆姝ゅ畯浠ョ‘淇濆畨鍏ㄦ streamLock.lock(); AutoContextSwitch streamInfoCxtGuard(StreamInfoContext); @@ -139,8 +148,7 @@ void StreamConsumer::init(StreamKey key, List* execProducerNodes, ParallelDesc d StreamElement* element = (StreamElement*)hash_search(m_streamInfoTbl, &m_key, HASH_ENTER, &found); if (element == NULL) { streamLock.unLock(); - ereport( - ERROR, (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("Failed to create stream element due to out of memory"))); + ereport(ERROR, (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("Failed to create stream element due to out of memory"))); } if (found == false) { @@ -154,16 +162,15 @@ void StreamConsumer::init(StreamKey key, List* execProducerNodes, ParallelDesc d if (NULL == element->value) { hash_search(m_streamInfoTbl, &key, HASH_REMOVE, NULL); streamLock.unLock(); - ereport(ERROR, - (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("Failed to generate stream element due to out of memory"))); + ereport(ERROR, (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("Failed to generate stream element due to out of memory"))); } element->value->connNum = 0; element->value->connInfoSize = 0; - /* No need to allocate the array size. */ + /* 涓嶉渶瑕佸垎閰嶆暟缁勫ぇ灏忋 */ element->value->connInfo = NULL; } else { - /* WTF? find a duplicate element in the hash table. */ + /* 鍦ㄥ搱甯岃〃涓壘鍒伴噸澶嶇殑鍏冪礌銆 */ if (element->value == NULL || element->value->consumer) { streamLock.unLock(); ereport(ERROR, @@ -173,7 +180,7 @@ void StreamConsumer::init(StreamKey key, List* execProducerNodes, ParallelDesc d } } - /* Found true means some information has not been updated, protected by streamLock. */ + /* 鎵惧埌涓虹湡琛ㄧず鏌愪簺淇℃伅灏氭湭鏇存柊锛岀敱streamLock淇濇姢銆 */ if (found == true) { Assert(element->value->connInfo != NULL); updateTransportInfo(element->value); @@ -215,65 +222,64 @@ void StreamConsumer::init(StreamKey key, List* execProducerNodes, ParallelDesc d */ void StreamConsumer::deInit() { - AutoMutexLock streamHashLock(&m_streamInfoLock); + AutoMutexLock streamHashLock(&m_streamInfoLock); // 鍔犻攣锛屼繚鎶ゅ搱甯岃〃鎿嶄綔 StreamElement* delinfo = NULL; - HOLD_INTERRUPTS(); - streamHashLock.lock(); + HOLD_INTERRUPTS(); // 鎸佹湁涓柇锛岀姝腑鏂彂鐢 + streamHashLock.lock(); // 鍔犻攣锛屼繚鎶ゅ搱甯岃〃鎿嶄綔 - /* Do not need de init. */ - if (m_init == false) { - if (m_threadSyncObjInit == true) { - pthread_mutex_destroy(&m_mutex); - pthread_cond_destroy(&m_cond); - m_threadSyncObjInit = false; + /* 涓嶉渶瑕佸幓鍒濆鍖栥 */ + if (m_init == false) { // 濡傛灉鏈垵濮嬪寲 + if (m_threadSyncObjInit == true) { // 濡傛灉绾跨▼鍚屾瀵硅薄宸茬粡鍒濆鍖 + pthread_mutex_destroy(&m_mutex); // 閿姣佷簰鏂ラ攣 + pthread_cond_destroy(&m_cond); // 閿姣佹潯浠跺彉閲 + m_threadSyncObjInit = false; // 鏍囪绾跨▼鍚屾瀵硅薄鏈垵濮嬪寲 } - streamHashLock.unLock(); - RESUME_INTERRUPTS(); + streamHashLock.unLock(); // 瑙i攣锛岄噴鏀鹃攣 + RESUME_INTERRUPTS(); // 鎭㈠涓柇 return; } - releaseCommStream(); + releaseCommStream(); // 閲婃斁閫氫俊娴 - /* Close local stream connection. */ + /* 鍏抽棴鏈湴娴佽繛鎺ャ */ if (NULL != m_sharedContext) { - gs_memory_close_conn(m_sharedContext, m_connNum, u_sess->stream_cxt.smp_id); + gs_memory_close_conn(m_sharedContext, m_connNum, u_sess->stream_cxt.smp_id); // 鍏抽棴鍏变韩鍐呭瓨涓殑杩炴帴 } - if (m_ready || u_sess->stream_cxt.dummy_thread == true) { - delinfo = (StreamElement*)hash_search(m_streamInfoTbl, &m_key, HASH_REMOVE, NULL); - if (delinfo != NULL) { + if (m_ready || u_sess->stream_cxt.dummy_thread == true) { // 濡傛灉宸茬粡灏辩华鎴栬呮槸铏氭嫙绾跨▼ + delinfo = (StreamElement*)hash_search(m_streamInfoTbl, &m_key, HASH_REMOVE, NULL); // 浠庡搱甯岃〃涓Щ闄よ娑堣垂鑰呬俊鎭 + if (delinfo != NULL) { // 濡傛灉鎵惧埌浜嗘秷璐硅呬俊鎭 if (delinfo->value->connInfo != NULL) { - pfree_ext(delinfo->value->connInfo); + pfree_ext(delinfo->value->connInfo); // 閲婃斁杩炴帴淇℃伅鍐呭瓨 delinfo->value->connInfo = NULL; } - pfree_ext(delinfo->value); + pfree_ext(delinfo->value); // 閲婃斁娑堣垂鑰呬俊鎭唴瀛 delinfo->value = NULL; } } else { /* - * set flag to release net port in case some producer not ready and element - * in stream info hash table can not get removed in wakeUpConsumer, - * or consumer get canceled when waiting producer ready. + * 璁剧疆鏍囧織浠ラ噴鏀剧綉缁滅鍙o紝鍦ㄦ煇浜涚敓浜ц呮湭灏辩华鐨勬儏鍐典笅锛 + * 鎴栬呭湪绛夊緟鐢熶骇鑰呭氨缁椂锛屽鏋滄秷璐硅呰鍙栨秷銆 */ - u_sess->stream_cxt.global_obj->setNeedClean(true); + u_sess->stream_cxt.global_obj->setNeedClean(true); // 璁剧疆闇瑕佹竻鐞嗘爣蹇 } - if (m_threadSyncObjInit == true) { - pthread_mutex_destroy(&m_mutex); - pthread_cond_destroy(&m_cond); - m_threadSyncObjInit = false; + if (m_threadSyncObjInit == true) { // 濡傛灉绾跨▼鍚屾瀵硅薄宸茬粡鍒濆鍖 + pthread_mutex_destroy(&m_mutex); // 閿姣佷簰鏂ラ攣 + pthread_cond_destroy(&m_cond); // 閿姣佹潯浠跺彉閲 + m_threadSyncObjInit = false; // 鏍囪绾跨▼鍚屾瀵硅薄鏈垵濮嬪寲 } - m_init = false; - streamHashLock.unLock(); + m_init = false; // 鏍囪娑堣垂鑰呮湭鍒濆鍖 + streamHashLock.unLock(); // 瑙i攣锛岄噴鏀鹃攣 - /* Cleanup the original producer list */ - m_originProducerNodeList = NIL; + /* 娓呯悊鍘熷鐢熶骇鑰呭垪琛 */ + m_originProducerNodeList = NIL; // 娓呯┖鍘熷鐢熶骇鑰呰妭鐐瑰垪琛 - RESUME_INTERRUPTS(); + RESUME_INTERRUPTS(); // 鎭㈠涓柇 } /* @@ -283,12 +289,13 @@ void StreamConsumer::deInit() */ void StreamConsumer::releaseCommStream() { - if (m_transport != NULL) { - for (int i = 0; i < m_connNum; i++) { - Assert(t_thrd.int_cxt.ImmediateInterruptOK == false); - StreamCOMM* scomm = (StreamCOMM*)m_transport[i]; - if (scomm != NULL) - scomm->release(); + if (m_transport != NULL) { // 濡傛灉浼犺緭瀵硅薄鏁扮粍涓嶄负绌 + for (int i = 0; i < m_connNum; i++) { // 閬嶅巻鎵鏈夎繛鎺 + Assert(t_thrd.int_cxt.ImmediateInterruptOK == false); // 鏂█褰撳墠涓嶅彲涓柇 + + StreamCOMM* scomm = (StreamCOMM*)m_transport[i]; // 鑾峰彇褰撳墠杩炴帴鐨勯氫俊瀵硅薄 + if (scomm != NULL) // 濡傛灉閫氫俊瀵硅薄涓嶄负绌 + scomm->release(); // 閲婃斁閫氫俊璧勬簮 } } } @@ -301,11 +308,11 @@ void StreamConsumer::releaseCommStream() */ int StreamConsumer::getNodeIdx(const char* nodename) { - for (int i = 0; i < m_connNum; i++) { - if (pg_strncasecmp(m_expectProducer[i].nodeName, nodename, strlen(nodename)) == 0) - return m_expectProducer[i].nodeIdx; + for (int i = 0; i < m_connNum; i++) { // 閬嶅巻鎵鏈夌敓浜ц呰妭鐐 + if (pg_strncasecmp(m_expectProducer[i].nodeName, nodename, strlen(nodename)) == 0) // 濡傛灉鑺傜偣鍚嶅尮閰 + return m_expectProducer[i].nodeIdx; // 杩斿洖鑺傜偣绱㈠紩 } - return -1; + return -1; // 濡傛灉鏈壘鍒板尮閰嶈妭鐐癸紝杩斿洖-1 } /* @@ -318,17 +325,17 @@ void StreamConsumer::findUnconnectProducer(StringInfo str) { bool found = false; - for (int j = 0; j < m_connNum; j++) { + for (int j = 0; j < m_connNum; j++) { // 閬嶅巻鎵鏈夐鏈熺殑鐢熶骇鑰呰妭鐐 found = false; - for (int i = 0; i < m_currentProducerNum; i++) { - if (strcmp(m_expectProducer[j].nodeName, m_transport[i]->m_nodeName) == 0) { - found = true; + for (int i = 0; i < m_currentProducerNum; i++) { // 閬嶅巻褰撳墠宸茶繛鎺ョ殑鐢熶骇鑰呰妭鐐 + if (strcmp(m_expectProducer[j].nodeName, m_transport[i]->m_nodeName) == 0) { // 濡傛灉鎵惧埌鍖归厤鑺傜偣 + found = true; // 鏍囪涓哄凡杩炴帴 break; } } - if (!found) - appendStringInfo(str, " %s", m_expectProducer[j].nodeName); + if (!found) // 濡傛灉鏈壘鍒板尮閰嶈妭鐐癸紙鍗虫湭杩炴帴锛 + appendStringInfo(str, " %s", m_expectProducer[j].nodeName); // 灏嗚妭鐐瑰悕杩藉姞鍒板瓧绗︿覆涓 } } @@ -342,21 +349,21 @@ int StreamConsumer::getFirstUnconnectedProducerNodeIdx() bool found = false; int nodeIdx = -1; - for (int j = 0; j < m_connNum; j++) { + for (int j = 0; j < m_connNum; j++) { // 閬嶅巻鎵鏈夐鏈熺殑鐢熶骇鑰呰妭鐐 found = false; - for (int i = 0; i < m_currentProducerNum; i++) { - if (strcmp(m_expectProducer[j].nodeName, m_transport[i]->m_nodeName) == 0) { - found = true; + for (int i = 0; i < m_currentProducerNum; i++) { // 閬嶅巻褰撳墠宸茶繛鎺ョ殑鐢熶骇鑰呰妭鐐 + if (strcmp(m_expectProducer[j].nodeName, m_transport[i]->m_nodeName) == 0) { // 濡傛灉鎵惧埌鍖归厤鑺傜偣 + found = true; // 鏍囪涓哄凡杩炴帴 break; } } - if (!found) { - nodeIdx = m_expectProducer[j].nodeIdx; + if (!found) { // 濡傛灉鏈壘鍒板尮閰嶈妭鐐癸紙鍗虫湭杩炴帴锛 + nodeIdx = m_expectProducer[j].nodeIdx; // 璁剧疆鏈繛鎺ヨ妭鐐圭殑绱㈠紩 break; } } - return nodeIdx; + return nodeIdx; // 杩斿洖绗竴涓湭杩炴帴鑺傜偣鐨勭储寮 } /* @@ -366,7 +373,7 @@ int StreamConsumer::getFirstUnconnectedProducerNodeIdx() */ void StreamConsumer::waitProducerReady() { - /* For local stream, producer will never connect to consumer. Consumer is ready, just return. */ + /* 瀵逛簬鏈湴娴侊紝鐢熶骇鑰呮案杩滀笉浼氳繛鎺ュ埌娑堣垂鑰呫傛秷璐硅呭噯澶囧ソ浜嗭紝鐩存帴杩斿洖銆 */ if (STREAM_IS_LOCAL_NODE(m_parallel_desc.distriType)) { m_ready = true; return; @@ -384,7 +391,7 @@ void StreamConsumer::waitProducerReady() Assert(t_thrd.int_cxt.ImmediateInterruptOK == false); streamLock.lock(); - /* 900s timeout. */ + /* 900绉掔殑瓒呮椂鏃堕棿銆 */ struct timespec timer; int ret; int ntimes = 1; @@ -419,11 +426,11 @@ void StreamConsumer::waitProducerReady() ereport(ERROR, (errmodule(MOD_STREAM), errcode(ERRCODE_CONNECTION_TIMED_OUT), - errmsg("Distribute query initializing network connection timeout. un-connected nodes: %s", + errmsg("Distribute query initializing network connection timeout. un-connected nodes锛%s", str.data))); } - /* Check for interrupts.(cancel signal?). */ + /* 妫鏌ヤ腑鏂紙鍙栨秷淇″彿锛燂級銆 */ CHECK_FOR_INTERRUPTS(); streamLock.lock(); } @@ -442,6 +449,7 @@ void StreamConsumer::waitProducerReady() return; } + /* * @Description: Wake up consumer and let it work * @@ -465,7 +473,7 @@ bool StreamConsumer::wakeUpConsumerCallBack(CommStreamKey commKey, StreamConnInf streamLock.lock(); - /* Check if can accept connection now */ + /* 妫鏌ユ槸鍚﹀彲浠ユ帴鍙楄繛鎺ャ */ if (StreamNodeGroup::checkStreamConnectPermission(key.queryId) == false) { streamLock.unLock(); return false; @@ -474,9 +482,9 @@ bool StreamConsumer::wakeUpConsumerCallBack(CommStreamKey commKey, StreamConnInf AutoContextSwitch streamInfoCxtGuard(StreamInfoContext); /* - * Register me in the global consumer table if the consumer thread has not been started. - * Libcomm r_flow_ctrl thread call this, must not use palloc and elog. - * so use isLibcommThread flag, return false where malloc failed. + * 濡傛灉娑堣垂鑰呯嚎绋嬪皻鏈惎鍔紝鍒欏湪鍏ㄥ眬娑堣垂鑰呰〃涓敞鍐屾垜銆 + * Libcomm r_flow_ctrl绾跨▼璋冪敤杩欎釜鍑芥暟锛屼笉鑳戒娇鐢╬alloc鍜宔log銆 + * 鎵浠ヤ娇鐢╥sLibcommThread鏍囧織锛屽湪malloc澶辫触鏃惰繑鍥瀎alse銆 */ StreamElement* element = (StreamElement*)hash_search(m_streamInfoTbl, &key, HASH_ENTER, &found); if (element == NULL) { @@ -485,7 +493,7 @@ bool StreamConsumer::wakeUpConsumerCallBack(CommStreamKey commKey, StreamConnInf return false; } - /* If StreamElement not register by the consumer thread, we save the information. */ + /* 濡傛灉StreamElement灏氭湭鐢辨秷璐硅呯嚎绋嬫敞鍐岋紝鍒欎繚瀛樹俊鎭 */ if (found == false) { element->value = (StreamValue*)palloc0_noexcept(sizeof(StreamValue)); if (NULL == element->value) { @@ -516,7 +524,7 @@ bool StreamConsumer::wakeUpConsumerCallBack(CommStreamKey commKey, StreamConnInf element->value->consumer = NULL; } else { if (element->value) { - /* Consumer thread has not been registered yet. */ + /* 娑堣垂鑰呯嚎绋嬪皻鏈敞鍐屻 */ if (element->value->consumer == NULL) { element->value->connInfo[element->value->connNum].port.libcomm_layer.gsock = connInfo.port.libcomm_layer.gsock; @@ -528,7 +536,7 @@ bool StreamConsumer::wakeUpConsumerCallBack(CommStreamKey commKey, StreamConnInf element->value->connInfo[element->value->connNum].producerSmpId = connInfo.producerSmpId; element->value->connNum++; - /* Check if need realloc to remember more connection info. */ + /* 妫鏌ユ槸鍚﹂渶瑕侀噸鏂板垎閰嶅唴瀛樹互璁颁綇鏇村鐨勮繛鎺ヤ俊鎭 */ if (element->value->connNum == element->value->connInfoSize) { StreamConnInfo* new_connInfo = NULL; int new_connInfoSize = 2 * element->value->connInfoSize; @@ -557,10 +565,10 @@ bool StreamConsumer::wakeUpConsumerCallBack(CommStreamKey commKey, StreamConnInf element->value->connInfoSize = new_connInfoSize; } } else { - /* Have registered, so we update the stream info. */ + /* 宸茬粡娉ㄥ唽锛屾墍浠ユ垜浠洿鏂版祦淇℃伅銆 */ res = element->value->consumer->updateStreamCommInfo(&connInfo); - /* We can free the memory, no longer need it. */ + /* 鎴戜滑鍙互閲婃斁鍐呭瓨浜嗭紝涓嶅啀闇瑕佸畠銆 */ if (element->value->connInfo != NULL) { pfree_ext(element->value->connInfo); element->value->connInfo = NULL; @@ -588,7 +596,7 @@ bool StreamConsumer::updateStreamCommInfo(StreamConnInfo* connInfo) streamLock.lock(); - /* WTF, duplicate plan id encounter or plan error. */ + /* 鍑虹幇閲嶅鐨勮鍒扞D鎴栬鍒掗敊璇 */ if (m_currentProducerNum >= m_connNum) { streamLock.unLock(); return false; @@ -632,4 +640,4 @@ void StreamConsumer::updateTransportInfo(StreamValue* val) if (m_currentProducerNum == m_connNum) m_ready = true; } -} +} \ No newline at end of file diff --git a/src/gausskernel/process/stream/streamCore.cpp b/src/gausskernel/process/stream/streamCore.cpp index 2c50a885c..e2212b4a8 100755 --- a/src/gausskernel/process/stream/streamCore.cpp +++ b/src/gausskernel/process/stream/streamCore.cpp @@ -64,7 +64,7 @@ #include "distributelayer/streamConsumer.h" #include "storage/procsignal.h" -/* Process-wise variables. */ +/* Process-wise鍙橀噺. */ MemoryContext StreamObj::m_memoryGlobalCxt = NULL; pthread_mutex_t StreamObj::m_streamInfoLock; HTAB* StreamObj::m_streamInfoTbl = NULL; @@ -75,25 +75,27 @@ HTAB* StreamNodeGroup::m_streamNodeGroupTbl = NULL; HTAB* StreamNodeGroup::m_streamConnectSyncTbl = NULL; pthread_mutex_t StreamNodeGroup::m_streamConnectSyncLock; +// 瀹氫箟涓涓潤鎬佸嚱鏁 ConsumerNodeSyncUpMessage锛屽弬鏁板寘鎷竴涓掑綊鑱斿悎鎺у埗鍣ㄦ寚閽堛佷竴涓楠ゆ暟鍜屼竴涓祦鐘舵佹寚閽 static void ConsumerNodeSyncUpMessage(RecursiveUnionController* controller, int step, StreamState* node); +// StreamObj 绫荤殑鏋勯犲嚱鏁帮紝鎺ュ彈鍐呭瓨涓婁笅鏂囧拰娴佸璞$被鍨嬩綔涓哄弬鏁 StreamObj::StreamObj(MemoryContext context, StreamObjType type) - : m_nodeGroup(0), - m_transport(0), - m_pair(NULL), - m_type(type), - m_memoryCxt(context), - m_connNum(0), - m_nodeGroupIdx(0), - m_threadId(InvalidTid) + : m_nodeGroup(0), // 鍒濆鍖栬妭鐐圭粍 ID 涓 0 + m_transport(0), // 鍒濆鍖栦紶杈撻氶亾涓 0 + m_pair(NULL), // 鍒濆鍖栨祦瀵硅薄瀵逛负 NULL + m_type(type), // 鍒濆鍖栨祦瀵硅薄绫诲瀷 + m_memoryCxt(context), // 鍒濆鍖栧唴瀛樹笂涓嬫枃 + m_connNum(0), // 鍒濆鍖栬繛鎺ユ暟涓 0 + m_nodeGroupIdx(0), // 鍒濆鍖栬妭鐐圭粍绱㈠紩涓 0 + m_threadId(InvalidTid) // 鍒濆鍖栫嚎绋 ID 涓烘棤鏁堝 { - m_nodeId = u_sess->pgxc_cxt.PGXCNodeId; - m_streamNode = NULL; - m_init = false; - m_threadSyncObjInit = false; - m_status = STREAM_UNDEFINED; + m_nodeId = u_sess->pgxc_cxt.PGXCNodeId; // 璁剧疆鑺傜偣 ID 涓哄綋鍓嶄細璇濈殑 PGXC 鑺傜偣 ID + m_streamNode = NULL; // 鍒濆鍖栨祦鑺傜偣涓 NULL + m_init = false; // 鍒濆鍖栨爣蹇椾綅涓 false锛岃〃绀烘湭鍒濆鍖 + m_threadSyncObjInit = false; // 鍒濆鍖栫嚎绋嬪悓姝ュ璞℃爣蹇椾綅涓 false + m_status = STREAM_UNDEFINED; // 鍒濆鍖栨祦鐘舵佷负 STREAM_UNDEFINED #ifdef ENABLE_MULTIPLE_NODES - /* should not be the initial value, check the logic that coordinator send node id. */ + // 澶氳妭鐐圭幆澧冧笅锛岃妭鐐 ID 涓嶅簲璇ユ槸鍒濆鍊硷紝妫鏌ュ崗璋冨櫒鍙戦佽妭鐐 ID 鐨勯昏緫 Assert(m_nodeId != -1); #endif } @@ -162,50 +164,50 @@ void StreamObj::releaseNetPort() */ void StreamObj::releaseNetPortInHashTable() { - StreamElement* element = NULL; - AutoMutexLock streamLock(&m_streamInfoLock); - HASH_SEQ_STATUS hash_seq; + StreamElement* element = NULL; // 澹版槑 StreamElement 鎸囬拡锛岀敤浜庨亶鍘嗗搱甯岃〃 + AutoMutexLock streamLock(&m_streamInfoLock); // 鍒涘缓鑷姩浜掓枼閿侊紝纭繚绾跨▼瀹夊叏璁块棶鍝堝笇琛 + HASH_SEQ_STATUS hash_seq; // 鍝堝笇琛ㄩ亶鍘嗗簭鍒楃姸鎬 - /* Exit if hash table is not yet created */ + /* 濡傛灉鍝堝笇琛ㄥ皻鏈垱寤猴紝鍒欓鍑哄嚱鏁 */ if (NULL == m_streamInfoTbl) return; - HOLD_INTERRUPTS(); /* add this macro for double safety */ - streamLock.lock(); - hash_seq_init(&hash_seq, m_streamInfoTbl); + HOLD_INTERRUPTS(); /* 娣诲姞姝ゅ畯浠ユ彁楂樺畨鍏ㄦ */ + streamLock.lock(); // 鍔犻攣锛屽紑濮嬭闂搱甯岃〃 + hash_seq_init(&hash_seq, m_streamInfoTbl); // 鍒濆鍖栧搱甯岃〃閬嶅巻搴忓垪 - /* Sequentially search through hash table and release net port identified by u_sess->debug_query_id. */ + /* 椤哄簭閬嶅巻鍝堝笇琛紝骞堕噴鏀剧敱 u_sess->debug_query_id 鏍囪瘑鐨勭綉缁滅鍙 */ while ((element = (StreamElement*)hash_seq_search(&hash_seq)) != NULL) { - if (element->key.queryId == (uint64)u_sess->debug_query_id) { - StreamValue* sVal = element->value; - StreamKey key = element->key; + if (element->key.queryId == (uint64)u_sess->debug_query_id) { // 濡傛灉鍏冪礌鐨勬煡璇 ID 涓庡綋鍓嶄細璇濈殑 debug_query_id 鍖归厤 + StreamValue* sVal = element->value; // 鑾峰彇 StreamValue 缁撴瀯浣撴寚閽 + StreamKey key = element->key; // 鑾峰彇 StreamKey 缁撴瀯浣 if (sVal != NULL && sVal->connInfo != NULL) { - StreamConnInfo* connInfo = sVal->connInfo; - int connNum = sVal->connNum; + StreamConnInfo* connInfo = sVal->connInfo; // 鑾峰彇杩炴帴淇℃伅鏁扮粍鎸囬拡 + int connNum = sVal->connNum; // 鑾峰彇杩炴帴鏁 for (int i = 0; i < connNum; i++) { - gs_close_gsocket(&connInfo[i].port.libcomm_layer.gsock); + gs_close_gsocket(&connInfo[i].port.libcomm_layer.gsock); // 鍏抽棴缃戠粶濂楁帴瀛 } } - /* Free memory. */ + /* 閲婃斁鍐呭瓨銆*/ if (element->value != NULL) { if (element->value->connInfo != NULL) { - pfree_ext(element->value->connInfo); + pfree_ext(element->value->connInfo); // 閲婃斁杩炴帴淇℃伅鍐呭瓨 element->value->connInfo = NULL; } - pfree_ext(element->value); + pfree_ext(element->value); // 閲婃斁 StreamValue 缁撴瀯浣撳唴瀛 element->value = NULL; } - /* Remove the element left in hash table. */ - (void)hash_search(m_streamInfoTbl, &key, HASH_REMOVE, NULL); + /* 浠庡搱甯岃〃涓Щ闄ゅ墿浣欑殑鍏冪礌銆*/ + (void)hash_search(m_streamInfoTbl, &key, HASH_REMOVE, NULL); // 浠庡搱甯岃〃涓Щ闄ゅ尮閰嶇殑鍏冪礌 } } - streamLock.unLock(); - RESUME_INTERRUPTS(); + streamLock.unLock(); // 瑙i攣锛岀粨鏉熷鍝堝笇琛ㄧ殑璁块棶 + RESUME_INTERRUPTS(); // 鎭㈠涓柇澶勭悊 } /* @@ -266,7 +268,7 @@ const Stream* StreamObj::getStream() */ void StreamObj::startUp() { - HASHCTL ctl; + HASHCTL ctl; // 澹版槑鍝堝笇琛ㄦ帶鍒剁粨鏋勪綋 errno_t rc = EOK; m_memoryGlobalCxt = AllocSetContextCreate(g_instance.instance_context, @@ -274,23 +276,23 @@ void StreamObj::startUp() ALLOCSET_DEFAULT_MINSIZE, ALLOCSET_DEFAULT_INITSIZE, ALLOCSET_DEFAULT_MAXSIZE, - SHARED_CONTEXT); + SHARED_CONTEXT); // 鍒涘缓鍏ㄥ眬鍐呭瓨涓婁笅鏂 - /* init the stream info table ctl. */ - rc = memset_s(&ctl, sizeof(ctl), 0, sizeof(ctl)); + /* 鍒濆鍖栧搱甯岃〃鎺у埗缁撴瀯浣撱*/ + rc = memset_s(&ctl, sizeof(ctl), 0, sizeof(ctl)); // 灏 ctl 缁撴瀯浣撴竻闆 securec_check(rc, "\0", "\0"); - ctl.keysize = sizeof(StreamKey); - ctl.entrysize = sizeof(StreamElement); - ctl.hash = tag_hash; - ctl.hcxt = m_memoryGlobalCxt; + ctl.keysize = sizeof(StreamKey); // 璁剧疆閿殑澶у皬涓 StreamKey 缁撴瀯浣撶殑澶у皬 + ctl.entrysize = sizeof(StreamElement); // 璁剧疆鏉$洰鐨勫ぇ灏忎负 StreamElement 缁撴瀯浣撶殑澶у皬 + ctl.hash = tag_hash; // 璁剧疆鍝堝笇鍑芥暟 + ctl.hcxt = m_memoryGlobalCxt; // 璁剧疆鍝堝笇琛ㄧ殑鍐呭瓨涓婁笅鏂囦负鍏ㄥ眬鍐呭瓨涓婁笅鏂 /* - * m_streamInfoTbl is created with HASH_NOEXCEPT, - * so hash_search with HASH_ENTER don't throw when - * palloc failed. We must check whether the result is NULL. + * m_streamInfoTbl 浣跨敤 HASH_NOEXCEPT 鍒涘缓锛 + * 鍥犳 hash_search 浣跨敤 HASH_ENTER 鍦 palloc 澶辫触鏃朵笉浼氭姏鍑哄紓甯搞 + * 鎴戜滑蹇呴』妫鏌ョ粨鏋滄槸鍚︿负 NULL銆 */ m_streamInfoTbl = - hash_create("stream info lookup hash", 256, &ctl, HASH_ELEM | HASH_FUNCTION | HASH_SHRCTX | HASH_NOEXCEPT); + hash_create("stream info lookup hash", 256, &ctl, HASH_ELEM | HASH_FUNCTION | HASH_SHRCTX | HASH_NOEXCEPT); // 鍒涘缓鍝堝笇琛 } /* @@ -334,30 +336,30 @@ ParallelDesc StreamObj::getParallelDesc() } StreamNodeGroup::StreamNodeGroup() - : m_size(0), - m_streamNum(1), - m_createThreadNum(0), - m_streamEnter(0), - m_canceled(false), - m_needClean(false), - m_errorStop(false), - m_recursiveVfdInvalid(false) + : m_size(0), // 鍒濆鍖栬妭鐐圭粍澶у皬涓 0 + m_streamNum(1), // 鍒濆鍖栨祦鏁伴噺涓 1 + m_createThreadNum(0), // 鍒濆鍖栧垱寤虹嚎绋嬫暟涓 0 + m_streamEnter(0), // 鍒濆鍖栬繘鍏ユ祦鐨勬鏁颁负 0 + m_canceled(false), // 鍒濆鍖栧彇娑堟爣蹇椾负 false + m_needClean(false), // 鍒濆鍖栭渶瑕佹竻鐞嗘爣蹇椾负 false + m_errorStop(false), // 鍒濆鍖栭敊璇仠姝㈡爣蹇椾负 false + m_recursiveVfdInvalid(false) // 鍒濆鍖栭掑綊 VFD 鏃犳晥鏍囧織涓 false { - pthread_mutex_init(&m_mutex, NULL); - pthread_mutex_init(&m_recursiveMutex, NULL); - pthread_cond_init(&m_cond, NULL); - m_pid = gs_thread_self(); - m_streamPairList = NULL; - m_streamConsumerList = NULL; - m_streamProducerList = NULL; - m_syncControllers = NIL; - m_streamRuntimeContext = NULL; - m_streamArray = NULL; - m_quitWaitCond = 0; - m_edataWriteProtect = EDATA_WRITE_ENABLE; - m_producerEdata = NULL; + pthread_mutex_init(&m_mutex, NULL); // 鍒濆鍖栦簰鏂ラ攣 m_mutex + pthread_mutex_init(&m_recursiveMutex, NULL); // 鍒濆鍖栭掑綊浜掓枼閿 m_recursiveMutex + pthread_cond_init(&m_cond, NULL); // 鍒濆鍖栨潯浠跺彉閲 m_cond + m_pid = gs_thread_self(); // 鑾峰彇褰撳墠绾跨▼ ID + m_streamPairList = NULL; // 鍒濆鍖栨祦瀵瑰垪琛ㄤ负 NULL + m_streamConsumerList = NULL; // 鍒濆鍖栨祦娑堣垂鑰呭垪琛ㄤ负 NULL + m_streamProducerList = NULL; // 鍒濆鍖栨祦鐢熶骇鑰呭垪琛ㄤ负 NULL + m_syncControllers = NIL; // 鍒濆鍖栧悓姝ユ帶鍒跺櫒鍒楄〃涓 NIL + m_streamRuntimeContext = NULL; // 鍒濆鍖栨祦杩愯鏃朵笂涓嬫枃涓 NULL + m_streamArray = NULL; // 鍒濆鍖栨祦鏁扮粍涓 NULL + m_quitWaitCond = 0; // 鍒濆鍖栭鍑虹瓑寰呮潯浠朵负 0 + m_edataWriteProtect = EDATA_WRITE_ENABLE; // 鍒濆鍖 edata 鍐欎繚鎶ょ姸鎬佷负鍙啓 + m_producerEdata = NULL; // 鍒濆鍖栫敓浜ц edata 涓 NULL #ifndef ENABLE_MULTIPLE_NODES - m_portal = NULL; + m_portal = NULL; // 鍒濆鍖 portal 涓 NULL锛堝湪鍗曡妭鐐规ā寮忎笅浣跨敤锛 #endif } @@ -372,25 +374,25 @@ StreamNodeGroup::~StreamNodeGroup() */ void StreamNodeGroup::Init(int threadNum) { - m_size = threadNum + 1; /* all stream thead + top consumer thread */ - m_streamArray = (StreamNode*)palloc0(sizeof(StreamNode) * m_size); + m_size = threadNum + 1; /* 鎵鏈夋祦绾跨▼ + 椤跺眰娑堣垂鑰呯嚎绋 */ + m_streamArray = (StreamNode*)palloc0(sizeof(StreamNode) * m_size); /* 鍒嗛厤娴佽妭鐐规暟缁勭殑鍐呭瓨骞跺垵濮嬪寲涓洪浂 */ for (int i = 0; i < m_size; i++) - m_streamArray[i].status = STREAM_UNDEFINED; + m_streamArray[i].status = STREAM_UNDEFINED; /* 灏嗘祦鑺傜偣鐘舵佸垵濮嬪寲涓 STREAM_UNDEFINED */ + + m_quitWaitCond = m_size; /* 閫鍑虹瓑寰呮潯浠舵暟绛変簬鑺傜偣缁勫ぇ灏 */ - /* all stream thead + top consumer thread. */ - m_quitWaitCond = m_size; #ifdef ENABLE_MULTIPLE_NODES bool found = false; AutoMutexLock streamLock(&m_streamNodeGroupLock); - /* register the node group now */ + /* 鐜板湪娉ㄥ唽鑺傜偣缁 */ streamLock.lock(); StreamNodeElement* element = (StreamNodeElement*)hash_search(m_streamNodeGroupTbl, &m_pid, HASH_ENTER, &found); if (found != false) { streamLock.unLock(); - ereport(ERROR, (errcode(ERRCODE_SYSTEM_ERROR), errmsg("pid of stream nodegroup id is duplicated"))); + ereport(ERROR, (errcode(ERRCODE_SYSTEM_ERROR), errmsg("pid of stream nodegroup id is duplicated"))); /* 濡傛灉鎵惧埌閲嶅鐨 PID锛屾姤閿 */ } - element->value = this; - element->key = gs_thread_self(); + element->value = this; /* 灏嗗綋鍓嶈妭鐐圭粍瀵硅薄璧嬬粰鍝堝笇琛ㄤ腑鐨勫 */ + element->key = gs_thread_self(); /* 灏嗗綋鍓嶇嚎绋 ID 璧嬬粰鍝堝笇琛ㄤ腑鐨勯敭 */ streamLock.unLock(); #endif } @@ -410,9 +412,9 @@ void StreamNodeGroup::StartUp() ALLOCSET_DEFAULT_MINSIZE, ALLOCSET_DEFAULT_INITSIZE, ALLOCSET_DEFAULT_MAXSIZE, - SHARED_CONTEXT); + SHARED_CONTEXT); /* 鍒涘缓鍏ㄥ眬鍐呭瓨涓婁笅鏂 */ - /* init the stream node group table ctl. */ + /* 鍒濆鍖栨祦鑺傜偣缁勫搱甯岃〃鐨勬帶鍒剁粨鏋 */ rc = memset_s(&nodectl, sizeof(nodectl), 0, sizeof(nodectl)); securec_check(rc, "\0", "\0"); nodectl.keysize = sizeof(ThreadId); @@ -423,9 +425,9 @@ void StreamNodeGroup::StartUp() m_streamNodeGroupTbl = hash_create("stream node group lookup hash", 256, &nodectl, HASH_ELEM | HASH_FUNCTION | HASH_SHRCTX); #endif - pthread_mutex_init(&m_streamNodeGroupLock, NULL); + pthread_mutex_init(&m_streamNodeGroupLock, NULL); /* 鍒濆鍖栨祦鑺傜偣缁勯攣 */ - /* init the stream connect sync table ctl */ + /* 鍒濆鍖栨祦杩炴帴鍚屾鍝堝笇琛ㄧ殑鎺у埗缁撴瀯 */ rc = memset_s(&nodectl, sizeof(nodectl), 0, sizeof(nodectl)); securec_check(rc, "\0", "\0"); nodectl.keysize = sizeof(uint64); @@ -436,7 +438,7 @@ void StreamNodeGroup::StartUp() m_streamConnectSyncTbl = hash_create("stream connect sync hash", 256, &nodectl, HASH_ELEM | HASH_FUNCTION | HASH_SHRCTX); - pthread_mutex_init(&m_streamConnectSyncLock, NULL); + pthread_mutex_init(&m_streamConnectSyncLock, NULL); /* 鍒濆鍖栨祦杩炴帴鍚屾閿 */ } /* @@ -447,24 +449,24 @@ void StreamNodeGroup::StartUp() */ int StreamNodeGroup::registerStream(StreamObj* obj) { - if (obj->getType() == STREAM_PRODUCER) { + if (obj->getType() == STREAM_PRODUCER) { /* 濡傛灉鏄敓浜ц呮祦瀵硅薄 */ int streamIdx; - AutoMutexLock streamLock(&m_mutex); + AutoMutexLock streamLock(&m_mutex); /* 鑷姩鍔犻攣 */ - streamLock.lock(); - m_streamArray[m_streamNum].streamObj = obj; - setNodeStatus(m_streamNum, STREAM_INPROGRESS); - streamIdx = m_streamNum; - m_streamNum++; - streamLock.unLock(); - Assert(m_streamNum <= m_size); - return streamIdx; - } else { - AutoContextSwitch streamContext(u_sess->stream_cxt.stream_runtime_mem_cxt); - m_streamArray[0].stopFlag = &u_sess->exec_cxt.executorStopFlag; - m_streamArray[0].consumerList = lcons(obj, m_streamArray[0].consumerList); - m_streamArray[0].status = STREAM_INPROGRESS; - return 0; + streamLock.lock(); /* 涓婇攣 */ + m_streamArray[m_streamNum].streamObj = obj; /* 鍦ㄦ祦鏁扮粍涓繚瀛樻祦瀵硅薄 */ + setNodeStatus(m_streamNum, STREAM_INPROGRESS); /* 璁剧疆鑺傜偣鐘舵佷负杩涜涓 */ + streamIdx = m_streamNum; /* 鑾峰彇娴佺储寮 */ + m_streamNum++; /* 澧炲姞娴佹暟閲 */ + streamLock.unLock(); /* 瑙i攣 */ + Assert(m_streamNum <= m_size); /* 鏂█娴佹暟閲忎笉瓒呰繃鎬绘暟 */ + return streamIdx; /* 杩斿洖娴佺储寮 */ + } else { /* 濡傛灉鏄秷璐硅呮祦瀵硅薄 */ + AutoContextSwitch streamContext(u_sess->stream_cxt.stream_runtime_mem_cxt); /* 鍒囨崲涓婁笅鏂囧埌娴佽繍琛屾椂鍐呭瓨涓婁笅鏂 */ + m_streamArray[0].stopFlag = &u_sess->exec_cxt.executorStopFlag; /* 璁剧疆鍋滄鏍囧織鎸囬拡 */ + m_streamArray[0].consumerList = lcons(obj, m_streamArray[0].consumerList); /* 灏嗘秷璐硅呮祦瀵硅薄娣诲姞鍒版秷璐硅呭垪琛 */ + m_streamArray[0].status = STREAM_INPROGRESS; /* 璁剧疆鑺傜偣鐘舵佷负杩涜涓 */ + return 0; /* 杩斿洖0琛ㄧず娑堣垂鑰呮祦瀵硅薄娉ㄥ唽鎴愬姛 */ } } @@ -477,37 +479,37 @@ int StreamNodeGroup::registerStream(StreamObj* obj) */ void StreamNodeGroup::unregisterStream(int groupIdx, StreamObjStatus status) { - if (groupIdx == 0) { + if (groupIdx == 0) { /* 濡傛灉鏄秷璐硅呮祦缁 */ ListCell* consumerCell = NULL; StreamConsumer* consumerObj = NULL; - if (m_streamArray && m_streamArray[0].consumerList != NULL) { - if (m_streamArray[0].stopFlag != NULL) - *(m_streamArray[0].stopFlag) = false; + if (m_streamArray && m_streamArray[0].consumerList != NULL) { /* 濡傛灉娑堣垂鑰呭垪琛ㄤ笉涓虹┖ */ + if (m_streamArray[0].stopFlag != NULL) /* 濡傛灉鍋滄鏍囧織鎸囬拡涓嶄负绌 */ + *(m_streamArray[0].stopFlag) = false; /* 灏嗗仠姝㈡爣蹇楄缃负false */ - foreach (consumerCell, m_streamArray[0].consumerList) { - consumerObj = (StreamConsumer*)lfirst(consumerCell); + foreach (consumerCell, m_streamArray[0].consumerList) { /* 閬嶅巻娑堣垂鑰呭垪琛 */ + consumerObj = (StreamConsumer*)lfirst(consumerCell); /* 鑾峰彇娑堣垂鑰呮祦瀵硅薄 */ if (consumerObj == NULL) { continue; } - consumerObj->deInit(); + consumerObj->deInit(); /* 璋冪敤娑堣垂鑰呮祦瀵硅薄鐨刣eInit()鏂规硶杩涜鍙嶅垵濮嬪寲 */ } - m_streamArray[0].consumerList = NULL; + m_streamArray[0].consumerList = NULL; /* 灏嗘秷璐硅呭垪琛ㄧ疆涓虹┖ */ } - } else { - Assert(groupIdx < m_streamNum); + } else { /* 濡傛灉鏄敓浜ц呮祦缁 */ + Assert(groupIdx < m_streamNum); /* 鏂█缁勭储寮曞皬浜庢祦鏁伴噺 */ if (m_streamArray && m_streamArray[groupIdx].streamObj != NULL) { - m_streamArray[groupIdx].streamObj->setThreadId(InvalidTid); + m_streamArray[groupIdx].streamObj->setThreadId(InvalidTid); /* 璁剧疆绾跨▼ID涓烘棤鏁堝 */ } - setNodeStatus(groupIdx, status); + setNodeStatus(groupIdx, status); /* 璁剧疆鑺傜偣鐘舵 */ } - /* Avoid other threads checking empty and assignmenting with stopFlag at the same time */ - AutoMutexLock streamLock(&m_streamNodeGroupLock); - streamLock.lock(); - if (m_streamArray) - m_streamArray[groupIdx].stopFlag = NULL; - streamLock.unLock(); + /* 閬垮厤鍏朵粬绾跨▼鍚屾椂妫鏌ョ┖鍜屽仠姝㈡爣蹇楃殑璧嬪 */ + AutoMutexLock streamLock(&m_streamNodeGroupLock); /* 鑷姩鍔犻攣 */ + streamLock.lock(); /* 涓婇攣 */ + if (m_streamArray) /* 濡傛灉娴佹暟缁勪笉涓虹┖ */ + m_streamArray[groupIdx].stopFlag = NULL; /* 灏嗗仠姝㈡爣蹇楁寚閽堢疆涓虹┖ */ + streamLock.unLock(); /* 瑙i攣 */ } /* @@ -516,72 +518,74 @@ void StreamNodeGroup::unregisterStream(int groupIdx, StreamObjStatus status) * @param[IN] signo: signal number * @return: void */ -void StreamNodeGroup::signalStreamThreadInNodeGroup(int signo) +void StreamNodeGroup::unregisterStream(int groupIdx, StreamObjStatus status) { - if (StreamTopConsumerAmI() && m_streamArray) { - for (int i = 0; i < m_streamNum; i++) { - if (m_streamArray[i].streamObj != NULL && m_streamArray[i].streamObj->getThreadId() != InvalidTid) { - int ntimes = 1; - StreamProducer* producer = (StreamProducer*)m_streamArray[i].streamObj; + if (groupIdx == 0) { /* 濡傛灉鏄秷璐硅呮祦缁 */ + ListCell* consumerCell = NULL; + StreamConsumer* consumerObj = NULL; - /* - * Signal slot must be already registered if stream thread already inited. - * If not, wait 1ms once and then recheck. Sets the maximum total wait - * time as 30s. - */ - while (producer->getThreadInit() == false) { - /* sleep 1ms */ - pg_usleep(1000); + if (m_streamArray && m_streamArray[0].consumerList != NULL) { /* 濡傛灉娑堣垂鑰呭垪琛ㄤ笉涓虹┖ */ + if (m_streamArray[0].stopFlag != NULL) /* 濡傛灉鍋滄鏍囧織鎸囬拡涓嶄负绌 */ + *(m_streamArray[0].stopFlag) = false; /* 灏嗗仠姝㈡爣蹇楄缃负false */ - ntimes++; - if (ntimes == 30000) { - /* wait 30s, just break here */ - break; - } + foreach (consumerCell, m_streamArray[0].consumerList) { /* 閬嶅巻娑堣垂鑰呭垪琛 */ + consumerObj = (StreamConsumer*)lfirst(consumerCell); /* 鑾峰彇娑堣垂鑰呮祦瀵硅薄 */ + if (consumerObj == NULL) { + continue; } - - /* - * mark before send signal, - * used for signal handle to check signal whether signal is vaild. - */ - t_thrd.sig_cxt.gs_sigale_check_type = SIGNAL_CHECK_STREAM_STOP; - gs_signal_send(producer->getThreadId(), signo); + consumerObj->deInit(); /* 璋冪敤娑堣垂鑰呮祦瀵硅薄鐨刣eInit()鏂规硶杩涜鍙嶅垵濮嬪寲 */ } + + m_streamArray[0].consumerList = NULL; /* 灏嗘秷璐硅呭垪琛ㄧ疆涓虹┖ */ } + } else { /* 濡傛灉鏄敓浜ц呮祦缁 */ + Assert(groupIdx < m_streamNum); /* 鏂█缁勭储寮曞皬浜庢祦鏁伴噺 */ + if (m_streamArray && m_streamArray[groupIdx].streamObj != NULL) { + m_streamArray[groupIdx].streamObj->setThreadId(InvalidTid); /* 璁剧疆绾跨▼ID涓烘棤鏁堝 */ + } + setNodeStatus(groupIdx, status); /* 璁剧疆鑺傜偣鐘舵 */ } + /* 閬垮厤鍏朵粬绾跨▼鍚屾椂妫鏌ョ┖鍜屽仠姝㈡爣蹇楃殑璧嬪 */ + AutoMutexLock streamLock(&m_streamNodeGroupLock); /* 鑷姩鍔犻攣 */ + streamLock.lock(); /* 涓婇攣 */ + if (m_streamArray) /* 濡傛灉娴佹暟缁勪笉涓虹┖ */ + m_streamArray[groupIdx].stopFlag = NULL; /* 灏嗗仠姝㈡爣蹇楁寚閽堢疆涓虹┖ */ + streamLock.unLock(); /* 瑙i攣 */ } -#ifndef ENABLE_MULTIPLE_NODES -void StreamNodeGroup::SigStreamThreadClose() +void StreamNodeGroup::unregisterStream(int groupIdx, StreamObjStatus status) { - if (StreamTopConsumerAmI() && m_streamArray) { - for (int i = 0; i < m_streamNum; i++) { - if (m_streamArray[i].streamObj != NULL && m_streamArray[i].streamObj->getThreadId() != InvalidTid) { - int ntimes = 1; - StreamProducer* producer = (StreamProducer*)m_streamArray[i].streamObj; - /* - * Signal slot must be already registered if stream thread already inited. - * If not, wait 1ms once and then recheck. Sets the maximum total wait - * time as 30s. - */ - while (producer->getThreadInit() == false) { - /* sleep 1ms */ - pg_usleep(1000); - ntimes++; - if (ntimes == 30000) { - /* wait 30s, just break here */ - break; - } + if (groupIdx == 0) { /* 濡傛灉鏄秷璐硅呮祦缁 */ + ListCell* consumerCell = NULL; + StreamConsumer* consumerObj = NULL; + + if (m_streamArray && m_streamArray[0].consumerList != NULL) { /* 濡傛灉娑堣垂鑰呭垪琛ㄤ笉涓虹┖ */ + if (m_streamArray[0].stopFlag != NULL) /* 濡傛灉鍋滄鏍囧織鎸囬拡涓嶄负绌 */ + *(m_streamArray[0].stopFlag) = false; /* 灏嗗仠姝㈡爣蹇楄缃负false */ + + foreach (consumerCell, m_streamArray[0].consumerList) { /* 閬嶅巻娑堣垂鑰呭垪琛 */ + consumerObj = (StreamConsumer*)lfirst(consumerCell); /* 鑾峰彇娑堣垂鑰呮祦瀵硅薄 */ + if (consumerObj == NULL) { + continue; } - /* - * mark before send signal, - * used for signal handle to check signal whether signal is vaild. - */ - (void)SendProcSignal(producer->getThreadId(), PROCSIG_STREAM_STOP_CHECK, InvalidBackendId); + consumerObj->deInit(); /* 璋冪敤娑堣垂鑰呮祦瀵硅薄鐨刣eInit()鏂规硶杩涜鍙嶅垵濮嬪寲 */ } + + m_streamArray[0].consumerList = NULL; /* 灏嗘秷璐硅呭垪琛ㄧ疆涓虹┖ */ } + } else { /* 濡傛灉鏄敓浜ц呮祦缁 */ + Assert(groupIdx < m_streamNum); /* 鏂█缁勭储寮曞皬浜庢祦鏁伴噺 */ + if (m_streamArray && m_streamArray[groupIdx].streamObj != NULL) { + m_streamArray[groupIdx].streamObj->setThreadId(InvalidTid); /* 璁剧疆绾跨▼ID涓烘棤鏁堝 */ + } + setNodeStatus(groupIdx, status); /* 璁剧疆鑺傜偣鐘舵 */ } + /* 閬垮厤鍏朵粬绾跨▼鍚屾椂妫鏌ョ┖鍜屽仠姝㈡爣蹇楃殑璧嬪 */ + AutoMutexLock streamLock(&m_streamNodeGroupLock); /* 鑷姩鍔犻攣 */ + streamLock.lock(); /* 涓婇攣 */ + if (m_streamArray) /* 濡傛灉娴佹暟缁勪笉涓虹┖ */ + m_streamArray[groupIdx].stopFlag = NULL; /* 灏嗗仠姝㈡爣蹇楁寚閽堢疆涓虹┖ */ + streamLock.unLock(); /* 瑙i攣 */ } -#endif /* * @Description: Cancel all stream thread registered in node group * @@ -600,85 +604,39 @@ void StreamNodeGroup::cancelStreamThread() * * @return: void */ -void StreamNodeGroup::quitSyncPoint() +void StreamNodeGroup::unregisterStream(int groupIdx, StreamObjStatus status) { - if (StreamThreadAmI() == true) { - StreamPair* pair = NULL; - AutoMutexLock streamLock(&m_mutex); + if (groupIdx == 0) { /* 濡傛灉鏄秷璐硅呮祦缁 */ + ListCell* consumerCell = NULL; + StreamConsumer* consumerObj = NULL; - /* signal the top consumer if i am the last stream thread. */ - streamLock.lock(); - m_streamEnter++; - Assert(u_sess->stream_cxt.producer_obj != NULL); - pair = (u_sess->stream_cxt.producer_obj)->getPair(); + if (m_streamArray && m_streamArray[0].consumerList != NULL) { /* 濡傛灉娑堣垂鑰呭垪琛ㄤ笉涓虹┖ */ + if (m_streamArray[0].stopFlag != NULL) /* 濡傛灉鍋滄鏍囧織鎸囬拡涓嶄负绌 */ + *(m_streamArray[0].stopFlag) = false; /* 灏嗗仠姝㈡爣蹇楄缃负false */ - /* pair->subThreadNum - pair->startSubThreadNum is the supposed fail to launch thread. */ - if (u_sess->stream_cxt.smp_id == 0) - m_quitWaitCond = m_quitWaitCond - 1 - (pair->expectThreadNum - pair->createThreadNum); - else - m_quitWaitCond = m_quitWaitCond - 1; /* other smp thread. */ - - Assert(m_quitWaitCond >= 0); - Assert(pair->expectThreadNum >= pair->createThreadNum); - - if (m_quitWaitCond == 0) - pthread_cond_broadcast(&m_cond); - else { - while (m_quitWaitCond != 0) - pthread_cond_wait(&m_cond, &m_mutex); - } - streamLock.unLock(); - } else if (StreamTopConsumerAmI() == true) { - /* if none thread is created ,no bother to wait on condition. */ - if (m_createThreadNum != 0) { - AutoMutexLock streamLock(&m_mutex); - streamLock.lock(); - - /* m_size - 1 - m_createNum means the failed producer thread. */ - m_quitWaitCond = m_quitWaitCond - 1 - (m_size - 1 - m_createThreadNum); - - Assert(m_quitWaitCond >= 0); - Assert(m_size >= m_createThreadNum); - - if (m_quitWaitCond == 0) - pthread_cond_broadcast(&m_cond); - else { - /* - * If inWaitingQuit is true, when we are interupted by a SIGINT signal, - * we just send SIGINT to sub-thread to stop them, and we do not elog, - * otherwise the waiting quit status of related threads will be broken. - * Notes that inWaitQuit should be set before t_thrd.int_cxt.ImmediateInterruptOK be set, - * and reset after t_thrd.int_cxt.ImmediateInterruptOK is reset, or there is an opportunity - * that we meet a signal but inWaitingQuit has not been set. - */ - u_sess->stream_cxt.in_waiting_quit = true; - - /* - * Set it to true to enable signal handling when waiting sub-thread quit, - * otherwise the cancel request will not be handled in this situation. - */ - t_thrd.int_cxt.ImmediateInterruptOK = true; - - /* - * If got a signal before t_thrd.int_cxt.ImmediateInterruptOK set to true, the signal can not be - * processed immediately util top consumer goes back to ReadCommand again. - * It maybe take long time to wait all stream threads come to quitSyncPoint - * and then it's not necessary to send signal to stream threads any more. - * Hence, signal should be handled soon here with CHECK_FOR_INTERRUPTS(). - */ - CHECK_FOR_INTERRUPTS(); - - while (m_quitWaitCond != 0) - pthread_cond_wait(&m_cond, &m_mutex); - - t_thrd.int_cxt.ImmediateInterruptOK = false; - u_sess->stream_cxt.in_waiting_quit = false; + foreach (consumerCell, m_streamArray[0].consumerList) { /* 閬嶅巻娑堣垂鑰呭垪琛 */ + consumerObj = (StreamConsumer*)lfirst(consumerCell); /* 鑾峰彇娑堣垂鑰呮祦瀵硅薄 */ + if (consumerObj == NULL) { + continue; + } + consumerObj->deInit(); /* 璋冪敤娑堣垂鑰呮祦瀵硅薄鐨刣eInit()鏂规硶杩涜鍙嶅垵濮嬪寲 */ } - streamLock.unLock(); + m_streamArray[0].consumerList = NULL; /* 灏嗘秷璐硅呭垪琛ㄧ疆涓虹┖ */ } - } else - return; + } else { /* 濡傛灉鏄敓浜ц呮祦缁 */ + Assert(groupIdx < m_streamNum); /* 鏂█缁勭储寮曞皬浜庢祦鏁伴噺 */ + if (m_streamArray && m_streamArray[groupIdx].streamObj != NULL) { + m_streamArray[groupIdx].streamObj->setThreadId(InvalidTid); /* 璁剧疆绾跨▼ID涓烘棤鏁堝 */ + } + setNodeStatus(groupIdx, status); /* 璁剧疆鑺傜偣鐘舵 */ + } + /* 閬垮厤鍏朵粬绾跨▼鍚屾椂妫鏌ョ┖鍜屽仠姝㈡爣蹇楃殑璧嬪 */ + AutoMutexLock streamLock(&m_streamNodeGroupLock); /* 鑷姩鍔犻攣 */ + streamLock.lock(); /* 涓婇攣 */ + if (m_streamArray) /* 濡傛灉娴佹暟缁勪笉涓虹┖ */ + m_streamArray[groupIdx].stopFlag = NULL; /* 灏嗗仠姝㈡爣蹇楁寚閽堢疆涓虹┖ */ + streamLock.unLock(); /* 瑙i攣 */ } /* @@ -743,22 +701,22 @@ const List* StreamNodeGroup::getStreamPairList() */ void StreamNodeGroup::initStreamThread(StreamProducer* producer, uint8 smpIdentifier, StreamPair* pair) { - ThreadId producerThreadId = ApplyStreamThread(producer); - if (producerThreadId != 0) { + ThreadId producerThreadId = ApplyStreamThread(producer); /* 鐢宠娴佺嚎绋 */ + if (producerThreadId != 0) { /* 濡傛灉绾跨▼ID涓嶄负0 */ #ifdef __aarch64__ - pg_memory_barrier(); + pg_memory_barrier(); /* 鍐呭瓨灞忛殰 */ #endif - AutoMutexLock streamLock(&m_mutex); - streamLock.lock(); - producer->setThreadId(producerThreadId); - /* Set create thread num for sync quit. */ + AutoMutexLock streamLock(&m_mutex); /* 鑷姩浜掓枼閿 */ + streamLock.lock(); /* 鍔犻攣 */ + producer->setThreadId(producerThreadId); /* 璁剧疆鐢熶骇鑰呯嚎绋婭D */ + /* 璁剧疆鍒涘缓绾跨▼鏁颁互杩涜鍚屾閫鍑恒 */ m_createThreadNum++; - /* Assume all stream threads build successfully for sync quit process. */ + /* 鍋囪鎵鏈夋祦绾跨▼鏋勫缓鎴愬姛浠ヨ繘琛屽悓姝ラ鍑鸿繃绋嬨 */ StreamPair* tmpPair = producer->getPair(); tmpPair->createThreadNum = tmpPair->expectThreadNum; - streamLock.unLock(); + streamLock.unLock(); /* 瑙i攣 */ - Assert(m_createThreadNum <= m_size); + Assert(m_createThreadNum <= m_size); /* 鏂█鍒涘缓绾跨▼鏁板皬浜庣瓑浜庤妭鐐规暟 */ STREAM_LOG(DEBUG2, "startup stream thread for " "producer(%lu, %u, %u), thread id %lu, %d/%d in top consumer", @@ -769,11 +727,11 @@ void StreamNodeGroup::initStreamThread(StreamProducer* producer, uint8 smpIdenti m_createThreadNum, m_size); } else { - producer->releaseNetPort(); + producer->releaseNetPort(); /* 閲婃斁缃戠粶绔彛 */ int childslots = ((StreamProducer*)producer)->getChildSlot(); // release only if StreamProducer has called setChildSlot(AssignPostmasterChildSlot()) before if (childslots > 0) - ReleasePostmasterChildSlot(childslots); + ReleasePostmasterChildSlot(childslots); /* 閲婃斁瀛愯繘绋嬫Ы浣 */ ereport(ERROR, (errcode(ERRCODE_SYSTEM_ERROR), errmsg("failed to startup stream thread, NodeName: %s, key(%lu, %u): %m", @@ -792,23 +750,23 @@ void StreamNodeGroup::initStreamThread(StreamProducer* producer, uint8 smpIdenti */ bool StreamNodeGroup::inNodeGroup(ThreadId pid1, ThreadId pid2) { - if (pid1 == pid2) + if (pid1 == pid2) /* 濡傛灉绾跨▼ID鐩稿悓锛岃繑鍥瀎alse */ return false; - bool flag = false; + bool flag = false; /* 鍒濆鍖栨爣蹇椾负false */ - if (pid1 == m_pid || pid2 == m_pid) { - for (int i = 1; i < m_streamNum; i++) { + if (pid1 == m_pid || pid2 == m_pid) { /* 濡傛灉浠讳綍涓涓嚎绋婭D绛変簬褰撳墠鑺傜偣鐨勭嚎绋婭D */ + for (int i = 1; i < m_streamNum; i++) { /* 閬嶅巻娴佺嚎绋嬫暟缁 */ if (m_streamArray[i].streamObj != NULL && - (m_streamArray[i].streamObj->getThreadId() == pid2 || + (m_streamArray[i].streamObj->getThreadId() == pid2 || /* 濡傛灉绾跨▼ID绛変簬pid1鎴杙id2 */ m_streamArray[i].streamObj->getThreadId() == pid1)) { - flag = true; - break; + flag = true; /* 璁剧疆鏍囧織涓簍rue */ + break; /* 璺冲嚭寰幆 */ } } } - return flag; + return flag; /* 杩斿洖鏍囧織 */ } /* @@ -898,24 +856,25 @@ ErrorData* StreamNodeGroup::getProducerEdata() */ void StreamNodeGroup::destroy(StreamObjStatus status) { - /* Only top consumer responsible for destroying stream node group */ + /* 鍙湁椤跺眰娑堣垂鑰呰礋璐i攢姣佹祦鑺傜偣缁 */ if (StreamTopConsumerAmI() == false) return; - /* We must relase all pthread mutex by my thread, Or it will dead lock. But it is not a good solution. */ - // lock the same thread mutex can't be conflict in one thread. + /* 蹇呴』鍦ㄦ垜鐨勭嚎绋嬩腑閲婃斁鎵鏈塸thread浜掓枼閿侊紝鍚﹀垯浼氬彂鐢熸閿併備絾杩欎笉鏄竴涓ソ鐨勮В鍐虫柟妗堛 */ + // 閿佸畾鐩稿悓绾跨▼鐨勪簰鏂ラ攣鍦ㄤ竴涓嚎绋嬩腑涓嶄細鍐茬獊銆 + ResourceOwnerReleasePthreadMutex(); WaitState oldStatus = pgstat_report_waitstatus(STATE_STREAM_WAIT_NODEGROUP_DESTROY); /* - * If top consumer is canceled before BuildStreamFlow, streamNodeGroup is not initialized. - * At this time, we should release net port left in hash table here. + * 濡傛灉椤跺眰娑堣垂鑰呭湪鏋勫缓StreamFlow涔嬪墠琚彇娑堬紝娴佽妭鐐圭粍灏氭湭鍒濆鍖栥 + * 姝ゆ椂锛屾垜浠簲璇ュ湪杩欓噷閲婃斁鍝堝笇琛ㄤ腑鍓╀綑鐨勭綉缁滅鍙c */ if (STREAM_ERROR == status) StreamObj::releaseNetPortInHashTable(); - /* Destroy the stream node group. */ + /* 閿姣佹祦鑺傜偣缁勩 */ if (u_sess->stream_cxt.global_obj != NULL) { #ifndef ENABLE_MULTIPLE_NODES if (u_sess->stream_cxt.global_obj->m_portal != NULL) { @@ -927,14 +886,14 @@ void StreamNodeGroup::destroy(StreamObjStatus status) u_sess->stream_cxt.global_obj = NULL; } - /* Destroy the global instrumentation. */ + /* 閿姣佸叏灞浠〃銆 */ if (u_sess->instr_cxt.global_instr != NULL) { delete u_sess->instr_cxt.global_instr; u_sess->instr_cxt.thread_instr = NULL; u_sess->instr_cxt.global_instr = NULL; } - /* Release stream context. */ + /* 閲婃斁娴佷笂涓嬫枃銆 */ DeinitStreamContext(); pgstat_report_waitstatus(oldStatus); } @@ -947,13 +906,14 @@ void StreamNodeGroup::destroy(StreamObjStatus status) */ void StreamNodeGroup::syncQuit(StreamObjStatus status) { - /* Only stream thread or top consumer need sync quit */ + /* 鍙湁娴佺嚎绋嬫垨椤跺眰娑堣垂鑰呴渶瑕佸悓姝ラ鍑 */ if (IS_PGXC_COORDINATOR || (StreamTopConsumerAmI() == false && StreamThreadAmI() == false) || u_sess->stream_cxt.enter_sync_point == true) return; - /* We must relase all pthread mutex by my thread, Or it will dead lock. But it is not a good solution. */ - // lock the same thread mutex can't be conflict in one thread. + /* 蹇呴』鍦ㄦ垜鐨勭嚎绋嬩腑閲婃斁鎵鏈塸thread浜掓枼閿侊紝鍚﹀垯浼氬彂鐢熸閿併備絾杩欎笉鏄竴涓ソ鐨勮В鍐虫柟妗堛 */ + // 閿佸畾鐩稿悓绾跨▼鐨勪簰鏂ラ攣鍦ㄤ竴涓嚎绋嬩腑涓嶄細鍐茬獊銆 + ResourceOwnerReleasePthreadMutex(); WaitState oldStatus = pgstat_report_waitstatus(STATE_STREAM_WAIT_THREAD_SYNC_QUIT); @@ -982,18 +942,15 @@ void StreamNodeGroup::syncQuit(StreamObjStatus status) if (StreamTopConsumerAmI()) { /* - * If an error is encountered during receiveing data, top consumer will - * come to sync point and wait all stream threads. At this time, error message - * may not be sent to Coordinator immediately(release net port and report - * error are behind sync point). If some producers need long time to finish - * sending data to other normal consumers, it will also take long time to - * report error. So we should signal all stream thread to cancel query in this - * case and then the whole query can be canceled quickly. + * 濡傛灉鍦ㄦ帴鏀舵暟鎹繃绋嬩腑閬囧埌閿欒锛岄《灞傛秷璐硅呭皢杩涘叆鍚屾鐐瑰苟绛夊緟鎵鏈夋祦绾跨▼銆 + * 姝ゆ椂锛岄敊璇秷鎭彲鑳芥棤娉曠珛鍗冲彂閫佸埌鍗忚皟鍣紙閲婃斁缃戠粶绔彛鍜屾姤鍛婇敊璇湪鍚屾鐐逛箣鍚庯級銆 + * 濡傛灉鏌愪簺鐢熶骇鑰呴渶瑕佸緢闀挎椂闂村皢鏁版嵁鍙戦佸埌鍏朵粬姝e父娑堣垂鑰咃紝瀹冧滑涔熷皢闇瑕佸緢闀挎椂闂存姤鍛婇敊璇 + * 鍥犳锛屽湪杩欑鎯呭喌涓嬶紝鎴戜滑搴旇鍚戞墍鏈夋祦绾跨▼鍙戦佷俊鍙蜂互鍙栨秷鏌ヨ锛岀劧鍚庢暣涓煡璇㈠彲浠ヨ繀閫熷彇娑堛 */ if (STREAM_ERROR == status) StreamNodeGroup::cancelStreamThread(); - /* before top consumer enter the sync point, it must unregister to make sure the fd is closed. */ + /* 鍦ㄩ《灞傛秷璐硅呰繘鍏ュ悓姝ョ偣涔嬪墠锛屽畠蹇呴』鍙栨秷娉ㄥ唽锛屼互纭繚fd宸插叧闂 */ u_sess->stream_cxt.global_obj->unregisterStream(0, status); } else if (StreamThreadAmI()) { Assert(u_sess->stream_cxt.producer_obj != NULL); @@ -1002,7 +959,7 @@ void StreamNodeGroup::syncQuit(StreamObjStatus status) u_sess->stream_cxt.global_obj->quitSyncPoint(); - /* After syncpoint, all these objects may have been freed by topConsumer. */ + /* 鍦ㄥ悓姝ョ偣涔嬪悗锛屾墍鏈夎繖浜涘璞″彲鑳藉凡缁忚椤跺眰娑堣垂鑰呴噴鏀俱 */ if (StreamThreadAmI()) { u_sess->stream_cxt.producer_obj = NULL; } @@ -1035,28 +992,27 @@ void StreamNodeGroup::deInit(StreamObjStatus status) pg_usleep(1000); } while (saveQuit == false); - /* release the socket in case not release. */ + /* 閲婃斁濂楁帴瀛椾互闃叉湭閲婃斁銆 */ foreach (cell, m_streamProducerList) { producer = (StreamProducer*)lfirst(cell); /* - * 1. For TCP, close fd of producer. - * 2. Consumer can accept connection after handling cancel signal. - * For SCTP, if top consumer get an error, close sctp stream of producer - * in case not release(producer complete execution), so that receiver - * stream can be closed by gs_receivers_flow_controller. + * 1. 瀵逛簬TCP锛屽叧闂敓浜ц呯殑fd銆 + * 2. 娑堣垂鑰呭彲浠ュ湪澶勭悊鍙栨秷淇″彿鍚庢帴鍙楄繛鎺ャ + * 瀵逛簬SCTP锛屽鏋滈《灞傛秷璐硅呴亣鍒伴敊璇紝鍏抽棴鐢熶骇鑰呯殑sctp娴 + * 浠ラ槻鏈噴鏀撅紙鐢熶骇鑰呭畬鎴愭墽琛岋級锛岃繖鏍锋帴鏀惰呯殑娴佸氨鍙互琚玤s_receivers_flow_controller鍏抽棴銆 */ if (STREAM_ERROR == status) producer->releaseNetPort(); /* producer release socket will be enough. */ } - /* release the socket in case not release. */ + /* 閲婃斁濂楁帴瀛椾互闃叉湭閲婃斁銆 */ foreach (cell, m_streamConsumerList) { consumer = (StreamConsumer*)lfirst(cell); consumer->deInit(); } - /* Free the synccontroller list */ + /* 閲婃斁鍚屾鎺у埗鍣ㄥ垪琛 */ if (m_syncControllers != NIL) { ListCell* lc = NULL; foreach (lc, m_syncControllers) { @@ -1072,13 +1028,11 @@ void StreamNodeGroup::deInit(StreamObjStatus status) m_streamRuntimeContext = NULL; /* - * 1. If length of m_streamPairList is not the same as m_size(number of stream exists in plan tree), - * it means that stream connection and stream thread initialization may not finish yet due to - * cancel signal. - * 2. m_needClean is true if some producer not ready and element in stream info hash table can not - * get removed in wakeUpConsumer, or consumer get canceled when waiting producer ready. - * In these two case, we should release net port cached in hash table instead of just releasing - * consumer in m_streamPairList. + * 1. 濡傛灉m_streamPairList鐨勯暱搴︿笌m_size锛堣鍒掓爲涓瓨鍦ㄧ殑娴佺殑鏁伴噺锛変笉鍚岋紝 + * 杩欐剰鍛崇潃鐢变簬鍙栨秷淇″彿锛屾祦杩炴帴鍜屾祦绾跨▼鍒濆鍖栧彲鑳藉皻鏈畬鎴愩 + * 2. 濡傛灉鏌愪簺鐢熶骇鑰呮湭鍑嗗濂斤紝娴佷俊鎭搱甯岃〃涓殑鍏冪礌鍙兘鏃犳硶鍦╳akeUpConsumer涓鍒犻櫎锛 + * 鎴栬呭湪绛夊緟鐢熶骇鑰呭噯澶囧氨缁椂锛屾秷璐硅呰鍙栨秷銆 + * 鍦ㄨ繖涓ょ鎯呭喌涓嬶紝鎴戜滑搴旇閲婃斁鍝堝笇琛ㄤ腑缂撳瓨鐨勭綉缁滅鍙o紝鑰屼笉浠呬粎鏄噴鏀緈_streamPairList涓殑娑堣垂鑰呫 */ if ((list_length(m_streamPairList) != m_size) || m_needClean) StreamObj::releaseNetPortInHashTable(); @@ -1108,7 +1062,7 @@ void StreamNodeGroup::stopAllThreadInNodeGroup(ThreadId pid, uint64 query_id) AutoMutexLock streamLock(&m_streamNodeGroupLock); streamLock.lock(); - /* Search in the stream node group. */ + /* 鍦ㄦ祦鑺傜偣缁勪腑鎼滅储銆*/ element = (StreamNodeElement*)hash_search(m_streamNodeGroupTbl, &pid, HASH_FIND, &found); if (found == true) { if (query_id == element->value->GetQueryId()) { @@ -1157,7 +1111,7 @@ void StreamNodeGroup::grantStreamConnectPermission() bool found = false; AutoMutexLock streamLock(&m_streamConnectSyncLock); - HOLD_INTERRUPTS(); /* add this macro for double safety */ + HOLD_INTERRUPTS(); /* 涓轰簡鍙岄噸淇濋櫓锛屾坊鍔犳瀹 */ streamLock.lock(); StreamConnectSyncElement* element = (StreamConnectSyncElement*)hash_search(m_streamConnectSyncTbl, &u_sess->debug_query_id, HASH_ENTER, &found); @@ -1184,7 +1138,7 @@ void StreamNodeGroup::revokeStreamConnectPermission() { AutoMutexLock streamLock(&m_streamConnectSyncLock); - HOLD_INTERRUPTS(); /* add this macro for double safety */ + HOLD_INTERRUPTS(); /* 娣诲姞姝ゅ畯浠ヨ幏寰楀弻閲嶅畨鍏 */ streamLock.lock(); (void)hash_search(m_streamConnectSyncTbl, &u_sess->debug_query_id, HASH_REMOVE, NULL); streamLock.unLock(); @@ -1221,12 +1175,12 @@ bool StreamNodeGroup::checkStreamConnectPermission(uint64 query_id) void StreamNodeGroup::SyncConsumerNextPlanStep(int controller_plannodeid, int stepno) { - /* We don't have todo any-thing */ + /* 鎴戜滑浠涔堥兘涓嶇敤鍋 */ if (!IS_PGXC_DATANODE) { return; } - /* We don't have todo step syncup when there is no stream operator in execution plan */ + /* 褰撴墽琛岃鍒掍腑娌℃湁娴佹搷浣滅鏃讹紝鎴戜滑涓嶅繀杩涜姝ヨ繘鍚屾 */ if (u_sess->stream_cxt.global_obj == NULL) { return; } @@ -1234,7 +1188,7 @@ void StreamNodeGroup::SyncConsumerNextPlanStep(int controller_plannodeid, int st StreamNodeGroup* stream_nodegroup = u_sess->stream_cxt.global_obj; SyncController* controller = stream_nodegroup->GetSyncController(controller_plannodeid); - /* Report Error when the controller is not found */ + /* 鎵句笉鍒版帶鍒跺櫒鏃舵姤鍛婇敊璇 */ if (controller == NULL) { ereport(ERROR, (errcode(ERRCODE_UNEXPECTED_NULL_VALUE), @@ -1293,8 +1247,7 @@ void StreamNodeGroup::SyncProducerNextPlanStep(int controller_plannodeid, int pr } /* - * Report Error when the controller for its belonging RecursiveUnion node is - * not found. + * 褰撳叾鎵灞濺ecursiveUnion鑺傜偣鐨勬帶鍒跺櫒涓烘椂锛屾姤鍛婇敊璇湭鎵惧埌銆 */ if (controller == NULL) { elog(ERROR, @@ -1303,11 +1256,9 @@ void StreamNodeGroup::SyncProducerNextPlanStep(int controller_plannodeid, int pr } /* - * Normally, we should do sync-up on producer side at the end of execution, however - * the corresponding consumer may encounter a "short-circuit" case where it does not - * have the opportunity to invoke ExecStream to reach the end of current thread (send - * 'Z' or 'R'), so in this case we need send 'R' forcely. to tell other datanodes we - * have done. + 閫氬父锛屾垜浠簲璇ュ湪鎵ц缁撴潫鏃跺湪鐢熶骇鑰呯杩涜鍚屾锛屼絾鏄浉搴旂殑娑堣垂鑰呭彲鑳戒細閬囧埌鈥滅煭璺濇儏鍐碉紝 + 鍗冲畠娌℃湁鏈轰細璋冪敤ExecStream鏉ュ埌杈惧綋鍓嶇嚎绋嬬殑缁撴潫(鍙戦'Z'鎴'R')锛屾墍浠ュ湪杩欑鎯呭喌涓嬶紝鎴戜滑闇瑕 + 寮哄埗鍙戦'R'鏉ュ憡璇夊叾浠栨暟鎹妭鐐规垜浠凡缁忚繖鏍峰仛浜 */ if (controller->executor_stop) { u_sess->exec_cxt.executorStopFlag = true; @@ -1338,7 +1289,7 @@ void StreamNodeGroup::SyncProducerNextPlanStep(int controller_plannodeid, int pr } } - /* Other thread failed, we need return error immediately */ + /* 鍏朵粬绾跨▼澶辫触锛屾垜浠渶瑕佺珛鍗宠繑鍥為敊璇 */ if (u_sess->stream_cxt.global_obj->m_errorStop) { ereport(ERROR, (errcode(ERRCODE_RU_STOP_QUERY), errmsg("error happened during execute query"))); } @@ -1354,22 +1305,23 @@ void StreamNodeGroup::ConsumerGetSyncUpMessage( StreamPrepareRequestForRecursive(node, true); if (msg_type == RUSYNC_MSGTYPE_NODE_FINISH) { - /* For message 'R', we only recieve it from worker-node */ + /* 瀵逛簬娑堟伅'R'锛屾垜浠彧浠巜orker-node鎺ユ敹瀹 */ ConsumerNodeSyncUpMessage(controller, step, node); } else { - Assert(false); + Assert(false); // 鏃犳晥鐨勬秷鎭被鍨嬶紝涓嶅簲璇ュ彂鐢 } return; } + void StreamNodeGroup::ConsumerMarkRUStepStatus(RecursiveUnionController* controller, int step, int iteration, StreamState* node, int pgxc_nodeid, int producer_plannodeid, int tuple_processed) { switch (step) { case WITH_RECURSIVE_SYNC_NONERQ: { if (pgxc_nodeid == u_sess->pgxc_cxt.PGXCNodeId) { - /* Receive message from self DN, we need verify it has been updated */ + /* 浠庤嚜韬獶N鎺ユ敹娑堟伅锛屾垜浠渶瑕侀獙璇佸畠鏄惁宸叉洿鏂 */ if (controller->none_recursive_tuples[pgxc_nodeid] == -1) { elog(ERROR, "MPP with-recursive step1 (C) is not set on datanode %s", @@ -1381,7 +1333,7 @@ void StreamNodeGroup::ConsumerMarkRUStepStatus(RecursiveUnionController* control } break; case WITH_RECURSIVE_SYNC_RQSTEP: { if (pgxc_nodeid == u_sess->pgxc_cxt.PGXCNodeId) { - /* Receive message from self DN, we need verify it has been updated */ + /* 浠庤嚜韬獶N鎺ユ敹娑堟伅锛屾垜浠渶瑕侀獙璇佸畠鏄惁宸叉洿鏂 */ if (controller->recursive_tuples[pgxc_nodeid] == -1) { elog(ERROR, "MPP with-recursive step2 (C) is not set on datanode %s", @@ -1389,7 +1341,7 @@ void StreamNodeGroup::ConsumerMarkRUStepStatus(RecursiveUnionController* control } } - /* Coordinator's step2.iteration is updated by itself, not from message */ + /* 鍗忚皟鍣ㄧ殑绗2姝ヨ凯浠f槸鐢辫嚜韬洿鏂扮殑锛岃屼笉鏄粠娑堟伅涓幏鍙栫殑 */ controller->recursive_tuples[pgxc_nodeid] = tuple_processed; } break; case WITH_RECURSIVE_SYNC_DONE: { @@ -1428,8 +1380,8 @@ void StreamNodeGroup::ProducerFinishRUIteration(int step) elog(DEBUG1, "MPP with-recursive step%d send 'Z' to consumer start >>> %s", step, producer_top_plannode_str); /* - * prepare an end message to all the consumer backend thread. - * if is dummy, do not bother send + * 涓烘墍鏈夋秷璐硅呭悗绔嚎绋嬪噯澶囦竴涓粨鏉熸秷鎭 + * 濡傛灉鏄櫄鎷熺殑锛屼笉瑕侀夯鐑﹀彂閫 */ if (producer->isDummy() == false) { for (i = 0; i < consumer_number; i++) { @@ -1446,7 +1398,7 @@ void StreamNodeGroup::ProducerFinishRUIteration(int step) pq_endmessage(&buf); } else if (PG_PROTOCOL_MAJOR(FrontendProtocol) >= 2) pq_putemptymessage('Z'); - /* Flush output at end of cycle in any case. */ + /* 鍦ㄤ换浣曟儏鍐典笅閮藉湪寰幆缁撴潫鏃跺埛鏂拌緭鍑恒 */ res = pq_flush(); if (res == EOF) { transport[i]->release(); @@ -1456,14 +1408,15 @@ void StreamNodeGroup::ProducerFinishRUIteration(int step) } } - /* Send a final signal to consumer for local stream, and producer can be triggered next one run. */ + /* 涓烘湰鍦版祦鍙戦佹渶缁堜俊鍙风粰娑堣垂鑰咃紝骞朵笖鐢熶骇鑰呭彲浠ュ湪涓嬩竴娆¤繍琛屾椂瑙﹀彂銆 */ producer->finalizeLocalStream(); - elog(DEBUG1, "MPP with-recursive step%d send 'Z' to consumer done <<< %s", step, producer_top_plannode_str); + elog(DEBUG1, "MPP with-recursive step%d send 'Z' to consumer done <<< %s", step, producer_top_plannode_str);(DEBUG1, "MPP with-recursive 绗%d姝 鍙戦 'Z' 鍒版秷璐硅呭畬鎴 <<< %s", step, producer_top_plannode_str); return; } + /* * Function ProducerSendSyncMessage() * @@ -1486,34 +1439,26 @@ void StreamNodeGroup::ProducerSendSyncMessage( StreamTransport** transport = producer->getTransport(); int iteration = 0; - /* Only syncup producer thread need send message */ if (!IsSyncUpProducerThread()) { return; } - /* Only Sync-Producer need send sync-up message to control-node */ if (!StreamNodeGroup::IsRUSyncProducer()) { return; } - /* - * Specify the iteration step in 'F' & 'R' to let the consumer side todo step - * verification. - */ if (step == WITH_RECURSIVE_SYNC_DONE) { iteration = u_sess->attr.attr_sql.max_recursive_times; } else { iteration = controller->iteration; } - /* Producer send sync-up message to each DN's consumer */ if (producer->isDummy() == false) { for (int connIdx = 0; connIdx < consumer_number; connIdx++) { if (producer->netSwitchDest(connIdx)) { StringInfoData buf; initStringInfo(&buf); - /* Prepare 'R' message */ pq_beginmessage(&buf, msg_type); appendStringInfo(&buf, "nodename:%s,", g_instance.attr.attr_common.PGXCNodeName); appendStringInfo(&buf, "rustep:%d,", step); @@ -1529,12 +1474,11 @@ void StreamNodeGroup::ProducerSendSyncMessage( if (msg_type == RUSYNC_MSGTYPE_NODE_FINISH) { iter = controller->iteration; } else { - /* Can not get here */ Assert(false); } elog(DEBUG1, - "MPP with-recursive step%d (P) send step-sync message '%c' iteration[%d] to %s(nodeid:%u) %s", + "MPP with-recursive 绗%d姝 (P) 鍙戦佹楠ゅ悓姝ユ秷鎭 '%c' 杩唬[%d] 鍒 %s(nodeid:%u) %s", step, msg_type, iter, @@ -1542,7 +1486,6 @@ void StreamNodeGroup::ProducerSendSyncMessage( transport[connIdx]->m_nodeoid, producer_top_plannode_str); - /* Flush output at end of cycle in any case. */ int res = pq_flush(); if (res == EOF) { transport[connIdx]->release(); @@ -1568,12 +1511,12 @@ void StreamNodeGroup::ProducerSendSyncMessage( */ bool StreamNodeGroup::IsRecursiveUnionDone(RecursiveUnionState* state) { - /* If no sync-up step required, just return TRUE */ + /* 濡傛灉涓嶉渶瑕佸悓姝ユ楠わ紝鍙繑鍥濼RUE*/ if (state != NULL && !NeedSyncUpRecursiveUnionStep((Plan*)state->ps.plan)) { return true; } - /* We don't have todo step syncup when there is no stream operator in execution plan */ + /* 褰撴墽琛岃鍒掍腑娌℃湁娴佹搷浣滅鏃讹紝鎴戜滑涓嶅繀杩涜姝ヨ繘鍚屾 */ if (u_sess->stream_cxt.global_obj == NULL) { return true; } @@ -1635,10 +1578,10 @@ SyncController* StreamNodeGroup::GetSyncController(int controller_plannodeid) } } - /* Other thread failed, we need return error immediately */ + /* 鍏朵粬绾跨▼鍙戠敓閿欒锛岄渶瑕佺珛鍗宠繑鍥為敊璇俊鎭 */ if (u_sess->stream_cxt.global_obj->m_errorStop) { streamLock.unLock(); - ereport(ERROR, (errcode(ERRCODE_RU_STOP_QUERY), errmsg("error happened during execute query"))); + ereport(ERROR, (errcode(ERRCODE_RU_STOP_QUERY), errmsg("鎵ц鏌ヨ鏃跺彂鐢熼敊璇"))); } } streamLock.unLock(); @@ -1714,9 +1657,10 @@ static void ConsumerNodeSyncUpMessage(RecursiveUnionController* controller, int connCount = node->conn_count; connections = node->connections; - /* Handle data from connections until the number of conections without return data becomes 0 */ + /* 澶勭悊杩炴帴鐨勬暟鎹紝鐩村埌鏃犺繑鍥炴暟鎹殑杩炴帴鏁颁负0 */ while (connCount) { if (node->need_fresh_data) { + /* 浠庨昏緫杩炴帴涓鍙栧搷搴 'R'锛岀洿鍒版病鏈夋柊鏁版嵁涓烘 */ if (datanode_receive_from_logic_conn(node->conn_count, connections, &node->netctl, -1)) { int error_code = getStreamSocketError(gs_comm_strerror()); ereport(ERROR, @@ -1731,15 +1675,15 @@ static void ConsumerNodeSyncUpMessage(RecursiveUnionController* controller, int } for (connIdx = 0; connIdx < node->conn_count; connIdx++) { - /* conection has return data */ + /* 杩炴帴鏈夎繑鍥炴暟鎹 */ if (connections[connIdx]->state == DN_CONNECTION_STATE_IDLE) { continue; } - /* Handle data from connections */ + /* 澶勭悊鏉ヨ嚜杩炴帴鐨勬暟鎹 */ int res = HandleStreamResponse(connections[connIdx], node); if (res == RESPONSE_RECURSIVE_SYNC_R) { - /* receive 'R' message, change conection's state, number of conections without return data -1 */ + /* 鎺ユ敹鍒 'R' 娑堟伅锛屼慨鏀硅繛鎺ョ姸鎬侊紝鏃犺繑鍥炴暟鎹殑杩炴帴鏁板噺1 */ connections[connIdx]->state = DN_CONNECTION_STATE_IDLE; connCount--; elog(DEBUG1, @@ -1747,7 +1691,7 @@ static void ConsumerNodeSyncUpMessage(RecursiveUnionController* controller, int step, connections[connIdx]->nodeIdx); } else if (res == RESPONSE_COMPLETE) { - /* receive unused 'Z' message, in case the unused message blocking connections */ + /* 鎺ユ敹鍒版湭浣跨敤鐨 'Z' 娑堟伅锛屼互闃叉鏈娇鐢ㄧ殑娑堟伅闃诲杩炴帴 */ connections[connIdx]->state = DN_CONNECTION_STATE_QUERY; ereport(DEBUG1, (errcode(ERRCODE_WRONG_OBJECT_TYPE), @@ -1776,15 +1720,17 @@ void StreamNodeGroup::ConsumerNodeStreamMessage(StreamState* node) int connCount = 0; PGXCNodeHandle** connections = NULL; + /* 濡傛灉鑺傜偣灏氭湭鍑嗗濂斤紝鍒欏噯澶囬掑綊璇锋眰 */ if (unlikely(node->isReady == false)) StreamPrepareRequestForRecursive(node, true); connCount = node->conn_count; connections = node->connections; - /* Handle data from connections until the number of conections without return data becomes 0 */ + /* 澶勭悊杩炴帴鐨勬暟鎹紝鐩村埌娌℃湁杩斿洖鏁版嵁鐨勮繛鎺ユ暟涓0涓烘 */ while (connCount) { if (node->need_fresh_data) { + /* 浠庨昏緫杩炴帴涓鍙栧搷搴 'Z'锛岀洿鍒版病鏈夋柊鏁版嵁涓烘 */ if (datanode_receive_from_logic_conn(node->conn_count, connections, &node->netctl, -1)) { int error_code = getStreamSocketError(gs_comm_strerror()); ereport(ERROR, @@ -1798,19 +1744,19 @@ void StreamNodeGroup::ConsumerNodeStreamMessage(StreamState* node) } for (connIdx = 0; connIdx < node->conn_count; connIdx++) { - /* conection has return data */ + /* 杩炴帴鏈夎繑鍥炴暟鎹 */ if (connections[connIdx]->state == DN_CONNECTION_STATE_IDLE) { continue; } - /* Handle data from connections */ + /* 澶勭悊鏉ヨ嚜杩炴帴鐨勬暟鎹 */ int res = HandleStreamResponse(connections[connIdx], node); if (res == RESPONSE_COMPLETE) { - /* receive 'Z' message, conection's state has changed, number of conections without return data -1 */ + /* 鎺ユ敹鍒 'Z' 娑堟伅锛岃繛鎺ョ殑鐘舵佸凡缁忔敼鍙橈紝娌℃湁杩斿洖鏁版嵁鐨勮繛鎺ユ暟鍑1 */ connCount--; elog(DEBUG1, "MPP with-recursive(C) receive message 'Z' from node:%d", connections[connIdx]->nodeIdx); } else if (res == RESPONSE_RECURSIVE_SYNC_R) { - /* receive unexpect 'R' message */ + /* 鎺ユ敹鍒版剰澶栫殑 'R' 娑堟伅 */ elog(ERROR, "MPP with-recursive(C) receive message 'R' from stream node:%d", connections[connIdx]->nodeIdx); @@ -1821,10 +1767,10 @@ void StreamNodeGroup::ConsumerNodeStreamMessage(StreamState* node) } } -/* Mark recursive vfd is invalid before aborting transaction. */ +/* 鍦ㄧ粓姝簨鍔′箣鍓嶆爣璁伴掑綊vfd鏃犳晥 */ void StreamNodeGroup::MarkRecursiveVfdInvalid() { - /* Only stream thread or top consumer need invalidate recursive vfd */ + /* 鍙湁娴佺嚎绋嬫垨鑰呴《灞傛秷璐硅呴渶瑕佷娇閫掑綊vfd鏃犳晥 */ if (IS_PGXC_COORDINATOR || (StreamTopConsumerAmI() == false && StreamThreadAmI() == false)) { return; } @@ -1841,11 +1787,11 @@ void StreamNodeGroup::MarkRecursiveVfdInvalid() #ifndef ENABLE_MULTIPLE_NODES bool InitStreamObject(PlannedStmt* planStmt) { - /* if plan contains stream node, shoule initial some object */ + /* 濡傛灉璁″垝涓寘鍚祦鑺傜偣锛屽垯搴旇鍒濆鍖栦竴浜涘璞 */ if (planStmt->num_streams > 0 && !StreamTopConsumerAmI() && !StreamThreadAmI()) { - /* Set top consumer at the very beginning. */ + /* 鍦ㄦ渶寮濮嬫椂璁剧疆椤跺眰娑堣垂鑰 */ StreamTopConsumerIam(); - /* Build stream context for stream plan. */ + /* 涓烘祦璁″垝鏋勫缓娴佷笂涓嬫枃 */ InitStreamContext(); u_sess->exec_cxt.under_stream_runtime = true; @@ -1858,4 +1804,4 @@ void StreamMarkStop() { u_sess->exec_cxt.executorStopFlag = true; } -#endif +#endif \ No newline at end of file diff --git a/src/gausskernel/process/stream/streamMain.cpp b/src/gausskernel/process/stream/streamMain.cpp index ef4421a5e..cd2890d20 100755 --- a/src/gausskernel/process/stream/streamMain.cpp +++ b/src/gausskernel/process/stream/streamMain.cpp @@ -50,17 +50,29 @@ #include "utils/timestamp.h" #include "instruments/instr_handle_mgr.h" +// 澹版槑CodeGenThreadInitialize鍑芥暟锛岀敤浜庡垵濮嬪寲浠g爜鐢熸垚绾跨▼ extern void CodeGenThreadInitialize(); +// 澹版槑InitRecursiveCTEGlobalVariables鍑芥暟锛岀敤浜庡垵濮嬪寲閫掑綊CTE鐨勫叏灞鍙橀噺 extern void InitRecursiveCTEGlobalVariables(const PlannedStmt* planstmt); +// 涓嬮潰鐨勫嚱鏁伴兘鏄綋鍓嶆枃浠跺唴鐨勯潤鎬佸嚱鏁帮紝鐢ㄤ簬鍒濆鍖栨祦鎵ц璁″垝鐨勫悇涓粍浠跺拰澶勭悊淇″彿 +// 鍒濆鍖栨祦鎵ц璁″垝鐨勭嚎绋 static void InitStreamThread(); +// 鍒濆鍖栨祦鎵ц璁″垝鐨勮矾寰 static void InitStreamPath(); +// 鍒濆鍖栨祦鎵ц璁″垝鐨勪俊鍙峰鐞 static void InitStreamSignal(); +// 鍒濆鍖栨祦鎵ц璁″垝鐨勮祫婧 static void InitStreamResource(); +// 澶勭悊娴佹墽琛岃鍒掔殑淇″彿璺宠浆 static void HandleStreamSigjmp(); +// 鎵ц娴佹墽琛岃鍒掔殑涓诲嚱鏁帮紝鐢ㄤ簬鐢熸垚鍜屽彂閫佹祦鏁版嵁 static void execute_stream_plan(StreamProducer* producer); +// 娴佹墽琛岃鍒掔粨鏉熸椂鐨勫鐞嗗嚱鏁 static void execute_stream_end(StreamProducer* producer); +// 閫鍑哄苟娓呯悊娴佹墽琛岃鍒掔殑鍑芥暟 static void StreamQuitAndClean(int code, Datum arg); +// 閲嶇疆娴佹墽琛岃鍒掔殑宸ヤ綔绾跨▼淇℃伅 static void ResetStreamWorkerInfo(); /* ---------------------------------------------------------------- @@ -68,32 +80,38 @@ static void ResetStreamWorkerInfo(); * stream thread main entrance * ---------------------------------------------------------------- */ +// StreamMain鍑芥暟鏄祦鎵ц璁″垝鐨勪富鍑芥暟锛岀敤浜庡鐞嗘祦鏁版嵁鐢熸垚鍜屽彂閫 + int StreamMain() { sigjmp_buf local_sigjmp_buf; + // 鍒濆鍖栨祦鎵ц璁″垝鐨勭嚎绋 InitStreamThread(); + // 璁剧疆澶勭悊妯″紡涓篘ormalProcessing SetProcessingMode(NormalProcessing); + // 鍦ㄨ繘绋嬮鍑烘椂璋冪敤StreamQuitAndClean鍑芥暟杩涜娓呯悊宸ヤ綔 on_proc_exit(StreamQuitAndClean, 0); /* - * process any libraries that should be preloaded at backend start (this - * likewise can't be done until GUC settings are complete) + * 澶勭悊鍦ㄥ悗绔惎鍔ㄦ椂棰勫姞杞界殑浠讳綍搴 + * 锛堣繖鍚屾牱涓嶈兘鍦℅UC璁剧疆瀹屾垚涔嬪墠鎵ц锛 */ process_local_preload_libraries(); int curTryCounter; int* oldTryCounter = NULL; if (sigsetjmp(local_sigjmp_buf, 1) != 0) { - /* reset signal block flag for threadpool worker */ + // 閲嶇疆淇″彿鍧楁爣蹇楋紝浠ヤ究绾跨▼姹犲伐浣滅嚎绋嬪彲浠ョ户缁鐞嗕俊鍙 ResetInterruptCxt(); if (g_threadPoolControler) { g_threadPoolControler->GetSessionCtrl()->releaseLockIfNecessary(); } gstrace_tryblock_exit(true, oldTryCounter); + // 澶勭悊淇″彿璺宠浆 HandleStreamSigjmp(); if (IS_THREAD_POOL_STREAM) { t_thrd.threadpool_cxt.stream->CleanUp(); @@ -103,23 +121,27 @@ int StreamMain() } oldTryCounter = gstrace_tryblock_entry(&curTryCounter); - + + // 鍒囨崲鍐呭瓨涓婁笅鏂囦负鎵ц鍣ㄧ殑鍐呭瓨涓婁笅鏂 MemoryContext oldMemory = MemoryContextSwitchTo( THREAD_GET_MEM_CXT_GROUP(MEMORY_CONTEXT_EXECUTOR)); #ifdef ENABLE_LLVM_COMPILE + // 鍒濆鍖朙LVM浠g爜鐢熸垚绾跨▼ CodeGenThreadInitialize(); #endif (void)MemoryContextSwitchTo(oldMemory); - - /* We can now handle ereport(ERROR) */ + + /* 鐜板湪鎴戜滑鍙互澶勭悊ereport(ERROR) */ t_thrd.log_cxt.PG_exception_stack = &local_sigjmp_buf; if (IS_THREAD_POOL_STREAM) { + // 閲嶇疆娴佸伐浣滅嚎绋嬬殑淇℃伅 ResetStreamWorkerInfo(); } while (true) { if (IS_THREAD_POOL_STREAM) { + // 姹囨姤褰撳墠鐘舵佷负STATE_IDLE锛屽苟绛夊緟浠诲姟鐨勫埌鏉 pgstat_report_activity(STATE_IDLE, NULL); pgstat_report_waitstatus(STATE_WAIT_COMM); t_thrd.threadpool_cxt.stream->WaitMission(); @@ -127,25 +149,28 @@ int StreamMain() pgstat_report_waitstatus(STATE_WAIT_UNDEFINED); } + // 姹囨姤璋冭瘯鏌ヨID绛変俊鎭 pgstat_report_queryid(u_sess->debug_query_id); pgstat_report_unique_sql_id(false); pgstat_report_global_session_id(u_sess->globalSessionId); pgstat_report_smpid(u_sess->stream_cxt.smp_id); timeInfoRecordStart(); - /* Wait thread ID ready */ + /* 绛夊緟绾跨▼ID鍑嗗灏辩华 */ u_sess->stream_cxt.producer_obj->waitThreadIdReady(); + // 鎵ц娴佽鍒 execute_stream_plan(u_sess->stream_cxt.producer_obj); + // 娴佹墽琛岃鍒掔粨鏉熷悗鐨勫鐞 execute_stream_end(u_sess->stream_cxt.producer_obj); WLMReleaseNodeFromHash(); WLMReleaseIoInfoFromHash(); - /* Reset here so that we can get debug_query_string when Stream thread is in Sync point */ + /* 鍦ㄨ繖閲岄噸缃紝浠ヤ究鍦ㄦ祦绾跨▼澶勪簬鍚屾鐐规椂鍙互鑾峰彇鍒癲ebug_query_string */ t_thrd.postgres_cxt.debug_query_string = NULL; /* - * Note that parent thread will do commit or abort transaction. - * Stream thread should not change clog file + * 璇锋敞鎰忥紝鐖剁嚎绋嬪皢杩涜鎻愪氦鎴栧洖婊氫簨鍔° + * 娴佺嚎绋嬩笉搴旇鏀瑰彉clog鏂囦欢 */ ResetTransactionInfo(); @@ -156,50 +181,64 @@ int StreamMain() } } + // 鍏抽棴GTM杩炴帴 CloseGTM(); return 0; } +// InitStreamThread鍑芥暟鐢ㄤ簬鍒濆鍖栨祦鎵ц璁″垝绾跨▼ + static void InitStreamThread() { + // 鍒濆鍖栭殢鏈烘暟鐢熸垚鍣 initRandomState(0, GetCurrentTimestamp()); + // 璁剧疆娴佹墽琛岃鍒掔嚎绋嬬殑杩涚▼ID鍜岃繍琛屾爣蹇 t_thrd.proc_cxt.MyProcPid = gs_thread_self(); u_sess->exec_cxt.under_stream_runtime = true; t_thrd.codegen_cxt.g_runningInFmgr = false; + // 璁剧疆鍓嶇鍗忚鐗堟湰鍜岃繙绋嬭繛鎺ョ被鍨 FrontendProtocol = PG_PROTOCOL_LATEST; u_sess->attr.attr_common.remoteConnType = REMOTE_CONN_DATANODE; + // 鍒濆鍖栨祦鎵ц璁″垝鐨勮矾寰 InitStreamPath(); + // 鍒濆鍖栨祦鎵ц璁″垝鐨勪俊鍙 InitStreamSignal(); - /* Early initialization */ + /* 鏃╂湡鍒濆鍖 */ BaseInit(); - /* We need to allow SIGINT, etc during the initial transaction */ + /* 鍦ㄥ垵濮嬩簨鍔℃湡闂达紝鎴戜滑闇瑕佸厑璁窼IGINT绛変俊鍙 */ gs_signal_setmask(&t_thrd.libpq_cxt.UnBlockSig, NULL); - /* Initialize the memory tracking information */ + /* 鍒濆鍖栧唴瀛樿窡韪俊鎭 */ MemoryTrackingInit(); if (!IS_THREAD_POOL_STREAM) { + // 鎻愬彇鐢熶骇鑰呬俊鎭 ExtractProduerInfo(); + // 璁剧疆鏁版嵁搴撳拰鐢ㄦ埛淇℃伅 t_thrd.proc_cxt.PostInit->SetDatabaseAndUser( u_sess->stream_cxt.producer_obj->getDbName(), InvalidOid, u_sess->stream_cxt.producer_obj->getUserName()); + // 淇GUC鍙橀噺 repair_guc_variables(); } + // 鍒濆鍖栨祦鎵ц璁″垝鐨勮祫婧 t_thrd.proc_cxt.PostInit->InitStreamWorker(); + // 鍒濆鍖栧悜閲忓嚱鏁版槧灏勮〃 InitVecFuncMap(); + // 鍒濆鍖栨祦鎵ц璁″垝鐨勮祫婧 InitStreamResource(); } static void InitStreamPath() { - /* Compute paths, if we didn't inherit them from postmaster */ + /* 璁$畻璺緞锛屽鏋滄垜浠病鏈変粠postmaster缁ф壙瀹冧滑鐨勮瘽 */ if (my_exec_path[0] == '\0') { if (find_my_exec("postgres", my_exec_path) < 0) ereport(FATAL, (errmsg("openGauss: could not locate my own executable path"))); @@ -213,23 +252,23 @@ static void InitStreamSignal() { (void)gspqsignal(SIGINT, StatementCancelHandler); (void)gspqsignal(SIGTERM, die); - (void)gspqsignal(SIGALRM, handle_sig_alarm); /* timeout conditions */ + (void)gspqsignal(SIGALRM, handle_sig_alarm); /* 瓒呮椂鏉′欢 */ (void)gspqsignal(SIGUSR1, procsignal_sigusr1_handler); (void)gs_signal_unblock_sigusr2(); if (IsUnderPostmaster) { - /* We allow SIGQUIT (quickdie) at all times */ + /* 鎴戜滑鍦ㄤ换浣曟椂鍊欓兘鍏佽SIGQUIT (quickdie) */ (void)sigdelset(&t_thrd.libpq_cxt.BlockSig, SIGQUIT); } } +// InitStreamResource鍑芥暟鐢ㄤ簬鍒濆鍖栨祦鎵ц璁″垝绾跨▼鐨勮祫婧 + static void InitStreamResource() { /* - * Create the memory context we will use in the main loop. - * - * t_thrd.mem_cxt.msg_mem_cxt is reset once per iteration of the main loop, ie, upon - * completion of processing of each command message from the client. + * 鍒涘缓涓诲惊鐜腑灏嗚浣跨敤鐨勫唴瀛樹笂涓嬫枃銆 + * t_thrd.mem_cxt.msg_mem_cxt鍦ㄤ富寰幆鐨勬瘡娆¤凯浠d腑閲嶇疆锛屽嵆鍦ㄥ畬鎴愬鐞嗗鎴风鐨勬瘡涓懡浠ゆ秷鎭悗銆 */ t_thrd.mem_cxt.msg_mem_cxt = AllocSetContextCreate(t_thrd.top_mem_cxt, "MessageContext", @@ -253,11 +292,13 @@ static void InitStreamResource() } } +// ExtractProduerInfo鍑芥暟鐢ㄤ簬鎻愬彇鐢熶骇鑰呯殑淇℃伅 void ExtractProduerInfo() { if (u_sess->stream_cxt.producer_obj == NULL) { return; } + // 鎻愬彇WLM鍙傛暟銆佹煡璇D銆佽窡韪爣蹇楃瓑淇℃伅 u_sess->wlm_cxt->wlm_params = u_sess->stream_cxt.producer_obj->getWlmParams(); u_sess->instr_cxt.gs_query_id->procId = u_sess->stream_cxt.producer_obj->getExplainThreadid(); u_sess->exec_cxt.need_track_resource = u_sess->stream_cxt.producer_obj->getExplainTrack(); @@ -266,16 +307,17 @@ void ExtractProduerInfo() u_sess->stream_cxt.producer_obj->getGlobalSessionId(&u_sess->globalSessionId); WLMGeneralParam *g_wlm_params = &u_sess->wlm_cxt->wlm_params; + // 璁剧疆鎺у埗缁勪俊鎭 errno_t ret = sprintf_s(u_sess->wlm_cxt->control_group, sizeof(u_sess->wlm_cxt->control_group), "%s", g_wlm_params->cgroup); securec_check_ss(ret, "\0", "\0"); - /* Get the node group information */ + /* 鑾峰彇鑺傜偣缁勪俊鎭 */ t_thrd.wlm_cxt.thread_node_group = WLMGetNodeGroupFromHTAB(g_wlm_params->ngroup); t_thrd.wlm_cxt.thread_climgr = &t_thrd.wlm_cxt.thread_node_group->climgr; t_thrd.wlm_cxt.thread_srvmgr = &t_thrd.wlm_cxt.thread_node_group->srvmgr; - /* Set the right pgxcnodeid */ + /* 璁剧疆姝g‘鐨刾gxcnodeid */ u_sess->pgxc_cxt.PGXCNodeId = u_sess->stream_cxt.producer_obj->getPgxcNodeId(); u_sess->instr_cxt.global_instr = u_sess->stream_cxt.producer_obj->getStreamInstrumentation(); u_sess->proc_cxt.MyProcPort->database_name = u_sess->stream_cxt.producer_obj->getDbName(); @@ -302,14 +344,14 @@ void ExtractProduerInfo() u_sess->stream_cxt.dummy_thread = false; } - /* stream workers share the same session memory entry as their parents */ + /* 娴佸紡宸ヤ綔鑰呭叡浜笌鍏剁埗杩涚▼鐩稿悓鐨勪細璇濆唴瀛樻潯鐩 */ t_thrd.shemem_ptr_cxt.mySessionMemoryEntry = u_sess->stream_cxt.producer_obj->getSessionMemory(); if (t_thrd.proc != NULL) { t_thrd.proc->sessMemorySessionid = u_sess->stream_cxt.producer_obj->getParentSessionid(); Assert(t_thrd.proc->sessMemorySessionid == t_thrd.shemem_ptr_cxt.mySessionMemoryEntry->sessionid); } - /* Initialize the global variables for recursive */ + /* 鍒濆鍖栭掑綊鐨勫叏灞鍙橀噺 */ InitRecursiveCTEGlobalVariables(u_sess->stream_cxt.producer_obj->getPlan()); STREAM_LOG(DEBUG2, "enter StreamMain, StreamKey(%lu, %u, %u)", @@ -318,34 +360,36 @@ void ExtractProduerInfo() u_sess->stream_cxt.producer_obj->getKey().smpIdentifier); } +// HandleStreamSigjmp鍑芥暟鐢ㄤ簬澶勭悊娴佹墽琛岃鍒掔嚎绋嬬殑淇″彿璺宠浆 + static void HandleStreamSigjmp() { + // 鎶ュ憡绛夊緟鐘舵佷负STATE_WAIT_UNDEFINED pgstat_report_waitstatus(STATE_WAIT_UNDEFINED); t_thrd.pgxc_cxt.GlobalNetInstr = NULL; - /* output the memory tracking information when error happened */ + /* 褰撳彂鐢熼敊璇椂锛岃緭鍑哄唴瀛樿拷韪俊鎭 */ MemoryTrackingOutputFile(); - /* Since not using PG_TRY, must reset error stack by hand */ + /* 鐢变簬娌℃湁浣跨敤PG_TRY锛屽繀椤绘墜鍔ㄩ噸缃敊璇爢鏍 */ t_thrd.log_cxt.error_context_stack = NULL; t_thrd.log_cxt.call_stack = NULL; - /* reset buffer strategy flag */ + /* 閲嶇疆缂撳啿绛栫暐鏍囧織 */ t_thrd.storage_cxt.is_btree_split = false; - /* Prevent interrupts while cleaning up */ + /* 鍦ㄦ竻鐞嗘椂闃绘涓柇 */ HOLD_INTERRUPTS(); /* - * Turn off these interrupts too. This is only needed here and not in - * other exception-catching places since these interrupts are only - * enabled while we wait for client input. + * 涔熷叧闂繖浜涗腑鏂傝繖浠呭湪姝ゅ闇瑕侊紝鑰屼笉鏄湪鍏朵粬鎹曡幏寮傚父鐨勫湴鏂癸紝 + * 鍥犱负杩欎簺涓柇鍙湁鍦ㄧ瓑寰呭鎴风杈撳叆鏃舵墠鍚敤銆 */ t_thrd.postgres_cxt.DoingCommandRead = false; /* - * Abort the current transaction in order to recover. + * 涓轰簡鎭㈠锛屼腑姝㈠綋鍓嶄簨鍔° */ ereport(DEBUG1, (errmsg("stream thread %lu end transaction " XID_FMT " abnormally", @@ -353,20 +397,20 @@ static void HandleStreamSigjmp() GetCurrentTransactionIdIfAny()))); /* - * when clearing the BCM encounter ERROR, we should ResetBCMArray, or it - * will enter ClearBCMArray infinite loop, then coredump. + * 鍦ㄦ竻闄CM鏃堕亣鍒癊RROR鏃讹紝鎴戜滑搴旇ResetBCMArray锛 + * 鍚﹀垯瀹冨皢杩涘叆ClearBCMArray鏃犻檺寰幆锛岀劧鍚巆ore dump銆 */ ResetBCMArray(); - /* release operator-level hash table in memory */ + /* 鍦ㄥ唴瀛樹腑閲婃斁鎿嶄綔绗︾骇鍒殑鍝堝笇琛 */ releaseExplainTable(); - /* Mark recursive vfd is invalid before aborting transaction. */ + /* 鍦ㄤ腑姝簨鍔′箣鍓嶆爣璁伴掑綊vfd涓烘棤鏁 */ StreamNodeGroup::MarkRecursiveVfdInvalid(); AbortCurrentTransaction(); - /* release resource held by lsc */ + /* 閲婃斁lsc鎸佹湁鐨勮祫婧 */ AtEOXact_SysDBCache(false); LWLockReleaseAll(); @@ -384,66 +428,62 @@ static void HandleStreamSigjmp() RESUME_INTERRUPTS(); timeInfoRecordEnd(); + // 璋冪敤StreamNodeGroup鐨剆yncQuit鍑芥暟锛屼紶鍏TREAM_ERROR鍙傛暟锛岃〃绀哄紓甯搁鍑 StreamNodeGroup::syncQuit(STREAM_ERROR); } +// execute_stream_plan鍑芥暟鐢ㄤ簬鎵ц娴佹墽琛岃鍒 + static void execute_stream_plan(StreamProducer* producer) { /* - * Start up a transaction command. All queries generated by the - * query_string will be in this same command block, *unless* we find a - * BEGIN/COMMIT/ABORT statement; we have to force a new xact command after - * one of those, else bad things will happen in xact.c. (Note that this - * will normally change current memory context.) + * 鍚姩涓涓簨鍔″懡浠ゃ傜敱query_string鐢熸垚鐨勬墍鏈夋煡璇㈤兘灏嗗湪鐩稿悓鐨勫懡浠ゅ潡涓紝*闄ら潪*鎴戜滑鎵惧埌浜 + * 涓涓狟EGIN/COMMIT/ABORT璇彞锛涘湪杩欑鎯呭喌涓嬶紝鎴戜滑蹇呴』鍦ㄥ叾鍚庡己鍒舵柊鐨剎act鍛戒护锛屽惁鍒欏湪xact.c涓細鍑虹幇闂銆 + * 锛堣娉ㄦ剰锛岃繖閫氬父浼氭敼鍙樺綋鍓嶅唴瀛樹笂涓嬫枃銆傦級 */ start_xact_command(); - producer->setUpStreamTxnEnvironment(); + producer->setUpStreamTxnEnvironment(); // 璁剧疆娴佷簨鍔$幆澧 - PlannedStmt* planstmt = producer->getPlan(); - CommandDest dest = producer->getDest(); - bool save_log_statement_stats = u_sess->attr.attr_common.log_statement_stats; + PlannedStmt* planstmt = producer->getPlan(); // 鑾峰彇璁″垝璇彞 + CommandDest dest = producer->getDest(); // 鑾峰彇鍛戒护鐩爣 + bool save_log_statement_stats = u_sess->attr.attr_common.log_statement_stats; // 淇濆瓨log_statement_stats璁剧疆 bool isTopLevel = false; - const char* commandTag = NULL; + const char* commandTag = NULL; // 鍛戒护鏍囩 char completionTag[COMPLETION_TAG_BUFSIZE]; Portal portal = NULL; DestReceiver* receiver = NULL; int16 format; char msec_str[PRINTF_DST_MAX]; - t_thrd.postgres_cxt.debug_query_string = planstmt->query_string; - pgstat_report_activity(STATE_RUNNING, t_thrd.postgres_cxt.debug_query_string); - /* Use planNodeId as thread_level, same as the key which SCTP use for send/receive */ + t_thrd.postgres_cxt.debug_query_string = planstmt->query_string; // 璁剧疆璋冭瘯鏌ヨ瀛楃涓 + pgstat_report_activity(STATE_RUNNING, t_thrd.postgres_cxt.debug_query_string); // 鎶ュ憡娲诲姩鐘舵 + /* 浣跨敤planNodeId浣滀负thread_level锛屼笌SCTP鐢ㄤ簬鍙戦/鎺ユ敹鐨勯敭鐩稿悓 */ pgstat_report_parent_sessionid(producer->getParentSessionid(), producer->getKey().planNodeId); if (u_sess->instr_cxt.global_instr && - u_sess->instr_cxt.perf_monitor_enable) // Don't use perf util you set has_use_perf = true - CPUMon::Initialize(CMON_GENERAL); + u_sess->instr_cxt.perf_monitor_enable) // 浠呭綋has_use_perf = true鏃讹紝浣跨敤perf鐩戞帶锛岄伩鍏嶄娇鐢╬erf util + CPUMon::Initialize(CMON_GENERAL); // 鍒濆鍖朇PU鐩戞帶 /* - * We use save_log_statement_stats so ShowUsage doesn't report incorrect - * results because ResetUsage wasn't called. + * 鎴戜滑浣跨敤save_log_statement_stats浠ヤ究ShowUsage涓嶄細鍥犱负ResetUsage鏈璋冪敤鑰屾姤鍛婁笉姝g‘鐨勭粨鏋溿 */ if (save_log_statement_stats) ResetUsage(); isTopLevel = true; - // For now plan shipping is used only for SELECTs, in future - // we should remove this hard coding and get the tag automatically + // 鐩墠锛岃鍒掕繍閫佷粎鐢ㄤ簬SELECT璇彞锛屽皢鏉ユ垜浠簲璇ュ幓鎺夎繖涓‖缂栫爜锛岃嚜鍔ㄨ幏鍙栨爣绛 commandTag = "SELECT"; set_ps_display(commandTag, false); - BeginCommand(commandTag, dest); + BeginCommand(commandTag, dest); // 寮濮嬪懡浠 /* - * If we are in an aborted transaction, reject all commands except - * COMMIT/ABORT. It is important that this test occur before we try - * to do parse analysis, rewrite, or planning, since all those phases - * try to do database accesses, which may fail in abort state. (It - * might be safe to allow some additional utility commands in this - * state, but not many...) + * 濡傛灉鎴戜滑澶勪簬涓涓腑姝㈢殑浜嬪姟鍧楃姸鎬侊紝鎷掔粷闄や簡COMMIT/ABORT涔嬪鐨勬墍鏈夊懡浠ゃ + * 杩欎釜娴嬭瘯鍦ㄦ垜浠皾璇曡繘琛岃В鏋愬垎鏋愩侀噸鍐欐垨璁″垝涔嬪墠鍙戠敓锛屽洜涓烘墍鏈夎繖浜涢樁娈甸兘灏濊瘯杩涜鏁版嵁搴撹闂紝 + * 鑰屽湪涓鐘舵佷笅鍙兘浼氬け璐ャ傦紙杩欏彲鑳藉畨鍏ㄥ湴鍏佽鍦ㄨ繖绉嶇姸鎬佷笅鎵ц涓浜涘叾浠栧疄鐢ㄧ▼搴忓懡浠わ紝浣嗕笉鏄お澶...锛 */ if (IsAbortedTransactionBlockState()) // && ereport(ERROR, @@ -453,51 +493,50 @@ static void execute_stream_plan(StreamProducer* producer) u_sess->proc_cxt.firstChar), errdetail_abort())); - /* Make sure we are in a transaction command */ + /* 纭繚鎴戜滑鍦ㄤ竴涓簨鍔″懡浠や腑 */ start_xact_command(); - /* If we got a cancel signal in parsing or prior command, quit */ + /* 濡傛灉鍦ㄨВ鏋愭垨涔嬪墠鐨勫懡浠や腑鏀跺埌鍙栨秷淇″彿锛屽垯閫鍑 */ CHECK_FOR_INTERRUPTS(); /* - * Create unnamed portal to run the query or queries in. If there - * already is one, silently drop it. + * 鍒涘缓涓涓棤鍚峱ortal鏉ヨ繍琛屾煡璇㈡垨鏌ヨ銆傚鏋滃凡缁忔湁涓涓紝灏遍粯榛樺湴鏀惧純瀹冦 */ portal = CreatePortal("", true, true); - /* Don't display the portal in pg_cursors */ + /* 鍦╬g_cursors涓笉鏄剧ずportal */ portal->visible = false; - u_sess->instr_cxt.global_instr = producer->getStreamInstrumentation(); - u_sess->instr_cxt.obs_instr = producer->getOBSInstrumentation(); + u_sess->instr_cxt.global_instr = producer->getStreamInstrumentation(); // 鑾峰彇娴佷华鍣ㄤ俊鎭 + u_sess->instr_cxt.obs_instr = producer->getOBSInstrumentation(); // 鑾峰彇OBS浠櫒淇℃伅 if (u_sess->instr_cxt.obs_instr) u_sess->instr_cxt.p_OBS_instr_valid = u_sess->instr_cxt.obs_instr->m_p_globalOBSInstrument_valid; PortalDefineQuery(portal, NULL, "DUMMY", commandTag, lappend(NULL, planstmt), NULL); /* - * Start the portal. No parameters here. + * 鍚姩portal銆傝繖閲屾病鏈夊弬鏁般 */ PortalStart(portal, producer->getParams(), 0, producer->getSnapShot()); format = 0; PortalSetResultFormat(portal, 1, &format); - receiver = CreateDestReceiver(dest); - if (dest >= DestTupleBroadCast) + receiver = CreateDestReceiver(dest); // 鍒涘缓鐩爣鎺ユ敹鍣 + if (dest >= DestTupleBroadCast) // 濡傛灉鐩爣鏄箍鎾紝璁剧疆娴佹帴鏀跺櫒鍙傛暟 SetStreamReceiverParams(receiver, producer, portal); /* - * Run the portal to completion, and then drop it (and the receiver). + * 杩愯portal鍒板畬鎴愶紝骞朵笖鐒跺悗涓㈠純瀹冿紙浠ュ強鎺ユ敹鍣級銆 */ (void)PortalRun(portal, FETCH_ALL, isTopLevel, receiver, receiver, completionTag); - (*receiver->rDestroy)(receiver); + (*receiver->rDestroy)(receiver); // 閿姣佹帴鏀跺櫒 - PortalDrop(portal, false); + PortalDrop(portal, false); // 涓㈠純portal - finish_xact_command(); + finish_xact_command(); // 瀹屾垚浜嬪姟鍛戒护 /* - * Emit duration logging if appropriate. + * 濡傛灉鍚堥傦紝璁板綍鎸佺画鏃堕棿鏃ュ織銆 */ switch (check_log_duration(msec_str, false)) { case 1: @@ -518,17 +557,19 @@ static void execute_stream_plan(StreamProducer* producer) ShowUsage("QUERY STATISTICS"); } +// execute_stream_end鍑芥暟鐢ㄤ簬缁撴潫娴佹墽琛岃鍒 + static void execute_stream_end(StreamProducer* producer) { int consumer_number; int i, res; - consumer_number = producer->getConnNum(); - StreamTransport** transport = producer->getTransport(); + consumer_number = producer->getConnNum(); // 鑾峰彇杩炴帴鏁 + StreamTransport** transport = producer->getTransport(); // 鑾峰彇浼犺緭瀵硅薄 - // prepare an end message to all the consumer backend thread. + // 鍑嗗涓涓粨鏉熸秷鎭彂閫佸埌鎵鏈夌殑娑堣垂鑰呭悗绔嚎绋嬨 // - // if is dummy, do not bother send + // 濡傛灉鏄櫄鎷熺殑锛屽氨涓嶉渶瑕佸彂閫佷簡 if (producer->isDummy() == false) { for (i = 0; i < consumer_number; i++) { if (producer->netSwitchDest(i)) { @@ -540,7 +581,7 @@ static void execute_stream_end(StreamProducer* producer) pq_endmessage(&buf); } else if (PG_PROTOCOL_MAJOR(FrontendProtocol) >= 2) pq_putemptymessage('Z'); - /* Flush output at end of cycle in any case. */ + /* 鍦ㄤ换浣曟儏鍐典笅锛屽湪鍛ㄦ湡缁撴潫鏃跺埛鏂拌緭鍑恒 */ res = pq_flush(); if (res == EOF) { transport[i]->release(); @@ -549,10 +590,10 @@ static void execute_stream_end(StreamProducer* producer) } } } - producer->finalizeLocalStream(); - timeInfoRecordEnd(); - StreamNodeGroup::syncQuit(STREAM_COMPLETE); - ForgetRegisterStreamSnapshots(); + producer->finalizeLocalStream(); // 瀹屾垚鏈湴娴佸鐞 + timeInfoRecordEnd(); // 璁板綍鏃堕棿淇℃伅缁撴潫 + StreamNodeGroup::syncQuit(STREAM_COMPLETE); // 鍚屾閫鍑 + ForgetRegisterStreamSnapshots(); // 蹇樿娉ㄥ唽娴佸揩鐓 } /* @@ -560,66 +601,67 @@ static void execute_stream_end(StreamProducer* producer) */ static void StreamQuitAndClean(int code, Datum arg) { - /* Close connection with GTM, if active */ + /* 鍏抽棴涓嶨TM鐨勮繛鎺ワ紝濡傛灉婵娲 */ CloseGTM(); - /* Free remote xact state */ + /* 鍏嶈垂杩滅▼绮剧‘鐘舵 */ free_RemoteXactState(); } -// reset some flag related to stream +// 閲嶇疆涓浜涗笌娴佺浉鍏崇殑鏍囧織 void ResetStreamEnv() { - t_thrd.subrole = NO_SUBROLE; - u_sess->stream_cxt.dummy_thread = false; - u_sess->exec_cxt.executorStopFlag = false; - u_sess->stream_cxt.global_obj = NULL; - u_sess->stream_cxt.producer_obj = NULL; - u_sess->instr_cxt.global_instr = NULL; - u_sess->instr_cxt.thread_instr = NULL; - u_sess->exec_cxt.under_stream_runtime = false; - u_sess->stream_cxt.in_waiting_quit = false; - u_sess->stream_cxt.enter_sync_point = false; - t_thrd.pgxc_cxt.GlobalNetInstr = NULL; + t_thrd.subrole = NO_SUBROLE; // 閲嶇疆瀛愯鑹 + u_sess->stream_cxt.dummy_thread = false; // 铏氭嫙绾跨▼鏍囧織閲嶇疆涓篺alse + u_sess->exec_cxt.executorStopFlag = false; // 鎵ц鍣ㄥ仠姝㈡爣蹇楅噸缃负false + u_sess->stream_cxt.global_obj = NULL; // 鍏ㄥ眬瀵硅薄閲嶇疆涓篘ULL + u_sess->stream_cxt.producer_obj = NULL; // 鐢熶骇鑰呭璞¢噸缃负NULL + u_sess->instr_cxt.global_instr = NULL; // 鍏ㄥ眬鎸囦护閲嶇疆涓篘ULL + u_sess->instr_cxt.thread_instr = NULL; // 绾跨▼鎸囦护閲嶇疆涓篘ULL + u_sess->exec_cxt.under_stream_runtime = false; // 鍦ㄦ祦杩愯鏃舵爣蹇楅噸缃负false + u_sess->stream_cxt.in_waiting_quit = false; // 鍦ㄧ瓑寰呴鍑烘爣蹇楅噸缃负false + u_sess->stream_cxt.enter_sync_point = false; // 杩涘叆鍚屾鐐规爣蹇楅噸缃负false + t_thrd.pgxc_cxt.GlobalNetInstr = NULL; // 鍏ㄥ眬缃戠粶鎸囦护閲嶇疆涓篘ULL #ifndef ENABLE_MULTIPLE_NODES - u_sess->opt_cxt.query_dop = u_sess->attr.attr_sql.query_dop_tmp; + u_sess->opt_cxt.query_dop = u_sess->attr.attr_sql.query_dop_tmp; // 鏌ヨDOP閲嶇疆涓轰复鏃禗OP #endif /* - * When gaussdb backend running in Query or Operator level, we are going to use global - * variable notplanshipping to mark current query is not plan shipping, so we do string - * initialization here + * 褰揋aussDB鍚庣鍦ㄦ煡璇㈡垨鎿嶄綔绾у埆杩愯鏃讹紝鎴戜滑灏嗕娇鐢ㄥ叏灞鍙橀噺notplanshipping鏉ユ爣璁板綋鍓嶆煡璇笉鏄鍒掑彂璐э紝 + * 鎵浠ユ垜浠湪杩欓噷杩涜瀛楃涓插垵濮嬪寲銆 */ - u_sess->opt_cxt.not_shipping_info->need_log = true; - errno_t errorno = memset_s( - u_sess->opt_cxt.not_shipping_info->not_shipping_reason, NOTPLANSHIPPING_LENGTH, '\0', NOTPLANSHIPPING_LENGTH); + u_sess->opt_cxt.not_shipping_info->need_log = true; // 闇瑕佹棩蹇楁爣蹇楄缃负true + errno_t errorno = memset_s(u_sess->opt_cxt.not_shipping_info->not_shipping_reason, + NOTPLANSHIPPING_LENGTH, '\0', NOTPLANSHIPPING_LENGTH); securec_check_c(errorno, "\0", "\0"); - t_thrd.postgres_cxt.table_created_in_CTAS = false; + t_thrd.postgres_cxt.table_created_in_CTAS = false; // CTAS鏍囧織閲嶇疆涓篺alse if (IS_PGXC_COORDINATOR) { - u_sess->exec_cxt.need_track_resource = false; + u_sess->exec_cxt.need_track_resource = false; // 闇瑕佽窡韪祫婧愭爣蹇楅噸缃负false } - u_sess->instr_cxt.gs_query_id->queryId = 0; + u_sess->instr_cxt.gs_query_id->queryId = 0; // 鏌ヨID閲嶇疆涓0 - u_sess->wlm_cxt->local_foreign_respool = NULL; - t_thrd.postmaster_cxt.forceNoSeparate = false; + u_sess->wlm_cxt->local_foreign_respool = NULL; // 鏈湴澶栭儴璧勬簮姹犻噸缃负NULL + t_thrd.postmaster_cxt.forceNoSeparate = false; // 寮哄埗涓嶅垎绂绘爣蹇楅噸缃负false - u_sess->pcache_cxt.gpc_remote_msg = false; + u_sess->pcache_cxt.gpc_remote_msg = false; // 杩滅▼娑堟伅鏍囧織閲嶇疆涓篺alse - t_thrd.postgres_cxt.gpc_fisrt_send_clean = true; + t_thrd.postgres_cxt.gpc_fisrt_send_clean = true; // 绗竴娆″彂閫佹竻闄ゆ爣蹇楅噸缃负true if (IS_PGXC_COORDINATOR) { WLMStatusTag status = t_thrd.wlm_cxt.collect_info->status; - if (!(status == WLM_STATUS_FINISHED || status == WLM_STATUS_ABORT)) + if (!(status == WLM_STATUS_FINISHED || status == WLM_STATUS_ABORT)) { return; + } } if (IS_PGXC_DATANODE) { WLMStatusTag status = t_thrd.wlm_cxt.dn_cpu_detail->status; - if (!(status == WLM_STATUS_FINISHED || status == WLM_STATUS_ABORT)) + if (!(status == WLM_STATUS_FINISHED || status == WLM_STATUS_ABORT)) { return; + } } t_thrd.shemem_ptr_cxt.mySessionMemoryEntry->initMemInChunks = t_thrd.utils_cxt.trackedMemChunks; @@ -654,28 +696,29 @@ void SetStreamWorkerInfo(StreamProducer* proObj) return; } - u_sess->stream_cxt.producer_obj = proObj; - u_sess->stream_cxt.smp_id = proObj->getKey().smpIdentifier; - u_sess->stream_cxt.producer_dop = proObj->getParallelDesc().producerDop; - u_sess->debug_query_id = proObj->getKey().queryId; - u_sess->utils_cxt.sync_guc_variables = u_sess->stream_cxt.producer_obj->get_sync_guc_variables(); - // set the stopFlag; - u_sess->stream_cxt.global_obj = u_sess->stream_cxt.producer_obj->getNodeGroup(); + u_sess->stream_cxt.producer_obj = proObj; // 璁剧疆鐢熶骇鑰呭璞 + u_sess->stream_cxt.smp_id = proObj->getKey().smpIdentifier; // 璁剧疆SMP鏍囪瘑绗 + u_sess->stream_cxt.producer_dop = proObj->getParallelDesc().producerDop; // 璁剧疆鐢熶骇鑰匘OP + u_sess->debug_query_id = proObj->getKey().queryId; // 璁剧疆璋冭瘯鏌ヨID + u_sess->utils_cxt.sync_guc_variables = u_sess->stream_cxt.producer_obj->get_sync_guc_variables(); // 鍚屾GUC鍙橀噺 + // 璁剧疆鍋滄鏍囧織 + u_sess->stream_cxt.global_obj = u_sess->stream_cxt.producer_obj->getNodeGroup(); // 璁剧疆鍏ㄥ眬瀵硅薄 u_sess->stream_cxt.global_obj->setStopFlagPoint( - u_sess->stream_cxt.producer_obj->getNodeGroupIdx(), &u_sess->exec_cxt.executorStopFlag); + u_sess->stream_cxt.producer_obj->getNodeGroupIdx(), &u_sess->exec_cxt.executorStopFlag); // 璁剧疆鍋滄鏍囧織鐐 } static void ResetStreamWorkerInfo() { - u_sess->stream_cxt.producer_obj = NULL; - u_sess->stream_cxt.global_obj = NULL; + u_sess->stream_cxt.producer_obj = NULL; // 閲嶇疆鐢熶骇鑰呭璞′负NULL + u_sess->stream_cxt.global_obj = NULL; // 閲嶇疆鍏ㄥ眬瀵硅薄涓篘ULL } static void StoreStreamSyncParam(StreamSyncParam *syncParam) { - syncParam->TempNamespace = u_sess->catalog_cxt.myTempNamespace; - syncParam->TempToastNamespace = u_sess->catalog_cxt.myTempToastNamespace; - syncParam->IsBinaryUpgrade = u_sess->proc_cxt.IsBinaryUpgrade; + syncParam->TempNamespace = u_sess->catalog_cxt.myTempNamespace; // 瀛樺偍涓存椂鍛藉悕绌洪棿 + syncParam->TempToastNamespace = u_sess->catalog_cxt.myTempToastNamespace; // 瀛樺偍涓存椂TOAST鍛藉悕绌洪棿 + syncParam->IsBinaryUpgrade = u_sess->proc_cxt.IsBinaryUpgrade; // 瀛樺偍浜岃繘鍒跺崌绾ф爣蹇 + // 濡傛灉閫氫俊IPC妯″潡鐨勬棩蹇楀紑鍚紝骞朵笖褰撳墠杩涚▼鐨勫伐浣滅増鏈彿澶т簬绛変簬92060锛屽垯璁剧疆CommIpcLog涓簍rue锛屽惁鍒欎负false銆 if (module_logging_is_on(MOD_COMM_IPC) && (t_thrd.proc && t_thrd.proc->workingVersionNum >= 92060)) { syncParam->CommIpcLog = true; } else { @@ -695,39 +738,39 @@ void RestoreStreamSyncParam(StreamSyncParam *syncParam) ThreadId ApplyStreamThread(StreamProducer *producer) { - ThreadId tid = InvalidTid; + ThreadId tid = InvalidTid; // 鍒濆鍖栫嚎绋婭D涓烘棤鏁堝 - producer->setParentSessionid(t_thrd.proc->sessMemorySessionid); - StoreStreamSyncParam(&producer->m_syncParam); + producer->setParentSessionid(t_thrd.proc->sessMemorySessionid); // 璁剧疆鐢熶骇鑰呯殑鐖朵細璇滻D涓哄綋鍓嶄細璇濈殑鍐呭瓨浼氳瘽ID + StoreStreamSyncParam(&producer->m_syncParam); // 瀛樺偍娴佸悓姝ュ弬鏁 - if (t_thrd.threadpool_cxt.group != NULL) { - tid = t_thrd.threadpool_cxt.group->GetStreamFromPool(producer); + if (t_thrd.threadpool_cxt.group != NULL) { // 濡傛灉绾跨▼姹犵粍涓嶄负绌 + tid = t_thrd.threadpool_cxt.group->GetStreamFromPool(producer); // 浠庣嚎绋嬫睜缁勪腑鑾峰彇娴佺嚎绋 STREAM_LOG(DEBUG2, "[StreamPool] Apply thread %lu query_id %lu, tlevel %u, smpid %u", tid, producer->getKey().queryId, producer->getKey().planNodeId, - producer->getKey().smpIdentifier); + producer->getKey().smpIdentifier); // 璁板綍鏃ュ織 } else { - producer->setChildSlot(AssignPostmasterChildSlot()); - if (producer->getChildSlot() == -1) { + producer->setChildSlot(AssignPostmasterChildSlot()); // 鍒嗛厤瀛愯繘绋嬫Ы浣 + if (producer->getChildSlot() == -1) { // 濡傛灉妲戒綅鍒嗛厤澶辫触锛岃繑鍥炴棤鏁堢嚎绋婭D return InvalidTid; } - tid = initialize_util_thread(STREAM_WORKER, producer); + tid = initialize_util_thread(STREAM_WORKER, producer); // 鍒濆鍖栨祦宸ヤ綔绾跨▼ } - return tid; + return tid; // 杩斿洖绾跨▼ID } void RestoreStream() { /* - * We should restoreStreamEnter after release the memory context. - * Make sure top consumer thread exit after stream thread. + * 鍦ㄩ噴鏀惧唴瀛樹笂涓嬫枃鍚庯紝鎴戜滑搴旇鍦╮estoreStreamEnter涔嬪悗杩涜鎭㈠銆 + * 纭繚椤剁骇娑堣垂鑰呯嚎绋嬪湪娴佺嚎绋嬩箣鍚庨鍑恒 */ if (StreamThreadAmI() && u_sess->stream_cxt.global_obj) { /* - * Set CurrentResourceOwner to NULL or will core dumped in ResourceOwnerEnlargePthreadMutex - * case t_thrd.top_mem_cxt has been set NULL. + * 璁剧疆CurrentResourceOwner涓篘ULL锛屽惁鍒欏湪ResourceOwnerEnlargePthreadMutex涓皢鍙戠敓鏍稿績杞偍锛 + * 鍥犱负t_thrd.top_mem_cxt宸茬粡璁剧疆涓篘ULL銆 */ t_thrd.utils_cxt.CurrentResourceOwner = NULL; u_sess->stream_cxt.global_obj->restoreStreamEnter(); @@ -741,7 +784,7 @@ void StreamExit() return; } - /* Reset to Local vfd if we have attach it to global vfdcache */ + /* 濡傛灉鎴戜滑宸茬粡灏嗗叾闄勫姞鍒板叏灞vfdcache锛屽垯閲嶇疆涓烘湰鍦皏fd */ ResetToLocalVfdCache(); CleanupDfsHandlers(true); @@ -750,7 +793,7 @@ void StreamExit() AtProcExit_Buffers(0, 0); ShutdownPostgres(0, 0); - if(!EnableLocalSysCache()) { + if (!EnableLocalSysCache()) { AtProcExit_Files(0, 0); } StreamQuitAndClean(0, 0); @@ -758,21 +801,21 @@ void StreamExit() RestoreStream(); if (!EnableLocalSysCache()) { - /* release memory context and reset flags. */ + /* 閲婃斁鍐呭瓨涓婁笅鏂囧苟閲嶇疆鏍囧織銆 */ MemoryContextReset(u_sess->syscache_cxt.SysCacheMemCxt); errno_t rc = EOK; rc = memset_s(u_sess->syscache_cxt.SysCache, sizeof(CatCache*) * SysCacheSize, - 0, sizeof(CatCache*) * SysCacheSize); + 0, sizeof(CatCache*) * SysCacheSize); securec_check(rc, "\0", "\0"); rc = memset_s(u_sess->syscache_cxt.SysCacheRelationOid, sizeof(Oid) * SysCacheSize, - 0, sizeof(Oid) * SysCacheSize); + 0, sizeof(Oid) * SysCacheSize); securec_check(rc, "\0", "\0"); } - /* release statement_cxt */ + /* 閲婃斁statement_cxt */ if (t_thrd.proc_cxt.MyBackendId != InvalidBackendId) { release_statement_context(t_thrd.shemem_ptr_cxt.MyBEEntry, __FUNCTION__, __LINE__); } free_session_context(u_sess); -} +} \ No newline at end of file diff --git a/src/gausskernel/process/stream/streamTransportComm.cpp b/src/gausskernel/process/stream/streamTransportComm.cpp index 6fffd9079..66caa99ca 100644 --- a/src/gausskernel/process/stream/streamTransportComm.cpp +++ b/src/gausskernel/process/stream/streamTransportComm.cpp @@ -32,11 +32,17 @@ StreamCOMM::StreamCOMM(libcommaddrinfo* addr, bool flag) : m_addr(addr) { + /* 鍒濆鍖栬妭鐐瑰悕绉颁负绌哄瓧绗︿覆 */ m_nodeName[0] = '\0'; + /* 鍒濆鍖栬妭鐐筄ID涓烘棤鏁圤ID */ m_nodeoid = InvalidOid; + /* 璁剧疆閫氫俊绫诲瀷涓篠TREAM_COMM */ m_type = STREAM_COMM; + /* 璁剧疆鍙戦佹柟鏍囧織 */ m_sendSide = flag; + /* 鍒濆鍖栫鍙d负NULL */ m_port = NULL; + /* 鍒濆鍖栫紦鍐插尯涓篘ULL */ m_buffer = NULL; } @@ -99,13 +105,20 @@ void StreamCOMM::init(char* dbname, char* usrname) */ void StreamCOMM::allocNetBuffer() { + /* 鍒嗛厤绔彛缁撴瀯鍐呭瓨骞跺垵濮嬪寲涓洪浂 */ m_port = (Port*)palloc0(sizeof(Port)); + /* 濡傛灉鏄彂閫佹柟 */ if (m_sendSide) { + /* 鍒嗛厤StreamBuffer缁撴瀯鍐呭瓨骞跺垵濮嬪寲涓洪浂 */ m_buffer = (StreamBuffer*)palloc0(sizeof(StreamBuffer)); + /* 璁剧疆鍙戦佺紦鍐插尯澶у皬涓篠TREAM_BUFFER_SIZE */ m_buffer->PqSendBufferSize = STREAM_BUFFER_SIZE; + /* 璁剧疆鍙戦佹寚閽堜负0 */ m_buffer->PqSendPointer = 0; + /* 璁剧疆鍙戦佸紑濮嬩綅缃负0 */ m_buffer->PqSendStart = 0; + /* 璁剧疆閫氫俊蹇欐爣蹇椾负false */ m_buffer->PqCommBusy = false; } } @@ -118,17 +131,17 @@ void StreamCOMM::allocNetBuffer() bool StreamCOMM::setActive() { /* - * if we use parallel send mode, - * and the head of address info list is already close, - * we must continue to send, - * and gs_broadcast can send to other node in address info list. + * 濡傛灉浣跨敤骞惰鍙戦佹ā寮忥紝 + * 骞朵笖鍦板潃淇℃伅鍒楄〃鐨勫ご閮ㄥ凡缁忓叧闂紝 + * 鎴戜滑蹇呴』缁х画鍙戦侊紝 + * 骞朵笖gs_broadcast鍙互鍙戦佸埌鍦板潃淇℃伅鍒楄〃涓殑鍏朵粬鑺傜偣銆 */ if (m_addr->parallel_send_mode == true) { /* - * if we use parallel send mode, - * we only send to head node of address info list, - * and do not care other node in address info list, - * gs_broadcast can parallel send to other node. + * 濡傛灉浣跨敤骞惰鍙戦佹ā寮忥紝 + * 鎴戜滑鍙彂閫佸埌鍦板潃淇℃伅鍒楄〃鐨勫ご鑺傜偣锛 + * 涓嶅叧蹇冨湴鍧淇℃伅鍒楄〃涓殑鍏朵粬鑺傜偣锛 + * gs_broadcast鍙互骞惰鍙戦佸埌鍏朵粬鑺傜偣銆 */ if (m_addr->addr_list_size == 0) return false; @@ -136,8 +149,10 @@ bool StreamCOMM::setActive() return false; } + /* 璁剧疆褰撳墠绾跨▼鐨凱rocPort */ u_sess->proc_cxt.MyProcPort = m_port; + /* 璁剧疆鍙戦佺紦鍐插尯鎸囬拡銆佸ぇ灏忓拰璧峰浣嶇疆浠ュ強閫氫俊蹇欐爣蹇 */ t_thrd.libpq_cxt.PqSendBuffer = &m_buffer->PqSendBuffer[0]; t_thrd.libpq_cxt.PqSendPointer = m_buffer->PqSendPointer; t_thrd.libpq_cxt.PqSendBufferSize = m_buffer->PqSendBufferSize; @@ -177,11 +192,14 @@ void StreamCOMM::setInActive() */ void StreamCOMM::updateInfo(StreamConnInfo* connInfo) { + /* 鑾峰彇鑺傜偣鍚嶇О鐨勯暱搴 */ int nodeNameLen = strlen(connInfo->nodeName); - errno_t rc = EOK; - + /* 灏嗚繛鎺ヤ俊鎭腑鐨勫鎺ュ瓧淇℃伅澶嶅埗鍒癝treamCOMM瀵硅薄鐨勫鎺ュ瓧淇℃伅涓 */ m_addr->gs_sock = connInfo->port.libcomm_layer.gsock; - rc = strncpy_s(m_nodeName, NAMEDATALEN, connInfo->nodeName, nodeNameLen + 1); + /* 灏嗚繛鎺ヤ俊鎭腑鐨勮妭鐐瑰悕绉板鍒跺埌StreamCOMM瀵硅薄鐨勮妭鐐瑰悕绉颁腑 */ + errno_t rc = strncpy_s(m_nodeName, NAMEDATALEN, connInfo->nodeName, nodeNameLen + 1); + /* 妫鏌ュ瓧绗︿覆澶嶅埗鏄惁鎴愬姛 */ securec_check(rc, "\0", "\0"); + /* 灏嗚繛鎺ヤ俊鎭腑鐨勭敓浜ц匰MP ID澶嶅埗鍒癝treamCOMM瀵硅薄鐨剆treamKey涓 */ m_addr->streamKey.producerSmpId = connInfo->producerSmpId; -} +} \ No newline at end of file diff --git a/src/gausskernel/process/stream/stream_cost.cpp b/src/gausskernel/process/stream/stream_cost.cpp index 2db722c78..da85919b7 100644 --- a/src/gausskernel/process/stream/stream_cost.cpp +++ b/src/gausskernel/process/stream/stream_cost.cpp @@ -1,245 +1,248 @@ -/* ------------------------------------------------------------------------- - * - * stream_cost.cpp - * functions used to calculate stream plan costs. - * - * - * Portions Copyright (c) 2020 Huawei Technologies Co.,Ltd. - * Portions Copyright (c) 1996-2012, PostgreSQL Global Development Group - * Portions Copyright (c) 1994, Regents of the University of California - * - * src/gaussdbkernel/porcess/stream/stream_cost.cpp - * - * ------------------------------------------------------------------------- - */ - -#include -#include -#include "access/hash.h" -#include "optimizer/cost.h" -#include "optimizer/dataskew.h" -#include "optimizer/planner.h" - -void parallel_stream_info_print(ParallelDesc* smpDesc, StreamType type) -{ - char* distri_type = NULL; - - if (NULL == smpDesc) - return; - - /* Set stream type tag. */ - switch (smpDesc->distriType) { - case REMOTE_DISTRIBUTE: - distri_type = "REDISTRIBUTE"; - break; - - case REMOTE_SPLIT_DISTRIBUTE: - distri_type = "SPLIT REDISTRIBUTE"; - break; - - case REMOTE_BROADCAST: - distri_type = "BROADCAST"; - break; - - case REMOTE_SPLIT_BROADCAST: - distri_type = "SPLIT BROADCAST"; - break; - - case LOCAL_DISTRIBUTE: - distri_type = "LOCAL REDISTRIBUTE"; - break; - - case LOCAL_BROADCAST: - distri_type = "LOCAL BROADCAST"; - break; - - case LOCAL_ROUNDROBIN: - distri_type = "LOCAL ROUNDROBIN"; - break; - - default: - if (type == STREAM_BROADCAST) - distri_type = "BROADCAST"; - else - distri_type = "REDISTRIBUTE"; - break; - } - - /* Print log. */ - elog(DEBUG1, - "Stream cost: SMP INFO: sendDop: %d, receiveDop: %d, distribute type: %s", - SET_DOP(smpDesc->producerDop), - SET_DOP(smpDesc->consumerDop), - distri_type); -} - -/* - * cost_stream - * computer cost of stream a RepOptInfo object - */ -void cost_stream(StreamPath* stream, int width, bool isJoin) -{ - const double startup_cost_broadcast = 0.0; - - AssertEreport(stream != NULL && stream->subpath != NULL, MOD_OPT, "The stream or subplan is invalid"); - - stream->path.startup_cost = startup_cost_broadcast; - stream->path.startup_cost += stream->subpath->startup_cost; - stream->path.total_cost = stream->subpath->total_cost; - stream->path.stream_cost = stream->subpath->startup_cost; - - unsigned int producer_num_datanodes = bms_num_members(stream->path.distribution.bms_data_nodeids); - unsigned int consumer_num_datanodes = bms_num_members(stream->consumer_distribution.bms_data_nodeids); - - compute_stream_cost(stream->type, - stream->subpath->locator_type, - PATH_LOCAL_ROWS(stream->subpath), - stream->subpath->rows, - stream->path.multiple, - width, - isJoin, - stream->path.distribute_keys, - &stream->path.total_cost, - &stream->path.rows, - producer_num_datanodes, - consumer_num_datanodes, - stream->smpDesc, - stream->skew_list); - - return; -} - -List* get_max_cost_distkey_for_hasdistkey(PlannerInfo* root, List* subPlans, int subPlanNum, - List** subPlanKeyArray, Cost* subPlanCostArray, Bitmapset** redistributePlanSetCopy) -{ - Cost* keyCostArray = NULL; - int counter = 0; - int maxCostIndex = 0; - int subPlanIndex = 0; - List* redistributeKeyIndex = NULL; - - /* - * There are more than one distribute key of subplan, - * find the max cost distribute key of subplan. - */ - keyCostArray = (Cost*)palloc0(sizeof(Cost) * subPlanNum); - - while (counter < subPlanNum) { - List* keyIndex = subPlanKeyArray[counter]; - - if (keyIndex == NULL) { - counter++; - continue; - } - - for (subPlanIndex = 0; subPlanIndex < subPlanNum; subPlanIndex++) { - if (equal(subPlanKeyArray[subPlanIndex], keyIndex)) { - if (subPlanIndex < counter) { - keyCostArray[counter] = 0; - break; - } else { - keyCostArray[counter] += subPlanCostArray[subPlanIndex]; - } - } - } - - counter++; - } - - /* - * Get the max cost for each redistributekey. - */ - for (counter = 0; counter < subPlanNum; counter++) { - if (keyCostArray[maxCostIndex] < keyCostArray[counter]) { - maxCostIndex = counter; - } - } - - /* - * Set other each subplan uesing the max cost redistribute key. - */ - redistributeKeyIndex = subPlanKeyArray[maxCostIndex]; - for (subPlanIndex = 0; subPlanIndex < subPlanNum; subPlanIndex++) { - if (!equal(subPlanKeyArray[subPlanIndex], redistributeKeyIndex)) { - *redistributePlanSetCopy = bms_add_member(*redistributePlanSetCopy, subPlanIndex); - } - } - - pfree_ext(keyCostArray); - keyCostArray = NULL; - return redistributeKeyIndex; -} - -/* - * We should get the max cost distribute key of subplan - * as the final redistribute key for other subplan. - */ -List* get_max_cost_distkey_for_nulldistkey( - PlannerInfo* root, List* subPlans, int subPlanNum, Cost* subPlanCostArray) - -{ - Plan* subPlan = NULL; - int counter = 0; - int maxCostIndex = 0; - List* redistributeKeyIndex = NULL; - - /* - * Get the max cost for each redistributekey. - */ - for (counter = 0; counter < subPlanNum; counter++) { - if (subPlanCostArray[maxCostIndex] < subPlanCostArray[counter]) { - maxCostIndex = counter; - } - } - - /* If there is no distkey, we should choose the max cost distkey. */ - subPlan = (Plan*)list_nth(subPlans, maxCostIndex); - redistributeKeyIndex = make_distkey_for_append(root, subPlan); - return redistributeKeyIndex; -} - -/* - * Construct distribute key index according to bias, if we cannot find distribute key. - * If the targetlist of subplan has no relid, we should choose the first three target entry - * of var for distribute key. - */ -List* make_distkey_for_append(PlannerInfo* root, Plan* subPlan) -{ - List* grplist = NIL; - List* subPlanKeyArray = NIL; - const int defaultDistkeyNum = 3; - - /* Construct group clause using targetlist. */ - grplist = make_groupcl_for_append(root, subPlan->targetlist); - if (grplist != NIL) { - double multiple; - List* distkeys = NIL; - - /* Get distkeys according to bias. */ - distkeys = get_distributekey_from_tlist(root, subPlan->targetlist, grplist, subPlan->plan_rows, &multiple); - if (distkeys != NIL) - subPlanKeyArray = distributeKeyIndex(root, distkeys, subPlan->targetlist); - - list_free_ext(grplist); - list_free_ext(distkeys); - } else { - /* Choose the first three target entry of var for distribute key. */ - int distkeynum = 0; - ListCell* teCell = NULL; - - foreach (teCell, subPlan->targetlist) { - TargetEntry* teEntry = (TargetEntry*)lfirst(teCell); - Node* node = (Node*)teEntry->expr; - - if (!teEntry->resjunk && IsTypeDistributable(exprType(node))) { - subPlanKeyArray = lappend_int(subPlanKeyArray, teEntry->resno); - distkeynum++; - - if (distkeynum <= defaultDistkeyNum) - break; - } - } - } - - return subPlanKeyArray; +/* ------------------------------------------------------------------------- + * + * stream_cost.cpp + * functions used to calculate stream plan costs. + * + * + * Portions Copyright (c) 2020 Huawei Technologies Co.,Ltd. + * Portions Copyright (c) 1996-2012, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * src/gaussdbkernel/porcess/stream/stream_cost.cpp + * + * ------------------------------------------------------------------------- + */ + +#include +#include +#include "access/hash.h" +#include "optimizer/cost.h" +#include "optimizer/dataskew.h" +#include "optimizer/planner.h" + +void parallel_stream_info_print(ParallelDesc* smpDesc, StreamType type) +{ + char* distri_type = NULL; + + if (NULL == smpDesc) + return; + + /* 璁剧疆娴佺被鍨嬫爣绛俱*/ + switch (smpDesc->distriType) { + case REMOTE_DISTRIBUTE: + distri_type = "REDISTRIBUTE"; + break; + + case REMOTE_SPLIT_DISTRIBUTE: + distri_type = "SPLIT REDISTRIBUTE"; + break; + + case REMOTE_BROADCAST: + distri_type = "BROADCAST"; + break; + + case REMOTE_SPLIT_BROADCAST: + distri_type = "SPLIT BROADCAST"; + break; + + case LOCAL_DISTRIBUTE: + distri_type = "LOCAL REDISTRIBUTE"; + break; + + case LOCAL_BROADCAST: + distri_type = "LOCAL BROADCAST"; + break; + + case LOCAL_ROUNDROBIN: + distri_type = "LOCAL ROUNDROBIN"; + break; + + default: + if (type == STREAM_BROADCAST) + distri_type = "BROADCAST"; + else + distri_type = "REDISTRIBUTE"; + break; + } + + /* 鎵撳嵃鏃ュ織銆*/ + elog(DEBUG1, + "Stream cost: SMP INFO: sendDop: %d, receiveDop: %d, distribute type: %s", + SET_DOP(smpDesc->producerDop), + SET_DOP(smpDesc->consumerDop), + distri_type); +} + +/* + * cost_stream + * computer cost of stream a RepOptInfo object + */ +void cost_stream(StreamPath* stream, int width, bool isJoin) +{ + const double startup_cost_broadcast = 0.0; + + // 鏂█锛氭祦鍜屽瓙璁″垝涓嶈兘涓虹┖ + AssertEreport(stream != NULL && stream->subpath != NULL, MOD_OPT, "The stream or subplan is invalid"); + + // 璁剧疆鍚姩鎴愭湰涓哄箍鎾殑鍚姩鎴愭湰 + stream->path.startup_cost = startup_cost_broadcast; + // 绱姞瀛愯鍒掔殑鍚姩鎴愭湰鍒版祦鐨勫惎鍔ㄦ垚鏈 + stream->path.startup_cost += stream->subpath->startup_cost; + // 璁剧疆娴佺殑鎬绘垚鏈负瀛愯鍒掔殑鎬绘垚鏈 + stream->path.total_cost = stream->subpath->total_cost; + // 璁剧疆娴佺殑鎴愭湰涓哄瓙璁″垝鐨勫惎鍔ㄦ垚鏈 + stream->path.stream_cost = stream->subpath->startup_cost; + + // 璁$畻鐢熶骇鑰呭拰娑堣垂鑰呮暟鎹妭鐐圭殑鏁伴噺 + unsigned int producer_num_datanodes = bms_num_members(stream->path.distribution.bms_data_nodeids); + unsigned int consumer_num_datanodes = bms_num_members(stream->consumer_distribution.bms_data_nodeids); + + // 璋冪敤compute_stream_cost鍑芥暟璁$畻娴佺殑鎴愭湰 + compute_stream_cost(stream->type, + stream->subpath->locator_type, + PATH_LOCAL_ROWS(stream->subpath), + stream->subpath->rows, + stream->path.multiple, + width, + isJoin, + stream->path.distribute_keys, + &stream->path.total_cost, + &stream->path.rows, + producer_num_datanodes, + consumer_num_datanodes, + stream->smpDesc, + stream->skew_list); + + return; +} + +List* get_max_cost_distkey_for_hasdistkey(PlannerInfo* root, List* subPlans, int subPlanNum, + List** subPlanKeyArray, Cost* subPlanCostArray, Bitmapset** redistributePlanSetCopy) +{ + Cost* keyCostArray = NULL; + int counter = 0; + int maxCostIndex = 0; + int subPlanIndex = 0; + List* redistributeKeyIndex = NULL; + + /* + * subplan鏈夊涓垎鍙戦敭锛屾壘鍑哄瓙璁″垝鐨勬渶澶ф垚鏈垎閰嶉敭銆 + */ + keyCostArray = (Cost*)palloc0(sizeof(Cost) * subPlanNum); + + while (counter < subPlanNum) { + List* keyIndex = subPlanKeyArray[counter]; + + if (keyIndex == NULL) { + counter++; + continue; + } + + for (subPlanIndex = 0; subPlanIndex < subPlanNum; subPlanIndex++) { + if (equal(subPlanKeyArray[subPlanIndex], keyIndex)) { + if (subPlanIndex < counter) { + keyCostArray[counter] = 0; + break; + } else { + keyCostArray[counter] += subPlanCostArray[subPlanIndex]; + } + } + } + + counter++; + } + + /* + * 寰楀埌姣忎釜redistributekey鐨勬渶澶т唬浠 + */ + for (counter = 0; counter < subPlanNum; counter++) { + if (keyCostArray[maxCostIndex] < keyCostArray[counter]) { + maxCostIndex = counter; + } + } + + /* + * 浣跨敤鏈澶ф垚鏈噸鍒嗗彂閿缃叾浠栨瘡涓瓙璁″垝 + */ + redistributeKeyIndex = subPlanKeyArray[maxCostIndex]; + for (subPlanIndex = 0; subPlanIndex < subPlanNum; subPlanIndex++) { + if (!equal(subPlanKeyArray[subPlanIndex], redistributeKeyIndex)) { + *redistributePlanSetCopy = bms_add_member(*redistributePlanSetCopy, subPlanIndex); + } + } + + pfree_ext(keyCostArray); + keyCostArray = NULL; + return redistributeKeyIndex; +} + +/* + * 鎴戜滑闇瑕佸緱鍒板瓙璁″垝鐨勬渶澶ф垚鏈垎閰嶉敭浣滀负鍏朵粬瀛愯鍒掔殑鏈缁堥噸鍒嗗彂閿 + */ +List* get_max_cost_distkey_for_nulldistkey(PlannerInfo* root, List* subPlans, int subPlanNum, Cost* subPlanCostArray) +{ + Plan* subPlan = NULL; + int counter = 0; + int maxCostIndex = 0; + List* redistributeKeyIndex = NULL; + + /* + * 鎵惧埌鍏锋湁鏈澶ф垚鏈殑閲嶆柊鍒嗗彂閿 + */ + for (counter = 0; counter < subPlanNum; counter++) { + if (subPlanCostArray[maxCostIndex] < subPlanCostArray[counter]) { + maxCostIndex = counter; + } + } + + /* 濡傛灉娌℃湁鍒嗗彂閿紝鎴戜滑搴旇閫夋嫨鍏锋湁鏈澶ф垚鏈殑鍒嗗彂閿 */ + subPlan = (Plan*)list_nth(subPlans, maxCostIndex); + redistributeKeyIndex = make_distkey_for_append(root, subPlan); + return redistributeKeyIndex; +} + +/* + 濡傛灉鎵句笉鍒板垎甯冮敭锛屽垯鏍规嵁鍋忓樊鏋勯犲垎甯冮敭绱㈠紩銆 + 濡傛灉subplan鐨則argetlist娌℃湁绌洪棽锛屾垜浠簲璇ラ夋嫨鍓嶄笁涓洰鏍囨潯鐩 + 鐨剉ar涓哄垎鍙戦敭銆 + */ +List* make_distkey_for_append(PlannerInfo* root, Plan* subPlan) +{ + List* grplist = NIL; + List* subPlanKeyArray = NIL; + const int defaultDistkeyNum = 3; + + /* 浣跨敤鐩爣鍒楄〃鏋勫缓鍒嗙粍瀛愬彞銆 */ + grplist = make_groupcl_for_append(root, subPlan->targetlist); + if (grplist != NIL) { + double multiple; + List* distkeys = NIL; + + /* 鏍规嵁鍋忓樊鑾峰彇鍒嗗彂閿 */ + distkeys = get_distributekey_from_tlist(root, subPlan->targetlist, grplist, subPlan->plan_rows, &multiple); + if (distkeys != NIL) + subPlanKeyArray = distributeKeyIndex(root, distkeys, subPlan->targetlist); + + list_free_ext(grplist); + list_free_ext(distkeys); + } else { + /* 閫夋嫨鍙橀噺鐨勫墠涓変釜鐩爣椤逛綔涓哄垎鍙戦敭銆 */ + int distkeynum = 0; + ListCell* teCell = NULL; + + foreach (teCell, subPlan->targetlist) { + TargetEntry* teEntry = (TargetEntry*)lfirst(teCell); + Node* node = (Node*)teEntry->expr; + + if (!teEntry->resjunk && IsTypeDistributable(exprType(node))) { + subPlanKeyArray = lappend_int(subPlanKeyArray, teEntry->resno); + distkeynum++; + + if (distkeynum <= defaultDistkeyNum) + break; + } + } + } + + return subPlanKeyArray; } \ No newline at end of file diff --git a/src/gausskernel/process/tcop/LIST.TXT b/src/gausskernel/process/tcop/LIST.TXT new file mode 100644 index 000000000..0b534b4be --- /dev/null +++ b/src/gausskernel/process/tcop/LIST.TXT @@ -0,0 +1,12 @@ +auditfuncs.cpp +autonomoustransaction.cpp +CMakeLists.txt +dest.cpp +fastpath.cpp +LIST.TXT +Makefile +postgres.cpp +pquery.cpp +stmt_retry.cpp +utility.cpp +新建文本文档.bat diff --git a/src/gausskernel/process/tcop/鏂板缓鏂囨湰鏂囨。.bat b/src/gausskernel/process/tcop/鏂板缓鏂囨湰鏂囨。.bat new file mode 100644 index 000000000..d055abd11 --- /dev/null +++ b/src/gausskernel/process/tcop/鏂板缓鏂囨湰鏂囨。.bat @@ -0,0 +1 @@ +DIR *.* /B >LIST.TXT \ No newline at end of file diff --git a/src/gausskernel/process/threadpool/knl_instance.cpp b/src/gausskernel/process/threadpool/knl_instance.cpp index a2d5768fd..b9d68b0f9 100755 --- a/src/gausskernel/process/threadpool/knl_instance.cpp +++ b/src/gausskernel/process/threadpool/knl_instance.cpp @@ -2,20 +2,10 @@ * Copyright (c) 2020 Huawei Technologies Co.,Ltd. * Portions Copyright (c) 2021, openGauss Contributors * - * openGauss is licensed under Mulan PSL v2. - * You can use this software according to the terms and conditions of the Mulan PSL v2. - * You may obtain a copy of Mulan PSL v2 at: - * - * http://license.coscl.org.cn/MulanPSL2 - * - * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, - * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, - * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. - * See the Mulan PSL v2 for more details. * ------------------------------------------------------------------------- * * knl_instance.cpp - * Initial functions for instance level global variables. + * 瀹炰緥绾у叏灞鍙橀噺鐨勫垵濮嬪嚱鏁 * * IDENTIFICATION * src/gausskernel/process/threadpool/knl_instance.cpp @@ -24,43 +14,46 @@ */ #include -#include "access/parallel_recovery/page_redo.h" -#include "access/reloptions.h" -#include "access/xlog.h" -#include "commands/prepare.h" -#include "executor/instrument.h" -#include "gssignal/gs_signal.h" +#include "access/parallel_recovery/page_redo.h"//鐢ㄤ簬骞惰鎭㈠鎿嶄綔鐨勫ご鏂囦欢 +#include "access/reloptions.h"//澶勭悊琛ㄥ拰绱㈠紩鐨勯夐」 +#include "access/xlog.h"//澶勭悊浜嬪姟鏃ュ織 +#include "commands/prepare.h"//鐢ㄤ簬SQL棰勫鐞 +#include "executor/instrument.h"//鐢ㄤ簬鎵ц璁″垝 +#include "gssignal/gs_signal.h"//澶勭悊鎿嶄綔绯荤粺淇″彿 +#include "instruments/instr_waitevent.h"//鐢ㄤ簬鎬ц兘鐩戞帶绛夊緟浜嬩欢 +#include "knl/knl_instance.h"//PostgreSQL鍐呮牳瀹炰緥 +#include "libcomm/libcomm.h"// 鐢ㄤ簬閫氫俊搴撶殑澶存枃浠 +#include "optimizer/cost.h"//鏌ヨ浼樺寲涓殑鎴愭湰浼扮畻 +#include "optimizer/dynsmp.h"//鍔ㄦ佸苟琛屾煡璇㈡墽琛 +#include "optimizer/planmain.h"//鏌ヨ瑙勫垝涓昏澶存枃浠 +#include "optimizer/planner.h"//鏌ヨ瑙勫垝鍣 +#include "optimizer/streamplan.h"//娴佸紡鏌ヨ璁″垝 +#include "pgstat.h"//鐢ㄤ簬鎬ц兘缁熻 +#include "regex/regex.h"//姝e垯琛ㄨ揪寮 +#include "utils/memutils.h"//鍐呭瓨绠$悊宸ュ叿 +#include "utils/palloc.h"//鍐呭瓨鍒嗛厤 +#include "workload/workload.h"// 宸ヤ綔璐熻浇绠$悊鐩稿叧 #include "instruments/instr_waitevent.h" -#include "knl/knl_instance.h" -#include "libcomm/libcomm.h" -#include "optimizer/cost.h" -#include "optimizer/dynsmp.h" -#include "optimizer/planmain.h" -#include "optimizer/planner.h" -#include "optimizer/streamplan.h" -#include "pgstat.h" -#include "regex/regex.h" -#include "utils/memutils.h" -#include "utils/palloc.h" -#include "workload/workload.h" -#include "instruments/instr_waitevent.h" -#include "access/multi_redo_api.h" -#include "utils/hotkey.h" -#include "lib/lrucache.h" +#include "access/multi_redo_api.h"//澶氱嚎绋嬮噸鍋氭搷浣 +#include "utils/hotkey.h"//澶勭悊鐑偣閿 +#include "lib/lrucache.h"//LRU缂撳瓨 + #ifdef ENABLE_WHITEBOX #include "access/ustore/knl_whitebox_test.h" #endif const int SIZE_OF_TWO_UINT64 = 16; - +//甯搁噺琛ㄧず,涓や釜64浣嶆暣鏁扮殑鎬诲ぇ灏忎负16瀛楄妭 knl_instance_context g_instance; const int ALLOCSET_UNDO_MAXSIZE = 300 * UNDO_ZONE_COUNT; extern void InitGlobalVecFuncMap(); - +//涓涓閮ㄥ嚱鏁板0鏄 static void knl_g_cost_init(knl_g_cost_context* cost_cxt) { + /*鍒濆鍖栦竴涓 knl_g_cost_context 缁撴瀯涓殑鍚勪釜鎴愬憳鍙橀噺, + 浠ヤ究鍚庣画鐨勬搷浣滃彲浠ヤ娇鐢ㄨ繖浜涘兼潵杩涜鎴愭湰浼扮畻鎴栧叾浠栬绠*/ cost_cxt->cpu_hash_cost = DEFAULT_CPU_HASH_COST; cost_cxt->send_kdata_cost = DEFAULT_SEND_KDATA_COST; cost_cxt->receive_kdata_cost = DEFAULT_RECEIVE_KDATA_COST; @@ -70,54 +63,83 @@ static void knl_g_cost_init(knl_g_cost_context* cost_cxt) static void knl_g_quota_init(knl_g_quota_context* quota_cxt) { + //鍒濆鍖栦竴涓 knl_g_quota_context 缁撴瀯涓殑鍚勪釜鎴愬憳鍙橀噺 Assert(quota_cxt != NULL); + //涓涓柇瑷璇彞锛岀敤浜庣‘淇 quota_cxt 鎸囬拡涓嶄负绌 + //濡傛灉涓虹┖锛屽垯浼氳Е鍙戞柇瑷澶辫触锛岃〃绀哄嚭鐜颁簡閿欒鎴栭潪棰勬湡鐨勬儏鍐 quota_cxt->g_quota = 0; quota_cxt->g_quotanofify_ratio = 0; quota_cxt->g_having_quota = true; + //褰撳墠鍏锋湁璧勬簮閰嶉 quota_cxt->g_quota_changing = NULL; + //褰撳墠娌℃湁姝e湪鏇存敼鐨勮祫婧愰厤棰 } static void knl_g_localinfo_init(knl_g_localinfo_context* localinfo_cxt) { + //鍒濆鍖栦竴涓 knl_g_localinfo_context 缁撴瀯涓殑鍚勪釜鎴愬憳鍙橀噺 Assert(localinfo_cxt != NULL); + //鐢ㄤ簬纭繚 localinfo_cxt 鎸囬拡涓嶄负绌 localinfo_cxt->g_local_host = NULL; + //璇存槑鏈湴涓绘満淇℃伅灏氭湭璁剧疆 localinfo_cxt->g_self_nodename = NULL; + //璇存槑鏈湴鑺傜偣鍚嶇О灏氭湭璁剧疆 localinfo_cxt->g_local_ctrl_tcp_sock = -1; - localinfo_cxt->sock_to_server_loop = -1; - localinfo_cxt->gs_krb_keyfile = NULL; + //璇存槑鏈湴鎺у埗 TCP 濂楁帴瀛楀皻鏈缓绔 + localinfo_cxt->sock_to_server_loop = -1; + //璇存槑涓庢湇鍔″櫒鐨勫鎺ュ瓧閫氫俊灏氭湭寤虹珛 + localinfo_cxt->gs_krb_keyfile = NULL; + //璇存槑Kerberos 瀵嗛挜鏂囦欢灏氭湭璁剧疆 } static void knl_g_counters_init(knl_g_counters_context* counters_cxt) { + //鍒濆鍖栦竴涓 knl_g_counters_context 缁撴瀯涓殑鍚勪釜鎴愬憳鍙橀噺 Assert(counters_cxt != NULL); + //鐢ㄤ簬纭繚 counters_cxt 鎸囬拡涓嶄负绌 counters_cxt->g_cur_node_num = 0; + //琛ㄧず褰撳墠鑺傜偣鏁伴噺涓0 counters_cxt->g_expect_node_num = 0; + //琛ㄧず鏈熸湜鐨勮妭鐐规暟閲忎负0 counters_cxt->g_max_stream_num = 0; + //琛ㄧず鏈澶ф祦鐨勬暟閲忎负0 counters_cxt->g_recv_num = 0; + //琛ㄧず鎺ユ敹鐨勬暟閲忎负0 counters_cxt->g_comm_send_timeout = 0; + //琛ㄧず閫氫俊鍙戦佽秴鏃舵椂闂翠负0 } static void knl_g_ckpt_init(knl_g_ckpt_context* ckpt_cxt) { + //鍒濆鍖栦竴涓 knl_g_ckpt_context 缁撴瀯涓殑鍚勪釜鎴愬憳鍙橀噺 Assert(ckpt_cxt != NULL); + //纭繚 ckpt_cxt 鎸囬拡涓嶄负绌 errno_t rc = memset_s(ckpt_cxt, sizeof(knl_g_ckpt_context), 0, sizeof(knl_g_ckpt_context)); - securec_check(rc, "\0", "\0"); + //鐢 memset_s 鍑芥暟灏 knl_g_ckpt_context 缁撴瀯鐨勫唴瀛樺尯鍩熷垵濮嬪寲涓0 + securec_check(rc, "\0", "\0"); + //鐢ㄤ簬妫鏌 memset_s 璋冪敤缁撴灉鐨勫畨鍏ㄦ鏌,濡傛灉璋冭瘯澶辫触锛屼細瑙﹀彂閿欒锛屽仠姝㈣繍琛 SpinLockInit(&(ckpt_cxt->queue_lock)); + //鍒濆鍖栧悕涓 queue_lock 鐨勮嚜鏃嬮攣 (鑷棆閿佹槸涓绉嶇敤浜庡绾跨▼缂栫▼鐨勫悓姝ユ満鍒讹紝鐢ㄤ簬淇濇姢鍏变韩璧勬簮鍏嶅彈骞跺彂璁块棶鐨勫共鎵) } static void knl_g_wal_init(knl_g_wal_context *const wal_cxt) { + //鍒濆鍖栦竴涓 knl_g_wal_context 缁撴瀯锛屽畠鍖呭惈浜嗕竴绯诲垪鎴愬憳鍙橀噺鐨勫垵濮嬪寲鎿嶄綔 int ret = 0; + //鐢ㄤ簬瀛樺偍鍑芥暟杩斿洖鍊兼垨閿欒鐮 ret = pthread_condattr_init(&wal_cxt->criticalEntryAtt); - if (ret != 0) { + //鍒濆鍖栨潯浠跺彉閲忓睘鎬 criticalEntryAtt + if (ret != 0) { elog(FATAL, "Fail to init conattr for walwrite"); } ret = pthread_condattr_setclock(&wal_cxt->criticalEntryAtt, CLOCK_MONOTONIC); - if (ret != 0) { + //璁剧疆鏉′欢鍙橀噺灞炴х殑鏃堕挓绫诲瀷涓 CLOCK_MONOTONIC + if (ret != 0) { elog(FATAL, "Fail to setclock walwrite"); } ret = pthread_cond_init(&wal_cxt->criticalEntryCV, &wal_cxt->criticalEntryAtt); - if (ret != 0) { + //鍒濆鍖栨潯浠跺彉閲 criticalEntryCV锛屽苟灏嗗叾鍏宠仈鍒版潯浠跺彉閲忓睘鎬 criticalEntryAtt + if (ret != 0) { elog(FATAL, "Fail to init cond for walwrite"); } @@ -143,37 +165,55 @@ static void knl_g_wal_init(knl_g_wal_context *const wal_cxt) wal_cxt->totalXlogIterBytes = 0; wal_cxt->totalXlogIterTimes = 0; wal_cxt->xlogFlushStats = NULL; + //鍒濆鍖栦簡缁撴瀯涓殑鍚勪釜鎴愬憳鍙橀噺 + //涓婅堪鍒濆鍖栭氬父鐢ㄤ簬鏁版嵁搴撶郴缁熶腑涓嶹AL鐩稿叧鐨勭鐞嗗拰鍚屾 } static void knl_g_bgwriter_init(knl_g_bgwriter_context *bgwriter_cxt) { + //鍒濆鍖栦竴涓 knl_g_bgwriter_context 缁撴瀯涓殑鍚勪釜鎴愬憳鍙橀噺 Assert(bgwriter_cxt != NULL); + //纭繚 bgwriter_cxt 鎸囬拡涓嶄负绌 bgwriter_cxt->unlink_rel_hashtbl = NULL; + //琛ㄧず鏈垎閰嶅叧鑱旂殑鍝堝笇琛 bgwriter_cxt->rel_hashtbl_lock = NULL; + //琛ㄧず鏈垎閰嶅叧鑱旂殑閿 bgwriter_cxt->invalid_buf_proc_latch = NULL; - bgwriter_cxt->unlink_rel_fork_hashtbl = NULL; - bgwriter_cxt->rel_one_fork_hashtbl_lock = NULL; + //琛ㄧず鏈垎閰嶅叧鑱旂殑浜嬩欢瑙﹀彂鍣 + bgwriter_cxt->unlink_rel_fork_hashtbl = NULL; + bgwriter_cxt->rel_one_fork_hashtbl_lock = NULL; + //涓婅堪鍒濆鍖栭氬父鐢ㄤ簬鏁版嵁搴撶郴缁熶腑涓庢暟鎹慨澶嶆垨涓鑷存ф鏌ョ浉鍏崇殑鏁版嵁缁撴瀯鍜屽悓姝 } static void knl_g_repair_init(knl_g_repair_context *repair_cxt) { + //鍒濆鍖栦竴涓 knl_g_repair_context 缁撴瀯涓殑鍚勪釜鎴愬憳鍙橀噺 Assert(repair_cxt != NULL); + //纭繚 repair_cxt 鎸囬拡涓嶄负绌 repair_cxt->page_repair_hashtbl = NULL; + //琛ㄧず鏈垎閰嶅叧鑱旂殑鍝堝笇琛 repair_cxt->page_repair_hashtbl_lock = NULL; - repair_cxt->repair_proc_latch = NULL; + //琛ㄧず鏈垎閰嶅叧鑱旂殑閿 + repair_cxt->repair_proc_latch = NULL; + //琛ㄧず鏈垎閰嶅叧鑱旂殑閿 } static void knl_g_startup_init(knl_g_startup_context *starup_cxt) { + //鍒濆鍖栦竴涓 knl_g_startup_context 缁撴瀯涓殑鍚勪釜鎴愬憳鍙橀噺 Assert(starup_cxt != NULL); starup_cxt->remoteReadPageNum = 0; + //琛ㄧず杩滅▼璇诲彇鐨勯〉闈㈡暟閲忎负0 starup_cxt->badPageHashTbl = NULL; starup_cxt->current_record = NULL; + //琛ㄧず褰撳墠璁板綍涓虹┖ + //涓婅堪浠g爜閫氬父鐢ㄤ簬鏁版嵁搴撶郴缁熺殑鍚姩闃舵鐩稿叧鐨勬暟鎹粨鏋勫垵濮嬪寲 } static void knl_g_tests_init(knl_g_tests_context* tests_cxt) { + //鍒濆鍖栦竴涓 knl_g_tests_context 缁撴瀯涓殑鍚勪釜鎴愬憳鍙橀噺 Assert(tests_cxt != NULL); tests_cxt->libcomm_test_current_thread = 0; tests_cxt->libcomm_test_thread_arg = NULL; @@ -184,10 +224,12 @@ static void knl_g_tests_init(knl_g_tests_context* tests_cxt) tests_cxt->libcomm_test_send_once = 0; tests_cxt->libcomm_test_recv_sleep = 0; tests_cxt->libcomm_test_recv_once = 0; + //涓婅堪澶氱敤浜庤繘琛屾祴璇曞拰璋冭瘯 } static void knl_g_pollers_init(knl_g_pollers_context* pollers_cxt) { + //琛ㄧず灏氭湭璇锋眰鍏抽棴杞锛坧oll锛夋搷浣 Assert(pollers_cxt != NULL); pollers_cxt->g_libcomm_receiver_poller_list = NULL; pollers_cxt->g_r_libcomm_poller_list_lock = NULL; @@ -199,20 +241,30 @@ static void knl_g_pollers_init(knl_g_pollers_context* pollers_cxt) static void knl_g_reqcheck_init(knl_g_reqcheck_context* reqcheck_cxt) { + // 鍒濆鍖栦竴涓 knl_g_reqcheck_context 缁撴瀯涓殑鍚勪釜鎴愬憳鍙橀噺 Assert(reqcheck_cxt != NULL); reqcheck_cxt->g_shutdown_requested = false; + //琛ㄧず灏氭湭璇锋眰鍏抽棴鎿嶄綔 reqcheck_cxt->g_cancel_requested = 0; + //琛ㄧず灏氭湭璇锋眰鍙栨秷鎿嶄綔 reqcheck_cxt->g_close_poll_requested = false; + //琛ㄧず灏氭湭璇锋眰鍏抽棴杞鎿嶄綔 } static void knl_g_mctcp_init(knl_g_mctcp_context* mctcp_cxt) { + //鍒濆鍖栦竴涓 knl_g_mctcp_context 缁撴瀯涓殑鍚勪釜鎴愬憳鍙橀噺 Assert(mctcp_cxt != NULL); mctcp_cxt->mc_tcp_keepalive_idle = 0; + //琛ㄧずTCP杩炴帴鐨勭┖闂叉椂闂达紙idle time锛変负0 mctcp_cxt->mc_tcp_keepalive_interval = 0; - mctcp_cxt->mc_tcp_keepalive_count = 0; + //琛ㄧずTCP淇濇椿娑堟伅鍙戦佺殑闂撮殧鏃堕棿涓0 + mctcp_cxt->mc_tcp_keepalive_count = 0; + //琛ㄧずTCP淇濇椿娑堟伅鍙戦佺殑娆℃暟涓0 mctcp_cxt->mc_tcp_connect_timeout = 0; + //琛ㄧずTCP杩炴帴鐨勮秴鏃舵椂闂翠负0 mctcp_cxt->mc_tcp_send_timeout = 0; + //琛ㄧずTCP鍙戦佹搷浣滅殑瓒呮椂鏃堕棿涓0 } static void knl_g_commutil_init(knl_g_commutil_context* commutil_cxt) @@ -231,14 +283,19 @@ static void knl_g_commutil_init(knl_g_commutil_context* commutil_cxt) static void knl_g_parallel_redo_init(knl_g_parallel_redo_context* predo_cxt) { Assert(predo_cxt != NULL); + //纭繚 predo_cxt 鎸囬拡涓嶄负绌 predo_cxt->state = REDO_INIT; + //琛ㄧず骞惰閲嶅仛鐨勭姸鎬佷负鍒濆鍖栫姸鎬 predo_cxt->parallelRedoCtx = NULL; + //琛ㄧず鏈垎閰嶅叧鑱旂殑骞惰閲嶅仛涓婁笅鏂 for (int i = 0; i < MAX_RECOVERY_THREAD_NUM; ++i) { predo_cxt->pageRedoThreadStatusList[i].threadId = 0; predo_cxt->pageRedoThreadStatusList[i].threadState = PAGE_REDO_WORKER_INVALID; } predo_cxt->totalNum = 0; + //琛ㄧず鎬荤嚎绋嬫暟涓0 SpinLockInit(&(predo_cxt->rwlock)); + //鍒濆鍖栬嚜鏃嬮攣 rwlock predo_cxt->redoPf.redo_start_ptr = 0; predo_cxt->redoPf.redo_start_time = 0; predo_cxt->redoPf.redo_done_time = 0; @@ -250,13 +307,18 @@ static void knl_g_parallel_redo_init(knl_g_parallel_redo_context* predo_cxt) predo_cxt->redoPf.speed_according_seg = 0; predo_cxt->redoPf.local_max_lsn = 0; predo_cxt->redoPf.oldest_segment = 1; + //鐢ㄤ簬璁板綍閲嶅仛鐨勮繘搴﹀拰鎬ц兘淇℃伅 knl_g_set_redo_finish_status(0); + //灏嗛噸鍋氬畬鎴愮姸鎬佽缃负0 predo_cxt->redoType = DEFAULT_REDO; + //琛ㄧず閲嶅仛绫诲瀷涓洪粯璁ょ被鍨 predo_cxt->pre_enable_switch = 0; + //灏 pre_enable_switch 鎴愬憳璁剧疆涓0 SpinLockInit(&(predo_cxt->destroy_lock)); for (int i = 0; i < NUM_MAX_PAGE_FLUSH_LSN_PARTITIONS; ++i) { pg_atomic_write_u64(&(predo_cxt->max_page_flush_lsn[i]), 0); } + //鐢ㄤ簬璁板綍鏈澶ч〉闈㈠埛鏂癓SN锛圠og Sequence Number锛夌殑鍊 predo_cxt->permitFinishRedo = 0; predo_cxt->last_replayed_conflict_csn = 0; predo_cxt->hotStdby = 0; @@ -276,27 +338,35 @@ static void knl_g_parallel_decode_init(knl_g_parallel_decode_context* pdecode_cx { Assert(pdecode_cxt != NULL); pdecode_cxt->state = DECODE_INIT; + //琛ㄧず骞惰瑙g爜鐨勭姸鎬佷负鍒濆鍖栫姸鎬 pdecode_cxt->parallelDecodeCtx = NULL; + //琛ㄧず鏈垎閰嶅叧鑱旂殑骞惰瑙g爜涓婁笅鏂 pdecode_cxt->ParallelReaderWorkerStatus.threadId = 0; pdecode_cxt->ParallelReaderWorkerStatus.threadState = PARALLEL_DECODE_WORKER_INVALID; - for (int i = 0; i < MAX_PARALLEL_DECODE_NUM; ++i) { + //琛ㄧず骞惰瑙g爜宸ヤ綔鑰呯姸鎬佷负鏃犳晥 + for (int i = 0; i < MAX_PARALLEL_DECODE_NUM; ++i) { pdecode_cxt->ParallelDecodeWorkerStatusList[i].threadId = 0; pdecode_cxt->ParallelDecodeWorkerStatusList[i].threadState = PARALLEL_DECODE_WORKER_INVALID; } pdecode_cxt->totalNum = 0; + //琛ㄧず鎬荤嚎绋嬫暟涓0 SpinLockInit(&(pdecode_cxt->rwlock)); SpinLockInit(&(pdecode_cxt->destroy_lock)); + //鍒濆鍖栬嚜鏃嬮攣 destroy_lock } static void knl_g_cache_init(knl_g_cache_context* cache_cxt) { cache_cxt->global_cache_mem = NULL; + //琛ㄧず鍏ㄥ眬缂撳瓨鍐呭瓨鏈垎閰 for (int i = 0; i < MAX_GLOBAL_CACHEMEM_NUM; ++i) cache_cxt->global_plancache_mem[i] = NULL; + //閫氳繃寰幆閬嶅巻锛屽 global_plancache_mem 鏁扮粍涓殑姣忎釜鍏冪礌杩涜鍒濆鍖 } void knl_g_cachemem_create() { + //鍒涘缓鍏ㄥ眬缂撳瓨鍐呭瓨涓婁笅鏂囷紝鍛藉悕涓 "GlobalCacheMemory"锛屽苟璁剧疆榛樿鐨勫唴瀛樺垎閰嶅弬鏁 g_instance.cache_cxt.global_cache_mem = AllocSetContextCreate(g_instance.instance_context, "GlobalCacheMemory", ALLOCSET_DEFAULT_MINSIZE, @@ -305,7 +375,7 @@ void knl_g_cachemem_create() SHARED_CONTEXT, DEFAULT_MEMORY_CONTEXT_MAX_SIZE, false); - + //閬嶅巻鍏ㄥ眬璁″垝缂撳瓨鍐呭瓨鏁扮粍锛屼负姣忎釜鍏冪礌鍒涘缓鍐呭瓨涓婁笅鏂囷紝鍛藉悕涓 "GlobalPlanCacheMemory"锛屽苟璁剧疆榛樿鐨勫唴瀛樺垎閰嶅弬鏁 for (int i = 0; i < MAX_GLOBAL_CACHEMEM_NUM; ++i) { g_instance.cache_cxt.global_plancache_mem[i] = AllocSetContextCreate(g_instance.instance_context, "GlobalPlanCacheMemory", @@ -316,6 +386,7 @@ void knl_g_cachemem_create() DEFAULT_MEMORY_CONTEXT_MAX_SIZE, false); } + //閬嶅巻鍏ㄥ眬鍖呰繍琛屾椂缂撳瓨鍐呭瓨鏁扮粍锛屼负姣忎釜鍏冪礌鍒涘缓鍐呭瓨涓婁笅鏂囷紝鍛藉悕涓 "GlobalPackageRuntimeCacheMemory"锛屽苟璁剧疆榛樿鐨勫唴瀛樺垎閰嶅弬鏁 for (int i = 0; i < MAX_GLOBAL_PRC_NUM; ++i) { g_instance.cache_cxt.global_prc_mem[i] = AllocSetContextCreate(g_instance.instance_context, "GlobalPackageRuntimeCacheMemory", @@ -326,58 +397,72 @@ void knl_g_cachemem_create() DEFAULT_MEMORY_CONTEXT_MAX_SIZE, false); } + //鍒涘缓鍏ㄥ眬璁″垝缂撳瓨瀵硅薄 g_instance.plan_cache = New(INSTANCE_GET_MEM_CXT_GROUP(MEMORY_CONTEXT_EXECUTOR)) GlobalPlanCache(); - g_instance.global_session_pkg = PLGlobalPackageRuntimeCache::Instance(); + //鍒涘缓鍏ㄥ眬浼氳瘽鍖呰繍琛屾椂缂撳瓨瀵硅薄 + g_instance.global_session_pkg = PLGlobalPackageRuntimeCache::Instance(); } static void knl_g_comm_init(knl_g_comm_context* comm_cxt) { + //鏂█纭繚浼犲叆鐨 comm_cxt 鎸囬拡涓嶄负绌 Assert(comm_cxt != NULL); - comm_cxt->gs_wakeup_consumer = NULL; - comm_cxt->g_receivers = NULL; - comm_cxt->g_senders = NULL; - comm_cxt->g_delay_survey_switch = false; - comm_cxt->g_unix_path = NULL; - comm_cxt->g_ha_shm_data = NULL; - comm_cxt->g_usable_streamid = NULL; - comm_cxt->g_r_node_sock = NULL; - comm_cxt->g_s_node_sock = NULL; - comm_cxt->g_delay_info = NULL; - comm_cxt->g_c_mailbox = NULL; - comm_cxt->g_p_mailbox = NULL; - comm_cxt->libcomm_log_timezone = NULL; - comm_cxt->force_cal_space_info = false; - comm_cxt->cal_all_space_info_in_progress = false; - comm_cxt->current_gsrewind_count = 0; - comm_cxt->isNeedChangeRole = false; - comm_cxt->usedDnSpace = NULL; - comm_cxt->request_disaster_cluster = true; - comm_cxt->lastArchiveRcvTime = 0; + + //鍒濆鍖 comm_cxt 缁撴瀯涓殑鍚勪釜鎴愬憳鍙橀噺涓洪粯璁ゅ兼垨 NULL + comm_cxt->gs_wakeup_consumer = NULL; //鎸囧悜鍞ら啋娑堣垂鑰呯殑鎸囬拡 + comm_cxt->g_receivers = NULL; //鎺ユ敹鑰呬俊鎭 + comm_cxt->g_senders = NULL; //鍙戦佽呬俊鎭 + comm_cxt->g_delay_survey_switch = false; //寤惰繜娴嬮噺寮鍏 + comm_cxt->g_unix_path = NULL; //UNIX 濂楁帴瀛楄矾寰 + comm_cxt->g_ha_shm_data = NULL; //HA 鍏变韩鍐呭瓨鏁版嵁 + comm_cxt->g_usable_streamid = NULL; //鍙敤鐨勬祦 ID + comm_cxt->g_r_node_sock = NULL; //鎺ユ敹鑺傜偣濂楁帴瀛椾俊鎭 + comm_cxt->g_s_node_sock = NULL; //鍙戦佽妭鐐瑰鎺ュ瓧淇℃伅 + comm_cxt->g_delay_info = NULL; //寤惰繜淇℃伅 + comm_cxt->g_c_mailbox = NULL; //CMailbox锛堥氫俊閭锛変俊鎭 + comm_cxt->g_p_mailbox = NULL; //PMailbox锛堥氫俊閭锛変俊鎭 + comm_cxt->libcomm_log_timezone = NULL; //鏃ュ織鏃跺尯 + comm_cxt->force_cal_space_info = false; //寮哄埗璁$畻绌洪棿淇℃伅鏍囧織 + comm_cxt->cal_all_space_info_in_progress = false; //姝e湪璁$畻鎵鏈夌┖闂翠俊鎭殑鏍囧織 + comm_cxt->current_gsrewind_count = 0; //褰撳墠 GS_REWIND 鐨勮鏁 + comm_cxt->isNeedChangeRole = false; //鏄惁闇瑕佹敼鍙樿鑹 + comm_cxt->usedDnSpace = NULL; //宸茬敤鐨勬暟鎹妭鐐圭┖闂翠俊鎭 + comm_cxt->request_disaster_cluster = true; //璇锋眰鐏惧闆嗙兢淇℃伅鐨勬爣蹇 + comm_cxt->lastArchiveRcvTime = 0; //涓婃褰掓。鎺ユ敹鏃堕棿 #ifdef USE_SSL - comm_cxt->libcomm_data_port_list = NULL; - comm_cxt->libcomm_ctrl_port_list = NULL; + //濡傛灉浣跨敤 SSL 鍔犲瘑閫氫俊锛屽垯鍒濆鍖 SSL 鐩稿叧鐨勬垚鍛樺彉閲 + comm_cxt->libcomm_data_port_list = NULL; //鏁版嵁绔彛鍒楄〃 + comm_cxt->libcomm_ctrl_port_list = NULL; //鎺у埗绔彛鍒楄〃 #endif - knl_g_quota_init(&g_instance.comm_cxt.quota_cxt); - knl_g_localinfo_init(&g_instance.comm_cxt.localinfo_cxt); - knl_g_counters_init(&g_instance.comm_cxt.counters_cxt); - knl_g_tests_init(&g_instance.comm_cxt.tests_cxt); - knl_g_pollers_init(&g_instance.comm_cxt.pollers_cxt); - knl_g_reqcheck_init(&g_instance.comm_cxt.reqcheck_cxt); - knl_g_mctcp_init(&g_instance.comm_cxt.mctcp_cxt); - knl_g_commutil_init(&g_instance.comm_cxt.commutil_cxt); - knl_g_parallel_redo_init(&g_instance.comm_cxt.predo_cxt); + //鍒嗗埆璋冪敤鍏朵粬鍒濆鍖栧嚱鏁版潵鍒濆鍖 comm_cxt 涓殑鍏朵粬鎴愬憳鍙橀噺 + knl_g_quota_init(&g_instance.comm_cxt.quota_cxt); //鍒濆鍖栭厤棰濅俊鎭 + knl_g_localinfo_init(&g_instance.comm_cxt.localinfo_cxt); //鍒濆鍖栨湰鍦颁俊鎭 + knl_g_counters_init(&g_instance.comm_cxt.counters_cxt); //鍒濆鍖栬鏁板櫒淇℃伅 + knl_g_tests_init(&g_instance.comm_cxt.tests_cxt); //鍒濆鍖栨祴璇曚俊鎭 + knl_g_pollers_init(&g_instance.comm_cxt.pollers_cxt); //鍒濆鍖栬疆璇㈠櫒淇℃伅 + knl_g_reqcheck_init(&g_instance.comm_cxt.reqcheck_cxt); //鍒濆鍖栬姹傛鏌ヤ俊鎭 + knl_g_mctcp_init(&g_instance.comm_cxt.mctcp_cxt); //鍒濆鍖 MCTCP 淇℃伅 + knl_g_commutil_init(&g_instance.comm_cxt.commutil_cxt); //鍒濆鍖栭氫俊宸ュ叿淇℃伅 + knl_g_parallel_redo_init(&g_instance.comm_cxt.predo_cxt); //鍒濆鍖栧苟琛岄噸鍋氫俊鎭 + + //閬嶅巻骞跺垵濮嬪寲骞惰瑙g爜淇℃伅锛堟牴鎹渶澶у鍒舵Ы鏁帮級 for (int i = 0; i < g_instance.attr.attr_storage.max_replication_slots; ++i) { knl_g_parallel_decode_init(&g_instance.comm_cxt.pdecode_cxt[i]); } } + static void knl_g_conn_init(knl_g_conn_context* conn_cxt) { conn_cxt->CurConnCount = 0; + //琛ㄧず褰撳墠杩炴帴鐨勬暟閲忎负0 conn_cxt->CurCMAConnCount = 0; + //琛ㄧず褰撳墠 CMA杩炴帴鐨勬暟閲忎负0 conn_cxt->CurCMAProcCount = 0; + //琛ㄧず褰撳墠 CMA 杩涚▼鐨勬暟閲忎负0 SpinLockInit(&conn_cxt->ConnCountLock); + //鐢ㄤ簬鍦ㄥ绾跨▼鐜涓嬩繚鎶よ繛鎺ヨ鏁颁俊鎭殑骞跺彂璁块棶 } static void knl_g_executor_init(knl_g_executor_context* exec_cxt) @@ -396,29 +481,43 @@ static void knl_g_rto_init(knl_g_rto_context *rto_cxt) static void knl_g_xlog_init(knl_g_xlog_context *xlog_cxt) { + // 濮嬪寲 xlog_cxt 缁撴瀯涓殑鎴愬憳鍙橀噺涓洪粯璁ゅ兼垨 NULL + + //鍒濆鍖 num_locks_in_group 涓0锛岃〃绀洪攣缁勬暟閲忎负0 xlog_cxt->num_locks_in_group = 0; + #ifdef ENABLE_MOT + //濡傛灉鍚敤浜 MOT 瀛樺偍寮曟搸锛屽垯鍒濆鍖 redoCommitCallback 涓 NULL xlog_cxt->redoCommitCallback = NULL; #endif + + //鍒濆鍖 shareStorageXLogCtl 鍜 shareStorageXLogCtlOrigin 涓 NULL xlog_cxt->shareStorageXLogCtl = NULL; xlog_cxt->shareStorageXLogCtlOrigin = NULL; + //浣跨敤 memset_s 鍑芥暟灏 shareStorageopCtl 缁撴瀯鍒濆鍖栦负0 errno_t rc = memset_s(&xlog_cxt->shareStorageopCtl, sizeof(ShareStorageOperateCtl), 0, sizeof(ShareStorageOperateCtl)); securec_check(rc, "\0", "\0"); + //鍒濆鍖 remain_segs_lock 浜掓枼閿佷负 NULL pthread_mutex_init(&xlog_cxt->remain_segs_lock, NULL); + //鍒濆鍖 shareStorageLockFd 涓 -1锛岃〃绀哄叡浜瓨鍌ㄩ攣鐨勬枃浠舵弿杩扮涓烘棤鏁堝 xlog_cxt->shareStorageLockFd = -1; } + static void KnlGUndoInit(knl_g_undo_context *undoCxt) { + //浣跨敤 undo 鍛藉悕绌洪棿 using namespace undo; MemoryContext oldContext; + + //鍒涘缓 Undo 鍛藉悕绌洪棿鐨勫唴瀛樹笂涓嬫枃锛屽苟灏嗗叾璁剧疆涓哄綋鍓嶄笂涓嬫枃 g_instance.undo_cxt.undoContext = AllocSetContextCreate(g_instance.instance_context, "Undo", ALLOCSET_DEFAULT_MINSIZE, ALLOCSET_DEFAULT_INITSIZE, ALLOCSET_UNDO_MAXSIZE, SHARED_CONTEXT); oldContext = MemoryContextSwitchTo(g_instance.undo_cxt.undoContext); /* - * Create three bitmaps for undozone with three kinds of tables(permanent, unlogged and temp). - * Use -1 to initialize each bit of the bitmap as 1. + 涓烘瘡涓寔涔呮х骇鍒紙permanent, unlogged 鍜 temp锛夊垱寤轰笁涓綅鍥撅紝 + 浣跨敤 -1 鍒濆鍖栦綅鍥剧殑姣忎釜浣嶏紙bit锛変负1銆 */ for (auto i = 0; i < UNDO_PERSISTENCE_LEVELS; i++) { g_instance.undo_cxt.uZoneBitmap[i] = bms_add_member(g_instance.undo_cxt.uZoneBitmap[i], PERSIST_ZONE_COUNT); @@ -426,7 +525,9 @@ static void KnlGUndoInit(knl_g_undo_context *undoCxt) (g_instance.undo_cxt.uZoneBitmap[i])->nwords * sizeof(bitmapword), -1, (g_instance.undo_cxt.uZoneBitmap[i])->nwords * sizeof(bitmapword)); } + //鎭㈠鍏堝墠鐨勫唴瀛樹笂涓嬫枃 MemoryContextSwitchTo(oldContext); + //鍒濆鍖 undoCxt 缁撴瀯涓殑鎴愬憳鍙橀噺涓洪粯璁ゅ undoCxt->undoTotalSize = 0; undoCxt->undoMetaSize = 0; undoCxt->uZoneCount = 0; @@ -443,6 +544,7 @@ static void knl_g_flashback_init(knl_g_flashback_context *flashbackCxt) static void knl_g_libpq_init(knl_g_libpq_context* libpq_cxt) { + //鍒濆鍖杔ibpq涓悇鍙傛暟鍊 Assert(libpq_cxt != NULL); libpq_cxt->pam_passwd = NULL; libpq_cxt->pam_port_cludge = NULL; @@ -452,6 +554,7 @@ static void knl_g_libpq_init(knl_g_libpq_context* libpq_cxt) static void InitHotkeyResources(knl_g_stat_context* stat_cxt) { + //濡傛灉 hotkeysCxt 涓 NULL锛屽垯鍒涘缓涓涓柊鐨勫唴瀛樹笂涓嬫枃 hotkeysCxt if (stat_cxt->hotkeysCxt == NULL) { stat_cxt->hotkeysCxt = AllocSetContextCreate(INSTANCE_GET_MEM_CXT_GROUP(MEMORY_CONTEXT_OPTIMIZER), "HotkeysMemory", @@ -460,48 +563,68 @@ static void InitHotkeyResources(knl_g_stat_context* stat_cxt) ALLOCSET_DEFAULT_MAXSIZE, SHARED_CONTEXT); } + + //鍦 hotkeysCxt 鍐呭瓨涓婁笅鏂囦腑鍒涘缓 CircularQueue锛堝惊鐜槦鍒楋級骞跺垵濮嬪寲 stat_cxt->hotkeysCollectList = New(stat_cxt->hotkeysCxt) CircularQueue(HOTKEYS_QUEUE_LENGTH, stat_cxt->hotkeysCxt); stat_cxt->hotkeysCollectList->Init(); + + //鍦 hotkeysCxt 鍐呭瓨涓婁笅鏂囦腑鍒涘缓 LRUCache锛堟渶杩戞渶灏戜娇鐢ㄧ紦瀛橈級骞跺垵濮嬪寲 stat_cxt->lru = New(stat_cxt->hotkeysCxt) LRUCache(LRU_QUEUE_LENGTH, stat_cxt->hotkeysCxt); stat_cxt->lru->Init(); + + //鍒濆鍖 fifo锛團irst-In-First-Out锛屽厛杩涘厛鍑猴級闃熷垪涓 NULL stat_cxt->fifo = NIL; } static void knl_g_stat_init(knl_g_stat_context* stat_cxt) { + //鍒濆鍖栫瓑寰呰鏁板搱甯岃〃涓 NULL stat_cxt->WaitCountHashTbl = NULL; + //鍒濆鍖栫瓑寰呰鏁扮姸鎬佸垪琛ㄤ负 NULL stat_cxt->WaitCountStatusList = NULL; + //鍒濆鍖 pgStatSock 涓烘棤鏁堢殑濂楁帴瀛 stat_cxt->pgStatSock = PGINVALID_SOCKET; + //鍒濆鍖 got_SIGHUP 涓 false stat_cxt->got_SIGHUP = false; - + //鍒濆鍖 UniqueSqlContext 涓 NULL stat_cxt->UniqueSqlContext = NULL; + //鍒濆鍖 UniqueSQLHashtbl 涓 NULL stat_cxt->UniqueSQLHashtbl = NULL; + //鍒濆鍖 InstrUserHTAB 涓 NULL stat_cxt->InstrUserHTAB = NULL; + //鍒濆鍖 calculate_on_other_cn 涓 false stat_cxt->calculate_on_other_cn = false; + //鍒濆鍖 force_process 涓 false stat_cxt->force_process = false; + //鍒濆鍖 RTPERCENTILE 鏁扮粍鐨勫厓绱犱负 0 stat_cxt->RTPERCENTILE[0] = 0; stat_cxt->RTPERCENTILE[1] = 0; + //鍒濆鍖 NodeStatResetTime 涓 0 stat_cxt->NodeStatResetTime = 0; + //鍒濆鍖 sql_rt_info_array 涓 NULL stat_cxt->sql_rt_info_array = NULL; - + //鍒濆鍖 gInstanceTimeInfo 鏁扮粍涓 0 stat_cxt->gInstanceTimeInfo = (int64*)MemoryContextAllocZero( INSTANCE_GET_MEM_CXT_GROUP(MEMORY_CONTEXT_DFX), TOTAL_TIME_INFO_TYPES * sizeof(int64)); errno_t rc; rc = memset_s( stat_cxt->gInstanceTimeInfo, TOTAL_TIME_INFO_TYPES * sizeof(int64), 0, TOTAL_TIME_INFO_TYPES * sizeof(int64)); securec_check(rc, "\0", "\0"); - + + //鍒濆鍖 snapshot_thread_counter 涓 0 stat_cxt->snapshot_thread_counter = 0; - + //鍒濆鍖 fileIOStat 涓 0 stat_cxt->fileIOStat = (FileIOStat*)MemoryContextAllocZero( INSTANCE_GET_MEM_CXT_GROUP(MEMORY_CONTEXT_DFX), sizeof(FileIOStat)); rc = memset_s(stat_cxt->fileIOStat, sizeof(FileIOStat), 0, sizeof(FileIOStat)); securec_check(rc, "\0", "\0"); + //鍒濆鍖 tableStat 涓 0 stat_cxt->tableStat = (UHeapPruneStat *) palloc0(sizeof(UHeapPruneStat)); rc = memset_s(stat_cxt->tableStat, sizeof(UHeapPruneStat), 0, sizeof(UHeapPruneStat)); securec_check(rc, "\0", "\0"); + stat_cxt->active_sess_hist_arrary = NULL; stat_cxt->ash_appname = NULL; stat_cxt->instr_stmt_is_cleaning = false; @@ -509,11 +632,13 @@ static void knl_g_stat_init(knl_g_stat_context* stat_cxt) stat_cxt->ASHUniqueSQLHashtbl = NULL; stat_cxt->track_context_hash = NULL; stat_cxt->track_memory_info_hash = NULL; + + //鍒涘缓骞跺垵濮嬪寲鐢ㄤ簬璺熻釜鍐呭瓨閿佺殑 rwlock pthread_rwlockattr_t attr; - /* set write-first lock for rwlock to avoid hunger of wrlock */ (void)pthread_rwlockattr_setkind_np(&attr, PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP); (void)pthread_rwlock_init(&(stat_cxt->track_memory_lock), &attr); - + + //璋冪敤 InitHotkeyResources 鍑芥暟鏉ュ垵濮嬪寲鐑偣鏁版嵁缁熻璧勬簮 InitHotkeyResources(stat_cxt); } @@ -524,17 +649,23 @@ static void knl_g_adv_init(knl_g_advisor_conntext* adv_cxt) adv_cxt->maxMemory = 0; adv_cxt->maxsqlCount = 0; adv_cxt->currentUser = InvalidOid; + //琛ㄧず娌℃湁鏈夋晥鐨勭敤鎴锋爣璇 adv_cxt->currentDB = InvalidOid; + //琛ㄧず娌℃湁鏈夋晥鐨勬暟鎹簱鏍囪瘑 adv_cxt->GWCArray = NULL; - + //琛ㄧず娌℃湁鍒嗛厤鍐呭瓨鎴栧垵濮嬪寲璇ユ暟缁 + adv_cxt->SQLAdvisorContext = NULL; + //琛ㄧず娌℃湁涓 SQL 鏌ヨ浼樺寲鎻愪緵棰濆鐨勪笂涓嬫枃鎴栬祫婧 } static void knl_g_pid_init(knl_g_pid_context* pid_cxt) { - errno_t rc; + errno_t rc;//琛ㄧず鎿嶄綔鏄惁鎴愬姛 rc = memset_s(pid_cxt, sizeof(knl_g_pid_context), 0, sizeof(knl_g_pid_context)); - pid_cxt->PageWriterPID = NULL; + /*memset_s 鏄竴涓畨鍏ㄧ増鏈殑鍐呭瓨娓呴浂鍑芥暟锛屽畠鎺ュ彈鍥涗釜鍙傛暟锛氱洰鏍囧唴瀛樺湴鍧锛岀洰鏍囧唴瀛樺ぇ灏忥紝 + 璁剧疆鐨勫硷紙杩欓噷鏄0锛夛紝浠ュ強鐩爣鍐呭瓨鐨勫ぇ灏忋傝繖鍙互纭繚 pid_cxt 鐨勬墍鏈夊瓧娈甸兘琚垵濮嬪寲涓0銆*/ + pid_cxt->PageWriterPID = NULL; pid_cxt->CommReceiverPIDS = NULL; pid_cxt->PgAuditPID = NULL; securec_check(rc, "\0", "\0"); @@ -542,7 +673,8 @@ static void knl_g_pid_init(knl_g_pid_context* pid_cxt) static void knl_g_wlm_init(knl_g_wlm_context* wlm_cxt) { - wlm_cxt->parctl_process_memory = 8; // initialize the per query memory as 8 MB + wlm_cxt->parctl_process_memory = 8; + //灏嗘瘡涓煡璇㈢殑鍐呭瓨鍒濆鍖栦负8 MB wlm_cxt->cluster_state = NULL; wlm_cxt->dnnum_in_cluster_state = 0; @@ -571,10 +703,15 @@ static void knl_g_compaction_init(knl_g_ts_compaction_context* tsc_cxt) Assert(tsc_cxt != NULL); tsc_cxt->totalNum = 0; tsc_cxt->state = Compaction::COMPACTION_INIT; - tsc_cxt->drop_db_count = 0; + //琛ㄧず鍘嬬缉鐘舵佷负鍒濆鍖栫姸鎬 + tsc_cxt->drop_db_count = 0; + //琛ㄧず瑕佸垹闄ょ殑鏁版嵁搴撴暟閲 tsc_cxt->origin_id = (int*)palloc0(sizeof(int) * Compaction::MAX_TSCOMPATION_NUM); - tsc_cxt->compaction_rest = false; + //鐢ㄤ簬璺熻釜鏁版嵁搴撶殑鍘熷鏍囪瘑 + tsc_cxt->compaction_rest = false; + //琛ㄧず娌℃湁杩涜鍘嬬缉鐨勪紤鎭姸鎬 tsc_cxt->dropdb_id = InvalidOid; + //琛ㄧず瑕佸垹闄ょ殑鏁版嵁搴撶殑鏍囪瘑 for (int i = 0; i < Compaction::MAX_TSCOMPATION_NUM; i++) { tsc_cxt->compaction_worker_status_list[i].thread_id = 0; tsc_cxt->compaction_worker_status_list[i].thread_state = Compaction::COMPACTION_WORKER_INVALID; @@ -595,10 +732,13 @@ static void knl_g_dw_init(knl_g_dw_context *dw_cxt) errno_t rc = memset_s(dw_cxt, sizeof(knl_g_dw_context), 0, sizeof(knl_g_dw_context)); securec_check(rc, "\0", "\0"); dw_cxt->closed = 1; - + //琛ㄧず鏁版嵁浠撳簱澶勪簬鍏抽棴鐘舵 dw_cxt->old_batch_version = false; + //琛ㄧず浣跨敤鐨勬槸鏃ф壒澶勭悊鐗堟湰 dw_cxt->recovery_dw_file_num = 0; + //琛ㄧず鎭㈠鏃剁殑鏁版嵁浠撳簱鏂囦欢鏁伴噺涓 0 dw_cxt->recovery_dw_file_size = 0; + //琛ㄧず鎭㈠鏃剁殑鏁版嵁浠撳簱鏂囦欢澶у皬涓 0 } static void knl_g_numa_init(knl_g_numa_context* numa_cxt) @@ -627,6 +767,7 @@ static void knl_g_archive_obs_init(knl_g_archive_context *archive_cxt) static void knl_g_archive_thread_info_init(knl_g_archive_thread_info *archive_thread_info) { + //鐢ㄤ簬涓哄綊妗g嚎绋嬩俊鎭殑鍏ㄥ眬缁撴瀯浣撹缃粯璁ゅ煎拰鐘舵 errno_t rc = memset_s(archive_thread_info, sizeof(knl_g_archive_thread_info), 0, sizeof(knl_g_archive_thread_info)); securec_check(rc, "\0", "\0"); @@ -637,6 +778,7 @@ static void knl_g_archive_thread_info_init(knl_g_archive_thread_info *archive_th static void knl_g_mot_init(knl_g_mot_context* mot_cxt) { mot_cxt->jitExecMode = JitExec::JIT_EXEC_MODE_INVALID; + //杩欎釜瀛楁鐢ㄤ簬琛ㄧず MOT 鎵ц鐨 JIT锛堝嵆鏃剁紪璇戯級妯″紡锛屾澶勫皢鍏跺垵濮嬪寲涓烘棤鏁堟ā寮 } #endif @@ -672,6 +814,7 @@ static void knl_g_pldebug_init(knl_g_pldebug_context* pldebug_cxt) static void knl_g_spi_plan_init(knl_g_spi_plan_context* spi_plan_cxt) { + //鐢ㄤ簬鍦ㄥ垵濮嬪寲 SPI 璁″垝涓婁笅鏂囨椂锛屽皢鍏跺瓧娈靛垵濮嬪寲涓洪粯璁ゅ兼垨绌哄 spi_plan_cxt->global_spi_plan_context = NULL; spi_plan_cxt->FPlans = NULL; spi_plan_cxt->nFPlans = 0; @@ -759,11 +902,17 @@ void knl_instance_init() pg_atomic_init_u32(&g_instance.extensionNum, 0); /* - * Set up the process wise memory context. The memory allocated from this - * context will not be released untill it is called free. Meanwhile, the - * memory context is visible to all threads but not thread safe, so only - * postmaster thread shall use it or use it with lock protection. + 杩欎釜鍐呭瓨涓婁笅鏂囨槸杩涚▼绾у埆鐨勶紝鍗虫瘡涓繘绋嬮兘鏈夎嚜宸辩嫭绔嬬殑鍐呭瓨涓婁笅鏂囷紝 + 鍏朵腑鍒嗛厤鐨勫唴瀛樺彧鏈夊湪鏄惧紡璋冪敤閲婃斁鍑芥暟涔嬪悗鎵嶄細閲婃斁銆傛澶栵紝杩欎釜鍐呭瓨 + 涓婁笅鏂囧鎵鏈夌嚎绋嬪彲瑙侊紝浣嗕笉鏄嚎绋嬪畨鍏ㄧ殑锛屽洜姝ゅ彧鏈変富杩涚▼锛圥ostmaster + 绾跨▼锛夊簲璇ヤ娇鐢ㄥ畠锛屾垨鑰呭湪浣跨敤鏃堕渶瑕佽繘琛岄攣淇濇姢銆 */ + + /* + 杩欑璁剧疆鍏佽杩涚▼鍦ㄨ繍琛岃繃绋嬩腑鍒嗛厤鍐呭瓨锛屽苟鍦ㄩ渶瑕佹椂鎵嬪姩閲婃斁锛岃屼笉浼 + 鍦ㄦ瘡娆″垎閰嶅唴瀛樻椂閮借繘琛岃嚜鍔ㄩ噴鏀俱傝繖瀵逛簬闇瑕佹洿缁嗙矑搴﹀湴鎺у埗鍐呭瓨绠 + 鐞嗙殑鎯呭喌闈炲父鏈夌敤锛屼絾闇瑕佸紑鍙戜汉鍛樿嚜琛岀鐞嗗唴瀛樼殑鐢熷懡鍛ㄦ湡鍜岀嚎绋嬪畨鍏ㄦс + */ g_instance.instance_context = AllocSetContextCreate((MemoryContext)NULL, "ProcessMemory", ALLOCSET_DEFAULT_MINSIZE, @@ -835,15 +984,20 @@ void knl_instance_init() void add_numa_alloc_info(void* numaAddr, size_t length) { + //濡傛灉宸插垎閰嶇殑 NUMA 鍐呭瓨淇℃伅鏁伴噺瓒呰繃浜嗘暟缁勭殑鏈澶ч暱搴,灏辫璁$畻鏂扮殑鏁扮粍闀垮害锛屽皢鏁扮粍闀垮害缈诲 if (g_instance.numa_cxt.allocIndex >= g_instance.numa_cxt.maxLength) { size_t newLength = g_instance.numa_cxt.maxLength * 2; g_instance.numa_cxt.numaAllocInfos = (NumaMemAllocInfo*)repalloc(g_instance.numa_cxt.numaAllocInfos, newLength * sizeof(NumaMemAllocInfo)); + //浣跨敤repalloc鍑芥暟閲嶆柊鍒嗛厤鍐呭瓨锛屼互閫傚簲鏂扮殑鏁扮粍闀垮害銆傝繖灏嗗鑷村垎閰嶄竴涓柊鐨勬暟缁勶紝鍚屾椂淇濈暀浠ュ墠鐨勬暟鎹 g_instance.numa_cxt.maxLength = newLength; } g_instance.numa_cxt.numaAllocInfos[g_instance.numa_cxt.allocIndex].numaAddr = numaAddr; - g_instance.numa_cxt.numaAllocInfos[g_instance.numa_cxt.allocIndex].length = length; + //灏嗗綋鍓嶇储寮曚綅缃殑 NUMA 鍐呭瓨鍦板潃璁剧疆涓轰紶鍏ョ殑 numaAddr + g_instance.numa_cxt.numaAllocInfos[g_instance.numa_cxt.allocIndex].length = length; + //灏嗗綋鍓嶇储寮曚綅缃殑 NUMA 鍐呭瓨鍧楅暱搴﹁缃负浼犲叆鐨 length ++g_instance.numa_cxt.allocIndex; + //澧炲姞 NUMA 鍐呭瓨淇℃伅鏁扮粍鐨勭储寮曪紝浠ヤ究涓嬫娣诲姞淇℃伅鏃朵娇鐢ㄦ柊鐨勪綅缃 } void knl_g_set_redo_finish_status(uint32 status) @@ -867,7 +1021,9 @@ bool knl_g_get_local_redo_finish_status() #if defined(__arm__) || defined(__arm) || defined(__aarch64__) || defined(__aarch64) pg_memory_barrier(); #endif + //浣跨敤鍘熷瓙璇诲彇鑾峰彇 Redo 瀹屾垚鐘舵 uint32 isRedoFinish = pg_atomic_read_u32(&(g_instance.comm_cxt.predo_cxt.isRedoFinish)); + //妫鏌ユ槸鍚︽湰鍦 Redo 瀹屾垚锛堟寜浣嶄笌鎿嶄綔锛 return (isRedoFinish & REDO_FINISH_STATUS_LOCAL) == REDO_FINISH_STATUS_LOCAL; } @@ -876,7 +1032,8 @@ bool knl_g_get_redo_finish_status() #if defined(__arm__) || defined(__arm) || defined(__aarch64__) || defined(__aarch64) pg_memory_barrier(); #endif + //浣跨敤鍘熷瓙璇诲彇鑾峰彇 Redo 瀹屾垚鐘舵 uint32 isRedoFinish = pg_atomic_read_u32(&(g_instance.comm_cxt.predo_cxt.isRedoFinish)); + //妫鏌ユ槸鍚︽暣浣 Redo 瀹屾垚锛堟寜浣嶄笌鎿嶄綔锛 return (isRedoFinish & REDO_FINISH_STATUS_CM) == REDO_FINISH_STATUS_CM; -} - +} \ No newline at end of file diff --git a/src/gausskernel/process/threadpool/knl_session.cpp b/src/gausskernel/process/threadpool/knl_session.cpp index 6c3225a37..4d57bbbb5 100755 --- a/src/gausskernel/process/threadpool/knl_session.cpp +++ b/src/gausskernel/process/threadpool/knl_session.cpp @@ -2,20 +2,11 @@ * Copyright (c) 2020 Huawei Technologies Co.,Ltd. * Portions Copyright (c) 2021, openGauss Contributors * - * openGauss is licensed under Mulan PSL v2. - * You can use this software according to the terms and conditions of the Mulan PSL v2. - * You may obtain a copy of Mulan PSL v2 at: * - * http://license.coscl.org.cn/MulanPSL2 - * - * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, - * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, - * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. - * See the Mulan PSL v2 for more details. * ------------------------------------------------------------------------- * * knl_session.cpp - * Initial functions for session level global variables. + * 浼氳瘽绾у埆涓婂叏灞鍙橀噺鐨勫垵濮嬪寲 * * IDENTIFICATION * src/gausskernel/process/threadpool/knl_session.cpp @@ -74,14 +65,20 @@ extern int SysCacheSize; static void KnlUUstoreInit(knl_u_ustore_context *ustoreCxt) { + // 鍒涘缓涓涓 URecVector 瀵硅薄锛屽苟灏嗗叾鍒嗛厤缁 ustoreCxt->urecvec ustoreCxt->urecvec = New(CurrentMemoryContext) URecVector(); + // 鍒濆鍖 ustoreCxt->urecvec锛岃缃渶澶у閲忎负 MAX_UNDORECORDS_PER_OPERATION锛屽苟鍚敤鑷姩澧為暱 ustoreCxt->urecvec->Initialize(MAX_UNDORECORDS_PER_OPERATION, true); + // 浣跨敤寰幆鍒濆鍖 ustoreCxt->undo_records 鏁扮粍 for (int i = 0; i < MAX_UNDORECORDS_PER_OPERATION; i++) { - ustoreCxt->undo_records[i] = New(CurrentMemoryContext)UndoRecord(); + // 鍒涘缓涓涓 UndoRecord 瀵硅薄锛屽苟灏嗗叾鍒嗛厤缁 ustoreCxt->undo_records 鏁扮粍鐨勬瘡涓厓绱 + ustoreCxt->undo_records[i] = New(CurrentMemoryContext) UndoRecord(); + // 灏嗘瘡涓 UndoRecord 瀵硅薄娣诲姞鍒 ustoreCxt->urecvec 涓 ustoreCxt->urecvec->PushBack(ustoreCxt->undo_records[i]); } + // 鍒濆鍖 ustoreCxt 鐨勫叾浠栨垚鍛樺彉閲 ustoreCxt->undo_buffer_idx = 0; ustoreCxt->undo_buffers = (UndoBuffer*) palloc0(MAX_UNDO_BUFFERS * sizeof(UndoBuffer)); @@ -91,6 +88,7 @@ KnlUUstoreInit(knl_u_ustore_context *ustoreCxt) static void KnlURepOriginInit(knl_u_rep_origin_context* repOriginCxt) { + // 鍒濆鍖 repOriginCxt 鐨勬垚鍛樺彉閲 repOriginCxt->curRepState = NULL; repOriginCxt->originId = InvalidRepOriginId; repOriginCxt->originLsn = InvalidXLogRecPtr; @@ -101,17 +99,20 @@ static void KnlURepOriginInit(knl_u_rep_origin_context* repOriginCxt) static void knl_u_analyze_init(knl_u_analyze_context* anl_cxt) { + // 鍒濆鍖栧垎鏋愪笂涓嬫枃缁撴瀯 anl_cxt 鐨勬垚鍛樺彉閲 anl_cxt->is_under_analyze = false; anl_cxt->need_autoanalyze = false; anl_cxt->analyze_context = NULL; anl_cxt->autoanalyze_process = NULL; anl_cxt->autoanalyze_timeinfo = NULL; + // 涓 anl_cxt->vac_strategy 鍒嗛厤鍐呭瓨锛屽苟灏嗗叾鍒濆鍖栦负闆 anl_cxt->vac_strategy = (BufferAccessStrategyData*)palloc0(sizeof(BufferAccessStrategyData)); } static void knl_u_attr_init(knl_session_attr* attr) { - const int sessionDefaultTimeout = 600; /* 10 * 60 = 10 min */ + // 璁剧疆浼氳瘽灞炴х粨鏋 attr 鐨勫悇涓垚鍛樺彉閲忕殑榛樿鍊 + const int sessionDefaultTimeout = 600; /* 10 * 60绉 = 10 鍒嗛挓 */ attr->attr_common.backtrace_min_messages = PANIC; attr->attr_common.log_min_messages = WARNING; attr->attr_common.client_min_messages = NOTICE; @@ -128,6 +129,7 @@ static void knl_u_attr_init(knl_session_attr* attr) void knl_u_executor_init(knl_u_executor_context* exec_cxt) { + // 鍒濆鍖栨墽琛屽櫒涓婁笅鏂囩粨鏋 exec_cxt 鐨勫悇涓垚鍛樺彉閲 exec_cxt->remotequery_list = NIL; exec_cxt->exec_result_checkqual_fail = false; exec_cxt->under_stream_runtime = false; @@ -139,7 +141,6 @@ void knl_u_executor_init(knl_u_executor_context* exec_cxt) exec_cxt->route = (PartitionIdentifier*)palloc0(sizeof(PartitionIdentifier)); exec_cxt->cur_tuple_hash_table = NULL; exec_cxt->cur_light_proxy_obj = NULL; - exec_cxt->ActivePortal = NULL; exec_cxt->PortalHashTable = NULL; exec_cxt->unnamed_portal_count = 0; @@ -148,36 +149,30 @@ void knl_u_executor_init(knl_u_executor_context* exec_cxt) exec_cxt->hasTempObject = false; exec_cxt->DfsDDLIsTopLevelXact = false; exec_cxt->could_cancel_redistribution = false; - exec_cxt->g_pgaudit_agent_attached = false; exec_cxt->pgaudit_track_sqlddl = true; - exec_cxt->HashScans = NULL; exec_cxt->executorStopFlag = false; - exec_cxt->CurrentOpFusionObj = NULL; exec_cxt->nesting_level = 0; - exec_cxt->is_exec_trigger_func = false; exec_cxt->single_shard_stmt = false; - exec_cxt->cast_owner = InvalidOid; - exec_cxt->CurrentRouter = NULL; exec_cxt->is_dn_enable_router = false; - exec_cxt->isExecTrunc = false; - exec_cxt->isLockRows = false; } static void knl_u_index_init(knl_u_index_context* index_cxt) { + // 鍒濆鍖栫储寮曚笂涓嬫枃缁撴瀯 index_cxt 鐨 counter 鎴愬憳鍙橀噺 index_cxt->counter = 1; } static void knl_u_instrument_init(knl_u_instrument_context* instr_cxt) { + // 鍒濆鍖栨ц兘鐩戣鍣ㄤ笂涓嬫枃缁撴瀯 instr_cxt 鐨勫悇涓垚鍛樺彉閲 instr_cxt->perf_monitor_enable = false; instr_cxt->can_record_to_table = false; instr_cxt->operator_plan_number = 0; @@ -193,6 +188,7 @@ static void knl_u_instrument_init(knl_u_instrument_context* instr_cxt) static void knl_u_locale_init(knl_u_locale_context* lc_cxt) { + // 鍒濆鍖栬瑷鐜涓婁笅鏂囩粨鏋 lc_cxt 鐨勫悇涓垚鍛樺彉閲 lc_cxt->cur_lc_conv_valid = false; lc_cxt->cur_lc_time_valid = false; lc_cxt->cur_lc_conv = (struct lconv*)palloc0(sizeof(struct lconv)); @@ -203,6 +199,7 @@ static void knl_u_locale_init(knl_u_locale_context* lc_cxt) static void knl_u_log_init(knl_u_log_context* log_cxt) { + // 鍒濆鍖栨棩蹇椾笂涓嬫枃缁撴瀯 log_cxt 鐨勫悇涓垚鍛樺彉閲 log_cxt->syslog_ident = NULL; log_cxt->module_logging_configure = (char*)palloc0(sizeof(char) * BEMD_BITMAP_SIZE); log_cxt->msgbuf = (StringInfoData*)palloc0(sizeof(StringInfoData)); @@ -210,6 +207,7 @@ static void knl_u_log_init(knl_u_log_context* log_cxt) static void knl_u_optimizer_init(knl_u_optimizer_context* opt_cxt) { + // 鍒濆鍖栦紭鍖栧櫒涓婁笅鏂囩粨鏋 opt_cxt 鐨勫悇涓垚鍛樺彉閲 errno_t rc; opt_cxt->disable_dop_change = false; @@ -218,15 +216,15 @@ static void knl_u_optimizer_init(knl_u_optimizer_context* opt_cxt) opt_cxt->is_stream = true; opt_cxt->is_stream_support = true; opt_cxt->is_multiple_nodegroup_scenario = false; - /* Installation nodegroup. */ opt_cxt->different_nodegroup_count = 1; opt_cxt->is_randomfunc_shippable = true; opt_cxt->is_dngather_support = true; - opt_cxt->srvtype = 0; opt_cxt->qrw_inlist2join_optmode = QRW_INLIST2JOIN_CBO; opt_cxt->plan_current_seed = 0; opt_cxt->plan_prev_seed = 0; + + // 浣跨敤 memset_s 鍑芥暟鍒濆鍖 path_current_seed_factor 鏁扮粍 rc = memset_s(opt_cxt->path_current_seed_factor, PATH_SEED_FACTOR_LEN, 0, PATH_SEED_FACTOR_LEN); securec_check(rc, "\0", "\0"); @@ -246,13 +244,13 @@ static void knl_u_optimizer_init(knl_u_optimizer_context* opt_cxt) opt_cxt->ft_context = NULL; opt_cxt->is_under_append_plan = false; - /* Palloc memory. */ + // 涓轰竴浜涙垚鍛樺彉閲忓垎閰嶅唴瀛 opt_cxt->dynamic_smp_info = (DynamicSmpInfo*)palloc0(sizeof(DynamicSmpInfo)); opt_cxt->not_shipping_info = (ShippingInfo*)palloc0(sizeof(ShippingInfo)); opt_cxt->bottom_seq = (PartitionIdentifier*)palloc0(sizeof(PartitionIdentifier)); opt_cxt->top_seq = (PartitionIdentifier*)palloc0(sizeof(PartitionIdentifier)); - /* Init dynamic smp info. */ + // 鍒濆鍖栧姩鎬 SMP 淇℃伅 opt_cxt->dynamic_smp_info->num_of_dn_in_one_machine = UNKNOWN_NUM_OF_DN_IN_ONE_MACHINE; opt_cxt->dynamic_smp_info->num_of_cpu_in_one_machine = UNKNOWN_NUM_OF_CPU_IN_ONE_MACHINE; opt_cxt->dynamic_smp_info->num_of_cpu_for_one_dn = UNKNOWN_NUM_OF_CPU_FOR_ONE_DN; @@ -264,6 +262,7 @@ static void knl_u_optimizer_init(knl_u_optimizer_context* opt_cxt) static void knl_u_parser_init(knl_u_parser_context* parser_cxt) { + // 鍒濆鍖栬В鏋愬櫒涓婁笅鏂囩粨鏋 parser_cxt 鐨勫悇涓垚鍛樺彉閲 parser_cxt->eaten_begin = false; parser_cxt->eaten_declare = false; parser_cxt->has_dollar = false; @@ -285,6 +284,7 @@ static void knl_u_parser_init(knl_u_parser_context* parser_cxt) static void knl_u_advisor_init(knl_u_advisor_context* adv_cxt) { + // 鍒濆鍖栭【闂笂涓嬫枃缁撴瀯 adv_cxt 鐨勫悇涓垚鍛樺彉閲 adv_cxt->adviseMode = AM_NONE; adv_cxt->adviseType = AT_NONE; adv_cxt->adviseCostMode = ACM_NONE; @@ -302,19 +302,17 @@ static void knl_u_advisor_init(knl_u_advisor_context* adv_cxt) adv_cxt->endTime = 0; adv_cxt->maxMemory = 0; adv_cxt->maxsqlCount = 0; - adv_cxt->candicateTables = NULL; adv_cxt->candicateQueries = NIL; adv_cxt->candicateAdviseGroups = NIL; adv_cxt->result = NIL; - adv_cxt->SQLAdvisorContext = NULL; - adv_cxt->getPlanInfoFunc = NULL; } static void knl_u_stream_init(knl_u_stream_context* stream_cxt) { + // 鍒濆鍖栨祦涓婁笅鏂囩粨鏋 stream_cxt 鐨勫悇涓垚鍛樺彉閲 stream_cxt->global_obj = NULL; stream_cxt->producer_obj = NULL; stream_cxt->producer_dop = 1; @@ -331,6 +329,7 @@ static void knl_u_stream_init(knl_u_stream_context* stream_cxt) static void knl_u_sig_init(knl_u_sig_context* sig_cxt) { + // 鍒濆鍖栦俊鍙峰鐞嗕笂涓嬫枃缁撴瀯 sig_cxt 鐨勫悇涓垚鍛樺彉閲 sig_cxt->got_SIGHUP = 0; sig_cxt->got_pool_reload = 0; sig_cxt->cp_PoolReload = 0; @@ -338,6 +337,7 @@ static void knl_u_sig_init(knl_u_sig_context* sig_cxt) static void knl_u_SPI_init(knl_u_SPI_context* spi) { + // 鍒濆鍖朣PI锛圫erver Programming Interface锛変笂涓嬫枃缁撴瀯 spi 鐨勫悇涓垚鍛樺彉閲 spi->lastoid = InvalidOid; spi->_stack_depth = 0; spi->_connected = -1; @@ -357,6 +357,7 @@ static void knl_u_SPI_init(knl_u_SPI_context* spi) static void knl_u_trigger_init(knl_u_trigger_context* tri_cxt) { + // 鍒濆鍖栬Е鍙戝櫒涓婁笅鏂囩粨鏋 tri_cxt 鐨勫悇涓垚鍛樺彉閲 tri_cxt->ri_compare_cache = NULL; tri_cxt->ri_query_cache = NULL; @@ -368,6 +369,7 @@ static void knl_u_trigger_init(knl_u_trigger_context* tri_cxt) static void knl_u_wlm_init(knl_u_wlm_context* wlmctx) { + // 鍒濆鍖朩LM锛圵orkload Management锛変笂涓嬫枃缁撴瀯 wlmctx 鐨勫悇涓垚鍛樺彉閲 wlmctx->cgroup_state = CG_ORIGINAL; wlmctx->cgroup_stmt = GSCGROUP_NONE_STMT; wlmctx->cgroup_last_stmt = GSCGROUP_NONE_STMT; @@ -390,6 +392,7 @@ static void knl_u_wlm_init(knl_u_wlm_context* wlmctx) static void knl_u_utils_init(knl_u_utils_context* utils_cxt) { + // 鍒濆鍖 utils_cxt 鐨勫悇涓垚鍛樺彉閲 utils_cxt->suffix_char = 0; utils_cxt->suffix_collation = 0; utils_cxt->test_err_type = 0; @@ -407,6 +410,7 @@ static void knl_u_utils_init(knl_u_utils_context* utils_cxt) utils_cxt->GUC_check_errhint_string = NULL; utils_cxt->set_params_htab = NULL; utils_cxt->sync_guc_variables = NULL; + for (int strategy = 0; strategy < MAX_GUC_ATTR; strategy++) { utils_cxt->ConfigureNamesBool[strategy] = NULL; utils_cxt->ConfigureNamesInt[strategy] = NULL; @@ -415,6 +419,7 @@ static void knl_u_utils_init(knl_u_utils_context* utils_cxt) utils_cxt->ConfigureNamesString[strategy] = NULL; utils_cxt->ConfigureNamesEnum[strategy] = NULL; } + utils_cxt->guc_dirty = false; utils_cxt->reporting_enabled = false; utils_cxt->GUCNestLevel = 0; @@ -469,6 +474,7 @@ static void knl_u_utils_init(knl_u_utils_context* utils_cxt) } static void knl_u_security_init(knl_u_security_context* sec_cxt) { + // 鍒濆鍖栧畨鍏ㄤ笂涓嬫枃缁撴瀯 sec_cxt 鐨勫悇涓垚鍛樺彉閲 sec_cxt->last_roleid = InvalidOid; sec_cxt->last_roleid_is_super = false; sec_cxt->last_roleid_is_sysdba = false; @@ -482,177 +488,190 @@ static void knl_u_security_init(knl_u_security_context* sec_cxt) { static void knl_u_streaming_init(knl_u_streaming_context* streaming_cxt) { + // 鍒濆鍖栨祦澶嶅埗涓婁笅鏂囩粨鏋 streaming_cxt 鐨勫悇涓垚鍛樺彉閲 streaming_cxt->gather_session = false; streaming_cxt->streaming_ddl_session = false; } static void knl_u_mb_init(knl_u_mb_context* mb_cxt) { - mb_cxt->insertValuesBind_compatible_illegal_chars = false; - mb_cxt->ConvProcList = NIL; /* List of ConvProcInfo */ - mb_cxt->ToServerConvProc = NULL; - mb_cxt->ToClientConvProc = NULL; - mb_cxt->ClientEncoding = &pg_enc2name_tbl[PG_SQL_ASCII]; - mb_cxt->DatabaseEncoding = &pg_enc2name_tbl[PG_SQL_ASCII]; - mb_cxt->PlatformEncoding = NULL; - mb_cxt->backend_startup_complete = false; - mb_cxt->pending_client_encoding = PG_SQL_ASCII; + // 鍒濆鍖栧瀛楄妭缂栫爜涓婁笅鏂囩粨鏋 mb_cxt 鐨勫悇涓垚鍛樺彉閲 + mb_cxt->insertValuesBind_compatible_illegal_chars = false; // 鏄惁鍏佽鎻掑叆涓庣粦瀹氬弬鏁颁笉鍏煎鐨勯潪娉曞瓧绗 + mb_cxt->ConvProcList = NIL; /* ConvProcInfo搴忓垪 */ // 缂栫爜杞崲澶勭悊绋嬪簭鍒楄〃 + mb_cxt->ToServerConvProc = NULL; // 鐢ㄤ簬鏈嶅姟鍣ㄧ鐨勭紪鐮佽浆鎹㈠鐞嗙▼搴 + mb_cxt->ToClientConvProc = NULL; // 鐢ㄤ簬瀹㈡埛绔殑缂栫爜杞崲澶勭悊绋嬪簭 + mb_cxt->ClientEncoding = &pg_enc2name_tbl[PG_SQL_ASCII]; // 瀹㈡埛绔紪鐮 + mb_cxt->DatabaseEncoding = &pg_enc2name_tbl[PG_SQL_ASCII]; // 鏁版嵁搴撶紪鐮 + mb_cxt->PlatformEncoding = NULL; // 骞冲彴缂栫爜 + mb_cxt->backend_startup_complete = false; // 鍚庣鍚姩鏄惁瀹屾垚 + mb_cxt->pending_client_encoding = PG_SQL_ASCII; // 寰呭鐞嗙殑瀹㈡埛绔紪鐮 } static void knl_u_plancache_init(knl_u_plancache_context* pcache_cxt) { - pcache_cxt->first_saved_plan = NULL; - pcache_cxt->ungpc_saved_plan = NULL; - pcache_cxt->query_has_params = false; - pcache_cxt->prepared_queries = NULL; - pcache_cxt->lightproxy_objs = NULL; - pcache_cxt->stmt_lightproxy_htab = NULL; - pcache_cxt->unnamed_gpc_lp = NULL; - pcache_cxt->datanode_queries = NULL; - pcache_cxt->unnamed_stmt_psrc = NULL; - pcache_cxt->cur_stmt_psrc = NULL; - pcache_cxt->private_refcount = 0; + // 鍒濆鍖栬鍒掔紦瀛樹笂涓嬫枃缁撴瀯 pcache_cxt 鐨勫悇涓垚鍛樺彉閲 + pcache_cxt->first_saved_plan = NULL; // 绗竴涓凡淇濆瓨鐨勮鍒 + pcache_cxt->ungpc_saved_plan = NULL; // 鏈懡鍚嶇殑閫氱敤璁″垝缂撳瓨涓殑宸蹭繚瀛樿鍒 + pcache_cxt->query_has_params = false; // 鏌ヨ鏄惁鍖呭惈鍙傛暟 + pcache_cxt->prepared_queries = NULL; // 宸插噯澶囩殑鏌ヨ鍒楄〃 + pcache_cxt->lightproxy_objs = NULL; // 杞婚噺绾т唬鐞嗗璞″垪琛 + pcache_cxt->stmt_lightproxy_htab = NULL; // 璇彞杞婚噺绾т唬鐞嗗搱甯岃〃 + pcache_cxt->unnamed_gpc_lp = NULL; // 鏈懡鍚嶇殑閫氱敤璁″垝缂撳瓨涓殑杞婚噺绾т唬鐞 + pcache_cxt->datanode_queries = NULL; // 鏁版嵁鑺傜偣鏌ヨ鍒楄〃 + pcache_cxt->unnamed_stmt_psrc = NULL; // 鏈懡鍚嶈鍙ョ殑璁″垝婧 + pcache_cxt->cur_stmt_psrc = NULL; // 褰撳墠璇彞鐨勮鍒掓簮 + pcache_cxt->private_refcount = 0; // 绉佹湁寮曠敤璁℃暟 - pcache_cxt->cur_stmt_name = NULL; - pcache_cxt->gpc_in_ddl = false; - pcache_cxt->gpc_remote_msg = false; - pcache_cxt->gpc_first_send = true; - pcache_cxt->gpc_in_try_store = false; - pcache_cxt->gpc_in_batch = false; + pcache_cxt->cur_stmt_name = NULL; // 褰撳墠璇彞鐨勫悕绉 + pcache_cxt->gpc_in_ddl = false; // 鏄惁鍦―DL璇彞涓 + pcache_cxt->gpc_remote_msg = false; // 鏄惁涓鸿繙绋嬫秷鎭 + pcache_cxt->gpc_first_send = true; // 鏄惁棣栨鍙戦 + pcache_cxt->gpc_in_try_store = false; // 鏄惁鍦ㄥ皾璇曞瓨鍌 + pcache_cxt->gpc_in_batch = false; // 鏄惁鍦ㄦ壒澶勭悊涓 } static void knl_u_typecache_init(knl_u_typecache_context* tycache_cxt) { - tycache_cxt->TypeCacheHash = NULL; - tycache_cxt->RecordCacheHash = NULL; - tycache_cxt->RecordCacheArray = NULL; - tycache_cxt->RecordCacheArrayLen = 0; - tycache_cxt->NextRecordTypmod = 0; + // 鍒濆鍖栫被鍨嬬紦瀛樹笂涓嬫枃缁撴瀯 tycache_cxt 鐨勫悇涓垚鍛樺彉閲 + tycache_cxt->TypeCacheHash = NULL; // 绫诲瀷缂撳瓨鍝堝笇琛 + tycache_cxt->RecordCacheHash = NULL; // 璁板綍缂撳瓨鍝堝笇琛 + tycache_cxt->RecordCacheArray = NULL; // 璁板綍缂撳瓨鏁扮粍 + tycache_cxt->RecordCacheArrayLen = 0; // 璁板綍缂撳瓨鏁扮粍闀垮害 + tycache_cxt->NextRecordTypmod = 0; // 涓嬩竴涓褰曠被鍨嬩慨鏀规爣璇 } static void knl_u_tscache_init(knl_u_tscache_context* tscache_cxt) { - tscache_cxt->TSParserCacheHash = NULL; - tscache_cxt->lastUsedParser = NULL; - tscache_cxt->TSDictionaryCacheHash = NULL; - tscache_cxt->lastUsedDictionary = NULL; - tscache_cxt->TSConfigCacheHash = NULL; - tscache_cxt->lastUsedConfig = NULL; - tscache_cxt->TSCurrentConfigCache = InvalidOid; + // 鍒濆鍖栨枃鏈悳绱㈢紦瀛樹笂涓嬫枃缁撴瀯 tscache_cxt 鐨勫悇涓垚鍛樺彉閲 + tscache_cxt->TSParserCacheHash = NULL; // 鏂囨湰鎼滅储瑙f瀽鍣ㄧ紦瀛樺搱甯岃〃 + tscache_cxt->lastUsedParser = NULL; // 鏈鍚庝娇鐢ㄧ殑瑙f瀽鍣 + tscache_cxt->TSDictionaryCacheHash = NULL; // 鏂囨湰鎼滅储瀛楀吀缂撳瓨鍝堝笇琛 + tscache_cxt->lastUsedDictionary = NULL; // 鏈鍚庝娇鐢ㄧ殑瀛楀吀 + tscache_cxt->TSConfigCacheHash = NULL; // 鏂囨湰鎼滅储閰嶇疆缂撳瓨鍝堝笇琛 + tscache_cxt->lastUsedConfig = NULL; // 鏈鍚庝娇鐢ㄧ殑閰嶇疆 + tscache_cxt->TSCurrentConfigCache = InvalidOid; // 褰撳墠鏂囨湰鎼滅储閰嶇疆缂撳瓨 } static void knl_u_misc_init(knl_misc_context* misc_cxt) { - misc_cxt->Mode = InitProcessing; - misc_cxt->AuthenticatedUserId = InvalidOid; - misc_cxt->SessionUserId = InvalidOid; - misc_cxt->OuterUserId = InvalidOid; - misc_cxt->CurrentUserId = InvalidOid; - misc_cxt->CurrentUserName = NULL; - misc_cxt->current_logic_cluster = InvalidOid; - misc_cxt->current_nodegroup_mode = NG_UNKNOWN; - misc_cxt->nodegroup_callback_registered = false; - misc_cxt->Pseudo_CurrentUserId = NULL; - misc_cxt->AuthenticatedUserIsSuperuser = false; - misc_cxt->SessionUserIsSuperuser = false; - misc_cxt->SecurityRestrictionContext = 0; - misc_cxt->SetRoleIsActive = false; - misc_cxt->process_shared_preload_libraries_in_progress = false; - misc_cxt->authentication_finished = false; + // 鍒濆鍖栨潅椤逛笂涓嬫枃缁撴瀯 misc_cxt 鐨勫悇涓垚鍛樺彉閲 + misc_cxt->Mode = InitProcessing; // 澶勭悊妯″紡 + misc_cxt->AuthenticatedUserId = InvalidOid; // 璁よ瘉鐢ㄦ埛鐨凮ID + misc_cxt->SessionUserId = InvalidOid; // 浼氳瘽鐢ㄦ埛鐨凮ID + misc_cxt->OuterUserId = InvalidOid; // 澶栭儴鐢ㄦ埛鐨凮ID + misc_cxt->CurrentUserId = InvalidOid; // 褰撳墠鐢ㄦ埛鐨凮ID + misc_cxt->CurrentUserName = NULL; // 褰撳墠鐢ㄦ埛鐨勫悕绉 + misc_cxt->current_logic_cluster = InvalidOid; // 褰撳墠閫昏緫闆嗙兢鐨凮ID + misc_cxt->current_nodegroup_mode = NG_UNKNOWN; // 褰撳墠鑺傜偣缁勬ā寮 + misc_cxt->nodegroup_callback_registered = false; // 鑺傜偣缁勫洖璋冩槸鍚﹀凡娉ㄥ唽 + misc_cxt->Pseudo_CurrentUserId = NULL; // 浼鐨勫綋鍓嶇敤鎴稯ID + misc_cxt->AuthenticatedUserIsSuperuser = false; // 璁よ瘉鐢ㄦ埛鏄惁鏄秴绾х敤鎴 + misc_cxt->SessionUserIsSuperuser = false; // 浼氳瘽鐢ㄦ埛鏄惁鏄秴绾х敤鎴 + misc_cxt->SecurityRestrictionContext = 0; // 瀹夊叏绾︽潫涓婁笅鏂 + misc_cxt->SetRoleIsActive = false; // 鏄惁澶勪簬璁剧疆瑙掕壊鐘舵 + misc_cxt->process_shared_preload_libraries_in_progress = false; // 鍏变韩棰勫姞杞藉簱鏄惁姝e湪杩涜涓 + misc_cxt->authentication_finished = false; // 璁よ瘉鏄惁宸插畬鎴 } static void knl_u_postgres_init(knl_u_postgres_context* postgres_cxt) { - postgres_cxt->doing_extended_query_message = false; - postgres_cxt->ignore_till_sync = false; + // 鍒濆鍖 PostgreSQL 涓婁笅鏂囩粨鏋 postgres_cxt 鐨勫悇涓垚鍛樺彉閲 + postgres_cxt->doing_extended_query_message = false; // 鏄惁姝e湪澶勭悊鎵╁睍鏌ヨ娑堟伅 + postgres_cxt->ignore_till_sync = false; // 鏄惁蹇界暐鐩村埌鍚屾 } static void knl_u_proc_init(knl_u_proc_context* proc_cxt) { - proc_cxt->MyProcPort = NULL; - proc_cxt->MyRoleId = InvalidOid; - proc_cxt->MyDatabaseId = InvalidOid; - proc_cxt->MyDatabaseTableSpace = InvalidOid; - proc_cxt->DatabasePath = NULL; - proc_cxt->Isredisworker = false; - proc_cxt->IsInnerMaintenanceTools = false; - proc_cxt->clientIsGsrewind = false; - proc_cxt->clientIsGsredis = false; - proc_cxt->clientIsGsdump = false; - proc_cxt->clientIsGsCtl = false; - proc_cxt->clientIsGsroach = false; - proc_cxt->IsBinaryUpgrade = false; - proc_cxt->IsWLMWhiteList = false; - proc_cxt->sessionBackupState = SESSION_BACKUP_NONE; - proc_cxt->LabelFile = NULL; - proc_cxt->TblspcMapFile = NULL; - proc_cxt->registerAbortBackupHandlerdone = false; - proc_cxt->gsRewindAddCount = false; - proc_cxt->PassConnLimit = false; - proc_cxt->sessionBackupState = SESSION_BACKUP_NONE; - proc_cxt->registerExclusiveHandlerdone = false; + // 鍒濆鍖栬繘绋嬩笂涓嬫枃缁撴瀯 proc_cxt 鐨勫悇涓垚鍛樺彉閲 + proc_cxt->MyProcPort = NULL; // 褰撳墠杩涚▼鐨勭鍙d俊鎭 + proc_cxt->MyRoleId = InvalidOid; // 褰撳墠杩涚▼鐨勮鑹睴ID + proc_cxt->MyDatabaseId = InvalidOid; // 褰撳墠杩涚▼鐨勬暟鎹簱OID + proc_cxt->MyDatabaseTableSpace = InvalidOid; // 褰撳墠杩涚▼鐨勬暟鎹簱琛ㄧ┖闂碠ID + proc_cxt->DatabasePath = NULL; // 鏁版嵁搴撹矾寰 + proc_cxt->Isredisworker = false; // 鏄惁涓 Redis 宸ヤ綔杩涚▼ + proc_cxt->IsInnerMaintenanceTools = false; // 鏄惁涓哄唴閮ㄧ淮鎶ゅ伐鍏 + proc_cxt->clientIsGsrewind = false; // 瀹㈡埛绔槸鍚︽槸 gsrewind + proc_cxt->clientIsGsredis = false; // 瀹㈡埛绔槸鍚︽槸 gsredis + proc_cxt->clientIsGsdump = false; // 瀹㈡埛绔槸鍚︽槸 gsdump + proc_cxt->clientIsGsCtl = false; // 瀹㈡埛绔槸鍚︽槸 gs_ctl + proc_cxt->clientIsGsroach = false; // 瀹㈡埛绔槸鍚︽槸 gs_roach + proc_cxt->IsBinaryUpgrade = false; // 鏄惁涓轰簩杩涘埗鍗囩骇 + proc_cxt->IsWLMWhiteList = false; // 鏄惁鍦 WLM 鐧藉悕鍗曞唴 + proc_cxt->sessionBackupState = SESSION_BACKUP_NONE; // 浼氳瘽澶囦唤鐘舵 + proc_cxt->LabelFile = NULL; // 鏍囩鏂囦欢 + proc_cxt->TblspcMapFile = NULL; // 琛ㄧ┖闂存槧灏勬枃浠 + proc_cxt->registerAbortBackupHandlerdone = false; // 鏄惁宸叉敞鍐屽浠戒腑姝㈠鐞嗙▼搴 + proc_cxt->gsRewindAddCount = false; // gsrewind 娣诲姞璁℃暟 + proc_cxt->PassConnLimit = false; // 鏄惁缁曡繃杩炴帴闄愬埗 + proc_cxt->sessionBackupState = SESSION_BACKUP_NONE; // 浼氳瘽澶囦唤鐘舵 + proc_cxt->registerExclusiveHandlerdone = false; // 鏄惁宸叉敞鍐屾帓瀹冨鐞嗙▼搴 } static void knl_u_time_init(knl_u_time_context* time_cxt) { - time_cxt->DateStyle = USE_ISO_DATES; - time_cxt->DateOrder = DATEORDER_MDY; - time_cxt->HasCTZSet = false; - time_cxt->CTimeZone = 0; + // 鍒濆鍖栨椂闂翠笂涓嬫枃缁撴瀯 time_cxt 鐨勫悇涓垚鍛樺彉閲 + time_cxt->DateStyle = USE_ISO_DATES; // 鏃ユ湡鏍峰紡 + time_cxt->DateOrder = DATEORDER_MDY; // 鏃ユ湡椤哄簭 + time_cxt->HasCTZSet = false; // 鏄惁宸茶缃簡鏃跺尯 + time_cxt->CTimeZone = 0; // 褰撳墠鏃跺尯 - time_cxt->sz_timezone_tktbl = 0; - time_cxt->timezone_tktbl = NULL; + time_cxt->sz_timezone_tktbl = 0; // 鏃跺尯浠ょ墝琛ㄧ殑澶у皬 + time_cxt->timezone_tktbl = NULL; // 鏃跺尯浠ょ墝琛 errno_t rc; - rc = memset_s(time_cxt->datecache, sizeof(datetkn*) * MAXDATEFIELDS, 0, sizeof(datetkn*) * MAXDATEFIELDS); + rc = memset_s(time_cxt->datecache, sizeof(datetkn*) * MAXDATEFIELDS, 0, sizeof(datetkn*) * MAXDATEFIELDS); // 鏃ユ湡浠ょ墝缂撳瓨 securec_check(rc, "\0", "\0"); - rc = memset_s(time_cxt->deltacache, sizeof(datetkn*) * MAXDATEFIELDS, 0, sizeof(datetkn*) * MAXDATEFIELDS); + rc = memset_s(time_cxt->deltacache, sizeof(datetkn*) * MAXDATEFIELDS, 0, sizeof(datetkn*) * MAXDATEFIELDS); // 鏃堕棿闂撮殧浠ょ墝缂撳瓨 securec_check(rc, "\0", "\0"); - time_cxt->timezone_cache = NULL; + time_cxt->timezone_cache = NULL; // 鏃跺尯缂撳瓨 } -void knl_u_commands_init(knl_u_commands_context* cmd_cxt) +static void knl_u_proc_init(knl_u_proc_context* proc_cxt) { - cmd_cxt->TableSpaceUsageArray = NULL; - cmd_cxt->isUnderCreateForeignTable = false; - cmd_cxt->CurrentExtensionObject = InvalidOid; - cmd_cxt->PendingLibraryDeletes = NIL; - - cmd_cxt->seqtab = NULL; - cmd_cxt->last_used_seq = NULL; - - cmd_cxt->TypeCreateType = '\0'; - - cmd_cxt->label_provider_list = NIL; - cmd_cxt->bulkload_compatible_illegal_chars = false; - cmd_cxt->bulkload_copy_state = NULL; - cmd_cxt->dest_encoding_for_copytofile = -1; - cmd_cxt->need_transcoding_for_copytofile = false; - cmd_cxt->OBSParserContext = NULL; - cmd_cxt->on_commits = NIL; - cmd_cxt->topRelatationIsInMyTempSession = false; - cmd_cxt->bogus_marker = {(NodeTag)0}; + // 鍒濆鍖栬繘绋嬩笂涓嬫枃缁撴瀯 proc_cxt 鐨勫悇涓垚鍛樺彉閲 + proc_cxt->MyProcPort = NULL; // 褰撳墠杩涚▼鐨勭鍙d俊鎭 + proc_cxt->MyRoleId = InvalidOid; // 褰撳墠杩涚▼鐨勮鑹睴ID + proc_cxt->MyDatabaseId = InvalidOid; // 褰撳墠杩涚▼鐨勬暟鎹簱OID + proc_cxt->MyDatabaseTableSpace = InvalidOid; // 褰撳墠杩涚▼鐨勬暟鎹簱琛ㄧ┖闂碠ID + proc_cxt->DatabasePath = NULL; // 鏁版嵁搴撹矾寰 + proc_cxt->Isredisworker = false; // 鏄惁涓 Redis 宸ヤ綔杩涚▼ + proc_cxt->IsInnerMaintenanceTools = false; // 鏄惁涓哄唴閮ㄧ淮鎶ゅ伐鍏 + proc_cxt->clientIsGsrewind = false; // 瀹㈡埛绔槸鍚︽槸 gsrewind + proc_cxt->clientIsGsredis = false; // 瀹㈡埛绔槸鍚︽槸 gsredis + proc_cxt->clientIsGsdump = false; // 瀹㈡埛绔槸鍚︽槸 gsdump + proc_cxt->clientIsGsCtl = false; // 瀹㈡埛绔槸鍚︽槸 gs_ctl + proc_cxt->clientIsGsroach = false; // 瀹㈡埛绔槸鍚︽槸 gs_roach + proc_cxt->IsBinaryUpgrade = false; // 鏄惁涓轰簩杩涘埗鍗囩骇 + proc_cxt->IsWLMWhiteList = false; // 鏄惁鍦 WLM 鐧藉悕鍗曞唴 + proc_cxt->sessionBackupState = SESSION_BACKUP_NONE; // 浼氳瘽澶囦唤鐘舵 + proc_cxt->LabelFile = NULL; // 鏍囩鏂囦欢 + proc_cxt->TblspcMapFile = NULL; // 琛ㄧ┖闂存槧灏勬枃浠 + proc_cxt->registerAbortBackupHandlerdone = false; // 鏄惁宸叉敞鍐屽浠戒腑姝㈠鐞嗙▼搴 + proc_cxt->gsRewindAddCount = false; // gsrewind 娣诲姞璁℃暟 + proc_cxt->PassConnLimit = false; // 鏄惁缁曡繃杩炴帴闄愬埗 + proc_cxt->sessionBackupState = SESSION_BACKUP_NONE; // 浼氳瘽澶囦唤鐘舵 + proc_cxt->registerExclusiveHandlerdone = false; // 鏄惁宸叉敞鍐屾帓瀹冨鐞嗙▼搴 } -static void knl_u_contrib_init(knl_u_contrib_context* contrib_cxt) +static void knl_u_time_init(knl_u_time_context* time_cxt) { + // 鍒濆鍖栨椂闂翠笂涓嬫枃缁撴瀯 time_cxt 鐨勫悇涓垚鍛樺彉閲 + time_cxt->DateStyle = USE_ISO_DATES; // 鏃ユ湡鏍峰紡 + time_cxt->DateOrder = DATEORDER_MDY; // 鏃ユ湡椤哄簭 + time_cxt->HasCTZSet = false; // 鏄惁宸茶缃簡鏃跺尯 + time_cxt->CTimeZone = 0; // 褰撳墠鏃跺尯 + + time_cxt->sz_timezone_tktbl = 0; // 鏃跺尯浠ょ墝琛ㄧ殑澶у皬 + time_cxt->timezone_tktbl = NULL; // 鏃跺尯浠ょ墝琛 errno_t rc; - - contrib_cxt->cursor_number = 0; - contrib_cxt->current_context_id = 0; - contrib_cxt->file_format = DFS_INVALID; - contrib_cxt->file_number = 0; - -#define MAX_SLOTS 50 /* supports 50 files */ - contrib_cxt->slots = (FileSlot*)palloc0(sizeof(FileSlot) * MAX_SLOTS); - contrib_cxt->slotid = 0; - /* mark the default value as not revoke set_maxline_size */ - const int default_max_line_size = 1024; - contrib_cxt->max_linesize = default_max_line_size; - contrib_cxt->cur_directory = (char*)palloc0(sizeof(char) * MAXPGPATH); - rc = memset_s(contrib_cxt->cur_directory, MAXPGPATH, 0, MAXPGPATH); + rc = memset_s(time_cxt->datecache, sizeof(datetkn*) * MAXDATEFIELDS, 0, sizeof(datetkn*) * MAXDATEFIELDS); // 鏃ユ湡浠ょ墝缂撳瓨 securec_check(rc, "\0", "\0"); + + rc = memset_s(time_cxt->deltacache, sizeof(datetkn*) * MAXDATEFIELDS, 0, sizeof(datetkn*) * MAXDATEFIELDS); // 鏃堕棿闂撮殧浠ょ墝缂撳瓨 + securec_check(rc, "\0", "\0"); + + time_cxt->timezone_cache = NULL; // 鏃跺尯缂撳瓨 } static void knl_u_upgrade_init(knl_u_upgrade_context* upg_cxt) @@ -791,255 +810,250 @@ static void knl_u_upgrade_init(knl_u_upgrade_context* upg_cxt) static void knl_u_plpgsql_init(knl_u_plpgsql_context* plsql_cxt) { - plsql_cxt->inited = false; - plsql_cxt->plpgsql_HashTable = NULL; - plsql_cxt->plpgsql_pkg_HashTable = NULL; - plsql_cxt->plpgsql_dlist_objects = NULL; - plsql_cxt->plpgsqlpkg_dlist_objects = NULL; - plsql_cxt->compile_status = NONE_STATUS; - plsql_cxt->curr_compile_context = NULL; - plsql_cxt->compile_context_list = NIL; - plsql_cxt->plpgsql_IndexErrorVariable = 0; - plsql_cxt->shared_simple_eval_resowner = NULL; - plsql_cxt->simple_eval_estate = NULL; - plsql_cxt->simple_econtext_stack = NULL; - plsql_cxt->context_array = NIL; - plsql_cxt->plugin_ptr = NULL; - plsql_cxt->rendezvousHash = NULL; - plsql_cxt->debug_proc_htbl = NULL; - plsql_cxt->debug_client = NULL; - plsql_cxt->has_step_into = false; - plsql_cxt->cur_debug_server = NULL; - plsql_cxt->dbe_output_buffer_limit = DEFAULT_DBE_BUFFER_LIMIT; - plsql_cxt->is_delete_function = false; - plsql_cxt->have_error = false; - plsql_cxt->client_info = NULL; - pthread_mutex_init(&plsql_cxt->client_info_lock, NULL); - plsql_cxt->sess_cxt_htab = NULL; - plsql_cxt->have_error = false; - plsql_cxt->stp_savepoint_cnt = 0; - plsql_cxt->nextStackEntryId = 0; - plsql_cxt->spi_xact_context = NULL; - plsql_cxt->package_as_line = 0; - plsql_cxt->procedure_start_line = 0; - plsql_cxt->insertError = false; - plsql_cxt->errorList = NULL; - plsql_cxt->plpgsql_yylloc = 0; - plsql_cxt->rawParsePackageFunction = false; - plsql_cxt->isCreateFunction = false; - plsql_cxt->need_pkg_dependencies = false; - plsql_cxt->pkg_dependencies = NIL; - plsql_cxt->func_tableof_index = NIL; - plsql_cxt->pass_func_tupdesc = NULL; - plsql_cxt->portal_depth = 0; - plsql_cxt->auto_parent_session_pkgs = NULL; - plsql_cxt->not_found_parent_session_pkgs = false; - plsql_cxt->storedPortals = NIL; - plsql_cxt->portalContext = NIL; - plsql_cxt->call_after_auto = false; - plsql_cxt->parent_session_id = 0; - plsql_cxt->parent_thread_id = 0; - plsql_cxt->parent_context = NULL; - plsql_cxt->is_package_instantiation = false; - plsql_cxt->cur_exception_cxt = NULL; - plsql_cxt->pragma_autonomous = false; - plsql_cxt->ActiveLobToastOid = InvalidOid; - plsql_cxt->is_insert_gs_source = false; + plsql_cxt->inited = false; // 鏄惁宸插垵濮嬪寲 + plsql_cxt->plpgsql_HashTable = NULL; // PL/pgSQL 鍑芥暟鍝堝笇琛 + plsql_cxt->plpgsql_pkg_HashTable = NULL; // PL/pgSQL 鍖呭搱甯岃〃 + plsql_cxt->plpgsql_dlist_objects = NULL; // PL/pgSQL 鍑芥暟鍙岄摼琛ㄥ璞 + plsql_cxt->plpgsqlpkg_dlist_objects = NULL; // PL/pgSQL 鍖呭弻閾捐〃瀵硅薄 + plsql_cxt->compile_status = NONE_STATUS; // 缂栬瘧鐘舵 + plsql_cxt->curr_compile_context = NULL; // 褰撳墠缂栬瘧涓婁笅鏂 + plsql_cxt->compile_context_list = NIL; // 缂栬瘧涓婁笅鏂囧垪琛 + plsql_cxt->plpgsql_IndexErrorVariable = 0; // PL/pgSQL 閿欒鍙橀噺绱㈠紩 + plsql_cxt->shared_simple_eval_resowner = NULL; // 鍏变韩鐨勭畝鍗曡瘎浼拌祫婧愭嫢鏈夎 + plsql_cxt->simple_eval_estate = NULL; // 绠鍗曡瘎浼版墽琛岀姸鎬 + plsql_cxt->simple_econtext_stack = NULL; // 绠鍗曡瘎浼版墽琛屼笂涓嬫枃鍫嗘爤 + plsql_cxt->context_array = NIL; // 涓婁笅鏂囨暟缁 + plsql_cxt->plugin_ptr = NULL; // 鎻掍欢鎸囬拡 + plsql_cxt->rendezvousHash = NULL; // 浼氬悎鍝堝笇琛 + plsql_cxt->debug_proc_htbl = NULL; // 璋冭瘯杩囩▼鍝堝笇琛 + plsql_cxt->debug_client = NULL; // 璋冭瘯瀹㈡埛绔 + plsql_cxt->has_step_into = false; // 鏄惁鏈夋杩 + plsql_cxt->cur_debug_server = NULL; // 褰撳墠璋冭瘯鏈嶅姟鍣 + plsql_cxt->dbe_output_buffer_limit = DEFAULT_DBE_BUFFER_LIMIT; // 璋冭瘯杈撳嚭缂撳啿鍖洪檺鍒 + plsql_cxt->is_delete_function = false; // 鏄惁鏄垹闄ゅ嚱鏁 + plsql_cxt->have_error = false; // 鏄惁鏈夐敊璇 + plsql_cxt->client_info = NULL; // 瀹㈡埛绔俊鎭 + pthread_mutex_init(&plsql_cxt->client_info_lock, NULL); // 瀹㈡埛绔俊鎭簰鏂ラ攣鍒濆鍖 + plsql_cxt->sess_cxt_htab = NULL; // 浼氳瘽涓婁笅鏂囧搱甯岃〃 + plsql_cxt->have_error = false; // 鏄惁鏈夐敊璇 + plsql_cxt->stp_savepoint_cnt = 0; // STP 淇濆瓨鐐硅鏁 + plsql_cxt->nextStackEntryId = 0; // 涓嬩竴涓爢鏍堟潯鐩甀D + plsql_cxt->spi_xact_context = NULL; // SPI 浜嬪姟涓婁笅鏂 + plsql_cxt->package_as_line = 0; // 鍖呬綔涓鸿 + plsql_cxt->procedure_start_line = 0; // 杩囩▼寮濮嬭 + plsql_cxt->insertError = false; // 鏄惁鎻掑叆閿欒 + plsql_cxt->errorList = NULL; // 閿欒鍒楄〃 + plsql_cxt->plpgsql_yylloc = 0; // PL/pgSQL 璇嶆硶浣嶇疆 + plsql_cxt->rawParsePackageFunction = false; // 鏄惁鍘熷瑙f瀽鍖呭嚱鏁 + plsql_cxt->isCreateFunction = false; // 鏄惁鏄垱寤哄嚱鏁 + plsql_cxt->need_pkg_dependencies = false; // 鏄惁闇瑕佸寘渚濊禆椤 + plsql_cxt->pkg_dependencies = NIL; // 鍖呬緷璧栭」鍒楄〃 + plsql_cxt->func_tableof_index = NIL; // 鍑芥暟 TABLEOF 绱㈠紩鍒楄〃 + plsql_cxt->pass_func_tupdesc = NULL; // 浼犻掑嚱鏁板厓缁勬弿杩 + plsql_cxt->portal_depth = 0; // 闂ㄦ埛娣卞害 + plsql_cxt->auto_parent_session_pkgs = NULL; // 鑷姩鐖朵細璇濆寘 + plsql_cxt->not_found_parent_session_pkgs = false; // 鏈壘鍒扮埗浼氳瘽鍖 + plsql_cxt->storedPortals = NIL; // 瀛樺偍鐨勯棬鎴峰垪琛 + plsql_cxt->portalContext = NIL; // 闂ㄦ埛涓婁笅鏂囧垪琛 + plsql_cxt->call_after_auto = false; // 鑷姩鎵ц鍚庤皟鐢 + plsql_cxt->parent_session_id = 0; // 鐖朵細璇滻D + plsql_cxt->parent_thread_id = 0; // 鐖剁嚎绋婭D + plsql_cxt->parent_context = NULL; // 鐖朵笂涓嬫枃 + plsql_cxt->is_package_instantiation = false; // 鏄惁鏄寘瀹炰緥鍖 + plsql_cxt->cur_exception_cxt = NULL; // 褰撳墠寮傚父涓婁笅鏂 + plsql_cxt->pragma_autonomous = false; // PRAGMA AUTONOMOUS + plsql_cxt->ActiveLobToastOid = InvalidOid; // 娲诲姩 LOB TOAST OID + plsql_cxt->is_insert_gs_source = false; // 鏄惁鎻掑叆 GS 婧 } static void knl_u_stat_init(knl_u_stat_context* stat_cxt) { - Size size = 0; - errno_t rc = EOK; + Size size = 0; // 鐢ㄤ簬瀛樺偍鍐呭瓨澶у皬鐨勫彉閲 + errno_t rc = EOK; // 鐢ㄤ簬瀛樺偍閿欒鐮佺殑鍙橀噺 - stat_cxt->pgstat_stat_filename = NULL; - stat_cxt->pgstat_stat_tmpname = NULL; - stat_cxt->pgStatDBHash = NULL; - stat_cxt->pgStatTabList = NULL; + stat_cxt->pgstat_stat_filename = NULL; // 缁熻淇℃伅鏂囦欢鍚 + stat_cxt->pgstat_stat_tmpname = NULL; // 缁熻淇℃伅涓存椂鏂囦欢鍚 + stat_cxt->pgStatDBHash = NULL; // 鏁版嵁搴撶粺璁′俊鎭搱甯岃〃 + stat_cxt->pgStatTabList = NULL; // 缁熻琛ㄥ垪琛 - stat_cxt->BgWriterStats = (PgStat_MsgBgWriter*)palloc0(sizeof(PgStat_MsgBgWriter)); - stat_cxt->globalStats = (PgStat_GlobalStats*)palloc0(sizeof(PgStat_GlobalStats)); - stat_cxt->pgStatTabHash = NULL; - stat_cxt->pgStatTabHashContext = NULL; - stat_cxt->pgStatFunctions = NULL; - stat_cxt->have_function_stats = false; - stat_cxt->pgStatXactStack = NULL; - stat_cxt->pgStatXactCommit = 0; - stat_cxt->pgStatXactRollback = 0; - stat_cxt->pgStatBlockReadTime = 0; - stat_cxt->pgStatBlockWriteTime = 0; - stat_cxt->localBackendStatusTable = NULL; - stat_cxt->localNumBackends = 0; - stat_cxt->analyzeCheckHash = NULL; - stat_cxt->pgStatRunningInCollector = false; + stat_cxt->BgWriterStats = (PgStat_MsgBgWriter*)palloc0(sizeof(PgStat_MsgBgWriter)); // 鍚庡彴鍐欒繘绋嬬粺璁′俊鎭 + stat_cxt->globalStats = (PgStat_GlobalStats*)palloc0(sizeof(PgStat_GlobalStats)); // 鍏ㄥ眬缁熻淇℃伅 + stat_cxt->pgStatTabHash = NULL; // 缁熻琛ㄥ搱甯岃〃 + stat_cxt->pgStatTabHashContext = NULL; // 缁熻琛ㄥ搱甯岃〃涓婁笅鏂 + stat_cxt->pgStatFunctions = NULL; // 缁熻鍑芥暟淇℃伅 + stat_cxt->have_function_stats = false; // 鏄惁鏈夊嚱鏁扮粺璁′俊鎭 + stat_cxt->pgStatXactStack = NULL; // 浜嬪姟缁熻鍫嗘爤 + stat_cxt->pgStatXactCommit = 0; // 鎻愪氦浜嬪姟璁℃暟 + stat_cxt->pgStatXactRollback = 0; // 鍥炴粴浜嬪姟璁℃暟 + stat_cxt->pgStatBlockReadTime = 0; // 鍧楄鍙栨椂闂 + stat_cxt->pgStatBlockWriteTime = 0; // 鍧楀啓鍏ユ椂闂 + stat_cxt->localBackendStatusTable = NULL; // 鏈湴鍚庡彴杩涚▼鐘舵佽〃 + stat_cxt->localNumBackends = 0; // 鏈湴鍚庡彴杩涚▼鏁 + stat_cxt->analyzeCheckHash = NULL; // 鍒嗘瀽妫鏌ュ搱甯岃〃 + stat_cxt->pgStatRunningInCollector = false; // 缁熻淇℃伅鏄惁鍦ㄦ敹闆嗗櫒涓繍琛 - stat_cxt->last_report = 0; - stat_cxt->isTopLevelPlSql = true; + stat_cxt->last_report = 0; // 涓婃鎶ュ憡鏃堕棿 + stat_cxt->isTopLevelPlSql = true; // 鏄惁椤跺眰 PL/SQL - stat_cxt->pgStatCollectThdStatusContext = NULL; - stat_cxt->pgStatLocalContext = NULL; + stat_cxt->pgStatCollectThdStatusContext = NULL; // 缁熻淇℃伅鏀堕泦绾跨▼鐘舵佷笂涓嬫枃 + stat_cxt->pgStatLocalContext = NULL; // 缁熻淇℃伅鏈湴涓婁笅鏂 - size = sizeof(NumericValue) * TOTAL_OS_RUN_INFO_TYPES; - stat_cxt->osStatDataArray = (NumericValue*)palloc0(size); + size = sizeof(NumericValue) * TOTAL_OS_RUN_INFO_TYPES; // 鎬荤殑鎿嶄綔绯荤粺杩愯淇℃伅绫诲瀷 + stat_cxt->osStatDataArray = (NumericValue*)palloc0(size); // 鎿嶄綔绯荤粺缁熻淇℃伅鏁扮粍 - size = sizeof(OSRunInfoDesc) * TOTAL_OS_RUN_INFO_TYPES; - stat_cxt->osStatDescArray = (OSRunInfoDesc*)palloc0(size); - rc = memcpy_s(stat_cxt->osStatDescArray, size, osStatDescArrayOrg, size); + size = sizeof(OSRunInfoDesc) * TOTAL_OS_RUN_INFO_TYPES; // 鎿嶄綔绯荤粺杩愯淇℃伅鎻忚堪鐨勫ぇ灏 + stat_cxt->osStatDescArray = (OSRunInfoDesc*)palloc0(size); // 鎿嶄綔绯荤粺缁熻淇℃伅鎻忚堪鏁扮粍 + rc = memcpy_s(stat_cxt->osStatDescArray, size, osStatDescArrayOrg, size); // 澶嶅埗鎿嶄綔绯荤粺缁熻淇℃伅鎻忚堪 securec_check(rc, "\0", "\0"); - size = sizeof(int64) * TOTAL_TIME_INFO_TYPES; - stat_cxt->localTimeInfoArray = (int64*)palloc0(size); - stat_cxt->localNetInfo = (uint64*)palloc0(sizeof(uint64) * TOTAL_NET_INFO_TYPES); + size = sizeof(int64) * TOTAL_TIME_INFO_TYPES; // 鎬荤殑鏃堕棿淇℃伅绫诲瀷 + stat_cxt->localTimeInfoArray = (int64*)palloc0(size); // 鏈湴鏃堕棿淇℃伅鏁扮粍 + stat_cxt->localNetInfo = (uint64*)palloc0(sizeof(uint64) * TOTAL_NET_INFO_TYPES); // 鏈湴缃戠粶淇℃伅鏁扮粍 - stat_cxt->trackedMemChunks = 0; - stat_cxt->trackedBytes = 0; - stat_cxt->hotkeySessContext = NULL; - stat_cxt->hotkeyCandidates = NULL; + stat_cxt->trackedMemChunks = 0; // 璺熻釜鐨勫唴瀛樺潡鏁 + stat_cxt->trackedBytes = 0; // 璺熻釜鐨勫瓧鑺傛暟 + stat_cxt->hotkeySessContext = NULL; // 鐑敭浼氳瘽涓婁笅鏂 + stat_cxt->hotkeyCandidates = NULL; // 鐑敭鍊欓夐」 } static void knl_u_storage_init(knl_u_storage_context* storage_cxt) { - storage_cxt->target_prefetch_pages = 0; - storage_cxt->session_timeout_active = false; - storage_cxt->session_fin_time = 0; + storage_cxt->target_prefetch_pages = 0; // 鐩爣棰勫彇椤垫暟 + storage_cxt->session_timeout_active = false; // 浼氳瘽瓒呮椂鏄惁婵娲 + storage_cxt->session_fin_time = 0; // 浼氳瘽缁撴潫鏃堕棿 /* var in fd.cpp */ - storage_cxt->nfile = 0; - storage_cxt->have_xact_temporary_files = false; - storage_cxt->temporary_files_size = 0; - storage_cxt->numAllocatedDescs = 0; - storage_cxt->maxAllocatedDescs = 0; - storage_cxt->allocatedDescs = NULL; - storage_cxt->tempFileCounter = 0; - storage_cxt->tempTableSpaces = NULL; - storage_cxt->numTempTableSpaces = -1; - storage_cxt->nextTempTableSpace = 0; - storage_cxt->AsyncSubmitIOCount = 0; - storage_cxt->VfdCache = NULL; - storage_cxt->SizeVfdCache = 0; + storage_cxt->nfile = 0; // 鏂囦欢鏁伴噺 + storage_cxt->have_xact_temporary_files = false; // 鏄惁鏈変簨鍔′复鏃舵枃浠 + storage_cxt->temporary_files_size = 0; // 涓存椂鏂囦欢澶у皬 + storage_cxt->numAllocatedDescs = 0; // 宸插垎閰嶆弿杩扮鏁 + storage_cxt->maxAllocatedDescs = 0; // 鏈澶у凡鍒嗛厤鎻忚堪绗︽暟 + storage_cxt->allocatedDescs = NULL; // 宸插垎閰嶆弿杩扮鏁扮粍 + storage_cxt->tempFileCounter = 0; // 涓存椂鏂囦欢璁℃暟鍣 + storage_cxt->tempTableSpaces = NULL; // 涓存椂琛ㄧ┖闂 + storage_cxt->numTempTableSpaces = -1; // 涓存椂琛ㄧ┖闂存暟閲 + storage_cxt->nextTempTableSpace = 0; // 涓嬩竴涓复鏃惰〃绌洪棿 + storage_cxt->AsyncSubmitIOCount = 0; // 寮傛鎻愪氦IO璁℃暟 + storage_cxt->VfdCache = NULL; // 铏氭嫙鏂囦欢鎻忚堪绗︾紦瀛 + storage_cxt->SizeVfdCache = 0; // 铏氭嫙鏂囦欢鎻忚堪绗︾紦瀛樺ぇ灏 - /* var in smgr.cpp */ - storage_cxt->SMgrRelationHash = NULL; - storage_cxt->unowned_reln = {{NULL, NULL}}; + storage_cxt->SMgrRelationHash = NULL; // 绠$悊鍣ㄥ叧绯诲搱甯岃〃 + storage_cxt->unowned_reln = {{NULL, NULL}}; // 鏈嫢鏈夌殑鍏崇郴 - /* var in md.cpp */ - storage_cxt->MdCxt = NULL; + storage_cxt->MdCxt = NULL; // 鍏冩暟鎹笂涓嬫枃 - /* var in knl_uundofile.cpp */ - storage_cxt->UndoFileCxt = NULL; + storage_cxt->UndoFileCxt = NULL; // 鎾ら攢鏂囦欢涓婁笅鏂 - /* var in sync.cpp */ - storage_cxt->pendingUnlinks = NIL; - storage_cxt->pendingOpsCxt = NULL; - storage_cxt->sync_cycle_ctr = 0; - storage_cxt->checkpoint_cycle_ctr = 0; - storage_cxt->pendingOps = NULL; + storage_cxt->pendingUnlinks = NIL; // 寰呭垹闄ょ殑閾炬帴 + storage_cxt->pendingOpsCxt = NULL; // 寰呭鐞嗘搷浣滀笂涓嬫枃 + storage_cxt->sync_cycle_ctr = 0; // 鍚屾鍛ㄦ湡璁℃暟鍣 + storage_cxt->checkpoint_cycle_ctr = 0; // 妫鏌ョ偣鍛ㄦ湡璁℃暟鍣 + storage_cxt->pendingOps = NULL; // 寰呭鐞嗘搷浣 - storage_cxt->nextLocalTransactionId = InvalidTransactionId; + storage_cxt->nextLocalTransactionId = InvalidTransactionId; // 涓嬩竴涓湰鍦颁簨鍔D for (int i = 0; i < MAX_LOCKMETHOD; i++) { - storage_cxt->holdSessionLock[i] = false; + storage_cxt->holdSessionLock[i] = false; // 浼氳瘽閿佹爣蹇楁暟缁 } - storage_cxt->twoPhaseCommitInProgress = false; - storage_cxt->dumpHashbucketIdNum = 0; - storage_cxt->dumpHashbucketIds = NULL; + storage_cxt->twoPhaseCommitInProgress = false; // 鏄惁姝e湪杩涜涓ら樁娈垫彁浜 + storage_cxt->dumpHashbucketIdNum = 0; // 鍝堝笇妗禝D鏁伴噺 + storage_cxt->dumpHashbucketIds = NULL; // 鍝堝笇妗禝D鏁扮粍 - /* session local buffer */ - storage_cxt->NLocBuffer = 0; /* until buffers are initialized */ - storage_cxt->LocalBufferDescriptors = NULL; - storage_cxt->LocalBufferBlockPointers = NULL; - storage_cxt->LocalRefCount = NULL; - storage_cxt->nextFreeLocalBuf = 0; - storage_cxt->LocalBufHash = NULL; - storage_cxt->cur_block = NULL; - storage_cxt->next_buf_in_block = 0; - storage_cxt->num_bufs_in_block = 0; - storage_cxt->total_bufs_allocated = 0; - storage_cxt->LocalBufferContext = NULL; + storage_cxt->NLocBuffer = 0; // 鏈湴缂撳啿鍖烘暟閲忥紝鐩村埌缂撳啿鍖哄垵濮嬪寲瀹屾垚 + storage_cxt->LocalBufferDescriptors = NULL; // 鏈湴缂撳啿鍖烘弿杩扮 + storage_cxt->LocalBufferBlockPointers = NULL; // 鏈湴缂撳啿鍖哄潡鎸囬拡 + storage_cxt->LocalRefCount = NULL; // 鏈湴寮曠敤璁℃暟 + storage_cxt->nextFreeLocalBuf = 0; // 涓嬩竴涓彲鐢ㄧ殑鏈湴缂撳啿鍖 + storage_cxt->LocalBufHash = NULL; // 鏈湴缂撳啿鍖哄搱甯岃〃 + storage_cxt->cur_block = NULL; // 褰撳墠鍧 + storage_cxt->next_buf_in_block = 0; // 涓嬩竴涓潡涓殑缂撳啿鍖 + storage_cxt->num_bufs_in_block = 0; // 鍧椾腑鐨勭紦鍐插尯鏁 + storage_cxt->total_bufs_allocated = 0; // 宸插垎閰嶇殑缂撳啿鍖烘绘暟 + storage_cxt->LocalBufferContext = NULL; // 鏈湴缂撳啿鍖轰笂涓嬫枃 } static void knl_u_libpq_init(knl_u_libpq_context* libpq_cxt) { - Assert(libpq_cxt != NULL); - libpq_cxt->cookies = NULL; - libpq_cxt->cookies_size = 0; - libpq_cxt->fscxt = NULL; - libpq_cxt->server_key = (GS_UCHAR*)palloc0((CIPHER_LEN + 1) * sizeof(GS_UCHAR)); - libpq_cxt->ident_lines = NIL; - libpq_cxt->ident_line_nums = NIL; - libpq_cxt->ident_context = NULL; - libpq_cxt->IsConnFromCmAgent = false; - libpq_cxt->HasErrorAccurs = false; + Assert(libpq_cxt != NULL); // 鏂█锛氱‘淇 libpq_cxt 涓嶄负绌 + libpq_cxt->cookies = NULL; // Cookie 鏁版嵁 + libpq_cxt->cookies_size = 0; // Cookie 鏁版嵁澶у皬 + libpq_cxt->fscxt = NULL; // 鏈娇鐢ㄧ殑瀛楁涓婁笅鏂 + libpq_cxt->server_key = (GS_UCHAR*)palloc0((CIPHER_LEN + 1) * sizeof(GS_UCHAR)); // 鏈嶅姟鍣ㄥ瘑閽 + libpq_cxt->ident_lines = NIL; // 韬唤楠岃瘉琛 + libpq_cxt->ident_line_nums = NIL; // 韬唤楠岃瘉琛屽彿 + libpq_cxt->ident_context = NULL; // 韬唤楠岃瘉涓婁笅鏂 + libpq_cxt->IsConnFromCmAgent = false; // 杩炴帴鏄惁鏉ヨ嚜 CM Agent + libpq_cxt->HasErrorAccurs = false; // 鏄惁鍙戠敓閿欒 #ifdef USE_SSL - libpq_cxt->ssl_loaded_verify_locations = false; - libpq_cxt->ssl_initialized = false; - libpq_cxt->SSL_server_context = NULL; + libpq_cxt->ssl_loaded_verify_locations = false; // SSL 鍔犺浇楠岃瘉浣嶇疆 + libpq_cxt->ssl_initialized = false; // SSL 鏄惁宸插垵濮嬪寲 + libpq_cxt->SSL_server_context = NULL; // SSL 鏈嶅姟鍣ㄤ笂涓嬫枃 #endif } -#define BUCKET_MAP_SIZE 32 +#define BUCKET_MAP_SIZE 32 // Bucket Map 澶у皬 static void knl_u_relcache_init(knl_u_relcache_context* relcache_cxt) { - relcache_cxt->RelationIdCache = NULL; - relcache_cxt->criticalRelcachesBuilt = false; - relcache_cxt->criticalSharedRelcachesBuilt = false; - relcache_cxt->relcacheInvalsReceived = 0L; - relcache_cxt->initFileRelationIds = NIL; - relcache_cxt->RelCacheNeedEOXActWork = false; - relcache_cxt->OpClassCache = NULL; - relcache_cxt->pgclassdesc = NULL; - relcache_cxt->pgindexdesc = NULL; - relcache_cxt->g_bucketmap_cache = NIL; - relcache_cxt->max_bucket_map_size = BUCKET_MAP_SIZE; + relcache_cxt->RelationIdCache = NULL; // 鍏崇郴 ID 缂撳瓨 + relcache_cxt->criticalRelcachesBuilt = false; // 閲嶈鍏崇郴缂撳瓨鏄惁宸叉瀯寤 + relcache_cxt->criticalSharedRelcachesBuilt = false; // 閲嶈鍏变韩鍏崇郴缂撳瓨鏄惁宸叉瀯寤 + relcache_cxt->relcacheInvalsReceived = 0L; // 鏀跺埌鐨勫叧绯荤紦瀛樺け鏁堟秷鎭暟 + relcache_cxt->initFileRelationIds = NIL; // 鍒濆鍖栨枃浠跺叧绯 ID + relcache_cxt->RelCacheNeedEOXActWork = false; // 鍏崇郴缂撳瓨鏄惁闇瑕佹墽琛岀粨鏉熶簨鍔″伐浣 + relcache_cxt->OpClassCache = NULL; // 杩愮畻绗︾被缂撳瓨 + relcache_cxt->pgclassdesc = NULL; // pg_class 鎻忚堪绗 + relcache_cxt->pgindexdesc = NULL; // pg_index 鎻忚堪绗 + relcache_cxt->g_bucketmap_cache = NIL; // 鍏ㄥ眬 Bucket Map 缂撳瓨 + relcache_cxt->max_bucket_map_size = BUCKET_MAP_SIZE; // 鏈澶 Bucket Map 澶у皬 - relcache_cxt->EOXactTupleDescArray = NULL; - relcache_cxt->NextEOXactTupleDescNum = 0; - relcache_cxt->EOXactTupleDescArrayLen = 0; + relcache_cxt->EOXactTupleDescArray = NULL; // 缁撴潫浜嬪姟鍏冪粍鎻忚堪绗︽暟缁 + relcache_cxt->NextEOXactTupleDescNum = 0; // 涓嬩竴涓粨鏉熶簨鍔″厓缁勬弿杩扮缂栧彿 + relcache_cxt->EOXactTupleDescArrayLen = 0; // 缁撴潫浜嬪姟鍏冪粍鎻忚堪绗︽暟缁勯暱搴 } static void knl_u_unique_sql_init(knl_u_unique_sql_context* unique_sql_cxt) { - Assert(unique_sql_cxt != NULL); + Assert(unique_sql_cxt != NULL); // 鏂█锛氱‘淇 unique_sql_cxt 涓嶄负绌 - unique_sql_cxt->unique_sql_id = 0; - unique_sql_cxt->unique_sql_user_id = InvalidOid; - unique_sql_cxt->unique_sql_cn_id = InvalidOid; - unique_sql_cxt->unique_sql_start_time = 0; - unique_sql_cxt->unique_sql_returned_rows_counter = 0; - unique_sql_cxt->unique_sql_soft_parse = 0; - unique_sql_cxt->unique_sql_hard_parse = 0; - unique_sql_cxt->last_stat_counter = (PgStat_TableCounts*)palloc0(sizeof(PgStat_TableCounts)); - unique_sql_cxt->current_table_counter = (PgStat_TableCounts*)palloc0(sizeof(PgStat_TableCounts)); - unique_sql_cxt->curr_single_unique_sql = NULL; - unique_sql_cxt->is_multi_unique_sql = false; - unique_sql_cxt->multi_sql_offset = 0; - unique_sql_cxt->is_top_unique_sql = false; - unique_sql_cxt->need_update_calls = true; - unique_sql_cxt->skipUniqueSQLCount = 0; - unique_sql_cxt->unique_sql_sort_instr = (unique_sql_sorthash_instr*)palloc0(sizeof(unique_sql_sorthash_instr)); - unique_sql_cxt->unique_sql_hash_instr = (unique_sql_sorthash_instr*)palloc0(sizeof(unique_sql_sorthash_instr)); - unique_sql_cxt->unique_sql_sort_instr->has_sorthash = false; - unique_sql_cxt->unique_sql_hash_instr->has_sorthash = false; - unique_sql_cxt->portal_nesting_level = 0; + unique_sql_cxt->unique_sql_id = 0; // 鍞竴 SQL 鏍囪瘑 + unique_sql_cxt->unique_sql_user_id = InvalidOid; // 鐢ㄦ埛 ID + unique_sql_cxt->unique_sql_cn_id = InvalidOid; // 杩炴帴 ID + unique_sql_cxt->unique_sql_start_time = 0; // SQL 寮濮嬫椂闂 + unique_sql_cxt->unique_sql_returned_rows_counter = 0; // 杩斿洖鐨勮鏁拌鏁板櫒 + unique_sql_cxt->unique_sql_soft_parse = 0; // 杞В鏋愯鏁 + unique_sql_cxt->unique_sql_hard_parse = 0; // 纭В鏋愯鏁 + unique_sql_cxt->last_stat_counter = (PgStat_TableCounts*)palloc0(sizeof(PgStat_TableCounts)); // 涓婃缁熻璁℃暟 + unique_sql_cxt->current_table_counter = (PgStat_TableCounts*)palloc0(sizeof(PgStat_TableCounts)); // 褰撳墠琛ㄨ鏁 + unique_sql_cxt->curr_single_unique_sql = NULL; // 褰撳墠鍗曚釜鍞竴 SQL + unique_sql_cxt->is_multi_unique_sql = false; // 鏄惁涓哄涓敮涓 SQL + unique_sql_cxt->multi_sql_offset = 0; // 澶氫釜鍞竴 SQL 鐨勫亸绉婚噺 + unique_sql_cxt->is_top_unique_sql = false; // 鏄惁涓洪《绾у敮涓 SQL + unique_sql_cxt->need_update_calls = true; // 鏄惁闇瑕佹洿鏂拌皟鐢ㄦ鏁 + unique_sql_cxt->skipUniqueSQLCount = 0; // 璺宠繃鐨勫敮涓 SQL 璁℃暟 + unique_sql_cxt->unique_sql_sort_instr = (unique_sql_sorthash_instr*)palloc0(sizeof(unique_sql_sorthash_instr)); // 鍞竴 SQL 鎺掑簭鎸囦护 + unique_sql_cxt->unique_sql_hash_instr = (unique_sql_sorthash_instr*)palloc0(sizeof(unique_sql_sorthash_instr)); // 鍞竴 SQL 鍝堝笇鎸囦护 + unique_sql_cxt->unique_sql_sort_instr->has_sorthash = false; // 鎺掑簭鎸囦护鏄惁瀛樺湪 + unique_sql_cxt->unique_sql_hash_instr->has_sorthash = false; // 鍝堝笇鎸囦护鏄惁瀛樺湪 + unique_sql_cxt->portal_nesting_level = 0; // Portal 宓屽绾у埆 #ifndef ENABLE_MULTIPLE_NODES - unique_sql_cxt->unique_sql_text = NULL; + unique_sql_cxt->unique_sql_text = NULL; // 鍞竴 SQL 鏂囨湰 #endif } static void knl_u_percentile_init(knl_u_percentile_context* percentile_cxt) { - Assert(percentile_cxt != NULL); - percentile_cxt->LocalsqlRT = NULL; - percentile_cxt->LocalCounter = 0; + Assert(percentile_cxt != NULL); // 鏂█锛氱‘淇 percentile_cxt 涓嶄负绌 + percentile_cxt->LocalsqlRT = NULL; // 鏈湴 SQL 鍝嶅簲鏃堕棿 + percentile_cxt->LocalCounter = 0; // 鏈湴璁℃暟鍣 } static void knl_u_slow_query_init(knl_u_slow_query_context* slow_query_cxt) { - Assert(slow_query_cxt != NULL); - slow_query_cxt->slow_query.localTimeInfoArray = (int64*)palloc0(sizeof(int64) * TOTAL_TIME_INFO_TYPES); - slow_query_cxt->slow_query.n_returned_rows = 0; - slow_query_cxt->slow_query.current_table_counter = (PgStat_TableCounts*)palloc0(sizeof(PgStat_TableCounts)); - slow_query_cxt->slow_query.unique_sql_id = 0; + Assert(slow_query_cxt != NULL); // 鏂█锛氱‘淇 slow_query_cxt 涓嶄负绌 + slow_query_cxt->slow_query.localTimeInfoArray = (int64*)palloc0(sizeof(int64) * TOTAL_TIME_INFO_TYPES); // 鏈湴鏃堕棿淇℃伅鏁扮粍 + slow_query_cxt->slow_query.n_returned_rows = 0; // 杩斿洖鐨勮鏁 + slow_query_cxt->slow_query.current_table_counter = (PgStat_TableCounts*)palloc0(sizeof(PgStat_TableCounts)); // 褰撳墠琛ㄨ鏁 + slow_query_cxt->slow_query.unique_sql_id = 0; // 鍞竴 SQL 鏍囪瘑 } static void knl_u_trace_context_init(knl_u_trace_context* trace_cxt) @@ -1061,177 +1075,176 @@ static void knl_u_user_login_init(knl_u_user_login_context* user_login_cxt) static void knl_u_statement_init(knl_u_statement_context* statement_cxt) { - Assert(statement_cxt != NULL); + Assert(statement_cxt != NULL); // 鏂█锛氱‘淇 statement_cxt 涓嶄负绌 - statement_cxt->db_name = NULL; - statement_cxt->user_name = NULL; - statement_cxt->client_addr = NULL; - statement_cxt->client_port = INSTR_STMT_NULL_PORT; - statement_cxt->session_id = 0; + statement_cxt->db_name = NULL; // 鏁版嵁搴撳悕绉 + statement_cxt->user_name = NULL; // 鐢ㄦ埛鍚嶇О + statement_cxt->client_addr = NULL; // 瀹㈡埛绔湴鍧 + statement_cxt->client_port = INSTR_STMT_NULL_PORT; // 瀹㈡埛绔鍙 + statement_cxt->session_id = 0; // 浼氳瘽 ID - statement_cxt->curStatementMetrics = NULL; - statement_cxt->allocatedCxtCnt = 0; + statement_cxt->curStatementMetrics = NULL; // 褰撳墠璇彞搴﹂噺淇℃伅 + statement_cxt->allocatedCxtCnt = 0; // 宸插垎閰嶇殑涓婁笅鏂囪鏁 - statement_cxt->free_count = 0; - statement_cxt->toFreeStatementList = NULL; - statement_cxt->suspend_count = 0; - statement_cxt->suspendStatementList = NULL; - statement_cxt->executer_run_level = 0; + statement_cxt->free_count = 0; // 绌洪棽璁℃暟 + statement_cxt->toFreeStatementList = NULL; // 寰呴噴鏀捐鍙ュ垪琛 + statement_cxt->suspend_count = 0; // 鏆傚仠璁℃暟 + statement_cxt->suspendStatementList = NULL; // 鏆傚仠璇彞鍒楄〃 + statement_cxt->executer_run_level = 0; // 鎵ц鍣ㄨ繍琛岀骇鍒 - (void)syscalllockInit(&statement_cxt->list_protect); - statement_cxt->stmt_stat_cxt = NULL; + (void)syscalllockInit(&statement_cxt->list_protect); // 鍒濆鍖栭攣 + statement_cxt->stmt_stat_cxt = NULL; // 璇彞缁熻涓婁笅鏂 } void knl_u_relmap_init(knl_u_relmap_context* relmap_cxt) { - relmap_cxt->shared_map = (RelMapFile*)palloc0(sizeof(RelMapFile)); - relmap_cxt->local_map = (RelMapFile*)palloc0(sizeof(RelMapFile)); - relmap_cxt->active_shared_updates = (RelMapFile*)palloc0(sizeof(RelMapFile)); - relmap_cxt->active_local_updates = (RelMapFile*)palloc0(sizeof(RelMapFile)); - relmap_cxt->pending_shared_updates = (RelMapFile*)palloc0(sizeof(RelMapFile)); - relmap_cxt->pending_local_updates = (RelMapFile*)palloc0(sizeof(RelMapFile)); - relmap_cxt->RelfilenodeMapHash = NULL; - relmap_cxt->UHeapRelfilenodeMapHash = NULL; + relmap_cxt->shared_map = (RelMapFile*)palloc0(sizeof(RelMapFile)); // 鍏变韩鏄犲皠鏂囦欢 + relmap_cxt->local_map = (RelMapFile*)palloc0(sizeof(RelMapFile)); // 鏈湴鏄犲皠鏂囦欢 + relmap_cxt->active_shared_updates = (RelMapFile*)palloc0(sizeof(RelMapFile)); // 娲诲姩鐨勫叡浜洿鏂 + relmap_cxt->active_local_updates = (RelMapFile*)palloc0(sizeof(RelMapFile)); // 娲诲姩鐨勬湰鍦版洿鏂 + relmap_cxt->pending_shared_updates = (RelMapFile*)palloc0(sizeof(RelMapFile)); // 寰呭鐞嗙殑鍏变韩鏇存柊 + relmap_cxt->pending_local_updates = (RelMapFile*)palloc0(sizeof(RelMapFile)); // 寰呭鐞嗙殑鏈湴鏇存柊 + relmap_cxt->RelfilenodeMapHash = NULL; // 鍏崇郴鏂囦欢鑺傜偣鏄犲皠鍝堝笇琛 + relmap_cxt->UHeapRelfilenodeMapHash = NULL; // UHeap 鍏崇郴鏂囦欢鑺傜偣鏄犲皠鍝堝笇琛 } void knl_u_inval_init(knl_u_inval_context* inval_cxt) { - inval_cxt->DeepthInAcceptInvalidationMessage = 0; - inval_cxt->transInvalInfo = NULL; - inval_cxt->SharedInvalidMessagesArray = NULL; - inval_cxt->numSharedInvalidMessagesArray = 0; - inval_cxt->maxSharedInvalidMessagesArray = 0; - inval_cxt->syscache_callback_list = (SYSCACHECALLBACK*)palloc0(sizeof(SYSCACHECALLBACK) * MAX_SYSCACHE_CALLBACKS); - inval_cxt->syscache_callback_count = 0; - inval_cxt->relcache_callback_list = (RELCACHECALLBACK*)palloc0(sizeof(RELCACHECALLBACK) * MAX_RELCACHE_CALLBACKS); - inval_cxt->relcache_callback_count = 0; - inval_cxt->partcache_callback_list = - (PARTCACHECALLBACK*)palloc0(sizeof(PARTCACHECALLBACK) * MAX_PARTCACHE_CALLBACKS); - inval_cxt->partcache_callback_count = 0; - inval_cxt->SIMCounter = 0; - inval_cxt->catchupInterruptPending = 0; - inval_cxt->messages = (SharedInvalidationMessage*)palloc0(MAXINVALMSGS * sizeof(SharedInvalidationMessage)); - inval_cxt->nextmsg = 0; - inval_cxt->nummsgs = 0; + inval_cxt->DeepthInAcceptInvalidationMessage = 0; // 鎺ユ敹澶辨晥娑堟伅娣卞害 + inval_cxt->transInvalInfo = NULL; // 浜嬪姟澶辨晥淇℃伅 + inval_cxt->SharedInvalidMessagesArray = NULL; // 鍏变韩澶辨晥娑堟伅鏁扮粍 + inval_cxt->numSharedInvalidMessagesArray = 0; // 鍏变韩澶辨晥娑堟伅鏁扮粍涓殑鏁伴噺 + inval_cxt->maxSharedInvalidMessagesArray = 0; // 鍏变韩澶辨晥娑堟伅鏁扮粍鐨勬渶澶уぇ灏 + inval_cxt->syscache_callback_list = (SYSCACHECALLBACK*)palloc0(sizeof(SYSCACHECALLBACK) * MAX_SYSCACHE_CALLBACKS); // 绯荤粺缂撳瓨鍥炶皟鍒楄〃 + inval_cxt->syscache_callback_count = 0; // 绯荤粺缂撳瓨鍥炶皟璁℃暟 + inval_cxt->relcache_callback_list = (RELCACHECALLBACK*)palloc0(sizeof(RELCACHECALLBACK) * MAX_RELCACHE_CALLBACKS); // 鍏崇郴缂撳瓨鍥炶皟鍒楄〃 + inval_cxt->relcache_callback_count = 0; // 鍏崇郴缂撳瓨鍥炶皟璁℃暟 + inval_cxt->partcache_callback_list = (PARTCACHECALLBACK*)palloc0(sizeof(PARTCACHECALLBACK) * MAX_PARTCACHE_CALLBACKS); // 鍒嗗尯缂撳瓨鍥炶皟鍒楄〃 + inval_cxt->partcache_callback_count = 0; // 鍒嗗尯缂撳瓨鍥炶皟璁℃暟 + inval_cxt->SIMCounter = 0; // SIM 璁℃暟鍣 + inval_cxt->catchupInterruptPending = 0; // 寰呭鐞嗙殑 catchup 涓柇 + inval_cxt->messages = (SharedInvalidationMessage*)palloc0(MAXINVALMSGS * sizeof(SharedInvalidationMessage)); // 澶辨晥娑堟伅鏁扮粍 + inval_cxt->nextmsg = 0; // 涓嬩竴涓秷鎭綅缃 + inval_cxt->nummsgs = 0; // 娑堟伅鏁伴噺 } static void knl_u_catalog_init(knl_u_catalog_context* catalog_cxt) { - catalog_cxt->nulls[0] = false; - catalog_cxt->nulls[1] = false; - catalog_cxt->nulls[2] = false; - catalog_cxt->nulls[3] = false; - catalog_cxt->route = (PartitionIdentifier*)palloc0(sizeof(PartitionIdentifier)); - catalog_cxt->Parse_sql_language = false; - catalog_cxt->pendingDeletes = NULL; - catalog_cxt->ColMainFileNodes = NULL; + catalog_cxt->nulls[0] = false; // 绗竴涓 null 鏍囧織 + catalog_cxt->nulls[1] = false; // 绗簩涓 null 鏍囧織 + catalog_cxt->nulls[2] = false; // 绗笁涓 null 鏍囧織 + catalog_cxt->nulls[3] = false; // 绗洓涓 null 鏍囧織 + catalog_cxt->route = (PartitionIdentifier*)palloc0(sizeof(PartitionIdentifier)); // 鍒嗗尯鏍囪瘑绗 + catalog_cxt->Parse_sql_language = false; // 鏄惁瑙f瀽 SQL 璇█ + catalog_cxt->pendingDeletes = NULL; // 寰呭鐞嗙殑鍒犻櫎鎿嶄綔 + catalog_cxt->ColMainFileNodes = NULL; // 鍒楀瓨涓绘枃浠惰妭鐐 #define ColMainFileNodesDefNum 16 - catalog_cxt->ColMainFileNodesMaxNum = ColMainFileNodesDefNum; - catalog_cxt->ColMainFileNodesCurNum = 0; - catalog_cxt->pendingDfsDeletes = NIL; - catalog_cxt->delete_conn = NULL; - catalog_cxt->vf_store_root = NULL; - catalog_cxt->currentlyReindexedHeap = InvalidOid; - catalog_cxt->currentlyReindexedIndex = InvalidOid; - catalog_cxt->pendingReindexedIndexes = NIL; - catalog_cxt->activeSearchPath = NIL; - catalog_cxt->activeCreationNamespace = InvalidOid; - catalog_cxt->activeTempCreationPending = false; - catalog_cxt->baseSearchPath = NIL; - catalog_cxt->baseCreationNamespace = InvalidOid; - catalog_cxt->baseTempCreationPending = false; - catalog_cxt->namespaceUser = InvalidOid; - catalog_cxt->baseSearchPathValid = true; - catalog_cxt->overrideStack = NIL; - catalog_cxt->overrideStackValid = true; - catalog_cxt->setCurCreateSchema = false; - catalog_cxt->curCreateSchema = NULL; - catalog_cxt->myTempNamespaceOld = InvalidOid; - catalog_cxt->myTempNamespace = InvalidOid; - catalog_cxt->myTempToastNamespace = InvalidOid; - catalog_cxt->deleteTempOnQuiting = false; - catalog_cxt->myTempNamespaceSubID = InvalidSubTransactionId; - catalog_cxt->redistribution_cancelable = false; + catalog_cxt->ColMainFileNodesMaxNum = ColMainFileNodesDefNum; // 鍒楀瓨涓绘枃浠惰妭鐐圭殑鏈澶ф暟閲 + catalog_cxt->ColMainFileNodesCurNum = 0; // 褰撳墠鍒楀瓨涓绘枃浠惰妭鐐规暟閲 + catalog_cxt->pendingDfsDeletes = NIL; // 寰呭鐞嗙殑 DFS 鍒犻櫎鎿嶄綔 + catalog_cxt->delete_conn = NULL; // 鍒犻櫎杩炴帴 + catalog_cxt->vf_store_root = NULL; // VF 瀛樺偍鏍圭洰褰 + catalog_cxt->currentlyReindexedHeap = InvalidOid; // 褰撳墠姝e湪閲嶅缓鐨勫爢琛 OID + catalog_cxt->currentlyReindexedIndex = InvalidOid; // 褰撳墠姝e湪閲嶅缓鐨勭储寮 OID + catalog_cxt->pendingReindexedIndexes = NIL; // 寰呴噸寤虹殑绱㈠紩鍒楄〃 + catalog_cxt->activeSearchPath = NIL; // 娲昏穬鐨勬悳绱㈣矾寰 + catalog_cxt->activeCreationNamespace = InvalidOid; // 娲昏穬鐨勫垱寤哄懡鍚嶇┖闂 OID + catalog_cxt->activeTempCreationPending = false; // 娲昏穬鐨勪复鏃跺垱寤虹瓑寰呬腑 + catalog_cxt->baseSearchPath = NIL; // 鍩虹鐨勬悳绱㈣矾寰 + catalog_cxt->baseCreationNamespace = InvalidOid; // 鍩虹鐨勫垱寤哄懡鍚嶇┖闂 OID + catalog_cxt->baseTempCreationPending = false; // 鍩虹鐨勪复鏃跺垱寤虹瓑寰呬腑 + catalog_cxt->namespaceUser = InvalidOid; // 鍛藉悕绌洪棿鐢ㄦ埛 OID + catalog_cxt->baseSearchPathValid = true; // 鍩虹鎼滅储璺緞鏄惁鏈夋晥 + catalog_cxt->overrideStack = NIL; // 瑕嗙洊鏍 + catalog_cxt->overrideStackValid = true; // 瑕嗙洊鏍堟槸鍚︽湁鏁 + catalog_cxt->setCurCreateSchema = false; // 鏄惁璁剧疆褰撳墠鍒涘缓妯″紡 + catalog_cxt->curCreateSchema = NULL; // 褰撳墠鍒涘缓妯″紡 + catalog_cxt->myTempNamespaceOld = InvalidOid; // 鏃х殑涓存椂鍛藉悕绌洪棿 OID + catalog_cxt->myTempNamespace = InvalidOid; // 褰撳墠鐨勪复鏃跺懡鍚嶇┖闂 OID + catalog_cxt->myTempToastNamespace = InvalidOid; // 褰撳墠鐨勪复鏃 Toast 鍛藉悕绌洪棿 OID + catalog_cxt->deleteTempOnQuiting = false; // 閫鍑烘椂鍒犻櫎涓存椂鏁版嵁 + catalog_cxt->myTempNamespaceSubID = InvalidSubTransactionId; // 褰撳墠鐨勪复鏃跺懡鍚嶇┖闂村瓙浜嬪姟 ID + catalog_cxt->redistribution_cancelable = false; // 鏄惁鍙彇娑堥噸鍒嗗彂 } static void knl_u_cache_init(knl_u_cache_context* cache_cxt) { - cache_cxt->num_res = 0; - cache_cxt->re_array = (cached_re_str*)palloc0(sizeof(cached_re_str) * MAX_CACHED_RES); + cache_cxt->num_res = 0; // 璧勬簮鏁伴噺 + cache_cxt->re_array = (cached_re_str*)palloc0(sizeof(cached_re_str) * MAX_CACHED_RES); // 璧勬簮鏁扮粍 - cache_cxt->cached_privs_role = InvalidOid; - cache_cxt->cached_privs_roles = NIL; - cache_cxt->cached_member_role = InvalidOid; - cache_cxt->cached_membership_roles = NIL; + cache_cxt->cached_privs_role = InvalidOid; // 缂撳瓨鐨勬潈闄愯鑹 OID + cache_cxt->cached_privs_roles = NIL; // 缂撳瓨鐨勬潈闄愯鑹插垪琛 + cache_cxt->cached_member_role = InvalidOid; // 缂撳瓨鐨勬垚鍛樿鑹 OID + cache_cxt->cached_membership_roles = NIL; // 缂撳瓨鐨勬垚鍛樿鑹插垪琛 - cache_cxt->plan_getrulebyoid = NULL; - cache_cxt->plan_getviewrule = NULL; + cache_cxt->plan_getrulebyoid = NULL; // 鑾峰彇瑙勫垯 OID 鐨勮鍒 + cache_cxt->plan_getviewrule = NULL; // 鑾峰彇瑙嗗浘瑙勫垯鐨勮鍒 - cache_cxt->att_opt_cache_hash = NULL; - cache_cxt->cache_header = NULL; + cache_cxt->att_opt_cache_hash = NULL; // 灞炴ч夐」缂撳瓨鍝堝笇琛 + cache_cxt->cache_header = NULL; // 缂撳瓨澶 - cache_cxt->TableSpaceCacheHash = NULL; + cache_cxt->TableSpaceCacheHash = NULL; // 琛ㄧ┖闂寸紦瀛樺搱甯岃〃 - cache_cxt->PartitionIdCache = NULL; - cache_cxt->BucketIdCache = NULL; - cache_cxt->PartCacheNeedEOXActWork = false; - cache_cxt->bucket_cache_need_eoxact_work = false; - cache_cxt->dn_hash_table = NULL; + cache_cxt->PartitionIdCache = NULL; // 鍒嗗尯 ID 缂撳瓨 + cache_cxt->BucketIdCache = NULL; // 妗 ID 缂撳瓨 + cache_cxt->PartCacheNeedEOXActWork = false; // 鍒嗗尯缂撳瓨闇瑕佺粨鏉熷瓙浜嬪姟宸ヤ綔 + cache_cxt->bucket_cache_need_eoxact_work = false; // 妗剁紦瀛橀渶瑕佺粨鏉熷瓙浜嬪姟宸ヤ綔 + cache_cxt->dn_hash_table = NULL; // 鏁版嵁鑺傜偣鍝堝笇琛 } static void knl_u_syscache_init(knl_u_syscache_context* syscache_cxt) { - syscache_cxt->SysCache = (CatCache**)palloc0(sizeof(CatCache*) * SysCacheSize); - syscache_cxt->SysCacheRelationOid = (Oid*)palloc0(sizeof(Oid) * SysCacheSize); - syscache_cxt->CacheInitialized = false; + syscache_cxt->SysCache = (CatCache**)palloc0(sizeof(CatCache*) * SysCacheSize); // 绯荤粺缂撳瓨鏁扮粍 + syscache_cxt->SysCacheRelationOid = (Oid*)palloc0(sizeof(Oid) * SysCacheSize); // 绯荤粺缂撳瓨鍏崇郴 OID 鏁扮粍 + syscache_cxt->CacheInitialized = false; // 缂撳瓨鏄惁宸插垵濮嬪寲 } static void knl_u_pgxc_init(knl_u_pgxc_context* pgxc_cxt) { #ifdef ENABLE_MULTIPLE_NODES - pgxc_cxt->NumDataNodes = 0; - pgxc_cxt->NumTotalDataNodes = 0; + pgxc_cxt->NumDataNodes = 0; // 鏁版嵁鑺傜偣鏁伴噺 + pgxc_cxt->NumTotalDataNodes = 0; // 鎬绘暟鎹妭鐐规暟閲 #else - pgxc_cxt->NumDataNodes = 1; + pgxc_cxt->NumDataNodes = 1; // 鏁版嵁鑺傜偣鏁伴噺锛堝崟鑺傜偣妯″紡锛 #endif - pgxc_cxt->NumCoords = 0; - pgxc_cxt->NumStandbyDataNodes = 0; - pgxc_cxt->datanode_count = 0; - pgxc_cxt->coord_count = 0; - pgxc_cxt->dn_matrics = NULL; - pgxc_cxt->dn_handles = NULL; - pgxc_cxt->co_handles = NULL; + pgxc_cxt->NumCoords = 0; // 鍗忚皟鑺傜偣鏁伴噺 + pgxc_cxt->NumStandbyDataNodes = 0; // 澶囨満鏁版嵁鑺傜偣鏁伴噺 + pgxc_cxt->datanode_count = 0; // 鏁版嵁鑺傜偣璁℃暟 + pgxc_cxt->coord_count = 0; // 鍗忚皟鑺傜偣璁℃暟 + pgxc_cxt->dn_matrics = NULL; // 鏁版嵁鑺傜偣鐭╅樀 + pgxc_cxt->dn_handles = NULL; // 鏁版嵁鑺傜偣杩炴帴鍙ユ焺鏁扮粍 + pgxc_cxt->co_handles = NULL; // 鍗忚皟鑺傜偣杩炴帴鍙ユ焺鏁扮粍 #ifdef ENABLE_MULTIPLE_NODES - pgxc_cxt->PGXCNodeId = -1; + pgxc_cxt->PGXCNodeId = -1; // PGXC 鑺傜偣 ID #else - pgxc_cxt->PGXCNodeId = 0; + pgxc_cxt->PGXCNodeId = 0; // PGXC 鑺傜偣 ID锛堝崟鑺傜偣妯″紡锛 #endif - pgxc_cxt->PGXCNodeIdentifier = 0; + pgxc_cxt->PGXCNodeIdentifier = 0; // PGXC 鑺傜偣鏍囪瘑绗 - pgxc_cxt->remoteXactState = (RemoteXactState*)palloc0(sizeof(RemoteXactState)); - pgxc_cxt->XactWriteNodes = NIL; - pgxc_cxt->XactReadNodes = NIL; - pgxc_cxt->preparedNodes = NULL; + pgxc_cxt->remoteXactState = (RemoteXactState*)palloc0(sizeof(RemoteXactState)); // 杩滅▼浜嬪姟鐘舵 + pgxc_cxt->XactWriteNodes = NIL; // 浜嬪姟鍐欒妭鐐瑰垪琛 + pgxc_cxt->XactReadNodes = NIL; // 浜嬪姟璇昏妭鐐瑰垪琛 + pgxc_cxt->preparedNodes = NULL; // 鍑嗗鑺傜偣鍒楄〃 - pgxc_cxt->last_reported_send_errno = 0; - pgxc_cxt->PoolerResendParams = false; - pgxc_cxt->PoolerConnectionInfo = (PGXCNodeConnectionInfo*)palloc0(sizeof(PGXCNodeConnectionInfo)); - pgxc_cxt->poolHandle = NULL; - pgxc_cxt->ConsistencyPointUpdating = false; - pgxc_cxt->disasterReadArray = NULL; - pgxc_cxt->DisasterReadArrayInit = false; + pgxc_cxt->last_reported_send_errno = 0; // 鏈鍚庢姤鍛婄殑鍙戦侀敊璇彿 + pgxc_cxt->PoolerResendParams = false; // 鏄惁閲嶆柊鍙戦佸弬鏁扮粰杩炴帴姹 + pgxc_cxt->PoolerConnectionInfo = (PGXCNodeConnectionInfo*)palloc0(sizeof(PGXCNodeConnectionInfo)); // 杩炴帴姹犺繛鎺ヤ俊鎭 + pgxc_cxt->poolHandle = NULL; // 杩炴帴姹犲彞鏌 + pgxc_cxt->ConsistencyPointUpdating = false; // 涓鑷存х偣鏇存柊涓 + pgxc_cxt->disasterReadArray = NULL; // 鐏惧璇绘暟缁 + pgxc_cxt->DisasterReadArrayInit = false; // 鐏惧璇绘暟缁勬槸鍚﹀垵濮嬪寲 - pgxc_cxt->connection_cache = NIL; - pgxc_cxt->connection_cache_handle = NIL; + pgxc_cxt->connection_cache = NIL; // 杩炴帴缂撳瓨鍒楄〃 + pgxc_cxt->connection_cache_handle = NIL; // 杩炴帴缂撳瓨鍙ユ焺鍒楄〃 - pgxc_cxt->is_gc_fdw = false; - pgxc_cxt->is_gc_fdw_analyze = false; - pgxc_cxt->gc_fdw_current_idx = 0; - pgxc_cxt->gc_fdw_max_idx = 0; - pgxc_cxt->gc_fdw_run_version = GCFDW_VERSION; - pgxc_cxt->gc_fdw_snapshot = NULL; - pgxc_cxt->primary_data_node = InvalidOid; - pgxc_cxt->num_preferred_data_nodes = 0; + pgxc_cxt->is_gc_fdw = false; // 鏄惁鏄 GC_FDW + pgxc_cxt->is_gc_fdw_analyze = false; // 鏄惁鏄 GC_FDW 鐨勫垎鏋愭搷浣 + pgxc_cxt->gc_fdw_current_idx = 0; // GC_FDW 褰撳墠绱㈠紩 + pgxc_cxt->gc_fdw_max_idx = 0; // GC_FDW 鏈澶х储寮 + pgxc_cxt->gc_fdw_run_version = GCFDW_VERSION; // GC_FDW 杩愯鐗堟湰 + pgxc_cxt->gc_fdw_snapshot = NULL; // GC_FDW 蹇収 + pgxc_cxt->primary_data_node = InvalidOid; // 涓绘暟鎹妭鐐 OID + pgxc_cxt->num_preferred_data_nodes = 0; // 棣栭夋暟鎹妭鐐规暟閲 } static void knl_u_erand_init(knl_u_erand_context* rand_cxt) @@ -1243,10 +1256,10 @@ static void knl_u_erand_init(knl_u_erand_context* rand_cxt) seed = t_thrd.postmaster_cxt.random_start_time.tv_usec ^ ((time.tv_usec << 16) | ((time.tv_usec >> 16) & 0xffff)); } while (seed == 0); - - rand_cxt->rand48_seed[0] = RAND48_SEED_0; - rand_cxt->rand48_seed[1] = (unsigned short)seed; - rand_cxt->rand48_seed[2] = (unsigned short)(seed >> 16); + + rand_cxt->rand48_seed[0] = RAND48_SEED_0; // 绉嶅瓙 0 + rand_cxt->rand48_seed[1] = (unsigned short)seed; // 绉嶅瓙 1 + rand_cxt->rand48_seed[2] = (unsigned short)(seed >> 16); // 绉嶅瓙 2 } static void knl_u_regex_init(knl_u_regex_context* regex_cxt) @@ -1256,31 +1269,31 @@ static void knl_u_regex_init(knl_u_regex_context* regex_cxt) static void knl_u_xact_init(knl_u_xact_context* xact_cxt) { - xact_cxt->Xact_callbacks = NULL; - xact_cxt->SubXact_callbacks = NULL; + xact_cxt->Xact_callbacks = NULL; // 浜嬪姟鍥炶皟鍑芥暟 + xact_cxt->SubXact_callbacks = NULL; // 瀛愪簨鍔″洖璋冨嚱鏁 #ifdef PGXC - xact_cxt->dbcleanup_info = (abort_callback_type*)palloc0(sizeof(abort_callback_type)); - xact_cxt->dbcleanupInfoList = NIL; + xact_cxt->dbcleanup_info = (abort_callback_type*)palloc0(sizeof(abort_callback_type)); // 鏁版嵁搴撴竻鐞嗗洖璋冧俊鎭 + xact_cxt->dbcleanupInfoList = NIL; // 鏁版嵁搴撴竻鐞嗗洖璋冧俊鎭垪琛 #endif - /* alloc in TopTransactionMemory Context, safe to set NULL */ - xact_cxt->prepareGID = NULL; - /* alloc in TopMemory Context, initialization is NULL when create new session */ - xact_cxt->savePrepareGID = NULL; + /* 鍦 TopTransactionMemory 涓婁笅鏂囧垎閰嶏紝瀹夊叏鍦拌缃负 NULL */ + xact_cxt->prepareGID = NULL; // 鍑嗗浜嬪姟鐨勫叏灞 ID + /* 鍦 TopMemory 涓婁笅鏂囧垎閰嶏紝鍒涘缓鏂颁細璇濇椂鍒濆鍖栦负 NULL */ + xact_cxt->savePrepareGID = NULL; // 淇濆瓨鍑嗗浜嬪姟鐨勫叏灞 ID - xact_cxt->pbe_execute_complete = true; - xact_cxt->sendSeqDbName = NULL; - xact_cxt->sendSeqSchmaName = NULL; - xact_cxt->sendSeqName = NULL; - xact_cxt->send_result = NULL; - xact_cxt->ActiveLobRelid = InvalidOid; + xact_cxt->pbe_execute_complete = true; // PBE 鎵ц鏄惁瀹屾垚 + xact_cxt->sendSeqDbName = NULL; // 鍙戦佸簭鍒楃殑鏁版嵁搴撳悕 + xact_cxt->sendSeqSchmaName = NULL; // 鍙戦佸簭鍒楃殑妯″紡鍚 + xact_cxt->sendSeqName = NULL; // 鍙戦佸簭鍒楃殑鍚嶅瓧 + xact_cxt->send_result = NULL; // 鍙戦佺殑缁撴灉 + xact_cxt->ActiveLobRelid = InvalidOid; // 娲昏穬 LOB 琛 ID } static void knl_u_ps_init(knl_u_ps_context* ps_cxt) { #ifndef PS_USE_CLOBBER_ARGV #define PS_BUFFER_SIZE 256 - ps_cxt->ps_buffer_size = PS_BUFFER_SIZE; + ps_cxt->ps_buffer_size = PS_BUFFER_SIZE; // 棰勫鐞嗚鍙ョ紦鍐插尯澶у皬 #endif } @@ -1288,21 +1301,21 @@ static void knl_u_ps_init(knl_u_ps_context* ps_cxt) static void knl_u_mot_init(knl_u_mot_context* mot_cxt) { Assert(mot_cxt != NULL); - mot_cxt->callbacks_set = false; - mot_cxt->session_id = -1; // invalid session id - mot_cxt->connection_id = -1; // invalid connection id - mot_cxt->session_context = NULL; - mot_cxt->txn_manager = NULL; - mot_cxt->jit_session_context_pool = NULL; - mot_cxt->jit_context_count = 0; - mot_cxt->jit_llvm_if_stack = NULL; - mot_cxt->jit_llvm_while_stack = NULL; - mot_cxt->jit_llvm_do_while_stack = NULL; - mot_cxt->jit_tvm_if_stack = NULL; - mot_cxt->jit_tvm_while_stack = NULL; - mot_cxt->jit_tvm_do_while_stack = NULL; - mot_cxt->jit_context = NULL; - mot_cxt->jit_txn = NULL; + mot_cxt->callbacks_set = false; // 鍥炶皟鍑芥暟鏄惁璁剧疆 + mot_cxt->session_id = -1; // 鏃犳晥鐨勪細璇 ID + mot_cxt->connection_id = -1; // 鏃犳晥鐨勮繛鎺 ID + mot_cxt->session_context = NULL; // 浼氳瘽涓婁笅鏂 + mot_cxt->txn_manager = NULL; // 浜嬪姟绠$悊鍣 + mot_cxt->jit_session_context_pool = NULL; // JIT 浼氳瘽涓婁笅鏂囨睜 + mot_cxt->jit_context_count = 0; // JIT 涓婁笅鏂囪鏁 + mot_cxt->jit_llvm_if_stack = NULL; // JIT LLVM IF 鏍 + mot_cxt->jit_llvm_while_stack = NULL; // JIT LLVM WHILE 鏍 + mot_cxt->jit_llvm_do_while_stack = NULL; // JIT LLVM DO-WHILE 鏍 + mot_cxt->jit_tvm_if_stack = NULL; // JIT TVM IF 鏍 + mot_cxt->jit_tvm_while_stack = NULL; // JIT TVM WHILE 鏍 + mot_cxt->jit_tvm_do_while_stack = NULL; // JIT TVM DO-WHILE 鏍 + mot_cxt->jit_context = NULL; // JIT 涓婁笅鏂 + mot_cxt->jit_txn = NULL; // JIT 浜嬪姟 } #endif @@ -1310,10 +1323,10 @@ static void knl_u_clientConnTime_init(knl_u_clientConnTime_context* clientConnTi { Assert(clientConnTime_cxt != NULL); - /* Record start time while initializing session for client connection */ + /* 鍦ㄤ负瀹㈡埛绔繛鎺ュ垵濮嬪寲浼氳瘽鏃惰褰曞紑濮嬫椂闂 */ INSTR_TIME_SET_CURRENT(clientConnTime_cxt->connStartTime); - /* Set flag to "true", to indicate this session in initial process */ + /* 灏嗘爣蹇楄缃负鈥渢rue鈥濓紝浠ユ寚绀烘浼氳瘽浣嶄簬鍒濆杩涚▼涓 */ clientConnTime_cxt->checkOnlyInConnProcess = true; } @@ -1414,26 +1427,31 @@ void knl_session_init(knl_session_context* sess_cxt) static void alloc_context_from_top(knl_session_context* sess, MemoryContext top_mem_cxt) { + // 浠庨《绾у唴瀛樹笂涓嬫枃`top_mem_cxt`涓垎閰嶅苟鍒涘缓涓嶅悓瀛愬唴瀛樹笂涓嬫枃 sess->self_mem_cxt = AllocSetContextCreate(top_mem_cxt, "SessionSelfMemoryContext", ALLOCSET_DEFAULT_MINSIZE, ALLOCSET_DEFAULT_INITSIZE, ALLOCSET_DEFAULT_MAXSIZE); + sess->cache_mem_cxt = AllocSetContextCreate(top_mem_cxt, "SessionCacheMemoryContext", ALLOCSET_DEFAULT_MINSIZE, ALLOCSET_DEFAULT_INITSIZE, - (1024 * 1024)); /* set max block size to 1MB */ + (1024 * 1024)); // 璁剧疆鏈澶у潡澶у皬涓1MB + sess->temp_mem_cxt = AllocSetContextCreate(top_mem_cxt, "SessionTempMemoryContext", ALLOCSET_DEFAULT_MINSIZE, ALLOCSET_DEFAULT_INITSIZE, ALLOCSET_DEFAULT_MAXSIZE); + sess->syscache_cxt.SysCacheMemCxt = AllocSetContextCreate(top_mem_cxt, "SystemCacheMemoryContext", ALLOCSET_DEFAULT_MINSIZE, ALLOCSET_DEFAULT_INITSIZE, ALLOCSET_DEFAULT_MAXSIZE); + sess->stat_cxt.hotkeySessContext = AllocSetContextCreate(top_mem_cxt, "HotkeySessionMemoryContext", ALLOCSET_DEFAULT_MINSIZE, @@ -1445,17 +1463,27 @@ knl_session_context* create_session_context(MemoryContext parent, uint64 id) { knl_session_context *sess, *old_sess; const int secondToMilliSecond = 1000; + + // 淇濆瓨褰撳墠浼氳瘽涓婁笅鏂囷紝浠ヤ究绋嶅悗鎭㈠ old_sess = u_sess; + + // 瑙e皝椤剁骇鍐呭瓨涓婁笅鏂囷紝浠ヤ究杩涜鍐呭瓨鍒嗛厤鎿嶄綔 MemoryContextUnSeal(t_thrd.top_mem_cxt); + + // 鍒嗛厤骞跺垵濮嬪寲浼氳瘽涓婁笅鏂噑ess sess = (knl_session_context*)MemoryContextAllocZero(parent, sizeof(knl_session_context)); + + // 灏佸嵃椤剁骇鍐呭瓨涓婁笅鏂囷紝浠ヤ究淇濇姢鍏跺唴瀹 MemoryContextSeal(t_thrd.top_mem_cxt); MemoryContext top_mem_cxt; if (id == 0) { + // 濡傛灉浼氳瘽ID涓0锛岃〃绀轰负涓讳細璇濓紝鍒欎娇鐢ㄩ《绾у唴瀛樹笂涓嬫枃 top_mem_cxt = t_thrd.top_mem_cxt; sess->mcxt_group = t_thrd.mcxt_group; } else { + // 濡傛灉浼氳瘽ID涓嶄负0锛岃〃绀轰负瀛愪細璇濓紝鍒欏垱寤烘柊鐨勫唴瀛樹笂涓嬫枃锛屽苟璁剧疆浼氳瘽ID top_mem_cxt = AllocSetContextCreate(parent, "SessionTopMemoryContext", ALLOCSET_DEFAULT_MINSIZE, @@ -1466,7 +1494,11 @@ knl_session_context* create_session_context(MemoryContext parent, uint64 id) true); top_mem_cxt->session_id = id; } + + // 鍒囨崲褰撳墠鍐呭瓨涓婁笅鏂囧埌top_mem_cxt MemoryContext old_cxt = MemoryContextSwitchTo(top_mem_cxt); + + // 璁剧疆浼氳瘽鐨勯《绾у唴瀛樹笂涓嬫枃鍜屼細璇滻D锛岀劧鍚庡垵濮嬪寲浼氳瘽 sess->top_mem_cxt = top_mem_cxt; knl_session_init(sess); sess->session_id = id; @@ -1476,29 +1508,32 @@ knl_session_context* create_session_context(MemoryContext parent, uint64 id) u_sess = sess; if (id != 0) { + // 濡傛灉浼氳瘽ID涓嶄负0锛岃〃绀轰负绾跨▼姹犱細璇濓紝鍒欐墽琛屼互涓嬫搷浣 MemoryContextUnSeal(top_mem_cxt); sess->mcxt_group = New(top_mem_cxt) MemoryContextGroup(); sess->mcxt_group->Init(top_mem_cxt); MemoryContextSeal(top_mem_cxt); - /* - * threadpool session, set init timeout to - * avoid user only establish connections but do not send data or SSL shakehands hang - * non-threadpool/fake session will direct call ReadCommand and enable alarm by sig timer - * */ + + // 涓虹嚎绋嬫睜浼氳瘽璁剧疆鍒濆瓒呮椂锛屼互閬垮厤鐢ㄦ埛鍙缓绔嬭繛鎺ヤ絾涓嶅彂閫佹暟鎹垨SSL鎻℃墜鑰屽鑷寸殑鎸傝捣 (void)enable_session_sig_alarm(u_sess->attr.attr_common.SessionTimeout * secondToMilliSecond); } - // Switch to context group, in case knl_u_executor_init will alloc memory on CurrentMemoryContext. + // 鍒囨崲鍒颁笂涓嬫枃缁勶紝浠ヤ究鍦╧nl_u_executor_init涓繘琛屽唴瀛樺垎閰 MemoryContextSwitchTo(sess->mcxt_group->GetMemCxtGroup(MEMORY_CONTEXT_EXECUTOR)); + + // 鍒濆鍖栨墽琛屽櫒涓婁笅鏂 knl_u_executor_init(&sess->exec_cxt); + // 浠庨《绾у唴瀛樹笂涓嬫枃涓垎閰嶅叾浠栧瓙涓婁笅鏂 alloc_context_from_top(sess, top_mem_cxt); - /* Initialize portal manager */ + /* 鍒濆鍖朠ortal绠$悊鍣 */ EnablePortalManager(); + // 鎭㈠涔嬪墠淇濆瓨鐨勪細璇濅笂涓嬫枃鍜屽綋鍓嶅唴瀛樹笂涓嬫枃 u_sess = old_sess; MemoryContextSwitchTo(old_cxt); + return sess; } @@ -1510,12 +1545,13 @@ void use_fake_session() void free_session_context(knl_session_context* session) { + // 纭繚褰撳墠浼氳瘽涓婁笅鏂囦笌浼犲叆鐨勪細璇濅笂涓嬫枃涓鑷 Assert(u_sess == session); - /* free the locale cache */ + /* 閲婃斁鍖哄煙璁剧疆缂撳瓨 */ freeLocaleCache(false); - /* discard all the data in the channel. */ + /* 涓㈠純閫氶亾涓殑鎵鏈夋暟鎹 */ t_thrd.libpq_cxt.PqSendPointer = 0; t_thrd.libpq_cxt.PqSendStart = 0; t_thrd.libpq_cxt.PqRecvPointer = 0; @@ -1525,17 +1561,25 @@ void free_session_context(knl_session_context* session) t_thrd.xact_cxt.next_xid = InvalidTransactionId; - /* Release session related memory. */ + /* 閲婃斁涓庝細璇濈浉鍏崇殑鍐呭瓨銆 */ SelfMemoryContext = NULL; + if (CurrentMemoryContext == u_sess->top_transaction_mem_cxt) { - /* abnormal cleanup */ + /* 寮傚父鎯呭喌涓嬬殑娓呯悊锛屽垏鎹㈠埌娑堟伅鍐呭瓨涓婁笅鏂 */ MemoryContextSwitchTo(t_thrd.mem_cxt.msg_mem_cxt); } + // 鍒犻櫎浼氳瘽椤剁骇鍐呭瓨涓婁笅鏂囧強鍏舵墍鏈夊瓙涓婁笅鏂 MemoryContextDeleteChildren(session->top_mem_cxt); MemoryContextDelete(session->top_mem_cxt); + + // 閲婃斁鍒犻櫎鍐呭瓨涓婁笅鏂囩殑浜掓枼閿 (void)syscalllockFree(&session->utils_cxt.deleMemContextMutex); + + // 閲婃斁浼氳瘽涓婁笅鏂囧唴瀛 pfree_ext(session); + + // 浣跨敤铏氭嫙浼氳瘽 use_fake_session(); } @@ -1543,6 +1587,8 @@ bool stp_set_commit_rollback_err_msg(stp_xact_err_type type) { int rt; size_t maxMsgLen = sizeof(u_sess->SPI_cxt.forbidden_commit_rollback_err_msg); + + // 妫鏌ラ敊璇秷鎭槸鍚︿负绌猴紝濡傛灉涓虹┖锛屽垯鏍规嵁绫诲瀷璁剧疆閿欒娑堟伅 if (u_sess->SPI_cxt.forbidden_commit_rollback_err_msg[0] == '\0') { switch (type) { case STP_XACT_OPEN_FOR: @@ -1555,7 +1601,7 @@ bool stp_set_commit_rollback_err_msg(stp_xact_err_type type) break; case STP_XACT_USED_AS_EXPR: rt = snprintf_s(u_sess->SPI_cxt.forbidden_commit_rollback_err_msg, maxMsgLen, maxMsgLen - 1, "%s", - "transaction statement in store procedure used as a expression is not supported"); + "transaction statement in store procedure used as an expression is not supported"); break; case STP_XACT_GUC_IN_OPT_CLAUSE: rt = snprintf_s(u_sess->SPI_cxt.forbidden_commit_rollback_err_msg, maxMsgLen, maxMsgLen - 1, "%s", @@ -1567,15 +1613,15 @@ bool stp_set_commit_rollback_err_msg(stp_xact_err_type type) break; case STP_XACT_AFTER_TRIGGER_BEGIN: rt = snprintf_s(u_sess->SPI_cxt.forbidden_commit_rollback_err_msg, maxMsgLen, maxMsgLen - 1, "%s", - "transaction statement in store procedure used as sql to get value is not supported"); + "transaction statement in store procedure used as SQL to get value is not supported"); break; case STP_XACT_PACKAGE_INSTANTIATION: rt = snprintf_s(u_sess->SPI_cxt.forbidden_commit_rollback_err_msg, maxMsgLen, maxMsgLen - 1, "%s", - "can not use commit/rollback/savepoint in package instantiation"); + "cannot use commit/rollback/savepoint in package instantiation"); break; case STP_XACT_COMPL_SQL: rt = snprintf_s(u_sess->SPI_cxt.forbidden_commit_rollback_err_msg, maxMsgLen, maxMsgLen - 1, "%s", - "can not use commit rollback in Complex SQL"); + "cannot use commit rollback in Complex SQL"); break; case STP_XACT_IMMUTABLE: rt = snprintf_s(u_sess->SPI_cxt.forbidden_commit_rollback_err_msg, maxMsgLen, maxMsgLen - 1, "%s", @@ -1583,15 +1629,16 @@ bool stp_set_commit_rollback_err_msg(stp_xact_err_type type) break; case STP_XACT_TOO_MANY_PORTAL: rt = snprintf_s(u_sess->SPI_cxt.forbidden_commit_rollback_err_msg, maxMsgLen, maxMsgLen - 1, "%s", - "transaction statement in store procedure is not supported used in multi-layer portal"); + "transaction statement in store procedure is not supported when used in multi-layer portal"); break; default: rt = snprintf_s(u_sess->SPI_cxt.forbidden_commit_rollback_err_msg, maxMsgLen, maxMsgLen - 1, "%s", "invalid transaction in store procedure"); break; } + // 妫鏌ュ瓧绗︿覆鏄惁琚纭啓鍏ユ垨婧㈠嚭 if (rt < 0 || rt > ((int)maxMsgLen)) { - ereport(ERROR, (errmsg("string of invalid transaction message would overflow buffer"))); + ereport(ERROR, (errmsg("string of invalid transaction message would overflow buffer"))); } return true; } @@ -1607,4 +1654,4 @@ bool enable_out_param_override() { return u_sess->attr.attr_sql.sql_compatibility == A_FORMAT && PROC_OUTPARAM_OVERRIDE; -} +} \ No newline at end of file diff --git a/src/gausskernel/process/threadpool/knl_thread.cpp b/src/gausskernel/process/threadpool/knl_thread.cpp index 068d74627..4db3678f4 100755 --- a/src/gausskernel/process/threadpool/knl_thread.cpp +++ b/src/gausskernel/process/threadpool/knl_thread.cpp @@ -15,15 +15,12 @@ * ------------------------------------------------------------------------- * * knl_thread.cpp - * Initial functions for thread level global variables. + * 绾跨▼绾у叏灞鍙橀噺鐨勫垵濮嬪嚱鏁般 * - * The thread level variables will be inited at the start up time of one - * thread, to be specific, at the beginning of SubPostmasterMain(). When - * anyone try to add variable in thread level context, remember to add - * initialization at this file. + * 绾跨▼绾у埆鐨勫彉閲忓皢鍦ㄤ竴涓嚎绋嬬殑鍚姩鏃惰繘琛屽垵濮嬪寲锛屽叿浣撴潵璇达紝鍦⊿ubPostmasterMain()鐨勫紑濮嬫椂銆 + * 褰撲换浣曚汉璇曞浘鍦ㄧ嚎绋嬬骇鍒笂涓嬫枃涓坊鍔犲彉閲忔椂锛岃璁板緱鍦ㄨ繖涓枃浠朵腑娣诲姞鍒濆鍖栥" * - * And be very careful to alloc memory here, the memory will be alloced from - * TopMemoryContext and will not be freed until the thread exit. + * "鍦ㄨ繖閲屽垎閰嶅唴瀛樻椂瑕侀潪甯稿皬蹇冿紝鍐呭瓨灏嗕粠TopMemoryContext涓垎閰嶏紝鐩村埌绾跨▼閫鍑烘椂鎵嶄細琚噴鏀俱" * * * IDENTIFICATION @@ -73,18 +70,23 @@ THR_LOCAL knl_thrd_context t_thrd; extern void temp_file_context_init(knl_t_libpq_context* libpq_cxt); +// 闈欐佸嚱鏁帮紝鐢ㄤ簬鍒濆鍖栫嚎绋嬬骇AES涓婁笅鏂囩粨鏋勪綋 static void knl_t_aes_init(knl_t_aes_context* aes_cxt) { + // 璁$畻鏁扮粍闀垮害 size_t arrlen = sizeof(GS_UCHAR) * RANDOM_LEN; + // 鐢ㄤ簬澶勭悊閿欒鐨勮繑鍥炵爜 errno_t rc; - aes_cxt->encryption_function_call = false; - aes_cxt->decryption_function_call = false; - aes_cxt->decryption_count = 0; - aes_cxt->insert_position = NUMBER_OF_SAVED_DERIVEKEYS / 2; - aes_cxt->random_salt_tag = false; - aes_cxt->random_salt_count = 0; + // 鍒濆鍖朅ES涓婁笅鏂囩粨鏋勪綋鐨勫悇涓垚鍛樺彉閲 + aes_cxt->encryption_function_call = false; // 鍔犲瘑鍑芥暟璋冪敤鏍囧織 + aes_cxt->decryption_function_call = false; // 瑙e瘑鍑芥暟璋冪敤鏍囧織 + aes_cxt->decryption_count = 0; // 瑙e瘑璁℃暟鍣 + aes_cxt->insert_position = NUMBER_OF_SAVED_DERIVEKEYS / 2; // 鎻掑叆浣嶇疆 + aes_cxt->random_salt_tag = false; // 闅忔満鐩愭爣蹇 + aes_cxt->random_salt_count = 0; // 闅忔満鐩愯鏁板櫒 + // 灏嗘暟缁勬垚鍛樺彉閲忓垵濮嬪寲涓0 rc = memset_s(aes_cxt->derive_vector_saved, arrlen, 0, arrlen); securec_check(rc, "\0", "\0"); rc = memset_s(aes_cxt->mac_vector_saved, arrlen, 0, arrlen); @@ -101,6 +103,7 @@ static void knl_t_aes_init(knl_t_aes_context* aes_cxt) sizeof(GS_UINT32) * NUMBER_OF_SAVED_DERIVEKEYS); securec_check(rc, "\0", "\0"); + // 寰幆鍒濆鍖栨暟缁勬垚鍛樺彉閲忎负0 for (int i = 0; i < NUMBER_OF_SAVED_DERIVEKEYS; i++) { rc = memset_s(aes_cxt->derive_vector_used[i], arrlen, 0, arrlen); securec_check(rc, "\0", "\0"); @@ -113,170 +116,182 @@ static void knl_t_aes_init(knl_t_aes_context* aes_cxt) } } +// 鍒濆鍖栦唬鐮佺敓鎴愪笂涓嬫枃缁撴瀯浣 static void knl_t_codegen_init(knl_t_codegen_context* codegen_cxt) { - codegen_cxt->thr_codegen_obj = NULL; - codegen_cxt->g_runningInFmgr = false; - codegen_cxt->codegen_IRload_thr_count = 0; + codegen_cxt->thr_codegen_obj = NULL; // 绾跨▼浠g爜鐢熸垚瀵硅薄 + codegen_cxt->g_runningInFmgr = false; // 鍦ㄥ嚱鏁扮鐞嗗櫒涓繍琛屾爣蹇 + codegen_cxt->codegen_IRload_thr_count = 0; // 浠g爜鐢熸垚IR鍔犺浇绾跨▼璁℃暟 } +// 鍒濆鍖栨牸寮忓寲涓婁笅鏂囩粨鏋勪綋 static void knl_t_format_init(knl_t_format_context* format_cxt) { - format_cxt->all_digits = false; - format_cxt->DCH_cache = (DCHCacheEntry*)palloc0(sizeof(DCHCacheEntry) * (DCH_CACHE_FIELDS + 1)); - format_cxt->n_DCH_cache = 0; - format_cxt->DCH_counter = 0; - format_cxt->NUM_cache = (NUMCacheEntry*)palloc0(sizeof(NUMCacheEntry) * (NUM_CACHE_FIELDS + 1)); - format_cxt->n_NUM_cache = 0; - format_cxt->NUM_counter = 0; - format_cxt->last_NUM_cache_entry = NULL; + format_cxt->all_digits = false; // 鍏ㄦ暟瀛楁爣蹇 + format_cxt->DCH_cache = (DCHCacheEntry*)palloc0(sizeof(DCHCacheEntry) * (DCH_CACHE_FIELDS + 1)); // DCH缂撳瓨 + format_cxt->n_DCH_cache = 0; // DCH缂撳瓨璁℃暟 + format_cxt->DCH_counter = 0; // DCH璁℃暟鍣 + format_cxt->NUM_cache = (NUMCacheEntry*)palloc0(sizeof(NUMCacheEntry) * (NUM_CACHE_FIELDS + 1)); // NUM缂撳瓨 + format_cxt->n_NUM_cache = 0; // NUM缂撳瓨璁℃暟 + format_cxt->NUM_counter = 0; // NUM璁℃暟鍣 + format_cxt->last_NUM_cache_entry = NULL; // 鏈鍚庝竴涓狽UM缂撳瓨鏉$洰 } +// 鍒濆鍖栨棩蹇椾笂涓嬫枃缁撴瀯浣 static void knl_t_log_init(knl_t_log_context* log_cxt) { - log_cxt->plog_msg_switch_tm = {1, 0}; - log_cxt->plog_md_read_entry = NULL; - log_cxt->plog_md_write_entry = NULL; - log_cxt->plog_obs_list_entry = NULL; - log_cxt->plog_obs_read_entry = NULL; - log_cxt->plog_obs_write_entry = NULL; - log_cxt->plog_hdp_read_entry = NULL; - log_cxt->plog_hdp_write_entry = NULL; - log_cxt->plog_hdp_open_entry = NULL; - log_cxt->plog_remote_read_entry = NULL; + log_cxt->plog_msg_switch_tm = {1, 0}; // plog娑堟伅寮鍏虫爣蹇 + log_cxt->plog_md_read_entry = NULL; // plog md璇诲彇鏉$洰 + log_cxt->plog_md_write_entry = NULL; // plog md鍐欏叆鏉$洰 + log_cxt->plog_obs_list_entry = NULL; // plog obs鍒楄〃鏉$洰 + log_cxt->plog_obs_read_entry = NULL; // plog obs璇诲彇鏉$洰 + log_cxt->plog_obs_write_entry = NULL; // plog obs鍐欏叆鏉$洰 + log_cxt->plog_hdp_read_entry = NULL; // plog hdp璇诲彇鏉$洰 + log_cxt->plog_hdp_write_entry = NULL; // plog hdp鍐欏叆鏉$洰 + log_cxt->plog_hdp_open_entry = NULL; // plog hdp鎵撳紑鏉$洰 + log_cxt->plog_remote_read_entry = NULL; // plog 杩滅▼璇诲彇鏉$洰 + + // 鍒嗛厤鍐呭瓨骞跺垵濮嬪寲plog娑堟伅鍐呭瓨鏁扮粍 log_cxt->g_plog_msgmem_array = (char***)palloc0(sizeof(char**) * DS_VALID_NUM); for (int i = 0; i < DSRQ_VALID_NUM; i++) { log_cxt->g_plog_msgmem_array[i] = (char**)palloc0(sizeof(char*) * DSRQ_VALID_NUM); } - log_cxt->error_context_stack = NULL; - log_cxt->call_stack = NULL; - log_cxt->PG_exception_stack = NULL; - log_cxt->thd_bt_symbol = NULL; - log_cxt->flush_message_immediately = false; - log_cxt->Log_destination = LOG_DESTINATION_STDERR; - log_cxt->disable_log_output = false; - log_cxt->on_mask_password = false; - log_cxt->openlog_done = false; - log_cxt->error_with_nodename = false; - log_cxt->errordata = (ErrorData*)palloc0(sizeof(ErrorData) * ERRORDATA_STACK_SIZE); - log_cxt->pLogCtl = NULL; - log_cxt->errordata_stack_depth = -1; - log_cxt->recursion_depth = 0; - log_cxt->syslog_seq = 0; - log_cxt->log_line_number = 0; - log_cxt->log_my_pid = 0; - log_cxt->csv_log_line_number = 0; - log_cxt->csv_log_my_pid = 0; - log_cxt->msgbuf = (StringInfoData*)palloc0(sizeof(StringInfoData)); - log_cxt->module_logging_configure = (unsigned char*)palloc0(sizeof(char) * BEMD_BITMAP_SIZE); + // 鍒濆鍖栧悇绉嶆棩蹇椾笂涓嬫枃鍙橀噺 + log_cxt->error_context_stack = NULL; // 閿欒涓婁笅鏂囧爢鏍 + log_cxt->call_stack = NULL; // 璋冪敤鍫嗘爤 + log_cxt->PG_exception_stack = NULL; // PG寮傚父鍫嗘爤 + log_cxt->thd_bt_symbol = NULL; // 绾跨▼鍥炴函绗﹀彿 + log_cxt->flush_message_immediately = false; // 绔嬪嵆鍒锋柊娑堟伅鏍囧織 + log_cxt->Log_destination = LOG_DESTINATION_STDERR; // 鏃ュ織杈撳嚭鐩爣 + log_cxt->disable_log_output = false; // 绂佹鏃ュ織杈撳嚭鏍囧織 + log_cxt->on_mask_password = false; // 鎺╃爜瀵嗙爜鏍囧織 + log_cxt->openlog_done = false; // 鎵撳紑鏃ュ織鏍囧織 + log_cxt->error_with_nodename = false; // 甯﹁妭鐐瑰悕鐨勯敊璇爣蹇 + log_cxt->errordata = (ErrorData*)palloc0(sizeof(ErrorData) * ERRORDATA_STACK_SIZE); // 閿欒鏁版嵁 + log_cxt->pLogCtl = NULL; // 鏃ュ織鎺у埗 + log_cxt->errordata_stack_depth = -1; // 閿欒鏁版嵁鍫嗘爤娣卞害 + log_cxt->recursion_depth = 0; // 閫掑綊娣卞害 + log_cxt->syslog_seq = 0; // syslog搴忓垪鍙 + log_cxt->log_line_number = 0; // 鏃ュ織琛屽彿 + log_cxt->log_my_pid = 0; // 鏃ュ織杩涚▼ID + log_cxt->csv_log_line_number = 0; // CSV鏃ュ織琛屽彿 + log_cxt->csv_log_my_pid = 0; // CSV鏃ュ織杩涚▼ID + log_cxt->msgbuf = (StringInfoData*)palloc0(sizeof(StringInfoData)); // 娑堟伅缂撳啿鍖 + log_cxt->module_logging_configure = (unsigned char*)palloc0(sizeof(char) * BEMD_BITMAP_SIZE); // 妯″潡鏃ュ織閰嶇疆 } +// 鍒濆鍖栭噸瀹氫綅閫夐」涓婁笅鏂囩粨鏋勪綋 static void knl_t_relopt_init(knl_t_relopt_context* relopt_cxt) { - relopt_cxt->relOpts = NULL; - relopt_cxt->last_assigned_kind = RELOPT_KIND_LAST_DEFAULT; - relopt_cxt->num_custom_options = 0; - relopt_cxt->custom_options = NULL; - relopt_cxt->need_initialization = true; - relopt_cxt->max_custom_options = 0; + relopt_cxt->relOpts = NULL; // 鍏崇郴閫夐」 + relopt_cxt->last_assigned_kind = RELOPT_KIND_LAST_DEFAULT; // 鏈鍚庡垎閰嶇殑閫夐」绉嶇被 + relopt_cxt->num_custom_options = 0; // 鑷畾涔夐夐」鏁伴噺 + relopt_cxt->custom_options = NULL; // 鑷畾涔夐夐」 + relopt_cxt->need_initialization = true; // 闇瑕佸垵濮嬪寲鏍囧織 + relopt_cxt->max_custom_options = 0; // 鏈澶ц嚜瀹氫箟閫夐」鏁伴噺 } +// 鍒濆鍖栧垪寮忓瓨鍌ㄤ笂涓嬫枃缁撴瀯浣 static void knl_t_cstore_init(knl_t_cstore_context* cstore_cxt) { - cstore_cxt->gCStoreAlterReg = NULL; - cstore_cxt->bulkload_memsize_used = 0; - cstore_cxt->cstore_prefetch_count = 0; - cstore_cxt->InProgressAioCUDispatch = NULL; - cstore_cxt->InProgressAioCUDispatchCount = 0; + cstore_cxt->gCStoreAlterReg = NULL; // 鍒楀紡瀛樺偍鍙樻洿娉ㄥ唽 + cstore_cxt->bulkload_memsize_used = 0; // 鎵归噺鍔犺浇鍐呭瓨浣跨敤閲 + cstore_cxt->cstore_prefetch_count = 0; // 鍒楀紡瀛樺偍棰勫彇鏁伴噺 + cstore_cxt->InProgressAioCUDispatch = NULL; // 杩涜涓殑寮傛IO CU鍒嗗彂 + cstore_cxt->InProgressAioCUDispatchCount = 0; // 杩涜涓殑寮傛IO CU鍒嗗彂鏁伴噺 } +// 鍒濆鍖朌FS涓婁笅鏂囩粨鏋勪綋 static void knl_t_dfs_init(knl_t_dfs_context* dfs_cxt) { - dfs_cxt->pending_free_reader_list = NIL; - dfs_cxt->pending_free_writer_list = NIL; + dfs_cxt->pending_free_reader_list = NIL; // 寰呴噴鏀剧殑璇诲彇鍣ㄥ垪琛 + dfs_cxt->pending_free_writer_list = NIL; // 寰呴噴鏀剧殑鍐欏叆鍣ㄥ垪琛 } +// 鍒濆鍖朞BS涓婁笅鏂囩粨鏋勪綋 static void knl_t_obs_init(knl_t_obs_context* obs_cxt) { - obs_cxt->ObsMemoryContext = NULL; - obs_cxt->pCAInfo = NULL; + obs_cxt->ObsMemoryContext = NULL; // OBS鍐呭瓨涓婁笅鏂 + obs_cxt->pCAInfo = NULL; // CA淇℃伅 #ifndef SLEEP_UNITS_PER_SECOND #define SLEEP_UNITS_PER_SECOND 1 #endif - obs_cxt->retrySleepInterval = 1 * SLEEP_UNITS_PER_SECOND; + obs_cxt->retrySleepInterval = 1 * SLEEP_UNITS_PER_SECOND; // 閲嶈瘯鐫$湢闂撮殧 } +// 鍒濆鍖朇BM涓婁笅鏂囩粨鏋勪綋 static void knl_t_cbm_init(knl_t_cbm_context* cbm_cxt) { - cbm_cxt->XlogCbmSys = NULL; + cbm_cxt->XlogCbmSys = NULL; // Xlog鎺у埗鍧楃鐞嗙郴缁 - cbm_cxt->got_SIGHUP = false; - cbm_cxt->shutdown_requested = false; - cbm_cxt->cbmwriter_context = NULL; - cbm_cxt->cbmwriter_page_context = NULL; + cbm_cxt->got_SIGHUP = false; // 鏀跺埌SIGHUP淇″彿鏍囧織 + cbm_cxt->shutdown_requested = false; // 璇锋眰鍏抽棴鏍囧織 + cbm_cxt->cbmwriter_context = NULL; // CBM鍐欏叆鍣ㄤ笂涓嬫枃 + cbm_cxt->cbmwriter_page_context = NULL; // CBM鍐欏叆鍣ㄩ〉闈笂涓嬫枃 } +// 鍒濆鍖栧叡浜唴瀛樻寚閽堜笂涓嬫枃缁撴瀯浣 static void knl_t_shemem_ptr_init(knl_t_shemem_ptr_context* shemem_ptr_cxt) { - shemem_ptr_cxt->scan_locations = NULL; - shemem_ptr_cxt->MultiXactOffsetCtl = (SlruCtlData*)palloc0(sizeof(SlruCtlData)); - shemem_ptr_cxt->MultiXactMemberCtl = (SlruCtlData*)palloc0(sizeof(SlruCtlData)); - shemem_ptr_cxt->MultiXactState = NULL; - shemem_ptr_cxt->OldestMemberMXactId = NULL; - shemem_ptr_cxt->OldestVisibleMXactId = NULL; - shemem_ptr_cxt->ClogCtl = NULL; - shemem_ptr_cxt->CsnlogCtlPtr = NULL; - shemem_ptr_cxt->XLogCtl = NULL; - shemem_ptr_cxt->GlobalWALInsertLocks = NULL; - shemem_ptr_cxt->LocalGroupWALInsertLocks = NULL; - shemem_ptr_cxt->ControlFile = NULL; - shemem_ptr_cxt->g_LsnXlogFlushChkFile = NULL; - shemem_ptr_cxt->OldSerXidSlruCtl = (SlruCtlData*)palloc0(sizeof(SlruCtlData)); - shemem_ptr_cxt->oldSerXidControl = NULL; - shemem_ptr_cxt->OldCommittedSxact = NULL; - shemem_ptr_cxt->PredXact = NULL; - shemem_ptr_cxt->RWConflictPool = NULL; - shemem_ptr_cxt->SerializableXidHash = NULL; - shemem_ptr_cxt->PredicateLockTargetHash = NULL; - shemem_ptr_cxt->PredicateLockHash = NULL; - shemem_ptr_cxt->FinishedSerializableTransactions = NULL; + shemem_ptr_cxt->scan_locations = NULL; // 鎵弿浣嶇疆 + shemem_ptr_cxt->MultiXactOffsetCtl = (SlruCtlData*)palloc0(sizeof(SlruCtlData)); // 澶氶噸浜嬪姟鍋忕Щ鎺у埗鍧 + shemem_ptr_cxt->MultiXactMemberCtl = (SlruCtlData*)palloc0(sizeof(SlruCtlData)); // 澶氶噸浜嬪姟鎴愬憳鎺у埗鍧 + shemem_ptr_cxt->MultiXactState = NULL; // 澶氶噸浜嬪姟鐘舵 + shemem_ptr_cxt->OldestMemberMXactId = NULL; // 鏈鏃х殑澶氶噸浜嬪姟ID + shemem_ptr_cxt->OldestVisibleMXactId = NULL; // 鏈鏃у彲瑙佺殑澶氶噸浜嬪姟ID + shemem_ptr_cxt->ClogCtl = NULL; // CLOG鎺у埗鍧 + shemem_ptr_cxt->CsnlogCtlPtr = NULL; // CSNLOG鎺у埗鍧楁寚閽 + shemem_ptr_cxt->XLogCtl = NULL; // XLOG鎺у埗鍧 + shemem_ptr_cxt->GlobalWALInsertLocks = NULL; // 鍏ㄥ眬WAL鎻掑叆閿 + shemem_ptr_cxt->LocalGroupWALInsertLocks = NULL; // 鏈湴缁刉AL鎻掑叆閿 + shemem_ptr_cxt->ControlFile = NULL; // 鎺у埗鏂囦欢 + shemem_ptr_cxt->g_LsnXlogFlushChkFile = NULL; // LSN Xlog鍒锋柊妫鏌ユ枃浠 + shemem_ptr_cxt->OldSerXidSlruCtl = (SlruCtlData*)palloc0(sizeof(SlruCtlData)); // 鏃х殑搴忓垪鍖栦簨鍔D SLRU鎺у埗鍧 + shemem_ptr_cxt->oldSerXidControl = NULL; // 鏃х殑搴忓垪鍖栦簨鍔D鎺у埗 + shemem_ptr_cxt->OldCommittedSxact = NULL; // 鏃х殑鎻愪氦鐨勫彲搴忓垪鍖栦簨鍔 + shemem_ptr_cxt->PredXact = NULL; // 棰勬祴浜嬪姟 + shemem_ptr_cxt->RWConflictPool = NULL; // 璇诲啓鍐茬獊姹 + shemem_ptr_cxt->SerializableXidHash = NULL; // 鍙簭鍒楀寲浜嬪姟ID鍝堝笇琛 + shemem_ptr_cxt->PredicateLockTargetHash = NULL; // 璋撹瘝閿佺洰鏍囧搱甯岃〃 + shemem_ptr_cxt->PredicateLockHash = NULL; // 璋撹瘝閿佸搱甯岃〃 + shemem_ptr_cxt->FinishedSerializableTransactions = NULL; // 宸插畬鎴愮殑鍙簭鍒楀寲浜嬪姟 - shemem_ptr_cxt->BackendStatusArray = NULL; - shemem_ptr_cxt->BackendClientHostnameBuffer = NULL; - shemem_ptr_cxt->BackendAppnameBuffer = NULL; - shemem_ptr_cxt->BackendConninfoBuffer = NULL; - shemem_ptr_cxt->BackendActivityBuffer = NULL; - shemem_ptr_cxt->WaitCountBuffer = NULL; - shemem_ptr_cxt->BackendActivityBufferSize = 0; + shemem_ptr_cxt->BackendStatusArray = NULL; // 鍚庣鐘舵佹暟缁 + shemem_ptr_cxt->BackendClientHostnameBuffer = NULL; // 鍚庣瀹㈡埛绔富鏈哄悕缂撳啿鍖 + shemem_ptr_cxt->BackendAppnameBuffer = NULL; // 鍚庣搴旂敤绋嬪簭鍚嶇紦鍐插尯 + shemem_ptr_cxt->BackendConninfoBuffer = NULL; // 鍚庣杩炴帴淇℃伅缂撳啿鍖 + shemem_ptr_cxt->BackendActivityBuffer = NULL; // 鍚庣娲诲姩淇℃伅缂撳啿鍖 + shemem_ptr_cxt->WaitCountBuffer = NULL; // 绛夊緟璁℃暟缂撳啿鍖 + shemem_ptr_cxt->BackendActivityBufferSize = 0; // 鍚庣娲诲姩淇℃伅缂撳啿鍖哄ぇ灏 - shemem_ptr_cxt->MyBEEntry = NULL; + shemem_ptr_cxt->MyBEEntry = NULL; // 褰撳墠鍚庣杩涚▼鍏ュ彛 - shemem_ptr_cxt->mySessionStatEntry = NULL; - shemem_ptr_cxt->sessionStatArray = NULL; - shemem_ptr_cxt->mySessionMemoryEntry = NULL; - shemem_ptr_cxt->sessionMemoryArray = NULL; + shemem_ptr_cxt->mySessionStatEntry = NULL; // 褰撳墠浼氳瘽缁熻淇℃伅鍏ュ彛 + shemem_ptr_cxt->sessionStatArray = NULL; // 浼氳瘽缁熻淇℃伅鏁扮粍 + shemem_ptr_cxt->mySessionMemoryEntry = NULL; // 褰撳墠浼氳瘽鍐呭瓨淇℃伅鍏ュ彛 + shemem_ptr_cxt->sessionMemoryArray = NULL; // 浼氳瘽鍐呭瓨淇℃伅鏁扮粍 - shemem_ptr_cxt->mySessionTimeEntry = NULL; - shemem_ptr_cxt->sessionTimeArray = NULL; + shemem_ptr_cxt->mySessionTimeEntry = NULL; // 褰撳墠浼氳瘽鏃堕棿淇℃伅鍏ュ彛 + shemem_ptr_cxt->sessionTimeArray = NULL; // 浼氳瘽鏃堕棿淇℃伅鏁扮粍 - shemem_ptr_cxt->ProcSignalSlots = NULL; - shemem_ptr_cxt->MyProcSignalSlot = NULL; - shemem_ptr_cxt->ShmemSegHdr = NULL; - shemem_ptr_cxt->ShmemBase = NULL; - shemem_ptr_cxt->ShmemEnd = NULL; - shemem_ptr_cxt->ShmemLock = NULL; - shemem_ptr_cxt->ShmemIndex = NULL; - shemem_ptr_cxt->shmInvalBuffer = NULL; - shemem_ptr_cxt->PMSignalState = NULL; - shemem_ptr_cxt->mainLWLockArray = NULL; + shemem_ptr_cxt->ProcSignalSlots = NULL; // 杩涚▼淇″彿妲芥暟缁 + shemem_ptr_cxt->MyProcSignalSlot = NULL; // 褰撳墠杩涚▼淇″彿妲 + shemem_ptr_cxt->ShmemSegHdr = NULL; // 鍏变韩鍐呭瓨娈靛ご閮 + shemem_ptr_cxt->ShmemBase = NULL; // 鍏变韩鍐呭瓨鍩哄潃 + shemem_ptr_cxt->ShmemEnd = NULL; // 鍏变韩鍐呭瓨缁撴潫鍦板潃 + shemem_ptr_cxt->ShmemLock = NULL; // 鍏变韩鍐呭瓨閿 + shemem_ptr_cxt->ShmemIndex = NULL; // 鍏变韩鍐呭瓨绱㈠紩 + shemem_ptr_cxt->shmInvalBuffer = NULL; // 鍏变韩鍐呭瓨澶辨晥缂撳啿鍖 + shemem_ptr_cxt->PMSignalState = NULL; // PM淇″彿鐘舵 + shemem_ptr_cxt->mainLWLockArray = NULL; // 涓籐W閿佹暟缁 } static void knl_t_xact_init(knl_t_xact_context* xact_cxt) { errno_t rc; - /* init var in transam.cpp */ + /* 鍦╰ranam .cpp涓垵濮嬪寲鍙橀噺 */ xact_cxt->cachedFetchCSNXid = InvalidTransactionId; xact_cxt->cachedFetchCSN = 0; xact_cxt->latestFetchCSNXid = InvalidTransactionId; @@ -287,11 +302,11 @@ static void knl_t_xact_init(knl_t_xact_context* xact_cxt) xact_cxt->cachedFetchXidStatus = 0; xact_cxt->cachedCommitLSN = 0; - /* init var in multixact.cpp */ + /* 鍦╩ultixact.cpp涓殑鍒濆鍖栧彉閲 */ xact_cxt->MXactCache = NULL; xact_cxt->MXactContext = NULL; - /* init var in twophase.cpp */ + /* 鍦╰wophase.cpp涓殑鍒濆鍖栧彉閲 */ xact_cxt->MyLockedGxact = NULL; xact_cxt->twophaseExitRegistered = false; xact_cxt->cached_xid = InvalidTransactionId; @@ -300,7 +315,7 @@ static void knl_t_xact_init(knl_t_xact_context* xact_cxt) rc = memset_s(&xact_cxt->records, sizeof(xllist), 0, sizeof(xllist)); securec_check(rc, "\0", "\0"); - /* init var in varsup.cpp */ + /* 鍦╲arsup.cpp涓殑鍒濆鍖栧彉閲*/ #define FirstBootstrapObjectId 10000 xact_cxt->cn_xid = InvalidTransactionId; xact_cxt->next_xid = InvalidTransactionId; @@ -308,7 +323,7 @@ static void knl_t_xact_init(knl_t_xact_context* xact_cxt) xact_cxt->InplaceUpgradeNextOid = FirstBootstrapObjectId; xact_cxt->ShmemVariableCache = NULL; - /* init var in xact.cpp */ + /* 鍦▁act.cpp涓殑鍒濆鍖栧彉閲 */ xact_cxt->CancelStmtForReadOnly = false; xact_cxt->MyXactAccessedTempRel = false; xact_cxt->MyXactAccessedRepRel = false; @@ -336,21 +351,21 @@ static void knl_t_xact_init(knl_t_xact_context* xact_cxt) xact_cxt->XactPrepareSent = false; xact_cxt->AlterCoordinatorStmt = false; xact_cxt->forceSyncCommit = false; - /* alloc in TopMemory Context, initialization is NULL when create new thread */ + /* 鍦═opMemory涓婁笅鏂囦腑锛屽垱寤烘柊绾跨▼鏃跺垵濮嬪寲涓篘ULL */ xact_cxt->TransactionAbortContext = NULL; xact_cxt->Seq_callbacks = NULL; xact_cxt->lxid = InvalidTransactionId; xact_cxt->stablexid = InvalidTransactionId; - /* init var in gtm.cpp */ + /* 鍦╣tm.cpp涓垵濮嬪寲鍙橀噺 */ xact_cxt->currentGxid = InvalidTransactionId; xact_cxt->conn = NULL; - /* init var in slru.cpp */ + /* 鍦╯lru.cpp涓垵濮嬪寲鍙橀噺 */ xact_cxt->slru_errcause = SLRU_MAX_FAILED; xact_cxt->slru_errno = 0; - /* init var in predicate.cpp */ + /* 鍦╬redicate.cpp涓垵濮嬪寲鍙橀噺 */ xact_cxt->ScratchTargetTagHash = 0; xact_cxt->ScratchPartitionLock = NULL; xact_cxt->LocalPredicateLockHash = NULL; @@ -371,148 +386,139 @@ static void knl_t_xact_init(knl_t_xact_context* xact_cxt) xact_cxt->isSelectInto = false; } +// 鍒濆鍖栧唴瀛樹笂涓嬫枃缁撴瀯浣 static void knl_t_mem_init(knl_t_mem_context* mem_cxt) { - mem_cxt->postmaster_mem_cxt = NULL; - mem_cxt->msg_mem_cxt = NULL; - mem_cxt->cur_transaction_mem_cxt = NULL; - mem_cxt->gs_signal_mem_cxt = NULL; - mem_cxt->mask_password_mem_cxt = NULL; - mem_cxt->row_desc_mem_cxt = NULL; - mem_cxt->portal_mem_cxt = NULL; - mem_cxt->mem_track_mem_cxt = NULL; - mem_cxt->batch_encode_numeric_mem_cxt = NULL; - mem_cxt->pgAuditLocalContext = NULL; + mem_cxt->postmaster_mem_cxt = NULL; // 鍚姩杩涚▼鍐呭瓨涓婁笅鏂 + mem_cxt->msg_mem_cxt = NULL; // 娑堟伅鍐呭瓨涓婁笅鏂 + mem_cxt->cur_transaction_mem_cxt = NULL; // 褰撳墠浜嬪姟鍐呭瓨涓婁笅鏂 + mem_cxt->gs_signal_mem_cxt = NULL; // GS淇″彿鍐呭瓨涓婁笅鏂 + mem_cxt->mask_password_mem_cxt = NULL; // 鎺╃爜瀵嗙爜鍐呭瓨涓婁笅鏂 + mem_cxt->row_desc_mem_cxt = NULL; // 琛屾弿杩板唴瀛樹笂涓嬫枃 + mem_cxt->portal_mem_cxt = NULL; // PORTAL鍐呭瓨涓婁笅鏂 + mem_cxt->mem_track_mem_cxt = NULL; // 鍐呭瓨璺熻釜鍐呭瓨涓婁笅鏂 + mem_cxt->batch_encode_numeric_mem_cxt = NULL; // 鎵归噺缂栫爜鏁板瓧鍐呭瓨涓婁笅鏂 + mem_cxt->pgAuditLocalContext = NULL; // PG瀹¤鏈湴涓婁笅鏂 } +// 鍒濆鍖朮LOG涓婁笅鏂囩粨鏋勪綋 static void knl_t_xlog_init(knl_t_xlog_context* xlog_cxt) { errno_t rc; - xlog_cxt->ThisTimeLineID = 0; - xlog_cxt->InRecovery = false; - xlog_cxt->standbyState = STANDBY_DISABLED; - xlog_cxt->LastRec = 0; - xlog_cxt->latestRecordCrc = 0; - xlog_cxt->lastFullPageWrites = false; - xlog_cxt->LocalRecoveryInProgress = true; - xlog_cxt->LocalHotStandbyActive = false; - xlog_cxt->LocalXLogInsertAllowed = -1; - xlog_cxt->ArchiveRecoveryRequested = false; - xlog_cxt->InArchiveRecovery = false; - xlog_cxt->ArchiveRestoreRequested = false; - xlog_cxt->restoredFromArchive = false; - xlog_cxt->recoveryRestoreCommand = NULL; - xlog_cxt->recoveryEndCommand = NULL; - xlog_cxt->archiveCleanupCommand = NULL; - xlog_cxt->recoveryTarget = RECOVERY_TARGET_UNSET; - xlog_cxt->recoveryTargetInclusive = true; - xlog_cxt->recoveryPauseAtTarget = true; - xlog_cxt->recoveryTargetXid = InvalidTransactionId; - xlog_cxt->recoveryTargetTime = 0; - xlog_cxt->obsRecoveryTargetTime = NULL; - xlog_cxt->recoveryTargetBarrierId = NULL; - xlog_cxt->recoveryTargetName = NULL; - xlog_cxt->recoveryTargetLSN = InvalidXLogRecPtr; - xlog_cxt->isRoachSingleReplayDone = false; - xlog_cxt->StandbyModeRequested = false; - xlog_cxt->PrimaryConnInfo = NULL; - xlog_cxt->TriggerFile = NULL; - xlog_cxt->StandbyMode = false; - xlog_cxt->recoveryTriggered = false; - xlog_cxt->recoveryStopXid = InvalidTransactionId; - xlog_cxt->recoveryStopTime = 0; - xlog_cxt->recoveryStopLSN = InvalidXLogRecPtr; + xlog_cxt->ThisTimeLineID = 0; // 褰撳墠鏃堕棿绾縄D + xlog_cxt->InRecovery = false; // 鏄惁澶勪簬鎭㈠鐘舵 + xlog_cxt->standbyState = STANDBY_DISABLED; // 绔欑偣鐘舵 + xlog_cxt->LastRec = 0; // 鏈鍚庤褰曚綅缃 + xlog_cxt->latestRecordCrc = 0; // 鏈鏂拌褰旵RC + xlog_cxt->lastFullPageWrites = false; // 涓婃鏄惁杩涜浜嗗畬鏁撮〉鍐欏叆 + xlog_cxt->LocalRecoveryInProgress = true; // 鏈湴鎭㈠鏄惁杩涜涓 + xlog_cxt->LocalHotStandbyActive = false; // 鏈湴鐑鏄惁婵娲 + xlog_cxt->LocalXLogInsertAllowed = -1; // 鏈湴XLOG鎻掑叆鏄惁鍏佽 + xlog_cxt->ArchiveRecoveryRequested = false; // 璇锋眰褰掓。鎭㈠鏍囧織 + xlog_cxt->InArchiveRecovery = false; // 鏄惁澶勪簬褰掓。鎭㈠涓 + xlog_cxt->ArchiveRestoreRequested = false; // 璇锋眰褰掓。鎭㈠鎭㈠鏍囧織 + xlog_cxt->restoredFromArchive = false; // 鏄惁浠庡綊妗d腑鎭㈠ + xlog_cxt->recoveryRestoreCommand = NULL; // 鎭㈠鎭㈠鍛戒护 + xlog_cxt->recoveryEndCommand = NULL; // 鎭㈠缁撴潫鍛戒护 + xlog_cxt->archiveCleanupCommand = NULL; // 褰掓。娓呯悊鍛戒护 + xlog_cxt->recoveryTarget = RECOVERY_TARGET_UNSET; // 鎭㈠鐩爣 + xlog_cxt->recoveryTargetInclusive = true; // 鎭㈠鐩爣鏄惁鍖呮嫭鍦ㄥ唴 + xlog_cxt->recoveryPauseAtTarget = true; // 鎭㈠鏃舵槸鍚﹀湪鐩爣浣嶇疆鏆傚仠 + xlog_cxt->recoveryTargetXid = InvalidTransactionId; // 鎭㈠鐩爣浜嬪姟ID + xlog_cxt->recoveryTargetTime = 0; // 鎭㈠鐩爣鏃堕棿 + xlog_cxt->obsRecoveryTargetTime = NULL; // OBS鎭㈠鐩爣鏃堕棿 + xlog_cxt->recoveryTargetBarrierId = NULL; // 鎭㈠鐩爣闅滅ID + xlog_cxt->recoveryTargetName = NULL; // 鎭㈠鐩爣鍚嶇О + xlog_cxt->recoveryTargetLSN = InvalidXLogRecPtr; // 鎭㈠鐩爣LSN + xlog_cxt->isRoachSingleReplayDone = false; // Roach鍗曚釜閲嶆斁鏄惁瀹屾垚 + xlog_cxt->StandbyModeRequested = false; // 璇锋眰澶囩敤妯″紡鏍囧織 + xlog_cxt->PrimaryConnInfo = NULL; // 涓绘満杩炴帴淇℃伅 + xlog_cxt->TriggerFile = NULL; // 瑙﹀彂鏂囦欢 + xlog_cxt->StandbyMode = false; // 澶囩敤妯″紡鏍囧織 + xlog_cxt->recoveryTriggered = false; // 鎭㈠鏄惁琚Е鍙 + xlog_cxt->recoveryStopXid = InvalidTransactionId; // 鎭㈠鍋滄浜嬪姟ID + xlog_cxt->recoveryStopTime = 0; // 鎭㈠鍋滄鏃堕棿 + xlog_cxt->recoveryStopLSN = InvalidXLogRecPtr; // 鎭㈠鍋滄LSN rc = memset_s(xlog_cxt->recoveryStopName, MAXFNAMELEN * sizeof(char), 0, MAXFNAMELEN * sizeof(char)); - securec_check(rc, "\0", "\0"); - xlog_cxt->recoveryStopAfter = false; - xlog_cxt->recoveryTargetTLI = 0; - xlog_cxt->recoveryTargetIsLatest = false; - xlog_cxt->expectedTLIs = NIL; - xlog_cxt->curFileTLI = 0; - xlog_cxt->ProcLastRecPtr = InvalidXLogRecPtr; - xlog_cxt->XactLastRecEnd = InvalidXLogRecPtr; - xlog_cxt->XactLastCommitEnd = InvalidXLogRecPtr; - xlog_cxt->RedoRecPtr = InvalidXLogRecPtr; - xlog_cxt->doPageWrites = false; - xlog_cxt->RedoStartLSN = InvalidXLogRecPtr; - xlog_cxt->server_mode = UNKNOWN_MODE; - xlog_cxt->is_cascade_standby = false; - xlog_cxt->is_hadr_main_standby = false; - xlog_cxt->startup_processing = false; - xlog_cxt->openLogFile = -1; - xlog_cxt->openLogSegNo = 0; - xlog_cxt->openLogOff = 0; - xlog_cxt->readFile = -1; - xlog_cxt->readSegNo = 0; - xlog_cxt->readOff = 0; - xlog_cxt->readLen = 0; - xlog_cxt->readSource = 0; - xlog_cxt->failedSources = 0; - xlog_cxt->XLogReceiptTime = 0; - xlog_cxt->XLogReceiptSource = 0; + securec_check(rc, "\0", "\0"); // 鍒濆鍖栨仮澶嶅仠姝㈠悕绉 + xlog_cxt->recoveryStopAfter = false; // 鎭㈠鍋滄涔嬪悗鏍囧織 + xlog_cxt->recoveryTargetTLI = 0; // 鎭㈠鐩爣鏃堕棿绾縄D + xlog_cxt->recoveryTargetIsLatest = false; // 鎭㈠鐩爣鏄惁鏄渶鏂扮殑 + xlog_cxt->expectedTLIs = NIL; // 棰勬湡鐨勬椂闂寸嚎ID鍒楄〃 + xlog_cxt->curFileTLI = 0; // 褰撳墠鏂囦欢鏃堕棿绾縄D + xlog_cxt->ProcLastRecPtr = InvalidXLogRecPtr; // 杩涚▼鏈鍚庤褰曚綅缃 + xlog_cxt->XactLastRecEnd = InvalidXLogRecPtr; // 浜嬪姟鏈鍚庤褰曠粨鏉熶綅缃 + xlog_cxt->XactLastCommitEnd = InvalidXLogRecPtr; // 浜嬪姟鏈鍚庢彁浜ょ粨鏉熶綅缃 + xlog_cxt->RedoRecPtr = InvalidXLogRecPtr; // 閲嶅仛璁板綍浣嶇疆 + xlog_cxt->doPageWrites = false; // 鏄惁杩涜椤靛啓鍏 + xlog_cxt->RedoStartLSN = InvalidXLogRecPtr; // 閲嶅仛寮濮婰SN + xlog_cxt->server_mode = UNKNOWN_MODE; // 鏈嶅姟鍣ㄦā寮 + xlog_cxt->is_cascade_standby = false; // 鏄惁鏄骇鑱斿鏈 + xlog_cxt->is_hadr_main_standby = false; // 鏄惁鏄疕ADR涓诲鏈 + xlog_cxt->startup_processing = false; // 鏄惁姝e湪杩涜鍚姩澶勭悊 + xlog_cxt->openLogFile = -1; // 鎵撳紑鐨勬棩蹇楁枃浠舵弿杩扮 + xlog_cxt->openLogSegNo = 0; // 鎵撳紑鐨勬棩蹇楁鍙 + xlog_cxt->openLogOff = 0; // 鎵撳紑鐨勬棩蹇楀亸绉婚噺 + xlog_cxt->readFile = -1; // 璇诲彇鐨勬棩蹇楁枃浠舵弿杩扮 + xlog_cxt->readSegNo = 0; // 璇诲彇鐨勬棩蹇楁鍙 + xlog_cxt->readOff = 0; // 璇诲彇鐨勬棩蹇楀亸绉婚噺 + xlog_cxt->readLen = 0; // 璇诲彇鐨勬棩蹇楅暱搴 + xlog_cxt->readSource = 0; // 璇诲彇鐨勬棩蹇楁潵婧 + xlog_cxt->failedSources = 0; // 澶辫触鐨勬棩蹇楁潵婧 + xlog_cxt->XLogReceiptTime = 0; // XLOG鎺ユ敹鏃堕棿 + xlog_cxt->XLogReceiptSource = 0; // XLOG鎺ユ敹鏉ユ簮 xlog_cxt->ReadRecPtr = 0; - xlog_cxt->EndRecPtr = 0; - xlog_cxt->minRecoveryPoint = 0; - xlog_cxt->updateMinRecoveryPoint = true; - xlog_cxt->reachedConsistency = false; - xlog_cxt->InRedo = false; - xlog_cxt->RedoDone = false; - xlog_cxt->bgwriterLaunched = false; - xlog_cxt->pagewriter_launched = false; - xlog_cxt->MyLockNo = 0; - xlog_cxt->holdingAllLocks = false; - xlog_cxt->lockToTry = -1; - xlog_cxt->cachedPage = 0; - xlog_cxt->cachedPos = NULL; #ifdef WIN32 - xlog_cxt->deletedcounter = 1; + xlog_cxt->deletedcounter = 1; // 鍒犻櫎璁℃暟鍣紙浠呴檺浜嶹indows骞冲彴锛 #endif - rc = memset_s(xlog_cxt->buf, STR_TIME_BUF_LEN, 0, STR_TIME_BUF_LEN); - securec_check(rc, "\0", "\0"); - xlog_cxt->receivedUpto = InvalidXLogRecPtr; - xlog_cxt->lastComplaint = InvalidXLogRecPtr; - xlog_cxt->failover_triggered = false; - xlog_cxt->switchover_triggered = false; - xlog_cxt->registered_buffers = NULL; - xlog_cxt->max_registered_buffers = 0; - xlog_cxt->max_registered_block_id = 0; - xlog_cxt->mainrdata_head = NULL; - xlog_cxt->mainrdata_last = NULL; - xlog_cxt->mainrdata_len = 0; - xlog_cxt->ptr_hdr_rdt = (XLogRecData*)palloc0(sizeof(XLogRecData)); - xlog_cxt->hdr_scratch = NULL; - xlog_cxt->rdatas = NULL; - xlog_cxt->num_rdatas = 0; - xlog_cxt->max_rdatas = 0; - xlog_cxt->begininsert_called = false; - xlog_cxt->include_origin = false; - xlog_cxt->xloginsert_cxt = NULL; - xlog_cxt->invalid_page_tab = NULL; - xlog_cxt->remain_segs = NULL; - xlog_cxt->sendId = 0; - xlog_cxt->sendFile = -1; - xlog_cxt->sendSegNo = 0; - xlog_cxt->sendOff = 0; - xlog_cxt->sendTLI = 0; - xlog_cxt->incomplete_actions = NIL; - xlog_cxt->gin_opCtx = NULL; - xlog_cxt->gist_opCtx = NULL; - xlog_cxt->spg_opCtx = NULL; - xlog_cxt->CheckpointStats = (CheckpointStatsData*)palloc0(sizeof(CheckpointStatsData)); - xlog_cxt->LogwrtResult = (XLogwrtResult*)palloc0(sizeof(XLogwrtResult)); - xlog_cxt->LogwrtPaxos = (XLogwrtPaxos*)palloc0(sizeof(XLogwrtPaxos)); - xlog_cxt->needImmediateCkp = false; - xlog_cxt->redoItemIdx = 0; + rc = memset_s(xlog_cxt->buf, STR_TIME_BUF_LEN, 0, STR_TIME_BUF_LEN); // 鍒濆鍖栫紦鍐插尯 + + securec_check(rc, "\0", "\0"); + + xlog_cxt->receivedUpto = InvalidXLogRecPtr; // 宸叉帴鏀剁殑XLOG璁板綍浣嶇疆 + xlog_cxt->lastComplaint = InvalidXLogRecPtr; // 涓婃鎶曡瘔鐨刋LOG璁板綍浣嶇疆 + xlog_cxt->failover_triggered = false; // 鏁呴殰鍒囨崲瑙﹀彂鏍囧織 + xlog_cxt->switchover_triggered = false; // 涓诲鍒囨崲瑙﹀彂鏍囧織 + xlog_cxt->registered_buffers = NULL; // 娉ㄥ唽鐨勭紦鍐插尯 + xlog_cxt->max_registered_buffers = 0; // 鏈澶ф敞鍐岀紦鍐插尯鏁 + xlog_cxt->max_registered_block_id = 0; // 鏈澶ф敞鍐屽潡ID + xlog_cxt->mainrdata_head = NULL; // 涓籜LOG璁板綍鏁版嵁澶撮儴 + xlog_cxt->mainrdata_last = NULL; // 涓籜LOG璁板綍鏁版嵁灏鹃儴 + xlog_cxt->mainrdata_len = 0; // 涓籜LOG璁板綍鏁版嵁闀垮害 + xlog_cxt->ptr_hdr_rdt = (XLogRecData*)palloc0(sizeof(XLogRecData)); // 璁板綍澶撮儴鏁版嵁鎸囬拡 + xlog_cxt->hdr_scratch = NULL; // 璁板綍澶撮儴涓存椂缂撳啿鍖 + xlog_cxt->rdatas = NULL; // XLOG璁板綍鏁版嵁 + xlog_cxt->num_rdatas = 0; // XLOG璁板綍鏁版嵁涓暟 + xlog_cxt->max_rdatas = 0; // 鏈澶LOG璁板綍鏁版嵁涓暟 + xlog_cxt->begininsert_called = false; // 鏄惁璋冪敤浜哹eginInsert鍑芥暟鏍囧織 + xlog_cxt->include_origin = false; // 鏄惁鍖呮嫭origin鏍囧織 + xlog_cxt->xloginsert_cxt = NULL; // XLOG鎻掑叆涓婁笅鏂 + xlog_cxt->invalid_page_tab = NULL; // 鏃犳晥椤甸潰琛 + xlog_cxt->remain_segs = NULL; // 鍓╀綑娈典俊鎭 + xlog_cxt->sendId = 0; // 鍙戦両D + xlog_cxt->sendFile = -1; // 鍙戦佹枃浠舵弿杩扮 + xlog_cxt->sendSegNo = 0; // 鍙戦佹鍙 + xlog_cxt->sendOff = 0; // 鍙戦佸亸绉婚噺 + xlog_cxt->sendTLI = 0; // 鍙戦佹椂闂寸嚎ID + xlog_cxt->incomplete_actions = NIL; // 涓嶅畬鏁存搷浣滃垪琛 + xlog_cxt->gin_opCtx = NULL; // GIN鎿嶄綔涓婁笅鏂 + xlog_cxt->gist_opCtx = NULL; // GIST鎿嶄綔涓婁笅鏂 + xlog_cxt->spg_opCtx = NULL; // SP-GiST鎿嶄綔涓婁笅鏂 + xlog_cxt->CheckpointStats = (CheckpointStatsData*)palloc0(sizeof(CheckpointStatsData)); // 妫鏌ョ偣缁熻淇℃伅 + xlog_cxt->LogwrtResult = (XLogwrtResult*)palloc0(sizeof(XLogwrtResult)); // XLOG鍐欏叆缁撴灉 + xlog_cxt->LogwrtPaxos = (XLogwrtPaxos*)palloc0(sizeof(XLogwrtPaxos)); // XLOG鍐欏叆Paxos + xlog_cxt->needImmediateCkp = false; // 鏄惁闇瑕佺珛鍗虫鏌ョ偣鏍囧織 + xlog_cxt->redoItemIdx = 0; // 閲嶅仛椤圭储寮 #ifndef ENABLE_MULTIPLE_NODES - xlog_cxt->committing_csn_list = NIL; + xlog_cxt->committing_csn_list = NIL; // 鎻愪氦鐨凜SN鍒楄〃锛堜粎闄愪簬鍗曡妭鐐规ā寮忥級 #endif - xlog_cxt->max_page_flush_lsn = MAX_XLOG_REC_PTR; - xlog_cxt->redoInterruptCallBackFunc = NULL; - xlog_cxt->redoPageRepairCallBackFunc = NULL; - xlog_cxt->xlog_atomic_op = NULL; - xlog_cxt->currentRetryTimes = 0; + xlog_cxt->max_page_flush_lsn = MAX_XLOG_REC_PTR; // 鏈澶ч〉鍒锋柊LSN + xlog_cxt->redoInterruptCallBackFunc = NULL; // 閲嶅仛涓柇鍥炶皟鍑芥暟 + xlog_cxt->redoPageRepairCallBackFunc = NULL; // 閲嶅仛椤甸潰淇鍥炶皟鍑芥暟 + xlog_cxt->xlog_atomic_op = NULL; // XLOG鍘熷瓙鎿嶄綔 + xlog_cxt->currentRetryTimes = 0; // 褰撳墠閲嶈瘯娆℃暟 } static void knl_t_index_init(knl_t_index_context* index_cxt) @@ -537,285 +543,289 @@ static void knl_t_dynahash_init(knl_t_dynahash_context* dyhash_cxt) static void knl_t_interrupt_init(knl_t_interrupt_context* int_cxt) { - int_cxt->QueryCancelPending = false; - int_cxt->PoolValidateCancelPending = false; - int_cxt->ProcDiePending = false; - int_cxt->ClientConnectionLost = false; - int_cxt->StreamConnectionLost = false; - int_cxt->ImmediateInterruptOK = false; - int_cxt->InterruptHoldoffCount = 0; - int_cxt->QueryCancelHoldoffCount = 0; - int_cxt->CritSectionCount = 0; - int_cxt->InterruptByCN = false; - int_cxt->InterruptCountResetFlag = false; - int_cxt->ignoreBackendSignal = false; + int_cxt->QueryCancelPending = false; // 鏌ヨ鍙栨秷鎸傝捣鏍囧織 + int_cxt->PoolValidateCancelPending = false; // 姹犻獙璇佸彇娑堟寕璧锋爣蹇 + int_cxt->ProcDiePending = false; // 杩涚▼閫鍑烘寕璧锋爣蹇 + int_cxt->ClientConnectionLost = false; // 瀹㈡埛绔繛鎺ヤ涪澶辨爣蹇 + int_cxt->StreamConnectionLost = false; // 娴佽繛鎺ヤ涪澶辨爣蹇 + int_cxt->ImmediateInterruptOK = false; // 绔嬪嵆涓柇鍏佽鏍囧織 + int_cxt->InterruptHoldoffCount = 0; // 涓柇淇濇寔璁℃暟 + int_cxt->QueryCancelHoldoffCount = 0; // 鏌ヨ鍙栨秷淇濇寔璁℃暟 + int_cxt->CritSectionCount = 0; // 涓寸晫鍖鸿鏁 + int_cxt->InterruptByCN = false; // 鐢盋N涓柇鏍囧織 + int_cxt->InterruptCountResetFlag = false; // 涓柇璁℃暟閲嶇疆鏍囧織 + int_cxt->ignoreBackendSignal = false; // 蹇界暐鍚庣淇″彿鏍囧織 } static void knl_t_proc_init(knl_t_proc_context* proc_cxt) { - proc_cxt->MyProgName = "unknown"; - proc_cxt->MyBackendId = InvalidBackendId; - proc_cxt->MyStartTime = 0; - proc_cxt->DataDir = NULL; - proc_cxt->postgres_initialized = false; - proc_cxt->PostInit = (PostgresInitializer*)New(CurrentMemoryContext) PostgresInitializer(); - proc_cxt->proc_exit_inprogress = false; - proc_cxt->sess_exit_inprogress = false; - proc_cxt->pooler_connection_inprogress = false; - proc_cxt->MyPMChildSlot = 0; + proc_cxt->MyProgName = "unknown"; // 杩涚▼鍚嶇О + proc_cxt->MyBackendId = InvalidBackendId; // 鍚庣ID + proc_cxt->MyStartTime = 0; // 杩涚▼鍚姩鏃堕棿 + proc_cxt->DataDir = NULL; // 鏁版嵁鐩綍 + proc_cxt->postgres_initialized = false; // PostgreSQL鍒濆鍖栨爣蹇 + proc_cxt->PostInit = (PostgresInitializer*)New(CurrentMemoryContext) PostgresInitializer(); // 鍚庡垵濮嬪寲瀵硅薄 + proc_cxt->proc_exit_inprogress = false; // 杩涚▼閫鍑鸿繘琛屼腑鏍囧織 + proc_cxt->sess_exit_inprogress = false; // 浼氳瘽閫鍑鸿繘琛屼腑鏍囧織 + proc_cxt->pooler_connection_inprogress = false; // 杩炴帴姹犺繛鎺ヨ繘琛屼腑鏍囧織 + proc_cxt->MyPMChildSlot = 0; // 杩涚▼绠$悊鍣ㄥ瓙杩涚▼妲戒綅 } static void knl_t_wlm_init(knl_t_wlmthrd_context* wlm_cxt) { - wlm_cxt->thread_node_group = NULL; - wlm_cxt->thread_climgr = NULL; - wlm_cxt->thread_srvmgr = NULL; - wlm_cxt->wlm_got_sighup = 0; - wlm_cxt->wlmalarm_pending = false; - wlm_cxt->wlmalarm_timeout_active = false; - wlm_cxt->wlmalarm_dump_active = false; - wlm_cxt->wlm_xact_start = false; - wlm_cxt->has_cursor_record = false; - wlm_cxt->wlmalarm_fin_time = 0; - wlm_cxt->MaskPasswordMemoryContext = NULL; - wlm_cxt->query_resource_track_mcxt = NULL; + wlm_cxt->thread_node_group = NULL; // 鑺傜偣缁勭嚎绋 + wlm_cxt->thread_climgr = NULL; // 瀹㈡埛绔鐞嗙嚎绋 + wlm_cxt->thread_srvmgr = NULL; // 鏈嶅姟绠$悊绾跨▼ + wlm_cxt->wlm_got_sighup = 0; // WLM鏀跺埌SIGHUP淇″彿璁℃暟 + wlm_cxt->wlmalarm_pending = false; // WLM鍛婅鎸傝捣鏍囧織 + wlm_cxt->wlmalarm_timeout_active = false; // WLM鍛婅瓒呮椂娲昏穬鏍囧織 + wlm_cxt->wlmalarm_dump_active = false; // WLM鍛婅杞偍娲昏穬鏍囧織 + wlm_cxt->wlm_xact_start = false; // WLM浜嬪姟鍚姩鏍囧織 + wlm_cxt->has_cursor_record = false; // 鏄惁鏈夋父鏍囪褰曟爣蹇 + wlm_cxt->wlmalarm_fin_time = 0; // WLM鍛婅缁撴潫鏃堕棿 + wlm_cxt->MaskPasswordMemoryContext = NULL; // 閬斀瀵嗙爜鍐呭瓨涓婁笅鏂 + wlm_cxt->query_resource_track_mcxt = NULL; // 鏌ヨ璧勬簮杩借釜鍐呭瓨涓婁笅鏂 - wlm_cxt->except_ctl = (ExceptionManager*)palloc0(sizeof(ExceptionManager)); - wlm_cxt->collect_info = (WLMCollectInfo*)palloc0(sizeof(WLMCollectInfo)); - wlm_cxt->dn_cpu_detail = (WLMDNRealTimeInfoDetail*)palloc0(sizeof(WLMDNRealTimeInfoDetail)); + wlm_cxt->except_ctl = (ExceptionManager*)palloc0(sizeof(ExceptionManager)); // 寮傚父绠$悊鍣 + wlm_cxt->collect_info = (WLMCollectInfo*)palloc0(sizeof(WLMCollectInfo)); // WLM閲囬泦淇℃伅 + wlm_cxt->dn_cpu_detail = (WLMDNRealTimeInfoDetail*)palloc0(sizeof(WLMDNRealTimeInfoDetail)); // DN CPU璇︾粏淇℃伅 } static void knl_t_audit_init(knl_t_audit_context* audit) { - audit->audit_indextbl = NULL; - audit->sysauditFile = NULL; - audit->policyauditFile = NULL; - audit->Audit_delete = false; - audit->pipe_eof_seen = false; - audit->rotation_disabled = false; - audit->pgaudit_totalspace = 0; - audit->user_login_time = 0; - audit->need_exit = false; - audit->got_SIGHUP = false; - audit->rotation_requested = false; - audit->space_beyond_size = (10 * 1024 * 1024); - audit->pgaudit_filepath[0] = '\0'; - audit->cur_thread_idx = -1; + audit->audit_indextbl = NULL; // 瀹¤绱㈠紩琛 + audit->sysauditFile = NULL; // 绯荤粺瀹¤鏂囦欢 + audit->policyauditFile = NULL; // 绛栫暐瀹¤鏂囦欢 + audit->Audit_delete = false; // 瀹¤鍒犻櫎鏍囧織 + audit->pipe_eof_seen = false; // 绠¢亾缁撴潫鏍囧織 + audit->rotation_disabled = false; // 鏃嬭浆绂佺敤鏍囧織 + audit->pgaudit_totalspace = 0; // Pgaudit鎬荤┖闂 + audit->user_login_time = 0; // 鐢ㄦ埛鐧诲綍鏃堕棿 + audit->need_exit = false; // 闇瑕侀鍑烘爣蹇 + audit->got_SIGHUP = false; // 鏀跺埌SIGHUP淇″彿鏍囧織 + audit->rotation_requested = false; // 鏃嬭浆璇锋眰鏍囧織 + audit->space_beyond_size = (10 * 1024 * 1024); // 瓒呰繃绌洪棿澶у皬 + audit->pgaudit_filepath[0] = '\0'; // Pgaudit鏂囦欢璺緞 + audit->cur_thread_idx = -1; // 褰撳墠绾跨▼绱㈠紩 } static void knl_t_async_init(knl_t_async_context* asy_cxt) { - asy_cxt->listenChannels = NIL; - asy_cxt->pendingActions = NIL; - asy_cxt->upperPendingActions = NIL; - asy_cxt->pendingNotifies = NIL; - asy_cxt->upperPendingNotifies = NIL; - asy_cxt->unlistenExitRegistered = false; - asy_cxt->amRegisteredListener = false; - asy_cxt->backendHasSentNotifications = false; + asy_cxt->listenChannels = NIL; // 鐩戝惉閫氶亾鍒楄〃 + asy_cxt->pendingActions = NIL; // 寰呭鐞嗗姩浣滃垪琛 + asy_cxt->upperPendingActions = NIL; // 涓婂眰寰呭鐞嗗姩浣滃垪琛 + asy_cxt->pendingNotifies = NIL; // 寰呴氱煡鍒楄〃 + asy_cxt->upperPendingNotifies = NIL; // 涓婂眰寰呴氱煡鍒楄〃 + asy_cxt->unlistenExitRegistered = false; // 娉ㄥ唽閫鍑虹洃鍚爣蹇 + asy_cxt->amRegisteredListener = false; // 娉ㄥ唽鐩戝惉鍣ㄦ爣蹇 + asy_cxt->backendHasSentNotifications = false; // 鍚庣鍙戦侀氱煡鏍囧織 } static void knl_t_explain_init(knl_t_explain_context* explain_cxt) { - explain_cxt->explain_light_proxy = false; + explain_cxt->explain_light_proxy = false; // 杞婚噺绾т唬鐞嗚В閲婃爣蹇 } static void knl_t_vacuum_init(knl_t_vacuum_context* vacuum_cxt) { - vacuum_cxt->VacuumPageHit = 0; - vacuum_cxt->VacuumPageMiss = 0; - vacuum_cxt->VacuumPageDirty = 0; - vacuum_cxt->VacuumCostBalance = 0; - vacuum_cxt->VacuumCostActive = false; - vacuum_cxt->vacuum_full_compact = false; - vacuum_cxt->vac_context = NULL; - vacuum_cxt->in_vacuum = false; + vacuum_cxt->VacuumPageHit = 0; // VACUUM椤甸潰鍛戒腑璁℃暟 + vacuum_cxt->VacuumPageMiss = 0; // VACUUM椤甸潰涓㈠け璁℃暟 + vacuum_cxt->VacuumPageDirty = 0; // VACUUM鑴忛〉闈㈣鏁 + vacuum_cxt->VacuumCostBalance = 0; // VACUUM鎴愭湰骞宠  + vacuum_cxt->VacuumCostActive = false; // VACUUM鎴愭湰婵娲绘爣蹇 + vacuum_cxt->vacuum_full_compact = false; // VACUUM鍏ㄩ噺绱у噾鏍囧織 + vacuum_cxt->vac_context = NULL; // VACUUM鍐呭瓨涓婁笅鏂 + vacuum_cxt->in_vacuum = false; // VACUUM杩涜涓爣蹇 } static void knl_t_arch_init(knl_t_arch_context* arch) { - arch->got_SIGHUP = false; - arch->got_SIGTERM = false; - arch->wakened = false; - arch->ready_to_stop = false; - arch->last_sigterm_time = 0; - arch->pitr_task_last_lsn = 0; - arch->task_wait_interval = 1000; - arch->last_arch_time = 0; - arch->arch_start_timestamp = 0; - arch->arch_start_lsn = InvalidXLogRecPtr; - arch->sync_walsender_idx = -1; + arch->got_SIGHUP = false; // 鏀跺埌SIGHUP淇″彿鏍囧織 + arch->got_SIGTERM = false; // 鏀跺埌SIGTERM淇″彿鏍囧織 + arch->wakened = false; // 鍞ら啋鏍囧織 + arch->ready_to_stop = false; // 鍑嗗鍋滄鏍囧織 + arch->last_sigterm_time = 0; // 涓婃SIGTERM鏃堕棿 + arch->pitr_task_last_lsn = 0; // PITR浠诲姟涓婃LSN + arch->task_wait_interval = 1000; // 浠诲姟绛夊緟闂撮殧 + arch->last_arch_time = 0; // 涓婃褰掓。鏃堕棿 + arch->arch_start_timestamp = 0; // 褰掓。寮濮嬫椂闂存埑 + arch->arch_start_lsn = InvalidXLogRecPtr; // 褰掓。寮濮婰SN + arch->sync_walsender_idx = -1; // 鍚屾WAL鍙戦佽呯储寮 #ifndef ENABLE_MULTIPLE_NODES - arch->sync_follower_id = -1; + arch->sync_follower_id = -1; // 鍚屾Follower ID #endif } -static void knl_t_barrier_arch_init(knl_t_barrier_arch_context* barrier_arch) +static void knl_t_audit_init(knl_t_audit_context* audit) { - barrier_arch->got_SIGHUP = false; - barrier_arch->got_SIGTERM = false; - barrier_arch->wakened = false; - barrier_arch->ready_to_stop = false; - barrier_arch->slot_name = NULL; - barrier_arch->lastArchiveLoc = InvalidXLogRecPtr; + audit->audit_indextbl = NULL; // 瀹¤绱㈠紩琛 + audit->sysauditFile = NULL; // 绯荤粺瀹¤鏂囦欢 + audit->policyauditFile = NULL; // 绛栫暐瀹¤鏂囦欢 + audit->Audit_delete = false; // 瀹¤鍒犻櫎鏍囧織 + audit->pipe_eof_seen = false; // 绠¢亾缁撴潫鏍囧織 + audit->rotation_disabled = false; // 鏃嬭浆绂佺敤鏍囧織 + audit->pgaudit_totalspace = 0; // Pgaudit鎬荤┖闂 + audit->user_login_time = 0; // 鐢ㄦ埛鐧诲綍鏃堕棿 + audit->need_exit = false; // 闇瑕侀鍑烘爣蹇 + audit->got_SIGHUP = false; // 鏀跺埌SIGHUP淇″彿鏍囧織 + audit->rotation_requested = false; // 鏃嬭浆璇锋眰鏍囧織 + audit->space_beyond_size = (10 * 1024 * 1024); // 瓒呰繃绌洪棿澶у皬 + audit->pgaudit_filepath[0] = '\0'; // Pgaudit鏂囦欢璺緞 + audit->cur_thread_idx = -1; // 褰撳墠绾跨▼绱㈠紩 } - -static void knl_t_logger_init(knl_t_logger_context* logger) +static void knl_t_async_init(knl_t_async_context* asy_cxt) { - logger->pipe_eof_seen = false; - logger->rotation_disabled = false; - logger->syslogFile = NULL; - logger->csvlogFile = NULL; - logger->querylogFile = NULL; - logger->asplogFile = NULL; - logger->first_syslogger_file_time = 0; - logger->last_file_name = NULL; - logger->last_csv_file_name = NULL; - logger->last_asp_file_name = NULL; - logger->got_SIGHUP = false; - logger->rotation_requested = false; + asy_cxt->listenChannels = NIL; // 鐩戝惉閫氶亾鍒楄〃 + asy_cxt->pendingActions = NIL; // 寰呭鐞嗗姩浣滃垪琛 + asy_cxt->upperPendingActions = NIL; // 涓婂眰寰呭鐞嗗姩浣滃垪琛 + asy_cxt->pendingNotifies = NIL; // 寰呴氱煡鍒楄〃 + asy_cxt->upperPendingNotifies = NIL; // 涓婂眰寰呴氱煡鍒楄〃 + asy_cxt->unlistenExitRegistered = false; // 娉ㄥ唽閫鍑虹洃鍚爣蹇 + asy_cxt->amRegisteredListener = false; // 娉ㄥ唽鐩戝惉鍣ㄦ爣蹇 + asy_cxt->backendHasSentNotifications = false; // 鍚庣鍙戦侀氱煡鏍囧織 } -static void knl_t_bulkload_init(knl_t_bulkload_context* bulk_cxt) +static void knl_t_explain_init(knl_t_explain_context* explain_cxt) { - int rc = 0; - - rc = memset_s(bulk_cxt->distExportDataDir, MAX_PATH_LEN, 0, MAX_PATH_LEN); - securec_check(rc, "\0", "\0"); - rc = memset_s(bulk_cxt->distExportTimestampStr, TIME_STAMP_STR_LEN, 0, TIME_STAMP_STR_LEN); - securec_check(rc, "\0", "\0"); - - bulk_cxt->distExportCurrXid = 0; - bulk_cxt->distExportNextSegNo = 0; - bulk_cxt->illegal_character_err_cnt = 0; - bulk_cxt->illegal_character_err_threshold_reported = false; + explain_cxt->explain_light_proxy = false; // 杞婚噺绾т唬鐞嗚В閲婃爣蹇 } -static void knl_t_job_init(knl_t_job_context* job_cxt) +static void knl_t_vacuum_init(knl_t_vacuum_context* vacuum_cxt) { - job_cxt->JobScheduleShmem = NULL; - job_cxt->got_SIGHUP = false; - job_cxt->got_SIGUSR2 = false; - job_cxt->got_SIGTERM = false; - job_cxt->JobScheduleMemCxt = NULL; - job_cxt->ExpiredJobList = NULL; - job_cxt->ExpiredJobListCtx = NULL; - job_cxt->MyWorkerInfo = NULL; + vacuum_cxt->VacuumPageHit = 0; // VACUUM椤甸潰鍛戒腑璁℃暟 + vacuum_cxt->VacuumPageMiss = 0; // VACUUM椤甸潰涓㈠け璁℃暟 + vacuum_cxt->VacuumPageDirty = 0; // VACUUM鑴忛〉闈㈣鏁 + vacuum_cxt->VacuumCostBalance = 0; // VACUUM鎴愭湰骞宠  + vacuum_cxt->VacuumCostActive = false; // VACUUM鎴愭湰婵娲绘爣蹇 + vacuum_cxt->vacuum_full_compact = false; // VACUUM鍏ㄩ噺绱у噾鏍囧織 + vacuum_cxt->vac_context = NULL; // VACUUM鍐呭瓨涓婁笅鏂 + vacuum_cxt->in_vacuum = false; // VACUUM杩涜涓爣蹇 } -static void knl_t_basebackup_init(knl_t_basebackup_context* basebackup_cxt) +static void knl_t_arch_init(knl_t_arch_context* arch) { - int rc = memset_s(basebackup_cxt->g_xlog_location, MAXPGPATH, 0, MAXPGPATH); - securec_check(rc, "\0", "\0"); - basebackup_cxt->buf_block = NULL; + arch->got_SIGHUP = false; // 鏀跺埌SIGHUP淇″彿鏍囧織 + arch->got_SIGTERM = false; // 鏀跺埌SIGTERM淇″彿鏍囧織 + arch->wakened = false; // 鍞ら啋鏍囧織 + arch->ready_to_stop = false; // 鍑嗗鍋滄鏍囧織 + arch->last_sigterm_time = 0; // 涓婃SIGTERM鏃堕棿 + arch->pitr_task_last_lsn = 0; // PITR浠诲姟涓婃LSN + arch->task_wait_interval = 1000; // 浠诲姟绛夊緟闂撮殧 + arch->last_arch_time = 0; // 涓婃褰掓。鏃堕棿 + arch->arch_start_timestamp = 0; // 褰掓。寮濮嬫椂闂存埑 + arch->arch_start_lsn = InvalidXLogRecPtr; // 褰掓。寮濮婰SN + arch->sync_walsender_idx = -1; // 鍚屾WAL鍙戦佽呯储寮 +#ifndef ENABLE_MULTIPLE_NODES + arch->sync_follower_id = -1; // 鍚屾Follower ID +#endif } static void knl_t_datarcvwriter_init(knl_t_datarcvwriter_context* datarcvwriter_cxt) { - datarcvwriter_cxt->data_writer_rel_tab = NULL; - datarcvwriter_cxt->dataRcvWriterFlushPageErrorCount = 0; - datarcvwriter_cxt->gotSIGHUP = false; - datarcvwriter_cxt->shutdownRequested = false; - datarcvwriter_cxt->AmDataReceiverForDummyStandby = false; - datarcvwriter_cxt->dummy_data_writer_file_num = 0; + datarcvwriter_cxt->data_writer_rel_tab = NULL; // 鏁版嵁鍐欏叆鍏崇郴琛 + datarcvwriter_cxt->dataRcvWriterFlushPageErrorCount = 0; // 鏁版嵁鎺ユ敹鍐欏叆鍒锋柊椤甸潰閿欒璁℃暟 + datarcvwriter_cxt->gotSIGHUP = false; // 鏀跺埌SIGHUP淇″彿鏍囧織 + datarcvwriter_cxt->shutdownRequested = false; // 鍏虫満璇锋眰鏍囧織 + datarcvwriter_cxt->AmDataReceiverForDummyStandby = false; // 鏄惁涓鸿櫄鎷熷鑺傜偣鐨勬暟鎹帴鏀惰呮爣蹇 + datarcvwriter_cxt->dummy_data_writer_file_num = 0; // 铏氭嫙澶囪妭鐐规暟鎹啓鍏ユ枃浠舵暟鐩 } static void knl_t_libwalreceiver_init(knl_t_libwalreceiver_context* libwalreceiver_cxt) { - libwalreceiver_cxt->streamConn = NULL; - libwalreceiver_cxt->recvBuf = NULL; - libwalreceiver_cxt->shared_storage_buf = NULL; - libwalreceiver_cxt->shared_storage_read_buf = NULL; - libwalreceiver_cxt->decompressBuf = NULL; - libwalreceiver_cxt->xlogreader = NULL; + libwalreceiver_cxt->streamConn = NULL; // 娴佽繛鎺 + libwalreceiver_cxt->recvBuf = NULL; // 鎺ユ敹缂撳啿鍖 + libwalreceiver_cxt->shared_storage_buf = NULL; // 鍏变韩瀛樺偍缂撳啿鍖 + libwalreceiver_cxt->shared_storage_read_buf = NULL; // 鍏变韩瀛樺偍璇诲彇缂撳啿鍖 + libwalreceiver_cxt->decompressBuf = NULL; // 瑙e帇缂╃紦鍐插尯 + libwalreceiver_cxt->xlogreader = NULL; // xlog璇诲彇鍣 } static void knl_t_sig_init(knl_t_sig_context* sig_cxt) { - sig_cxt->signal_handle_cnt = 0; - sig_cxt->gs_sigale_check_type = SIGNAL_CHECK_NONE; - sig_cxt->session_id = 0; - sig_cxt->cur_ctrl_index = 0; + sig_cxt->signal_handle_cnt = 0; // 淇″彿澶勭悊璁℃暟 + sig_cxt->gs_sigale_check_type = SIGNAL_CHECK_NONE; // 淇″彿妫鏌ョ被鍨 + sig_cxt->session_id = 0; // 浼氳瘽ID + sig_cxt->cur_ctrl_index = 0; // 褰撳墠鎺у埗绱㈠紩 } static void knl_t_slot_init(knl_t_slot_context* slot_cxt) { - slot_cxt->ReplicationSlotCtl = NULL; - slot_cxt->MyReplicationSlot = NULL; + slot_cxt->ReplicationSlotCtl = NULL; // 澶嶅埗鎻掓Ы鎺у埗淇℃伅 + slot_cxt->MyReplicationSlot = NULL; // 褰撳墠澶嶅埗鎻掓Ы } static void knl_t_datareceiver_init(knl_t_datareceiver_context* datareceiver_cxt) { - datareceiver_cxt->DataReplFlag = 1; - datareceiver_cxt->got_SIGHUP = false; - datareceiver_cxt->got_SIGTERM = false; - datareceiver_cxt->reply_message = (StandbyDataReplyMessage*)palloc0(sizeof(StandbyDataReplyMessage)); - datareceiver_cxt->dataStreamingConn = NULL; - datareceiver_cxt->AmDataReceiverForDummyStandby = false; - datareceiver_cxt->recvBuf = NULL; - datareceiver_cxt->DataRcv = NULL; - datareceiver_cxt->DataRcvImmediateInterruptOK = false; + datareceiver_cxt->DataReplFlag = 1; // 鏁版嵁澶嶅埗鏍囧織 + datareceiver_cxt->got_SIGHUP = false; // 鏀跺埌SIGHUP淇″彿鏍囧織 + datareceiver_cxt->got_SIGTERM = false; // 鏀跺埌SIGTERM淇″彿鏍囧織 + datareceiver_cxt->reply_message = (StandbyDataReplyMessage*)palloc0(sizeof(StandbyDataReplyMessage)); // 鍥炲娑堟伅 + datareceiver_cxt->dataStreamingConn = NULL; // 鏁版嵁娴佽繛鎺 + datareceiver_cxt->AmDataReceiverForDummyStandby = false; // 鏄惁涓鸿櫄鎷熷鑺傜偣鐨勬暟鎹帴鏀惰呮爣蹇 + datareceiver_cxt->recvBuf = NULL; // 鎺ユ敹缂撳啿鍖 + datareceiver_cxt->DataRcv = NULL; // 鏁版嵁鎺ユ敹鍣 + datareceiver_cxt->DataRcvImmediateInterruptOK = false; // 鏁版嵁鎺ユ敹鍣ㄧ珛鍗充腑鏂爣蹇 } static void knl_t_datasender_init(knl_t_datasender_context* datasender_cxt) { - datasender_cxt->DataSndCtl = NULL; - datasender_cxt->MyDataSnd = NULL; - datasender_cxt->am_datasender = false; - datasender_cxt->reply_message = (StringInfoData*)palloc0(sizeof(StringInfoData)); - datasender_cxt->output_message = NULL; - datasender_cxt->dummy_data_read_file_num = 1; - datasender_cxt->dummy_data_read_file_fd = NULL; - datasender_cxt->ping_sent = false; - datasender_cxt->got_SIGHUP = false; - datasender_cxt->datasender_shutdown_requested = false; - datasender_cxt->datasender_ready_to_stop = false; + datasender_cxt->DataSndCtl = NULL; // 鏁版嵁鍙戦佹帶鍒朵俊鎭 + datasender_cxt->MyDataSnd = NULL; // 褰撳墠鏁版嵁鍙戦佽妭鐐 + datasender_cxt->am_datasender = false; // 鏄惁涓烘暟鎹彂閫佽呮爣蹇 + datasender_cxt->reply_message = (StringInfoData*)palloc0(sizeof(StringInfoData)); // 鍥炲娑堟伅 + datasender_cxt->output_message = NULL; // 杈撳嚭娑堟伅 + datasender_cxt->dummy_data_read_file_num = 1; // 铏氭嫙鏁版嵁璇诲彇鏂囦欢鏁扮洰 + datasender_cxt->dummy_data_read_file_fd = NULL; // 铏氭嫙鏁版嵁璇诲彇鏂囦欢鎻忚堪绗 + datasender_cxt->ping_sent = false; // 鍙戦乸ing娑堟伅鏍囧織 + datasender_cxt->got_SIGHUP = false; // 鏀跺埌SIGHUP淇″彿鏍囧織 + datasender_cxt->datasender_shutdown_requested = false; // 鏁版嵁鍙戦佸櫒鍏虫満璇锋眰鏍囧織 + datasender_cxt->datasender_ready_to_stop = false; // 鏁版嵁鍙戦佸櫒鍑嗗鍋滄鏍囧織 } static void knl_t_walreceiverfuncs_init(knl_t_walreceiverfuncs_context* walreceiverfuncs_cxt) { - walreceiverfuncs_cxt->WalRcv = NULL; - walreceiverfuncs_cxt->WalReplIndex = 1; + walreceiverfuncs_cxt->WalRcv = NULL; // WAL鎺ユ敹鍣 + walreceiverfuncs_cxt->WalReplIndex = 1; // WAL澶嶅埗绱㈠紩 } static void knl_t_replgram_init(knl_t_replgram_context* replgram_cxt) { - replgram_cxt->replication_parse_result = NULL; + replgram_cxt->replication_parse_result = NULL; // 澶嶅埗瑙f瀽缁撴灉 } static void knl_t_replscanner_init(knl_t_replscanner_context* replscanner_cxt) { - replscanner_cxt->scanbufhandle = NULL; - replscanner_cxt->litbuf = (StringInfoData*)palloc0(sizeof(StringInfoData)); + replscanner_cxt->scanbufhandle = NULL; // 鎵弿缂撳啿鍖哄彞鏌 + replscanner_cxt->litbuf = (StringInfoData*)palloc0(sizeof(StringInfoData)); // 鏂囨湰缂撳啿鍖 } static void knl_t_syncgram_init(knl_t_syncrepgram_context* syncrepgram_cxt) { - syncrepgram_cxt->syncrep_parse_result = NIL; + syncrepgram_cxt->syncrep_parse_result = NIL; // 鍚屾澶嶅埗瑙f瀽缁撴灉 } static void knl_t_syncrepscanner_init(knl_t_syncrepscanner_context* syncrepscanner_cxt) { - syncrepscanner_cxt->scanbufhandle = NULL; - syncrepscanner_cxt->xdbuf = (StringInfoData*)palloc0(sizeof(StringInfoData)); - syncrepscanner_cxt->result = 1; + syncrepscanner_cxt->scanbufhandle = NULL; // 鎵弿缂撳啿鍖哄彞鏌 + syncrepscanner_cxt->xdbuf = (StringInfoData*)palloc0(sizeof(StringInfoData)); // 鎵╁睍鏁版嵁缂撳啿鍖 + syncrepscanner_cxt->result = 1; // 瑙f瀽缁撴灉 } static void knl_t_syncrep_init(knl_t_syncrep_context* syncrep_cxt) { - syncrep_cxt->SyncRepConfig = NULL; - syncrep_cxt->SyncRepConfigGroups = 0; - syncrep_cxt->SyncRepMaxPossib = 0; - syncrep_cxt->announce_next_takeover = true; + syncrep_cxt->SyncRepConfig = NULL; // 鍚屾澶嶅埗閰嶇疆淇℃伅 + syncrep_cxt->SyncRepConfigGroups = 0; // 鍚屾澶嶅埗閰嶇疆缁勬暟 + syncrep_cxt->SyncRepMaxPossib = 0; // 鍚屾澶嶅埗鏈澶у彲鑳芥暟 + syncrep_cxt->announce_next_takeover = true; // 瀹e竷涓嬫鎺ョ鏍囧織 } static void knl_t_logical_init(knl_t_logical_context* logical_cxt) { - logical_cxt->sendFd = -1; - logical_cxt->sendSegNo = 0; - logical_cxt->sendOff = 0; - logical_cxt->ExportInProgress = false; + logical_cxt->sendFd = -1; // 鍙戦佹枃浠舵弿杩扮 + logical_cxt->sendSegNo = 0; // 鍙戦佹鍙 + logical_cxt->sendOff = 0; // 鍙戦佸亸绉婚噺 + logical_cxt->ExportInProgress = false; // 瀵煎嚭杩涜涓爣蹇 } #define BCMElementArrayLen 8192 @@ -844,180 +854,185 @@ static void knl_t_walrcvwriter_init(knl_t_walrcvwriter_context* walrcvwriter_cxt static void knl_t_postgres_init(knl_t_postgres_context* postgres_cxt) { - postgres_cxt->clear_key_memory = false; - postgres_cxt->table_created_in_CTAS = false; - postgres_cxt->debug_query_string = NULL; - postgres_cxt->isInResetUserName = false; - postgres_cxt->whereToSendOutput = DestDebug; - postgres_cxt->local_foreign_respool = NULL; - postgres_cxt->max_stack_depth_bytes = 100 * 1024L; - postgres_cxt->password_changed = false; - postgres_cxt->stack_base_ptr = NULL; - postgres_cxt->xact_started = false; - postgres_cxt->DoingCommandRead = false; - postgres_cxt->userDoption = NULL; - postgres_cxt->EchoQuery = false; + postgres_cxt->clear_key_memory = false; // 娓呴櫎鍏抽敭鍐呭瓨鏍囧織 + postgres_cxt->table_created_in_CTAS = false; // 鍦–REATE TABLE AS涓垱寤虹殑琛ㄦ爣蹇 + postgres_cxt->debug_query_string = NULL; // 璋冭瘯鏌ヨ瀛楃涓 + postgres_cxt->isInResetUserName = false; // 閲嶇疆鐢ㄦ埛鍚嶆爣蹇 + postgres_cxt->whereToSendOutput = DestDebug; // 杈撳嚭鐩爣璁剧疆涓鸿皟璇 + postgres_cxt->local_foreign_respool = NULL; // 鏈湴澶栭儴璧勬簮姹 + postgres_cxt->max_stack_depth_bytes = 100 * 1024L; // 鏈澶у爢鏍堟繁搴︼紙瀛楄妭锛 + postgres_cxt->password_changed = false; // 瀵嗙爜宸叉洿鏀规爣蹇 + postgres_cxt->stack_base_ptr = NULL; // 鍫嗘爤鍩烘寚閽 + postgres_cxt->xact_started = false; // 浜嬪姟宸插惎鍔ㄦ爣蹇 + postgres_cxt->DoingCommandRead = false; // 鍛戒护璇诲彇涓爣蹇 + postgres_cxt->userDoption = NULL; // 鐢ㄦ埛閫夐」 + postgres_cxt->EchoQuery = false; // 鍥炴樉鏌ヨ鏍囧織 + #ifndef TCOP_DONTUSENEWLINE - postgres_cxt->UseNewLine = 1; /* Use newlines query delimiters (the default) */ + postgres_cxt->UseNewLine = 1; /* 浣跨敤鎹㈣绗︿綔涓烘煡璇㈠垎闅旂锛堥粯璁わ級 */ #else - postgres_cxt->UseNewLine = 0; /* Use EOF as query delimiters */ + postgres_cxt->UseNewLine = 0; /* 浣跨敤EOF浣滀负鏌ヨ鍒嗛殧绗 */ #endif /* TCOP_DONTUSENEWLINE */ - postgres_cxt->RecoveryConflictPending = false; - postgres_cxt->RecoveryConflictRetryable = true; - postgres_cxt->row_description_buf = (StringInfoData*)palloc0(sizeof(StringInfoData)); + postgres_cxt->RecoveryConflictPending = false; // 鎭㈠鍐茬獊鎸傝捣鏍囧織 + postgres_cxt->RecoveryConflictRetryable = true; // 鎭㈠鍐茬獊鍙噸璇曟爣蹇 - postgres_cxt->clobber_qstr = NULL; - postgres_cxt->query_result = 0; - postgres_cxt->g_NoAnalyzeRelNameList = NULL; - postgres_cxt->mark_explain_analyze = false; - postgres_cxt->mark_explain_only = false; - postgres_cxt->enable_explicit_stmt_name = false; - postgres_cxt->val = 0; + postgres_cxt->row_description_buf = (StringInfoData*)palloc0(sizeof(StringInfoData)); // 琛屾弿杩颁俊鎭紦鍐插尯 - postgres_cxt->gpc_fisrt_send_clean = true; + postgres_cxt->clobber_qstr = NULL; // 瑕嗙洊鐨勬煡璇㈠瓧绗︿覆 + postgres_cxt->query_result = 0; // 鏌ヨ缁撴灉 + postgres_cxt->g_NoAnalyzeRelNameList = NULL; // 涓嶅垎鏋愮殑鍏崇郴鍚嶇О鍒楄〃 + postgres_cxt->mark_explain_analyze = false; // 鏍囪鎵ц瑙i噴鍒嗘瀽璁″垝 + postgres_cxt->mark_explain_only = false; // 鏍囪鍙墽琛岃В閲婅鍒 + postgres_cxt->enable_explicit_stmt_name = false; // 鍚敤鏄剧ず璇彞鍚嶇О + postgres_cxt->val = 0; // 鍊 + + postgres_cxt->gpc_fisrt_send_clean = true; // GPC棣栨鍙戦佹竻鐞嗘爣蹇 } static void knl_t_utils_init(knl_t_utils_context* utils_cxt) { - utils_cxt->mctx_sequent_count = 0; - utils_cxt->ExecutorMemoryTrack = NULL; -#ifdef MEMORY_CONTEXT_CHECKING - utils_cxt->memory_track_sequent_count = -1; - utils_cxt->memory_track_plan_nodeid = -1; + utils_cxt->mctx_sequent_count = 0; // 鍐呭瓨涓婁笅鏂囬『搴忚鏁 + utils_cxt->ExecutorMemoryTrack = NULL; // 鎵ц鍣ㄥ唴瀛樿拷韪 - utils_cxt->detailTrackingBuf = (StringInfoData*)palloc0(sizeof(StringInfoData)); +#ifdef MEMORY_CONTEXT_CHECKING + utils_cxt->memory_track_sequent_count = -1; // 鍐呭瓨杩借釜椤哄簭璁℃暟 + utils_cxt->memory_track_plan_nodeid = -1; // 鍐呭瓨杩借釜璁″垝鑺傜偣ID + + utils_cxt->detailTrackingBuf = (StringInfoData*)palloc0(sizeof(StringInfoData)); // 璇︾粏杩借釜缂撳啿鍖 #endif - utils_cxt->track_cnt = 0; + utils_cxt->track_cnt = 0; // 杩借釜璁℃暟 + + utils_cxt->partId = (PartitionIdentifier*)palloc0(sizeof(PartitionIdentifier)); // 鍒嗗尯鏍囪瘑绗 + utils_cxt->gValueCompareContext = NULL; // 鍊兼瘮杈冧笂涓嬫枃 + utils_cxt->ContextUsedCount = 0; // 涓婁笅鏂囦娇鐢ㄨ鏁 - utils_cxt->partId = (PartitionIdentifier*)palloc0(sizeof(PartitionIdentifier)); - utils_cxt->gValueCompareContext = NULL; - utils_cxt->ContextUsedCount = 0; #define RANGE_PARTKEYMAXNUM 4 int rc = memset_s( - utils_cxt->valueItemArr, RANGE_PARTKEYMAXNUM * sizeof(Const*), 0, RANGE_PARTKEYMAXNUM * sizeof(Const*)); + utils_cxt->valueItemArr, RANGE_PARTKEYMAXNUM * sizeof(Const*), 0, RANGE_PARTKEYMAXNUM * sizeof(Const*)); // 鍊奸」鐩暟缁 securec_check(rc, "\0", "\0"); - utils_cxt->CurrentResourceOwner = NULL; - utils_cxt->STPSavedResourceOwner = NULL; - utils_cxt->CurTransactionResourceOwner = NULL; - utils_cxt->TopTransactionResourceOwner = NULL; - utils_cxt->SortColumnOptimize = false; - utils_cxt->pRelatedRel = NULL; - utils_cxt->sigTimerId = NULL; - utils_cxt->pg_strtok_ptr = NULL; - utils_cxt->maxChunksPerThread = 0; - utils_cxt->beyondChunk = 0; + utils_cxt->CurrentResourceOwner = NULL; // 褰撳墠璧勬簮鎷ユ湁鑰 + utils_cxt->STPSavedResourceOwner = NULL; // STP淇濆瓨鐨勮祫婧愭嫢鏈夎 + utils_cxt->CurTransactionResourceOwner = NULL; // 褰撳墠浜嬪姟鐨勮祫婧愭嫢鏈夎 + utils_cxt->TopTransactionResourceOwner = NULL; // 椤跺眰浜嬪姟鐨勮祫婧愭嫢鏈夎 + utils_cxt->SortColumnOptimize = false; // 鎺掑簭鍒椾紭鍖栨爣蹇 + utils_cxt->pRelatedRel = NULL; // 鐩稿叧鍏崇郴 + utils_cxt->sigTimerId = NULL; // 淇″彿瀹氭椂鍣↖D + utils_cxt->pg_strtok_ptr = NULL; // PG strtok鎸囬拡 + + utils_cxt->maxChunksPerThread = 0; // 姣忕嚎绋嬬殑鏈澶у潡鏁 + utils_cxt->beyondChunk = 0; // 瓒呭嚭鍧楁暟 } static void knl_t_pgxc_init(knl_t_pgxc_context* pgxc_cxt) { errno_t rc; - pgxc_cxt->current_installation_nodegroup = NULL; - pgxc_cxt->current_redistribution_nodegroup = NULL; - pgxc_cxt->globalBucketLen = 0; + pgxc_cxt->current_installation_nodegroup = NULL; // 褰撳墠瀹夎鑺傜偣缁 + pgxc_cxt->current_redistribution_nodegroup = NULL; // 褰撳墠閲嶅垎甯冭妭鐐圭粍 + pgxc_cxt->globalBucketLen = 0; // 鍏ㄥ眬妗堕暱搴 - pgxc_cxt->shmemNumCoords = NULL; - pgxc_cxt->shmemNumCoordsInCluster = NULL; - pgxc_cxt->shmemNumDataNodes = NULL; - pgxc_cxt->shmemNumDataStandbyNodes = NULL; - pgxc_cxt->coDefs = NULL; - pgxc_cxt->coDefsInCluster = NULL; - pgxc_cxt->dnDefs = NULL; - pgxc_cxt->dnStandbyDefs = NULL; + pgxc_cxt->shmemNumCoords = NULL; // 鍏变韩鍐呭瓨鍧愭爣鏁 + pgxc_cxt->shmemNumCoordsInCluster = NULL; // 闆嗙兢涓殑鍏变韩鍐呭瓨鍧愭爣鏁 + pgxc_cxt->shmemNumDataNodes = NULL; // 鍏变韩鍐呭瓨鏁版嵁鑺傜偣鏁 + pgxc_cxt->shmemNumDataStandbyNodes = NULL; // 鍏变韩鍐呭瓨鏁版嵁澶囩敤鑺傜偣鏁 + pgxc_cxt->coDefs = NULL; // 鍗忚皟鍣ㄥ畾涔 + pgxc_cxt->coDefsInCluster = NULL; // 闆嗙兢涓殑鍗忚皟鍣ㄥ畾涔 + pgxc_cxt->dnDefs = NULL; // 鏁版嵁鑺傜偣瀹氫箟 + pgxc_cxt->dnStandbyDefs = NULL; // 鏁版嵁澶囩敤鑺傜偣瀹氫箟 - pgxc_cxt->pgxc_net_ctl = (PGXCNodeNetCtlLayer*)palloc0(sizeof(PGXCNodeNetCtlLayer)); - pgxc_cxt->GlobalNetInstr = NULL; - pgxc_cxt->compute_pool_handle = NULL; - pgxc_cxt->compute_pool_conn = NULL; + pgxc_cxt->pgxc_net_ctl = (PGXCNodeNetCtlLayer*)palloc0(sizeof(PGXCNodeNetCtlLayer)); // PGXC缃戠粶鎺у埗灞 + pgxc_cxt->GlobalNetInstr = NULL; // 鍏ㄥ眬缃戠粶鎸囦护 + pgxc_cxt->compute_pool_handle = NULL; // 璁$畻姹犲彞鏌 + pgxc_cxt->compute_pool_conn = NULL; // 璁$畻姹犺繛鎺 - pgxc_cxt->temp_object_included = false; - pgxc_cxt->dbcleanup_info = (abort_callback_type*)palloc0(sizeof(abort_callback_type)); - rc = memset_s(pgxc_cxt->socket_buffer, SOCKET_BUFFER_LEN, 0, SOCKET_BUFFER_LEN); + pgxc_cxt->temp_object_included = false; // 涓存椂瀵硅薄宸插寘鍚爣蹇 + pgxc_cxt->dbcleanup_info = (abort_callback_type*)palloc0(sizeof(abort_callback_type)); // 鏁版嵁搴撴竻鐞嗕俊鎭 + rc = memset_s(pgxc_cxt->socket_buffer, SOCKET_BUFFER_LEN, 0, SOCKET_BUFFER_LEN); // 濂楁帴瀛楃紦鍐插尯 securec_check(rc, "\0", "\0"); - rc = memset_s(pgxc_cxt->begin_cmd, BEGIN_CMD_BUFF_SIZE, 0, BEGIN_CMD_BUFF_SIZE); + rc = memset_s(pgxc_cxt->begin_cmd, BEGIN_CMD_BUFF_SIZE, 0, BEGIN_CMD_BUFF_SIZE); // BEGIN鍛戒护缂撳啿鍖 securec_check(rc, "\0", "\0"); } static void knl_t_conn_init(knl_t_conn_context* conn_cxt) { - conn_cxt->ecCtrl = NULL; - conn_cxt->dl_handle = NULL; - conn_cxt->_conn = NULL; - conn_cxt->_result = NULL; - conn_cxt->_DatabaseEncoding = &pg_enc2name_tbl[PG_SQL_ASCII]; - conn_cxt->_float_inf = "Inf"; + conn_cxt->ecCtrl = NULL; // 杩炴帴鎵╁睍鎺у埗 + conn_cxt->dl_handle = NULL; // 鍔ㄦ侀摼鎺ュ簱鍙ユ焺 + conn_cxt->_conn = NULL; // 杩炴帴缁撴瀯浣 + conn_cxt->_result = NULL; // 鏌ヨ缁撴灉缁撴瀯浣 + conn_cxt->_DatabaseEncoding = &pg_enc2name_tbl[PG_SQL_ASCII]; // 鏁版嵁搴撶紪鐮 + conn_cxt->_float_inf = "Inf"; // 娴偣姝f棤绌峰ぇ } static void knl_t_page_redo_init(knl_t_page_redo_context* page_redo_cxt) { - page_redo_cxt->shutdown_requested = false; - page_redo_cxt->got_SIGHUP = false; - page_redo_cxt->sleep_long = false; - page_redo_cxt->check_repair = false; + page_redo_cxt->shutdown_requested = false; // 鍏虫満璇锋眰鏍囧織 + page_redo_cxt->got_SIGHUP = false; // 鏀跺埌SIGHUP淇″彿鏍囧織 + page_redo_cxt->sleep_long = false; // 闀挎椂闂翠紤鐪犳爣蹇 + page_redo_cxt->check_repair = false; // 妫鏌ヤ慨澶嶆爣蹇 } static void knl_t_parallel_decode_init(knl_t_parallel_decode_worker_context* parallel_decode_cxt) { - parallel_decode_cxt->shutdown_requested = false; - parallel_decode_cxt->got_SIGHUP = false; - parallel_decode_cxt->sleep_long = false; + parallel_decode_cxt->shutdown_requested = false; // 鍏虫満璇锋眰鏍囧織 + parallel_decode_cxt->got_SIGHUP = false; // 鏀跺埌SIGHUP淇″彿鏍囧織 + parallel_decode_cxt->sleep_long = false; // 闀挎椂闂翠紤鐪犳爣蹇 } static void knl_t_parallel_decode_reader_init(knl_t_logical_read_worker_context* parallel_decode_reader_cxt) { - parallel_decode_reader_cxt->shutdown_requested = false; - parallel_decode_reader_cxt->got_SIGHUP = false; - parallel_decode_reader_cxt->sleep_long = false; + parallel_decode_reader_cxt->shutdown_requested = false; // 鍏虫満璇锋眰鏍囧織 + parallel_decode_reader_cxt->got_SIGHUP = false; // 鏀跺埌SIGHUP淇″彿鏍囧織 + parallel_decode_reader_cxt->sleep_long = false; // 闀挎椂闂翠紤鐪犳爣蹇 } static void knl_t_startup_init(knl_t_startup_context* startup_cxt) { - startup_cxt->got_SIGHUP = false; - startup_cxt->shutdown_requested = false; - startup_cxt->failover_triggered = false; - startup_cxt->switchover_triggered = false; - startup_cxt->primary_triggered = false; - startup_cxt->standby_triggered = false; - startup_cxt->in_restore_command = false; - startup_cxt->NotifySigState = NULL; + startup_cxt->got_SIGHUP = false; // 鏀跺埌SIGHUP淇″彿鏍囧織 + startup_cxt->shutdown_requested = false; // 鍏虫満璇锋眰鏍囧織 + startup_cxt->failover_triggered = false; // 鏁呴殰鍒囨崲瑙﹀彂鏍囧織 + startup_cxt->switchover_triggered = false; // 瑙﹀彂鍒囨崲鏍囧織 + startup_cxt->primary_triggered = false; // 涓昏Е鍙戞爣蹇 + startup_cxt->standby_triggered = false; // 澶囪Е鍙戞爣蹇 + startup_cxt->in_restore_command = false; // 鎭㈠鍛戒护涓爣蹇 + startup_cxt->NotifySigState = NULL; // 閫氱煡淇″彿鐘舵 } static void knl_t_alarmchecker_init(knl_t_alarmchecker_context* alarm_cxt) { - alarm_cxt->gotSighup = false; - alarm_cxt->gotSigdie = false; + alarm_cxt->gotSighup = false; // 鏀跺埌SIGHUP淇″彿鏍囧織 + alarm_cxt->gotSigdie = false; // 鏀跺埌SIGDIE淇″彿鏍囧織 } static void knl_t_lwlockmoniter_init(knl_t_lwlockmoniter_context* lwm_cxt) { - lwm_cxt->got_SIGHUP = false; - lwm_cxt->shutdown_requested = false; + lwm_cxt->got_SIGHUP = false; // 鏀跺埌SIGHUP淇″彿鏍囧織 + lwm_cxt->shutdown_requested = false; // 鍏虫満璇锋眰鏍囧織 } static void knl_t_walwriter_init(knl_t_walwriter_context* walwriter_cxt) { - walwriter_cxt->got_SIGHUP = false; - walwriter_cxt->shutdown_requested = false; + walwriter_cxt->got_SIGHUP = false; // 鏀跺埌SIGHUP淇″彿鏍囧織 + walwriter_cxt->shutdown_requested = false; // 鍏虫満璇锋眰鏍囧織 } static void knl_t_walwriterauxiliary_init(knl_t_walwriterauxiliary_context *const walwriterauxiliary_cxt) { - walwriterauxiliary_cxt->got_SIGHUP = false; - walwriterauxiliary_cxt->shutdown_requested = false; + walwriterauxiliary_cxt->got_SIGHUP = false; // 鏀跺埌SIGHUP淇″彿鏍囧織 + walwriterauxiliary_cxt->shutdown_requested = false; // 鍏虫満璇锋眰鏍囧織 } static void knl_t_poolcleaner_init(knl_t_poolcleaner_context* poolcleaner_cxt) { - poolcleaner_cxt->shutdown_requested = false; - poolcleaner_cxt->got_SIGHUP = false; + poolcleaner_cxt->shutdown_requested = false; // 鍏虫満璇锋眰鏍囧織 + poolcleaner_cxt->got_SIGHUP = false; // 鏀跺埌SIGHUP淇″彿鏍囧織 } static void knl_t_catchup_init(knl_t_catchup_context* catchup_cxt) { - catchup_cxt->catchup_shutdown_requested = false; + catchup_cxt->catchup_shutdown_requested = false; // 鍏虫満璇锋眰鏍囧織 } /* interval for calling AbsorbFsyncRequests in CheckpointWriteDelay */ @@ -1025,161 +1040,160 @@ static void knl_t_catchup_init(knl_t_catchup_context* catchup_cxt) static void knl_t_checkpoint_init(knl_t_checkpoint_context* checkpoint_cxt) { - checkpoint_cxt->CheckpointerShmem = NULL; - checkpoint_cxt->got_SIGHUP = false; - checkpoint_cxt->checkpoint_requested = false; - checkpoint_cxt->shutdown_requested = false; - checkpoint_cxt->ckpt_active = false; - checkpoint_cxt->absorbCounter = WRITES_PER_ABSORB; - checkpoint_cxt->ckpt_done = 0; + checkpoint_cxt->CheckpointerShmem = NULL; // 妫鏌ョ偣鍏变韩鍐呭瓨缁撴瀯浣 + checkpoint_cxt->got_SIGHUP = false; // 鏀跺埌SIGHUP淇″彿鏍囧織 + checkpoint_cxt->checkpoint_requested = false; // 妫鏌ョ偣璇锋眰鏍囧織 + checkpoint_cxt->shutdown_requested = false; // 鍏虫満璇锋眰鏍囧織 + checkpoint_cxt->ckpt_active = false; // 妫鏌ョ偣婵娲绘爣蹇 + checkpoint_cxt->absorbCounter = WRITES_PER_ABSORB; // 鍚告敹鍐欏叆璇锋眰鐨勮鏁板櫒 + checkpoint_cxt->ckpt_done = 0; // 瀹屾垚鐨勬鏌ョ偣鏁伴噺 } static void knl_t_autovacuum_init(knl_t_autovacuum_context* autovacuum_cxt) { - autovacuum_cxt->got_SIGHUP = false; - autovacuum_cxt->got_SIGUSR2 = false; - autovacuum_cxt->got_SIGTERM = false; - autovacuum_cxt->pgStatAutoVacInfo = NULL; - autovacuum_cxt->autovacuum_coordinators_string = ""; - autovacuum_cxt->autovac_iops_limits = 0; - autovacuum_cxt->DatabaseList = NULL; - autovacuum_cxt->DatabaseListCxt = NULL; - autovacuum_cxt->MyWorkerInfo = NULL; - autovacuum_cxt->AutovacuumLauncherPid = 0; - autovacuum_cxt->last_read = 0; + autovacuum_cxt->got_SIGHUP = false; // 鏀跺埌SIGHUP淇″彿鏍囧織 + autovacuum_cxt->got_SIGUSR2 = false; // 鏀跺埌SIGUSR2淇″彿鏍囧織 + autovacuum_cxt->got_SIGTERM = false; // 鏀跺埌SIGTERM淇″彿鏍囧織 + autovacuum_cxt->pgStatAutoVacInfo = NULL; // 鑷姩娓呯悊缁熻淇℃伅缁撴瀯浣 + autovacuum_cxt->autovacuum_coordinators_string = ""; // 鑷姩娓呯悊鍗忚皟鍣ㄥ瓧绗︿覆 + autovacuum_cxt->autovac_iops_limits = 0; // 鑷姩娓呯悊IOPS闄愬埗 + autovacuum_cxt->DatabaseList = NULL; // 鏁版嵁搴撳垪琛 + autovacuum_cxt->DatabaseListCxt = NULL; // 鏁版嵁搴撳垪琛ㄥ唴瀛樹笂涓嬫枃 + autovacuum_cxt->MyWorkerInfo = NULL; // 鑷韩鐨勫伐浣滆繘绋嬩俊鎭粨鏋勪綋 + autovacuum_cxt->AutovacuumLauncherPid = 0; // 鑷姩娓呯悊鍚姩鍣ㄨ繘绋婭D + autovacuum_cxt->last_read = 0; // 涓婃璇诲彇鐨勬椂闂存埑 } static void KnlTApplyLauncherInit(knl_t_apply_launcher_context* applyLauncherCxt) { - applyLauncherCxt->got_SIGHUP = false; - applyLauncherCxt->newWorkerRequest = false; - applyLauncherCxt->got_SIGTERM = false; - applyLauncherCxt->onCommitLauncherWakeup = false; - applyLauncherCxt->applyLauncherShm = NULL; + applyLauncherCxt->got_SIGHUP = false; // 鏀跺埌SIGHUP淇″彿鏍囧織 + applyLauncherCxt->newWorkerRequest = false; // 鏂板伐浣滆姹傛爣蹇 + applyLauncherCxt->got_SIGTERM = false; // 鏀跺埌SIGTERM淇″彿鏍囧織 + applyLauncherCxt->onCommitLauncherWakeup = false; // 鎻愪氦鏃跺敜閱掓爣蹇 + applyLauncherCxt->applyLauncherShm = NULL; // 搴旂敤鍚姩鍣ㄥ叡浜唴瀛樼粨鏋勪綋 } static void KnlTApplyWorkerInit(knl_t_apply_worker_context* applyWorkerCxt) { - applyWorkerCxt->got_SIGHUP = false; - applyWorkerCxt->got_SIGTERM = false; - applyWorkerCxt->lsnMapping.head.next = &applyWorkerCxt->lsnMapping.head; + applyWorkerCxt->got_SIGHUP = false; // 鏀跺埌SIGHUP淇″彿鏍囧織 + applyWorkerCxt->got_SIGTERM = false; // 鏀跺埌SIGTERM淇″彿鏍囧織 + applyWorkerCxt->lsnMapping.head.next = &applyWorkerCxt->lsnMapping.head; // 閫昏緫澶嶅埗浣嶇疆鏄犲皠閾捐〃 applyWorkerCxt->lsnMapping.head.prev = &applyWorkerCxt->lsnMapping.head; - applyWorkerCxt->logicalRepRelMap = NULL; - applyWorkerCxt->sendTime = 0; - applyWorkerCxt->lastRecvpos = InvalidXLogRecPtr; - applyWorkerCxt->lastWritepos = InvalidXLogRecPtr; - applyWorkerCxt->lastFlushpos = InvalidXLogRecPtr; - applyWorkerCxt->mySubscription = NULL; - applyWorkerCxt->mySubscriptionValid = false; - applyWorkerCxt->inRemoteTransaction = false; - applyWorkerCxt->curWorker = NULL; - applyWorkerCxt->messageContext = NULL; - applyWorkerCxt->logicalRepRelMapContext = NULL; - applyWorkerCxt->applyContext = NULL; + applyWorkerCxt->logicalRepRelMap = NULL; // 閫昏緫澶嶅埗鍏崇郴鏄犲皠 + applyWorkerCxt->sendTime = 0; // 鍙戦佹椂闂存埑 + applyWorkerCxt->lastRecvpos = InvalidXLogRecPtr; // 鏈鍚庢帴鏀朵綅缃 + applyWorkerCxt->lastWritepos = InvalidXLogRecPtr; // 鏈鍚庡啓鍏ヤ綅缃 + applyWorkerCxt->lastFlushpos = InvalidXLogRecPtr; // 鏈鍚庡埛鏂颁綅缃 + applyWorkerCxt->mySubscription = NULL; // 璁㈤槄淇℃伅缁撴瀯浣 + applyWorkerCxt->mySubscriptionValid = false; // 璁㈤槄淇℃伅鏈夋晥鎬ф爣蹇 + applyWorkerCxt->inRemoteTransaction = false; // 杩滅▼浜嬪姟鏍囧織 + applyWorkerCxt->curWorker = NULL; // 褰撳墠宸ヤ綔杩涚▼淇℃伅缁撴瀯浣 + applyWorkerCxt->messageContext = NULL; // 娑堟伅鍐呭瓨涓婁笅鏂 + applyWorkerCxt->logicalRepRelMapContext = NULL; // 閫昏緫澶嶅埗鍏崇郴鏄犲皠鍐呭瓨涓婁笅鏂 + applyWorkerCxt->applyContext = NULL; // 搴旂敤鍐呭瓨涓婁笅鏂 } static void KnlTPublicationInit(knl_t_publication_context* publicationCxt) { - publicationCxt->publications_valid = false; - publicationCxt->RelationSyncCache = NULL; + publicationCxt->publications_valid = false; // 鍙戝竷淇℃伅鏈夋晥鎬ф爣蹇 + publicationCxt->RelationSyncCache = NULL; // 鍏崇郴鍚屾缂撳瓨 } static void KnlTUndolauncherInit(knl_t_undolauncher_context* undolauncherCxt) { - undolauncherCxt->got_SIGHUP = false; - undolauncherCxt->got_SIGUSR2 = false; - undolauncherCxt->got_SIGTERM = false; - - undolauncherCxt->UndoLauncherPid = 0; + undolauncherCxt->got_SIGHUP = false; // 鏀跺埌SIGHUP淇″彿鏍囧織 + undolauncherCxt->got_SIGUSR2 = false; // 鏀跺埌SIGUSR2淇″彿鏍囧織 + undolauncherCxt->got_SIGTERM = false; // 鏀跺埌SIGTERM淇″彿鏍囧織 + undolauncherCxt->UndoLauncherPid = 0; // 鎾ら攢鍚姩鍣ㄨ繘绋婭D } -static void KnlTUndoInit (knl_t_undo_context* undoCtx) +static void KnlTUndoInit(knl_t_undo_context* undoCtx) { for (auto i = 0; i < UNDO_PERSISTENCE_LEVELS; i++) { UndoPersistence upersistence = static_cast(i); - undoCtx->zids[upersistence] = INVALID_ZONE_ID; - undoCtx->prevXid[upersistence] = InvalidTransactionId; - undoCtx->slots[upersistence] = NULL; - undoCtx->slotPtr[upersistence] = INVALID_UNDO_REC_PTR; + undoCtx->zids[upersistence] = INVALID_ZONE_ID; // 鍖哄煙ID + undoCtx->prevXid[upersistence] = InvalidTransactionId; // 涓婁竴涓簨鍔D + undoCtx->slots[upersistence] = NULL; // undo妲戒綅 + undoCtx->slotPtr[upersistence] = INVALID_UNDO_REC_PTR; // undo璁板綍鎸囬拡 } - undoCtx->transUndoSize = 0; - undoCtx->fetchRecord = false; + undoCtx->transUndoSize = 0; // 浜嬪姟undo澶у皬 + undoCtx->fetchRecord = false; // 妫绱ndo璁板綍鏍囧織 } static void KnlTUndoworkerInit(knl_t_undoworker_context* undoworkerCxt) { - undoworkerCxt->got_SIGHUP = false; - undoworkerCxt->got_SIGUSR2 = false; - undoworkerCxt->got_SIGTERM = false; + undoworkerCxt->got_SIGHUP = false; // 鏀跺埌SIGHUP淇″彿鏍囧織 + undoworkerCxt->got_SIGUSR2 = false; // 鏀跺埌SIGUSR2淇″彿鏍囧織 + undoworkerCxt->got_SIGTERM = false; // 鏀跺埌SIGTERM淇″彿鏍囧織 } static void KnlTUndorecyclerInit(knl_t_undorecycler_context* undorecyclerCxt) { - undorecyclerCxt->got_SIGHUP = false; - undorecyclerCxt->shutdown_requested = false; + undorecyclerCxt->got_SIGHUP = false; // 鏀跺埌SIGHUP淇″彿鏍囧織 + undorecyclerCxt->shutdown_requested = false; // 鍏虫満璇锋眰鏍囧織 } static void KnlTRollbackRequestsInit(knl_t_rollback_requests_context* context) { - context->rollback_requests_hash = NULL; - context->next_bucket_for_scan = 0; + context->rollback_requests_hash = NULL; // 鍥炴粴璇锋眰鍝堝笇琛 + context->next_bucket_for_scan = 0; // 涓嬩竴涓鎵弿鐨勫搱甯屾《绱㈠紩 } static void KnlTGstatInit(knl_t_gstat_context* context) { - context->got_SIGHUP = false; - context->got_SIGUSR2 = false; - context->got_SIGTERM = false; + context->got_SIGHUP = false; // 鏀跺埌SIGHUP淇″彿鏍囧織 + context->got_SIGUSR2 = false; // 鏀跺埌SIGUSR2淇″彿鏍囧織 + context->got_SIGTERM = false; // 鏀跺埌SIGTERM淇″彿鏍囧織 } static void knl_t_aiocompleter_init(knl_t_aiocompleter_context* aio_cxt) { - aio_cxt->shutdown_requested = false; - aio_cxt->config_requested = false; + aio_cxt->shutdown_requested = false; // 鍏虫満璇锋眰鏍囧織 + aio_cxt->config_requested = false; // 閰嶇疆璇锋眰鏍囧織 } static void knl_t_twophasecleaner_init(knl_t_twophasecleaner_context* tpcleaner_cxt) { - tpcleaner_cxt->got_SIGHUP = false; - tpcleaner_cxt->shutdown_requested = false; + tpcleaner_cxt->got_SIGHUP = false; // 鏀跺埌SIGHUP淇″彿鏍囧織 + tpcleaner_cxt->shutdown_requested = false; // 鍏虫満璇锋眰鏍囧織 } static void knl_t_bgwriter_init(knl_t_bgwriter_context* bgwriter_cxt) { - bgwriter_cxt->got_SIGHUP = false; - bgwriter_cxt->shutdown_requested = false; + bgwriter_cxt->got_SIGHUP = false; // 鏀跺埌SIGHUP淇″彿鏍囧織 + bgwriter_cxt->shutdown_requested = false; // 鍏虫満璇锋眰鏍囧織 } static void knl_t_pagewriter_init(knl_t_pagewriter_context* pagewriter_cxt) { - pagewriter_cxt->got_SIGHUP = false; - pagewriter_cxt->sync_requested = false; - pagewriter_cxt->sync_retry = false; - pagewriter_cxt->shutdown_requested = false; - pagewriter_cxt->page_writer_after = WRITEBACK_MAX_PENDING_FLUSHES; - pagewriter_cxt->pagewriter_id = -1; + pagewriter_cxt->got_SIGHUP = false; // 鏀跺埌SIGHUP淇″彿鏍囧織 + pagewriter_cxt->sync_requested = false; // 鍚屾璇锋眰鏍囧織 + pagewriter_cxt->sync_retry = false; // 鍚屾閲嶈瘯鏍囧織 + pagewriter_cxt->shutdown_requested = false; // 鍏虫満璇锋眰鏍囧織 + pagewriter_cxt->page_writer_after = WRITEBACK_MAX_PENDING_FLUSHES; // 寰呭啓鍏ョ殑鏈澶ц剰椤垫暟 + pagewriter_cxt->pagewriter_id = -1; // 椤靛啓鍏ュ櫒ID } static void knl_t_barrier_creator_init(knl_t_barrier_creator_context* barrier_creator_cxt) { - barrier_creator_cxt->archive_slot_names = NULL; - barrier_creator_cxt->got_SIGHUP = false; - barrier_creator_cxt->is_first_barrier = false; - barrier_creator_cxt->barrier_update_last_time_info = NULL; - barrier_creator_cxt->shutdown_requested = false; - barrier_creator_cxt->first_cn_timeline = 0; + barrier_creator_cxt->archive_slot_names = NULL; // 褰掓。妲藉悕绉板垪琛 + barrier_creator_cxt->got_SIGHUP = false; // 鏀跺埌SIGHUP淇″彿鏍囧織 + barrier_creator_cxt->is_first_barrier = false; // 绗竴涓殰纰嶆爣蹇 + barrier_creator_cxt->barrier_update_last_time_info = NULL; // 闅滅鏇存柊鐨勪笂娆℃椂闂翠俊鎭 + barrier_creator_cxt->shutdown_requested = false; // 鍏虫満璇锋眰鏍囧織 + barrier_creator_cxt->first_cn_timeline = 0; // 绗竴涓狢oordinator鐨勬椂闂寸嚎鍙 } static void knl_t_xlogcopybackend_init(knl_t_sharestoragexlogcopyer_context* cxt) { - cxt->got_SIGHUP = false; - cxt->shutdown_requested = false; - cxt->wakeUp = false; - cxt->readFile = -1; - cxt->readOff = 0; - cxt->readSegNo = 0; - cxt->buf = NULL; - cxt->originBuf = NULL; + cxt->got_SIGHUP = false; // 鏀跺埌SIGHUP淇″彿鏍囧織 + cxt->shutdown_requested = false; // 鍏虫満璇锋眰鏍囧織 + cxt->wakeUp = false; // 鍞ら啋鏍囧織 + cxt->readFile = -1; // 璇诲彇鏂囦欢鎻忚堪绗 + cxt->readOff = 0; // 璇诲彇鏂囦欢鍋忕Щ閲 + cxt->readSegNo = 0; // 璇诲彇鏂囦欢娈靛彿 + cxt->buf = NULL; // 缂撳啿鍖 + cxt->originBuf = NULL; // 鍘熷缂撳啿鍖 } @@ -1190,22 +1204,29 @@ extern bool HeapTupleSatisfiesToast(HeapTuple htup, Snapshot snapshot, Buffer bu static void knl_t_snapshot_init(knl_t_snapshot_context* snapshot_cxt) { + // 涓 SNAPSHOT_NOW 涓婁笅鏂囧垎閰嶅唴瀛樺苟鍒濆鍖栦负 0 snapshot_cxt->SnapshotNowData = (SnapshotData*)palloc0(sizeof(SnapshotData)); snapshot_cxt->SnapshotNowData->satisfies = SNAPSHOT_NOW; + // 涓 SNAPSHOT_SELF 涓婁笅鏂囧垎閰嶅唴瀛樺苟鍒濆鍖栦负 0 snapshot_cxt->SnapshotSelfData = (SnapshotData*)palloc0(sizeof(SnapshotData)); snapshot_cxt->SnapshotSelfData->satisfies = SNAPSHOT_SELF; + // 涓 SNAPSHOT_ANY 涓婁笅鏂囧垎閰嶅唴瀛樺苟鍒濆鍖栦负 0 snapshot_cxt->SnapshotAnyData = (SnapshotData*)palloc0(sizeof(SnapshotData)); snapshot_cxt->SnapshotAnyData->satisfies = SNAPSHOT_ANY; + // 涓 SNAPSHOT_TOAST 涓婁笅鏂囧垎閰嶅唴瀛樺苟鍒濆鍖栦负 0 snapshot_cxt->SnapshotToastData = (SnapshotData*)palloc0(sizeof(SnapshotData)); snapshot_cxt->SnapshotToastData->satisfies = SNAPSHOT_TOAST; } static void knl_t_comm_init(knl_t_comm_context* comm_cxt) { + // 鏂█纭繚 comm_cxt 涓嶄负 NULL Assert(comm_cxt != NULL); + + // 鍒濆鍖栭氫俊涓婁笅鏂囩殑鍚勭璁℃暟鍣ㄥ拰鏍囧織涓 0 comm_cxt->g_receiver_loop_poll_up = 0; comm_cxt->LibcommThreadType = LIBCOMM_NONE; comm_cxt->libcomm_semaphore = NULL; @@ -1220,31 +1241,38 @@ static void knl_t_libpq_init(knl_t_libpq_context* libpq_cxt) { errno_t rc; + // 鏂█纭繚 libpq_cxt 涓嶄负 NULL Assert(libpq_cxt != NULL); + + // 灏 libpq 涓婁笅鏂囩殑濂楁帴瀛楄矾寰勫垵濮嬪寲涓 0 libpq_cxt->listen_fd_for_recv_flow_ctrl = -1; rc = memset_s(libpq_cxt->sock_path, MAXPGPATH, 0, MAXPGPATH); securec_check(rc, "\0", "\0"); rc = memset_s(libpq_cxt->ha_sock_path, MAXPGPATH, 0, MAXPGPATH); securec_check(rc, "\0", "\0"); + + // 鍒濆鍖 libpq 涓婁笅鏂囩殑鍏朵粬鏍囧織鍜岀紦鍐插尯 libpq_cxt->PqSendBuffer = NULL; libpq_cxt->PqCommBusy = false; libpq_cxt->DoingCopyOut = false; - libpq_cxt->save_query_result_to_disk = false; temp_file_context_init(libpq_cxt); - libpq_cxt->parsed_hba_lines = NIL; libpq_cxt->parsed_hba_context = NULL; } - static void knl_t_contrib_init(knl_t_contrib_context* contrib_cxt) { + // 灏 g_searchletId 鍒濆鍖栦负 0 contrib_cxt->g_searchletId = 0; + // 鍒濆鍖 vec_info 涓 NULL contrib_cxt->vec_info = NULL; + // 鍚敤鏂█ contrib_cxt->assert_enabled = true; + // 鍒濆鍖栨棩蹇椾富鏈哄悕鍜岃妭鐐瑰悕涓 0 contrib_cxt->g_log_hostname = (Datum)0; contrib_cxt->g_log_nodename = (Datum)0; + // 鍒濆鍖 ShippableCacheHash 涓 NULL contrib_cxt->ShippableCacheHash = NULL; } @@ -1252,6 +1280,7 @@ static void knl_t_walreceiver_init(knl_t_walreceiver_context* walreceiver_cxt) { errno_t rc; + // 鍒濆鍖栧悇绉嶆爣蹇楀拰缂撳啿鍖轰负榛樿鍊 walreceiver_cxt->got_SIGHUP = false; walreceiver_cxt->got_SIGTERM = false; walreceiver_cxt->start_switchover = false; @@ -1261,16 +1290,17 @@ static void knl_t_walreceiver_init(knl_t_walreceiver_context* walreceiver_cxt) securec_check(rc, "\0", "\0"); rc = memset_s(walreceiver_cxt->gucconf_lock_file, MAXPGPATH, 0, MAXPGPATH); securec_check(rc, "\0", "\0"); + // 灏 reserve_item 鐨勫悇瀛楁鍒濆鍖栦负 0 walreceiver_cxt->reserve_item = {0}; + // 璁剧疆鏂囦欢瓒呮椂妫鏌ユ椂闂翠负 1 灏忔椂 walreceiver_cxt->check_file_timeout = 60 * 60 * 1000; + // 灏嗗悇绉嶆秷鎭粨鏋勪綋鍒濆鍖栦负 0锛屽苟鍒嗛厤鍐呭瓨 walreceiver_cxt->walRcvCtlBlock = NULL; walreceiver_cxt->reply_message = (StandbyReplyMessage*)palloc0(sizeof(StandbyReplyMessage)); walreceiver_cxt->feedback_message = (StandbyHSFeedbackMessage*)palloc0(sizeof(StandbyHSFeedbackMessage)); - ; walreceiver_cxt->request_message = (StandbySwitchRequestMessage*)palloc0(sizeof(StandbySwitchRequestMessage)); - ; walreceiver_cxt->reply_modify_message = (ConfigModifyTimeMessage*)palloc0(sizeof(ConfigModifyTimeMessage)); - ; + // 灏嗗叾浠栨爣蹇楀拰璁℃暟鍣ㄥ垵濮嬪寲涓洪粯璁ゅ walreceiver_cxt->WalRcvImmediateInterruptOK = false; walreceiver_cxt->AmWalReceiverForFailover = false; walreceiver_cxt->AmWalReceiverForStandby = false; @@ -1284,10 +1314,13 @@ static void knl_t_storage_init(knl_t_storage_context* storage_cxt) { errno_t rc; + // 灏 latestObservedXid 鍒濆鍖栦负鏃犳晥浜嬪姟 ID storage_cxt->latestObservedXid = InvalidTransactionId; + // 鍒嗛厤骞跺垵濮嬪寲 CurrentRunningXacts 缁撴瀯浣 storage_cxt->CurrentRunningXacts = (RunningTransactionsData*)palloc0(sizeof(RunningTransactionsData)); storage_cxt->proc_vxids = NULL; + // 鍒濆鍖栧悇绉嶇紦鍐插尯鍜岄攣瀹氱浉鍏崇殑鍙橀噺 storage_cxt->BufferDescriptors = NULL; storage_cxt->BufferBlocks = NULL; storage_cxt->BackendWritebackContext = (WritebackContext*)palloc0(sizeof(WritebackContext)); @@ -1300,8 +1333,8 @@ static void knl_t_storage_init(knl_t_storage_context* storage_cxt) storage_cxt->InProgressAioBuf = NULL; storage_cxt->InProgressAioType = AioUnkown; storage_cxt->is_btree_split = false; - storage_cxt->PrivateRefCountArray = - (PrivateRefCountEntry*)palloc0(sizeof(PrivateRefCountEntry) * REFCOUNT_ARRAY_ENTRIES); + // 鍒嗛厤骞跺垵濮嬪寲 PrivateRefCount 鐩稿叧鐨勬暟鎹粨鏋 + storage_cxt->PrivateRefCountArray = (PrivateRefCountEntry*)palloc0(sizeof(PrivateRefCountEntry) * REFCOUNT_ARRAY_ENTRIES); storage_cxt->PrivateRefCountHash = NULL; storage_cxt->PrivateRefCountOverflowed = 0; storage_cxt->PrivateRefCountClock = 0; @@ -1317,15 +1350,18 @@ static void knl_t_storage_init(knl_t_storage_context* storage_cxt) storage_cxt->CacheBlockInProgressUncompress = CACHE_BLOCK_INVALID_IDX; storage_cxt->MetaBlockInProgressIO = CACHE_BLOCK_INVALID_IDX; + // 璁剧疆绛夊緟閿佺殑鍒濆瓒呮椂鏃堕棿 #define STANDBY_INITIAL_WAIT_US 1000 storage_cxt->RecoveryLockList = NIL; storage_cxt->standbyWait_us = STANDBY_INITIAL_WAIT_US; storage_cxt->lo_heap_r = NULL; storage_cxt->lo_index_r = NULL; + // 鍒濆鍖 dummy_spinlock 涓 0 rc = memset_s(&storage_cxt->dummy_spinlock, sizeof(slock_t), 0, sizeof(slock_t)); securec_check(rc, "\0", "\0"); storage_cxt->spins_per_delay = DEFAULT_SPINS_PER_DELAY; + // 鍒濆鍖栧悇绉嶉攣鍜岀害鏉熺浉鍏崇殑鏁版嵁缁撴瀯 storage_cxt->visitedProcs = NULL; storage_cxt->nVisitedProcs = 0; storage_cxt->topoProcs = NULL; @@ -1359,6 +1395,7 @@ static void knl_t_storage_init(knl_t_storage_context* storage_cxt) storage_cxt->blocking_redistribution_proc = NULL; storage_cxt->lock_vxids = NULL; + // 鍒濆鍖栧悇绉嶈秴鏃舵爣蹇楀拰璁℃椂鍣 storage_cxt->EnlargeDeadlockTimeout = false; storage_cxt->lockAwaited = NULL; storage_cxt->standby_timeout_active = false; @@ -1372,8 +1409,10 @@ static void knl_t_storage_init(knl_t_storage_context* storage_cxt) storage_cxt->statement_fin_time2 = 0; storage_cxt->pageCopy = NULL; + // 鍒濆鍖栧叾浠栭攣瀹氱浉鍏冲彉閲 storage_cxt->isSwitchoverLockHolder = false; storage_cxt->num_held_lwlocks = 0; + // 鍒嗛厤 held_lwlocks 鐨勫唴瀛樺苟鍒濆鍖栦负 0 storage_cxt->held_lwlocks = (LWLockHandle*)palloc0(MAX_SIMUL_LWLOCKS * sizeof(LWLockHandle)); storage_cxt->lock_addin_request = 0; storage_cxt->lock_addin_request_allowed = true; @@ -1382,10 +1421,12 @@ static void knl_t_storage_init(knl_t_storage_context* storage_cxt) storage_cxt->remote_function_context = NULL; storage_cxt->work_env_init = false; + // 鍒濆鍖栧叾浠栫郴缁熺浉鍏崇殑鍙橀噺 storage_cxt->shmem_startup_hook = NULL; storage_cxt->total_addin_request = 0; storage_cxt->addin_request_allowed = true; storage_cxt->atexit_callback_setup = false; + // 灏 on_proc_exit_list 鍜 on_shmem_exit_list 鍒濆鍖栦负 0 rc = memset_s(storage_cxt->on_proc_exit_list, MAX_ON_EXITS * sizeof(ONEXIT), 0, MAX_ON_EXITS * sizeof(ONEXIT)); securec_check(rc, "\0", "\0"); rc = memset_s(storage_cxt->on_shmem_exit_list, MAX_ON_EXITS * sizeof(ONEXIT), 0, MAX_ON_EXITS * sizeof(ONEXIT)); @@ -1393,12 +1434,14 @@ static void knl_t_storage_init(knl_t_storage_context* storage_cxt) storage_cxt->on_proc_exit_index = 0; storage_cxt->on_shmem_exit_index = 0; + // 鍒嗛厤骞跺垵濮嬪寲涓浜涚紦瀛樺拰鍏冩暟鎹俊鎭殑缁撴瀯浣 storage_cxt->cmprMetaInfo = (CmprMetaUnion*)palloc0(sizeof(CmprMetaUnion)); storage_cxt->DataFileIdCache = NULL; storage_cxt->SegSpcCache = NULL; storage_cxt->uidHashCache = NULL; storage_cxt->DisasterCache = NULL; + // 鍒濆鍖栨枃浠舵弿杩扮绛夌郴缁熷弬鏁 storage_cxt->max_safe_fds = 32; storage_cxt->max_userdatafiles = 8192 - 1000; storage_cxt->timeoutRemoteOpera = 0; @@ -1406,7 +1449,9 @@ static void knl_t_storage_init(knl_t_storage_context* storage_cxt) static void knl_t_port_init(knl_t_port_context* port_cxt) { + // 鍒濆鍖栫嚎绋嬮鍑烘爣蹇椾负 false port_cxt->thread_is_exiting = false; + // 鍒濆鍖栬瑷鐜鐩稿叧鍙橀噺 port_cxt->save_locale_r = (locale_t)0; port_cxt->cur_datcollate.data[0] = '\0'; port_cxt->cur_datctype.data[0] = '\0'; @@ -1418,6 +1463,7 @@ static void knl_t_walsender_init(knl_t_walsender_context* walsender_cxt) { errno_t rc; + // 鍒濆鍖栭昏緫澶嶅埗鐩稿叧鍙橀噺 walsender_cxt->load_cu_buffer = NULL; walsender_cxt->load_cu_buffer_size = 64 * 1024 * 1024; walsender_cxt->WalSndCtl = NULL; @@ -1442,12 +1488,16 @@ static void knl_t_walsender_init(knl_t_walsender_context* walsender_cxt) walsender_cxt->walsender_ready_to_stop = false; walsender_cxt->response_switchover_requested = false; walsender_cxt->server_run_mode = NORMAL_MODE; + + // 鍒濆鍖栧瓧绗︿覆鐩稿叧鍙橀噺 rc = memset_s(walsender_cxt->gucconf_file, MAXPGPATH, 0, MAXPGPATH); securec_check(rc, "\0", "\0"); rc = memset_s(walsender_cxt->gucconf_lock_file, MAXPGPATH, 0, MAXPGPATH); securec_check(rc, "\0", "\0"); rc = memset_s(walsender_cxt->slotname, NAMEDATALEN, 0, NAMEDATALEN); securec_check(rc, "\0", "\0"); + + // 鍒濆鍖栭昏緫澶嶅埗涓殑鍚勭鍙橀噺鍜屾枃浠舵弿杩扮 walsender_cxt->ws_dummy_data_read_file_fd = NULL; walsender_cxt->ws_dummy_data_read_file_num = 1; walsender_cxt->CheckCUArray = NULL; @@ -1468,6 +1518,8 @@ static void knl_t_walsender_init(knl_t_walsender_context* walsender_cxt) walsender_cxt->compressBuf = NULL; walsender_cxt->ep_fd = -1; walsender_cxt->datafd = -1; + + // 鍒濆鍖栧叾浠栨爣蹇楀拰鐘舵佸彉閲 walsender_cxt->is_obsmode = false; walsender_cxt->standbyConnection = false; walsender_cxt->restoreLogicalLogHead = NULL; @@ -1481,116 +1533,188 @@ static void knl_t_tsearch_init(knl_t_tsearch_context* tsearch_cxt) static void knl_t_postmaster_init(knl_t_postmaster_context* postmaster_cxt) { + // 鍒濆鍖栭昏緫杩炴帴鐨勫惎鍔ㄥ寘澶勭悊鏍囧織 postmaster_cxt->ProcessStartupPacketForLogicConn = false; + // 鍒濆鍖栫敤浜巐ibcomm鐨勫鎺ュ瓧鍜岀鍙 postmaster_cxt->sock_for_libcomm = -1; postmaster_cxt->port_for_libcomm = NULL; + // 鍒濆鍖栨祦澶嶅埗涓繚鎸佸鎺ュ瓧鎵撳紑鐨勬爣蹇 postmaster_cxt->KeepSocketOpenForStream = false; int rc; + // 鍒濆鍖栧鍒惰繛鎺ユ暟缁 rc = memset_s(postmaster_cxt->ReplConnArray, - MAX_REPLNODE_NUM * sizeof(replconninfo*), - 0, - MAX_REPLNODE_NUM * sizeof(replconninfo*)); + MAX_REPLNODE_NUM * sizeof(replconninfo*), + 0, + MAX_REPLNODE_NUM * sizeof(replconninfo*)); securec_check(rc, "\0", "\0"); - rc = memset_s(postmaster_cxt->ReplConnChangeType, MAX_REPLNODE_NUM * sizeof(int), - NO_CHANGE, MAX_REPLNODE_NUM * sizeof(int)); + // 鍒濆鍖栧鍒惰繛鎺ュ彉鍖栫被鍨嬫暟缁 + rc = memset_s(postmaster_cxt->ReplConnChangeType, + MAX_REPLNODE_NUM * sizeof(int), + NO_CHANGE, + MAX_REPLNODE_NUM * sizeof(int)); securec_check(rc, "\0", "\0"); - rc = memset_s(postmaster_cxt->CrossClusterReplConnArray, MAX_REPLNODE_NUM * sizeof(replconninfo*), 0, - MAX_REPLNODE_NUM * sizeof(replconninfo*)); + // 鍒濆鍖栬法闆嗙兢澶嶅埗杩炴帴鏁扮粍鍜岃繛鎺ュ彉鍖栨爣蹇楁暟缁 + rc = memset_s(postmaster_cxt->CrossClusterReplConnArray, + MAX_REPLNODE_NUM * sizeof(replconninfo*), + 0, + MAX_REPLNODE_NUM * sizeof(replconninfo*)); securec_check(rc, "\0", "\0"); - rc = memset_s(postmaster_cxt->CrossClusterReplConnChanged, MAX_REPLNODE_NUM * sizeof(bool), 0, + rc = memset_s(postmaster_cxt->CrossClusterReplConnChanged, + MAX_REPLNODE_NUM * sizeof(bool), + 0, MAX_REPLNODE_NUM * sizeof(bool)); securec_check(rc, "\0", "\0"); + // 鍒濆鍖朒A鍏变韩鍐呭瓨鏁版嵁 postmaster_cxt->HaShmData = NULL; + // 鍒濆鍖栨湰鍦癐P鏁伴噺 postmaster_cxt->LocalIpNum = 0; + // 鍒濆鍖朢PC宸ヤ綔绾跨▼鏍囧織 postmaster_cxt->IsRPCWorkerThread = false; + // 鍒濆鍖栧璁$浉鍏虫爣蹇 postmaster_cxt->audit_primary_start = true; postmaster_cxt->audit_primary_failover = false; postmaster_cxt->audit_standby_switchover = false; + // 鍒濆鍖栧彂閫佸埌铏氭嫙澶囨満鍜屾瀯寤哄鏈虹殑鏍囧織 postmaster_cxt->senderToDummyStandby = false; postmaster_cxt->senderToBuildStandby = false; + // 鍒濆鍖朠ostmaster鏄惁宸茶揪鍒版甯歌繍琛岀姸鎬佺殑鏍囧織 postmaster_cxt->ReachedNormalRunning = false; + // 鍒濆鍖栭噸瀹氬悜鏄惁宸插畬鎴愮殑鏍囧織 postmaster_cxt->redirection_done = false; + // 鍒濆鍖栬嚜鍔ㄦ竻鐞嗚繘绋嬪惎鍔ㄦ爣蹇 postmaster_cxt->start_autovac_launcher = false; + // 鍒濆鍖栬嚜鍔ㄦ竻鐞嗚繘绋嬫槸鍚﹂渶瑕佷俊鍙风殑鏍囧織 postmaster_cxt->avlauncher_needs_signal = false; + // 鍒濆鍖栦綔涓氳皟搴﹀櫒鍚姩鏍囧織 postmaster_cxt->start_job_scheduler = false; + // 鍒濆鍖栦綔涓氳皟搴﹀櫒鏄惁闇瑕佷俊鍙风殑鏍囧織 postmaster_cxt->jobscheduler_needs_signal = false; + // 鍒濆鍖栭殢鏈烘暟绉嶅瓙 postmaster_cxt->random_seed = 0; + // 鍒濆鍖栨槸鍚﹀己鍒朵笉鍒嗙鏃ュ織鏂囦欢鐨勬爣蹇 postmaster_cxt->forceNoSeparate = false; + // 鍒濆鍖朠ostmaster鏄惁瀛樻椿鐨勬枃浠舵弿杩扮 postmaster_cxt->postmaster_alive_fds[0] = -1; postmaster_cxt->postmaster_alive_fds[1] = -1; + // 鍒濆鍖栫郴缁熸棩蹇楃閬撶殑鏂囦欢鎻忚堪绗 postmaster_cxt->syslogPipe[0] = -1; postmaster_cxt->syslogPipe[1] = -1; } +// 鍒濆鍖 bootstrap 涓婁笅鏂囩粨鏋勪綋 static void knl_t_bootstrap_init(knl_t_bootstrap_context* bootstrap_cxt) { + // 鍒濆鍖栧瓧娈 num_columns_read 涓 0 bootstrap_cxt->num_columns_read = 0; + // 鍒濆鍖栧瓧娈 yyline 涓 1 bootstrap_cxt->yyline = 1; + // 鍒濆鍖栧瓧娈 MyAuxProcType 涓 NotAnAuxProcess bootstrap_cxt->MyAuxProcType = NotAnAuxProcess; + // 鍒濆鍖栨寚閽堝瓧娈 Typ 涓 NULL bootstrap_cxt->Typ = NULL; + // 鍒濆鍖栨寚閽堝瓧娈 Ap 涓 NULL bootstrap_cxt->Ap = NULL; + // 鍒濆鍖栨寚閽堝瓧娈 nogc 涓 NULL bootstrap_cxt->nogc = NULL; + // 鍒濆鍖栨寚閽堝瓧娈 ILHead 涓 NULL bootstrap_cxt->ILHead = NULL; } +// 鍒濆鍖 percentile 涓婁笅鏂囩粨鏋勪綋 static void knl_t_pencentile_init(knl_t_percentile_context* percentile_cxt) { + // 鍒濆鍖栧瓧娈 need_exit 涓 false percentile_cxt->need_exit = false; + // 鍒濆鍖栧瓧娈 need_reset_timer 涓 true percentile_cxt->need_reset_timer = true; + // 鍒濆鍖栨寚閽堝瓧娈 pgxc_all_handles 涓 NULL percentile_cxt->pgxc_all_handles = NULL; + // 鍒濆鍖栧瓧娈 got_SIGHUP 涓 false percentile_cxt->got_SIGHUP = false; } +// 鍒濆鍖 perf_snap 涓婁笅鏂囩粨鏋勪綋 static void knl_t_perf_snap_init(knl_t_perf_snap_context* perf_snap_cxt) { + // 鍒濆鍖栧瓧娈 need_exit 涓 false perf_snap_cxt->need_exit = false; + // 鍒濆鍖栧瓧娈 got_SIGHUP 涓 false perf_snap_cxt->got_SIGHUP = false; + // 鍒濆鍖栧瓧娈 last_snapshot_start_time 涓 0 perf_snap_cxt->last_snapshot_start_time = 0; + // 鍒濆鍖栧瓧娈 curr_table_size 涓 0 perf_snap_cxt->curr_table_size = 0; + // 鍒濆鍖栧瓧娈 curr_snapid 涓 0 perf_snap_cxt->curr_snapid = 0; + // 鍒濆鍖栨寚閽堝瓧娈 connect 涓 NULL perf_snap_cxt->connect = NULL; + // 鍒濆鍖栧瓧娈 cancel_request 涓 0 perf_snap_cxt->cancel_request = 0; + // 鍒濆鍖栧瓧娈 request_snapshot 涓 false perf_snap_cxt->request_snapshot = false; + // 鍒濆鍖栨寚閽堝瓧娈 res 涓 NULL perf_snap_cxt->res = NULL; + // 鍒濆鍖栧瓧娈 is_mem_protect 涓 false perf_snap_cxt->is_mem_protect = false; } +// 鍒濆鍖 ash 涓婁笅鏂囩粨鏋勪綋 static void knl_t_ash_init(knl_t_ash_context* ash_cxt) { + // 鍒濆鍖栧瓧娈 last_ash_start_time 涓 0 ash_cxt->last_ash_start_time = 0; + // 鍒濆鍖栧瓧娈 need_exit 涓 false ash_cxt->need_exit = false; + // 鍒濆鍖栧瓧娈 got_SIGHUP 涓 false ash_cxt->got_SIGHUP = false; + // 鍒濆鍖栧瓧娈 slot 涓 0 ash_cxt->slot = 0; + // 鍒濆鍖栨寚閽堝瓧娈 waitEventStr 涓 NULL ash_cxt->waitEventStr = NULL; } +// 鍒濆鍖 statement 涓婁笅鏂囩粨鏋勪綋 static void knl_t_statement_init(knl_t_statement_context* statement_cxt) { + // 鍒濆鍖栧瓧娈 need_exit 涓 false statement_cxt->need_exit = false; + // 鍒濆鍖栧瓧娈 got_SIGHUP 涓 false statement_cxt->got_SIGHUP = false; + // 鍒濆鍖栧瓧娈 full_sql_retention_time 涓 0 statement_cxt->full_sql_retention_time = 0; + // 鍒濆鍖栧瓧娈 slow_sql_retention_time 涓 0 statement_cxt->slow_sql_retention_time = 0; + // 鍒濆鍖栨寚閽堝瓧娈 instr_prev_post_parse_analyze_hook 涓 NULL statement_cxt->instr_prev_post_parse_analyze_hook = NULL; } - +// 鍒濆鍖 stat 涓婁笅鏂囩粨鏋勪綋 static void knl_t_stat_init(knl_t_stat_context* stat_cxt) { + // 鍒濆鍖栨寚閽堝瓧娈 local_bad_block_mcxt 涓 NULL stat_cxt->local_bad_block_mcxt = NULL; + // 鍒濆鍖栨寚閽堝瓧娈 local_bad_block_stat 涓 NULL stat_cxt->local_bad_block_stat = NULL; + // 鍒濆鍖栧瓧娈 need_exit 涓 false stat_cxt->need_exit = false; } +// 鍒濆鍖 heartbeat 涓婁笅鏂囩粨鏋勪綋 static void knl_t_heartbeat_init(knl_t_heartbeat_context* heartbeat_cxt) { + // 鍒濆鍖栧瓧娈 got_SIGHUP 涓 false heartbeat_cxt->got_SIGHUP = false; + // 鍒濆鍖栧瓧娈 shutdown_requested 涓 false heartbeat_cxt->shutdown_requested = false; + // 鍒濆鍖栨寚閽堝瓧娈 state 涓 NULL heartbeat_cxt->state = NULL; + // 鍒濆鍖栧瓧娈 total_failed_times 涓 0 heartbeat_cxt->total_failed_times = 0; + // 鍒濆鍖栧瓧娈 last_failed_timestamp 涓 0 heartbeat_cxt->last_failed_timestamp = 0; } @@ -1696,8 +1820,10 @@ void KnlLscContextInit(knl_t_lsc_context *lsc_cxt) lsc_cxt->FetchTupleFromCatCList = NULL; } +// 绾跨▼瑙掕壊鍒濆鍖栧嚱鏁 void knl_thread_init(knl_thread_role role) { + // 璁剧疆绾跨▼鐨勮鑹 t_thrd.role = role; t_thrd.subrole = NO_SUBROLE; t_thrd.proc = NULL; @@ -1707,20 +1833,21 @@ void knl_thread_init(knl_thread_role role) t_thrd.myLogicTid = 10000; t_thrd.fake_session = NULL; t_thrd.threadpool_cxt.reaper_dead_session = false; - ENABLE_MEMORY_PROTECT(); - MemoryContextUnSeal(t_thrd.top_mem_cxt); - t_thrd.mcxt_group = New(t_thrd.top_mem_cxt) MemoryContextGroup(); - t_thrd.mcxt_group->Init(t_thrd.top_mem_cxt); - MemoryContextSeal(t_thrd.top_mem_cxt); - MemoryContextSwitchTo(THREAD_GET_MEM_CXT_GROUP(MEMORY_CONTEXT_DEFAULT)); + ENABLE_MEMORY_PROTECT(); // 鍚敤鍐呭瓨淇濇姢 + MemoryContextUnSeal(t_thrd.top_mem_cxt); // 瑙i櫎椤跺眰鍐呭瓨涓婁笅鏂囩殑灏佸嵃 + t_thrd.mcxt_group = New(t_thrd.top_mem_cxt) MemoryContextGroup(); // 鍒涘缓鍐呭瓨涓婁笅鏂囩粍 + t_thrd.mcxt_group->Init(t_thrd.top_mem_cxt); // 鍒濆鍖栧唴瀛樹笂涓嬫枃缁 + MemoryContextSeal(t_thrd.top_mem_cxt); // 灏佸嵃椤跺眰鍐呭瓨涓婁笅鏂 + // 鍒濆鍖栧悇涓ā鍧楃殑涓婁笅鏂 KnlLscContextInit(&t_thrd.lsc_cxt); - /* CommProxy Support */ + /* CommProxy 鏀寔 */ t_thrd.comm_sock_option = g_default_invalid_sock_opt; t_thrd.comm_epoll_option = g_default_invalid_epoll_opt; t_thrd.comm_poll_option = g_default_invalid_poll_opt; - - knl_t_aes_init(&t_thrd.aes_cxt); + + // 鍒濆鍖栧悇涓ā鍧楃殑涓婁笅鏂 + knl_t_aes_init(&t_thrd.aes_cxt); knl_t_aiocompleter_init(&t_thrd.aio_cxt); knl_t_alarmchecker_init(&t_thrd.alarm_cxt); knl_t_arch_init(&t_thrd.arch); @@ -1821,16 +1948,18 @@ void knl_thread_init(knl_thread_role role) #ifdef ENABLE_MOT knl_t_mot_init(&t_thrd.mot_cxt); #endif - - KnlTGstatInit(&t_thrd.gstat_cxt); + + // 鍒濆鍖栧悇涓ā鍧楃殑涓婁笅鏂 + KnlTGstatInit(&t_thrd.gstat_cxt); // 鍏ㄥ眬缁熻淇℃伅鐨勫垵濮嬪寲 #ifdef DEBUG_UHEAP - knl_t_uheap_stats_init(&t_thrd.uheap_stats_cxt); + knl_t_uheap_stats_init(&t_thrd.uheap_stats_cxt); // UHeap缁熻淇℃伅鐨勫垵濮嬪寲锛堜粎鍦ㄨ皟璇曟ā寮忎笅锛 #endif - KnlDcfContextInit(&t_thrd.dcf_cxt); + KnlDcfContextInit(&t_thrd.dcf_cxt); // DCF妯″潡鐨勫垵濮嬪寲 } + __attribute__ ((__used__)) knl_thrd_context *GetCurrentThread() { return &t_thrd; @@ -1868,4 +1997,3 @@ void RedoPageRepairCallBack(RepairBlockKey key, XLogPhyBlock pblk) t_thrd.xlog_cxt.redoPageRepairCallBackFunc(key, pblk); } } - diff --git a/src/gausskernel/process/threadpool/threadpool_controler.cpp b/src/gausskernel/process/threadpool/threadpool_controler.cpp index 63c13d4a9..dedb9f47a 100644 --- a/src/gausskernel/process/threadpool/threadpool_controler.cpp +++ b/src/gausskernel/process/threadpool/threadpool_controler.cpp @@ -7,16 +7,12 @@ * * http://license.coscl.org.cn/MulanPSL2 * - * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, - * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, - * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. - * See the Mulan PSL v2 for more details. * ------------------------------------------------------------------------- * * threadpool_controler.cpp - * Controler for thread pool. Class ThreadPoolControler is defined to - * initilize thread pool's worker and listener threads, and dispatch - * new session from postmaster thread to suitable thread group. + * 绾跨▼姹犵殑鎺у埗鍣ㄣ傚畾涔変簡 ThreadPoolControler 绫伙紝 + * 鐢ㄤ簬鍒濆鍖栫嚎绋嬫睜鐨勫伐浣滅嚎绋嬪拰鐩戝惉绾跨▼锛屽苟灏嗘柊浼氳瘽浠 + * 涓荤嚎绋嬪垎娲惧埌鍚堥傜殑绾跨▼缁勩 * * * IDENTIFICATION @@ -71,32 +67,33 @@ ThreadPoolControler* g_threadPoolControler = NULL; static const long one_hundred_micro_sec = 100; +// 绾跨▼姹犳帶鍒跺櫒鐨勬瀯閫犲嚱鏁 ThreadPoolControler::ThreadPoolControler() { - m_threadPoolContext = NULL; - m_sessCtrl = NULL; - m_groups = NULL; - m_scheduler = NULL; - m_groupNum = 1; - m_threadNum = 0; - m_maxPoolSize = 0; - m_maxStreamPoolSize = 0; - m_streamProcRatio = 0; + m_threadPoolContext = NULL; // 绾跨▼姹犱笂涓嬫枃 + m_sessCtrl = NULL; // 浼氳瘽鎺у埗 + m_groups = NULL; // 绾跨▼缁 + m_scheduler = NULL; // 璋冨害鍣 + m_groupNum = 1; // 绾跨▼缁勬暟閲 + m_threadNum = 0; // 绾跨▼鏁伴噺 + m_maxPoolSize = 0; // 鏈澶х嚎绋嬫睜澶у皬 + m_maxStreamPoolSize = 0; // 鏈澶ф祦绾跨▼姹犲ぇ灏 + m_streamProcRatio = 0; // 娴佸鐞嗘瘮渚 } ThreadPoolControler::~ThreadPoolControler() { - delete m_scheduler; - delete m_sessCtrl; - MemoryContextDelete(m_threadPoolContext); - m_threadPoolContext = NULL; - m_groups = NULL; - m_sessCtrl = NULL; + delete m_scheduler; // 鍒犻櫎璋冨害鍣ㄥ璞 + delete m_sessCtrl; // 鍒犻櫎浼氳瘽鎺у埗瀵硅薄 + MemoryContextDelete(m_threadPoolContext); // 鍒犻櫎绾跨▼姹犱笂涓嬫枃 + m_threadPoolContext = NULL; // 灏嗙嚎绋嬫睜涓婁笅鏂囩疆涓虹┖ + m_groups = NULL; // 灏嗙嚎绋嬬粍鎸囬拡缃负绌 + m_sessCtrl = NULL; // 灏嗕細璇濇帶鍒舵寚閽堢疆涓虹┖ } void ThreadPoolControler::Init(bool enableNumaDistribute) { - + // 鍒涘缓绾跨▼姹犱笂涓嬫枃 m_threadPoolContext = AllocSetContextCreate(g_instance.instance_context, "ThreadPoolContext", ALLOCSET_DEFAULT_MINSIZE, @@ -104,12 +101,18 @@ void ThreadPoolControler::Init(bool enableNumaDistribute) ALLOCSET_DEFAULT_MAXSIZE, SHARED_CONTEXT); + // 鍒囨崲鍒扮嚎绋嬫睜涓婁笅鏂 AutoContextSwitch memSwitch(m_threadPoolContext); + // 鍒嗛厤绾跨▼缁勬暟缁 m_groups = (ThreadPoolGroup**)palloc(sizeof(ThreadPoolGroup*) * m_groupNum); + + // 鍒涘缓绾跨▼姹犱細璇濇帶鍒跺璞 m_sessCtrl = New(CurrentMemoryContext) ThreadPoolSessControl(CurrentMemoryContext); + // 妫鏌ユ槸鍚︾粦瀹 CPU bool bindCpu = CheckCpuBind(); + // 妫鏌ユ槸鍚︾粦瀹 CPU NUMA bool bindCpuNuma = CheckCpuNumaBind(); int maxThreadNum = 0; int expectThreadNum = 0; @@ -123,16 +126,14 @@ void ThreadPoolControler::Init(bool enableNumaDistribute) while (m_cpuInfo.cpuArrSize[numaId] == 0) numaId++; - /* - * Invoke numa_set_preferred before starting worker thread to make - * more memory allocation local to worker thread. - */ #ifdef __USE_NUMA + // 濡傛灉鍚敤 NUMA 鍒嗛厤锛屽垯璁剧疆棣栭 NUMA 鑺傜偣 if (enableNumaDistribute) { numa_set_preferred(numaId); } #endif + // 鑾峰彇褰撳墠 NUMA 鑺傜偣鐨 CPU 鏁伴噺 Assert(numaId < m_cpuInfo.totalNumaNum); expectThreadNum = (int)round( (double)m_threadNum * ((double)m_cpuInfo.cpuArrSize[numaId] / (double)m_cpuInfo.activeCpuNum)); @@ -143,30 +144,35 @@ void ThreadPoolControler::Init(bool enableNumaDistribute) cpuNum = m_cpuInfo.cpuArrSize[numaId]; cpuArr = m_cpuInfo.cpuArr[numaId]; + // 澧炲姞 NUMA ID锛屼互澶勭悊涓嬩竴涓 NUMA 鑺傜偣 numaId++; } else { + // 濡傛灉鏈粦瀹 CPU锛屽垯鍧囧寑鍒嗛厤绾跨▼鍜屾祦鐨勬暟閲 expectThreadNum = m_threadNum / m_groupNum; maxThreadNum = m_maxPoolSize / m_groupNum; maxStreamNum = m_maxPoolSize / m_groupNum; numaId = -1; } + // 鍒涘缓绾跨▼姹犵粍瀵硅薄骞跺垵濮嬪寲 m_groups[i] = New(CurrentMemoryContext)ThreadPoolGroup(maxThreadNum, expectThreadNum, maxStreamNum, i, numaId, cpuNum, cpuArr, bindCpuNuma); m_groups[i]->Init(enableNumaDistribute); } + // 绛夊緟鎵鏈夌嚎绋嬫睜缁勫噯澶囧氨缁 for (int i = 0; i < m_groupNum; i++) { m_groups[i]->WaitReady(); } #ifdef __USE_NUMA if (enableNumaDistribute) { - /* Set to interleave mode for other than worker thread */ + /* 璁剧疆涓轰氦缁囨ā寮忎互渚涢櫎宸ヤ綔绾跨▼涔嬪鐨勫叾浠栫嚎绋嬩娇鐢 */ numa_set_interleave_mask(numa_all_nodes_ptr); } #endif + // 鍒涘缓绾跨▼姹犺皟搴﹀櫒瀵硅薄骞跺惎鍔 m_scheduler = New(CurrentMemoryContext) ThreadPoolScheduler(m_groupNum, m_groups); m_scheduler->StartUp(); } @@ -194,9 +200,10 @@ void AdjustThreadAffinity(void) { cpu_set_t m_cpuset; CPU_ZERO(&m_cpuset); - /* Check if the instance has been attch to some specific CPUs. */ + // 妫鏌ュ疄渚嬫槸鍚﹀凡缁戝畾鍒版煇浜涚壒瀹氱殑 CPU int ret = pthread_getaffinity_np(PostmasterPid, sizeof(cpu_set_t), &m_cpuset); if (ret == 0) { + // 濡傛灉缁戝畾鍒 CPU 0 鑰屾湭缁戝畾鍒 CPU 1锛屽垯閲嶆柊璁剧疆 CPU 浜插拰鎬э紝浠ラ伩鍏嶇粦瀹氬埌鍗曚竴 CPU if ((CPU_ISSET(0, &m_cpuset)) && (!CPU_ISSET(1, &m_cpuset))) { int num_processors = sysconf(_SC_NPROCESSORS_CONF); CPU_ZERO(&m_cpuset); @@ -204,7 +211,7 @@ void AdjustThreadAffinity(void) { CPU_SET(j, &m_cpuset); } - // set CPU affinity of a thread + // 璁剧疆绾跨▼鐨 CPU 浜插拰鎬 int s = pthread_setaffinity_np(PostmasterPid, sizeof(cpu_set_t), &m_cpuset); if (s != 0) { ereport(WARNING, (errmsg("AdjustThreadAffinity fail to bind thread %lu, errno: %d", PostmasterPid, ret))); @@ -213,17 +220,16 @@ void AdjustThreadAffinity(void) { } } - -void ThreadPoolControler::GetInstanceBind(cpu_set_t *cpuset) -{ - /* this function is used to avoid the libgomp bug on some specified OS */ +void ThreadPoolControler::GetInstanceBind(cpu_set_t *cpuset) { + // 淇 libgomp 鍦ㄦ煇浜涙寚瀹氭搷浣滅郴缁熶笂鐨 bug AdjustThreadAffinity(); - /* Check if the instance has been attch to some specific CPUs. */ + // 妫鏌ュ疄渚嬫槸鍚﹀凡缁戝畾鍒版煇浜涚壒瀹氱殑 CPU int ret = pthread_getaffinity_np(PostmasterPid, sizeof(cpu_set_t), cpuset); if (ret == 0) { return; } else { + // 鍒濆鍖 cpuset锛屼互閬垮厤鏈粦瀹氱殑鎯呭喌 errno_t rc = memset_s(cpuset, sizeof(cpu_set_t), 0, sizeof(cpu_set_t)); securec_check(rc, "\0", "\0"); } @@ -235,7 +241,7 @@ void ThreadPoolControler::ParseAttr() m_attr.groupNum = DEFAULT_THREAD_POOL_GROUPS; m_attr.bindCpu = NULL; - /* Do str copy and remove space. */ + /* 澶嶅埗瀛楃涓插苟绉婚櫎绌烘牸 */ char* attr = TrimStr(g_instance.attr.attr_common.thread_pool_attr); if (IS_NULL_STR(attr)) return; @@ -244,13 +250,13 @@ void ThreadPoolControler::ParseAttr() char* psave = NULL; const char* pdelimiter = ","; - /* Get thread num */ + /* 鑾峰彇绾跨▼鏁 */ ptoken = TrimStr(strtok_r(attr, pdelimiter, &psave)); if (!IS_NULL_STR(ptoken)) m_attr.threadNum = pg_strtoint32(ptoken); pfree_ext(ptoken); - /* Ger group num */ + /* 鑾峰彇绾跨▼缁勬暟 */ ptoken = TrimStr(strtok_r(NULL, pdelimiter, &psave)); if (!IS_NULL_STR(ptoken)) m_attr.groupNum = pg_strtoint32(ptoken); @@ -258,15 +264,15 @@ void ThreadPoolControler::ParseAttr() if (m_attr.threadNum < 0 || m_attr.threadNum > MAX_THREAD_POOL_SIZE) INVALID_ATTR_ERROR( - errdetail("Current thread num %d is out of range [%d, %d].", m_attr.threadNum, 0, MAX_THREAD_POOL_SIZE)); + errdetail("褰撳墠绾跨▼鏁 %d 瓒呭嚭鑼冨洿 [%d, %d]銆", m_attr.threadNum, 0, MAX_THREAD_POOL_SIZE)); if (m_attr.groupNum < 0 || m_attr.groupNum > MAX_THREAD_POOL_GROUPS) INVALID_ATTR_ERROR( - errdetail("Current group num %d is out of range [%d, %d].", m_attr.groupNum, 0, MAX_THREAD_POOL_GROUPS)); + errdetail("褰撳墠绾跨▼缁勬暟 %d 瓒呭嚭鑼冨洿 [%d, %d]銆", m_attr.groupNum, 0, MAX_THREAD_POOL_GROUPS)); - /* Get attach cpu */ + /* 鑾峰彇缁戝畾 CPU */ m_attr.bindCpu = TrimStr(psave); ParseBindCpu(); - + pfree_ext(attr); } @@ -276,7 +282,8 @@ void ThreadPoolControler::ParseStreamAttr() m_stream_attr.procRatio = DEFAULT_THREAD_POOL_STREAM_PROC_RATIO; m_stream_attr.groupNum = DEFAULT_THREAD_POOL_GROUPS; m_stream_attr.bindCpu = NULL; - + + // 鑾峰彇娴佸紡绾跨▼姹犲睘鎬ч厤缃瓧绗︿覆 char* attr = TrimStr(g_instance.attr.attr_common.thread_pool_stream_attr); if (IS_NULL_STR(attr)) { return; @@ -285,36 +292,36 @@ void ThreadPoolControler::ParseStreamAttr() char* ptoken = NULL; char* psave = NULL; const char* pdelimiter = ","; - - /* Get stream_thread_pool_stream max thread num */ + + // 瑙f瀽娴佸紡绾跨▼姹犵殑鏈澶х嚎绋嬫暟 ptoken = TrimStr(strtok_r(attr, pdelimiter, &psave)); if (IS_NULL_STR(ptoken) || !isdigit((unsigned char)*ptoken)) { INVALID_ATTR_ERROR( - errdetail("Current thread_pool_stream_attr format is error, stream_thread_num must be digital.")); + errdetail("褰撳墠 thread_pool_stream_attr 鏍煎紡閿欒锛宻tream_thread_num 蹇呴』涓烘暟瀛椼")); } m_stream_attr.threadNum = pg_strtoint32(ptoken); pfree_ext(ptoken); if (m_stream_attr.threadNum < 0 || m_stream_attr.threadNum > MAX_THREAD_POOL_SIZE) { INVALID_ATTR_ERROR( - errdetail("Current stream_thread_num %d is out of range [%d, %d].", + errdetail("褰撳墠 stream_thread_num %d 瓒呭嚭鑼冨洿 [%d, %d]銆", m_stream_attr.threadNum, 0, MAX_THREAD_POOL_SIZE)); } - - /* Get proc ratio of stream threads */ + + // 瑙f瀽娴佸紡绾跨▼姹犵殑澶勭悊姣斾緥 ptoken = TrimStr(strtok_r(NULL, pdelimiter, &psave)); if (IS_NULL_STR(ptoken) || !isdigit((unsigned char)*ptoken)) { INVALID_ATTR_ERROR( - errdetail("Current thread_pool_stream_attr format is error, stream_proc_ratio must be digital.")); + errdetail("褰撳墠 thread_pool_stream_attr 鏍煎紡閿欒锛宻tream_proc_ratio 蹇呴』涓烘暟瀛椼")); } m_stream_attr.procRatio = atof(ptoken); pfree_ext(ptoken); if (m_stream_attr.procRatio <= 0 || m_stream_attr.procRatio > MAX_THREAD_POOL_STREAM_PROC_RATIO) { INVALID_ATTR_ERROR( - errdetail("Current stream_proc_ratio %f is out of range (%d, %d].", + errdetail("褰撳墠 stream_proc_ratio %f 瓒呭嚭鑼冨洿 (%d, %d]銆", m_stream_attr.procRatio, 0, MAX_THREAD_POOL_STREAM_PROC_RATIO)); } pfree_ext(attr); - + return; } @@ -325,6 +332,7 @@ void ThreadPoolControler::ParseBindCpu() return; } + // 澶嶅埗灞炴у瓧绗︿覆浠ヨ繘琛岃В鏋 char* pattr = pstrdup(m_attr.bindCpu); char* scpu = pattr; char* ptoken = NULL; @@ -332,15 +340,18 @@ void ThreadPoolControler::ParseBindCpu() const char* pdelimiter = ":"; int bindNum = 0; + // 妫鏌ュ睘鎬у瓧绗︿覆鐨勬牸寮忔槸鍚︽纭 if (scpu[0] != '(' || scpu[strlen(scpu) - 1] != ')') - INVALID_ATTR_ERROR("Use '(' ')' to indicate cpu bind info."); + INVALID_ATTR_ERROR("浣跨敤 '(' ')' 鏉ヨ〃绀 CPU 缁戝畾淇℃伅銆"); scpu++; scpu[strlen(scpu) - 1] = '\0'; + // 瑙f瀽灞炴у瓧绗︿覆骞惰浆鎹负灏忓啓 ptoken = TrimStr(strtok_r(scpu, pdelimiter, &psave)); ptoken = pg_strtolower(ptoken); + // 鏍规嵁涓嶅悓鐨勫睘鎬х被鍨嬭繘琛岃В鏋 if (strncmp("nobind", ptoken, strlen("nobind")) == 0) { m_cpuInfo.bindType = NO_CPU_BIND; return; @@ -360,16 +371,16 @@ void ThreadPoolControler::ParseBindCpu() m_cpuInfo.isBindCpuNumaArr = (bool*)palloc0(sizeof(bool) * m_cpuInfo.totalCpuNum); bindNum = ParseRangeStr(psave, m_cpuInfo.isBindCpuNumaArr, m_cpuInfo.totalCpuNum, "numabind"); } else { - INVALID_ATTR_ERROR(errdetail("Only 'nobind', 'allbind', 'cpubind', 'nodebind' and 'numabind' " - "are valid attribute.")); + INVALID_ATTR_ERROR(errdetail("鍙湁 'nobind', 'allbind', 'cpubind', 'nodebind' 鍜 'numabind' " + "鏄湁鏁堢殑灞炴с")); } + // 妫鏌ユ槸鍚︽壘鍒版湁鏁堢殑 CPU 杩涜绾跨▼缁戝畾 if (bindNum == 0) INVALID_ATTR_ERROR( - errdetail("Can not find valid CPU for thread binding, there are two possible reasons:\n" - "1. These CPUs are not active, use lscpu to check On-line CPU(s) list.\n" - "2. The process has been bind to other CPUs and there is no intersection," - "use taskset -pc to check process CPU bind info.\n")); + errdetail("鏃犳硶鎵惧埌鏈夋晥鐨 CPU 杩涜绾跨▼缁戝畾锛屽彲鑳界殑鍘熷洜鏈変袱涓細\n" + "1. 杩欎簺 CPU 涓嶅浜庢椿鍔ㄧ姸鎬侊紝璇蜂娇鐢 lscpu 鍛戒护妫鏌ュ湪绾 CPU 鍒楄〃銆俓n" + "2. 杩涚▼宸茬粦瀹氬埌鍏朵粬 CPU锛屼笖娌℃湁浜ら泦锛岃浣跨敤 taskset -pc 鍛戒护妫鏌ヨ繘绋 CPU 缁戝畾淇℃伅銆俓n")); pfree_ext(ptoken); pfree_ext(pattr); } @@ -381,6 +392,7 @@ int ThreadPoolControler::ParseRangeStr(char* attr, bool* arr, int totalNum, char const char* pdelimiter = ","; int retNum = 0; + // 瑙f瀽灞炴у瓧绗︿覆 ptoken = TrimStr(strtok_r(attr, pdelimiter, &psave)); while (!IS_NULL_STR(ptoken)) { @@ -390,25 +402,29 @@ int ThreadPoolControler::ParseRangeStr(char* attr, bool* arr, int totalNum, char int startid = -1; int endid = -1; + // 瑙f瀽鑼冨洿瀛楃涓诧紝鍙兘鍖呭惈璧峰鍜岀粨鏉熷 pt = TrimStr(strtok_r(ptoken, pd, &ps)); if (!IS_NULL_STR(pt)) startid = pg_strtoint32(pt); if (!IS_NULL_STR(ps)) endid = pg_strtoint32(ps); + // 妫鏌ヨВ鏋愮殑鍊兼槸鍚︽湁鏁 if (startid < 0 && endid < 0) - INVALID_ATTR_ERROR(errdetail("Can not parse attribute %s", pt)); + INVALID_ATTR_ERROR(errdetail("鏃犳硶瑙f瀽灞炴 %s", pt)); if (startid >= totalNum) INVALID_ATTR_ERROR( - errdetail("The %s attribute %d is out of valid range [%d, %d]", bindtype, startid, 0, totalNum - 1)); + errdetail("灞炴 %s 涓殑 %d 瓒呭嚭浜嗘湁鏁堣寖鍥 [%d, %d]", bindtype, startid, 0, totalNum - 1)); if (endid >= totalNum) INVALID_ATTR_ERROR( - errdetail("The %s attribute %d is out of valid range [%d, %d]", bindtype, endid, 0, totalNum - 1)); + errdetail("灞炴 %s 涓殑 %d 瓒呭嚭浜嗘湁鏁堣寖鍥 [%d, %d]", bindtype, endid, 0, totalNum - 1)); if (endid == -1) { + // 鍗曚釜 CPU 缁戝畾 retNum += arr[startid] ? 0 : 1; arr[startid] = true; } else { + // 鑼冨洿鍐呯殑澶氫釜 CPU 缁戝畾 if (startid > endid) { int tmpid = startid; startid = endid; @@ -421,7 +437,7 @@ int ThreadPoolControler::ParseRangeStr(char* attr, bool* arr, int totalNum, char } } - /* Don't need to free when error ocurrs, errors here are FATAL level! */ + // 閲婃斁涓存椂瀛楃涓插唴瀛橈紝涓嶉渶瑕佸湪閿欒鍙戠敓鏃堕噴鏀撅紝杩欓噷鐨勯敊璇槸鑷村懡鐨勶紒 pfree_ext(pt); pfree_ext(ptoken); ptoken = TrimStr(strtok_r(NULL, pdelimiter, &psave)); @@ -438,9 +454,8 @@ bool* ThreadPoolControler::GetMcsCpuInfo(int totalCpuNum) bool* isMcsCpuArr = (bool*)palloc0(sizeof(bool) * totalCpuNum); /* - * When the database is deplyed on MCS, we need to read cpuset.cpus to find - * available CPUs in this MCS. If we can read this file, then we think all - * CPUs are available. + * 褰撴暟鎹簱閮ㄧ讲鍦∕CS涓婃椂锛屾垜浠渶瑕佽鍙朿puset.cpus鏂囦欢浠ユ煡鎵炬MCS涓彲鐢ㄧ殑CPU銆 + * 濡傛灉鎴戜滑鑳藉璇诲彇姝ゆ枃浠讹紝閭d箞鎴戜滑璁や负鎵鏈塁PU閮芥槸鍙敤鐨勩 */ fp = fopen("/sys/fs/cgroup/cpuset/cpuset.cpus", "r"); if (fp == NULL) { @@ -473,11 +488,12 @@ bool* ThreadPoolControler::GetMcsCpuInfo(int totalCpuNum) void ThreadPoolControler::GetActiveCpu(NumaCpuId *numaCpuIdList, int *num) { - *num = 0; + *num = 0; // 鍒濆鍖栦紶鍑哄弬鏁 num 涓 0 char buf[BUFSIZE]; - FILE* fp = popen("lscpu -b -e=cpu,node", "r"); + FILE* fp = popen("lscpu -b -e=cpu,node", "r"); // 鎵撳紑涓涓敤浜庤鍙 CPU 淇℃伅鐨勬祦 + if (fp == NULL) { - ereport(WARNING, (errmsg("Unable to use 'lscpu' to read CPU info."))); + ereport(WARNING, (errmsg("Unable to use 'lscpu' to read CPU info."))); // 濡傛灉鎵撳紑娴佸け璐ワ紝鍙戝嚭璀﹀憡娑堟伅 return; } @@ -486,45 +502,49 @@ void ThreadPoolControler::GetActiveCpu(NumaCpuId *numaCpuIdList, int *num) const char* pdelimiter = " "; int cpuid = 0; int numaid = 0; - /* try to read the header. */ + + // 灏濊瘯璇诲彇澶撮儴淇℃伅 if (fgets(buf, sizeof(buf), fp) != NULL) { while (fgets(buf, sizeof(buf), fp) != NULL) { ptoken = strtok_r(buf, pdelimiter, &psave); if (!IS_NULL_STR(ptoken)) { - cpuid = pg_strtoint32(ptoken); + cpuid = pg_strtoint32(ptoken); // 瑙f瀽 CPU ID } ptoken = strtok_r(NULL, pdelimiter, &psave); if (!IS_NULL_STR(ptoken)) { - numaid = pg_strtoint32(ptoken); + numaid = pg_strtoint32(ptoken); // 瑙f瀽 NUMA ID } - numaCpuIdList[*num].cpuId = cpuid; - numaCpuIdList[*num].numaId = numaid; - (*num)++; + numaCpuIdList[*num].cpuId = cpuid; // 灏 CPU ID 瀛樺叆浼犲嚭鍙傛暟 + numaCpuIdList[*num].numaId = numaid; // 灏 NUMA ID 瀛樺叆浼犲嚭鍙傛暟 + (*num)++; // 閫掑浼犲嚭鍙傛暟 num } } - pclose(fp); + pclose(fp); // 鍏抽棴娴 } void ThreadPoolControler::GetSysCpuInfo() { if (m_cpuInfo.totalNumaNum == 0 || m_cpuInfo.totalCpuNum == 0) { - ereport(WARNING, (errmsg("Fail to read cpu num or numa num."))); + ereport(WARNING, (errmsg("Fail to read cpu num or numa num."))); // 濡傛灉娌℃湁璇诲彇鍒 CPU 鏁伴噺鎴 NUMA 鏁伴噺锛屽彂鍑鸿鍛婃秷鎭 return; } - m_cpuInfo.isMcsCpuArr = GetMcsCpuInfo(m_cpuInfo.totalCpuNum); + m_cpuInfo.isMcsCpuArr = GetMcsCpuInfo(m_cpuInfo.totalCpuNum); // 鑾峰彇 MCS CPU 淇℃伅 m_cpuInfo.cpuArr = (int**)palloc0(sizeof(int*) * m_cpuInfo.totalNumaNum); m_cpuInfo.cpuArrSize = (int*)palloc0(sizeof(int) * m_cpuInfo.totalNumaNum); int cpu_per_numa = m_cpuInfo.totalCpuNum / m_cpuInfo.totalNumaNum; + for (int i = 0; i < m_cpuInfo.totalNumaNum; i++) { - m_cpuInfo.cpuArr[i] = (int*)palloc0(sizeof(int) * cpu_per_numa); + m_cpuInfo.cpuArr[i] = (int*)palloc0(sizeof(int) * cpu_per_numa); // 涓烘瘡涓 NUMA 鑺傜偣鍒嗛厤鍐呭瓨 } + m_cpuInfo.activeCpuNum = 0; NumaCpuId *sysNumaCpuIdList = (NumaCpuId*)palloc0(sizeof(NumaCpuId) * m_cpuInfo.totalCpuNum); int sysNumaCpuIdNum = 0; - GetActiveCpu(sysNumaCpuIdList, &sysNumaCpuIdNum); + + GetActiveCpu(sysNumaCpuIdList, &sysNumaCpuIdNum); // 鑾峰彇婵娲荤殑 CPU 淇℃伅 if (sysNumaCpuIdNum == 0) { return; @@ -533,56 +553,58 @@ void ThreadPoolControler::GetSysCpuInfo() for (int i = 0; i < sysNumaCpuIdNum; ++i) { int cpuid = sysNumaCpuIdList[i].cpuId; int numaid = sysNumaCpuIdList[i].numaId; + if (IsActiveCpu(cpuid, numaid)) { - m_cpuInfo.cpuArr[numaid][m_cpuInfo.cpuArrSize[numaid]] = cpuid; - m_cpuInfo.cpuArrSize[numaid]++; - m_cpuInfo.activeCpuNum++; + m_cpuInfo.cpuArr[numaid][m_cpuInfo.cpuArrSize[numaid]] = cpuid; // 灏 CPU ID 瀛樺叆鐩稿簲 NUMA 鑺傜偣鐨勬暟缁勪腑 + m_cpuInfo.cpuArrSize[numaid]++; // 閫掑鐩稿簲 NUMA 鑺傜偣鐨勬暟缁勫ぇ灏 + m_cpuInfo.activeCpuNum++; // 閫掑婵娲荤殑 CPU 鏁伴噺 } - } - pfree_ext(sysNumaCpuIdList); + pfree_ext(sysNumaCpuIdList); // 閲婃斁鍐呭瓨 for (int i = 0; i < m_cpuInfo.totalNumaNum; i++) { if (m_cpuInfo.cpuArrSize[i] > 0) - m_cpuInfo.activeNumaNum++; + m_cpuInfo.activeNumaNum++; // 缁熻婵娲荤殑 NUMA 鑺傜偣鏁伴噺 } } void ThreadPoolControler::InitCpuInfo() { - m_cpuInfo.totalCpuNum = 0; - m_cpuInfo.activeCpuNum = 0; - m_cpuInfo.totalNumaNum = 0; - m_cpuInfo.activeNumaNum = 0; - m_cpuInfo.cpuArrSize = NULL; - m_cpuInfo.cpuArr = NULL; + m_cpuInfo.totalCpuNum = 0; // 鍒濆鍖栨 CPU 鏁伴噺涓 0 + m_cpuInfo.activeCpuNum = 0; // 鍒濆鍖栨縺娲荤殑 CPU 鏁伴噺涓 0 + m_cpuInfo.totalNumaNum = 0; // 鍒濆鍖栨 NUMA 鑺傜偣鏁伴噺涓 0 + m_cpuInfo.activeNumaNum = 0; // 鍒濆鍖栨縺娲荤殑 NUMA 鑺傜偣鏁伴噺涓 0 + m_cpuInfo.cpuArrSize = NULL; // 鍒濆鍖 CPU 鏁扮粍澶у皬涓 NULL + m_cpuInfo.cpuArr = NULL; // 鍒濆鍖 CPU 鏁扮粍涓 NULL - m_cpuInfo.bindType = NO_CPU_BIND; - m_cpuInfo.isBindCpuArr = NULL; - m_cpuInfo.isBindNumaArr = NULL; - m_cpuInfo.isMcsCpuArr = NULL; + m_cpuInfo.bindType = NO_CPU_BIND; // 鍒濆鍖 CPU 缁戝畾绫诲瀷涓 NO_CPU_BIND + m_cpuInfo.isBindCpuArr = NULL; // 鍒濆鍖 CPU 缁戝畾鏁扮粍涓 NULL + m_cpuInfo.isBindNumaArr = NULL; // 鍒濆鍖 NUMA 鑺傜偣缁戝畾鏁扮粍涓 NULL + m_cpuInfo.isMcsCpuArr = NULL; // 鍒濆鍖 MCS CPU 鏁扮粍涓 NULL } void ThreadPoolControler::GetCpuAndNumaNum(int32 *totalCpuNum, int32 *totalNumaNum) { char buf[BUFSIZE]; - FILE* fp = NULL; + // 鎵撳紑 "lscpu" 鍛戒护鐨勮緭鍑轰互鑾峰彇 CPU 鍜 NUMA 鑺傜偣鏁伴噺淇℃伅 if ((fp = popen("LANG=en_US.UTF-8;lscpu", "r")) != NULL) { while (fgets(buf, sizeof(buf), fp) != NULL) { if (strncmp("CPU(s)", buf, strlen("CPU(s)")) == 0 && strncmp("On-line CPU(s) list", buf, strlen("On-line CPU(s) list")) != 0 && strncmp("NUMA node", buf, strlen("NUMA node")) != 0) { + // 褰撻亣鍒板寘鍚 "CPU(s)" 鐨勮鏃讹紝瑙f瀽骞惰幏鍙栨 CPU 鏁伴噺 char* loc = strchr(buf, ':'); *totalCpuNum = pg_strtoint32(loc + 1); } else if (strncmp("NUMA node(s)", buf, strlen("NUMA node(s)")) == 0) { + // 褰撻亣鍒板寘鍚 "NUMA node(s)" 鐨勮鏃讹紝瑙f瀽骞惰幏鍙栨 NUMA 鑺傜偣鏁伴噺 char* loc = strchr(buf, ':'); *totalNumaNum = pg_strtoint32(loc + 1); } } - pclose(fp); + pclose(fp); // 鍏抽棴鏂囦欢娴 } } @@ -591,67 +613,72 @@ bool ThreadPoolControler::IsActiveCpu(int cpuid, int numaid) switch (m_cpuInfo.bindType) { case NO_CPU_BIND: case ALL_CPU_BIND: + // 濡傛灉鏈繘琛 CPU 缁戝畾锛屾垨鑰呰繘琛屼簡鍏ㄥ眬 CPU 缁戝畾锛屾鏌 CPU 鏄惁婵娲 return (m_cpuInfo.isMcsCpuArr[cpuid] && CPU_ISSET(cpuid, &m_cpuset)); case NODE_BIND: + // 濡傛灉杩涜浜 NUMA 鑺傜偣缁戝畾锛屾鏌 CPU 鍜 NUMA 鑺傜偣鏄惁婵娲 return (m_cpuInfo.isBindNumaArr[numaid] && m_cpuInfo.isMcsCpuArr[cpuid] && CPU_ISSET(cpuid, &m_cpuset)); case CPU_BIND: + // 濡傛灉杩涜浜 CPU 缁戝畾锛屾鏌 CPU 鏄惁婵娲 return (m_cpuInfo.isBindCpuArr[cpuid] && m_cpuInfo.isMcsCpuArr[cpuid] && CPU_ISSET(cpuid, &m_cpuset)); case NUMA_BIND: + // 濡傛灉杩涜浜 NUMA 鑺傜偣鍜 CPU 缁戝畾锛屾鏌 CPU 鍜 NUMA 鑺傜偣鏄惁婵娲 return (m_cpuInfo.isBindCpuNumaArr[cpuid] && m_cpuInfo.isMcsCpuArr[cpuid] && CPU_ISSET(cpuid, &m_cpuset)); } - return false; + return false; // 榛樿鎯呭喌涓嬶紝杩斿洖 false } bool ThreadPoolControler::CheckCpuBind() const { if (m_cpuInfo.bindType == NO_CPU_BIND) - return false; + return false; // 濡傛灉娌℃湁杩涜 CPU 缁戝畾锛屽垯杩斿洖 false + if (m_groupNum != m_cpuInfo.activeNumaNum) { ereport(WARNING, - (errmsg("Can not bind worker thread to CPU because the " - "thread group num must equal to active NUMA num."))); - return false; - } - if (m_cpuInfo.activeCpuNum == 0 || m_cpuInfo.cpuArr == NULL) { - ereport(WARNING, (errmsg("Can not bind worker thread to CPU because no valid CPUs."))); - return false; + (errmsg("鏃犳硶灏嗗伐浣滅嚎绋嬬粦瀹氬埌 CPU锛屽洜涓虹嚎绋嬬粍鏁板繀椤荤瓑浜庢縺娲荤殑 NUMA 鑺傜偣鏁般"))); + return false; // 濡傛灉绾跨▼缁勬暟涓嶇瓑浜庢縺娲荤殑 NUMA 鑺傜偣鏁帮紝杩斿洖 false } - return true; + if (m_cpuInfo.activeCpuNum == 0 || m_cpuInfo.cpuArr == NULL) { + ereport(WARNING, (errmsg("鏃犳硶灏嗗伐浣滅嚎绋嬬粦瀹氬埌 CPU锛屽洜涓烘病鏈夋湁鏁堢殑 CPU銆"))); + return false; // 濡傛灉娌℃湁鏈夋晥鐨 CPU锛岃繑鍥 false + } + + return true; // 鍏朵粬鎯呭喌涓嬶紝杩斿洖 true } bool ThreadPoolControler::CheckCpuNumaBind() const { - return m_cpuInfo.bindType == NUMA_BIND; + return m_cpuInfo.bindType == NUMA_BIND; // 濡傛灉杩涜浜 NUMA 缁戝畾锛岃繑鍥 true锛屽惁鍒欒繑鍥 false } bool ThreadPoolControler::CheckNumaDistribute(int numaNodeNum) const { if (m_cpuInfo.bindType == NO_CPU_BIND) { ereport(WARNING, - (errmsg("allbind should be used to replace nobind in thread_pool_attr when NUMA is activated."))); - return false; + (errmsg("鍦ㄦ縺娲 NUMA 鏃讹紝搴斾娇鐢 allbind 鏉ユ浛浠 nobind 鍦 thread_pool_attr 涓"))); + return false; // 濡傛灉鏈繘琛 CPU 缁戝畾锛岀粰鍑鸿鍛婂苟杩斿洖 false } if (!CheckCpuBind()) { - return false; + return false; // 濡傛灉 CPU 缁戝畾妫鏌ュけ璐ワ紝杩斿洖 false } if (m_cpuInfo.totalNumaNum != numaNodeNum || !m_cpuInfo.cpuArrSize) { ereport(WARNING, - (errmsg("Can not activate NUMA distribute because no multiple NUMA nodes or CPUs are available."))); - return false; + (errmsg("鏃犳硶婵娲 NUMA 鍒嗗竷锛屽洜涓烘病鏈夊涓 NUMA 鑺傜偣鎴栧彲鐢ㄧ殑 CPU銆"))); + return false; // 濡傛灉 NUMA 鑺傜偣鏁颁笉绛変簬缁欏畾鐨 numaNodeNum锛屾垨鑰 cpuArrSize 涓虹┖锛岃繑鍥 false } for (int i = 0; i < m_cpuInfo.totalNumaNum; ++i) { if (m_cpuInfo.cpuArrSize[i] <= 0) { ereport(WARNING, - (errmsg("Can not activate NUMA distribute because no available cpu in node %d.", i))); - return false; + (errmsg("鏃犳硶婵娲 NUMA 鍒嗗竷锛屽洜涓鸿妭鐐 %d 涓病鏈夊彲鐢ㄧ殑 CPU銆", i))); + return false; // 濡傛灉鏌愪釜 NUMA 鑺傜偣涓病鏈夊彲鐢ㄧ殑 CPU锛岃繑鍥 false } } - return true; + return true; // 鍏朵粬鎯呭喌涓嬶紝杩斿洖 true } CPUBindType ThreadPoolControler::GetCpuBindType() const @@ -669,55 +696,54 @@ void ThreadPoolControler::SetGroupAndThreadNum() { if (m_attr.groupNum == 0) { if (m_cpuInfo.totalNumaNum > 0) - m_groupNum = m_cpuInfo.activeNumaNum; + m_groupNum = m_cpuInfo.activeNumaNum; // 濡傛灉鏈寚瀹氱嚎绋嬬粍鏁颁笖瀛樺湪 NUMA 鑺傜偣锛屽垯浣跨敤婵娲荤殑 NUMA 鑺傜偣鏁 else - m_groupNum = DEFAULT_THREAD_POOL_GROUPS; + m_groupNum = DEFAULT_THREAD_POOL_GROUPS; // 鍚﹀垯浣跨敤榛樿鐨勭嚎绋嬬粍鏁 } else { - m_groupNum = m_attr.groupNum; + m_groupNum = m_attr.groupNum; // 濡傛灉鎸囧畾浜嗙嚎绋嬬粍鏁帮紝鍒欎娇鐢ㄦ寚瀹氱殑绾跨▼缁勬暟 } if (m_attr.threadNum == 0) { if (m_cpuInfo.activeCpuNum > 0) - m_threadNum = m_cpuInfo.activeCpuNum * THREAD_CORE_RATIO; + m_threadNum = m_cpuInfo.activeCpuNum * THREAD_CORE_RATIO; // 濡傛灉鏈寚瀹氱嚎绋嬫暟涓斿瓨鍦ㄦ縺娲荤殑 CPU锛屽垯璁$畻绾跨▼鏁 else - m_threadNum = DEFAULT_THREAD_POOL_SIZE; + m_threadNum = DEFAULT_THREAD_POOL_SIZE; // 鍚﹀垯浣跨敤榛樿鐨勭嚎绋嬫暟 } else { - m_threadNum = m_attr.threadNum; + m_threadNum = m_attr.threadNum; // 濡傛灉鎸囧畾浜嗙嚎绋嬫暟锛屽垯浣跨敤鎸囧畾鐨勭嚎绋嬫暟 } - ConstrainThreadNum(); + ConstrainThreadNum(); // 璋冪敤 ConstrainThreadNum 鏂规硶杩涜绾跨▼鏁扮害鏉 } void ThreadPoolControler::ConstrainThreadNum() { - /* Thread pool size should not be larger than max_connections. */ + /* 绾跨▼姹犲ぇ灏忎笉搴旇秴杩 max_connections銆 */ if (MAX_THREAD_POOL_SIZE > g_instance.attr.attr_network.MaxConnections) { ereport(LOG, (errcode(ERRCODE_OPERATE_INVALID_PARAM), - errmsg("Max thread pool size %d should not be larger than max_connections %d, " - "so reduce max thread pool size to max_connections", + errmsg("鏈澶х嚎绋嬫睜澶у皬 %d 涓嶅簲瓒呰繃 max_connections %d锛屽洜姝ゅ皢鏈澶х嚎绋嬫睜澶у皬鍑忓皬鍒 max_connections", MAX_THREAD_POOL_SIZE, g_instance.attr.attr_network.MaxConnections))); } - m_maxPoolSize = Min(MAX_THREAD_POOL_SIZE, g_instance.attr.attr_network.MaxConnections); - m_threadNum = Min(m_threadNum, m_maxPoolSize); + m_maxPoolSize = Min(MAX_THREAD_POOL_SIZE, g_instance.attr.attr_network.MaxConnections); // 鏈澶х嚎绋嬫睜澶у皬鍙楅檺浜 max_connections + m_threadNum = Min(m_threadNum, m_maxPoolSize); // 绾跨▼鏁颁笉搴旇秴杩囨渶澶х嚎绋嬫睜澶у皬 } int ThreadPoolControler::GetThreadNum() { - return m_maxPoolSize; + return m_maxPoolSize; // 杩斿洖鏈澶х嚎绋嬫睜澶у皬 } ThreadPoolStat* ThreadPoolControler::GetThreadPoolStat(uint32* num) { - ThreadPoolStat* result = (ThreadPoolStat*)palloc(m_groupNum * sizeof(ThreadPoolStat)); + ThreadPoolStat* result = (ThreadPoolStat*)palloc(m_groupNum * sizeof(ThreadPoolStat)); // 鍒嗛厤瀛樺偍绾跨▼姹犵粺璁′俊鎭殑鍐呭瓨 int i; for (i = 0; i < m_groupNum; i++) { - m_groups[i]->GetThreadPoolGroupStat(&result[i]); + m_groups[i]->GetThreadPoolGroupStat(&result[i]); // 鑾峰彇姣忎釜绾跨▼缁勭殑缁熻淇℃伅 } - *num = m_groupNum; - return result; + *num = m_groupNum; // 杩斿洖绾跨▼缁勬暟閲 + return result; // 杩斿洖绾跨▼姹犵粺璁′俊鎭暟缁 } void ThreadPoolControler::CloseAllSessions() @@ -725,14 +751,14 @@ void ThreadPoolControler::CloseAllSessions() ereport(LOG, (errmodule(MOD_THREAD_POOL), errmsg("pmState:%d, start to close all sessions in threadpool.", pmState))); - m_sessCtrl->MarkAllSessionClose(); - (void)SignalCancelAllBackEnd(); + m_sessCtrl->MarkAllSessionClose(); // 鏍囪鎵鏈変細璇濅负鍏抽棴鐘舵 + (void)SignalCancelAllBackEnd(); // 鍙戦佸彇娑堜俊鍙蜂互鍙栨秷鎵鏈夊悗绔换鍔 for (int i = 0; i < m_groupNum; i++) { - m_groups[i]->GetListener()->SendShutDown(); + m_groups[i]->GetListener()->SendShutDown(); // 鍙戦佸叧闂俊鍙风粰鎵鏈夌洃鍚櫒 } - /* Check until all groups have closed their sessions. */ + /* 妫鏌ョ洿鍒版墍鏈夌粍閮藉叧闂簡瀹冧滑鐨勪細璇濄 */ bool allclose = false; while (!allclose) { if (m_sessCtrl->IsActiveListEmpty()) { @@ -741,9 +767,9 @@ void ThreadPoolControler::CloseAllSessions() allclose = true; for (int i = 0; i < m_groupNum; i++) { - allclose = (m_groups[i]->AllSessionClosed() && allclose); + allclose = (m_groups[i]->AllSessionClosed() && allclose); // 妫鏌ユ瘡涓粍鐨勪細璇濇槸鍚﹂兘宸插叧闂 } - pg_usleep(one_hundred_micro_sec); + pg_usleep(one_hundred_micro_sec); // 鐭殏浼戠湢浠ュ噺灏 CPU 浣跨敤 } ereport(LOG, (errmodule(MOD_THREAD_POOL), @@ -753,21 +779,21 @@ void ThreadPoolControler::CloseAllSessions() void ThreadPoolControler::ShutDownThreads(bool forceWait) { for (int i = 0; i < m_groupNum; i++) { - m_groups[i]->ShutDownThreads(); + m_groups[i]->ShutDownThreads(); // 鍏抽棴鎵鏈夌嚎绋嬬粍涓殑绾跨▼ } ereport(LOG, (errmodule(MOD_THREAD_POOL), errmsg("pmState:%d, shut down all threadpool threads.", pmState))); if (forceWait) { - /* Check until all groups have shut down their workers. */ + /* 妫鏌ョ洿鍒版墍鏈夌粍閮藉叧闂簡瀹冧滑鐨勫伐浣滅嚎绋嬨 */ bool allshut = false; while (!allshut) { allshut = true; for (int i = 0; i < m_groupNum; i++) { - allshut = (m_groups[i]->AllThreadShutDown() && allshut); + allshut = (m_groups[i]->AllThreadShutDown() && allshut); // 妫鏌ユ瘡涓粍鐨勭嚎绋嬫槸鍚﹂兘宸插叧闂 } - pg_usleep(one_hundred_micro_sec); + pg_usleep(one_hundred_micro_sec); // 鐭殏浼戠湢浠ュ噺灏 CPU 浣跨敤 } ereport(LOG, (errmodule(MOD_THREAD_POOL), @@ -778,16 +804,16 @@ void ThreadPoolControler::ShutDownThreads(bool forceWait) void ThreadPoolControler::ShutDownListeners(bool forceWait) { for (int i = 0; i < m_groupNum; i++) { - m_groups[i]->GetListener()->ShutDown(); + m_groups[i]->GetListener()->ShutDown(); // 鍏抽棴鎵鏈夌嚎绋嬬粍鐨勭洃鍚櫒 } if (forceWait) { bool allshut = false; while (!allshut) { allshut = true; for (int i = 0; i < m_groupNum; i++) { - allshut = (m_groups[i]->GetListener()->GetThreadId() == 0) && allshut; + allshut = (m_groups[i]->GetListener()->GetThreadId() == 0) && allshut; // 妫鏌ョ洃鍚櫒绾跨▼鏄惁閮藉凡鍏抽棴 } - pg_usleep(one_hundred_micro_sec); + pg_usleep(one_hundred_micro_sec); // 鐭殏浼戠湢浠ュ噺灏 CPU 浣跨敤 } } } @@ -828,20 +854,20 @@ void ThreadPoolControler::AddWorkerIfNecessary() ThreadPoolGroup* ThreadPoolControler::FindThreadGroupWithLeastSession() { - int idx = 0; - float4 least_session = 0.0; - float4 session_per_thread = 0.0; + int idx = 0; // 鐢ㄤ簬璁板綍鍏锋湁鏈灏戜細璇濈殑绾跨▼缁勭殑绱㈠紩 + float4 least_session = 0.0; // 鐢ㄤ簬璁板綍鏈灏戜細璇濇暟 + float4 session_per_thread = 0.0; // 鐢ㄤ簬璁板綍姣忎釜绾跨▼鐨勫钩鍧囦細璇濇暟 - least_session = m_groups[0]->GetSessionPerThread(); + least_session = m_groups[0]->GetSessionPerThread(); // 鑾峰彇绗竴涓嚎绋嬬粍鐨勫钩鍧囦細璇濇暟浣滀负鍒濆鍊 for (int i = 1; i < m_groupNum; i++) { - session_per_thread = m_groups[i]->GetSessionPerThread(); - if (session_per_thread < least_session) { - least_session = session_per_thread; - idx = i; + session_per_thread = m_groups[i]->GetSessionPerThread(); // 鑾峰彇褰撳墠绾跨▼缁勭殑骞冲潎浼氳瘽鏁 + if (session_per_thread < least_session) { // 濡傛灉褰撳墠绾跨▼缁勭殑骞冲潎浼氳瘽鏁版洿灏 + least_session = session_per_thread; // 鏇存柊鏈灏戜細璇濇暟 + idx = i; // 鏇存柊鍏锋湁鏈灏戜細璇濈殑绾跨▼缁勭殑绱㈠紩 } } - return m_groups[idx]; + return m_groups[idx]; // 杩斿洖鍏锋湁鏈灏戜細璇濈殑绾跨▼缁勭殑鎸囬拡 } bool ThreadPoolControler::StayInAttachMode() @@ -855,15 +881,14 @@ int ThreadPoolControler::DispatchSession(Port* port) knl_session_context* sc = NULL; /* - * In comm_proxy mode, each accepted fd is combined with a fixed communicator thread in one NUMA group, - * we no longer distribute it with old mothod "group with latest sessions", - * so just return the communicator's NUMA group. + * 鍦╟omm_proxy妯″紡涓嬶紝姣忎釜鎺ュ彈鐨勬枃浠舵弿杩扮锛坒d锛夐兘涓庝竴涓 + * 鍥哄畾鐨勯氫俊绾跨▼鍚堝苟鍦ㄤ竴涓狽UMA缁勪腑锛屾垜浠笉鍐嶄娇鐢ㄦ棫鐨勬柟娉曗 + * 涓庢渶鏂颁細璇濈殑缁勫悎鈥濊繘琛屽垎閰嶏紝鍥犳鍙渶杩斿洖閫氫俊绾跨▼鎵鍦ㄧ殑NUMA缁勫嵆鍙 * - * Note: We assume that each connected user session can be equal-possibily distributed to communicators, - * fortunately,it looks like Euler OS can guarantee this(proved), - * otherwise we need revisit it. + * 娉ㄦ剰锛氭垜浠亣璁炬瘡涓繛鎺ョ殑鐢ㄦ埛浼氳瘽鍙互绛夊彲鑳藉湴鍒嗗竷缁欓氫俊鍣紝 + * 骞歌繍鐨勬槸锛屾鎷夋搷浣滅郴缁熶技涔庡彲浠ヤ繚璇佽繖涓鐐癸紙宸茬粡璇佹槑锛夛紝鍚﹀垯鎴戜滑杩橀渶瑕侀噸鏂拌冭檻杩欎釜闂銆 * - * Performance optimization with comm_proxy when thread_pool m_groupNum same as comm_proxy numa groups + * 鎬ц兘浼樺寲锛氬湪浣跨敤`comm_proxy`鏃讹紝褰揱thread_pool`鐨刞m_groupNum`涓巂comm_proxy`鐨凬UMA缁勬暟鐩稿悓鏃讹紝鍙互瀹炵幇鎬ц兘浼樺寲銆 */ if (AmIProxyModeSockfd(port->sock) && m_groupNum == g_comm_proxy_config.s_numa_num) { CommSockDesc* comm_sock = g_comm_controller->FdGetCommSockDesc(port->sock); @@ -876,7 +901,7 @@ int ThreadPoolControler::DispatchSession(Port* port) Assert(false); return STATUS_ERROR; } - /* if this group is hanged, we don't accept new session */ + /* 濡傛灉杩欎釜缁勬寕璧蜂簡锛屾垜浠笉浼氭帴鍙楁柊鐨勪細璇濄 */ if (grp->IsGroupHanged()) { ereport(WARNING, (errmodule(MOD_THREAD_POOL), @@ -893,29 +918,39 @@ int ThreadPoolControler::DispatchSession(Port* port) } /* - * Bind the specified thread to all the available CPUs. - * This is invoked by auxiliary thread, such as WALSender. + * 灏嗘寚瀹氱殑绾跨▼缁戝畾鍒版墍鏈夊彲鐢ㄧ殑CPU銆 + * 姝ゆ搷浣滅敱杈呭姪绾跨▼锛堜緥濡俉AL鍙戦佽咃級璋冪敤銆 */ void ThreadPoolControler::BindThreadToAllAvailCpu(ThreadId thread) const { + // 濡傛灉涓嶉渶瑕佺粦瀹欳PU锛岀洿鎺ヨ繑鍥 if (!CheckCpuBind()) { return; } + // 濡傛灉缁戝畾鏂瑰紡鏄疉LL_CPU_BIND锛屼篃鐩存帴杩斿洖 if (m_cpuInfo.bindType == ALL_CPU_BIND) { return; } + // 鍒涘缓涓涓狢PU闆嗗悎锛屽垵濮嬪寲涓虹┖ cpu_set_t availCpuSet; CPU_ZERO(&availCpuSet); + + // 閬嶅巻姣忎釜NUMA鑺傜偣 for (int numaNo = 0; numaNo < m_cpuInfo.totalNumaNum; ++numaNo) { int cpuNumber = m_cpuInfo.cpuArrSize[numaNo]; + + // 灏嗘瘡涓狽UMA鑺傜偣涓婄殑CPU娣诲姞鍒癈PU闆嗗悎涓 for (int i = 0; i < cpuNumber; ++i) { CPU_SET(m_cpuInfo.cpuArr[numaNo][i], &availCpuSet); } } + + // 浣跨敤pthread_setaffinity_np鍑芥暟灏嗙嚎绋嬬粦瀹氬埌CPU闆嗗悎涓 int ret = pthread_setaffinity_np(thread, sizeof(cpu_set_t), &availCpuSet); + + // 濡傛灉缁戝畾澶辫触锛岃緭鍑鸿鍛婁俊鎭 if (ret != 0) ereport(WARNING, (errmsg("BindThreadToAllAvailCpu fail to bind thread %lu, errno: %d", thread, ret))); } - diff --git a/src/gausskernel/process/threadpool/threadpool_group.cpp b/src/gausskernel/process/threadpool/threadpool_group.cpp index 59d0203fd..6e11b6655 100644 --- a/src/gausskernel/process/threadpool/threadpool_group.cpp +++ b/src/gausskernel/process/threadpool/threadpool_group.cpp @@ -14,7 +14,9 @@ * ------------------------------------------------------------------------- * * threadpool_group.cpp - * Thread pool group controls listener and worker threads. + * 绾跨▼姹犵粍鎺у埗鐩戝惉鍣ㄧ嚎绋嬪拰宸ヤ綔鑰呯嚎绋 + * 鐩戝惉鍣ㄧ嚎绋嬭礋璐f帴鍙楁柊鐨勮繛鎺ヨ姹傦紝閫氬父鐢ㄤ簬澶勭悊瀹㈡埛绔笌鏈嶅姟鍣ㄤ箣闂寸殑閫氫俊寤虹珛鍜岀淮鎶ゃ + * 宸ヤ綔鑰呯嚎绋嬭礋璐e疄闄呯殑浠诲姟澶勭悊锛岄氬父鐢ㄤ簬鎵ц鏁版嵁搴撴煡璇€佷簨鍔″鐞嗙瓑鍏蜂綋鐨勪笟鍔¢昏緫銆 * * * IDENTIFICATION @@ -59,12 +61,12 @@ ThreadPoolGroup::ThreadPoolGroup(int maxWorkerNum, int expectWorkerNum, int maxStreamNum, int groupId, int numaId, int cpuNum, int* cpuArr, bool enableBindCpuNuma) : m_listener(NULL), - m_maxWorkerNum(maxWorkerNum), - m_maxStreamNum(maxStreamNum), + m_maxWorkerNum(maxWorkerNum),//鏈澶у伐浣滆呯嚎绋嬫暟閲 + m_maxStreamNum(maxStreamNum),//鏈澶ф祦绾跨▼鏁伴噺 m_defaultWorkerNum(expectWorkerNum), m_workerNum(0), m_listenerNum(0), - m_expectWorkerNum(expectWorkerNum), + m_expectWorkerNum(expectWorkerNum),//棰勬湡宸ヤ綔鑰呯嚎绋嬫暟閲 m_idleWorkerNum(0), m_pendingWorkerNum(0), m_streamNum(0), @@ -73,8 +75,8 @@ ThreadPoolGroup::ThreadPoolGroup(int maxWorkerNum, int expectWorkerNum, int maxS m_waitServeSessionCount(0), m_processTaskCount(0), m_hasHanged(0), - m_groupId(groupId), - m_numaId(numaId), + m_groupId(groupId),//绾跨▼姹犵粍鐨勫敮涓鏍囪瘑绗 + m_numaId(numaId),//NUMA 鑺傜偣鐨勬爣璇嗙 m_groupCpuNum(cpuNum), m_groupCpuArr(cpuArr), m_enableNumaDistribute(false), @@ -104,6 +106,7 @@ ThreadPoolGroup::~ThreadPoolGroup() void ThreadPoolGroup::Init(bool enableNumaDistribute) { + // 鍒涘缓绾跨▼姹犵粍涓婁笅鏂 m_context = AllocSetContextCreate(g_instance.instance_context, "ThreadPoolGroupContext", ALLOCSET_DEFAULT_MINSIZE, @@ -111,22 +114,27 @@ void ThreadPoolGroup::Init(bool enableNumaDistribute) ALLOCSET_DEFAULT_MAXSIZE, SHARED_CONTEXT); + // 鍒囨崲鍒扮嚎绋嬫睜缁勪笂涓嬫枃 AutoContextSwitch acontext(m_context); + // 鍒涘缓绾跨▼姹犵洃鍚櫒骞跺惎鍔 m_listener = New(CurrentMemoryContext) ThreadPoolListener(this); m_listener->StartUp(); + // 濡傛灉鍚敤 CPU 缁戝畾鍜 NUMA 鍒嗛厤锛屽皢鎸囧畾鐨 CPU 娣诲姞鍒 CPU 闆嗗悎涓 if (m_enableBindCpuNuma) { for (int i = 0; i < m_groupCpuNum; i++) { CPU_SET(m_groupCpuArr[i], &m_CpuNumaSet); } } + // 鍒濆鍖栧伐浣滆呯嚎绋嬬鐞 InitWorkerSentry(); + // 鍒濆鍖栨祦绾跨▼绠$悊 InitStreamSentry(); - /* Prepare the CPU_SET including all of available cpus in this node */ + // 鍑嗗鍖呭惈鏈妭鐐规墍鏈夊彲鐢 CPU 鐨 CPU_SET m_enableNumaDistribute = enableNumaDistribute; for (int i = 0; i < m_groupCpuNum; ++i) { CPU_SET(m_groupCpuArr[i], &m_nodeCpuSet); @@ -135,19 +143,19 @@ void ThreadPoolGroup::Init(bool enableNumaDistribute) void ThreadPoolGroup::InitWorkerSentry() { - /* Prepare slots in case we need to enlarge this thread group. */ + /* 涓哄彲鑳介渶瑕佹墿灞曠殑绾跨▼缁勫噯澶囨彃妲姐 */ m_workers = (ThreadWorkerSentry*)palloc0_noexcept(sizeof(ThreadWorkerSentry) * m_maxWorkerNum); if (m_workers == NULL) { - ereport(ERROR, (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of memory"))); + ereport(ERROR, (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("鍐呭瓨涓嶈冻"))); } - /* Init lock for each slot. */ + /* 涓烘瘡涓彃妲藉垵濮嬪寲閿併 */ for (int i = 0; i < m_maxWorkerNum; i++) { pthread_mutex_init(&m_workers[i].mutex, NULL); pthread_cond_init(&m_workers[i].cond, NULL); } - /* Start up workers. */ + /* 鍚姩宸ヤ綔鑰呯嚎绋嬨 */ for (int i = 0; i < m_expectWorkerNum; i++) { AddWorker(i); } @@ -155,8 +163,10 @@ void ThreadPoolGroup::InitWorkerSentry() void ThreadPoolGroup::AddWorker(int i) { + // 鍒涘缓绾跨▼姹犲伐浣滆 m_workers[i].worker = New(m_context) ThreadPoolWorker(i, this, &m_workers[i].mutex, &m_workers[i].cond); + // 鍚姩宸ヤ綔鑰呯嚎绋 int ret = m_workers[i].worker->StartUp(); if (ret == STATUS_OK) { m_workers[i].stat.slotStatus = THREAD_SLOT_INUSE; @@ -175,7 +185,7 @@ void ThreadPoolGroup::AddWorker(int i) } else { delete m_workers[i].worker; m_workers[i].worker = NULL; - ereport(LOG, (errmsg("Faid to start up thread pool worker: %m"))); + ereport(LOG, (errmsg("鍚姩绾跨▼姹犲伐浣滆呭け璐: %m"))); } } @@ -183,6 +193,7 @@ void ThreadPoolGroup::ReleaseWorkerSlot(int i) { Assert(m_workers[i].worker != NULL); + // 鍔犻攣浠ヤ慨鏀瑰伐浣滆呮暟閲 pthread_mutex_lock(&m_mutex); pg_atomic_fetch_sub_u32((volatile uint32*)&m_workerNum, 1); Assert(m_workerNum >= 0); @@ -192,11 +203,12 @@ void ThreadPoolGroup::ReleaseWorkerSlot(int i) void ThreadPoolGroup::WaitReady() { + // 寰幆绛夊緟鐩村埌鐩戝惉鍣ㄦ暟閲忎负 1锛岃〃绀哄凡缁忓氨缁 while (true) { if (m_listenerNum == 1) { break; } - pg_usleep(500); + pg_usleep(500); // 绛夊緟 500 寰 } } @@ -207,26 +219,32 @@ float4 ThreadPoolGroup::GetSessionPerThread() void ThreadPoolGroup::GetThreadPoolGroupStat(ThreadPoolStat* stat) { - stat->groupId = m_groupId; - stat->numaId = m_numaId; - stat->bindCpuNum = m_groupCpuNum; - stat->listenerNum = m_listenerNum; + // 灏嗙嚎绋嬫睜缁勭殑鐘舵佷俊鎭~鍏呭埌缁欏畾鐨 ThreadPoolStat 缁撴瀯浣撲腑 + stat->groupId = m_groupId; // 绾跨▼姹犵粍鐨 ID + stat->numaId = m_numaId; // NUMA 鑺傜偣鐨 ID + stat->bindCpuNum = m_groupCpuNum; // 缁戝畾鐨 CPU 鏁伴噺 + stat->listenerNum = m_listenerNum; // 鐩戝惉鍣ㄦ暟閲 + // 濉厖宸ヤ綔鑰呯嚎绋嬩俊鎭 int rc = sprintf_s(stat->workerInfo, STATUS_INFO_SIZE, - "default: %d new: %d expect: %d actual: %d idle: %d pending: %d", - m_defaultWorkerNum, m_expectWorkerNum - m_defaultWorkerNum, m_expectWorkerNum, - m_workerNum, m_idleWorkerNum, m_pendingWorkerNum); + "default: %d new: %d expect: %d actual: %d idle: %d pending: %d", + m_defaultWorkerNum, m_expectWorkerNum - m_defaultWorkerNum, m_expectWorkerNum, + m_workerNum, m_idleWorkerNum, m_pendingWorkerNum); securec_check_ss(rc, "", ""); + // 璁$畻杩愯涓拰绌洪棽涓殑浼氳瘽鏁伴噺 int runSessionNum = m_workerNum - m_idleWorkerNum; int idleSessionNum = m_sessionCount - m_waitServeSessionCount - runSessionNum; idleSessionNum = (idleSessionNum < 0) ? 0 : idleSessionNum; + + // 濉厖浼氳瘽淇℃伅 rc = sprintf_s(stat->sessionInfo, STATUS_INFO_SIZE, - "total: %d waiting: %d running:%d idle: %d", - m_sessionCount, m_waitServeSessionCount, - runSessionNum, idleSessionNum); + "total: %d waiting: %d running:%d idle: %d", + m_sessionCount, m_waitServeSessionCount, + runSessionNum, idleSessionNum); securec_check_ss(rc, "", ""); + // 濡傛灉鏄 PGXC 鏁版嵁鑺傜偣锛屽~鍏呮祦淇℃伅锛屽惁鍒欏皢娴佷俊鎭疆涓虹┖ if (IS_PGXC_DATANODE) { rc = sprintf_s(stat->streamInfo, STATUS_INFO_SIZE, "total: %d running: %d idle: %d", m_streamNum, m_streamNum - m_idleStreamNum, m_idleStreamNum); @@ -238,10 +256,12 @@ void ThreadPoolGroup::GetThreadPoolGroupStat(ThreadPoolStat* stat) void ThreadPoolGroup::AddWorkerIfNecessary() { + // 鑷姩鍔犻攣锛岀‘淇濈嚎绋嬪畨鍏 AutoMutexLock alock(&m_mutex); alock.lock(); m_workerNum = (m_workerNum >= 0) ? m_workerNum : 0; + // 濡傛灉褰撳墠宸ヤ綔鑰呯嚎绋嬫暟閲忓皬浜庢湡鏈涚殑鏁伴噺锛屽垯娣诲姞宸ヤ綔鑰呯嚎绋 if (m_workerNum < m_expectWorkerNum) { for (int i = 0; i < m_expectWorkerNum; i++) { if (m_workers[i].stat.slotStatus == THREAD_SLOT_UNUSE) { @@ -252,80 +272,84 @@ void ThreadPoolGroup::AddWorkerIfNecessary() } } } - alock.unLock(); + alock.unLock(); // 瑙i攣 } bool ThreadPoolGroup::EnlargeWorkers(int enlargeNum) { + // 鑷姩鍔犻攣锛岀‘淇濈嚎绋嬪畨鍏 AutoMutexLock alock(&m_mutex); alock.lock(); + // 濡傛灉鏈熸湜鐨勫伐浣滆呯嚎绋嬫暟閲忓凡缁忕瓑浜庢渶澶ф暟閲忥紝涓嶅啀鎵╁睍 if (m_expectWorkerNum == m_maxWorkerNum) { alock.unLock(); return false; } int num = m_expectWorkerNum; - m_expectWorkerNum += enlargeNum; - m_expectWorkerNum = Min(m_expectWorkerNum, m_maxWorkerNum); + m_expectWorkerNum += enlargeNum; // 澧炲姞鏈熸湜鐨勫伐浣滆呯嚎绋嬫暟閲 + m_expectWorkerNum = Min(m_expectWorkerNum, m_maxWorkerNum); // 涓嶈秴杩囨渶澶у伐浣滆呯嚎绋嬫暟閲 elog(LOG, "[SCHEDULER] Group %d enlarge worker. Old worker num %d, new worker num %d", - m_groupId, num, m_expectWorkerNum); + m_groupId, num, m_expectWorkerNum); int diff = m_expectWorkerNum - num; - /* Turn pending workers into running workers if we have. */ + // 濡傛灉鏈夊緟澶勭悊鐨勫伐浣滆呯嚎绋嬶紝灏嗗畠浠浆鎹负杩愯涓殑绾跨▼ if (m_pendingWorkerNum != 0) { ThreadPoolWorker* worker = NULL; - int wakeUpNum = Min(diff, m_pendingWorkerNum); - m_pendingWorkerNum -= wakeUpNum; + int wakeUpNum = Min(diff, m_pendingWorkerNum); // 璁$畻闇瑕佸敜閱掔殑鏁伴噺 + m_pendingWorkerNum -= wakeUpNum; // 鍑忓皯寰呭鐞嗙殑宸ヤ綔鑰呯嚎绋嬫暟閲 for (int i = num; i < num + wakeUpNum; i++) { if (m_workers[i].stat.slotStatus == THREAD_SLOT_INUSE) { worker = m_workers[i].worker; if (worker->GetthreadStatus() == THREAD_PENDING) { - worker->WakeUpToUpdate(THREAD_RUN); + worker->WakeUpToUpdate(THREAD_RUN); // 鍞ら啋寰呭鐞嗙嚎绋嬶紝浣垮叾杩愯 elog(LOG, "[SCHEDULER] Group %d enlarge: wakeup pending worker %lu", - m_groupId, m_workers[i].worker->GetThreadId()); + m_groupId, m_workers[i].worker->GetThreadId()); } } } } - alock.unLock(); + alock.unLock(); // 瑙i攣 - /* Start up worker if pending worker is not enough. */ + // 鍚 Postmaster 鍙戦佷俊鍙蜂互鍚姩鏂扮殑宸ヤ綔鑰呯嚎绋 SendPostmasterSignal(PMSIGNAL_START_THREADPOOL_WORKER); return true; } void ThreadPoolGroup::ReduceWorkers(int reduceNum) { + // 鑷姩鍔犻攣锛岀‘淇濈嚎绋嬪畨鍏 AutoMutexLock alock(&m_mutex); alock.lock(); int num = m_expectWorkerNum; m_expectWorkerNum -= reduceNum; - m_expectWorkerNum = Max(m_expectWorkerNum, m_defaultWorkerNum); + m_expectWorkerNum = Max(m_expectWorkerNum, m_defaultWorkerNum); // 淇濊瘉涓嶄綆浜庨粯璁ゅ伐浣滆呯嚎绋嬫暟閲 if (num - m_expectWorkerNum == 0) { alock.unLock(); return; } - m_pendingWorkerNum += (num - m_expectWorkerNum); + m_pendingWorkerNum += (num - m_expectWorkerNum); // 灏嗗浣欑殑宸ヤ綔鑰呯嚎绋嬭缃负寰呭鐞嗙姸鎬 elog(LOG, "[SCHEDULER] Group %d reduce worker. Old worker num %d, new worker num %d", - m_groupId, num, m_expectWorkerNum); - /* only wake up free thread to pending, if we meet working thread, just skip it. */ + m_groupId, num, m_expectWorkerNum); + /* 鍙敜閱掔┖闂茬嚎绋嬪埌寰呭鐞嗙姸鎬侊紝濡傛灉閬囧埌姝e湪宸ヤ綔鐨勭嚎绋嬶紝鍒欒烦杩 */ for (int i = m_expectWorkerNum; i < num; i++) { if (m_workers[i].stat.slotStatus == THREAD_SLOT_INUSE) { Assert(m_workers[i].worker != NULL); if (m_workers[i].worker->WakeUpToPendingIfFree()) { elog(LOG, "[SCHEDULER] Group %d reduce: pending worker %lu", - m_groupId, m_workers[i].worker->GetThreadId()); + m_groupId, m_workers[i].worker->GetThreadId()); } } } elog(LOG, "[SCHEDULER] Group %d reduce worker end. Old worker num %d, new worker num %d", - m_groupId, num, m_expectWorkerNum); + m_groupId, num, m_expectWorkerNum); alock.unLock(); } + void ThreadPoolGroup::ShutDownPendingWorkers() { if (m_pendingWorkerNum == 0) { @@ -333,7 +357,7 @@ void ThreadPoolGroup::ShutDownPendingWorkers() } elog(LOG, "[SCHEDULER] Group %d shut down pending workers start. pending worker num %d, current worker num %d", - m_groupId, m_pendingWorkerNum, m_expectWorkerNum); + m_groupId, m_pendingWorkerNum, m_expectWorkerNum); AutoMutexLock alock(&m_mutex); ThreadPoolWorker* worker = NULL; @@ -342,41 +366,46 @@ void ThreadPoolGroup::ShutDownPendingWorkers() if (m_workers[i].stat.slotStatus == THREAD_SLOT_INUSE) { worker = m_workers[i].worker; if (worker->GetthreadStatus() == THREAD_PENDING) { - worker->WakeUpToUpdate(THREAD_EXIT); + worker->WakeUpToUpdate(THREAD_EXIT); // 鍞ら啋寰呭鐞嗙嚎绋嬩互閫鍑 } } } m_pendingWorkerNum = 0; elog(LOG, "[SCHEDULER] Group %d shut down pending workers end. pending worker num %d, current worker num %d", - m_groupId, m_pendingWorkerNum, m_expectWorkerNum); + m_groupId, m_pendingWorkerNum, m_expectWorkerNum); alock.unLock(); } void ThreadPoolGroup::ShutDownThreads() { + // 鑷姩鍔犻攣锛岀‘淇濈嚎绋嬪畨鍏 AutoMutexLock alock(&m_mutex); alock.lock(); + // 鍏抽棴宸ヤ綔鑰呯嚎绋 for (int i = 0; i < m_maxWorkerNum; i++) { if (m_workers[i].stat.slotStatus != THREAD_SLOT_UNUSE) { - m_workers[i].worker->WakeUpToUpdate(THREAD_EXIT); + m_workers[i].worker->WakeUpToUpdate(THREAD_EXIT); // 鍞ら啋宸ヤ綔鑰呯嚎绋嬩互閫鍑 } } - m_pendingWorkerNum = 0; + m_pendingWorkerNum = 0; // 閲嶇疆寰呭鐞嗗伐浣滆呯嚎绋嬫暟閲 + // 鍏抽棴娴佺嚎绋 for (int i = 0; i < m_maxStreamNum; i++) { if (m_streams[i].stat.slotStatus != THREAD_SLOT_UNUSE) { - m_streams[i].stream->WakeUpToUpdate(THREAD_EXIT); + m_streams[i].stream->WakeUpToUpdate(THREAD_EXIT); // 鍞ら啋娴佺嚎绋嬩互閫鍑 } } - alock.unLock(); + alock.unLock(); // 瑙i攣 } bool ThreadPoolGroup::IsGroupHang() { + // 妫鏌ユ槸鍚﹀瓨鍦ㄦ鍦ㄥ鐞嗙殑浠诲姟鎴栫┖闂插伐浣滆呯嚎绋 if (pg_atomic_exchange_u32((volatile uint32*)&m_processTaskCount, 0) != 0 || m_idleWorkerNum != 0) return false; + // 璋冪敤 ThreadPoolListener 鐨 GetSessIshang 鍑芥暟妫鏌ユ槸鍚︾嚎绋嬬粍鎸傝捣 bool ishang = m_listener->GetSessIshang(&m_current_time, &m_sessionId); return ishang; } @@ -394,45 +423,57 @@ bool ThreadPoolGroup::IsGroupHanged() void ThreadPoolGroup::AttachThreadToCPU(ThreadId thread, int cpu) { + // 鍒涘缓涓涓 CPU 闆嗗悎骞跺皢鎸囧畾鐨 CPU 娣诲姞鍒伴泦鍚堜腑 cpu_set_t cpuset; int ret = 0; CPU_ZERO(&cpuset); CPU_SET(cpu, &cpuset); + + // 浣跨敤 pthread_setaffinity_np 鍑芥暟灏嗙嚎绋嬬粦瀹氬埌鎸囧畾鐨 CPU ret = pthread_setaffinity_np(thread, sizeof(cpu_set_t), &cpuset); if (ret != 0) { + // 濡傛灉缁戝畾澶辫触锛岃褰曡鍛婃棩蹇 ereport(WARNING, (errmsg("Fail to attach thread %lu to CPU %d", thread, cpu))); } } void ThreadPoolGroup::AttachThreadToNodeLevel(ThreadId thread) const { + // 浣跨敤 pthread_setaffinity_np 鍑芥暟灏嗙嚎绋嬬粦瀹氬埌 NUMA 鑺傜偣鐨 CPU 闆嗗悎 int ret = pthread_setaffinity_np(thread, sizeof(cpu_set_t), &m_nodeCpuSet); if (ret != 0) + // 濡傛灉缁戝畾澶辫触锛岃褰曡鍛婃棩蹇 ereport(WARNING, (errmsg("Fail to attach thread %lu to numa node %d", thread, m_numaId))); } void ThreadPoolGroup::AttachThreadToCpuNuma(ThreadId thread) { + // 浣跨敤 pthread_setaffinity_np 鍑芥暟灏嗙嚎绋嬬粦瀹氬埌鎸囧畾鐨 CPU NUMA 鐨 CPU 闆嗗悎 int ret = pthread_setaffinity_np(thread, sizeof(cpu_set_t), &m_CpuNumaSet); if (ret != 0) { + // 濡傛灉缁戝畾澶辫触锛岃褰曡鍛婃棩蹇 ereport(WARNING, (errmsg("Fail to attach thread %lu to CPU NUMA", thread))); } } void ThreadPoolGroup::InitStreamSentry() { + // 鍒嗛厤鐢ㄤ簬瀛樺偍绾跨▼娴佺殑鏁版嵁缁撴瀯鏁扮粍 m_streams = (ThreadStreamSentry*)palloc0_noexcept(sizeof(ThreadStreamSentry) * m_maxStreamNum); if (m_streams == NULL) { + // 濡傛灉鍐呭瓨鍒嗛厤澶辫触锛岃褰曢敊璇棩蹇 ereport(ERROR, (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of memory"))); } + // 涓烘瘡涓嚎绋嬫祦鍒濆鍖栦簰鏂ラ攣鍜屾潯浠跺彉閲 for (int i = 0; i < m_maxStreamNum; i++) { pthread_mutex_init(&m_streams[i].mutex, NULL); pthread_cond_init(&m_streams[i].cond, NULL); } - m_freeStreamList = New(CurrentMemoryContext)DllistWithLock(); + // 鍒涘缓涓涓甫閿佺殑鍙屽悜閾捐〃 + m_freeStreamList = New(CurrentMemoryContext) DllistWithLock(); } ThreadId ThreadPoolGroup::GetStreamFromPool(StreamProducer* producer) @@ -442,23 +483,31 @@ ThreadId ThreadPoolGroup::GetStreamFromPool(StreamProducer* producer) AutoMutexLock alock(&m_mutex); alock.lock(); + // 妫鏌ユ槸鍚︽湁绌洪棽鐨勭嚎绋嬫祦鍙敤 if (m_freeStreamList->IsEmpty()) { + // 濡傛灉娌℃湁绌洪棽鐨勭嚎绋嬫祦锛屽苟涓斿凡杈惧埌鏈澶х嚎绋嬫祦鏁伴檺鍒讹紝鎶ラ敊 if (m_streamNum == m_maxStreamNum) { alock.unLock(); ereport(ERROR, (errcode(ERRCODE_SYSTEM_ERROR), errmsg("Exceed stream thread pool limitation %d in group %d", m_maxStreamNum, m_groupId))); } + // 鍒嗛厤涓涓 Postmaster 瀛愯繘绋嬫Ы浣 producer->setChildSlot(AssignPostmasterChildSlot()); if (producer->getChildSlot() == -1) { return InvalidTid; } + + // 娣诲姞涓涓柊鐨勭嚎绋嬫祦 tid = AddStream(producer); } else { + // 濡傛灉鏈夌┖闂茬殑绾跨▼娴侊紝浠庣┖闂茬嚎绋嬫祦鍒楄〃涓幏鍙栦竴涓 Dlelem* elem = m_freeStreamList->RemoveHead(); + // 鍑忓皯绌洪棽绾跨▼娴佽鏁 pg_atomic_fetch_sub_u32((volatile uint32*)&m_idleStreamNum, 1); stream = (ThreadPoolStream*)DLE_VAL(elem); tid = stream->GetThreadId(); + // 鍞ら啋绾跨▼娴佷互澶勭悊鐢熶骇鑰呯殑浠诲姟 stream->WakeUpToWork(producer); } return tid; @@ -469,6 +518,8 @@ ThreadId ThreadPoolGroup::AddStream(StreamProducer* producer) ThreadId tid = InvalidTid; ThreadStreamSentry* streamSentry = NULL; int idx = 0; + + // 瀵绘壘涓涓┖闂茬殑绾跨▼娴佹Ы浣 for (idx = 0; idx < m_maxStreamNum; idx++) { if (m_streams[idx].stat.slotStatus == THREAD_SLOT_UNUSE) { streamSentry = &m_streams[idx]; @@ -478,25 +529,31 @@ ThreadId ThreadPoolGroup::AddStream(StreamProducer* producer) break; } } + + // 濡傛灉娌℃湁鎵惧埌绌洪棽鐨勬Ы浣嶏紝鎶ラ敊 if (streamSentry == NULL) { ereport(ERROR, (errcode(ERRCODE_INSUFFICIENT_RESOURCES), errmsg("Fail to find a free slot for stream"))); } - ThreadPoolStream *stream = New(m_context) ThreadPoolStream(); + // 鍒涘缓涓涓柊鐨勭嚎绋嬫祦 + ThreadPoolStream* stream = New(m_context) ThreadPoolStream(); tid = stream->StartUp(idx, producer, this, &streamSentry->mutex, &streamSentry->cond); if (tid != 0) { + // 鏍囪绾跨▼娴佹Ы浣嶄负宸蹭娇鐢ㄧ姸鎬 streamSentry->stat.slotStatus = THREAD_SLOT_INUSE; streamSentry->stat.spawntick++; streamSentry->stat.lastSpawnTime = GetCurrentTimestamp(); streamSentry->stream = stream; tid = stream->GetThreadId(); if (m_groupCpuArr) { + // 濡傛灉鍚敤浜 NUMA 鍒嗗竷锛屽皢绾跨▼娴佺粦瀹氬埌 NUMA 鑺傜偣 AttachThreadToNodeLevel(tid); } m_streamNum++; } else { + // 鍚姩绾跨▼娴佸け璐ワ紝閲婃斁璧勬簮骞惰褰曟棩蹇 delete stream; tid = 0; ereport(LOG, (errmsg("Faid to start up thread pool stream: %m"))); @@ -524,7 +581,11 @@ void ThreadPoolGroup::RemoveStreamFromPool(Dlelem* elem, int idx) void ThreadPoolGroup::ReduceStreams() { pthread_mutex_lock(&m_mutex); + + // 璁$畻鏈澶у彲浠ュ噺灏戠殑绾跨▼娴佹暟閲 int max_reduce_num = m_streamNum - m_defaultWorkerNum; + + // 濡傛灉鍙互鍑忓皯绾跨▼娴佹暟閲忥紝鎵ц鍑忓皯鎿嶄綔 if (max_reduce_num > 0) { elog(LOG, "Reduce %d stream thread", max_reduce_num); for (int i = 0; i < max_reduce_num; i++) { @@ -536,5 +597,6 @@ void ThreadPoolGroup::ReduceStreams() stream->WakeUpToUpdate(THREAD_EXIT); } } + pthread_mutex_unlock(&m_mutex); -} +} \ No newline at end of file diff --git a/src/gausskernel/process/threadpool/threadpool_listener.cpp b/src/gausskernel/process/threadpool/threadpool_listener.cpp index e3caab1a0..b36fa06b1 100644 --- a/src/gausskernel/process/threadpool/threadpool_listener.cpp +++ b/src/gausskernel/process/threadpool/threadpool_listener.cpp @@ -15,10 +15,9 @@ * * threadpool_listener.cpp * - * There are multiple tasks for listener thread: - * 1. Listen to all connections from client or other componets of this cluster - * (like connections from other cn). - * 2. Dispatch session to available woker thread. + * 鐩戝惉绾跨▼鏈夊涓换鍔★細 + * 1. 鐩戝惉鏉ヨ嚜瀹㈡埛绔垨闆嗙兢涓叾浠栫粍浠讹紙濡傛潵鑷叾浠栬绠楄妭鐐圭殑杩炴帴锛夌殑鎵鏈夎繛鎺ャ + * 2. 灏嗕細璇濆垎娲剧粰鍙敤鐨勫伐浣滅嚎绋嬨 * * IDENTIFICATION * src/gausskernel/process/threadpool/threadpool_listener.cpp @@ -74,7 +73,7 @@ void TpoolListenerMain(ThreadPoolListener* listener) (void)gspqsignal(SIGHUP, SIG_IGN); (void)gspqsignal(SIGINT, SIG_IGN); - // die with pm + // Postmaster杩涚▼閫鍑烘椂缁堟 (void)gspqsignal(SIGTERM, SIG_IGN); (void)gspqsignal(SIGQUIT, SIG_IGN); (void)gspqsignal(SIGPIPE, SIG_IGN); @@ -107,31 +106,49 @@ void ThreadPoolListenerIAm() ThreadPoolListener::ThreadPoolListener(ThreadPoolGroup* group) { + // 灏嗕紶鍏ョ殑绾跨▼姹犵粍瀵硅薄淇濆瓨鍒版垚鍛樺彉閲忎腑 m_group = group; + + // 鍒濆鍖栦竴浜涙垚鍛樺彉閲忥紝璁剧疆涓哄垵濮嬪 m_tid = InvalidTid; m_epollFd = INVALID_FD; m_epollEvents = NULL; m_reaperAllSession = false; m_getKilled = false; + + // 鍒涘缓鐢ㄤ簬绠$悊绌洪棽宸ヤ綔绾跨▼鐨勯摼琛 m_freeWorkerList = New(CurrentMemoryContext) DllistWithLock(); + + // 鍒涘缓鐢ㄤ簬绠$悊鍑嗗灏辩华鐨勪細璇濈殑閾捐〃 m_readySessionList = New(CurrentMemoryContext) DllistWithLock(); + + // 鍒涘缓鐢ㄤ簬绠$悊绌洪棽浼氳瘽鐨勯摼琛 m_idleSessionList = New(CurrentMemoryContext) DllistWithLock(); + // 妫鏌ユ槸鍚﹀惎鐢ㄦ湰鍦扮郴缁熺紦瀛橈紝鏍规嵁鎯呭喌杩涜鍒濆鍖 if (EnableLocalSysCache()) { - /* see HASH_INDEX, Since the hash table must contain a power-of-2 number of elements */ + // 鏍规嵁閰嶇疆璁剧疆浼氳瘽鍝堝笇琛ㄧ殑妗舵暟锛堥氬父涓2鐨勫箓锛 #ifdef ENABLE_LITE_MODE m_session_nbucket = 128; #else m_session_nbucket = MAX_THREAD_POOL_SIZE; #endif + + // 鍒嗛厤浼氳瘽妗剁殑鍐呭瓨绌洪棿 m_session_bucket = (Dllist*)palloc0(m_session_nbucket * sizeof(Dllist)); + + // 鍒嗛厤浼氳瘽璇诲啓閿佺殑鍐呭瓨绌洪棿 m_session_rw_locks = (pthread_rwlock_t *)palloc0(m_session_nbucket * sizeof(pthread_rwlock_t)); + + // 鍒濆鍖栨瘡涓細璇濇《鐨勮鍐欓攣 for (int i = 0; i < m_session_nbucket; i++) { PthreadRwLockInit(&m_session_rw_locks[i], NULL); } + + // 鍒濆鍖栫敤浜庡尮閰嶆悳绱㈢殑鏍囧織 m_match_search = 0; - } else { + // 濡傛灉鏈惎鐢ㄦ湰鍦扮郴缁熺紦瀛橈紝鍒欏皢鐩稿叧鎴愬憳鍙橀噺璁剧疆涓哄垵濮嬪 m_session_nbucket = 0; m_session_bucket = NULL; m_session_rw_locks = NULL; @@ -141,21 +158,27 @@ ThreadPoolListener::ThreadPoolListener(ThreadPoolGroup* group) ThreadPoolListener::~ThreadPoolListener() { + // 鏍规嵁瀹忓畾涔夐夋嫨涓嶅悓鐨勫叧闂柟娉 if (ENABLE_THREAD_POOL_DN_LOGICCONN) { CommEpollClose(m_epollFd); } else { - comm_close(m_epollFd); /* CommProxy support */ + comm_close(m_epollFd); /* CommProxy 鏀寔 */ } + + // 灏嗙浉鍏虫垚鍛樺彉閲忚缃负 NULL锛屼互閲婃斁瀵硅祫婧愮殑寮曠敤 m_group = NULL; m_epollEvents = NULL; m_freeWorkerList = NULL; m_readySessionList = NULL; m_idleSessionList = NULL; + // 濡傛灉鍚敤浜嗘湰鍦扮郴缁熺紦瀛橈紝閲婃斁鐩稿簲鐨勮祫婧 if (EnableLocalSysCache()) { pfree_ext(m_session_bucket); pfree_ext(m_session_rw_locks); } + + // 灏嗕笌鏈湴绯荤粺缂撳瓨鐩稿叧鐨勬垚鍛樺彉閲忚缃负鍒濆鍊 m_session_nbucket = 0; m_session_bucket = NULL; } @@ -173,27 +196,32 @@ void ThreadPoolListener::NotifyReady() void ThreadPoolListener::CreateEpoll() { - /* MAX_LISTEN_SESSIONS for epool_create is ignored Since Linux 2.6.8 */ + // 鏍规嵁瀹忓畾涔夐夋嫨涓嶅悓鐨 epoll 鍒涘缓鍑芥暟 if (ENABLE_THREAD_POOL_DN_LOGICCONN) { + // 浣跨敤 CommEpollCreate 鍑芥暟鍒涘缓 epoll锛屼紶鍏ユ渶澶т細璇濇暟 m_epollFd = CommEpollCreate(GLOBAL_MAX_SESSION_NUM); } else { + // 浣跨敤 comm_epoll_create 鍑芥暟鍒涘缓 epoll锛屼紶鍏ユ渶澶т細璇濇暟 CommSetEpollOption(CommEpollThreadPoolListener); m_epollFd = comm_epoll_create(GLOBAL_MAX_SESSION_NUM); } + // 妫鏌 epoll 鍒涘缓鏄惁鎴愬姛 if (m_epollFd == INVALID_FD) { ereport(LOG, (errmsg("Fail to create epoll for thread pool listener, " "check if the system is out of memory or " "limit on the total number of open files has been reached."))); - proc_exit(0); + proc_exit(0); // 閫鍑哄綋鍓嶈繘绋 } + // 鍒嗛厤鐢ㄤ簬瀛樺偍 epoll 浜嬩欢鐨勫唴瀛 m_epollEvents = (struct epoll_event*)palloc0_noexcept(sizeof(struct epoll_event) * GLOBAL_MAX_SESSION_NUM); + // 妫鏌ュ唴瀛樺垎閰嶆槸鍚︽垚鍔 if (m_epollEvents == NULL) { elog(LOG, "Not enough memory for listener epoll"); - proc_exit(0); + proc_exit(0); // 閫鍑哄綋鍓嶈繘绋 } } @@ -207,20 +235,19 @@ void ThreadPoolListener::AddEpoll(knl_session_context* session) (errmodule(MOD_THREAD_POOL), errmsg("Add a session:%lu to idleSessionList ", session->session_id))); /* - * Because we will dispatch the socket to worker thread once - * we find an input event of the socket, so we use one_shot mode. + * 鍥犱负涓鏃﹀彂鐜板鎺ュ瓧鏈夎緭鍏ヤ簨浠讹紝灏变細灏嗗鎺ュ瓧鍒嗘淳缁欏伐浣滅嚎绋嬪鐞嗭紝鎵浠ヤ娇鐢 "one_shot" + * 妯″紡鏄悎閫傜殑銆傝繖鎰忓懗鐫褰撲竴涓伐浣滅嚎绋嬪鐞嗗鎺ュ瓧浜嬩欢鏃讹紝鍏朵粬绾跨▼涓嶄細鍚屾椂澶勭悊鐩稿悓鐨勫鎺ュ瓧浜嬩欢锛 + * 浠庤岀‘淇濅簡绾跨▼涔嬮棿鐨勪簰鏂ユэ紝閬垮厤浜嗙珵鎬佹潯浠跺拰鏁版嵁鎹熷潖銆 */ ev.events = EPOLLRDHUP | EPOLLIN | EPOLLET | EPOLLONESHOT; ev.data.ptr = (void*)session; if (session->status != KNL_SESS_UNINIT) { - /* CommProxy Support */ if (ENABLE_THREAD_POOL_DN_LOGICCONN) { res = CommEpollCtl(m_epollFd, EPOLL_CTL_MOD, session->proc_cxt.MyProcPort->sock, &ev); } else { res = comm_epoll_ctl(m_epollFd, EPOLL_CTL_MOD, session->proc_cxt.MyProcPort->sock, &ev); } } else { - /* CommProxy Support */ if (ENABLE_THREAD_POOL_DN_LOGICCONN) { res = CommEpollCtl(m_epollFd, EPOLL_CTL_ADD, session->proc_cxt.MyProcPort->sock, &ev); } else { @@ -244,10 +271,14 @@ void ThreadPoolListener::AddEpoll(knl_session_context* session) bool ThreadPoolListener::TryFeedWorker(ThreadPoolWorker* worker) { Dlelem* sc = GetReadySession(worker); + //鑾峰彇涓涓噯澶囧氨缁殑浼氳瘽 if (sc != NULL) { worker->SetSession((knl_session_context*)sc->dle_val); + //灏嗚浼氳瘽璁剧疆缁欏伐浣滅嚎绋 pg_atomic_fetch_sub_u32((volatile uint32*)&m_group->m_waitServeSessionCount, 1); + //鍑忓皯绛夊緟鏈嶅姟浼氳瘽鐨勮鏁帮紝琛ㄧず璇ヤ細璇濆凡琚垎閰 pg_atomic_fetch_add_u32((volatile uint32*)&m_group->m_processTaskCount, 1); + //澧炲姞姝e湪澶勭悊浠诲姟鐨勮鏁帮紝琛ㄧず宸ヤ綔绾跨▼姝e湪澶勭悊浠诲姟銆 return true; } else { if (EnableLocalSysCache()) { @@ -271,9 +302,10 @@ bool ThreadPoolListener::TryFeedWorker(ThreadPoolWorker* worker) void ThreadPoolListener::AddNewSession(knl_session_context* session) { - AddEpoll(session); + AddEpoll(session);//灏嗘寚瀹氱殑浼氳瘽 session 娣诲姞鍒 epoll 鐩戝惉涓 (void)pg_atomic_fetch_add_u32((volatile uint32*)&m_group->m_sessionCount, 1); - ereport(DEBUG2, + //浣跨敤鍘熷瓙鎿嶄綔澧炲姞绾跨▼姹犵粍鐨勪細璇濊鏁帮紝琛ㄧず鎴愬姛娣诲姞浜嗕竴涓柊鐨勪細璇 + ereport(DEBUG2, (errmodule(MOD_THREAD_POOL), errmsg("This group add a session, and now sessionCount is %d, ", m_group->m_sessionCount))); @@ -298,9 +330,8 @@ void ThreadPoolListener::ReaperAllSession() while (m_group->m_sessionCount > 0) { /* - * There is a very rare case that all thread pool workers happen to - * encounter FATAL and exit before close session. - * Under such scenarios, we choose to exit directly. + * 鍦ㄩ潪甯哥綍瑙佺殑鎯呭喌涓嬶紝鎵鏈夌嚎绋嬫睜宸ヤ綔鑰呴兘閬囧埌浜嗚嚧鍛介敊璇紙FATAL锛夊苟鍦ㄥ叧闂細璇濅箣鍓嶉鍑恒 + * 鍦ㄨ繖绉嶆儏鍐典笅锛屾垜浠夋嫨鐩存帴閫鍑虹▼搴忋 */ if (m_group->m_workerNum <= 0 && m_group->m_sessionCount > 0) { ereport(WARNING, @@ -309,8 +340,7 @@ void ThreadPoolListener::ReaperAllSession() " encounter FATAL problems before session close."))); abort(); } - /* m_sessionCount should be sum of the list length of m_idleSessionList and m_readySessionList - and worker's attached session */ + /* m_sessionCount 搴旇鏄 m_idleSessionList 鍜 m_readySessionList 鐨勫垪琛ㄩ暱搴︿箣鍜岋紝浠ュ強涓庡伐浣滅嚎绋嬪叧鑱旂殑浼氳瘽鐨勬暟閲忎箣鍜 */ pg_memory_barrier(); if (m_idleSessionList->IsEmpty() && m_readySessionList->IsEmpty() && m_group->m_workerNum - m_group->m_idleWorkerNum == 0) { @@ -348,10 +378,10 @@ void ThreadPoolListener::WaitTask() while (true) { if (unlikely(m_getKilled)) { m_getKilled = false; - proc_exit(0); + proc_exit(0); // 濡傛灉闇瑕侀鍑猴紝鐩存帴閫鍑鸿繘绋 } if (unlikely(m_reaperAllSession)) { - ReaperAllSession(); + ReaperAllSession(); // 濡傛灉闇瑕佹竻鐞嗘墍鏈変細璇濓紝鎵ц娓呯悊鎿嶄綔 } /* as we specify timeout -1, so 0 will not be return, either > 0 or < 0 */ @@ -360,6 +390,8 @@ void ThreadPoolListener::WaitTask() } else { nevents = comm_epoll_wait(m_epollFd, m_epollEvents, GLOBAL_MAX_SESSION_NUM, -1); /* CommProxy Support */ } + + // 澶勭悊鏀跺埌鐨勪簨浠 if (nevents > 0 && nevents <= GLOBAL_MAX_SESSION_NUM) { HandleConnEvent(nevents); continue; @@ -367,9 +399,9 @@ void ThreadPoolListener::WaitTask() ereport(PANIC, (errmsg("epoll receive %d events which exceed the limitation %d", nevents, GLOBAL_MAX_SESSION_NUM))); } else if (nevents == -1 && errno == EINTR) { - continue; + continue; // 濡傛灉鏄腑鏂俊鍙凤紝缁х画绛夊緟浜嬩欢 } else { - ereport(LOG, (errmsg("listener wait event encounter some error :%d", errno))); + ereport(LOG, (errmsg("listener wait event encounter some error :%d", errno))); // 鍏朵粬閿欒鎯呭喌涓嬭緭鍑烘棩蹇 } } } @@ -384,10 +416,10 @@ void ThreadPoolListener::HandleConnEvent(int nevets) session = GetSessionBaseOnEvent(tmp_event); if (session == NULL) { - continue; + continue; // 濡傛灉娌℃湁鑾峰彇鍒颁細璇濓紝缁х画澶勭悊涓嬩竴涓簨浠 } - DispatchSession(session); + DispatchSession(session); // 澶勭悊浼氳瘽鐨勫垎娲 } } @@ -402,20 +434,18 @@ knl_session_context* ThreadPoolListener::GetSessionBaseOnEvent(struct epoll_even } else { session->status = KNL_SESS_CLOSE; } - return session; + return session; // 濡傛灉鍙戠敓閿欒鎴栦細璇濆叧闂簨浠讹紝鍒欒繑鍥炶浼氳瘽 } else if (ev->events & EPOLLIN) { - return session; + return session; // 濡傛灉鏄緭鍏ヤ簨浠讹紝杩斿洖璇ヤ細璇 } - return NULL; + return NULL; // 鍏朵粬鎯呭喌涓嬭繑鍥 NULL锛岃〃绀烘病鏈夐渶瑕佸鐞嗙殑浼氳瘽 } void ThreadPoolListener::DispatchSession(knl_session_context* session) { m_idleSessionList->Remove(&session->elem); /* - * If the sock, idx, and streamid parameters of the current session - * do not meet the requirements for logical connection parameters, - * skip this dispatch operation. + * 濡傛灉褰撳墠浼氳瘽鐨 sock銆乮dx 鍜 streamid 鍙傛暟涓嶇鍚堥昏緫杩炴帴鍙傛暟鐨勮姹傦紝鍒欒烦杩囨鍒嗘淳鎿嶄綔銆 */ if (session->proc_cxt.MyProcPort->sock == NO_SOCKET && session->proc_cxt.MyProcPort->gs_sock.idx == 0 && @@ -443,7 +473,7 @@ void ThreadPoolListener::DispatchSession(knl_session_context* session) __func__, session->session_id))); INSTR_TIME_SET_CURRENT(session->last_access_time); - /* Add new session to the head so the connection request can be quickly processed. */ + /* 灏嗘柊浼氳瘽娣诲姞鍒板ご閮紝浠ヤ究鍙互蹇熷鐞嗚繛鎺ヨ姹 */ if (session->status == KNL_SESS_UNINIT) { AddIdleSessionToHead(session); } else { @@ -457,10 +487,15 @@ void ThreadPoolListener::DispatchSession(knl_session_context* session) void ThreadPoolListener::DelSessionFromEpoll(knl_session_context* session) { + //妫鏌ユ槸鍚﹀惎鐢ㄤ簡绾跨▼姹犵殑閫昏緫杩炴帴鏀寔 if (ENABLE_THREAD_POOL_DN_LOGICCONN) { - struct epoll_event ev = {0}; + //鍒涘缓涓涓悕涓 ev 鐨 epoll 浜嬩欢缁撴瀯锛屽苟鍒濆鍖栨墍鏈夊瓧娈典负闆 + struct epoll_event ev = {0}; + //璁剧疆 epoll 浜嬩欢鐨勫叧娉ㄤ簨浠 ev.events = EPOLLRDHUP | EPOLLIN | EPOLLET | EPOLLONESHOT; - ev.data.ptr = (void*)session; + //灏 ev 浜嬩欢鐨勬暟鎹寚閽堣缃负鎸囧悜褰撳墠浼氳瘽 (session) 鐨勬寚閽 + ev.data.ptr = (void*)session; + //浣跨敤 CommEpollCtl 鍑芥暟浠 epoll 涓垹闄ゅ鎺ュ瓧浜嬩欢 CommEpollCtl(m_epollFd, EPOLL_CTL_DEL, session->proc_cxt.MyProcPort->sock, &ev); #ifdef ENABLE_MULTIPLE_NODES } else { @@ -469,6 +504,7 @@ void ThreadPoolListener::DelSessionFromEpoll(knl_session_context* session) #endif comm_epoll_ctl(m_epollFd, EPOLL_CTL_DEL, session->proc_cxt.MyProcPort->sock, NULL); } + //浣跨敤鍘熷瓙鎿嶄綔灏嗕細璇濊鏁板噺灏 1 (void)pg_atomic_fetch_sub_u32((volatile uint32*)&m_group->m_sessionCount, 1); } @@ -479,37 +515,52 @@ void ThreadPoolListener::RemoveWorkerFromList(ThreadPoolWorker* worker) bool ThreadPoolListener::GetSessIshang(instr_time* current_time, uint64* sessionId) { + // 鍒濆鍖 ishang 涓 true bool ishang = true; + + // 鑾峰彇灏辩华浼氳瘽鍒楄〃鐨勯攣 m_readySessionList->GetLock(); + // 鑾峰彇灏辩华浼氳瘽鍒楄〃鐨勫ご鍏冪礌 Dlelem* elem = m_readySessionList->GetHead(); + + // 濡傛灉澶村厓绱犱负绌猴紝閲婃斁閿佸苟杩斿洖 false if (elem == NULL) { m_readySessionList->ReleaseLock(); return false; } + + // 灏嗗ご鍏冪礌杞崲涓 knl_session_context 鎸囬拡 knl_session_context* head_sess = (knl_session_context *)(elem->dle_val); + + // 妫鏌ュ氨缁細璇濈殑鏃堕棿鎴冲拰浼氳瘽ID鏄惁涓庝紶鍏ョ殑鍊煎尮閰 if (INSTR_TIME_GET_MICROSEC(head_sess->last_access_time) == INSTR_TIME_GET_MICROSEC(*current_time) && head_sess->session_id == *sessionId) { - ishang = true; + ishang = true; // 濡傛灉鍖归厤锛宨shang 淇濇寔 true } else { + // 鏇存柊浼犲叆鐨勬椂闂存埑鍜屼細璇滻D *current_time = head_sess->last_access_time; *sessionId = head_sess->session_id; - ishang = false; + ishang = false; // ishang 璁句负 false 琛ㄧず涓嶅啀鎸傝捣鐘舵 } + + // 閲婃斁灏辩华浼氳瘽鍒楄〃鐨勯攣 m_readySessionList->ReleaseLock(); + + // 杩斿洖 ishang锛屾寚绀虹洃鍚櫒鏄惁鎸傝捣 return ishang; } Dlelem *ThreadPoolListener::GetFreeWorker(knl_session_context* session) { - /* only lite mode need find right threadworker, - * otherwise since there are so many requests, we dont have any freeworkers. so optimization is not necessary */ + /* 鍙湁鍦 "杞婚噺绾фā寮" 涓嬫墠闇瑕佹壘鍒版纭殑绾跨▼宸ヤ綔绾跨▼锛屽惁鍒欑敱浜庢湁濡傛 + 澶氱殑璇锋眰锛屾垜浠病鏈変换浣曠┖闂插伐浣滅嚎绋嬶紝鍥犳涓嶉渶瑕佽繘琛屼紭鍖栥*/ #ifdef ENABLE_LITE_MODE if (!EnableLocalSysCache()) { return m_freeWorkerList->RemoveHead(); } - /* sess is not init, we dont know how to hit the cache */ + /* 濡傛灉浼氳瘽鏈垵濮嬪寲锛屾垜浠笉鐭ラ亾濡備綍鍛戒腑缂撳瓨 */ if (session->status != KNL_SESS_ATTACH && session->status != KNL_SESS_DETACH) { return m_freeWorkerList->RemoveTail(); } @@ -518,16 +569,16 @@ Dlelem *ThreadPoolListener::GetFreeWorker(knl_session_context* session) return m_freeWorkerList->RemoveTail(); } - /* for lite_mode, threadworkers are a small amount, so it is quickly to traverse the list */ + /* 瀵逛簬杞婚噺绾фā寮忥紝绾跨▼宸ヤ綔鑰呮暟閲忚緝灏戯紝鍥犳杩呴熼亶鍘嗗垪琛ㄦ槸鍙鐨勩 */ m_freeWorkerList->GetLock(); for (Dlelem *elt = m_freeWorkerList->GetHead(); elt != NULL; elt = DLGetSucc(elt)) { ThreadPoolWorker *worker = (ThreadPoolWorker *)DLE_VAL(elt); LocalSysDBCache *lsc = worker->GetThreadContextPtr()->lsc_cxt.lsc; - /* uninited lsc are addtotail of the list, so when see one uninited, the follow all are uninited. just break */ + /* 鏈垵濮嬪寲鐨勬湰鍦扮郴缁熺紦瀛橈紙lsc锛夎娣诲姞鍒板垪琛ㄧ殑鏈熬锛屽洜姝ゅ綋閬囧埌涓涓湭鍒濆鍖栫殑鏃跺欙紝鍚庣画鐨勬墍鏈変篃閮芥槸鏈垵濮嬪寲鐨勩傚洜姝ゅ彲浠ョ洿鎺ヤ腑鏂紙break锛夈 */ if (unlikely(lsc == NULL || lsc->my_database_id == InvalidOid)) { break; } - /* cache hit */ + /* 缂撳瓨鍛戒腑 */ if (likely(lsc->my_database_id == session->proc_cxt.MyDatabaseId)) { m_freeWorkerList->Remove(elt); m_freeWorkerList->ReleaseLock(); @@ -535,7 +586,8 @@ Dlelem *ThreadPoolListener::GetFreeWorker(knl_session_context* session) } } m_freeWorkerList->ReleaseLock(); - /* dont find, use tail instead head, because head of the list has syscache of other db */ + /* 寤鸿涓嶈浠庨摼琛ㄧ殑澶撮儴鏌ユ壘锛岃屾槸浠庡熬閮ㄥ紑濮嬫煡鎵撅紝鍥犱负閾捐〃鐨勫ご閮ㄥ彲鑳藉寘鍚簡 + 鏉ヨ嚜鍏朵粬鏁版嵁搴撶殑绯荤粺缂撳瓨锛坰yscache锛夋暟鎹 */ return m_freeWorkerList->RemoveTail(); #else return m_freeWorkerList->RemoveHead(); @@ -544,12 +596,12 @@ Dlelem *ThreadPoolListener::GetFreeWorker(knl_session_context* session) static Dlelem *GetHeadUnInitSession(DllistWithLock* m_readySessionList) { - /* uninit session needs be replied first */ + /* 鏈垵濮嬪寲鐨勪細璇濆簲璇ラ鍏堝緱鍒板洖澶 */ m_readySessionList->GetLock(); Dlelem *head = m_readySessionList->GetHead(); if (likely(head != NULL)) { if (((knl_session_context *)DLE_VAL(head))->status != KNL_SESS_UNINIT) { - /* go cache hit branch, set it null */ + /* 绋嬪簭鍦ㄦ墽琛岃繃绋嬩腑杩涘叆浜嗏滅紦瀛樺懡涓垎鏀濓紝骞朵笖灏嗘煇涓艰缃负浜 null */ head = NULL; } else { head = m_readySessionList->RemoveHeadNoLock(); @@ -574,11 +626,11 @@ Dlelem *ThreadPoolListener::GetSessFromReadySessionList(ThreadPoolWorker *worker break; } LocalSysDBCache *lsc = worker->GetThreadContextPtr()->lsc_cxt.lsc; - // worker not init, any session is matched + // 濡傛灉宸ヤ綔绾跨▼灏氭湭鍒濆鍖栵紝閭d箞浠讳綍浼氳瘽閮戒笉浼氳鍖归厤鎴栧叧鑱 if (unlikely(lsc == NULL || lsc->my_database_id == InvalidOid)) { break; } - // now we try to reuse workers syscache + // 鐜板湪鎴戜滑灏濊瘯閲嶇敤宸ヤ綔绾跨▼鐨勭郴缁熺紦瀛 Index hash_index = HASH_INDEX(lsc->my_database_id, (uint32)m_session_nbucket); ResourceOwner owner = LOCAL_SYSDB_RESOWNER; PthreadRWlockRdlock(owner, &m_session_rw_locks[hash_index]); @@ -588,7 +640,7 @@ Dlelem *ThreadPoolListener::GetSessFromReadySessionList(ThreadPoolWorker *worker break; } if (!m_readySessionList->RemoveConfirm(&((knl_session_context *)DLE_VAL(elt))->elem)) { - // someone remove it already + // 宸茬粡灏嗕粬绉婚櫎浜 PthreadRWlockUnlock(owner, &m_session_rw_locks[hash_index]); break; } @@ -606,14 +658,17 @@ Dlelem *ThreadPoolListener::GetReadySession(ThreadPoolWorker *worker) if (!EnableLocalSysCache()) { return m_readySessionList->RemoveHead(); } + // 濡傛灉涓嶅惎鐢ㄦ湰鍦扮郴缁熺紦瀛橈紝鐩存帴浠庡氨缁細璇濆垪琛ㄧ殑澶撮儴绉婚櫎骞惰繑鍥炰竴涓細璇濄 Dlelem *elt = GetSessFromReadySessionList(worker); if (elt == NULL) { return NULL; } + // 浠庢湰鍦扮郴缁熺紦瀛樹腑鑾峰彇涓涓細璇濄 knl_session_context *session = (knl_session_context *)DLE_VAL(elt); Oid cur_dbid = session->proc_cxt.MyDatabaseId; Index hash_index = HASH_INDEX(cur_dbid, (uint32)m_session_nbucket); ResourceOwner owner = LOCAL_SYSDB_RESOWNER; + // 鑾峰彇鏈湴绯荤粺缂撳瓨鐨勮祫婧愰攣锛屽苟浠庡氨缁細璇濆垪琛ㄤ腑绉婚櫎璇ヤ細璇濄 PthreadRWlockWrlock(owner, &m_session_rw_locks[hash_index]); DLRemove(&session->elem2); PthreadRWlockUnlock(owner, &m_session_rw_locks[hash_index]); @@ -626,8 +681,10 @@ void ThreadPoolListener::AddIdleSessionToTail(knl_session_context* session) m_readySessionList->AddTail(&session->elem); return; } + // 濡傛灉涓嶅惎鐢ㄦ湰鍦扮郴缁熺紦瀛橈紝灏嗕細璇濇坊鍔犲埌灏辩华浼氳瘽鍒楄〃鐨勫熬閮ㄣ Index hash_index = HASH_INDEX(session->proc_cxt.MyDatabaseId, (uint32)m_session_nbucket); ResourceOwner owner = LOCAL_SYSDB_RESOWNER; + // 鑾峰彇鏈湴绯荤粺缂撳瓨鐨勮祫婧愰攣锛屽苟灏嗕細璇濇坊鍔犲埌鏈湴绯荤粺缂撳瓨鍜屽氨缁細璇濆垪琛ㄧ殑灏鹃儴銆 PthreadRWlockWrlock(owner, &m_session_rw_locks[hash_index]); DLAddTail(&m_session_bucket[hash_index], &session->elem2); PthreadRWlockUnlock(owner, &m_session_rw_locks[hash_index]); @@ -640,10 +697,12 @@ void ThreadPoolListener::AddIdleSessionToHead(knl_session_context* session) m_readySessionList->AddHead(&session->elem); return; } + // 濡傛灉涓嶅惎鐢ㄦ湰鍦扮郴缁熺紦瀛橈紝灏嗕細璇濇坊鍔犲埌灏辩华浼氳瘽鍒楄〃鐨勫ご閮ㄣ Index hash_index = HASH_INDEX(session->proc_cxt.MyDatabaseId, (uint32)m_session_nbucket); ResourceOwner owner = LOCAL_SYSDB_RESOWNER; + // 鑾峰彇鏈湴绯荤粺缂撳瓨鐨勮祫婧愰攣锛屽苟灏嗕細璇濇坊鍔犲埌鏈湴绯荤粺缂撳瓨鍜屽氨缁細璇濆垪琛ㄧ殑澶撮儴銆 PthreadRWlockWrlock(owner, &m_session_rw_locks[hash_index]); DLAddHead(&m_session_bucket[hash_index], &session->elem2); PthreadRWlockUnlock(owner, &m_session_rw_locks[hash_index]); m_readySessionList->AddHead(&session->elem); -} +} \ No newline at end of file diff --git a/src/gausskernel/process/threadpool/threadpool_scheduler.cpp b/src/gausskernel/process/threadpool/threadpool_scheduler.cpp index e44aa11ca..90532019b 100644 --- a/src/gausskernel/process/threadpool/threadpool_scheduler.cpp +++ b/src/gausskernel/process/threadpool/threadpool_scheduler.cpp @@ -42,35 +42,40 @@ #include "utils/guc.h" #include "replication/syncrep.h" -#define SCHEDULER_TIME_UNIT 1000000 //us +// 瀹氫箟甯搁噺锛岃〃绀烘椂闂村崟浣嶄负寰 +#define SCHEDULER_TIME_UNIT 1000000 //寰 #define ENLARGE_THREAD_TIME 5 #define MAX_HANG_TIME 100 #define REDUCE_THREAD_TIME 100 #define SHUTDOWN_THREAD_TIME 1000 #define GPC_CLEAN_TIME 300 +// 瀹氫箟澶勭悊SIGKILL淇″彿鐨勫嚱鏁 static void SchedulerSIGKILLHandler(SIGNAL_ARGS) { t_thrd.threadpool_cxt.scheduler->m_getKilled = true; } +// 瀹氫箟ThreadPoolScheduler绫荤殑SigHupHandler鏂规硶锛岀敤浜庡鐞哠IGHUP淇″彿 void ThreadPoolScheduler::SigHupHandler() { m_getSIGHUP = true; } +// 瀹氫箟reloadConfigFileIfNecessary鍑芥暟锛屽鏋滈渶瑕佺殑璇濋噸鏂板姞杞介厤缃枃浠 static void reloadConfigFileIfNecessary() { if (unlikely(t_thrd.threadpool_cxt.scheduler->m_getSIGHUP)) { t_thrd.threadpool_cxt.scheduler->m_getSIGHUP = false; ProcessConfigFile(PGC_SIGHUP); - /* Update most_available_sync if it's modified dynamically. */ - most_available_sync = (volatile bool) u_sess->attr.attr_storage.guc_most_available_sync; + /* 濡傛灉鍔ㄦ佷慨鏀逛簡most_available_sync锛屽垯鏇存柊瀹冦 */ + most_available_sync = (volatile bool)u_sess->attr.attr_storage.guc_most_available_sync; SyncRepUpdateSyncStandbysDefined(); } } -void TpoolSchedulerMain(ThreadPoolScheduler *scheduler) +// 瀹氫箟TpoolSchedulerMain鍑芥暟锛岃繖鏄嚎绋嬫睜璋冨害鍣ㄧ殑涓昏鎵ц鍑芥暟 +void TpoolSchedulerMain(ThreadPoolScheduler* scheduler) { int gpc_count = 0; @@ -99,18 +104,20 @@ void TpoolSchedulerMain(ThreadPoolScheduler *scheduler) proc_exit(0); } +// 瀹氫箟ThreadPoolScheduler绫荤殑鏋勯犲嚱鏁帮紝鎺ュ彈绾跨▼姹犵粍鏁伴噺鍜岀嚎绋嬫睜缁勬暟缁勪綔涓哄弬鏁 ThreadPoolScheduler::ThreadPoolScheduler(int groupNum, ThreadPoolGroup** groups) -:m_groupNum(groupNum), m_groups(groups), m_has_shutdown(false) + : m_groupNum(groupNum), m_groups(groups), m_has_shutdown(false) { m_tid = 0; - m_hangTestCount = (uint *)palloc0(sizeof(uint) * groupNum); - m_freeTestCount = (uint *)palloc0(sizeof(uint) * groupNum); - m_freeStreamCount = (uint *)palloc0(sizeof(uint) * groupNum); + m_hangTestCount = (uint*)palloc0(sizeof(uint) * groupNum); + m_freeTestCount = (uint*)palloc0(sizeof(uint) * groupNum); + m_freeStreamCount = (uint*)palloc0(sizeof(uint) * groupNum); m_gpcContext = NULL; m_getSIGHUP = false; m_canAdjustPool = true; } +// 瀹氫箟ThreadPoolScheduler绫荤殑鏋愭瀯鍑芥暟 ThreadPoolScheduler::~ThreadPoolScheduler() { m_groups = NULL; @@ -119,12 +126,14 @@ ThreadPoolScheduler::~ThreadPoolScheduler() m_freeTestCount = NULL; } +// 瀹氫箟ThreadPoolScheduler绫荤殑StartUp鏂规硶锛岀敤浜庡垵濮嬪寲璋冨害鍣ㄥ苟鍚姩鍏朵富寰幆 int ThreadPoolScheduler::StartUp() { m_tid = initialize_util_thread(THREADPOOL_SCHEDULER, (void*)this); return ((m_tid == 0) ? STATUS_ERROR : STATUS_OK); } +// 瀹氫箟ThreadPoolScheduler绫荤殑DynamicAdjustThreadPool鏂规硶锛岀敤浜庡姩鎬佽皟鏁寸嚎绋嬫睜 void ThreadPoolScheduler::DynamicAdjustThreadPool() { for (int i = 0; i < m_groupNum; i++) { @@ -135,6 +144,7 @@ void ThreadPoolScheduler::DynamicAdjustThreadPool() } } +// 瀹氫箟ThreadPoolScheduler绫荤殑GPCScheduleCleaner鏂规硶锛岀敤浜庢竻鐞嗗叏灞璁″垝缂撳瓨(GPC)鏉$洰 void ThreadPoolScheduler::GPCScheduleCleaner(int* gpc_count) { if (ENABLE_GPC && *gpc_count == GPC_CLEAN_TIME) { @@ -152,16 +162,18 @@ void ThreadPoolScheduler::GPCScheduleCleaner(int* gpc_count) (*gpc_count)++; } +// 瀹氫箟ThreadPoolScheduler绫荤殑ShutDown鏂规硶锛岀敤浜庡彂閫丼IGKILL淇″彿浠ュ叧闂嚎绋嬫睜璋冨害鍣 void ThreadPoolScheduler::ShutDown() const { if (m_tid != 0) gs_signal_send(m_tid, SIGKILL); } +// 瀹氫箟ThreadPoolScheduler绫荤殑AdjustWorkerPool鏂规硶锛岀敤浜庤皟鏁村伐浣滅嚎绋嬫睜 void ThreadPoolScheduler::AdjustWorkerPool(int idx) { ThreadPoolGroup* group = m_groups[idx]; - /* When no idle worker and no task has been processed, the system may hang. */ + /* 褰撴病鏈夌┖闂插伐浣滅嚎绋嬩笖娌℃湁浠诲姟琚鐞嗘椂锛岀郴缁熷彲鑳戒細鎸傝捣銆 */ if (group->IsGroupHang()) { m_hangTestCount[idx]++; m_freeTestCount[idx] = 0; @@ -174,56 +186,5 @@ void ThreadPoolScheduler::AdjustWorkerPool(int idx) } } -void ThreadPoolScheduler::AdjustStreamPool(int idx) -{ -#ifdef ENABLE_MULTIPLE_NODES - ThreadPoolGroup* group = m_groups[idx]; - - if (group->HasFreeStream()) { - m_freeStreamCount[idx]++; - if (m_freeStreamCount[idx] == SHUTDOWN_THREAD_TIME) { - group->ReduceStreams(); - m_freeStreamCount[idx] = 0; - } - } else { - m_freeStreamCount[idx] = 0; - } -#endif -} - -void ThreadPoolScheduler::EnlargeWorkerIfNecessage(int groupIdx) -{ - ThreadPoolGroup *group = m_groups[groupIdx]; - if (m_hangTestCount[groupIdx] >= ENLARGE_THREAD_TIME && m_hangTestCount[groupIdx] < MAX_HANG_TIME) { - if (group->EnlargeWorkers(THREAD_SCHEDULER_STEP)) { - m_hangTestCount[groupIdx] = 0; - } - } else if (m_hangTestCount[groupIdx] == MAX_HANG_TIME) { - elog(WARNING, "[SCHEDULER] Detect the system has hang %d seconds, " - "and the thread num in pool exceed maximum, " - "so we need to close all new sessions.", MAX_HANG_TIME); - /* set flag for don't accept new session */ - group->SetGroupHanged(true); - } -} - -void ThreadPoolScheduler::ReduceWorkerIfNecessary(int groupIdx) -{ - ThreadPoolGroup *group = m_groups[groupIdx]; - - if (group->m_expectWorkerNum == group->m_defaultWorkerNum && - group->m_pendingWorkerNum == 0) { - m_freeTestCount[groupIdx] = 0; - return; - } - - if (m_freeTestCount[groupIdx] % REDUCE_THREAD_TIME == 0) { - group->ReduceWorkers(THREAD_SCHEDULER_STEP); - } - - if (m_freeTestCount[groupIdx] == SHUTDOWN_THREAD_TIME) { - group->ShutDownPendingWorkers(); - m_freeTestCount[groupIdx] = 0; - } -} - +// 瀹氫箟ThreadPoolScheduler绫荤殑AdjustStreamPool鏂规硶锛岀敤浜庤皟鏁存祦绾跨▼姹 +void ThreadPoolScheduler::AdjustStreamPool(int diff --git a/src/gausskernel/process/threadpool/threadpool_sessctl.cpp b/src/gausskernel/process/threadpool/threadpool_sessctl.cpp index 1267f0ad1..cb972b2d7 100755 --- a/src/gausskernel/process/threadpool/threadpool_sessctl.cpp +++ b/src/gausskernel/process/threadpool/threadpool_sessctl.cpp @@ -59,51 +59,63 @@ #endif +// 绾跨▼姹犱細璇濇帶鍒剁被鐨勬瀯閫犲嚱鏁帮紙鍙傛暟锛氬唴瀛樹笂涓嬫枃锛 ThreadPoolSessControl::ThreadPoolSessControl(MemoryContext context) { + // 鑷姩涓婁笅鏂囧垏鎹㈠埌鎸囧畾鐨勫唴瀛樹笂涓嬫枃 AutoContextSwitch acontext(context); m_context = context; - pthread_mutex_init(&m_sessCtrlock, NULL); - m_sessionId = 0; - m_activeSessionCount = 0; - m_maxActiveSessionCount = GLOBAL_MAX_SESSION_NUM; - m_maxReserveSessionCount = GLOBAL_RESERVE_SESSION_NUM; - DLInitList(&m_activelist); - DLInitList(&m_freelist); + pthread_mutex_init(&m_sessCtrlock, NULL); // 鍒濆鍖栫嚎绋嬩簰鏂ラ攣 + m_sessionId = 0; // 浼氳瘽 ID 鍒濆鍖栦负 0 + m_activeSessionCount = 0; // 娲昏穬浼氳瘽璁℃暟鍣ㄥ垵濮嬪寲涓 0 + m_maxActiveSessionCount = GLOBAL_MAX_SESSION_NUM; // 鏈澶ф椿璺冧細璇濇暟鍒濆鍖栦负鍏ㄥ眬鏈澶т細璇濇暟 + m_maxReserveSessionCount = GLOBAL_RESERVE_SESSION_NUM; // 鏈澶т繚鐣欎細璇濇暟鍒濆鍖栦负鍏ㄥ眬淇濈暀浼氳瘽鏁 + DLInitList(&m_activelist); // 鍒濆鍖栨椿璺冧細璇濆垪琛 + DLInitList(&m_freelist); // 鍒濆鍖栫┖闂蹭細璇濆垪琛 + // 鍒嗛厤瀛樺偍绌洪棿骞跺垵濮嬪寲鍩虹浼氳瘽鎺у埗缁撴瀯 m_base = (knl_sess_control*)palloc0(sizeof(knl_sess_control) * m_maxActiveSessionCount); for (int i = 0; i < m_maxActiveSessionCount; i++) { - m_base[i].idx = (m_maxReserveSessionCount + i); - m_base[i].lock = 0; - DLInitElem(&m_base[i].elem, &m_base[i]); - DLAddHead(&m_freelist, &m_base[i].elem); + m_base[i].idx = (m_maxReserveSessionCount + i); // 璁剧疆浼氳瘽绱㈠紩 + m_base[i].lock = 0; // 浼氳瘽閿佸畾鏍囧織鍒濆鍖栦负 0 + DLInitElem(&m_base[i].elem, &m_base[i]); // 鍒濆鍖栧弻鍚戦摼琛ㄥ厓绱 + DLAddHead(&m_freelist, &m_base[i].elem); // 灏嗗綋鍓嶄細璇濇坊鍔犲埌绌洪棽浼氳瘽鍒楄〃澶撮儴 } } +// 绾跨▼姹犱細璇濇帶鍒剁被鐨勬瀽鏋勫嚱鏁 ThreadPoolSessControl::~ThreadPoolSessControl() { - pfree_ext(m_base); - m_context = NULL; + pfree_ext(m_base); // 閲婃斁鍩虹浼氳瘽鎺у埗缁撴瀯鐨勫唴瀛 + m_context = NULL; // 灏嗗唴瀛樹笂涓嬫枃鎸囬拡缃负绌 } +// 鍒涘缓鏂扮殑绾跨▼姹犱細璇濓紙鍙傛暟锛氱鍙f寚閽堬級 knl_session_context* ThreadPoolSessControl::CreateSession(Port* port) { knl_session_context* sc = NULL; - /* We use u_sess->session_id to mark memory context. */ + /* 浣跨敤 u_sess->session_id 鏍囪鍐呭瓨涓婁笅鏂囥 */ m_sessionId++; + // 鍒涘缓浼氳瘽涓婁笅鏂 sc = create_session_context(m_context, m_sessionId); if (sc == NULL) { - ereport(WARNING, (errmsg("can't allocate memory for session"))); + ereport(WARNING, (errmsg("can't allocate memory for session"))); // 鍐呭瓨鍒嗛厤澶辫触鎶ヨ return NULL; } + // 鍒囨崲鍐呭瓨涓婁笅鏂囧埌榛樿鍐呭瓨涓婁笅鏂 MemoryContext old_cxt = MemoryContextSwitchTo(sc->mcxt_group->GetMemCxtGroup(MEMORY_CONTEXT_DEFAULT)); + // 鍒嗛厤骞跺鍒剁鍙d俊鎭埌鏂扮殑浼氳瘽涓婁笅鏂 sc->proc_cxt.MyProcPort = (Port*)palloc0(sizeof(Port)); MemoryContextSwitchTo(old_cxt); + + // 澶嶅埗绔彛淇℃伅 int rc = memcpy_s(sc->proc_cxt.MyProcPort, sizeof(Port), port, sizeof(Port)); securec_check(rc, "\0", "\0"); - ereport(DEBUG4, (errmsg("CreateSession fd:[%d] to dispatch.", port->sock))); + ereport(DEBUG4, (errmsg("CreateSession fd:[%d] to dispatch.", port->sock))); // 鍒涘缓浼氳瘽骞跺垎娲炬姤鍛婃棩蹇 + + // 鍒嗛厤浼氳瘽妲戒綅锛屽鏋滄垚鍔熷垯杩斿洖浼氳瘽锛屽惁鍒欐竻鐞嗚祫婧愯繑鍥 NULL if (AllocateSlot(sc)) { sc->stat_cxt.trackedBytes += u_sess->stat_cxt.trackedBytes; sc->stat_cxt.trackedMemChunks += u_sess->stat_cxt.trackedMemChunks; @@ -113,7 +125,7 @@ knl_session_context* ThreadPoolSessControl::CreateSession(Port* port) } else { u_sess->stat_cxt.trackedBytes += sc->stat_cxt.trackedBytes; u_sess->stat_cxt.trackedMemChunks += sc->stat_cxt.trackedMemChunks; - // sc->top_mem_cxt has been sealed in create_session_context + // sc->top_mem_cxt 鍦 create_session_context 涓凡缁忚灏佸瓨 MemoryContextUnSeal(sc->top_mem_cxt); MemoryContextDeleteChildren(sc->top_mem_cxt); MemoryContextDelete(sc->top_mem_cxt); @@ -122,117 +134,121 @@ knl_session_context* ThreadPoolSessControl::CreateSession(Port* port) } } +// 鍒嗛厤涓涓細璇濇Ы浣嶅苟杩斿洖浼氳瘽鎺у埗缁撴瀯鎸囬拡锛堝弬鏁帮細浼氳瘽涓婁笅鏂囷級 knl_sess_control* ThreadPoolSessControl::AllocateSlot(knl_session_context* sc) { - AutoMutexLock alock(&m_sessCtrlock); - alock.lock(); + AutoMutexLock alock(&m_sessCtrlock); // 鑷姩閿佸畾浜掓枼閿 + alock.lock(); // 閿佸畾浜掓枼閿 + + // 妫鏌ユ槸鍚﹀彲浠ユ帴鍙楁柊杩炴帴 if (canAcceptConnections(true) != CAC_OK) { - alock.unLock(); - /* CN is in the process of starting recovery, redo is not completed, so the connection error is reasonable */ - ereport(WARNING, - (errmsg("ThreadPool cannot start new session due to PM state, PM state is %s", GetPMState(pmState)))); + alock.unLock(); // 瑙i攣浜掓枼閿 + /* 鏁版嵁搴撴鍦ㄦ墽琛屾仮澶嶈繃绋嬶紝姝ゆ椂杩炴帴閿欒鏄悎鐞嗙殑 */ + ereport(WARNING, (errmsg("ThreadPool cannot start new session due to PM state, PM state is %s", GetPMState(pmState)))); return NULL; } + // 妫鏌ユ椿璺冧細璇濇暟鏄惁宸茶揪涓婇檺 if (m_activeSessionCount == m_maxActiveSessionCount) { - alock.unLock(); - ereport(WARNING, - (errmsg("ThreadPool cannot start new session due to to many sessions, current upper bound is %d", - m_maxActiveSessionCount))); + alock.unLock(); // 瑙i攣浜掓枼閿 + ereport(WARNING, (errmsg("ThreadPool cannot start new session due to to many sessions, current upper bound is %d", + m_maxActiveSessionCount))); // 娲昏穬浼氳瘽鏁板凡杈句笂闄愭姤璀 return NULL; } - Assert(DLListLength(&m_freelist) != 0); + Assert(DLListLength(&m_freelist) != 0); // 纭繚绌洪棽浼氳瘽鍒楄〃涓嶄负绌 - /* remove from free list */ + // 浠庣┖闂蹭細璇濆垪琛ㄤ腑绉婚櫎涓涓細璇濇帶鍒剁粨鏋 knl_sess_control* ctrl = (knl_sess_control*)DLE_VAL(DLRemHead(&m_freelist)); ctrl->sess = sc; - sc->session_ctr_index = ctrl->idx; - DLAddHead(&m_activelist, &ctrl->elem); - m_activeSessionCount++; - alock.unLock(); + sc->session_ctr_index = ctrl->idx; // 璁剧疆浼氳瘽妲戒綅绱㈠紩 + DLAddHead(&m_activelist, &ctrl->elem); // 灏嗕細璇濇帶鍒剁粨鏋勬坊鍔犲埌娲昏穬浼氳瘽鍒楄〃澶撮儴 + m_activeSessionCount++; // 娲昏穬浼氳瘽璁℃暟鍣ㄥ姞涓 + alock.unLock(); // 瑙i攣浜掓枼閿 return ctrl; } +// 閲婃斁涓涓細璇濇Ы浣嶏紙鍙傛暟锛氫細璇濇Ы浣嶇储寮曪級 void ThreadPoolSessControl::FreeSlot(int ctrl_index) { if (!IsValidCtrlIndex(ctrl_index)) { return; } - AutoMutexLock alock(&m_sessCtrlock); - alock.lock(); + AutoMutexLock alock(&m_sessCtrlock); // 鑷姩閿佸畾浜掓枼閿 + alock.lock(); // 閿佸畾浜掓枼閿 - knl_sess_control *ctrl = &m_base[ctrl_index - m_maxReserveSessionCount]; - Assert(ctrl->elem.dle_list == &m_activelist); + knl_sess_control *ctrl = &m_base[ctrl_index - m_maxReserveSessionCount]; // 鑾峰彇浼氳瘽鎺у埗缁撴瀯 + Assert(ctrl->elem.dle_list == &m_activelist); // 纭繚浼氳瘽鎺у埗缁撴瀯鍦ㄦ椿璺冧細璇濆垪琛ㄤ腑 - m_activeSessionCount--; + m_activeSessionCount--; // 娲昏穬浼氳瘽璁℃暟鍣ㄥ噺涓 volatile sig_atomic_t* plock = &ctrl->lock; sig_atomic_t val; do { if (*plock == 0) { - /* perform an atomic compare and swap. */ + /* 杩涜鍘熷瓙姣旇緝鍜屼氦鎹㈡搷浣 */ val = __sync_val_compare_and_swap(plock, 0, 1); if (val == 0) { ctrl->sess = NULL; - /* restore the value. */ + /* 鎭㈠鍊 */ ctrl->lock = 0; - DLRemove(&ctrl->elem); - DLAddHead(&m_freelist, &ctrl->elem); + DLRemove(&ctrl->elem); // 浠庢椿璺冧細璇濆垪琛ㄤ腑绉婚櫎 + DLAddHead(&m_freelist, &ctrl->elem); // 灏嗕細璇濇帶鍒剁粨鏋勬坊鍔犲埌绌洪棽浼氳瘽鍒楄〃澶撮儴 break; } } - pg_usleep(100); + pg_usleep(100); // 浼戠湢 100 寰 } while (true); - alock.unLock(); + alock.unLock(); // 瑙i攣浜掓枼閿 } +// 鏍囪鎵鏈変細璇濅负鍏抽棴鐘舵 void ThreadPoolSessControl::MarkAllSessionClose() { - /* Mark all session to be closed. */ - AutoMutexLock alock(&m_sessCtrlock); - alock.lock(); + /* 鏍囪鎵鏈変細璇濅负鍏抽棴鐘舵併*/ + AutoMutexLock alock(&m_sessCtrlock); // 鑷姩閿佸畾浜掓枼閿 + alock.lock(); // 閿佸畾浜掓枼閿 knl_sess_control* ctrl = NULL; - Dlelem* elem = DLGetHead(&m_activelist); + Dlelem* elem = DLGetHead(&m_activelist); // 鑾峰彇娲昏穬浼氳瘽鍒楄〃鐨勫ご閮 while (elem != NULL) { - ctrl= (knl_sess_control*)DLE_VAL(elem); - ctrl->sess->status = KNL_SESS_CLOSE; - CloseClientSocket(ctrl->sess, false); - elem = DLGetSucc(elem); + ctrl = (knl_sess_control*)DLE_VAL(elem); + ctrl->sess->status = KNL_SESS_CLOSE; // 璁剧疆浼氳瘽鐘舵佷负鍏抽棴 + CloseClientSocket(ctrl->sess, false); // 鍏抽棴瀹㈡埛绔鎺ュ瓧 + elem = DLGetSucc(elem); // 鑾峰彇涓嬩竴涓厓绱 } - alock.unLock(); + alock.unLock(); // 瑙i攣浜掓枼閿 ereport(LOG, (errmodule(MOD_THREAD_POOL), - errmsg("pmState:%d, mark all threadpool sessions closed.", pmState))); + errmsg("pmState:%d, mark all threadpool sessions closed.", pmState))); // 璁板綍鏃ュ織 } +// 妫鏌ュ彂閫佷俊鍙风殑鏉冮檺锛堝弬鏁帮細浼氳瘽涓婁笅鏂囷紝閿佹寚閽堬級 void ThreadPoolSessControl::CheckPermissionForSendSignal(knl_session_context* sess, sig_atomic_t* lock) { - /* User id is invalid only when sometimes dealing with cancel signal. Because that permission is ensured - by random cancel key, so we don't have to check the permission again. */ + /* 褰撳鐞嗗彇娑堜俊鍙锋椂锛岀敤鎴 ID 鏃犳晥銆傚洜涓哄彇娑堜俊鍙风殑鏉冮檺鏄氳繃闅忔満鍙栨秷瀵嗛挜淇濊瘉鐨勶紝鎵浠ヤ笉闇瑕佸啀娆℃鏌ユ潈闄愩*/ if (!OidIsValid(u_sess->misc_cxt.CurrentUserId)) { return; } - /* Only users with sysadmin privilege or the member of gs_role_signal_backend role - * or the owner of the database or user himself have the permission to send singal. */ + /* 鍙湁鍏锋湁 sysadmin 鐗规潈銆乬s_role_signal_backend 瑙掕壊鐨勬垚鍛樸佹暟鎹簱鐨勬墍鏈夎呮垨鐢ㄦ埛鏈韩鎵嶅叿鏈夊彂閫佷俊鍙风殑鏉冮檺銆 */ bool role_signal_backend_permission = is_member_of_role(GetUserId(), DEFAULT_ROLE_SIGNAL_BACKENDID) && (sess->proc_cxt.MyRoleId != BOOTSTRAP_SUPERUSERID && !is_role_persistence(sess->proc_cxt.MyRoleId)); if (!superuser() && !pg_database_ownercheck(sess->proc_cxt.MyDatabaseId, u_sess->misc_cxt.CurrentUserId) && !role_signal_backend_permission) { if (sess->proc_cxt.MyRoleId != GetUserId()) { - *lock = 0; + *lock = 0; // 瑙i攣 ereport(ERROR, (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), (errmsg("must have sysadmin privilege or a member of the gs_role_signal_backend role or the " - "owner of the database or the same user to terminate other backend")))); + "owner of the database or the same user to terminate other backend")))); // 鍙戦侀敊璇姤鍛 } } } +// 濡傛灉蹇呰锛岄噴鏀鹃攣锛堥氬父鐢ㄤ簬澶勭悊寮傚父鎯呭喌锛 void ThreadPoolSessControl::releaseLockIfNecessary() { if (unlikely(t_thrd.sig_cxt.cur_ctrl_index != 0)) { - knl_sess_control* ctrl = &m_base[t_thrd.sig_cxt.cur_ctrl_index - m_maxReserveSessionCount]; + knl_sess_control* ctrl = &m_base[t_thrd.sig_cxt.cur_ctrl_index - m_maxReserveSessionCount]; // 鑾峰彇浼氳瘽鎺у埗缁撴瀯 volatile sig_atomic_t plock = ctrl->lock; if (plock != 0) { plock = 0; @@ -241,468 +257,549 @@ void ThreadPoolSessControl::releaseLockIfNecessary() } } +// 鍚戞寚瀹氫細璇濆彂閫佷俊鍙凤紙鍙傛暟锛氫細璇濇Ы浣嶇储寮曪紝淇″彿缂栧彿锛 int ThreadPoolSessControl::SendSignal(int ctrl_index, int signal) { - Assert(signal != SIGHUP); - int status = ESRCH; + Assert(signal != SIGHUP); // 鏂█锛氫俊鍙蜂笉鑳戒负 SIGHUP + int status = ESRCH; // 鍒濆鐘舵佷负 ESRCH锛堟病鏈夎繖鏍风殑杩涚▼锛 + + // 妫鏌ヤ細璇濇Ы浣嶇储寮曟槸鍚︽湁鏁 if (!IsValidCtrlIndex(ctrl_index)) { - return ESRCH; + return ESRCH; // 杩斿洖 ESRCH锛堟病鏈夎繖鏍风殑杩涚▼锛 } + // 鑾峰彇鎸囧畾浼氳瘽鐨勪細璇濇帶鍒剁粨鏋 knl_sess_control* ctrl = &m_base[ctrl_index - m_maxReserveSessionCount]; - t_thrd.sig_cxt.cur_ctrl_index = ctrl_index; - volatile sig_atomic_t* plock = &ctrl->lock; + t_thrd.sig_cxt.cur_ctrl_index = ctrl_index; // 璁剧疆褰撳墠鎺у埗缁撴瀯鐨勭储寮 + volatile sig_atomic_t* plock = &ctrl->lock; // 鑾峰彇鎺у埗缁撴瀯涓殑閿 sig_atomic_t val; + do { if (*plock == 0) { - /* perform an atomic compare and swap. */ + /* 鎵ц鍘熷瓙姣旇緝鍜屼氦鎹㈡搷浣 */ val = __sync_val_compare_and_swap(plock, 0, 1); if (val == 0) { - knl_session_context* sess = ctrl->sess; - /* Session may be NULL when the session exits during the clean connection process. - We do nothing if the session is NULL */ + knl_session_context* sess = ctrl->sess; // 鑾峰彇浼氳瘽涓婁笅鏂 + /* 褰撲細璇濆湪娓呯悊杩炴帴杩囩▼涓鍑烘椂锛屼細璇濆彲鑳戒负 NULL銆傛鏃舵垜浠笉鎵ц浠讳綍鎿嶄綔銆 */ if (sess == NULL) { - /* restore the value. */ + /* 鎭㈠鍊笺 */ ctrl->lock = 0; - status = ESRCH; + status = ESRCH; // 璁剧疆鐘舵佷负 ESRCH锛堟病鏈夎繖鏍风殑杩涚▼锛 break; } - /* Check user permission, and we dont have user id for cancel request. */ + + /* 妫鏌ョ敤鎴锋潈闄愶紝瀵逛簬鍙栨秷璇锋眰锛屾垜浠病鏈夌敤鎴 ID銆 */ CheckPermissionForSendSignal(sess, (sig_atomic_t*)plock); + + // 濡傛灉浼氳瘽鐘舵佷负宸茶繛鎺ワ紙KNL_SESS_ATTACH锛 if (sess->status == KNL_SESS_ATTACH) { - t_thrd.sig_cxt.gs_sigale_check_type = SIGNAL_CHECK_SESS_KEY; - t_thrd.sig_cxt.session_id = sess->session_id; - status = gs_signal_send(sess->attachPid, signal); - t_thrd.sig_cxt.gs_sigale_check_type = SIGNAL_CHECK_NONE; - t_thrd.sig_cxt.session_id = 0; - } else if (sess->status == KNL_SESS_DETACH) { + t_thrd.sig_cxt.gs_sigale_check_type = SIGNAL_CHECK_SESS_KEY; // 璁剧疆淇″彿妫鏌ョ被鍨 + t_thrd.sig_cxt.session_id = sess->session_id; // 璁剧疆浼氳瘽 ID + status = gs_signal_send(sess->attachPid, signal); // 鍚戣繘绋嬪彂閫佷俊鍙 + t_thrd.sig_cxt.gs_sigale_check_type = SIGNAL_CHECK_NONE; // 鎭㈠淇″彿妫鏌ョ被鍨 + t_thrd.sig_cxt.session_id = 0; // 鎭㈠浼氳瘽 ID + } + // 濡傛灉浼氳瘽鐘舵佷负宸插垎绂伙紙KNL_SESS_DETACH锛 + else if (sess->status == KNL_SESS_DETACH) { switch (signal) { - case SIGTERM: - sess->status = KNL_SESS_CLOSE; - CloseClientSocket(sess, false); - status = 0; + case SIGTERM: // 濡傛灉淇″彿鏄 SIGTERM锛堢粓姝俊鍙凤級 + sess->status = KNL_SESS_CLOSE; // 璁剧疆浼氳瘽鐘舵佷负鍏抽棴 + CloseClientSocket(sess, false); // 鍏抽棴瀹㈡埛绔鎺ュ瓧 + status = 0; // 璁剧疆鐘舵佷负 0锛堟垚鍔燂級 break; default: break; } } else { - status = ESRCH; + status = ESRCH; // 璁剧疆鐘舵佷负 ESRCH锛堟病鏈夎繖鏍风殑杩涚▼锛 } - /* restore the value. */ + + /* 鎭㈠鍊笺 */ ctrl->lock = 0; break; } } - pg_usleep(100); + pg_usleep(100); // 浼戠湢 100 寰 } while (true); - t_thrd.sig_cxt.cur_ctrl_index = 0; - return status; + t_thrd.sig_cxt.cur_ctrl_index = 0; // 鎭㈠褰撳墠鎺у埗缁撴瀯鐨勭储寮曚负 0 + + return status; // 杩斿洖鐘舵 } -void ThreadPoolSessControl::SendProcSignal(int ctrl_index, ProcSignalReason reason, uint64 query_id) +// 鍚戞寚瀹氱殑浼氳瘽鍙戦佷俊鍙凤紙鍙傛暟锛氫細璇濇Ы浣嶇储寮曪紝淇″彿缂栧彿锛 +int ThreadPoolSessControl::SendSignal(int ctrl_index, int signal) { + Assert(signal != SIGHUP); // 鏂█锛氫俊鍙蜂笉鑳戒负 SIGHUP + + int status = ESRCH; // 鍒濆鐘舵佷负 ESRCH锛堟病鏈夎繖鏍风殑杩涚▼锛 + + // 妫鏌ヤ細璇濇Ы浣嶇储寮曟槸鍚︽湁鏁 if (!IsValidCtrlIndex(ctrl_index)) { - return; + return ESRCH; // 杩斿洖 ESRCH锛堟病鏈夎繖鏍风殑杩涚▼锛 } + // 鑾峰彇鎸囧畾浼氳瘽鐨勪細璇濇帶鍒剁粨鏋 knl_sess_control* ctrl = &m_base[ctrl_index - m_maxReserveSessionCount]; - - volatile sig_atomic_t* plock = &ctrl->lock; + t_thrd.sig_cxt.cur_ctrl_index = ctrl_index; // 璁剧疆褰撳墠鎺у埗缁撴瀯鐨勭储寮 + volatile sig_atomic_t* plock = &ctrl->lock; // 鑾峰彇鎺у埗缁撴瀯涓殑閿 sig_atomic_t val; + do { if (*plock == 0) { - /* perform an atomic compare and swap. */ + /* 鎵ц鍘熷瓙姣旇緝鍜屼氦鎹㈡搷浣 */ val = __sync_val_compare_and_swap(plock, 0, 1); if (val == 0) { - if (ctrl->sess != NULL) { - switch (reason) { - case PROCSIG_EXECUTOR_FLAG: { - if (IS_PGXC_DATANODE && ctrl->sess->debug_query_id == query_id) { - ctrl->sess->exec_cxt.executorStopFlag = true; - } - break; - } - default: { - Assert(0); - ctrl->lock = 0; - ereport(ERROR, - (errcode(ERRCODE_CONNECTION_EXCEPTION), errmsg("Unexpected receive proc signal."))); - } - } + knl_session_context* sess = ctrl->sess; // 鑾峰彇浼氳瘽涓婁笅鏂 + + /* 褰撲細璇濆湪娓呯悊杩炴帴杩囩▼涓鍑烘椂锛屼細璇濆彲鑳戒负 NULL銆傛鏃舵垜浠笉鎵ц浠讳綍鎿嶄綔銆 */ + if (sess == NULL) { + /* 鎭㈠閿佺殑鍊笺 */ + ctrl->lock = 0; + status = ESRCH; // 璁剧疆鐘舵佷负 ESRCH锛堟病鏈夎繖鏍风殑杩涚▼锛 + break; } - /* restore the value. */ + + /* 妫鏌ョ敤鎴锋潈闄愩傚浜庡彇娑堣姹傦紝鎴戜滑娌℃湁鐢ㄦ埛 ID銆 */ + CheckPermissionForSendSignal(sess, (sig_atomic_t*)plock); + + // 濡傛灉浼氳瘽鐘舵佷负宸茶繛鎺ワ紙KNL_SESS_ATTACH锛 + if (sess->status == KNL_SESS_ATTACH) { + t_thrd.sig_cxt.gs_sigale_check_type = SIGNAL_CHECK_SESS_KEY; // 璁剧疆淇″彿妫鏌ョ被鍨 + t_thrd.sig_cxt.session_id = sess->session_id; // 璁剧疆浼氳瘽 ID + status = gs_signal_send(sess->attachPid, signal); // 鍚戣繘绋嬪彂閫佷俊鍙 + t_thrd.sig_cxt.gs_sigale_check_type = SIGNAL_CHECK_NONE; // 鎭㈠淇″彿妫鏌ョ被鍨 + t_thrd.sig_cxt.session_id = 0; // 鎭㈠浼氳瘽 ID + } + // 濡傛灉浼氳瘽鐘舵佷负宸插垎绂伙紙KNL_SESS_DETACH锛 + else if (sess->status == KNL_SESS_DETACH) { + switch (signal) { + case SIGTERM: // 濡傛灉淇″彿鏄 SIGTERM锛堢粓姝俊鍙凤級 + sess->status = KNL_SESS_CLOSE; // 璁剧疆浼氳瘽鐘舵佷负鍏抽棴 + CloseClientSocket(sess, false); // 鍏抽棴瀹㈡埛绔鎺ュ瓧 + status = 0; // 璁剧疆鐘舵佷负 0锛堟垚鍔燂級 + break; + default: + break; + } + } else { + status = ESRCH; // 璁剧疆鐘舵佷负 ESRCH锛堟病鏈夎繖鏍风殑杩涚▼锛 + } + + /* 鎭㈠閿佺殑鍊笺 */ ctrl->lock = 0; break; } } - pg_usleep(100); + pg_usleep(100); // 浼戠湢 100 寰 } while (true); + + t_thrd.sig_cxt.cur_ctrl_index = 0; // 鎭㈠褰撳墠鎺у埗缁撴瀯鐨勭储寮曚负 0 + + return status; // 杩斿洖鐘舵 } +// 璁$畻鎸囧畾鏁版嵁搴揑D鐨勪細璇濇暟閲 int ThreadPoolSessControl::CountDBSessions(Oid dbId) { - AutoMutexLock alock(&m_sessCtrlock); - alock.lock(); + AutoMutexLock alock(&m_sessCtrlock); // 鑷姩浜掓枼閿侊紝纭繚绾跨▼瀹夊叏 + alock.lock(); // 鑾峰彇閿 - knl_sess_control* ctrl = NULL; - Dlelem* elem = DLGetHead(&m_activelist); - int count = 0; + knl_sess_control* ctrl = NULL; // 浼氳瘽鎺у埗缁撴瀯鎸囬拡 + Dlelem* elem = DLGetHead(&m_activelist); // 鑾峰彇娲诲姩浼氳瘽閾捐〃鐨勫ご鎸囬拡 + int count = 0; // 浼氳瘽鏁伴噺璁℃暟鍣 + // 閬嶅巻娲诲姩浼氳瘽閾捐〃 while (elem != NULL) { - ctrl= (knl_sess_control*)DLE_VAL(elem); + ctrl = (knl_sess_control*)DLE_VAL(elem); // 鑾峰彇浼氳瘽鎺у埗缁撴瀯鎸囬拡 + // 濡傛灉浼氳瘽鐨勬暟鎹簱ID鍖归厤鎸囧畾鐨勬暟鎹簱ID if (ctrl->sess->proc_cxt.MyDatabaseId == dbId) { - count++; + count++; // 澧炲姞浼氳瘽鏁伴噺璁℃暟鍣 + // 濡傛灉浼氳瘽鐨勫簲鐢ㄧ▼搴忓悕绉版槸 "WDRXdb" if (strcmp(ctrl->sess->attr.attr_common.application_name, "WDRXdb") == 0) { - ThreadPoolSessControl::SendSignal(ctrl->idx, SIGTERM); - ThreadPoolSessControl::SendSignal(ctrl->idx, SIGUSR2); + ThreadPoolSessControl::SendSignal(ctrl->idx, SIGTERM); // 鍙戦丼IGTERM淇″彿缁欎細璇 + ThreadPoolSessControl::SendSignal(ctrl->idx, SIGUSR2); // 鍙戦丼IGUSR2淇″彿缁欎細璇 } } - - elem = DLGetSucc(elem); + elem = DLGetSucc(elem); // 鑾峰彇涓嬩竴涓細璇濆厓绱 } - alock.unLock(); + alock.unLock(); // 閲婃斁閿 - return count; + return count; // 杩斿洖浼氳瘽鏁伴噺 } +// 楠岃瘉鎸囧畾鐨勬暟鎹簱OID鍜岀敤鎴稯ID鏄惁鏈夋晥 bool ThreadPoolSessControl::ValidDBoidAndUseroid(Oid dbOid, Oid userOid, knl_sess_control* ctrl) { /* - * Thread are 3 situation in CLEAN CONNECTION: - * 1. Only database, for example: CLEAN CONNECTION TO ALL FORCE FOR DATABASE xxx; - * 2. Only user, for example: CLEAN CONNECTION TO ALL FORCE TO USER xxx; - * 3. Both database and user, for example: CLEAN CONNECTION TO ALL FORCE FOR DATABASE xxx TO USER xxx; + * 鍦ㄦ竻鐞嗚繛鎺ヨ繃绋嬩腑锛岀嚎绋嬫湁3绉嶆儏鍐碉細 + * 1. 鍙湁鏁版嵁搴擄紝渚嬪锛欳LEAN CONNECTION TO ALL FORCE FOR DATABASE xxx; + * 2. 鍙湁鐢ㄦ埛锛屼緥濡傦細CLEAN CONNECTION TO ALL FORCE TO USER xxx; + * 3. 鏃㈡湁鏁版嵁搴撳張鏈夌敤鎴凤紝渚嬪锛欳LEAN CONNECTION TO ALL FORCE FOR DATABASE xxx TO USER xxx; */ if (((dbOid != InvalidOid) && (userOid == InvalidOid) && (ctrl->sess->proc_cxt.MyDatabaseId == dbOid)) || ((dbOid == InvalidOid) && (userOid != InvalidOid) && (ctrl->sess->proc_cxt.MyRoleId == userOid)) || ((ctrl->sess->proc_cxt.MyDatabaseId == dbOid) && (ctrl->sess->proc_cxt.MyRoleId == userOid))) { - return true; + return true; // 楠岃瘉閫氳繃 } - return false; + return false; // 楠岃瘉鏈氳繃 } +// 璁$畻鏈竻鐞嗙殑鎸囧畾鏁版嵁搴揙ID鍜岀敤鎴稯ID鐨勪細璇濇暟閲 int ThreadPoolSessControl::CountDBSessionsNotCleaned(Oid dbOid, Oid userOid) { + // 濡傛灉鏁版嵁搴揙ID鍜岀敤鎴稯ID閮芥槸鏃犳晥鐨勶紙鍙兘涓篘ULL锛 if ((dbOid == InvalidOid) && (userOid == InvalidOid)) { ereport(WARNING, (errmsg("DB oid and user oid are all Invalid (may be NULL). Shut down clean activite sessions."))); - return 0; + return 0; // 杩斿洖0锛岃〃绀烘病鏈変細璇濊娓呯悊 } - AutoMutexLock alock(&m_sessCtrlock); - alock.lock(); + AutoMutexLock alock(&m_sessCtrlock); // 鑷姩浜掓枼閿侊紝纭繚绾跨▼瀹夊叏 + alock.lock(); // 鑾峰彇閿 - int count = 0; - knl_sess_control* ctrl = NULL; - Dlelem* elem = DLGetHead(&m_activelist); + int count = 0; // 浼氳瘽鏁伴噺璁℃暟鍣 + knl_sess_control* ctrl = NULL; // 浼氳瘽鎺у埗缁撴瀯鎸囬拡 + Dlelem* elem = DLGetHead(&m_activelist); // 鑾峰彇娲诲姩浼氳瘽閾捐〃鐨勫ご鎸囬拡 + // 閬嶅巻娲诲姩浼氳瘽閾捐〃 while (elem != NULL) { - ctrl= (knl_sess_control*)DLE_VAL(elem); + ctrl = (knl_sess_control*)DLE_VAL(elem); // 鑾峰彇浼氳瘽鎺у埗缁撴瀯鎸囬拡 + // 濡傛灉鏁版嵁搴揙ID鍜岀敤鎴稯ID涓庝細璇濈殑鏁版嵁搴揑D鍜岀敤鎴稩D鍖归厤 if (ValidDBoidAndUseroid(dbOid, userOid, ctrl)) { - int status = ThreadPoolSessControl::SendSignal(ctrl->idx, 0); + int status = ThreadPoolSessControl::SendSignal(ctrl->idx, 0); // 鍚戜細璇濆彂閫佷俊鍙凤紙0琛ㄧず鏌ヨ鏄惁宸茬粡缁堟锛 + // 濡傛灉缁堟鎿嶄綔灏氭湭瀹屾垚 if (status == 0) { - /* Termination not done yet */ - count++; + count++; // 澧炲姞浼氳瘽鏁伴噺璁℃暟鍣 } } - elem = DLGetSucc(elem); + elem = DLGetSucc(elem); // 鑾峰彇涓嬩竴涓細璇濆厓绱 } - alock.unLock(); - return count; + alock.unLock(); // 閲婃斁閿 + + return count; // 杩斿洖浼氳瘽鏁伴噺 } +// 娓呯悊鎸囧畾鏁版嵁搴揙ID鍜岀敤鎴稯ID鐨勪細璇 int ThreadPoolSessControl::CleanDBSessions(Oid dbOid, Oid userOid) { + // 濡傛灉鏁版嵁搴揙ID鍜岀敤鎴稯ID閮芥槸鏃犳晥鐨勶紙鍙兘涓篘ULL锛 if ((dbOid == InvalidOid) && (userOid == InvalidOid)) { ereport(WARNING, (errmsg("DB oid and user oid are all Invalid (may be NULL). Shut down clean activite sessions."))); - return 0; + return 0; // 杩斿洖0锛岃〃绀烘病鏈変細璇濊娓呯悊 } - AutoMutexLock alock(&m_sessCtrlock); - alock.lock(); + AutoMutexLock alock(&m_sessCtrlock); // 鑷姩浜掓枼閿侊紝纭繚绾跨▼瀹夊叏 + alock.lock(); // 鑾峰彇閿 - int count = 0; - knl_sess_control* ctrl = NULL; - Dlelem* elem = DLGetHead(&m_activelist); + int count = 0; // 浼氳瘽鏁伴噺璁℃暟鍣 + knl_sess_control* ctrl = NULL; // 浼氳瘽鎺у埗缁撴瀯鎸囬拡 + Dlelem* elem = DLGetHead(&m_activelist); // 鑾峰彇娲诲姩浼氳瘽閾捐〃鐨勫ご鎸囬拡 + // 閬嶅巻娲诲姩浼氳瘽閾捐〃 while (elem != NULL) { - ctrl= (knl_sess_control*)DLE_VAL(elem); + ctrl = (knl_sess_control*)DLE_VAL(elem); // 鑾峰彇浼氳瘽鎺у埗缁撴瀯鎸囬拡 + // 濡傛灉鏁版嵁搴揙ID鍜岀敤鎴稯ID涓庝細璇濈殑鏁版嵁搴揑D鍜岀敤鎴稩D鍖归厤 if (ValidDBoidAndUseroid(dbOid, userOid, ctrl)) { - count++; - ThreadPoolSessControl::SendSignal(ctrl->idx, SIGTERM); - ThreadPoolSessControl::SendSignal(ctrl->idx, SIGUSR2); + count++; // 澧炲姞浼氳瘽鏁伴噺璁℃暟鍣 + ThreadPoolSessControl::SendSignal(ctrl->idx, SIGTERM); // 鍚戜細璇濆彂閫丼IGTERM淇″彿 + ThreadPoolSessControl::SendSignal(ctrl->idx, SIGUSR2); // 鍚戜細璇濆彂閫丼IGUSR2淇″彿 } - elem = DLGetSucc(elem); + elem = DLGetSucc(elem); // 鑾峰彇涓嬩竴涓細璇濆厓绱 } - alock.unLock(); - return count; + alock.unLock(); // 閲婃斁閿 + + return count; // 杩斿洖浼氳瘽鏁伴噺 } +// 澶勭悊SIGHUP淇″彿 void ThreadPoolSessControl::SigHupHandler() { - AutoMutexLock alock(&m_sessCtrlock); - alock.lock(); + AutoMutexLock alock(&m_sessCtrlock); // 鑷姩浜掓枼閿侊紝纭繚绾跨▼瀹夊叏 + alock.lock(); // 鑾峰彇閿 - knl_sess_control* ctrl = NULL; - Dlelem* elem = DLGetHead(&m_activelist); + knl_sess_control* ctrl = NULL; // 浼氳瘽鎺у埗缁撴瀯鎸囬拡 + Dlelem* elem = DLGetHead(&m_activelist); // 鑾峰彇娲诲姩浼氳瘽閾捐〃鐨勫ご鎸囬拡 + + // 閬嶅巻娲诲姩浼氳瘽閾捐〃 while (elem != NULL) { - ctrl= (knl_sess_control*)DLE_VAL(elem); - ctrl->sess->sig_cxt.got_SIGHUP = true; - elem = DLGetSucc(elem); + ctrl = (knl_sess_control*)DLE_VAL(elem); // 鑾峰彇浼氳瘽鎺у埗缁撴瀯鎸囬拡 + ctrl->sess->sig_cxt.got_SIGHUP = true; // 鏍囪鎺ユ敹鍒癝IGHUP淇″彿 + elem = DLGetSucc(elem); // 鑾峰彇涓嬩竴涓細璇濆厓绱 } - alock.unLock(); + alock.unLock(); // 閲婃斁閿 } +// 澶勭悊杩炴帴姹犻噸鏂板姞杞戒簨浠 void ThreadPoolSessControl::HandlePoolerReload() { + // 濡傛灉鏄疨GXC鏁版嵁鑺傜偣锛岀洿鎺ヨ繑鍥烇紝涓嶅鐞嗚繛鎺ユ睜閲嶆柊鍔犺浇浜嬩欢 if (IS_PGXC_DATANODE) { return; } - AutoMutexLock alock(&m_sessCtrlock); - alock.lock(); + AutoMutexLock alock(&m_sessCtrlock); // 鑷姩浜掓枼閿侊紝纭繚绾跨▼瀹夊叏 + alock.lock(); // 鑾峰彇閿 - knl_sess_control* ctrl = NULL; - Dlelem* elem = DLGetHead(&m_activelist); + knl_sess_control* ctrl = NULL; // 浼氳瘽鎺у埗缁撴瀯鎸囬拡 + Dlelem* elem = DLGetHead(&m_activelist); // 鑾峰彇娲诲姩浼氳瘽閾捐〃鐨勫ご鎸囬拡 + + // 閬嶅巻娲诲姩浼氳瘽閾捐〃 while (elem != NULL) { - ctrl= (knl_sess_control*)DLE_VAL(elem); - /* we have already send got_pool_reload to threads */ - ctrl->sess->sig_cxt.got_pool_reload = true; - ctrl->sess->sig_cxt.cp_PoolReload = true; - elem = DLGetSucc(elem); + ctrl = (knl_sess_control*)DLE_VAL(elem); // 鑾峰彇浼氳瘽鎺у埗缁撴瀯鎸囬拡 + /* 宸茬粡鍚戠嚎绋嬪彂閫佷簡got_pool_reload淇″彿 */ + ctrl->sess->sig_cxt.got_pool_reload = true; // 鏍囪鎺ユ敹鍒拌繛鎺ユ睜閲嶆柊鍔犺浇浜嬩欢 + ctrl->sess->sig_cxt.cp_PoolReload = true; // 鏍囪杩炴帴姹犻噸鏂板姞杞戒簨浠 + elem = DLGetSucc(elem); // 鑾峰彇涓嬩竴涓細璇濆厓绱 } - alock.unLock(); + alock.unLock(); // 閲婃斁閿 } +// 璁$畻浼氳瘽鐨勫唴瀛樹笂涓嬫枃缁熻淇℃伅 void ThreadPoolSessControl::calculateSessMemCxtStats( knl_session_context* sess, const MemoryContext context, Tuplestorestate* tupStore, TupleDesc tupDesc) { - AllocSetContext* set = (AllocSetContext*)context; + AllocSetContext* set = (AllocSetContext*)context; // 鑾峰彇鍐呭瓨涓婁笅鏂囩殑鍒嗛厤闆嗕笂涓嬫枃 - char sessId[SESSION_ID_LEN] = {0}; - ThreadId threadId = 0; - pg_time_t sessStartTime = 0; - uint64 sessionId = 0; + char sessId[SESSION_ID_LEN] = {0}; // 浼氳瘽ID + ThreadId threadId = 0; // 绾跨▼ID + pg_time_t sessStartTime = 0; // 浼氳瘽寮濮嬫椂闂 + uint64 sessionId = 0; // 浼氳瘽ID if (sess != NULL) { - sessionId = sess->session_id; - threadId = sess->attachPid; - sessStartTime = timestamptz_to_time_t(sess->proc_cxt.MyProcPort->SessionStartTime); + sessionId = sess->session_id; // 鑾峰彇浼氳瘽ID + threadId = sess->attachPid; // 鑾峰彇绾跨▼ID + sessStartTime = timestamptz_to_time_t(sess->proc_cxt.MyProcPort->SessionStartTime); // 鑾峰彇浼氳瘽寮濮嬫椂闂 } - getSessionID(sessId, sessStartTime, sessionId); + getSessionID(sessId, sessStartTime, sessionId); // 鐢熸垚浼氳瘽ID - /* build one tuple and save it in tuplestore. */ - Datum values[NUM_SESSION_MEMORY_DETAIL_ELEM] = {0}; - bool nulls[NUM_SESSION_MEMORY_DETAIL_ELEM] = {false}; + /* 鏋勫缓涓涓厓缁勫苟灏嗗叾淇濆瓨鍦ㄥ厓缁勫瓨鍌ㄥ櫒涓*/ + Datum values[NUM_SESSION_MEMORY_DETAIL_ELEM] = {0}; // 鍏冪粍鏁版嵁 + bool nulls[NUM_SESSION_MEMORY_DETAIL_ELEM] = {false}; // 鍏冪粍鐨勭┖鏍囧織浣 - values[0] = CStringGetTextDatum(sessId); - values[1] = Int64GetDatum(threadId); + values[0] = CStringGetTextDatum(sessId); // 浼氳瘽ID + values[1] = Int64GetDatum(threadId); // 绾跨▼ID - values[2] = CStringGetTextDatum(pstrdup(context->name)); - values[3] = Int16GetDatum(context->level); + values[2] = CStringGetTextDatum(pstrdup(context->name)); // 鍐呭瓨涓婁笅鏂囧悕绉 + values[3] = Int16GetDatum(context->level); // 鍐呭瓨涓婁笅鏂囧眰绾 if (context->level > 0 && context->parent != NULL) - values[4] = CStringGetTextDatum(pstrdup(context->parent->name)); + values[4] = CStringGetTextDatum(pstrdup(context->parent->name)); // 鐖剁骇鍐呭瓨涓婁笅鏂囧悕绉 else - nulls[4] = true; - values[5] = Int64GetDatum(set->totalSpace); - values[6] = Int64GetDatum(set->freeSpace); - values[7] = Int64GetDatum(set->totalSpace - set->freeSpace); + nulls[4] = true; // 濡傛灉娌℃湁鐖剁骇鍐呭瓨涓婁笅鏂囷紝灏嗙┖鏍囧織浣嶈缃负true + values[5] = Int64GetDatum(set->totalSpace); // 鎬诲叡鍒嗛厤鐨勫唴瀛樼┖闂 + values[6] = Int64GetDatum(set->freeSpace); // 鍓╀綑鐨勫唴瀛樼┖闂 + values[7] = Int64GetDatum(set->totalSpace - set->freeSpace); // 宸蹭娇鐢ㄧ殑鍐呭瓨绌洪棿 - tuplestore_putvalues(tupStore, tupDesc, values, nulls); + tuplestore_putvalues(tupStore, tupDesc, values, nulls); // 灏嗗厓缁勬暟鎹彃鍏ュ埌鍏冪粍瀛樺偍鍣ㄤ腑 } +// 閫掑綊璁$畻浼氳瘽鐨勫唴瀛樹笂涓嬫枃缁熻淇℃伅 void ThreadPoolSessControl::recursiveSessMemCxt( knl_session_context* sess, const MemoryContext context, Tuplestorestate* tupStore, TupleDesc tupDesc) { - /* calculate MemoryContext Stats */ + /* 璁$畻鍐呭瓨涓婁笅鏂囩粺璁′俊鎭 */ calculateSessMemCxtStats(sess, context, tupStore, tupDesc); - /* recursive MemoryContext's child */ + /* 閫掑綊澶勭悊鍐呭瓨涓婁笅鏂囩殑瀛愮骇 */ for (MemoryContext child = context->firstchild; child != NULL; child = child->nextchild) { recursiveSessMemCxt(sess, child, tupStore, tupDesc); } } +// 鑾峰彇浼氳瘽鐨勫唴瀛樿缁嗕俊鎭 void ThreadPoolSessControl::getSessionMemoryDetail(Tuplestorestate* tupStore, TupleDesc tupDesc, knl_sess_control** sess) { - AutoMutexLock alock(&m_sessCtrlock); - knl_sess_control* ctrl = NULL; - Dlelem* elem = NULL; + AutoMutexLock alock(&m_sessCtrlock); // 鑷姩浜掓枼閿侊紝纭繚绾跨▼瀹夊叏 + knl_sess_control* ctrl = NULL; // 浼氳瘽鎺у埗缁撴瀯鎸囬拡 + Dlelem* elem = NULL; // 鍙屽悜閾捐〃鍏冪礌鎸囬拡 PG_TRY(); { - HOLD_INTERRUPTS(); - alock.lock(); + HOLD_INTERRUPTS(); // 鏆傛椂灞忚斀涓柇 + alock.lock(); // 鑾峰彇閿 - /* collect all the Memory Context status, put in data */ - elem = DLGetHead(&m_activelist); + /* 鏀堕泦鎵鏈夊唴瀛樹笂涓嬫枃鐨勭姸鎬佷俊鎭紝灏嗗叾鏀惧叆鏁版嵁涓 */ + elem = DLGetHead(&m_activelist); // 鑾峰彇娲诲姩浼氳瘽閾捐〃鐨勫ご鎸囬拡 while (elem != NULL) { - ctrl = (knl_sess_control*)DLE_VAL(elem); - *sess = ctrl; + ctrl = (knl_sess_control*)DLE_VAL(elem); // 鑾峰彇浼氳瘽鎺у埗缁撴瀯鎸囬拡 + *sess = ctrl; // 鏇存柊浼氳瘽鎺у埗缁撴瀯鎸囬拡 if (ctrl->sess) { - (void)syscalllockAcquire(&ctrl->sess->utils_cxt.deleMemContextMutex); - recursiveSessMemCxt(ctrl->sess, ctrl->sess->top_mem_cxt, tupStore, tupDesc); - (void)syscalllockRelease(&ctrl->sess->utils_cxt.deleMemContextMutex); + (void)syscalllockAcquire(&ctrl->sess->utils_cxt.deleMemContextMutex); // 鑾峰彇鍐呭瓨涓婁笅鏂囦簰鏂ラ攣 + recursiveSessMemCxt(ctrl->sess, ctrl->sess->top_mem_cxt, tupStore, tupDesc); // 閫掑綊璁$畻鍐呭瓨涓婁笅鏂囩粺璁′俊鎭 + (void)syscalllockRelease(&ctrl->sess->utils_cxt.deleMemContextMutex); // 閲婃斁鍐呭瓨涓婁笅鏂囦簰鏂ラ攣 } - elem = DLGetSucc(elem); + elem = DLGetSucc(elem); // 鑾峰彇涓嬩竴涓細璇濆厓绱 } - alock.unLock(); + alock.unLock(); // 閲婃斁閿 - RESUME_INTERRUPTS(); + RESUME_INTERRUPTS(); // 鎭㈠涓柇 } PG_CATCH(); { if (*sess != NULL) { ctrl = *sess; - (void)syscalllockRelease(&ctrl->sess->utils_cxt.deleMemContextMutex); + (void)syscalllockRelease(&ctrl->sess->utils_cxt.deleMemContextMutex); // 閲婃斁鍐呭瓨涓婁笅鏂囦簰鏂ラ攣 } - alock.unLock(); - PG_RE_THROW(); + alock.unLock(); // 閲婃斁閿 + PG_RE_THROW(); // 閲嶆柊鎶涘嚭寮傚父 } - PG_END_TRY(); + PG_END_TRY(); // 缁撴潫寮傚父澶勭悊 + } +// 璁$畻瀹㈡埛绔俊鎭 void ThreadPoolSessControl::calculateClientInfo( knl_session_context* sess, Tuplestorestate* tupStore, TupleDesc tupDesc) { - /* build one tuple and save it in tuplestore. */ - const int COLUMN_NUM = 2; - Datum values[COLUMN_NUM] = {0}; - bool nulls[COLUMN_NUM] = {false}; - - values[0] = Int64GetDatum(sess->session_id); + /* 鏋勫缓涓涓厓缁勫苟灏嗗叾淇濆瓨鍦ㄥ厓缁勫瓨鍌ㄥ櫒涓*/ + const int COLUMN_NUM = 2; // 鍏冪粍鐨勫垪鏁 + Datum values[COLUMN_NUM] = {0}; // 鍏冪粍鏁版嵁 + bool nulls[COLUMN_NUM] = {false}; // 鍏冪粍鐨勭┖鏍囧織浣 + + values[0] = Int64GetDatum(sess->session_id); // 浼氳瘽ID if (sess->plsql_cxt.client_info != NULL) { - values[1] = CStringGetTextDatum(sess->plsql_cxt.client_info); + values[1] = CStringGetTextDatum(sess->plsql_cxt.client_info); // 瀹㈡埛绔俊鎭 } else { - nulls[1] = true; + nulls[1] = true; // 濡傛灉瀹㈡埛绔俊鎭负绌猴紝灏嗙┖鏍囧織浣嶈缃负true } - tuplestore_putvalues(tupStore, tupDesc, values, nulls); + tuplestore_putvalues(tupStore, tupDesc, values, nulls); // 灏嗗厓缁勬暟鎹彃鍏ュ埌鍏冪粍瀛樺偍鍣ㄤ腑 } +// 鑾峰彇浼氳瘽鐨勫鎴风淇℃伅 void ThreadPoolSessControl::getSessionClientInfo(Tuplestorestate* tupStore, TupleDesc tupDesc) { - AutoMutexLock alock(&m_sessCtrlock); - knl_sess_control* ctrl = NULL; - Dlelem* elem = NULL; - knl_sess_control* sess = NULL; - + AutoMutexLock alock(&m_sessCtrlock); // 鑷姩浜掓枼閿侊紝纭繚绾跨▼瀹夊叏 + knl_sess_control* ctrl = NULL; // 浼氳瘽鎺у埗缁撴瀯鎸囬拡 + Dlelem* elem = NULL; // 鍙屽悜閾捐〃鍏冪礌鎸囬拡 + knl_sess_control* sess = NULL; // 浼氳瘽鎺у埗缁撴瀯鎸囬拡 + PG_TRY(); { - HOLD_INTERRUPTS(); - alock.lock(); - - /* collect all the Memory Context status, put in data */ - elem = DLGetHead(&m_activelist); - + HOLD_INTERRUPTS(); // 鏆傛椂灞忚斀涓柇 + alock.lock(); // 鑾峰彇閿 + + /* 鏀堕泦鎵鏈夊唴瀛樹笂涓嬫枃鐨勭姸鎬佷俊鎭紝灏嗗叾鏀惧叆鏁版嵁涓 */ + elem = DLGetHead(&m_activelist); // 鑾峰彇娲诲姩浼氳瘽閾捐〃鐨勫ご鎸囬拡 + while (elem != NULL) { - ctrl = (knl_sess_control*)DLE_VAL(elem); - sess = ctrl; + ctrl = (knl_sess_control*)DLE_VAL(elem); // 鑾峰彇浼氳瘽鎺у埗缁撴瀯鎸囬拡 + sess = ctrl; // 鏇存柊浼氳瘽鎺у埗缁撴瀯鎸囬拡 if (ctrl->sess) { - (void)syscalllockAcquire(&ctrl->sess->plsql_cxt.client_info_lock); - calculateClientInfo(ctrl->sess, tupStore, tupDesc); - (void)syscalllockRelease(&ctrl->sess->plsql_cxt.client_info_lock); + (void)syscalllockAcquire(&ctrl->sess->plsql_cxt.client_info_lock); // 鑾峰彇瀹㈡埛绔俊鎭簰鏂ラ攣 + calculateClientInfo(ctrl->sess, tupStore, tupDesc); // 璁$畻瀹㈡埛绔俊鎭苟灏嗗叾淇濆瓨鍦ㄥ厓缁勫瓨鍌ㄥ櫒涓 + (void)syscalllockRelease(&ctrl->sess->plsql_cxt.client_info_lock); // 閲婃斁瀹㈡埛绔俊鎭簰鏂ラ攣 } - elem = DLGetSucc(elem); + elem = DLGetSucc(elem); // 鑾峰彇涓嬩竴涓細璇濆厓绱 } - alock.unLock(); - sess = NULL; - - RESUME_INTERRUPTS(); + alock.unLock(); // 閲婃斁閿 + sess = NULL; // 閲嶇疆浼氳瘽鎺у埗缁撴瀯鎸囬拡 + + RESUME_INTERRUPTS(); // 鎭㈠涓柇 } PG_CATCH(); { if (sess != NULL) { ctrl = sess; - (void)syscalllockRelease(&ctrl->sess->plsql_cxt.client_info_lock); + (void)syscalllockRelease(&ctrl->sess->plsql_cxt.client_info_lock); // 閲婃斁瀹㈡埛绔俊鎭簰鏂ラ攣 } - alock.unLock(); - PG_RE_THROW(); + alock.unLock(); // 閲婃斁閿 + PG_RE_THROW(); // 閲嶆柊鎶涘嚭寮傚父 } - PG_END_TRY(); + PG_END_TRY(); // 缁撴潫寮傚父澶勭悊 + } -void ThreadPoolSessControl::getSessionMemoryContextInfo(const char* ctx_name, - StringInfoData* buf, knl_sess_control** sess) +// 鑾峰彇鎸囧畾鍐呭瓨涓婁笅鏂囩殑璇︾粏淇℃伅锛屽苟灏嗙粨鏋滀繚瀛樺湪缁欏畾鐨勭紦鍐插尯涓 +void ThreadPoolSessControl::getSessionMemoryContextInfo(const char* ctx_name, StringInfoData* buf, knl_sess_control** sess) { -#ifdef MEMORY_CONTEXT_TRACK - AutoMutexLock alock(&m_sessCtrlock); - knl_sess_control* ctrl = NULL; - Dlelem* elem = NULL; +#ifdef MEMORY_CONTEXT_TRACK // 濡傛灉鍚敤鍐呭瓨涓婁笅鏂囪拷韪 + AutoMutexLock alock(&m_sessCtrlock); // 鑷姩浜掓枼閿侊紝纭繚绾跨▼瀹夊叏 + knl_sess_control* ctrl = NULL; // 浼氳瘽鎺у埗缁撴瀯鎸囬拡 + Dlelem* elem = NULL; // 鍙屽悜閾捐〃鍏冪礌鎸囬拡 PG_TRY(); { - HOLD_INTERRUPTS(); - alock.lock(); + HOLD_INTERRUPTS(); // 鏆傛椂灞忚斀涓柇 + alock.lock(); // 鑾峰彇閿 - /* collect all the Memory Context status, put in data */ - elem = DLGetHead(&m_activelist); + /* 鏀堕泦鎵鏈夊唴瀛樹笂涓嬫枃鐨勭姸鎬佷俊鎭紝灏嗗叾鏀惧叆鏁版嵁涓 */ + elem = DLGetHead(&m_activelist); // 鑾峰彇娲诲姩浼氳瘽閾捐〃鐨勫ご鎸囬拡 while (elem != NULL) { - ctrl = (knl_sess_control*)DLE_VAL(elem); - *sess = ctrl; + ctrl = (knl_sess_control*)DLE_VAL(elem); // 鑾峰彇浼氳瘽鎺у埗缁撴瀯鎸囬拡 + *sess = ctrl; // 鏇存柊浼氳瘽鎺у埗缁撴瀯鎸囬拡 if (ctrl->sess) { - (void)syscalllockAcquire(&ctrl->sess->utils_cxt.deleMemContextMutex); - gs_recursive_unshared_memory_context(ctrl->sess->top_mem_cxt, ctx_name, buf); - (void)syscalllockRelease(&ctrl->sess->utils_cxt.deleMemContextMutex); + (void)syscalllockAcquire(&ctrl->sess->utils_cxt.deleMemContextMutex); // 鑾峰彇鍐呭瓨涓婁笅鏂囦簰鏂ラ攣 + gs_recursive_unshared_memory_context(ctrl->sess->top_mem_cxt, ctx_name, buf); // 閫掑綊鑾峰彇鍐呭瓨涓婁笅鏂囦俊鎭 + (void)syscalllockRelease(&ctrl->sess->utils_cxt.deleMemContextMutex); // 閲婃斁鍐呭瓨涓婁笅鏂囦簰鏂ラ攣 } - elem = DLGetSucc(elem); + elem = DLGetSucc(elem); // 鑾峰彇涓嬩竴涓細璇濆厓绱 } - alock.unLock(); + alock.unLock(); // 閲婃斁閿 - RESUME_INTERRUPTS(); + RESUME_INTERRUPTS(); // 鎭㈠涓柇 } PG_CATCH(); { if (*sess != NULL) { ctrl = *sess; - (void)syscalllockRelease(&ctrl->sess->utils_cxt.deleMemContextMutex); + (void)syscalllockRelease(&ctrl->sess->utils_cxt.deleMemContextMutex); // 閲婃斁鍐呭瓨涓婁笅鏂囦簰鏂ラ攣 } - alock.unLock(); - PG_RE_THROW(); + alock.unLock(); // 閲婃斁閿 + PG_RE_THROW(); // 閲嶆柊鎶涘嚭寮傚父 } - PG_END_TRY(); + PG_END_TRY(); // 缁撴潫寮傚父澶勭悊 #endif } +// 鏍规嵁浼氳瘽妲戒綅绱㈠紩鑾峰彇浼氳瘽涓婁笅鏂 knl_session_context* ThreadPoolSessControl::GetSessionByIdx(int idx) { if (IsValidCtrlIndex(idx)) { - return m_base[idx - m_maxReserveSessionCount].sess; + return m_base[idx - m_maxReserveSessionCount].sess; // 杩斿洖鎸囧畾妲戒綅绱㈠紩鐨勪細璇濅笂涓嬫枃 } else { - return NULL; + return NULL; // 濡傛灉绱㈠紩鏃犳晥锛屽垯杩斿洖 NULL } } +// 鏍规嵁浼氳瘽ID鏌ユ壘浼氳瘽妲戒綅绱㈠紩 int ThreadPoolSessControl::FindCtrlIdxBySessId(uint64 id) { - int cidx = 0; + int cidx = 0; // 鎺у埗缁撴瀯绱㈠紩 for (cidx = 0; cidx < m_maxActiveSessionCount; cidx++) { if (m_base[cidx].sess != NULL && m_base[cidx].sess->session_id == id) { - return cidx + m_maxReserveSessionCount; + return cidx + m_maxReserveSessionCount; // 杩斿洖鎵惧埌鐨勪細璇濇Ы浣嶇储寮 } } - ereport(LOG, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("Invalid session id"))); + ereport(LOG, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("Invalid session id"))); // 璁板綍鏃ュ織锛岃〃绀轰細璇滻D鏃犳晥 - return -1; + return -1; // 杩斿洖-1琛ㄧず鏈壘鍒 } + +// 妫鏌ヤ細璇濊秴鏃 void ThreadPoolSessControl::CheckSessionTimeout() { - AutoMutexLock alock(&m_sessCtrlock); - alock.lock(); - int cidx; - TimestampTz now = GetCurrentTimestamp(); + AutoMutexLock alock(&m_sessCtrlock); // 鑷姩浜掓枼閿侊紝纭繚绾跨▼瀹夊叏 + alock.lock(); // 鑾峰彇閿 + int cidx; // 鎺у埗缁撴瀯绱㈠紩 + TimestampTz now = GetCurrentTimestamp(); // 鑾峰彇褰撳墠鏃堕棿鎴 + + // 閬嶅巻鎵鏈夋椿鍔ㄤ細璇濈殑鎺у埗缁撴瀯 for (cidx = 0; cidx < m_maxActiveSessionCount; cidx++) { - knl_sess_control* ctrl = &m_base[cidx]; - knl_session_context* sess = ctrl->sess; + knl_sess_control* ctrl = &m_base[cidx]; // 鑾峰彇浼氳瘽鎺у埗缁撴瀯鎸囬拡 + knl_session_context* sess = ctrl->sess; // 鑾峰彇浼氳瘽涓婁笅鏂囨寚閽 + + // 濡傛灉浼氳瘽涓嶄负NULL涓旇缃簡浼氳瘽瓒呮椂 if (sess != NULL && sess->attr.attr_common.SessionTimeout != 0) { + // 濡傛灉浼氳瘽鐨勫瓨鍌ㄤ笂涓嬫枃涓殑浼氳瘽瓒呮椂娲诲姩鏍囧織涓虹湡 if (sess->storage_cxt.session_timeout_active) { + // 濡傛灉褰撳墠鏃堕棿瓒呰繃浜嗕細璇濈殑缁撴潫鏃堕棿锛屽苟涓斾細璇濈殑瓒呮椂璁℃暟灏忎簬10 if (now >= sess->storage_cxt.session_fin_time && sess->attr.attr_common.SessionTimeoutCount < 10) { #ifdef HAVE_INT64_TIMESTAMP elog(LOG, "close session : %lu for %d times due to session timeout : %d, max finish time is %ld. But now is:%ld", @@ -713,25 +810,28 @@ void ThreadPoolSessControl::CheckSessionTimeout() sess->session_id, sess->attr.attr_common.SessionTimeoutCount + 1, sess->attr.attr_common.SessionTimeout, sess->storage_cxt.session_fin_time, now); #endif - sess->attr.attr_common.SessionTimeoutCount++; - CloseClientSocket(sess, false); + sess->attr.attr_common.SessionTimeoutCount++; // 澧炲姞浼氳瘽鐨勮秴鏃惰鏁 + CloseClientSocket(sess, false); // 鍏抽棴瀹㈡埛绔鎺ュ瓧 } } } } - alock.unLock(); + alock.unLock(); // 閲婃斁閿 } +// 鍒楀嚭鎵鏈変細璇濈殑鍏ㄥ眬涓存椂琛紙GTT锛夌殑鍐荤粨浜嬪姟ID TransactionId ThreadPoolSessControl::ListAllSessionGttFrozenxids(int maxSize, ThreadId *pids, TransactionId *xids, int *n) { - TransactionId result = InvalidTransactionId; - int i = 0; + TransactionId result = InvalidTransactionId; // 鍒濆鍖栧喕缁撲簨鍔D涓烘棤鏁堜簨鍔D + int i = 0; // 璁℃暟鍣 + // 濡傛灉鏈惎鐢ㄥ叏灞涓存椂琛紝鐩存帴杩斿洖 if (u_sess->attr.attr_storage.max_active_gtt <= 0) { return 0; } + // 濡傛灉浼犲叆鐨勫弬鏁板悎娉曪紝鍒濆鍖栫浉鍏冲彉閲 if (maxSize > 0) { Assert(pids); Assert(xids); @@ -739,51 +839,58 @@ TransactionId ThreadPoolSessControl::ListAllSessionGttFrozenxids(int maxSize, *n = 0; } + // 濡傛灉鏁版嵁搴撲腑鏈惎鐢ㄥ叏灞涓存椂琛紝杩斿洖鏃犳晥浜嬪姟ID if (u_sess->attr.attr_storage.max_active_gtt <= 0) { return InvalidTransactionId; } + // 濡傛灉澶勪簬鎭㈠鐘舵侊紝杩斿洖鏃犳晥浜嬪姟ID if (RecoveryInProgress()) { return InvalidTransactionId; } - AutoMutexLock alock(&m_sessCtrlock); - alock.lock(); - knl_sess_control *ctl = nullptr; - knl_session_context *session = nullptr; - Dlelem* elem = DLGetHead(&m_activelist); + AutoMutexLock alock(&m_sessCtrlock); // 鑷姩浜掓枼閿侊紝纭繚绾跨▼瀹夊叏 + alock.lock(); // 鑾峰彇閿 + knl_sess_control *ctl = nullptr; // 浼氳瘽鎺у埗缁撴瀯鎸囬拡 + knl_session_context *session = nullptr; // 浼氳瘽涓婁笅鏂囨寚閽 + Dlelem* elem = DLGetHead(&m_activelist); // 鑾峰彇娲诲姩浼氳瘽閾捐〃鐨勫ご鎸囬拡 while (elem != nullptr) { - ctl = (knl_sess_control*)DLE_VAL(elem); - session = ctl->sess; + ctl = (knl_sess_control*)DLE_VAL(elem); // 鑾峰彇浼氳瘽鎺у埗缁撴瀯鎸囬拡 + session = ctl->sess; // 鑾峰彇浼氳瘽涓婁笅鏂囨寚閽 + // 濡傛灉浼氳瘽鐨勬暟鎹簱ID涓庡綋鍓嶄細璇濈殑鏁版嵁搴揑D鐩稿悓锛屽苟涓斾細璇濈殑GTT鍐荤粨浜嬪姟ID鏈夋晥 if (session->proc_cxt.MyDatabaseId == u_sess->proc_cxt.MyDatabaseId && TransactionIdIsNormal(session->gtt_ctx.gtt_session_frozenxid)) { + // 濡傛灉result涓烘棤鏁堜簨鍔D锛屾垨鑰呭綋鍓嶄細璇濈殑GTT鍐荤粨浜嬪姟ID杈冨皬锛屽垯鏇存柊result if (result == InvalidTransactionId) { result = session->gtt_ctx.gtt_session_frozenxid; } else if (TransactionIdPrecedes(session->gtt_ctx.gtt_session_frozenxid, result)) { result = session->gtt_ctx.gtt_session_frozenxid; } + // 濡傛灉浼犲叆鐨勫弬鏁板厑璁镐繚瀛樹俊鎭 if (maxSize > 0) { - pids[i] = session->attachPid; - xids[i] = session->gtt_ctx.gtt_session_frozenxid; - i++; + pids[i] = session->attachPid; // 淇濆瓨浼氳瘽鐨勮繘绋婭D + xids[i] = session->gtt_ctx.gtt_session_frozenxid; // 淇濆瓨浼氳瘽鐨凣TT鍐荤粨浜嬪姟ID + i++; // 璁℃暟鍣ㄥ姞1 } } - elem = DLGetSucc(elem); + elem = DLGetSucc(elem); // 鑾峰彇涓嬩竴涓細璇 } - alock.unLock(); + alock.unLock(); // 閲婃斁閿 + // 濡傛灉浼犲叆鐨勫弬鏁板厑璁镐繚瀛樹俊鎭紝鏇存柊淇濆瓨淇℃伅鐨勬暟閲 if (maxSize > 0) { *n = i; } - return result; + return result; // 杩斿洖鏈澶х殑GTT鍐荤粨浜嬪姟ID } +// 妫鏌ユ椿鍔ㄤ細璇濋摼琛ㄦ槸鍚︿负绌 bool ThreadPoolSessControl::IsActiveListEmpty() { - AutoMutexLock alock(&m_sessCtrlock); - alock.lock(); - bool res = (m_activelist.dll_len == 0); - alock.unLock(); - return res; -} + AutoMutexLock alock(&m_sessCtrlock); // 鑷姩浜掓枼閿侊紝纭繚绾跨▼瀹夊叏 + alock.lock(); // 鑾峰彇閿 + bool res = (m_activelist.dll_len == 0); // 妫鏌ユ椿鍔ㄤ細璇濋摼琛ㄧ殑闀垮害鏄惁涓0 + alock.unLock(); // 閲婃斁閿 + return res; // 杩斿洖缁撴灉锛宼rue琛ㄧず閾捐〃涓虹┖锛宖alse琛ㄧず閾捐〃涓嶄负绌 +} \ No newline at end of file diff --git a/src/gausskernel/process/threadpool/threadpool_stream.cpp b/src/gausskernel/process/threadpool/threadpool_stream.cpp index d87c00fc2..a579a83b1 100644 --- a/src/gausskernel/process/threadpool/threadpool_stream.cpp +++ b/src/gausskernel/process/threadpool/threadpool_stream.cpp @@ -26,7 +26,6 @@ */ #include "postgres.h" - #include "distributelayer/streamMain.h" #include "distributelayer/streamProducer.h" #include "executor/executor.h" @@ -37,8 +36,10 @@ #include "utils/guc.h" #include "utils/postinit.h" +// 閲嶇疆娴佺姸鎬佺殑闈欐佸嚱鏁 static void ResetStreamStatus(); +// 绾跨▼姹犳祦鐨勬瀯閫犲嚱鏁 ThreadPoolStream::ThreadPoolStream() { m_tid = InvalidTid; @@ -51,10 +52,12 @@ ThreadPoolStream::ThreadPoolStream() m_threadStatus = THREAD_UNINIT; } +// 绾跨▼姹犳祦鐨勬瀽鏋勫嚱鏁 ThreadPoolStream::~ThreadPoolStream() { } +// 鍚姩绾跨▼姹犳祦 int ThreadPoolStream::StartUp(int idx, StreamProducer* producer, ThreadPoolGroup* group, pthread_mutex_t* mutex, pthread_cond_t* cond) { @@ -73,6 +76,7 @@ int ThreadPoolStream::StartUp(int idx, StreamProducer* producer, ThreadPoolGroup return m_tid; } +// 绛夊緟浠诲姟 void ThreadPoolStream::WaitMission() { PreventSignal(); @@ -95,6 +99,7 @@ void ThreadPoolStream::WaitMission() AllowSignal(); } +// 鍞ら啋绾跨▼姹犳祦浠ュ紑濮嬪伐浣 void ThreadPoolStream::WakeUpToWork(StreamProducer* producer) { pthread_mutex_lock(m_mutex); @@ -103,6 +108,7 @@ void ThreadPoolStream::WakeUpToWork(StreamProducer* producer) pthread_mutex_unlock(m_mutex); } +// 鍞ら啋绾跨▼姹犳祦浠ユ洿鏂扮嚎绋嬬姸鎬 void ThreadPoolStream::WakeUpToUpdate(ThreadStatus status) { pthread_mutex_lock(m_mutex); @@ -111,6 +117,7 @@ void ThreadPoolStream::WakeUpToUpdate(ThreadStatus status) pthread_mutex_unlock(m_mutex); } +// 鍒濆鍖栨祦 void ThreadPoolStream::InitStream() { knl_session_context* sc = @@ -122,7 +129,7 @@ void ThreadPoolStream::InitStream() u_sess = sc; SelfMemoryContext = u_sess->self_mem_cxt; - /* Switch context to Session context. */ + /* 鍒囨崲涓婁笅鏂囧埌浼氳瘽涓婁笅鏂 */ AutoContextSwitch memSwitch(SESS_GET_MEM_CXT_GROUP(MEMORY_CONTEXT_EXECUTOR)); SetStreamWorkerInfo(m_producer); @@ -133,17 +140,17 @@ void ThreadPoolStream::InitStream() SetProcessingMode(InitProcessing); - /* Init GUC option for this session. */ + /* 涓烘浼氳瘽鍒濆鍖朑UC閫夐」 */ InitializeGUCOptions(); - /* Read in remaining GUC variables */ + /* 璇诲彇鍓╀綑鐨凣UC鍙橀噺 */ read_nondefault_variables(); - /* Do local initialization of file, storage and buffer managers */ + /* 鎵ц鏂囦欢銆佸瓨鍌ㄥ拰缂撳啿绠$悊鍣ㄧ殑鏈湴鍒濆鍖 */ ReBuildLSC(); InitFileAccess(); smgrinit(); - /* Init Stream thread user and database */ + /* 鍒濆鍖栨祦绾跨▼鐨勭敤鎴峰拰鏁版嵁搴 */ t_thrd.proc_cxt.PostInit->SetDatabaseAndUser( u_sess->stream_cxt.producer_obj->getDbName(), InvalidOid, u_sess->stream_cxt.producer_obj->getUserName()); t_thrd.proc_cxt.PostInit->InitStreamSession(); @@ -162,6 +169,7 @@ void ThreadPoolStream::InitStream() m_producer->getKey().smpIdentifier); } +// 娓呯悊娴 void ThreadPoolStream::CleanUp() { m_producer = NULL; @@ -171,15 +179,17 @@ void ThreadPoolStream::CleanUp() m_group->ReturnStreamToPool(&m_elem); } +// 鍏抽棴娴 void ThreadPoolStream::ShutDown() { m_producer = NULL; m_group->RemoveStreamFromPool(&m_elem, m_idx); } +// 閲嶇疆娴佺姸鎬 static void ResetStreamStatus() { - /* Add the pg_delete_audit operation to audit log */ + /* 娣诲姞pg_delete_audit鎿嶄綔鍒板璁℃棩蹇 */ t_thrd.audit.Audit_delete = false; t_thrd.postgres_cxt.debug_query_string = NULL; t_thrd.postgres_cxt.g_NoAnalyzeRelNameList = NIL; @@ -193,8 +203,7 @@ static void ResetStreamStatus() } /* - * Reset extended-query-message flag, so that any errors - * encountered in "idle" state don't provoke skip. + * 閲嶇疆extended-query-message鏍囧織锛屼互闃叉鍦ㄢ滅┖闂测濈姸鎬佷笅閬囧埌鐨勪换浣曢敊璇紩鍙戣烦杩囥 */ u_sess->postgres_cxt.doing_extended_query_message = false; u_sess->debug_query_id = 0; @@ -202,23 +211,30 @@ static void ResetStreamStatus() u_sess->misc_cxt.AuthenticatedUserId = InvalidOid; u_sess->analyze_cxt.is_under_analyze = false; - /* We don't have a transaction command open anymore */ + /* 涓嶅啀瀛樺湪浜嬪姟鍛戒护 */ t_thrd.postgres_cxt.xact_started = false; /* - * Reset top transaction in case we have received parent transaction - * from main worker thread, which has already been release. + * 閲嶇疆椤剁骇浜嬪姟鐘舵侊紝浠ラ槻鎴戜滑宸茬粡鎺ユ敹鍒颁富宸ヤ綔绾跨▼涓凡閲婃斁鐨勭埗浜嬪姟銆 */ InitTopTransactionState(); InitCurrentTransactionState(); - if (!IS_PGSTATE_TRACK_UNDEFINE) { - volatile PgBackendStatus* beentry = t_thrd.shemem_ptr_cxt.MyBEEntry; - beentry->st_queryid = 0; - pgstat_report_unique_sql_id(true); - beentry->st_sessionid = 0; - beentry->st_parent_sessionid = 0; - beentry->st_thread_level = 0; - beentry->st_smpid = 0; - } + // 濡傛灉涓嶆槸鏈畾涔夌殑鐘舵佽窡韪紙PGSTATE_TRACK_UNDEFINE鏄竴涓畯锛屽彲鑳借〃绀虹姸鎬佽窡韪槸鍚﹀凡鍚敤锛 +if (!IS_PGSTATE_TRACK_UNDEFINE) { + // 鑾峰彇褰撳墠绾跨▼鐨勫悗绔姸鎬侊紙鐢╲olatile淇グ锛岃〃绀哄畠鍙兘鍦ㄤ换浣曟椂鍊欒鏇存敼锛 + volatile PgBackendStatus* beentry = t_thrd.shemem_ptr_cxt.MyBEEntry; + // 灏嗘煡璇D閲嶇疆涓0 + beentry->st_queryid = 0; + // 鎶ュ憡鍞竴SQL ID锛屽弬鏁颁负true琛ㄧず娓呴櫎鍏堝墠鐨凷QL ID + pgstat_report_unique_sql_id(true); + // 閲嶇疆浼氳瘽ID涓0 + beentry->st_sessionid = 0; + // 閲嶇疆鐖朵細璇滻D涓0 + beentry->st_parent_sessionid = 0; + // 閲嶇疆绾跨▼绾у埆涓0 + beentry->st_thread_level = 0; + // 閲嶇疆SMP锛圫ymmetric Multi-Processing锛 ID涓0 + beentry->st_smpid = 0; } +} diff --git a/src/gausskernel/process/threadpool/threadpool_worker.cpp b/src/gausskernel/process/threadpool/threadpool_worker.cpp index ac92f6a8c..262474612 100644 --- a/src/gausskernel/process/threadpool/threadpool_worker.cpp +++ b/src/gausskernel/process/threadpool/threadpool_worker.cpp @@ -75,64 +75,95 @@ static void SendSessionIdxToClient(); static void ResetSignalHandle(); static void SessionSetBackendOptions(); +// 绾跨▼姹犲伐浣滅嚎绋嬬殑鏋勯犲嚱鏁帮紝鍒濆鍖栧悇涓垚鍛樺彉閲 ThreadPoolWorker::ThreadPoolWorker(uint idx, ThreadPoolGroup* group, pthread_mutex_t* mutex, pthread_cond_t* cond) { + // 宸ヤ綔绾跨▼鐨勭储寮 m_idx = idx; + // 鎵灞炵嚎绋嬫睜缁 m_group = group; + // 绾跨▼ID鍒濆鍖栦负鏃犳晥鍊 m_tid = InvalidTid; + // 绾跨▼鐘舵佸垵濮嬪寲涓烘湭鍒濆鍖 m_threadStatus = THREAD_UNINIT; + // 褰撳墠浼氳瘽鍒濆鍖栦负NULL m_currentSession = NULL; + // 浜掓枼閿佸拰鏉′欢鍙橀噺鐢ㄤ簬绾跨▼鍚屾 m_mutex = mutex; m_cond = cond; + // 绛夊緟鐘舵佸垵濮嬪寲涓烘湭瀹氫箟 m_waitState = STATE_WAIT_UNDEFINED; + // 鍒濆鍖栧弻鍚戦摼琛ㄥ厓绱 DLInitElem(&m_elem, this); + // 璁剧疆绾跨▼鐨勭鏈夋暟鎹寚閽堜负鍏ㄥ眬绾跨▼绉佹湁鏁版嵁 m_thrd = &t_thrd; } +// 绾跨▼姹犲伐浣滅嚎绋嬬殑鏋愭瀯鍑芥暟锛屾竻鐞嗚祫婧 ThreadPoolWorker::~ThreadPoolWorker() { + // 閲婃斁璧勬簮锛屽皢鎴愬憳鍙橀噺缃负NULL m_currentSession = NULL; m_group = NULL; m_mutex = NULL; m_cond = NULL; } +// 鍏抽棴宸ヤ綔绾跨▼鐨勫嚱鏁 void ThreadPoolWorker::ShutDown() { + // 鑾峰彇浜掓枼閿 pthread_mutex_lock(m_mutex); + // 璁剧疆绾跨▼鐘舵佷负閫鍑 m_threadStatus = THREAD_EXIT; + // 娓呯悊褰撳墠浼氳瘽鐨勮祫婧 CleanUpSession(true); - /* Remove the worker if it is in the free worker list. */ + /* 濡傛灉宸ヤ綔绾跨▼鍦ㄧ┖闂茬嚎绋嬪垪琛ㄤ腑锛屽皢鍏剁Щ闄 */ m_group->GetListener()->RemoveWorkerFromList(this); + // 閲婃斁浜掓枼閿 pthread_mutex_unlock(m_mutex); + // 閲婃斁宸ヤ綔绾跨▼鍗犵敤鐨勬Ы浣 m_group->ReleaseWorkerSlot(m_idx); } +// 閫氱煡宸ヤ綔绾跨▼鍑嗗灏辩华鐨勫嚱鏁 void ThreadPoolWorker::NotifyReady() { + // 鑾峰彇浜掓枼閿 pthread_mutex_lock(m_mutex); + // 濡傛灉绾跨▼鐘舵佹槸閫鍑猴紝鍒欎繚鎸佷负閫鍑虹姸鎬侊紝鍚﹀垯璁剧疆涓鸿繍琛岀姸鎬 m_threadStatus = (m_threadStatus == THREAD_EXIT) ? THREAD_EXIT : THREAD_RUN; + // 閲婃斁浜掓枼閿 pthread_mutex_unlock(m_mutex); } +// 鍚姩宸ヤ綔绾跨▼鐨勫嚱鏁 int ThreadPoolWorker::StartUp() { Port port; + // 鍒濆鍖栫鍙g粨鏋勪綋锛屽苟璁剧疆鍙互鎺ュ彈杩炴帴 int ss_rc = memset_s(&port, sizeof(port), 0, sizeof(port)); securec_check(ss_rc, "\0", "\0"); - port.canAcceptConnections = CAC_OK; port.sock = PGINVALID_SOCKET; port.gs_sock = GS_INVALID_GSOCK; - /* Calculate cancel key which will be assigned to backend. */ + + /* 璁$畻灏嗗垎閰嶇粰鍚庣鐨勫彇娑堥敭鍊笺 */ GenerateCancelKey(false); + // 鍒嗛厤鍚庣妲戒綅 t_thrd.proc_cxt.MyPMChildSlot = AssignPostmasterChildSlot(); if (t_thrd.proc_cxt.MyPMChildSlot == -1) { return STATUS_ERROR; } + + // 鍒涘缓鍚庣杩涚▼ Backend* bn = CreateBackend(); + // 鍒濆鍖栧伐浣滅嚎绋嬪苟鑾峰彇绾跨▼ID m_tid = initialize_worker_thread(THREADPOOL_WORKER, &port, (void*)this); + // 閲嶇疆妲戒綅 t_thrd.proc_cxt.MyPMChildSlot = 0; + + // 濡傛灉绾跨▼ID鏃犳晥锛岄噴鏀炬Ы浣嶏紝杩斿洖閿欒鐘舵 if (m_tid == InvalidTid) { ReleasePostmasterChildSlot(bn->child_slot); bn->pid = 0; @@ -140,9 +171,11 @@ int ThreadPoolWorker::StartUp() return STATUS_ERROR; } + // 璁剧疆鍚庣鐨勮繘绋婭D鍜岃鑹 bn->pid = m_tid; bn->role = THREADPOOL_WORKER; Assert(bn->child_slot != 0); + // 娣诲姞鍚庣鍒板叏灞鍚庣鍒楄〃 AddBackend(bn); return STATUS_OK; @@ -159,13 +192,13 @@ void PreventSignal() void AllowSignal() { t_thrd.int_cxt.ignoreBackendSignal = false; - /* now we can accept signal. out of this, we rely on signal handle. */ + /* 鐜板湪鎴戜滑鍙互鎺ユ敹淇″彿浜嗭紝涓烘锛屾垜浠緷璧栦簬淇″彿鍙ユ焺銆 */ RESUME_INTERRUPTS(); } void ThreadPoolWorker::WaitMission() { - /* Return if we still in a transaction block. */ + /* 濡傛灉浠嶅湪浜嬪姟鍧椾腑锛屽垯杩斿洖 */ if (!WorkerThreadCanSeekAnotherMission(&m_reason)) { return; } @@ -180,22 +213,22 @@ void ThreadPoolWorker::WaitMission() errmsg("InterruptHoldoffCount should be zero when get next session."))); } /* - * prevent any signal execep siguit. - * reset any pending signal and timer. - * before we serve next session we must keep us clean. + 闃叉浠讳綍淇″彿锛岄櫎浜嗕俊鍙枫 + 澶嶄綅浠讳綍鎸傝捣鐨勪俊鍙峰拰瀹氭椂鍣ㄣ + 鍦ㄦ垜浠笅娆″彂鐞冨墠锛屾垜浠繀椤讳繚鎸佸共鍑 */ PreventSignal(); MemoryContext old = CurrentMemoryContext; while (true) { - /* we should keep the thread clean for next Session. */ + /* 鎴戜滑搴旇涓轰笅涓涓細璇濅繚鎸佺嚎绋嬪共鍑. */ CleanThread(); - /* Get next session. */ + /* 鑾峰彇涓嬩竴涓細璇. */ WaitNextSession(); Assert(m_currentSession != NULL); isRawSession = (m_currentSession->status == KNL_SESS_UNINIT); - /* do the binding process ,binding the connection and thread */ - /* return to worker pool if binding fail. */ + /* 鍋氱粦鎵庤繃绋嬶紝缁戞墡鐨勮繛鎺ュ拰绾跨▼ */ + /* 濡傛灉缁戝畾澶辫触锛岃繑鍥炲伐浣滄睜 */ if (AttachSessionToThread()) { if (isRawSession) { if (t_thrd.libpq_cxt.PqRecvPointer == t_thrd.libpq_cxt.PqRecvLength) { @@ -213,7 +246,7 @@ void ThreadPoolWorker::WaitMission() /* * CommProxy Support * - * session attach thread success, we record relation of sock with worker + * 浼氳瘽杩炴帴绾跨▼鎴愬姛锛岃褰晄ock涓巜orker鐨勫叧绯 */ if (AmIProxyModeSockfd(m_currentSession->proc_cxt.MyProcPort->sock)) { g_comm_controller->SetCommSockActive(m_currentSession->proc_cxt.MyProcPort->sock, m_idx); @@ -226,64 +259,83 @@ void ThreadPoolWorker::WaitMission() } MemoryContextSwitchTo(old); (void)disable_session_sig_alarm(); - /* now we can accept signal. out of this, we rely on signal handle. */ + /* 鐜板湪鎴戜滑鍙互鎺ユ敹淇″彿浜嗐備负姝わ紝鎴戜滑渚濊禆浜庝俊鍙峰彞鏌勩 */ AllowSignal(); ShutDownIfNecessary(); } +// 鍞ら啋宸ヤ綔绾跨▼鏉ュ鐞嗙壒瀹氫細璇濈殑鍑芥暟 bool ThreadPoolWorker::WakeUpToWork(knl_session_context* session) { bool succ = true; + // 鑾峰彇浜掓枼閿 pthread_mutex_lock(m_mutex); + // 濡傛灉绾跨▼鐘舵佷笉鏄鍑烘垨鎸傝捣 if (likely(m_threadStatus != THREAD_EXIT && m_threadStatus != THREAD_PENDING)) { + // 璁剧疆褰撳墠浼氳瘽 m_currentSession = session; + // 鍙戦佹潯浠朵俊鍙凤紝鍞ら啋绾跨▼澶勭悊浼氳瘽 pthread_cond_signal(m_cond); } else { + // 濡傛灉绾跨▼鐘舵佹槸閫鍑烘垨鎸傝捣锛岃繑鍥炲け璐 succ = false; } + // 閲婃斁浜掓枼閿 pthread_mutex_unlock(m_mutex); return succ; } +// 鍞ら啋宸ヤ綔绾跨▼鏉ユ洿鏂扮嚎绋嬬姸鎬佺殑鍑芥暟 void ThreadPoolWorker::WakeUpToUpdate(ThreadStatus status) { + // 鑾峰彇浜掓枼閿 pthread_mutex_lock(m_mutex); + // 濡傛灉绾跨▼鐘舵佷笉鏄鍑 if (m_threadStatus != THREAD_EXIT) { + // 鏇存柊绾跨▼鐘舵 m_threadStatus = status; + // 鍙戦佹潯浠朵俊鍙凤紝鍞ら啋绾跨▼鏇存柊鐘舵 pthread_cond_signal(m_cond); } + // 閲婃斁浜掓枼閿 pthread_mutex_unlock(m_mutex); } +// 鍞ら啋宸ヤ綔绾跨▼鏉ユ寕璧风嚎绋嬶紙濡傛灉绾跨▼鏄嚜鐢辩殑锛夌殑鍑芥暟 bool ThreadPoolWorker::WakeUpToPendingIfFree() { bool ans = false; + // 鑾峰彇浜掓枼閿 pthread_mutex_lock(m_mutex); + // 濡傛灉绾跨▼鐘舵佷笉鏄鍑恒佹寕璧凤紝骞朵笖褰撳墠浼氳瘽涓虹┖ if (m_threadStatus != THREAD_EXIT && m_threadStatus != THREAD_PENDING && m_currentSession == NULL) { + // 璁剧疆绾跨▼鐘舵佷负鎸傝捣 m_threadStatus = THREAD_PENDING; + // 鍙戦佹潯浠朵俊鍙凤紝鍞ら啋绾跨▼鎸傝捣 pthread_cond_signal(m_cond); - ans = true; + ans = true; // 杩斿洖鎴愬姛 } else { - ans = false; + ans = false; // 杩斿洖澶辫触 } + // 閲婃斁浜掓枼閿 pthread_mutex_unlock(m_mutex); return ans; } /* - * Some variable are session level, however they are used by some opensource - * component like postgis, we can not move them to knl_session_context directly. - * To solve this problem, providing two interface: RestoreThreadVariable and - * SaveThreadVariable. + 鏈変簺鍙橀噺鏄細璇濈骇鍒殑锛屼絾鏄畠浠涓浜涘紑婧愮▼搴忎娇鐢 + 鍍弍ostgis杩欐牱鐨勭粍浠讹紝鎴戜滑涓嶈兘鐩存帴灏嗗畠浠Щ鍔ㄥ埌knl_session_context銆 + 涓轰簡瑙e喅杩欎釜闂锛屾彁渚涗簡涓や釜鎺ュ彛:RestoreThreadVariable鍜 + SaveThreadVariable */ void ThreadPoolWorker::RestoreThreadVariable() { Assert(m_currentSession != NULL); - /* use values in session to set local thread GUC */ + /* 浣跨敤浼氳瘽涓殑鍊兼潵璁剧疆鏈湴绾跨▼GUC */ SetThreadLocalGUC(m_currentSession); - /* use values in session to set other thread local variables */ + /* 浣跨敤浼氳瘽涓殑鍊兼潵璁剧疆鍏朵粬绾跨▼灞閮ㄥ彉閲 */ pg_reset_srand48(m_currentSession->rand_cxt.rand48_seed); } @@ -291,7 +343,7 @@ void ThreadPoolWorker::RestoreLocaleInfo() { if (strcmp(NameStr(m_currentSession->mb_cxt.datcollate), NameStr(t_thrd.port_cxt.cur_datcollate)) == 0 && strcmp(NameStr(m_currentSession->mb_cxt.datctype), NameStr(t_thrd.port_cxt.cur_datctype)) == 0) { - /* no need set again. */ + /* 涓嶇敤鍐嶈缃簡. */ return; } @@ -325,14 +377,16 @@ void ThreadPoolWorker::RestoreLocaleInfo() NAMEDATALEN); securec_check(rc, "\0", "\0"); - /* Use the right encoding in translated messages */ + /* 鍦ㄧ炕璇戝悗鐨勬秷鎭腑浣跨敤姝g‘鐨勭紪鐮 */ #ifdef ENABLE_NLS pg_bind_textdomain_codeset(textdomain(NULL)); #endif } +// 鎭㈠浼氳瘽鍙橀噺鐨勫嚱鏁 void ThreadPoolWorker::RestoreSessionVariable() { + // 鎭㈠鍚勪釜浼氳瘽鍙橀噺鐨勫垵濮嬪 m_currentSession->attr.attr_sql.default_statistics_target = default_statistics_target; m_currentSession->attr.attr_common.session_timezone = session_timezone; m_currentSession->attr.attr_common.log_timezone = log_timezone; @@ -344,28 +398,33 @@ void ThreadPoolWorker::RestoreSessionVariable() m_currentSession->attr.attr_network.comm_client_bind = comm_client_bind; m_currentSession->attr.attr_network.comm_ackchk_time = comm_ackchk_time; + // 鎭㈠闅忔満鏁板彂鐢熷櫒鐨勭瀛 unsigned short* rand48 = pg_get_srand48(); m_currentSession->rand_cxt.rand48_seed[0] = rand48[0]; m_currentSession->rand_cxt.rand48_seed[1] = rand48[1]; m_currentSession->rand_cxt.rand48_seed[2] = rand48[2]; } +// 璁剧疆浼氳瘽淇℃伅鐨勫嚱鏁 void ThreadPoolWorker::SetSessionInfo() { - /* - * The proc and pgxact are more likely thread level variable, maybe we need to - * reconsider if it's better to put it in knl_thread_context. - */ + // 鑾峰彇褰撳墠绾跨▼鐨勮繘绋嬪拰PGXACT缁撴瀯 struct PGPROC* thread_proc = t_thrd.proc; + // 璁剧疆鏁版嵁搴揑D鍜岃鑹睮D thread_proc->databaseId = m_currentSession->proc_cxt.MyDatabaseId; thread_proc->roleId = m_currentSession->proc_cxt.MyRoleId; Assert(thread_proc->pid == t_thrd.proc_cxt.MyProcPid); + // 璁剧疆浼氳瘽ID鍜屽叏灞浼氳瘽ID thread_proc->sessionid = m_currentSession->session_id; thread_proc->globalSessionId = m_currentSession->globalSessionId; + // 璁剧疆宸ヤ綔绾跨▼鐨勭増鏈彿 thread_proc->workingVersionNum = m_currentSession->proc_cxt.MyProcPort->SessionVersionNum; + // 璁剧疆浼氳瘽鐨勯檮灞炶繘绋婭D m_currentSession->attachPid = thread_proc->pid; + // 濡傛灉PGXACT缁撴瀯涓嶄负绌轰笖褰撳墠浼氳瘽鏄疪edis宸ヤ綔鑰 if (t_thrd.pgxact != NULL && m_currentSession->proc_cxt.Isredisworker) { + // 鑾峰彇杩涚▼鏁扮粍閿侊紝璁剧疆杩涚▼涓篟edis宸ヤ綔鑰 LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE); t_thrd.pgxact->vacuumFlags |= PROC_IS_REDIST; LWLockRelease(ProcArrayLock); @@ -377,15 +436,15 @@ void ThreadPoolWorker::WaitNextSession() if (EnableLocalSysCache()) { g_instance.global_sysdbcache.GSCMemThresholdCheck(); } - /* Return worker to pool unless we can get a task right now. */ + /* 闄ら潪鎴戜滑鐜板湪鑳芥壘鍒板伐浣滐紝鍚﹀垯灏辨妸宸ヤ汉閫佸洖姹犲瓙閲 */ ThreadPoolListener* lsn = m_group->GetListener(); Assert(lsn != NULL); while (true) { - /* Wait if the thread was turned into pending mode. */ + /* 濡傛灉绾跨▼鍙樻垚鎸傝捣妯″紡锛屽垯绛夊緟 */ if (unlikely(m_threadStatus == THREAD_PENDING)) { Pending(); - /* pending thread must don't have session on it */ + /* 鎸傝捣鐨勭嚎绋嬪繀椤绘病鏈変細璇 */ if (m_currentSession != NULL) { u_sess = m_currentSession; ereport(FATAL, @@ -399,9 +458,9 @@ void ThreadPoolWorker::WaitNextSession() break; } - /* Wait for listener dispatch. */ + /* 绛夊緟渚﹀惉鍣ㄨ皟搴 */ if (!lsn->TryFeedWorker(this)) { - /* report thread status. */ + /* 鎶ュ憡绾跨▼鐘舵 */ u_sess = t_thrd.fake_session; WaitState oldStatus = pgstat_report_waitstatus(STATE_WAIT_COMM); @@ -426,24 +485,35 @@ void ThreadPoolWorker::WaitNextSession() } } +// 鎸傝捣绾跨▼鐨勫嚱鏁 void ThreadPoolWorker::Pending() { + // 灏嗗伐浣滅嚎绋嬫暟閲忓噺涓锛堝師瀛愭搷浣滐級 pg_atomic_fetch_sub_u32((volatile uint32*)&m_group->m_workerNum, 1); + // 鑾峰彇浜掓枼閿 pthread_mutex_lock(m_mutex); + // 濡傛灉绾跨▼鐘舵佹槸鎸傝捣 while (m_threadStatus == THREAD_PENDING) { + // 绛夊緟鏉′欢淇″彿锛屾寕璧风嚎绋 pthread_cond_wait(m_cond, m_mutex); } + // 閲婃斁浜掓枼閿 pthread_mutex_unlock(m_mutex); + // 灏嗗伐浣滅嚎绋嬫暟閲忓姞涓锛堝師瀛愭搷浣滐級 pg_atomic_fetch_add_u32((volatile uint32*)&m_group->m_workerNum, 1); + // 濡傛灉绾跨▼鐘舵佹槸閫鍑猴紝鎵ц鍏抽棴鎿嶄綔 if (m_threadStatus == THREAD_EXIT) { ShutDownIfNecessary(); - } + } } +// 濡傛灉闇瑕佺殑璇濓紝鍏抽棴绾跨▼鐨勫嚱鏁 void ThreadPoolWorker::ShutDownIfNecessary() { + // 濡傛灉绾跨▼鐘舵佹槸閫鍑 if (unlikely(m_threadStatus == THREAD_EXIT)) { + // 濡傛灉褰撳墠浼氳瘽涓虹┖锛屼娇鐢ㄨ櫄鎷熶細璇 if (!m_currentSession) { use_fake_session(); m_currentSession = t_thrd.fake_session; @@ -451,11 +521,12 @@ void ThreadPoolWorker::ShutDownIfNecessary() u_sess = m_currentSession; } + // 鎭㈠绾跨▼鍙橀噺 RestoreThreadVariable(); + // 閫鍑鸿繘绋 proc_exit(0); } - /* there is time window which the cancle signal has arrived but ignored by prevent signal called before, - * so we rebuild the signal status here in case that happens. */ + /* 鍦ㄩ槻姝俊鍙疯璋冪敤涔嬪墠锛屽彇娑堜俊鍙峰凡缁忓埌杈句絾琚拷鐣ョ殑鏃堕棿绐楀彛锛屾墍浠ュ湪杩欓噷閲嶅缓淇″彿鐘舵佷互闃插彂鐢熻繖绉嶆儏鍐点 */ if (unlikely(m_currentSession != NULL && m_currentSession->status == KNL_SESS_CLOSE)) { t_thrd.int_cxt.ClientConnectionLost = true; ereport(ERROR, (errmodule(MOD_THREAD_POOL), @@ -466,8 +537,8 @@ void ThreadPoolWorker::ShutDownIfNecessary() void ThreadPoolWorker::CleanThread() { /* - * In thread pool mode, ensure that packet transmission must be completed before thread switchover. - * Otherwise, packet format disorder may occurs. + 鍦ㄧ嚎绋嬫睜妯″紡涓嬶紝璇风‘淇濆湪鍒囨崲绾跨▼鍓嶅畬鎴愭姤鏂囦紶杈擄紝 + 鍚﹀垯鍙兘瀵艰嚧鏁版嵁鍖呮牸寮忔贩涔 */ if (m_currentSession != NULL && t_thrd.libpq_cxt.PqSendPointer > 0) { int res = pq_flush(); @@ -477,12 +548,12 @@ void ThreadPoolWorker::CleanThread() } /* - * Clean up Allocated descs incase long jump happend - * and they are not cleaned up in AtEOXact_Files. + * 濡傛灉璺宠繙鍙戠敓锛屾竻鐞嗗垎閰嶇殑浣嶇疆 + * 骞朵笖瀹冧滑涓嶄細鍦ˋtEOXact_Files涓娓呯悊 */ FreeAllAllocatedDescs(); - /* we should abandon this session. */ + /* 鎴戜滑搴旇鏀惧純杩欐浼氳 */ if (t_thrd.int_cxt.ClientConnectionLost || t_thrd.threadpool_cxt.reaper_dead_session) { t_thrd.int_cxt.ClientConnectionLost = false; t_thrd.threadpool_cxt.reaper_dead_session = false; @@ -510,17 +581,18 @@ void ThreadPoolWorker::CleanThread() } } +// 灏嗕細璇濅粠绾跨▼涓垎绂荤殑鍑芥暟 void ThreadPoolWorker::DetachSessionFromThread() { - /* session attach thread success, we record relation of sock with worker */ + /* 浼氳瘽鎴愬姛闄勫姞鍒扮嚎绋嬩笂锛屾垜浠褰曞鎺ュ瓧鍜屽伐浣滅嚎绋嬬殑鍏崇郴 */ if (AmIProxyModeSockfd(m_currentSession->proc_cxt.MyProcPort->sock)) { g_comm_controller->SetCommSockIdle(m_currentSession->proc_cxt.MyProcPort->sock); } - /* If some error occur at session initialization, we need to close it. */ + /* 濡傛灉鍦ㄤ細璇濆垵濮嬪寲鏃跺彂鐢熼敊璇紝鎴戜滑闇瑕佸叧闂細璇濄 */ if (m_currentSession->status == KNL_SESS_UNINIT) { m_currentSession->status = KNL_SESS_CLOSERAW; - /* cache may be in wrong stat, rebuild is ok */ + /* 缂撳瓨鍙兘澶勪簬閿欒鐘舵侊紝閲嶆柊鏋勫缓鏄彲浠ョ殑 */ ReBuildLSC(); CleanUpSession(false); m_currentSession = NULL; @@ -540,33 +612,44 @@ void ThreadPoolWorker::DetachSessionFromThread() m_currentSession->pcache_cxt.gpc_in_ddl = false; } RestoreSessionVariable(); + // 浠庢ц兘缁熻涓彇娑堝叧鑱斿綋鍓嶄細璇 pgstat_couple_decouple_session(false); + // 鍙栨秷鍏宠仈浼氳瘽鐨勬ц兘缁熻 pgstat_deinitialize_session(); m_currentSession->attachPid = (ThreadId)-1; - /* should restore the data before return to listener. */ + /* 鍦ㄨ繑鍥炲埌鐩戝惉鍣ㄤ箣鍓嶏紝搴旇杩樺師鏁版嵁銆 */ m_group->GetListener()->AddEpoll(m_currentSession); m_currentSession = NULL; u_sess = NULL; } +// 灏嗕細璇濋檮鍔犲埌绾跨▼涓婄殑鍑芥暟 bool ThreadPoolWorker::AttachSessionToThread() { + // 鏂█褰撳墠浼氳瘽涓嶄负绌猴紝骞朵笖褰撳墠绾跨▼娌℃湁浜嬪姟璧勬簮鎵鏈夎 Assert(m_currentSession != NULL); Assert(t_thrd.utils_cxt.TopTransactionResourceOwner == NULL); + // 璁剧疆浼氳瘽淇℃伅骞舵仮澶嶇嚎绋嬪彉閲 SetSessionInfo(); RestoreThreadVariable(); + + // 濡傛灉浼氳瘽鐘舵佷负 KNL_SESS_DETACH锛屽垯杩樺師鏈湴鍖栦俊鎭 if (m_currentSession->status == KNL_SESS_DETACH) { RestoreLocaleInfo(); } + // 灏嗗綋鍓嶄細璇濊缃负娲诲姩浼氳瘽 u_sess = m_currentSession; + // 璁剧疆杈撳嚭鍙戦佺洰鏍囦负杩滅▼ t_thrd.postgres_cxt.whereToSendOutput = DestRemote; + // 灏嗗綋鍓嶅唴瀛樹笂涓嬫枃璁剧疆涓轰細璇濊嚜韬唴瀛樹笂涓嬫枃 SelfMemoryContext = u_sess->self_mem_cxt; + /* - * Since thread pool worker may start earlier than startup finishing recovery, - * init xlog access if necessary. + * 鐢变簬绾跨▼姹犲伐浣滅嚎绋嬪彲鑳芥棭浜庢仮澶嶅畬鎴愪箣鍓嶅惎鍔紝 + * 濡傛灉闇瑕侊紝鍒濆鍖 xlog 璁块棶銆 */ PG_TRY(); { @@ -574,31 +657,33 @@ bool ThreadPoolWorker::AttachSessionToThread() } PG_CATCH(); { - /* if init xlog has error, should throw fatal this thread */ + /* 濡傛灉鍒濆鍖 xlog 鍑洪敊锛屽簲璇ヤ负璇ョ嚎绋嬫姏鍑鸿嚧鍛介敊璇 */ ereport(FATAL, (errmsg("init xlog failed, throw fatal for this thread"))); } PG_END_TRY(); -#ifdef ENABLE_QUNIT - set_qunit_case_number_hook(u_sess->utils_cxt.qunit_case_number, NULL); -#endif + // 鏍规嵁浼氳瘽鐘舵佹墽琛岀浉搴旂殑鎿嶄綔 switch (m_currentSession->status) { case KNL_SESS_UNINIT: { + // 濡傛灉浼氳瘽鍒濆鍖栨垚鍔 if (InitSession(m_currentSession)) { - /* Registering backend_version */ + /* 娉ㄥ唽鍚庣鐗堟湰淇℃伅 */ if (t_thrd.proc && contain_backend_version(t_thrd.proc->workingVersionNum)) { register_backend_version(t_thrd.proc->workingVersionNum); } + // 灏嗕細璇濈姸鎬佽缃负闄勫姞 m_currentSession->status = KNL_SESS_ATTACH; + // 鏂█褰撳墠鏁版嵁搴撳尮閰 Assert(CheckMyDatabaseMatch()); } else { + // 濡傛灉浼氳瘽鍒濆鍖栧け璐 m_currentSession->status = KNL_SESS_CLOSE; - /* clean up mess. */ + /* 娓呯悊娣蜂贡鐘舵併 */ CleanUpSession(false); m_currentSession = NULL; u_sess = NULL; } - /* init port will change the signal handle */ + /* 鍒濆鍖栫鍙d細鏀瑰彉淇″彿澶勭悊 */ ResetSignalHandle(); } break; @@ -608,6 +693,7 @@ bool ThreadPoolWorker::AttachSessionToThread() int rcs = 0; Port *port = m_currentSession->proc_cxt.MyProcPort; + // 璁剧疆绾跨▼鍚嶇О涓哄綋鍓嶄細璇濈敤鎴峰悕锛屼互鍖哄垎涓嶅悓绫诲瀷鐨勭嚎绋 if (t_thrd.role == WORKER) { rcs = snprintf_truncated_s(thr_name, sizeof(thr_name), "w:%s", port->user_name); securec_check_ss(rcs, "\0", "\0"); @@ -618,24 +704,27 @@ bool ThreadPoolWorker::AttachSessionToThread() (void)pthread_setname_np(gs_thread_self(), thr_name); } #endif + // 鍒濆鍖栨ц兘缁熻淇℃伅 pgstat_initialize_session(); + // 鍏宠仈褰撳墠浼氳瘽鐨勬ц兘缁熻淇℃伅 pgstat_couple_decouple_session(true); - /* Postgres init thread syscache. */ + /* Postgres 鍒濆鍖栫嚎绋嬬殑绯荤粺缂撳瓨銆 */ t_thrd.proc_cxt.PostInit->InitLoadLocalSysCache(u_sess->proc_cxt.MyDatabaseId, u_sess->proc_cxt.MyProcPort->database_name); Assert(CheckMyDatabaseMatch()); + // 灏嗕細璇濈姸鎬佽缃负闄勫姞 m_currentSession->status = KNL_SESS_ATTACH; } break; case KNL_SESS_CLOSERAW: case KNL_SESS_CLOSE: { - /* unified auditing logout */ + /* 缁熶竴瀹¤鐧诲嚭 */ audit_processlogout_unified(); - /* clean up tmp schema */ + /* 娓呯悊涓存椂妯″紡 */ RemoveTempNamespace(); - /* clean up mess. */ + /* 娓呯悊娣蜂贡鐘舵併 */ CleanUpSession(false); m_currentSession = NULL; u_sess = NULL; @@ -648,11 +737,13 @@ bool ThreadPoolWorker::AttachSessionToThread() default: Assert(false); + // 鏈畾涔夌殑浼氳瘽鐘舵侊紝搴旇鎶涘嚭 PANIC 閿欒 ereport(PANIC, (errcode(ERRCODE_INVALID_ATTRIBUTE), errmsg("undefined state %d for session attach", m_currentSession->status))); } + // 濡傛灉褰撳墠浼氳瘽鐘舵佷负闄勫姞锛屽垯杩斿洖 true锛屽惁鍒欎娇鐢ㄨ櫄鍋囦細璇濆苟杩斿洖 false if (m_currentSession && m_currentSession->status == KNL_SESS_ATTACH) { return true; } else { @@ -662,12 +753,14 @@ bool ThreadPoolWorker::AttachSessionToThread() } } +// 閲婃斁浼氳瘽閿佸畾璧勬簮 void ThreadPoolWorker::CleanUpSessionWithLock() { if (m_currentSession == NULL) { return; } + // 濡傛灉鏄 Redis 宸ヤ綔绾跨▼锛岄噴鏀惧搴旂殑閿佸畾璧勬簮 if (t_thrd.pgxact != NULL && m_currentSession->proc_cxt.Isredisworker) { LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE); t_thrd.pgxact->vacuumFlags &= ~PROC_IS_REDIST; @@ -675,17 +768,20 @@ void ThreadPoolWorker::CleanUpSessionWithLock() } } +// 娓呯悊浼氳瘽璧勬簮 void ThreadPoolWorker::CleanUpSession(bool threadexit) { if (m_currentSession == NULL) { return; } + // 濡傛灉褰撳墠浼氳瘽澶勪簬铏氬亣鐘舵侊紝涓旂嚎绋嬬姸鎬佷负 THREAD_EXIT锛屽垯鐩存帴杩斿洖 if (m_currentSession->status == KNL_SESS_FAKE) { Assert(m_threadStatus == THREAD_EXIT); return; } + // 濡傛灉褰撳墠浼氳瘽鐘舵佷笉鏄 KNL_SESS_END_PHASE1锛屽垯鎵ц蹇呰鐨勬竻鐞嗗伐浣 if (m_currentSession->status != KNL_SESS_END_PHASE1) { InitThreadLocalWhenSessionExit(); @@ -694,9 +790,10 @@ void ThreadPoolWorker::CleanUpSession(bool threadexit) DecreaseUserCount(m_currentSession->proc_cxt.MyRoleId); } - /* Close Session. */ + /* 鍏抽棴浼氳瘽 */ m_group->GetListener()->DelSessionFromEpoll(m_currentSession); + // 濡傛灉浼氳瘽瓒呰繃杩炴帴闄愬埗锛屽垯鍑忓皯杩炴帴鏁 if (m_currentSession->proc_cxt.PassConnLimit) { SpinLockAcquire(&g_instance.conn_cxt.ConnCountLock); g_instance.conn_cxt.CurConnCount--; @@ -705,34 +802,31 @@ void ThreadPoolWorker::CleanUpSession(bool threadexit) } /* - * Record this state in case we reenter this function because - * ERROR/FATAL occurs in sess_exit(). + * 鍦 ERROR/FATAL 鍦 sess_exit() 鍑芥暟涓啀娆¤繘鍏ユ鍑芥暟涔嬪墠锛岃褰曟鐘舵併 */ m_currentSession->status = KNL_SESS_END_PHASE1; } /* - * If clean up work already be done at proc_exit(), then we don't need to - * call sess_exit() anymore, otherwise, there will be double free. + * 濡傛灉宸茬粡鍦 proc_exit() 鍑芥暟涓畬鎴愪簡娓呯悊宸ヤ綔锛屽垯涓嶉渶瑕佸啀娆¤皟鐢 sess_exit() 鍑芥暟锛屽惁鍒欎細瀵艰嚧閲嶅閲婃斁璧勬簮銆 */ if (!t_thrd.proc_cxt.proc_exit_inprogress) { sess_exit(0); } - /* clear pgstat slot */ + /* 娓呯悊 pgstat 鎻掓Ы */ pgstat_release_session_memory_entry(); pgstat_deinitialize_session(); pgstat_beshutdown_session(m_currentSession->session_ctr_index); localeconv_deinitialize_session(); - /* clean gpc refcount and plancache in shared memory */ + /* 娓呯悊 GPC 寮曠敤璁℃暟鍜屽叡浜唴瀛樹腑鐨勮鍒掔紦瀛 */ if (ENABLE_DN_GPC) CleanSessGPCPtr(m_currentSession); /* - * clear invalid msg slot - * If called during pool worker thread exit, session's invalid msg slot has already - * been cleared along with that of pool worker in shmem_exit. + * 娓呯悊鏃犳晥娑堟伅妲 + * 濡傛灉鍦ㄦ睜宸ヤ綔绾跨▼閫鍑烘湡闂磋皟鐢紝鍒欎細璇濈殑鏃犳晥娑堟伅妲藉凡缁忛殢鐫姹犲伐浣滅嚎绋嬬殑娑堟伅妲戒竴璧峰湪 shmem_exit 涓娓呯悊銆 */ if (!t_thrd.proc_cxt.proc_exit_inprogress) { CleanupWorkSessionInvalidation(); @@ -745,6 +839,7 @@ void ThreadPoolWorker::CleanUpSession(bool threadexit) m_currentSession = NULL; } +// 鍒涘缓鍚庣杩涚▼ Backend* ThreadPoolWorker::CreateBackend() { Backend* bn = AssignFreeBackEnd(t_thrd.proc_cxt.MyPMChildSlot); @@ -754,6 +849,7 @@ Backend* ThreadPoolWorker::CreateBackend() return bn; } +// 灏嗗悗绔繘绋嬫坊鍔犲埌鍏ㄥ眬鍚庣鍒楄〃涓 void ThreadPoolWorker::AddBackend(Backend* bn) { bn->is_autovacuum = false; @@ -761,6 +857,7 @@ void ThreadPoolWorker::AddBackend(Backend* bn) DLAddHead(g_instance.backend_list, &bn->elem); } +// 鍒濆鍖栦細璇濆叡浜唴瀛 static void init_session_share_memory() { TableSpaceUsageManager::Init(); @@ -769,21 +866,22 @@ static void init_session_share_memory() #endif } +// 濡傛灉闇瑕侊紝鍒濆鍖 BSQL 鎻掍欢閽╁瓙 #ifndef ENABLE_MULTIPLE_NODES extern void InitBSqlPluginHookIfNeeded(); #endif +// 鍒濆鍖栦細璇濓紙鍙傛暟锛氫細璇濅笂涓嬫枃锛 static bool InitSession(knl_session_context* session) { - /* non't send ereport to client now */ + /* 闈炲疄鏃跺悜瀹㈡埛绔彂閫侀敊璇俊鎭 */ t_thrd.postgres_cxt.whereToSendOutput = DestNone; - /* Switch context to Session context. */ + /* 鍒囨崲涓婁笅鏂囧埌浼氳瘽涓婁笅鏂 */ AutoContextSwitch memSwitch(session->mcxt_group->GetMemCxtGroup(MEMORY_CONTEXT_DEFAULT)); /* - * Set thread version to the latest working version number for - * InitializeGUCOptions. - * This is ugly and can not avoid all race conditions during online upgrade. + * 涓 InitializeGUCOptions 璁剧疆褰撳墠绾跨▼鐗堟湰鍙枫 + * 杩欐槸涓戦檵鐨勶紝鏃犳硶閬垮厤鍦ㄧ嚎鍗囩骇鏈熼棿鎵鏈夌珵鎬佹潯浠躲 */ t_thrd.proc->workingVersionNum = pg_atomic_read_u32(&WorkingGrandVersionNum); @@ -793,55 +891,55 @@ static bool InitSession(knl_session_context* session) (void)pg_atomic_add_fetch_u32(&g_instance.comm_cxt.current_gsrewind_count, 1); } - /* Init GUC option for this session. */ + /* 鍒濆鍖栦細璇濈殑 GUC 閫夐」 */ InitializeGUCOptions(); - /* Read in remaining GUC variables */ + /* 璇诲彇鍓╀綑鐨 GUC 鍙橀噺 */ read_nondefault_variables(); - /* now safe to ereport to client */ + /* 鐜板湪瀹夊叏鍦板悜瀹㈡埛绔彂閫侀敊璇姤鍛 */ t_thrd.postgres_cxt.whereToSendOutput = DestRemote; - /* Init port and connection. */ + /* 鍒濆鍖栫鍙e拰杩炴帴 */ if (!InitPort(session->proc_cxt.MyProcPort)) { - /* reset some status below */ + /* 閲嶇疆浠ヤ笅鐘舵 */ if (!disable_sig_alarm(false)) { ereport(FATAL, (errmsg("could not disable timer for startup packet timeout"))); } return false; } - /* switch version number to that gotten from port */ + /* 灏嗙増鏈彿鍒囨崲鍒颁粠绔彛鑾峰緱鐨勭増鏈彿 */ t_thrd.proc->workingVersionNum = session->proc_cxt.MyProcPort->SessionVersionNum; - /* add process definer mode */ + /* 娣诲姞杩涚▼瀹氫箟妯″紡 */ Reset_Pseudo_CurrentUserId(); SetProcessingMode(InitProcessing); SessionSetBackendOptions(); - /* initialize guc variables which need to be sended to stream threads */ + /* 鍒濆鍖栭渶瑕佸彂閫佺粰娴佺嚎绋嬬殑 GUC 鍙橀噺 */ #ifdef PGXC if (IS_PGXC_DATANODE && IsUnderPostmaster) { init_sync_guc_variables(); } #endif - /* We need to allow SIGINT, etc during the initial transaction */ + /* 鎴戜滑闇瑕佸湪鍒濆浜嬪姟鏈熼棿鍏佽 SIGINT 绛変俊鍙 */ gs_signal_setmask(&t_thrd.libpq_cxt.UnBlockSig, NULL); - /* init invalid msg slot */ + /* 鍒濆鍖栨棤鏁堟秷鎭Ы */ SharedInvalBackendInit(false, true); - /* init pgstat slot */ + /* 鍒濆鍖 pgstat 鎻掓Ы */ pgstat_initialize_session(); - /* Do local initialization of file, storage and buffer managers */ + /* 鎵ц鏂囦欢銆佸瓨鍌ㄥ拰缂撳啿绠$悊鍣ㄧ殑鏈湴鍒濆鍖 */ InitFileAccess(); smgrinit(); - /* openGauss init. */ + /* openGauss 鍒濆鍖 */ char* dbname = session->proc_cxt.MyProcPort->database_name; char* username = session->proc_cxt.MyProcPort->user_name; t_thrd.proc_cxt.PostInit->SetDatabaseAndUser(dbname, InvalidOid, username); @@ -863,12 +961,12 @@ static bool InitSession(knl_session_context* session) SendSessionIdxToClient(); - /* init param hash table for sending set message */ + /* 鍒濆鍖栫敤浜庡彂閫佽缃秷鎭殑鍙傛暟鍝堝笇琛 */ if (IS_PGXC_COORDINATOR) { init_set_params_htab(); } - /* check if memory already reach the max_dynamic_memory */ + /* 妫鏌ュ唴瀛樻槸鍚﹀凡缁忚揪鍒版渶澶у姩鎬佸唴瀛 */ if (t_thrd.utils_cxt.gs_mp_inited && processMemInChunks > maxChunksPerProcess) { ereport(ERROR, (errcode(ERRCODE_OUT_OF_LOGICAL_MEMORY), @@ -883,9 +981,10 @@ static bool InitSession(knl_session_context* session) return true; } +// 鍒濆鍖栫鍙o紙鍙傛暟锛氱鍙f寚閽堬級 static bool InitPort(Port* port) { - /* session version number is initialized to process version number */ + /* 浼氳瘽鐗堟湰鍙峰垵濮嬪寲涓鸿繘绋嬬増鏈彿 */ port->SessionVersionNum = pg_atomic_read_u32(&WorkingGrandVersionNum); PortInitialize(port, NULL); @@ -903,6 +1002,7 @@ static bool InitPort(Port* port) return true; } +// 鍚戝鎴风鍙戦佷細璇濈储寮 static void SendSessionIdxToClient() { GenerateCancelKey(true); @@ -917,17 +1017,19 @@ static void SendSessionIdxToClient() } } +// 閲嶇疆淇″彿澶勭悊鍑芥暟 static void ResetSignalHandle() { - // may change during thread init port(accept new connection) + // 鍙兘鍦ㄥ垵濮嬪寲绔彛鏃讹紙鎺ュ彈鏂拌繛鎺ワ級鍙戠敓鍙樺寲 (void)gspqsignal(SIGALRM, handle_sig_alarm); - (void)gspqsignal(SIGQUIT, quickdie); /* hard crash time */ - (void)gspqsignal(SIGTERM, die); /* cancel current query and exit */ + (void)gspqsignal(SIGQUIT, quickdie); /* 寮哄埗宕╂簝鏃 */ + (void)gspqsignal(SIGTERM, die); /* 鍙栨秷褰撳墠鏌ヨ骞堕鍑 */ gs_signal_setmask(&t_thrd.libpq_cxt.UnBlockSig, NULL); - /* not necessary, unblock for sure */ + /* 涓嶆槸蹇呴渶鐨勶紝纭繚淇″彿瑙i櫎闃诲 */ gs_signal_unblock_sigusr2(); } +// 璁剧疆浼氳瘽鍚庣閫夐」 static void SessionSetBackendOptions() { char** av = NULL; @@ -935,11 +1037,10 @@ static void SessionSetBackendOptions() int ac = 0; /* - * Now, build the argv vector that will be given to PostgresMain. + * 鐜板湪锛屾瀯寤哄皢浼犻掔粰 PostgresMain 鐨 argv 鍚戦噺銆 * - * The maximum possible number of commandline arguments that could come - * from ExtraOptions is (strlen(ExtraOptions) + 1) / 2; see - * pg_split_opts(). + * 鏉ヨ嚜 ExtraOptions 鐨勫彲鑳界殑鍛戒护琛屽弬鏁扮殑鏈澶ф暟閲忔槸 (strlen(ExtraOptions) + 1) / 2锛 + * 璇峰弬闃 pg_split_opts()銆 */ maxac = (strlen(g_instance.ExtraOptions) + 1) / 2 + 2; @@ -949,6 +1050,6 @@ static void SessionSetBackendOptions() pg_split_opts(av, &ac, g_instance.ExtraOptions); av[ac] = NULL; - /* Parse command-line options. */ + /* 瑙f瀽鍛戒护琛岄夐」 */ process_postgres_switches(ac, av, PGC_POSTMASTER, NULL); -} +} \ No newline at end of file diff --git a/src/gausskernel/storage/.vscode/settings.json b/src/gausskernel/storage/.vscode/settings.json new file mode 100644 index 000000000..ce8d15f93 --- /dev/null +++ b/src/gausskernel/storage/.vscode/settings.json @@ -0,0 +1,5 @@ +{ + "files.associations": { + "condition_variable": "cpp" + } +} \ No newline at end of file diff --git a/src/gausskernel/storage/access/archive/archive_am.cpp b/src/gausskernel/storage/access/archive/archive_am.cpp index 9d6280ef0..0ec329e13 100644 --- a/src/gausskernel/storage/access/archive/archive_am.cpp +++ b/src/gausskernel/storage/access/archive/archive_am.cpp @@ -11,6 +11,7 @@ * * ------------------------------------------------------------------------- */ +// 鍖呭惈鐨勫繀瑕佺殑澶存枃浠 #include #include #include @@ -23,83 +24,88 @@ #include "replication/slot.h" - -size_t ArchiveRead(const char* fileName, const int offset, char *buffer, const int length, - ArchiveConfig *archive_config) +// 瀹氫箟鐨勫嚱鏁帮紝鐢ㄤ簬浠庡綊妗e偍瀛樹腑璇诲彇鏁版嵁 +size_t ArchiveRead(const char *fileName, const int offset, char *buffer, const int length, + ArchiveConfig *archive_config) // archive_config鏄敤浜庡瓨鍌ㄥ綊妗e瓨鍌ㄩ厤缃俊鎭殑鏁版嵁缁撴瀯銆 { - if (archive_config == NULL) { + if (archive_config == NULL) { // 濡傛灉鏈寚瀹歛rchive_config锛屽垯鏃犳硶璇诲彇鏁版嵁 return 0; } - if (archive_config->media_type == ARCHIVE_OBS) { - return obsRead(fileName, offset, buffer, length, archive_config); - } else if (archive_config->media_type == ARCHIVE_NAS) { - return NasRead(fileName, offset, buffer, length, archive_config); + // 鏍规嵁褰掓。瀛樺偍浠嬭川绫诲瀷鎵ц鐩稿簲鐨勮鍙栧嚱鏁 + if (archive_config->media_type == ARCHIVE_OBS) { // 鍒ゆ柇褰掓。瀛樺偍浠嬭川鐨勭被鍨嬧斺斿璞″偍瀛 + return obsRead(fileName, offset, buffer, length, archive_config); // OBS鍌ㄥ瓨浠嬭川鐨勮鍙栧嚱鏁 + } else if (archive_config->media_type == ARCHIVE_NAS) { // 鐢ㄤ簬鍖哄垎褰掓。瀛樺偍鎿嶄綔鏄湪缃戠粶闄勫姞瀛樺偍涓婅繘琛岀殑 + return NasRead(fileName, offset, buffer, length, archive_config); // NSA鍌ㄥ瓨浠嬭川鐨勮鍙栧嚱鏁 } - return 0; + return 0; // 濡傛灉浠嬭川绫诲瀷鏈煡锛岃繑鍥0 } - -int ArchiveWrite(const char* fileName, const char *buffer, const int bufferLength, ArchiveConfig *archive_config) +// 瀹氫箟浜嗕竴涓嚱鏁扮敤浜庡悜褰掓。瀛樺偍涓啓鍏ユ暟鎹 +int ArchiveWrite(const char *fileName, const char *buffer, const int bufferLength, ArchiveConfig *archive_config) { int ret = -1; if (archive_config == NULL) { - return ret; + return ret; // 濡傛灉褰掓。閰嶇疆涓虹┖锛岀洿鎺ヨ繑鍥 -1 琛ㄧず鍐欏叆澶辫触 } - + // 鏍规嵁褰掓。瀛樺偍浠嬭川绫诲瀷鎵ц鐩稿簲鐨勫啓鍏ュ嚱鏁 if (archive_config->media_type == ARCHIVE_OBS) { - ret = obsWrite(fileName, buffer, bufferLength, archive_config); + ret = obsWrite(fileName, buffer, bufferLength, archive_config); // OBS鍌ㄥ瓨浠嬭川鐨勫啓鍏ュ嚱鏁 } else if (archive_config->media_type == ARCHIVE_NAS) { - ret = NasWrite(fileName, buffer, bufferLength, archive_config); + ret = NasWrite(fileName, buffer, bufferLength, archive_config); // NSA鍌ㄥ瓨浠嬭川鐨勫啓鍏ュ嚱鏁 } - return ret; + return ret; // 鏍规嵁杩斿洖缁撴灉鍙互鍒ゆ柇鏄惁鍐欏叆鎴愬姛锛屾垚鍔燂紙闈炶礋鏁帮級锛屽け璐ワ紙-1锛 } - -int ArchiveDelete(const char* fileName, ArchiveConfig *archive_config) +// 瀹氫箟浜嗕竴涓嚱鏁扮敤浜庡垹闄ゅ綊妗e瓨鍌ㄤ腑鐨勬暟鎹 +int ArchiveDelete(const char *fileName, ArchiveConfig *archive_config) { int ret = -1; if (archive_config == NULL) { - return ret; + return ret; // 濡傛灉褰掓。閰嶇疆涓虹┖锛岀洿鎺ヨ繑鍥 -1 琛ㄧず鍒犻櫎澶辫触 } - + // 鏍规嵁褰掓。瀛樺偍浠嬭川绫诲瀷鎵ц鐩稿簲鐨勫垹闄ゅ嚱鏁 if (archive_config->media_type == ARCHIVE_OBS) { - ret = obsDelete(fileName, archive_config); + ret = obsDelete(fileName, archive_config); // 璋冪敤OBS瀛樺偍鐨勫垹闄ゅ嚱鏁 } else if (archive_config->media_type == ARCHIVE_NAS) { - ret = NasDelete(fileName, archive_config); + ret = NasDelete(fileName, archive_config); // 璋冪敤NAS瀛樺偍鐨勫垹闄ゅ嚱鏁 } - return ret; + return ret; // 鏍规嵁杩斿洖缁撴灉鍙互鍒ゆ柇鏄惁鍒犻櫎鎴愬姛锛屾垚鍔燂紙闈炶礋鏁帮級锛屽け璐ワ紙-1锛 } - -List* ArchiveList(const char* prefix, ArchiveConfig *archive_config, bool reportError, bool shortenConnTime) +// 瀹氫箟浜嗕竴涓嚱鏁帮紝鐢ㄤ簬鍒楀嚭褰掓。瀛樺偍涓殑鏂囦欢鍒楄〃 +List *ArchiveList(const char *prefix, ArchiveConfig *archive_config, bool reportError, bool shortenConnTime) { - List* fileNameList = NIL; + List *fileNameList = NIL; if (archive_config == NULL) { return fileNameList; } - + // 鏍规嵁褰掓。瀛樺偍浠嬭川绫诲瀷鎵ц鐩稿簲鐨勫垪鍑烘枃浠跺垪琛ㄥ嚱鏁 if (archive_config->media_type == ARCHIVE_OBS) { fileNameList = obsList(prefix, archive_config, reportError, shortenConnTime); + // 璋冪敤OBS鍌ㄥ瓨鐨勬枃浠跺垪琛紝浼犲叆reporError锛堟寚瀹氭槸鍚﹀湪鍒楀嚭鏂囦欢鍒楄〃杩囩▼涓姤鍛婇敊璇級浠ュ強shortenConnTime锛堟寚瀹氭槸鍚︾缉鐭繛鎺ユ椂闂达級 + // 浠庤屾彁渚涙洿澶氱殑鎺у埗鍜岀伒娲绘э紝浠庤岀伒娲荤殑鑾峰緱鏂囦欢鍒楄〃 } else if (archive_config->media_type == ARCHIVE_NAS) { - fileNameList = NasList(prefix, archive_config); + fileNameList = NasList(prefix, archive_config); // 璋冪敤NAS瀛樺偍鐨勫垪鍑烘枃浠跺垪琛ㄥ嚱鏁 } - return fileNameList; + return fileNameList; // 杩斿洖鏂囦欢鍚嶅垪琛 } - -bool ArchiveFileExist(const char* file_path, ArchiveConfig *archive_config) +// 瀹氫箟浜嗕竴涓嚱鏁扮敤浜庢鏌ュ綊妗e瓨鍌ㄤ腑鐨勬枃浠舵槸鍚﹀瓨鍦 +bool ArchiveFileExist(const char *file_path, ArchiveConfig *archive_config) { bool ret = false; if (archive_config == NULL) { - ereport(WARNING, (errmsg("when check file exist, the archive config is null"))); + ereport( + WARNING, + (errmsg("when check file exist, the archive config is null"))); // 濡傛灉褰掓。閰嶇疆涓虹┖锛屼細鍙戝嚭璀﹀憡骞惰繑鍥瀎alse return ret; } - + // 鏍规嵁褰掓。瀛樺偍浠嬭川绫诲瀷鎵ц鐩稿簲鐨勬鏌ユ枃浠跺瓨鍦ㄥ嚱鏁 if (archive_config->media_type == ARCHIVE_OBS) { - ret = checkOBSFileExist(file_path, archive_config); + ret = checkOBSFileExist(file_path, archive_config); // 璋冪敤OBS瀛樺偍鐨勬鏌ユ枃浠跺瓨鍦ㄥ嚱鏁 } else if (archive_config->media_type == ARCHIVE_NAS) { - ret = checkNASFileExist(file_path, archive_config); + ret = checkNASFileExist(file_path, archive_config); // 璋冪敤NAS瀛樺偍鐨勬鏌ユ枃浠跺瓨鍦ㄥ嚱鏁 } - return ret; -} + return ret; // 杩斿洖妫鏌ョ粨鏋滐紝鍙兘鏄瓨鍦紙true锛夋垨涓嶅瓨鍦紙false锛 +} \ No newline at end of file diff --git a/src/gausskernel/storage/access/archive/nas_am.cpp b/src/gausskernel/storage/access/archive/nas_am.cpp index 9c823f265..092cd7aad 100644 --- a/src/gausskernel/storage/access/archive/nas_am.cpp +++ b/src/gausskernel/storage/access/archive/nas_am.cpp @@ -46,11 +46,22 @@ #include "postmaster/alarmchecker.h" #include "replication/walreceiver.h" +//瀹氫箟鏂囦欢璺緞鐨勬渶澶ч暱搴︼紝浣夸唬鐮佹洿鍔犳竻鏅板拰鏄撲簬缁存姢 #define MAX_PATH_LEN 1024 +//瀹氫箟浜嗕竴涓ご閮ㄩ暱搴 static int headerLen = 22; +// 瀹氫箟涓涓嚱鏁帮紝鐢ㄤ簬浠嶯AS瀛樺偍涓鍙栨枃浠舵暟鎹 size_t NasRead(const char* fileName, const int offset, char *buffer, const int length, ArchiveConfig *nas_config) { + /* + fileName锛氳璇诲彇鐨勬枃浠跺悕銆 + offset锛氳鍙栫殑璧峰鍋忕Щ閲忋 + buffer锛氱敤浜庡瓨鍌ㄨ鍙栫殑鏁版嵁鐨勭紦鍐插尯銆 + length锛氳璇诲彇鐨勬暟鎹暱搴︺ + nas_config锛氬綊妗i厤缃俊鎭殑鎸囬拡锛屾寚鍚 ArchiveConfig 缁撴瀯锛屽寘鍚簡鏈夊叧瀛樺偍浣嶇疆鍜岃缃殑淇℃伅銆 + */ + //鍒濆鍖 size_t readLength = 0; ArchiveConfig *archive_nas = NULL; char file_path[MAXPGPATH] = {0}; @@ -58,40 +69,45 @@ size_t NasRead(const char* fileName, const int offset, char *buffer, const int l FILE *fp = NULL; struct stat statbuf; - if ((fileName == NULL) || (buffer == NULL)) { + if ((fileName == NULL) || (buffer == NULL)) {//濡傛灉鏂囦欢鍚嶅拰缂撳啿鍖轰负绌轰細鎶ラ敊 ereport(ERROR, (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED), errmsg("The parameter cannot be NULL"))); } - + //鑾峰彇NAS瀛樺偍鐨勯厤缃俊鎭 if (nas_config != NULL) { archive_nas = nas_config; } else { archive_nas = getArchiveConfig(); } - if (archive_nas == NULL) { + if (archive_nas == NULL) {//鏃犳硶鑾峰彇褰掓。閰嶇疆淇℃伅鏃舵姤閿 ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("Cannot get archive config from replication slots"))); } - if (strncmp(fileName, "global_barrier_records", headerLen) != 0) { + if (strncmp(fileName, "global_barrier_records", headerLen) != 0) {//鏋勫缓鏂囦欢鐨勫畬鏁磋矾寰 + //璋冪敤snprintf_s鍑芥暟鏋勫缓涓涓畬鏁寸殑鏂囦欢璺緞锛屽苟灏嗙粨鏋滃瓨鍌ㄥ湪 file_path 鍙橀噺涓 ret = snprintf_s(file_path, MAXPGPATH, MAXPGPATH - 1, "%s/%s", archive_nas->archive_prefix, fileName); - securec_check_ss(ret, "\0", "\0"); + // ret鐢ㄤ簬鍌ㄥ瓨snprintf_s 鍑芥暟鐨勮繑鍥炲笺傝繖涓繑鍥炲艰〃绀哄凡鏍煎紡鍖栧瓧绗︿覆鐨勯暱搴︺ + securec_check_ss(ret, "\0", "\0");//濡傛灉鍙戠敓閿欒灏嗕細鍦 ret 涓繑鍥 '\0' 锛屼粠鑰屽府鍔╁畾浣嶉敊璇殑浣嶇疆銆 + //鐢ㄤ簬妫鏌 snprintf_s鍑芥暟鐨勮繑鍥炲煎苟杩涜瀹夊叏鎬ф鏌ワ紝浠ョ‘淇濇病鏈夊彂鐢熺紦鍐插尯婧㈠嚭鎴栨牸寮忓寲閿欒 } else { - char pathPrefix[MAXPGPATH] = {0}; + char pathPrefix[MAXPGPATH] = {0};//鐢熸垚涓涓┖鐨刢har鏁扮粍浣滀负pathPrefix锛堢敤浜庡偍瀛樺綊妗i厤缃殑瀛樻。鍓嶇紑锛 ret = strcpy_s(pathPrefix, MAXPGPATH, archive_nas->archive_prefix); + //澶嶅埗 archive_nas->archive_prefix 鍒 pathPrefix securec_check_ss(ret, "\0", "\0"); if (!IS_PGXC_COORDINATOR) { - char *p = strrchr(pathPrefix, '/'); + char *p = strrchr(pathPrefix, '/');//鍦╬athPrefix涓壘鍒版渶鍚庝竴涓枩鏉犵殑浣嶇疆 if (p == NULL) { ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("Obs path prefix is invalid"))); } - *p = '\0'; + *p = '\0';//灏嗘渶鍚庝竴涓枩鏉犳浛鎹负'\0' } ret = snprintf_s(file_path, MAXPGPATH, MAXPGPATH - 1, "%s/%s", pathPrefix, fileName); securec_check_ss(ret, "\0", "\0"); + // 鏋勫缓瀹屾暣璺緞骞舵鏌 snprintf_s 鍑芥暟鐨勮繑鍥炲 } - + //妫鏌ユ枃浠舵槸鍚﹀瓨鍦 if (stat(file_path, &statbuf)) { if (errno != ENOENT) { ereport(ERROR, (errcode_for_file_access(), errmsg("could not stat file \"%s\": %m", fileName))); @@ -99,9 +115,10 @@ size_t NasRead(const char* fileName, const int offset, char *buffer, const int l ereport(ERROR, (errcode_for_file_access(), errmsg("The file \"%s\" not exists", fileName))); return readLength; } - + //鎵撳紑鏂囦欢骞惰鍙栨暟鎹 canonicalize_path(file_path); fp = fopen(file_path, "rb"); + //瀵逛簬鎵撳紑鏂囦欢浜х敓鐨勯敊璇繘琛屽鐞 if (fp == NULL) { ereport(ERROR, (errcode_for_file_access(), errmsg("could not read file \"%s\": %m", fileName))); return readLength; @@ -111,90 +128,99 @@ size_t NasRead(const char* fileName, const int offset, char *buffer, const int l ereport(ERROR, (errcode_for_file_access(), errmsg("file size is wrong, \"%s\": %m", fileName))); return readLength; } - + + //璇诲彇鏁版嵁鍒扮紦鍐插尯涓 readLength = fread(buffer, 1, statbuf.st_size, fp); fclose(fp); return readLength; } - +//璇ュ嚱鏁扮敤浜庡皢鏁版嵁鍐欏叆鏂囦欢锛屽苟鍦ㄥ繀瑕佹椂杩涜澶囦唤鍜岄噸鍛藉悕 int NasWrite(const char* fileName, const char *buffer, const int bufferLength, ArchiveConfig *nas_config) { int ret = 0; - ArchiveConfig *archive_nas = NULL; - char file_path[MAXPGPATH] = {0}; - char file_path_bak[MAXPGPATH] = {0}; - char *origin_file_path = NULL; - char *base_path = NULL; - FILE *fp = NULL; - + ArchiveConfig *archive_nas = NULL;//瀛樺偍NAS閰嶇疆鐨勬寚閽 + char file_path[MAXPGPATH] = {0};//瀛樺偍鏋勫缓鐨勬枃浠惰矾 + char file_path_bak[MAXPGPATH] = {0};//瀛樺偍澶囦唤鏂囦欢璺緞 + char *origin_file_path = NULL;//瀛樺偍瑙勮寖鍖栫殑鏂囦欢璺緞鐨勫壇鏈 + char *base_path = NULL;//瀛樺偍鏂囦欢鐨勫熀纭璺緞 + FILE *fp = NULL;//鏂囦欢鎸囬拡锛岀敤浜庢搷浣滄枃浠 + + //妫鏌ヤ紶鍏ョ殑鍙傛暟鏄惁涓虹┖锛屾枃浠跺悕鍜岀紦鍐插櫒涓虹┖鏃舵姤閿 if ((fileName == NULL) || (buffer == NULL)) { ereport(ERROR, (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED), errmsg("The parameter cannot be NULL"))); } - + //鑾峰彇褰掓。閰嶇疆淇℃伅锛屽鏋滀紶鍏ョ殑褰掓。閰嶇疆鍙傛暟涓篘ULL锛屽垯灏濊瘯浠庨粯璁や綅缃幏鍙 if (nas_config != NULL) { archive_nas = nas_config; } else { archive_nas = getArchiveConfig(); } - + //妫鏌ヨ幏鍙栧埌鐨勫綊妗i厤缃俊鎭槸鍚︽湁鏁堬紝鏃犳晥鏃舵姤閿 if (archive_nas == NULL) { ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("Cannot get archive config from replication slots"))); } - - if (strncmp(fileName, "global_barrier_records", headerLen) != 0) { + //鏍规嵁鏂囦欢鍚嶆瀯寤哄畬鏁寸殑鏂囦欢璺緞 + if (strncmp(fileName, "global_barrier_records", headerLen) != 0) {//鍒ゆ柇鏂囦欢鍚嶆槸鍚︿负"global_barrier_records" ret = snprintf_s(file_path, MAXPGPATH, MAXPGPATH - 1, "%s/%s", archive_nas->archive_prefix, fileName); securec_check_ss(ret, "\0", "\0"); + //鏋勫缓瀹屾暣璺緞骞舵鏌nprintf_s鍑芥暟鐨勮繑鍥炲 } else { - char pathPrefix[MAXPGPATH] = {0}; - ret = strcpy_s(pathPrefix, MAXPGPATH, archive_nas->archive_prefix); + char pathPrefix[MAXPGPATH] = {0};//鐢ㄤ簬瀛樺偍璺緞鍓嶇紑 + ret = strcpy_s(pathPrefix, MAXPGPATH, archive_nas->archive_prefix);//澶嶅埗 archive_nas->archive_prefix 鍒 pathPrefix securec_check_ss(ret, "\0", "\0"); - if (!IS_PGXC_COORDINATOR) { - char *p = strrchr(pathPrefix, '/'); - if (p == NULL) { + if (!IS_PGXC_COORDINATOR) {// 濡傛灉涓嶆槸鍗忚皟鍣ㄨ妭鐐 + char *p = strrchr(pathPrefix, '/');//鍦╬athPrefix涓煡鎵炬渶鍚庝竴涓'/' + if (p == NULL) {//娌℃湁鎵惧埌'/'鍒欎細鎶ラ敊 ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("Obs path prefix is invalid"))); } - *p = '\0'; + *p = '\0';//灏嗘渶鍚庝竴涓枩鏉犳浛鎹负'\0' } ret = snprintf_s(file_path, MAXPGPATH, MAXPGPATH - 1, "%s/%s", pathPrefix, fileName); securec_check_ss(ret, "\0", "\0"); + // 鏋勫缓瀹屾暣璺緞骞舵鏌 snprintf_s 鍑芥暟鐨勮繑鍥炲 } - canonicalize_path(file_path); + canonicalize_path(file_path);//瑙勮寖鍖栨枃浠惰矾寰勶紝鍘婚櫎澶氫綑鐨勫瓧绗︼紝濡'.'銆'..'绛 - origin_file_path = pstrdup(file_path); - base_path = dirname(origin_file_path); + origin_file_path = pstrdup(file_path);//澶嶅埗鏂囦欢璺緞鍒皁rigin_file_path + base_path = dirname(origin_file_path);//鑾峰彇origin_file_path锛堟枃浠剁殑瀹屾暣璺緞锛夌殑鐖剁骇璺緞锛屽嵆鍩虹璺緞 + //妫鏌ュ熀纭璺緞鏄惁瀛樺湪锛屽鏋滀笉瀛樺湪鍒欏垱寤 if (!isDirExist(base_path)) { - if (pg_mkdir_p(base_path, S_IRWXU) != 0) { - pfree_ext(origin_file_path); + // 璋冪敤 pg_mkdir_p 鍑芥暟灏濊瘯鍒涘缓鐩綍锛孲_IRWXU 鏄寚瀹氭潈闄愬弬鏁 + if (pg_mkdir_p(base_path, S_IRWXU) != 0) {//濡傛灉杩斿洖鍊间笉涓0锛屽垯璇存槑鍒涘缓鐩綍澶辫触 + // 濡傛灉鍒涘缓鐩綍澶辫触锛岄噴鏀惧唴瀛樺苟鎶ュ憡閿欒 + pfree_ext(origin_file_path);//閲婃斁鍏跺崰鐢ㄧ殑鍐呭瓨绌洪棿 ereport(LOG, (errmsg("could not create path \"%s\"", base_path))); - return -1; + return -1;//杩斿洖 -1 琛ㄧず鍒涘缓鐩綍澶辫触 } } - + //鏋勫缓澶囦唤鏂囦欢鐨勮矾寰勶紝灏 ".bak" 娣诲姞鍒 file_path ret = snprintf_s(file_path_bak, MAXPGPATH, MAXPGPATH - 1, "%s.bak", file_path); securec_check_ss(ret, "\0", "\0"); - fp = fopen(file_path_bak, "wb"); - if (fp == NULL) { + fp = fopen(file_path_bak, "wb");//鎵撳紑澶囦唤鏂囦欢锛屼互浜岃繘鍒跺啓鍏ユā寮 + if (fp == NULL) {//濡傛灉鎵撳紑澶囦唤鏂囦欢澶辫触锛岄噴鏀惧唴瀛樺苟鎶ュ憡閿欒 pfree_ext(origin_file_path); ereport(LOG, (errmsg("could not create file \"%s\": %m", fileName))); return -1; } - + //灏嗘暟鎹啓鍏ュ浠芥枃浠 if (fwrite(buffer, bufferLength, 1, fp) != 1) { ereport(LOG, (errmsg("could not write file \"%s\": %m", fileName))); pfree_ext(origin_file_path); fclose(fp); return -1; } + //鍒锋柊鏂囦欢缂撳啿鍖猴紝纭繚鏁版嵁鍐欏叆纾佺洏 if (fflush(fp) != 0) { ereport(LOG, (errmsg("could not fflush file \"%s\": %m", fileName))); (void)fclose(fp); pfree_ext(origin_file_path); return -1; } + //灏嗗浠芥枃浠堕噸鍛藉悕涓烘寮忔枃浠 if (rename(file_path_bak, file_path) < 0) { ereport(LOG, (errmsg("could not rename file \"%s\": %m", fileName))); (void)fclose(fp); @@ -202,8 +228,8 @@ int NasWrite(const char* fileName, const char *buffer, const int bufferLength, A return -1; } - pfree_ext(origin_file_path); - fclose(fp); + pfree_ext(origin_file_path);//閲婃斁琚崰鐢ㄧ殑鍐呭瓨绌洪棿 + fclose(fp);//鍏抽棴鏂囦欢 return 0; } @@ -420,4 +446,4 @@ bool checkNASFileExist(const char* file_path, ArchiveConfig *nas_config) } return true; -} \ No newline at end of file +} diff --git a/src/gausskernel/storage/buffer/buf_init.cpp b/src/gausskernel/storage/buffer/buf_init.cpp index 6956b35d7..ef78c756e 100644 --- a/src/gausskernel/storage/buffer/buf_init.cpp +++ b/src/gausskernel/storage/buffer/buf_init.cpp @@ -13,6 +13,7 @@ * * ------------------------------------------------------------------------- */ + //包含所必要的头文件 #include "storage/dfs/dfscache_mgr.h" #include "postgres.h" @@ -26,7 +27,7 @@ #include "postmaster/pagewriter.h" #include "postmaster/bgwriter.h" #include "utils/palloc.h" - +// 用于控制缓冲区的队列插槽的数量的倍增因子 const int PAGE_QUEUE_SLOT_MULTI_NBUFFERS = 5; /* @@ -59,37 +60,39 @@ const int PAGE_QUEUE_SLOT_MULTI_NBUFFERS = 5; * Pins must be released before end of transaction. For efficiency the * shared refcount isn't increased if a individual backend pins a buffer * multiple times. Check the PrivateRefCount infrastructure in bufmgr.c. - */ -/* + * * Initialize shared buffer pool * * This is called once during shared-memory initialization (either in the * postmaster, or in a standalone backend). */ + // 初始化共享缓冲池 void InitBufferPool(void) { + // 用于指示是否找到共享内存结构的变量 bool found_bufs = false; bool found_descs = false; bool found_buf_ckpt = false; uint64 buffer_size; - + //在共享内容中初始化缓冲区描述符 t_thrd.storage_cxt.BufferDescriptors = (BufferDescPadded *)CACHELINEALIGN( ShmemInitStruct("Buffer Descriptors", TOTAL_BUFFER_NUM * sizeof(BufferDescPadded) + PG_CACHE_LINE_SIZE, &found_descs)); /* Init candidate buffer list and candidate buffer free map */ + // 初始化候选缓冲区列表和候选缓冲区空闲映射 candidate_buf_init(); -#ifdef __aarch64__ +#ifdef __aarch64__// 在共享内存中分配缓冲块的内存 buffer_size = TOTAL_BUFFER_NUM * (Size)BLCKSZ + PG_CACHE_LINE_SIZE; t_thrd.storage_cxt.BufferBlocks = (char *)CACHELINEALIGN(ShmemInitStruct("Buffer Blocks", buffer_size, &found_bufs)); -#else +#else//在非aarch64时执行以下代码,用于为缓冲区分配共享内存。 buffer_size = TOTAL_BUFFER_NUM * (Size)BLCKSZ; t_thrd.storage_cxt.BufferBlocks = (char *)ShmemInitStruct("Buffer Blocks", buffer_size, &found_bufs); #endif - + // 检查是否需要对共享缓冲区进行黑名单处理 if (BBOX_BLACKLIST_SHARE_BUFFER) { /* Segment Buffer is exclued from the black list, as it contains many critical information for debug */ bbox_blacklist_add(SHARED_BUFFER, t_thrd.storage_cxt.BufferBlocks, NORMAL_SHARED_BUFFER_NUM * (Size)BLCKSZ); @@ -102,24 +105,30 @@ void InitBufferPool(void) * the checkpointer is restarted, memory allocation failures would be * painful. */ + // 在共享内存中初始化用于排序检查点缓冲区 ID 的数组 g_instance.ckpt_cxt_ctl->CkptBufferIds = (CkptSortItem *)ShmemInitStruct("Checkpoint BufferIds", TOTAL_BUFFER_NUM * sizeof(CkptSortItem), &found_buf_ckpt); - + + //如果启用了增量检查点,并且脏页队列尚未分配,就分配并初始化该队列。 if (ENABLE_INCRE_CKPT && g_instance.ckpt_cxt_ctl->dirty_page_queue == NULL) { + // 计算脏页队列所需的大小 g_instance.ckpt_cxt_ctl->dirty_page_queue_size = TOTAL_BUFFER_NUM * PAGE_QUEUE_SLOT_MULTI_NBUFFERS; + // 切换内存上下文以分配队列 MemoryContext oldcontext = MemoryContextSwitchTo(g_instance.increCheckPoint_context); - + // 计算脏页队列的总内存大小 Size queue_mem_size = g_instance.ckpt_cxt_ctl->dirty_page_queue_size * sizeof(DirtyPageQueueSlot); + // 使用 'palloc_huge' 为脏页队列分配内存 g_instance.ckpt_cxt_ctl->dirty_page_queue = (DirtyPageQueueSlot *)palloc_huge(CurrentMemoryContext, queue_mem_size); /* The memory of the memset sometimes exceeds 2 GB. so, memset_s cannot be used. */ MemSet((char*)g_instance.ckpt_cxt_ctl->dirty_page_queue, 0, queue_mem_size); + // 切换回原始的内存上下文 (void)MemoryContextSwitchTo(oldcontext); } - + // 初始化后台写入程序的哈希表 if (g_instance.bgwriter_cxt.unlink_rel_hashtbl == NULL) { g_instance.bgwriter_cxt.unlink_rel_hashtbl = relfilenode_hashtbl_create("unlink_rel_hashtbl", true); } diff --git a/src/gausskernel/storage/buffer/buf_table.cpp b/src/gausskernel/storage/buffer/buf_table.cpp index 2d69f0fd0..d26e77944 100644 --- a/src/gausskernel/storage/buffer/buf_table.cpp +++ b/src/gausskernel/storage/buffer/buf_table.cpp @@ -20,6 +20,13 @@ * * ------------------------------------------------------------------------- */ +/* + *这段代码实现了将BufferTags映射到缓冲区索引的相关功能。 + *它定义了一些用于在哈希表中查找、插入和删除缓冲区映射的函数。 + *这些函数用于管理缓冲区标签与实际缓冲区索引之间的映射关系, + *从而允许系统根据缓冲区标签快速定位相应的缓冲区。 + * + */ #include "postgres.h" #include "knl/knl_variable.h" diff --git a/src/gausskernel/storage/buffer/freelist.cpp b/src/gausskernel/storage/buffer/freelist.cpp index af45abcab..3084f646b 100644 --- a/src/gausskernel/storage/buffer/freelist.cpp +++ b/src/gausskernel/storage/buffer/freelist.cpp @@ -71,15 +71,15 @@ const int MAX_RETRY_TIMES = 1000; const float NEED_DELAY_RETRY_GET_BUF = 0.8; /* Prototypes for internal functions */ -static BufferDesc* GetBufferFromRing(BufferAccessStrategy strategy, uint32* buf_state); -static void AddBufferToRing(BufferAccessStrategy strategy, volatile BufferDesc* buf); -void PageListBackWrite(uint32* bufList, int32 n, - /* buffer list, bufs to scan, */ - uint32 flags = 0, /* opt flags */ - SMgrRelation use_smgrReln = NULL, /* opt relation */ - int32* bufs_written = NULL, /* opt written count returned */ - int32* bufs_reusable = NULL); /* opt reusable count returned */ -static BufferDesc* get_buf_from_candidate_list(BufferAccessStrategy strategy, uint32* buf_state); +static BufferDesc *GetBufferFromRing(BufferAccessStrategy strategy, uint32 *buf_state); +static void AddBufferToRing(BufferAccessStrategy strategy, volatile BufferDesc *buf); +void PageListBackWrite(uint32 *bufList, int32 n, + /* buffer list, bufs to scan, */ + uint32 flags = 0, /* opt flags */ + SMgrRelation use_smgrReln = NULL, /* opt relation */ + int32 *bufs_written = NULL, /* opt written count returned */ + int32 *bufs_reusable = NULL); /* opt reusable count returned */ +static BufferDesc *get_buf_from_candidate_list(BufferAccessStrategy strategy, uint32 *buf_state); static void perform_delay(StrategyDelayStatus *status) { @@ -99,7 +99,6 @@ static void perform_delay(StrategyDelayStatus *status) return; } - /* * ClockSweepTick - Helper routine for StrategyGetBuffer() * @@ -177,7 +176,7 @@ static inline uint32 ClockSweepTick(int max_nbuffer_can_use) * If the fraction is too small, we will increase dynamiclly to avoid elog(ERROR) * in `Startup' process because of ERROR will promote to FATAL. */ -BufferDesc* StrategyGetBuffer(BufferAccessStrategy strategy, uint32* buf_state) +BufferDesc *StrategyGetBuffer(BufferAccessStrategy strategy, uint32 *buf_state) { BufferDesc *buf = NULL; int bgwproc_no; @@ -185,8 +184,8 @@ BufferDesc* StrategyGetBuffer(BufferAccessStrategy strategy, uint32* buf_state) uint32 local_buf_state = 0; /* to avoid repeated (de-)referencing */ int max_buffer_can_use; bool am_standby = RecoveryInProgress(); - StrategyDelayStatus retry_lock_status = { 0, 0 }; - StrategyDelayStatus retry_buf_status = { 0, 0 }; + StrategyDelayStatus retry_lock_status = {0, 0}; + StrategyDelayStatus retry_buf_status = {0, 0}; /* * If given a strategy object, see whether it can select a buffer. We @@ -352,7 +351,7 @@ int StrategySyncStart(uint32 *complete_passes, uint32 *num_buf_alloc) * Additionally add the number of wraparounds that happened before * completePasses could be incremented. C.f. ClockSweepTick(). */ - *complete_passes += next_victim_buffer / (unsigned int) NORMAL_SHARED_BUFFER_NUM; + *complete_passes += next_victim_buffer / (unsigned int)NORMAL_SHARED_BUFFER_NUM; } if (num_buf_alloc != NULL) { @@ -487,7 +486,7 @@ BufferAccessStrategy GetAccessStrategy(BufferAccessStrategyType btype) break; case BAS_VACUUM: ring_size = g_instance.attr.attr_storage.NBuffers / 32 / - Max(g_instance.attr.attr_storage.autovacuum_max_workers, 1); + Max(g_instance.attr.attr_storage.autovacuum_max_workers, 1); break; case BAS_REPAIR: ring_size = Min(g_instance.attr.attr_storage.NBuffers, MIN_REPAIR_FILE_SLOT_NUM); @@ -609,7 +608,7 @@ RETRY: if (retry_times < Min(MAX_RETRY_RING_TIMES, strategy->ring_size * MAX_RETRY_RING_PCT)) { goto RETRY; } else if (get_curr_candidate_nums(false) >= (uint32)g_instance.attr.attr_storage.NBuffers * - u_sess->attr.attr_storage.candidate_buf_percent_target){ + u_sess->attr.attr_storage.candidate_buf_percent_target) { strategy->current_was_in_ring = false; return NULL; } @@ -617,8 +616,7 @@ RETRY: local_buf_state = LockBufHdr(buf); if (BUF_STATE_GET_REFCOUNT(local_buf_state) == 0 && BUF_STATE_GET_USAGECOUNT(local_buf_state) <= 1 && - (backend_can_flush_dirty_page() || !(local_buf_state & BM_DIRTY)) && - !(local_buf_state & BM_IS_META)) { + (backend_can_flush_dirty_page() || !(local_buf_state & BM_DIRTY)) && !(local_buf_state & BM_IS_META)) { strategy->current_was_in_ring = true; *buf_state = local_buf_state; return buf; @@ -673,26 +671,59 @@ bool StrategyRejectBuffer(BufferAccessStrategy strategy, BufferDesc *buf) return true; } - +/* + * 鍔熻兘锛氭牴鎹紦鍐插尯璁块棶绛栫暐鑾峰彇鐜舰棰勫彇鐨勬暟閲忓拰瑙﹀彂鍣ㄥ + * + * 鍙傛暟鍒楄〃锛 + * strategy锛氱紦鍐插尯璁块棶绛栫暐 + * quantity锛氱敤浜庡瓨鍌ㄩ鍙栨暟閲忕殑鎸囬拡 + * trigger锛氱敤浜庡瓨鍌ㄩ鍙栬Е鍙戝櫒鍊肩殑鎸囬拡 + * + * 杩斿洖鍊硷細 + * 鏃 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庣‘瀹氱幆褰㈤鍙栫殑鏁伴噺鍜岃Е鍙戝櫒鍊硷紝浠ヤ紭鍖栫鐩業/O鎬ц兘銆 + * 濡傛灉浼犲叆鐨勭瓥鐣ヤ负绌烘垨鑰呬笉鏄疊AS_BULKREAD绫诲瀷锛屽垯涓嶈繘琛岄鍙栬缃 + * 棰勫彇鏁伴噺鍜岃Е鍙戝櫒鍊煎皢鍩轰簬鐜舰缂撳啿鍖虹殑澶у皬鍜岄厤缃弬鏁版潵璁$畻銆 + */ void StrategyGetRingPrefetchQuantityAndTrigger(BufferAccessStrategy strategy, int *quantity, int *trigger) { int threshold; - int prefetch_trigger = u_sess->attr.attr_storage.prefetch_quantity; + int prefetch_trigger = u_sess->attr.attr_storage.prefetch_quantity; // 鑾峰彇棰勫彇瑙﹀彂鍣ㄧ殑鍊硷紝浠庨厤缃弬鏁颁腑鑾峰彇 if (strategy == NULL || strategy->btype != BAS_BULKREAD) { - return; + return; // 濡傛灉浼犲叆鐨勭瓥鐣ヤ负绌烘垨鑰呬笉鏄疊AS_BULKREAD绫诲瀷锛岀洿鎺ヨ繑鍥烇紝涓嶈繘琛岄鍙栬缃 } + + // 棰勫彇闃堝艰缃负缂撳啿绛栫暐鐨勭幆褰㈢紦鍐插尯澶у皬鐨1/4 threshold = strategy->ring_size / 4; + if (quantity != NULL) { + // 濡傛灉浼犲叆鐨剄uantity鍙傛暟涓嶄负绌猴紝鍒欒缃畄uantity涓洪厤缃弬鏁颁腑鐨刾refetch_quantity鎴栬卼hreshold涓殑杈冨皬鍊 *quantity = (threshold > u_sess->attr.attr_storage.prefetch_quantity) ? u_sess->attr.attr_storage.prefetch_quantity : threshold; } + if (trigger != NULL) { + // 濡傛灉浼犲叆鐨則rigger鍙傛暟涓嶄负绌猴紝鍒欒缃畉rigger涓簆refetch_trigger鎴栬卼hreshold涓殑杈冨皬鍊 *trigger = (threshold > prefetch_trigger) ? prefetch_trigger : threshold; } } - +/* + * 鍔熻兘锛氬敜閱掗〉鍐欏叆绾跨▼ + * + * 鍙傛暟鍒楄〃锛 + * 鏃 + * + * 杩斿洖鍊硷細 + * 鏃 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庡敜閱掗〉鍐欏叆绾跨▼锛屼互渚垮叾缁х画澶勭悊寰呭啓鍏ョ殑鏁版嵁銆 + * 瀹冩鏌ラ〉鍐欏叆绾跨▼鏄惁瀛樺湪锛屽鏋滃瓨鍦ㄥ垯瑙﹀彂绾跨▼鐨勫鐞嗐 + */ void wakeup_pagewriter_thread() { PageWriterProc *pgwr = &g_instance.ckpt_cxt_ctl->pgwr_procs.writer_proc[0]; @@ -703,45 +734,66 @@ void wakeup_pagewriter_thread() return; } -const int CANDIDATE_DIRTY_LIST_LEN = 100; -const float HIGH_WATER = 0.75; -static BufferDesc* get_buf_from_candidate_list(BufferAccessStrategy strategy, uint32* buf_state) +const int CANDIDATE_DIRTY_LIST_LEN = 100; // 瀹氫箟鍊欓夎剰椤靛垪琛ㄧ殑鏈澶ч暱搴 +const float HIGH_WATER = 0.75; // 瀹氫箟鑴忛〉楂樻按浣嶇嚎姣斾緥 +/* + * 鍔熻兘锛氫粠鍊欓夊垪琛ㄤ腑鑾峰彇缂撳啿鍖烘弿杩扮 + * + * 鍙傛暟鍒楄〃锛 + * strategy锛氱紦鍐插尯璁块棶绛栫暐 + * buf_state锛氭寚鍚戝瓨鍌ㄧ紦鍐插尯鐘舵佺殑鍙橀噺鐨勬寚閽 + * + * 杩斿洖鍊硷細 + * 鎸囧悜缂撳啿鍖烘弿杩扮鐨勬寚閽堬紝濡傛灉娌℃湁鍙敤缂撳啿鍖哄垯杩斿洖 NULL + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庝粠鍊欓夊垪琛ㄤ腑鑾峰彇缂撳啿鍖烘弿杩扮锛屽苟鏍规嵁绛栫暐閫夋嫨鍚堥傜殑缂撳啿鍖恒 + * 鍦ㄨ幏鍙栫紦鍐插尯涔嬪墠锛屽畠浼氭鏌ョ紦鍐插尯鐨勫彲鐢ㄦу拰鐘舵侊紝骞跺彲鑳借Е鍙戦〉鍐欏叆绾跨▼銆 + */ +static BufferDesc *get_buf_from_candidate_list(BufferAccessStrategy strategy, uint32 *buf_state) { - BufferDesc* buf = NULL; - uint32 local_buf_state; - int buf_id = 0; - int list_num = g_instance.ckpt_cxt_ctl->pgwr_procs.sub_num; - int list_id = 0; - volatile PgBackendStatus* beentry = t_thrd.shemem_ptr_cxt.MyBEEntry; - Buffer *candidate_dirty_list = NULL; - int dirty_list_num = 0; - bool enable_available = false; - bool need_push_dirst_list = false; + BufferDesc *buf = NULL; // 缂撳啿鍖烘弿杩扮鎸囬拡 + uint32 local_buf_state; // 鏈湴缂撳啿鍖虹姸鎬 + int buf_id = 0; // 缂撳啿鍖篒D + int list_num = g_instance.ckpt_cxt_ctl->pgwr_procs.sub_num; // 瀛愯繘绋嬫暟閲 + int list_id = 0; // 鍒楄〃ID + volatile PgBackendStatus *beentry = t_thrd.shemem_ptr_cxt.MyBEEntry; // 鑾峰彇褰撳墠绾跨▼鐨勫悗绔姸鎬佷俊鎭 + Buffer *candidate_dirty_list = NULL; // 瀛樺偍鍊欓夎剰椤电殑鍒楄〃 + int dirty_list_num = 0; // 鍊欓夎剰椤靛垪琛ㄤ腑鐨勮剰椤垫暟閲 + bool enable_available = false; // 鏄惁鍙敤鏍囧織 + bool need_push_dirst_list = false; // 鏄惁闇瑕佸皢缂撳啿鍖烘坊鍔犲埌鍊欓夎剰椤靛垪琛ㄧ殑鏍囧織 bool need_scan_dirty = - (g_instance.ckpt_cxt_ctl->actual_dirty_page_num / (float)(g_instance.attr.attr_storage.NBuffers) > HIGH_WATER) - && backend_can_flush_dirty_page(); + (g_instance.ckpt_cxt_ctl->actual_dirty_page_num / (float)(g_instance.attr.attr_storage.NBuffers) > + HIGH_WATER) && + backend_can_flush_dirty_page(); // 鏄惁闇瑕佹壂鎻忚剰椤电殑鏍囧織锛屾牴鎹剰椤靛崰鐢ㄦ瘮渚嬪拰鏄惁鍏佽鍒锋柊鑴忛〉鍐冲畾 + if (need_scan_dirty) { - /*Not return the dirty page when there are few dirty pages */ - candidate_dirty_list = (Buffer*)palloc0(sizeof(Buffer) * CANDIDATE_DIRTY_LIST_LEN); + /* 鍒嗛厤鐢ㄤ簬淇濆瓨鑴忛〉鐨勫欓夊垪琛 */ + candidate_dirty_list = (Buffer *)palloc0(sizeof(Buffer) * CANDIDATE_DIRTY_LIST_LEN); } + /* 璁$畻鍒楄〃 ID */ list_id = beentry->st_tid > 0 ? (beentry->st_tid % list_num) : (beentry->st_sessionid % list_num); + /* 閬嶅巻鍊欓夊垪琛 */ for (int i = 0; i < list_num; i++) { - /* the pagewriter sub thread store normal buffer pool, sub thread starts from 1 */ + /* 瀛愯繘绋嬬殑ID锛屼粠1寮濮 */ int thread_id = (list_id + i) % list_num + 1; Assert(thread_id > 0 && thread_id <= list_num); + while (candidate_buf_pop(&buf_id, thread_id)) { Assert(buf_id < SegmentBufferStartID); - buf = GetBufferDescriptor(buf_id); - local_buf_state = LockBufHdr(buf); + buf = GetBufferDescriptor(buf_id); // 鑾峰彇缂撳啿鍖烘弿杩扮 + local_buf_state = LockBufHdr(buf); // 閿佸畾缂撳啿鍖哄ご閮 if (g_instance.ckpt_cxt_ctl->candidate_free_map[buf_id]) { g_instance.ckpt_cxt_ctl->candidate_free_map[buf_id] = false; enable_available = BUF_STATE_GET_REFCOUNT(local_buf_state) == 0 && !(local_buf_state & BM_IS_META); - need_push_dirst_list = need_scan_dirty && dirty_list_num < CANDIDATE_DIRTY_LIST_LEN && - free_space_enough(buf_id); + need_push_dirst_list = + need_scan_dirty && dirty_list_num < CANDIDATE_DIRTY_LIST_LEN && free_space_enough(buf_id); + if (enable_available) { + /* 濡傛灉缂撳啿鍖哄彲鐢紝灏嗗叾娣诲姞鍒扮瓥鐣ョ幆涓 */ if (NEED_CONSIDER_USECOUNT && BUF_STATE_GET_USAGECOUNT(local_buf_state) != 0) { local_buf_state -= BUF_USAGECOUNT_ONE; } else if (!(local_buf_state & BM_DIRTY)) { @@ -758,10 +810,11 @@ static BufferDesc* get_buf_from_candidate_list(BufferAccessStrategy strategy, ui } } } - UnlockBufHdr(buf, local_buf_state); + UnlockBufHdr(buf, local_buf_state); // 瑙i攣缂撳啿鍖哄ご閮 } } + /* 鍞ら啋 PageWriter 绾跨▼ */ wakeup_pagewriter_thread(); if (need_scan_dirty) { @@ -769,9 +822,11 @@ static BufferDesc* get_buf_from_candidate_list(BufferAccessStrategy strategy, ui buf_id = candidate_dirty_list[i]; buf = GetBufferDescriptor(buf_id); local_buf_state = LockBufHdr(buf); - enable_available = (BUF_STATE_GET_REFCOUNT(local_buf_state) == 0) && !(local_buf_state & BM_IS_META) - && free_space_enough(buf_id); + enable_available = (BUF_STATE_GET_REFCOUNT(local_buf_state) == 0) && !(local_buf_state & BM_IS_META) && + free_space_enough(buf_id); + if (enable_available) { + /* 濡傛灉缂撳啿鍖哄彲鐢紝灏嗗叾娣诲姞鍒扮瓥鐣ョ幆涓 */ if (strategy != NULL) { AddBufferToRing(strategy, buf); } @@ -779,13 +834,13 @@ static BufferDesc* get_buf_from_candidate_list(BufferAccessStrategy strategy, ui pfree(candidate_dirty_list); return buf; } - UnlockBufHdr(buf, local_buf_state); + UnlockBufHdr(buf, local_buf_state); // 瑙i攣缂撳啿鍖哄ご閮 } } if (candidate_dirty_list != NULL) { - pfree(candidate_dirty_list); + pfree(candidate_dirty_list); // 閲婃斁鍊欓夎剰椤靛垪琛ㄥ唴瀛 } - return NULL; -} + return NULL; // 杩斿洖 NULL锛岃〃绀烘病鏈夊彲鐢ㄧ殑缂撳啿鍖 +} diff --git a/src/gausskernel/storage/buffer/localbuf.cpp b/src/gausskernel/storage/buffer/localbuf.cpp index c14078840..e9d61e4f2 100644 --- a/src/gausskernel/storage/buffer/localbuf.cpp +++ b/src/gausskernel/storage/buffer/localbuf.cpp @@ -60,7 +60,7 @@ void LocalPrefetchBuffer(SMgrRelation smgr, ForkNumber forkNum, BlockNumber bloc InitLocalBuffers(); /* See if the desired buffer already exists */ - hresult = (LocalBufferLookupEnt*)hash_search(u_sess->storage_cxt.LocalBufHash, (void*)&new_tag, HASH_FIND, NULL); + hresult = (LocalBufferLookupEnt *)hash_search(u_sess->storage_cxt.LocalBufHash, (void *)&new_tag, HASH_FIND, NULL); if (hresult != NULL) { /* Yes, so nothing to do */ return; @@ -95,7 +95,17 @@ void LocalBufferFlushForExtremRTO(BufferDesc *bufHdr) } FlushBuffer(bufHdr, NULL, WITH_LOCAL_CACHE); } - +/* + * 鍔熻兘锛氬埛鏂版墍鏈夋湰鍦扮紦鍐插尯涓殑鑴忕紦鍐插尯 + * + * 鍙傛暟鍒楄〃锛氭棤 + * + * 杩斿洖鍊硷細鏃 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁伴亶鍘嗘墍鏈夋湰鍦扮紦鍐插尯锛屾鏌ュ苟鍒锋柊鎵鏈夎剰缂撳啿鍖恒 + * 鏈湴缂撳啿鍖烘槸鐗瑰畾浜庢湰鍦版枃浠剁郴缁熺殑缂撳啿鍖恒 + */ void LocalBufferFlushAllBuffer() { int i; @@ -104,25 +114,45 @@ void LocalBufferFlushAllBuffer() BufferDesc *bufHdr = &u_sess->storage_cxt.LocalBufferDescriptors[i]; uint32 buf_state; + /* 鑾峰彇缂撳啿鍖虹姸鎬 */ buf_state = pg_atomic_read_u32(&bufHdr->state); + + /* 鏂█锛氭湰鍦板紩鐢ㄨ鏁颁负0锛岀‘淇濇病鏈夎鍏朵粬鍦版柟寮曠敤 */ Assert(u_sess->storage_cxt.LocalRefCount[i] == 0); + /* 濡傛灉缂撳啿鍖烘槸鏈夋晥鐨勪笖鑴忕殑 */ if ((buf_state & BM_VALID) && (buf_state & BM_DIRTY)) { + /* 鎵ц鏋佺RTO鏃剁殑鏈湴缂撳啿鍖哄埛鏂 */ LocalBufferFlushForExtremRTO(bufHdr); + /* 娓呴櫎鑴忔爣蹇椾綅 */ buf_state &= ~BM_DIRTY; pg_atomic_write_u32(&bufHdr->state, buf_state); + /* 鏇存柊缁熻淇℃伅锛氭湰鍦板潡鍐欏叆璁℃暟 */ u_sess->instr_cxt.pg_buffer_usage->local_blks_written++; } } } - +/* + * 鍔熻兘锛氭鏌ユ湰鍦扮紦鍐插尯鐨勪竴鑷存 + * + * 鍙傛暟鍒楄〃锛 + * tag1锛氱涓涓紦鍐插尯鏍囩 + * tag2锛氱浜屼釜缂撳啿鍖烘爣绛 + * + * 杩斿洖鍊硷細鏃 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庢鏌ヤ袱涓湰鍦扮紦鍐插尯鏍囩鏄惁鐩哥瓑锛屽鏋滀笉鐩哥瓑锛屽垯寮曞彂鏁版嵁鎹熷潖閿欒銆 + * 鏈湴缂撳啿鍖烘爣绛剧敤浜庢爣璇嗙壒瀹氱殑鏈湴缂撳啿鍖恒 + */ static void LocalBufferSanityCheck(BufferTag tag1, BufferTag tag2) { + /* 濡傛灉涓や釜缂撳啿鍖烘爣绛句笉鐩哥瓑 */ if (!BUFFERTAGS_EQUAL(tag1, tag2)) { - ereport(ERROR, (errcode(ERRCODE_DATA_CORRUPTED), - (errmsg("local buffer hash tag mismatch.")))); + /* 寮曞彂鏁版嵁鎹熷潖閿欒 */ + ereport(ERROR, (errcode(ERRCODE_DATA_CORRUPTED), (errmsg("local buffer hash tag mismatch.")))); } } @@ -135,6 +165,22 @@ static void LocalBufferSanityCheck(BufferTag tag1, BufferTag tag2) * does not get set. Lastly, we support only default access strategy * (hence, usage_count is always advanced). */ +/* + * 鍔熻兘锛氬垎閰嶆湰鍦扮紦鍐插尯骞惰繑鍥炵紦鍐插尯鎻忚堪绗 + * + * 鍙傛暟鍒楄〃锛 + * smgr锛氬瓨鍌ㄧ鐞嗗櫒鍏崇郴 + * forkNum锛氬垎鍙夊彿 + * blockNum锛氬潡鍙 + * foundPtr锛氭寚鍚戝瓨鍌ㄦ槸鍚︽壘鍒扮殑鎸囬拡鐨勬寚閽 + * + * 杩斿洖鍊硷細 + * 鎸囧悜缂撳啿鍖烘弿杩扮鐨勬寚閽堬紝濡傛灉鏈壘鍒板彲鐢ㄧ紦鍐插尯鍒欒繑鍥 NULL + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庡垎閰嶆湰鍦扮紦鍐插尯锛屽苟杩斿洖涓庣粰瀹氬潡鏍囪瘑绗﹀叧鑱旂殑缂撳啿鍖烘弿杩扮銆 + * 濡傛灉缂撳啿鍖哄凡瀛樺湪锛屽垯鐩存帴杩斿洖锛屽惁鍒欏垎閰嶆柊鐨勭紦鍐插尯銆 + */ BufferDesc *LocalBufferAlloc(SMgrRelation smgr, ForkNumber forkNum, BlockNumber blockNum, bool *foundPtr) { BufferTag new_tag; /* identity of requested block */ @@ -152,7 +198,7 @@ BufferDesc *LocalBufferAlloc(SMgrRelation smgr, ForkNumber forkNum, BlockNumber InitLocalBuffers(); /* See if the desired buffer already exists */ - hresult = (LocalBufferLookupEnt*)hash_search(u_sess->storage_cxt.LocalBufHash, (void*)&new_tag, HASH_FIND, NULL); + hresult = (LocalBufferLookupEnt *)hash_search(u_sess->storage_cxt.LocalBufHash, (void *)&new_tag, HASH_FIND, NULL); if (hresult != NULL) { b = hresult->id; buf_desc = &u_sess->storage_cxt.LocalBufferDescriptors[b]; @@ -257,8 +303,8 @@ BufferDesc *LocalBufferAlloc(SMgrRelation smgr, ForkNumber forkNum, BlockNumber pg_atomic_write_u32(&buf_desc->state, buf_state); } - hresult = (LocalBufferLookupEnt *)hash_search(u_sess->storage_cxt.LocalBufHash, (void *)&new_tag, HASH_ENTER, - &found); + hresult = + (LocalBufferLookupEnt *)hash_search(u_sess->storage_cxt.LocalBufHash, (void *)&new_tag, HASH_ENTER, &found); if (found) /* shouldn't happen */ ereport(ERROR, (errcode(ERRCODE_DATA_CORRUPTED), (errmsg("local buffer hash table corrupted.")))); hresult->id = b; @@ -325,8 +371,8 @@ void DropRelFileNodeLocalBuffers(const RelFileNode &rnode, ForkNumber forkNum, B int i; for (i = 0; i < u_sess->storage_cxt.NLocBuffer; i++) { - BufferDesc* buf_desc = &u_sess->storage_cxt.LocalBufferDescriptors[i]; - LocalBufferLookupEnt* hresult = NULL; + BufferDesc *buf_desc = &u_sess->storage_cxt.LocalBufferDescriptors[i]; + LocalBufferLookupEnt *hresult = NULL; uint32 buf_state; buf_state = pg_atomic_read_u32(&buf_desc->state); @@ -335,15 +381,14 @@ void DropRelFileNodeLocalBuffers(const RelFileNode &rnode, ForkNumber forkNum, B buf_desc->tag.forkNum == forkNum && buf_desc->tag.blockNum >= firstDelBlock) { if (u_sess->storage_cxt.LocalRefCount[i] != 0) { ereport(ERROR, - (errcode(ERRCODE_INVALID_BUFFER_REFERENCE), - (errmsg("block %u of %s is still referenced (local %d)", - buf_desc->tag.blockNum, - relpathbackend(buf_desc->tag.rnode, BackendIdForTempRelations, buf_desc->tag.forkNum), - u_sess->storage_cxt.LocalRefCount[i])))); + (errcode(ERRCODE_INVALID_BUFFER_REFERENCE), + (errmsg("block %u of %s is still referenced (local %d)", buf_desc->tag.blockNum, + relpathbackend(buf_desc->tag.rnode, BackendIdForTempRelations, buf_desc->tag.forkNum), + u_sess->storage_cxt.LocalRefCount[i])))); } /* Remove entry from hashtable */ - hresult = (LocalBufferLookupEnt*)hash_search( - u_sess->storage_cxt.LocalBufHash, (void*)&buf_desc->tag, HASH_REMOVE, NULL); + hresult = (LocalBufferLookupEnt *)hash_search(u_sess->storage_cxt.LocalBufHash, (void *)&buf_desc->tag, + HASH_REMOVE, NULL); if (hresult == NULL) /* shouldn't happen */ ereport(ERROR, (errcode(ERRCODE_DATA_CORRUPTED), (errmsg("local buffer hash table corrupted.")))); /* Mark buffer invalid */ @@ -367,8 +412,8 @@ void DropRelFileNodeAllLocalBuffers(const RelFileNode &rnode) int i; for (i = 0; i < u_sess->storage_cxt.NLocBuffer; i++) { - BufferDesc* buf_desc = &u_sess->storage_cxt.LocalBufferDescriptors[i]; - LocalBufferLookupEnt* hresult = NULL; + BufferDesc *buf_desc = &u_sess->storage_cxt.LocalBufferDescriptors[i]; + LocalBufferLookupEnt *hresult = NULL; uint32 buf_state; buf_state = pg_atomic_read_u32(&buf_desc->state); @@ -380,15 +425,14 @@ void DropRelFileNodeAllLocalBuffers(const RelFileNode &rnode) errmsg("fork number should not be less than zero"))); } ereport(ERROR, - (errcode(ERRCODE_INVALID_BUFFER_REFERENCE), - (errmsg("block %u of %s is still referenced (local %d)", - buf_desc->tag.blockNum, - relpathbackend(buf_desc->tag.rnode, BackendIdForTempRelations, buf_desc->tag.forkNum), - u_sess->storage_cxt.LocalRefCount[i])))); + (errcode(ERRCODE_INVALID_BUFFER_REFERENCE), + (errmsg("block %u of %s is still referenced (local %d)", buf_desc->tag.blockNum, + relpathbackend(buf_desc->tag.rnode, BackendIdForTempRelations, buf_desc->tag.forkNum), + u_sess->storage_cxt.LocalRefCount[i])))); } /* Remove entry from hashtable */ - hresult = (LocalBufferLookupEnt*)hash_search( - u_sess->storage_cxt.LocalBufHash, (void*)&buf_desc->tag, HASH_REMOVE, NULL); + hresult = (LocalBufferLookupEnt *)hash_search(u_sess->storage_cxt.LocalBufHash, (void *)&buf_desc->tag, + HASH_REMOVE, NULL); if (hresult == NULL) /* shouldn't happen */ ereport(ERROR, (errcode(ERRCODE_DATA_CORRUPTED), (errmsg("local buffer hash table corrupted.")))); /* Mark buffer invalid */ @@ -413,12 +457,12 @@ static void InitLocalBuffers(void) int i; /* Allocate and zero buffer headers and auxiliary arrays */ - u_sess->storage_cxt.LocalBufferDescriptors = (BufferDesc*)MemoryContextAllocZero( + u_sess->storage_cxt.LocalBufferDescriptors = (BufferDesc *)MemoryContextAllocZero( SESS_GET_MEM_CXT_GROUP(MEMORY_CONTEXT_STORAGE), (unsigned int)nbufs * sizeof(BufferDesc)); - u_sess->storage_cxt.LocalBufferBlockPointers = (Block*)MemoryContextAllocZero( + u_sess->storage_cxt.LocalBufferBlockPointers = (Block *)MemoryContextAllocZero( SESS_GET_MEM_CXT_GROUP(MEMORY_CONTEXT_STORAGE), (unsigned int)nbufs * sizeof(Block)); - u_sess->storage_cxt.LocalRefCount = (int32*)MemoryContextAllocZero( - SESS_GET_MEM_CXT_GROUP(MEMORY_CONTEXT_STORAGE), (unsigned int)nbufs * sizeof(int32)); + u_sess->storage_cxt.LocalRefCount = (int32 *)MemoryContextAllocZero(SESS_GET_MEM_CXT_GROUP(MEMORY_CONTEXT_STORAGE), + (unsigned int)nbufs * sizeof(int32)); if (!u_sess->storage_cxt.LocalBufferDescriptors || !u_sess->storage_cxt.LocalBufferBlockPointers || !u_sess->storage_cxt.LocalRefCount) ereport(FATAL, (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of memory"))); @@ -427,7 +471,7 @@ static void InitLocalBuffers(void) /* initialize fields that need to start off nonzero */ for (i = 0; i < nbufs; i++) { - BufferDesc* buf = &u_sess->storage_cxt.LocalBufferDescriptors[i]; + BufferDesc *buf = &u_sess->storage_cxt.LocalBufferDescriptors[i]; /* * negative to indicate local buffer. This is tricky: shared buffers @@ -446,12 +490,11 @@ static void InitLocalBuffers(void) info.hash = tag_hash; info.hcxt = SESS_GET_MEM_CXT_GROUP(MEMORY_CONTEXT_STORAGE); - u_sess->storage_cxt.LocalBufHash = hash_create( - "Local Buffer Lookup Table", nbufs, &info, HASH_ELEM | HASH_CONTEXT | HASH_FUNCTION); + u_sess->storage_cxt.LocalBufHash = + hash_create("Local Buffer Lookup Table", nbufs, &info, HASH_ELEM | HASH_CONTEXT | HASH_FUNCTION); if (!u_sess->storage_cxt.LocalBufHash) { - ereport(ERROR, (errcode(ERRCODE_INITIALIZE_FAILED), - (errmsg("could not initialize local buffer hash table.")))); + ereport(ERROR, (errcode(ERRCODE_INITIALIZE_FAILED), (errmsg("could not initialize local buffer hash table.")))); } /* Initialization done, mark buffers allocated */ @@ -483,11 +526,9 @@ static Block GetLocalBufferStorage(void) * output. Create the context on first use. */ if (u_sess->storage_cxt.LocalBufferContext == NULL) - u_sess->storage_cxt.LocalBufferContext = AllocSetContextCreate(u_sess->top_mem_cxt, - "LocalBufferContext", - ALLOCSET_DEFAULT_MINSIZE, - ALLOCSET_DEFAULT_INITSIZE, - ALLOCSET_DEFAULT_MAXSIZE); + u_sess->storage_cxt.LocalBufferContext = + AllocSetContextCreate(u_sess->top_mem_cxt, "LocalBufferContext", ALLOCSET_DEFAULT_MINSIZE, + ALLOCSET_DEFAULT_INITSIZE, ALLOCSET_DEFAULT_MAXSIZE); /* Start with a 16-buffer request; subsequent ones double each time */ num_bufs = Max(u_sess->storage_cxt.num_bufs_in_block * 2, 16); @@ -497,7 +538,7 @@ static Block GetLocalBufferStorage(void) num_bufs = Min((unsigned int)(num_bufs), MaxAllocSize / BLCKSZ); u_sess->storage_cxt.cur_block = - (char*)MemoryContextAlloc(u_sess->storage_cxt.LocalBufferContext, num_bufs * BLCKSZ); + (char *)MemoryContextAlloc(u_sess->storage_cxt.LocalBufferContext, num_bufs * BLCKSZ); u_sess->storage_cxt.next_buf_in_block = 0; u_sess->storage_cxt.num_bufs_in_block = num_bufs; } @@ -560,10 +601,10 @@ void AtProcExit_LocalBuffers(void) void ForgetLocalBuffer(RelFileNode rnode, ForkNumber forkNum, BlockNumber blockNum) { SMgrRelation smgr = smgropen(rnode, t_thrd.proc_cxt.MyBackendId); - BufferTag tag; /* identity of target block */ + BufferTag tag; /* identity of target block */ LocalBufferLookupEnt *hresult; BufferDesc *bufHdr; - uint32 bufState; + uint32 bufState; /* * If somehow this is the first request in the session, there's nothing to @@ -577,8 +618,7 @@ void ForgetLocalBuffer(RelFileNode rnode, ForkNumber forkNum, BlockNumber blockN INIT_BUFFERTAG(tag, smgr->smgr_rnode.node, forkNum, blockNum); /* see if the block is in the local buffer pool */ - hresult = (LocalBufferLookupEnt *) - hash_search(t_thrd.storage_cxt.LocalBufHash, (void *) &tag, HASH_REMOVE, NULL); + hresult = (LocalBufferLookupEnt *)hash_search(t_thrd.storage_cxt.LocalBufHash, (void *)&tag, HASH_REMOVE, NULL); /* didn't find it, so nothing to do */ if (!hresult) { diff --git a/src/gausskernel/storage/bulkload/dist_fdw.cpp b/src/gausskernel/storage/bulkload/dist_fdw.cpp index 44155d30f..b692ddc5e 100644 --- a/src/gausskernel/storage/bulkload/dist_fdw.cpp +++ b/src/gausskernel/storage/bulkload/dist_fdw.cpp @@ -129,50 +129,49 @@ const int GSOBS_PREFIX_LEN = strlen(GSOBS_PREFIX); */ static struct DistFdwOption loader_valid_options[] = { /* File options */ - { optLocation, ForeignTableRelationId }, - { OPTION_NAME_REGION, ForeignTableRelationId }, + {optLocation, ForeignTableRelationId}, + {OPTION_NAME_REGION, ForeignTableRelationId}, /* Format options */ /* oids option is not supported */ - { optFormat, ForeignTableRelationId }, - { optHeader, ForeignTableRelationId }, - { optDelimiter, ForeignTableRelationId }, - { optQutote, ForeignTableRelationId }, - { optEscape, ForeignTableRelationId }, - { optNull, ForeignTableRelationId }, - { optEncoding, ForeignTableRelationId }, - { optFillMissFields, ForeignTableRelationId }, - { optMode, ForeignTableRelationId }, - { optWithoutEscaping, ForeignTableRelationId }, - { optForceNotNull, AttributeRelationId }, - { optEol, ForeignTableRelationId }, - { optFix, ForeignTableRelationId }, - { optFileHeader, ForeignTableRelationId }, - { optOutputFilePrefix, ForeignTableRelationId }, - { optOutputFixAlignment, ForeignTableRelationId }, - { optRejectLimit, ForeignTableRelationId }, - { optIgnoreExtraData, ForeignTableRelationId }, + {optFormat, ForeignTableRelationId}, + {optHeader, ForeignTableRelationId}, + {optDelimiter, ForeignTableRelationId}, + {optQutote, ForeignTableRelationId}, + {optEscape, ForeignTableRelationId}, + {optNull, ForeignTableRelationId}, + {optEncoding, ForeignTableRelationId}, + {optFillMissFields, ForeignTableRelationId}, + {optMode, ForeignTableRelationId}, + {optWithoutEscaping, ForeignTableRelationId}, + {optForceNotNull, AttributeRelationId}, + {optEol, ForeignTableRelationId}, + {optFix, ForeignTableRelationId}, + {optFileHeader, ForeignTableRelationId}, + {optOutputFilePrefix, ForeignTableRelationId}, + {optOutputFixAlignment, ForeignTableRelationId}, + {optRejectLimit, ForeignTableRelationId}, + {optIgnoreExtraData, ForeignTableRelationId}, /* OBS only options */ - { optChunkSize, ForeignTableRelationId }, - { optEncrypt, ForeignTableRelationId }, - { optAccessKey, ForeignTableRelationId }, - { optSecretAccessKey, ForeignTableRelationId }, + {optChunkSize, ForeignTableRelationId}, + {optEncrypt, ForeignTableRelationId}, + {optAccessKey, ForeignTableRelationId}, + {optSecretAccessKey, ForeignTableRelationId}, /* * bulkload compatible illegal chars option */ - { optCompatibleIllegalChars, ForeignTableRelationId }, + {optCompatibleIllegalChars, ForeignTableRelationId}, /* * bulkload datetime format options */ - { optDateFormat, ForeignTableRelationId }, - { optTimeFormat, ForeignTableRelationId }, - { optTimestampFormat, ForeignTableRelationId }, - { optSmalldatetimeFormat, ForeignTableRelationId }, + {optDateFormat, ForeignTableRelationId}, + {optTimeFormat, ForeignTableRelationId}, + {optTimestampFormat, ForeignTableRelationId}, + {optSmalldatetimeFormat, ForeignTableRelationId}, /* Sentinel */ - { NULL, InvalidOid } -}; + {NULL, InvalidOid}}; PG_FUNCTION_INFO_V1(dist_fdw_handler); PG_FUNCTION_INFO_V1(dist_fdw_validator); @@ -297,48 +296,113 @@ Datum dist_fdw_handler(PG_FUNCTION_ARGS) * * Raise an ERROR if the option or its value is considered invalid. */ +/* + * 鍔熻兘锛氬垎甯冨紡澶栭儴鏁版嵁瀵煎叆鐨勯夐」楠岃瘉鍑芥暟 + * + * 鍙傛暟鍒楄〃锛 + * PG_FUNCTION_ARGS锛歅ostgreSQL UDF 鍑芥暟鍙傛暟 + * + * 杩斿洖鍊硷細 + * 鏃 + */ Datum dist_fdw_validator(PG_FUNCTION_ARGS) { + // 瑙f瀽澶栭儴琛ㄩ夐」鍒楄〃 List *options_list = untransformRelOptions(PG_GETARG_DATUM(0)); + + // 鑾峰彇澶栭儴琛ㄧ殑鐩綍 OID Oid catalog = PG_GETARG_OID(1); + + // 鍒涘缓鍒嗗竷寮忓鍏ヨ鍒掔姸鎬佸拰鎵ц鐘舵佺粨鏋 DistImportPlanState planstate; DistImportExecutionState execState; - errno_t rc = EOK; + // 鍒濆鍖栬鍒掔姸鎬佺粨鏋勭殑鍐呭瓨 + errno_t rc = EOK; rc = memset_s(&planstate, sizeof(planstate), 0, sizeof(planstate)); securec_check(rc, "\0", "\0"); + + // 鍒濆鍖栨墽琛岀姸鎬佺粨鏋勭殑鍐呭瓨 rc = memset_s(&execState, sizeof(execState), 0, sizeof(execState)); securec_check(rc, "\0", "\0"); + + // 澶勭悊澶栭儴琛ㄩ夐」锛屽~鍏呰鍒掔姸鎬佺粨鏋 ProcessDistImportOptions(&planstate, options_list, true, catalog != ForeignTableRelationId); - ProcessCopyOptions((CopyState) & execState, !planstate.writeOnly, planstate.options); + + // 澶勭悊COPY閫夐」锛屽~鍏呮墽琛岀姸鎬佺粨鏋 + ProcessCopyOptions((CopyState)&execState, !planstate.writeOnly, planstate.options); + + // 楠岃瘉鏂囦欢缂栫爜 VerifyEncoding(planstate.fileEncoding); + + // 濡傛灉鏂囦欢鏍煎紡涓嶆槸TEXT骞朵笖浣跨敤浜哠HARED妯″紡锛屽垯鎶ラ敊 if (execState.fileformat != FORMAT_TEXT && IS_SHARED_MODE(planstate.mode)) ereport(ERROR, (errcode(ERRCODE_FDW_ERROR), errmsg("SHARED mode can only be used with TEXT format"))); + + // 杩斿洖绌虹粨鏋 PG_RETURN_VOID(); } +/* + * 鍔熻兘锛氳幏鍙栧閮ㄩ敊璇褰曡〃鐨勭紦瀛樻潯鐩 + * + * 鍙傛暟鍒楄〃锛 + * relid锛氬閮ㄨ〃鐨凮ID + * distSessionKey锛氬垎甯冨紡浼氳瘽瀵嗛挜 + * + * 杩斿洖鍊硷細 + * 濡傛灉鎵惧埌鐩稿叧閫夐」骞舵垚鍔熻幏鍙朎rrorCacheEntry锛岃繑鍥炶鏉$洰鐨勬寚閽堬紝鍚﹀垯杩斿洖NULL銆 + */ ErrorCacheEntry *GetForeignErrCacheEntry(Oid relid, uint32 distSessionKey) { + // 澹版槑骞跺垵濮嬪寲涓涓寚鍚慐rrorCacheEntry缁撴瀯鐨勬寚閽坋ntry锛屽垵濮嬪间负NULL ErrorCacheEntry *entry = NULL; + + // 浣跨敤GetForeignTableOptionByName鍑芥暟鏌ユ壘涓巖elid鐩稿叧鐨勫閮ㄨ〃閫夐」optErrorRel DefElem *def = GetForeignTableOptionByName(relid, optErrorRel); + // 濡傛灉鎵惧埌浜嗛夐」def if (def != NULL) { + // 澹版槑骞跺垵濮嬪寲涓涓寚鍚慠angeTblEntry缁撴瀯鐨勬寚閽坮te锛屽垵濮嬪间负NULL RangeTblEntry *rte = NULL; + + // 浠庨夐」def涓幏鍙栧閮ㄩ敊璇褰曡〃鐨勮〃鍚峳elname char *relname = strVal(def->arg); + + // 浣跨敤琛ㄥ悕relname鍜屽叧鑱旇〃鐨勫懡鍚嶇┖闂磋幏鍙栭敊璇褰曡〃鐨凮ID Oid errorOid = get_relname_relid(relname, get_rel_namespace(relid)); + // 鍒涘缓涓涓柊鐨凟rrorCacheEntry缁撴瀯锛屽苟灏嗗叾鍒嗛厤缁檈ntry entry = makeNode(ErrorCacheEntry); + + // 濡傛灉鎵惧埌鐨別rrorOid鏄棤鏁堢殑 if (errorOid == InvalidOid) + // 鎶ュ憡涓涓敊璇紝鎸囨槑鏃犳硶鎵惧埌閿欒璁板綍琛 ereport(ERROR, (errcode(ERRCODE_FDW_ERROR), errmsg("can't find error record table \"%s\"", relname))); + + // 涓篹ntry璁剧疆filename锛岀敓鎴愬敮涓鐨勭紦瀛樺悕绉板墠缂锛屼娇鐢╡rrorOid鍜宒istSessionKey entry->filename = generate_unique_cache_name_prefix(errorOid, distSessionKey); + // 鍒嗛厤骞跺垵濮嬪寲涓涓柊鐨凴angeTblEntry缁撴瀯锛屽苟灏嗗叾鍒嗛厤缁檙te rte = (RangeTblEntry *)makeNode(RangeTblEntry); + + // 璁剧疆rte鐨勭被鍨嬩负RTE_RELATION锛岃〃绀鸿繖鏄竴涓叧绯昏〃 rte->rtekind = RTE_RELATION; + + // 璁剧疆rte鐨剅elid涓篹rrorOid锛岃〃绀哄叧鑱旂殑琛ㄧ殑OID rte->relid = errorOid; + + // 鑾峰彇骞惰缃畆te鐨剅elkind锛岃〃绀哄叧鑱旇〃鐨勭被鍨嬶紙濡傝〃銆佽鍥剧瓑锛 rte->relkind = get_rel_relkind(errorOid); + + // 璁剧疆rte鐨剅equiredPerms涓篈CL_INSERT锛岃〃绀烘墍闇鐨勬潈闄愭槸鎻掑叆鏉冮檺 rte->requiredPerms = ACL_INSERT; + + // 灏唕te璁剧疆涓篹ntry鐨剅te瀛楁锛岃〃绀轰笌閿欒璁板綍琛ㄥ叧鑱旂殑RangeTblEntry entry->rte = rte; } + + // 杩斿洖鑾峰彇鐨凟rrorCacheEntry缁撴瀯鎸囬拡锛屽鏋滄病鏈夋壘鍒扮浉鍏崇殑閫夐」锛屽垯涓篘ULL return entry; } @@ -346,14 +410,28 @@ ErrorCacheEntry *GetForeignErrCacheEntry(Oid relid, uint32 distSessionKey) * Check if the provided option is one of the valid options. * context is the Oid of the catalog holding the object the option is for. */ +/* + * 鍔熻兘锛氭鏌ラ夐」鏄惁鍦ㄦ湁鏁堥夐」鍒楄〃涓 + * + * 鍙傛暟鍒楄〃锛 + * option锛氳妫鏌ョ殑閫夐」鍚嶇О + * context锛氶夐」鐨勪笂涓嬫枃锛堜緥濡傦紝ForeignTableRelationId锛 + * + * 杩斿洖鍊硷細 + * 濡傛灉閫夐」鍦ㄦ湁鏁堥夐」鍒楄〃涓笖涓婁笅鏂囧尮閰嶏紝杩斿洖true锛涘惁鍒欒繑鍥瀎alse銆 + */ static bool is_valid_option(const char *option, Oid context) { struct DistFdwOption *opt = NULL; + // 閬嶅巻鏈夋晥閫夐」鍒楄〃 for (opt = loader_valid_options; opt->optname; opt++) { + // 妫鏌ラ夐」涓婁笅鏂囧拰閫夐」鍚嶇О鏄惁鍖归厤 if (context == opt->optcontext && strcmp(opt->optname, option) == 0) return true; } + + // 鏈壘鍒板尮閰嶇殑閫夐」 return false; } @@ -363,6 +441,17 @@ static bool is_valid_option(const char *option, Oid context) * We have to separate out "filename" from the other options because * it must not appear in the options list passed to the core COPY code. */ +/* + * 鍔熻兘锛氫粠澶栭儴琛ㄣ佸閮ㄦ湇鍔″櫒鍜屽閮ㄦ暟鎹寘瑁呭櫒涓彁鍙栭夐」 + * + * 鍙傛暟鍒楄〃锛 + * foreigntableid锛氬閮ㄨ〃鐨凮ID + * locaionts锛氬閮ㄨ〃鐨凩OCATION閫夐」鍊硷紙杈撳嚭鍙傛暟锛 + * other_options锛氬寘鍚櫎LOCATION浠ュ鐨勫叾浠栭夐」鐨勯夐」鍒楄〃锛堣緭鍑哄弬鏁帮級 + * + * 杩斿洖鍊硷細 + * 鏃 + */ void distGetOptions(Oid foreigntableid, char **locaionts, List **other_options) { ForeignTable *table = NULL; @@ -415,19 +504,38 @@ void distGetOptions(Oid foreigntableid, char **locaionts, List **other_options) * we add the parameter (void* additionalData). This parameter may not be * used by fileAnalyzeForeignTable function. */ +/* + * 鍔熻兘锛氬垎鏋愬閮ㄨ〃鐨勫嚱鏁 + * + * 鍙傛暟鍒楄〃锛 + * relation锛氬叧绯诲璞 + * func锛氶噰闆嗘牱鏈鐨勫嚱鏁版寚閽 + * totalPageCount锛氭婚〉鏁帮紙杈撳嚭鍙傛暟锛 + * additionalData锛氶澶栫殑鍒嗘瀽鏁版嵁锛堥氬父鏄閮ㄨ〃鐨勭浉鍏充俊鎭級 + * estimate_table_rownum锛氭槸鍚︿及绠楄〃鐨勮鏁 + * + * 杩斿洖鍊硷細 + * 濡傛灉鎴愬姛鍒嗘瀽澶栭儴琛紝杩斿洖true锛涘惁鍒欒繑鍥瀎alse銆 + */ static bool distAnalyzeForeignTable(Relation relation, AcquireSampleRowsFunc *func, BlockNumber *totalPageCount, void *additionalData, bool estimate_table_rownum) { + // 濡傛灉澶栭儴琛ㄦ槸鍙啓鐨勶紝涓嶈繘琛屽垎鏋 if (isWriteOnlyFt(RelationGetRelid(relation))) { return false; } + + // 濡傛灉澶栭儴琛ㄤ笉鏄疧BS CSV鎴朤XT鏍煎紡锛屼笉杩涜鍒嗘瀽 if (!IS_OBS_CSV_TXT_FOREIGN_TABLE(RelationGetRelid(relation))) { return false; } - if (additionalData == NULL) + // 濡傛灉additionalData涓篘ULL锛岃〃绀轰笉闇瑕佽繘琛屽垎鏋愶紝鐩存帴杩斿洖true + if (additionalData == NULL) { return true; + } + // 鑾峰彇澶栭儴琛ㄧ殑鎬婚〉鏁帮紝骞跺皢缁撴灉瀛樺偍鍦╰otalPageCount涓 (*totalPageCount) = getPageCountForFt(additionalData); return true; @@ -439,31 +547,54 @@ static bool distAnalyzeForeignTable(Relation relation, AcquireSampleRowsFunc *fu * @in foreignTableId, the given foreign table Oid. * @return return the dn task. */ +/* + * 鍔熻兘锛氫负鍒嗗竷寮廜BS澶栭儴琛ㄨ繘琛岃皟搴 + * + * 鍙傛暟鍒楄〃锛 + * foreignTableId锛氬閮ㄨ〃鐨凮ID + * + * 杩斿洖鍊硷細 + * 濡傛灉鎴愬姛锛岃繑鍥炰换鍔″垪琛紱鍚﹀垯杩斿洖NULL銆 + */ List *CNSchedulingForDistOBSFt(Oid foreignTableId) { + // 鑾峰彇澶栭儴琛ㄧ殑URL char *url = HdfsGetOptionValue(foreignTableId, optLocation); + // 鑾峰彇澶栭儴琛ㄧ殑Region Code char *regionCode = HdfsGetOptionValue(foreignTableId, OPTION_NAME_REGION); + // 鍒濆鍖栨柊鐨刄RL char *newUrl = url; errno_t rc = EOK; + // 鏂█URL涓嶄负绌 Assert(url != NULL); + // 濡傛灉URL浠BS_PREFIX寮澶达紝灏濊瘯閲嶅缓鎵鏈塋ocation閫夐」 if (url != NULL && pg_strncasecmp(url, OBS_PREFIX, OBS_PREfIX_LEN) == 0) { /* the regionCode may be NULL, we will get the default region. */ newUrl = rebuildAllLocationOptions(regionCode, url); } + // 鍙嶅簭鍒楀寲URL鍒楄〃 List *urlList = DeserializeLocations(newUrl); + // 鍒濆鍖栧姞瀵嗘爣蹇 bool encrypt = false; + // 鑾峰彇鏈嶅姟鍣ㄥ姞瀵嗛夐」 DefElem *encryptStr = HdfsGetOptionDefElem(foreignTableId, OPTION_NAME_SERVER_ENCRYPT); + // 鑾峰彇Access Key char *ak = HdfsGetOptionValue(foreignTableId, OPTION_NAME_SERVER_AK); + // 鑾峰彇Secret Access Key char *sak = HdfsGetOptionValue(foreignTableId, OPTION_NAME_SERVER_SAK); + // 濡傛灉瀛樺湪鍔犲瘑閫夐」锛岃幏鍙栧姞瀵嗘爣蹇 if (encryptStr != NULL) { encrypt = defGetBoolean(encryptStr); } + // 鑾峰彇OBS鏂囦欢鍒楄〃 List *obsFileList = getOBSFileList(urlList, encrypt, ak, sak, true); + // 鍒濆鍖栦换鍔″垪琛 List *totalTask = NIL; + // 鑾峰彇澶栭儴琛ㄧ殑鍒嗗竷淇℃伅 List *nodeList = NIL; RelationLocInfo *rlc = GetRelationLocInfo(foreignTableId); if (rlc != NULL) { @@ -471,17 +602,22 @@ List *CNSchedulingForDistOBSFt(Oid foreignTableId) } /* get all data node names */ + // 鑾峰彇鎵鏈夋暟鎹妭鐐瑰悕绉 List *dnNames = !nodeList ? PgxcNodeGetAllDataNodeNames() : PgxcNodeGetDataNodeNames(nodeList); /* assign obs file to each data node */ + // 灏哋BS鏂囦欢鍒嗛厤缁欐瘡涓暟鎹妭鐐 assignOBSFileToDataNode(obsFileList, &totalTask, dnNames); + // 閲婃斁鍏崇郴淇℃伅 pfree(rlc); + // 娓呴櫎骞堕噴鏀維ecret Access Key鐨勫唴瀛 if (sak != NULL) { rc = memset_s(sak, strlen(sak), 0, strlen(sak)); securec_check(rc, "\0", "\0"); pfree(sak); } + // 杩斿洖浠诲姟鍒楄〃 return totalTask; } #endif @@ -494,6 +630,16 @@ List *CNSchedulingForDistOBSFt(Oid foreignTableId) * @out * @return */ +/* + * 鍔熻兘锛氭瀯寤轰笌澶栭儴琛ㄥ叧鑱旂殑鎵弿鐘舵佷俊鎭 + * + * 鍙傛暟鍒楄〃锛 + * relation锛氬叧鑱旂殑澶栭儴琛 + * splitinfo锛氬垎甯冨紡澶栭儴琛ㄦ枃浠舵淇℃伅 + * + * 杩斿洖鍊硷細 + * 杩斿洖鏋勫缓鐨凢oreignScanState瀵硅薄銆 + */ ForeignScanState *buildRelatedStateInfo(Relation relation, DistFdwFileSegment *splitinfo) { ForeignScanState *scanState = NULL; @@ -505,29 +651,36 @@ ForeignScanState *buildRelatedStateInfo(Relation relation, DistFdwFileSegment *s TupleDesc tupleDescriptor = RelationGetDescr(relation); int columnCount = tupleDescriptor->natts; + // 涓哄垪鍊煎拰绌哄煎垎閰嶅唴瀛 Datum *columnValues = (Datum *)palloc0(columnCount * sizeof(Datum)); bool *columnNulls = (bool *)palloc0(columnCount * sizeof(bool)); + // 鍒涘缓鏂囦欢娈典俊鎭 fileInfo = makeNode(DistFdwFileSegment); fileInfo->filename = splitinfo->filename; + // 鍒涘缓鏁版嵁鑺傜偣浠诲姟 DistFdwDataNodeTask *fileSplitTask = NULL; /* Put file information into SplitMap struct */ + // 灏嗘枃浠朵俊鎭斁鍏ユ暟鎹妭鐐逛换鍔 fileSplitTask = makeNode(DistFdwDataNodeTask); fileWorkList = lappend(fileWorkList, (void *)fileInfo); fileSplitTask->dnName = g_instance.attr.attr_common.PGXCNodeName; fileSplitTask->task = fileWorkList; + // 灏嗘暟鎹妭鐐逛换鍔℃坊鍔犲埌HDFS鑺傜偣宸ヤ綔鍒楄〃 HDFSNodeWorkList = lappend(HDFSNodeWorkList, fileSplitTask); /* setup foreign scan plan node */ + // 璁剧疆澶栭儴鎵弿璁″垝鑺傜偣 ForeignScan *foreignScan = NULL; foreignScan = makeNode(ForeignScan); - foreignScan->fdw_private = lappend(foreignScan->fdw_private, - makeDefElem(pstrdup(optTaskList), (Node *)HDFSNodeWorkList)); + foreignScan->fdw_private = + lappend(foreignScan->fdw_private, makeDefElem(pstrdup(optTaskList), (Node *)HDFSNodeWorkList)); ; /* setup tuple slot */ + // 璁剧疆鍏冪粍妲 scanTupleSlot = MakeTupleTableSlot(true, tupleDescriptor->tdTableAmType); scanTupleSlot->tts_tupleDescriptor = tupleDescriptor; scanTupleSlot->tts_values = columnValues; @@ -539,10 +692,12 @@ ForeignScanState *buildRelatedStateInfo(Relation relation, DistFdwFileSegment *s scanState->ss.ps.plan = (Plan *)foreignScan; scanState->ss.ss_ScanTupleSlot = scanTupleSlot; - scanState->scanMcxt = AllocSetContextCreate(CurrentMemoryContext, "analyze for Foreign Scan", - ALLOCSET_DEFAULT_MINSIZE, ALLOCSET_DEFAULT_INITSIZE, - ALLOCSET_DEFAULT_MAXSIZE); + // 鍒嗛厤鎵弿鍐呭瓨涓婁笅鏂 + scanState->scanMcxt = + AllocSetContextCreate(CurrentMemoryContext, "analyze for Foreign Scan", ALLOCSET_DEFAULT_MINSIZE, + ALLOCSET_DEFAULT_INITSIZE, ALLOCSET_DEFAULT_MAXSIZE); + // 寮濮嬪垎甯冨紡瀵煎叆鎿嶄綔 distImportBegin(scanState, 0); return scanState; @@ -570,7 +725,8 @@ ForeignScanState *buildRelatedStateInfo(Relation relation, DistFdwFileSegment *s * input param @additionalData:we use this parameter to pass data. */ static int distAcquireSampleRows(Relation relation, int logLevel, HeapTuple *sampleRows, int targetRowCount, - double *totalRowCount, double *deadRows, void *additionalData, bool estimate_table_rownum) + double *totalRowCount, double *deadRows, void *additionalData, + bool estimate_table_rownum) { /* We report "analyze" nothing if additionalData is null. */ if (additionalData == NULL) { @@ -613,9 +769,9 @@ static int distAcquireSampleRows(Relation relation, int logLevel, HeapTuple *sam * Use per-tuple memory context to prevent leak of memory used to read and * parse rows from the file using ReadLineFromFile and FillTupleSlot. */ - tupleContext = AllocSetContextCreate(CurrentMemoryContext, "TEX/CSV OBS temporary context", - ALLOCSET_DEFAULT_MINSIZE, ALLOCSET_DEFAULT_INITSIZE, - ALLOCSET_DEFAULT_MAXSIZE); + tupleContext = + AllocSetContextCreate(CurrentMemoryContext, "TEX/CSV OBS temporary context", ALLOCSET_DEFAULT_MINSIZE, + ALLOCSET_DEFAULT_INITSIZE, ALLOCSET_DEFAULT_MAXSIZE); /* prepare for sampling rows */ selectionState = anl_init_selection_state(targetRowCount); @@ -655,7 +811,8 @@ static int distAcquireSampleRows(Relation relation, int logLevel, HeapTuple *sam * reach the end of the relation. */ if (sampleRowCount < targetRowCount) { - sampleRows[sampleRowCount++] = (HeapTuple)tableam_tops_form_tuple(tupleDescriptor, columnValues, columnNulls, HEAP_TUPLE); + sampleRows[sampleRowCount++] = + (HeapTuple)tableam_tops_form_tuple(tupleDescriptor, columnValues, columnNulls, HEAP_TUPLE); } else { /* * If we need to compute a new S value, we must use the "not yet @@ -675,7 +832,8 @@ static int distAcquireSampleRows(Relation relation, int logLevel, HeapTuple *sam Assert(rowIndex < targetRowCount); heap_freetuple(sampleRows[rowIndex]); - sampleRows[rowIndex] = (HeapTuple)tableam_tops_form_tuple(tupleDescriptor, columnValues, columnNulls, HEAP_TUPLE); + sampleRows[rowIndex] = + (HeapTuple)tableam_tops_form_tuple(tupleDescriptor, columnValues, columnNulls, HEAP_TUPLE); } rowCountToSkip -= 1; } @@ -719,7 +877,17 @@ static int distAcquireSampleRows(Relation relation, int logLevel, HeapTuple *sam (*deadRows) = 0; /* @hdfs dead rows is no means to foreign table */ return sampleRowCount; } - +/* + * 鍔熻兘锛氭鏌ユ槸鍚﹂渶瑕侀夋嫨鎬х殑浜岃繘鍒惰浆鎹 + * + * 鍙傛暟鍒楄〃锛 + * baserel锛氬熀鏈叧绯讳俊鎭 + * foreigntableid锛氬閮ㄨ〃鐨凮ID + * columns锛氶渶瑕侀夋嫨鎬ц浆鎹㈢殑鍒楀悕鍒楄〃锛堣緭鍑哄弬鏁帮級 + * + * 杩斿洖鍊硷細 + * 濡傛灉闇瑕佽繘琛岄夋嫨鎬т簩杩涘埗杞崲锛岃繑鍥瀟rue锛涘惁鍒欒繑鍥瀎alse銆 + */ bool check_selective_binary_conversion(RelOptInfo *baserel, Oid foreigntableid, List **columns) { ForeignTable *table = NULL; @@ -819,6 +987,19 @@ bool check_selective_binary_conversion(RelOptInfo *baserel, Oid foreigntableid, /* * read raw buffer */ +/* + * 鍔熻兘锛氫粠鏂囦欢涓鍙栧師濮嬫暟鎹埌缂撳啿鍖 + * + * 鍙傛暟鍒楄〃锛 + * file锛氭枃浠舵寚閽 + * buf锛氱敤浜庡瓨鍌ㄨ鍙栫殑鏁版嵁鐨勭紦鍐插尯 + * pos锛氭枃浠朵腑鐨勪綅缃紝浠庤浣嶇疆寮濮嬭鍙栨暟鎹 + * len锛氳璇诲彇鐨勬暟鎹暱搴 + * filename锛氭枃浠跺悕锛堢敤浜庨敊璇鐞嗭級 + * + * 杩斿洖鍊硷細 + * 杩斿洖璇诲彇鐨勫瓧鑺傛暟锛屽鏋滃彂鐢熼敊璇紝鍒欐姏鍑洪敊璇苟缁堟绋嬪簭銆 + */ static int getRawBuffer(FILE *file, char *buf, long pos, long len, char *filename) { int bytesread = 0; @@ -831,13 +1012,27 @@ static int getRawBuffer(FILE *file, char *buf, long pos, long len, char *filenam ereport(ERROR, (errcode_for_file_access(), errmsg("could not read from file: %m"))); } - Assert(bytesread == len); + Assert(bytesread == len); // 纭繚璇诲彇鐨勫瓧鑺傛暟绛変簬璇锋眰鐨勯暱搴 return bytesread; } /* * search char from begin to end */ +/* + * 鍔熻兘锛氬湪鏂囦欢涓悜鍓嶆悳绱㈡寚瀹氬瓧绗 + * + * 鍙傛暟鍒楄〃锛 + * file锛氭枃浠舵寚閽 + * buf锛氱敤浜庡瓨鍌ㄨ鍙栫殑鏁版嵁鐨勭紦鍐插尯 + * begin锛氭悳绱㈣寖鍥寸殑璧峰浣嶇疆 + * end锛氭悳绱㈣寖鍥寸殑缁撴潫浣嶇疆 + * fileName锛氭枃浠跺悕锛堢敤浜庨敊璇鐞嗭級 + * searchChar锛氳鎼滅储鐨勫瓧绗 + * + * 杩斿洖鍊硷細 + * 濡傛灉鎵惧埌鎸囧畾瀛楃锛岃繑鍥炲叾鍦ㄦ枃浠朵腑鐨勪綅缃紱鍚﹀垯杩斿洖0銆 + */ static long searchForward(FILE *file, char *buf, long begin, long end, char *fileName, char searchChar) { long readStartPos = end; @@ -873,6 +1068,18 @@ static long searchForward(FILE *file, char *buf, long begin, long end, char *fil /* * Divide file into segments */ +/* + * 鍔熻兘锛氬皢鏂囦欢鍒嗗壊鎴愬涓枃浠舵 + * + * 鍙傛暟鍒楄〃锛 + * fileName锛氳鍒嗗壊鐨勬枃浠跺悕 + * fileSize锛氭枃浠剁殑鎬诲ぇ灏 + * segmentlist锛氬瓨鍌ㄦ枃浠舵鐨勫垪琛紙杈撳嚭鍙傛暟锛 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁板皢鎸囧畾鐨勬枃浠跺垎鍓叉垚澶氫釜鏂囦欢娈碉紝姣忎釜鏂囦欢娈甸兘鍖呭惈鏂囦欢鐨勪竴閮ㄥ垎銆 + * 鏂囦欢娈靛垪琛ㄥ皢浣滀负杈撳嚭鍙傛暟杩斿洖銆 + */ void divideFileSegment(char *fileName, long fileSize, List **segmentlist) { Assert(fileName && segmentlist && fileSize >= 0); @@ -965,6 +1172,15 @@ void divideFileSegment(char *fileName, long fileSize, List **segmentlist) /* * Through each directory to find the matching files, and segment it if the file large than 64MB */ +/* + * 鍔熻兘锛氳幏鍙栨枃浠舵鍒楄〃 + * + * 鍙傛暟鍒楄〃锛 + * urllist锛氬寘鍚枃浠禪RL鐨勫垪琛 + * + * 杩斿洖鍊硷細 + * 杩斿洖涓涓寘鍚枃浠舵鐨勫垪琛ㄣ + */ List *getFileSegmentList(List *urllist) { char *path = NULL; @@ -1001,6 +1217,16 @@ List *getFileSegmentList(List *urllist) /* * assign file segments to data node */ +/* + * 鍔熻兘锛氬皢鏂囦欢娈靛垪琛ㄥ垎閰嶇粰鏁版嵁鑺傜偣浠诲姟鍒楄〃 + * + * 鍙傛暟鍒楄〃锛 + * segmentlist锛氭枃浠舵鍒楄〃 + * dnNames锛氭暟鎹妭鐐瑰悕绉板垪琛 + * + * 杩斿洖鍊硷細 + * 杩斿洖鍖呭惈鏁版嵁鑺傜偣浠诲姟鐨勫垪琛ㄣ + */ List *assignFileSegmentList(List *segmentlist, List *dnNames) { ListCell *lc = NULL; @@ -1333,7 +1559,15 @@ List *assignTaskToDataNode(List *urllist, ImportMode mode, List *nodeList, int d return totalTask; } - +/* + * 鍔熻兘锛氬喅瀹氭槸鍚︽帴鍙椾竴涓敊璇褰 + * + * 鍙傛暟鍒楄〃锛 + * festate锛氬垎甯冨紡瀵煎叆鎵ц鐘舵 + * + * 杩斿洖鍊硷細 + * 濡傛灉闇瑕佷繚瀛橀敊璇褰曚笖灏氭湭杈惧埌鎷掔粷闄愬埗锛屽垯杩斿洖true锛屽惁鍒欒繑鍥瀎alse銆 + */ bool DoAcceptOneError(DistImportExecutionState *festate) { bool do_accept = false; @@ -1345,7 +1579,15 @@ bool DoAcceptOneError(DistImportExecutionState *festate) } return do_accept; } - +/* + * 鍔熻兘锛氬喅瀹氭槸鍚︽帴鍙椾竴涓敊璇褰 + * + * 鍙傛暟鍒楄〃锛 + * cstate锛欳OPY鎿嶄綔鐨勭姸鎬佷俊鎭 + * + * 杩斿洖鍊硷細 + * 濡傛灉闇瑕佽褰曢敊璇俊鎭紙log_errors鎴杔ogErrorsData涓簍rue锛変笖灏氭湭杈惧埌鎷掔粷闄愬埗锛屽垯杩斿洖true锛屽惁鍒欒繑鍥瀎alse銆 + */ bool DoAcceptOneError(CopyState cstate) { bool do_accept = false; @@ -1358,7 +1600,18 @@ bool DoAcceptOneError(CopyState cstate) } return do_accept; } - +/* + * 鍔熻兘锛氬垵濮嬪寲COPY鎿嶄綔鐨勭姸鎬佷俊鎭 + * + * 鍙傛暟鍒楄〃锛 + * cstate锛欳OPY鎿嶄綔鐨勭姸鎬佷俊鎭 + * isImport锛氭寚绀烘槸鍚︽槸瀵煎叆鎿嶄綔 + * rel锛氫笌COPY鎿嶄綔鍏宠仈鐨勫叧绯诲璞 + * raw_query锛氭煡璇㈡爲涓殑鍘熷鑺傜偣 + * queryString锛氬寘鍚獵OPY鎿嶄綔鐨勫師濮嬫煡璇㈠瓧绗︿覆 + * attnamelist锛氶渶瑕佸鐞嗙殑灞炴у悕绉板垪琛 + * options锛欳OPY鎿嶄綔鐨勯夐」鍒楄〃 + */ static void DistBegin(CopyState cstate, bool isImport, Relation rel, Node *raw_query, const char *queryString, List *attnamelist, List *options) { @@ -1460,8 +1713,8 @@ static void DistBegin(CopyState cstate, bool isImport, Relation rel, Node *raw_q * are the same, we must apply pg_any_to_server() to validate data in * multibyte encodings. */ - cstate->need_transcoding = (cstate->file_encoding != GetDatabaseEncoding() || - pg_database_encoding_max_length() > 1); + cstate->need_transcoding = + (cstate->file_encoding != GetDatabaseEncoding() || pg_database_encoding_max_length() > 1); /* See Multibyte encoding comment above */ cstate->encoding_embeds_ascii = PG_ENCODING_IS_CLIENT_ONLY(cstate->file_encoding); @@ -1470,7 +1723,17 @@ static void DistBegin(CopyState cstate, bool isImport, Relation rel, Node *raw_q (void)MemoryContextSwitchTo(oldcontext); } - +/* + * 鍔熻兘锛氬垵濮嬪寲鍒嗗竷寮忓鍏ユ搷浣滅殑鐘舵佷俊鎭 + * + * 鍙傛暟鍒楄〃锛 + * importstate锛氬垎甯冨紡瀵煎叆鎿嶄綔鐨勭姸鎬佷俊鎭 + * rel锛氫笌瀵煎叆鎿嶄綔鍏宠仈鐨勫叧绯诲璞 + * filename锛氬鍏ョ殑鏂囦欢鍚 + * attnamelist锛氶渶瑕佸鐞嗙殑灞炴у悕绉板垪琛 + * options锛氬鍏ユ搷浣滅殑閫夐」鍒楄〃 + * totalTask锛氭荤殑浠诲姟鍒楄〃 + */ void InitDistImport(DistImportExecutionState *importstate, Relation rel, const char *filename, List *attnamelist, List *options, List *totalTask) { @@ -1652,9 +1915,9 @@ static const char *FetchAndCheckFormat(DefElem *defel); static void distExportSwitchSegment(CopyState cstate, Relation rel); #ifndef WIN32 - static const char delimiter = '/'; +static const char delimiter = '/'; #else - static const char delimiter = '\\'; +static const char delimiter = '\\'; #endif static const uint64 distExportMaxSegSize = (1 << 30); @@ -1663,9 +1926,20 @@ static const uint64 distExportMaxSegSize = (1 << 30); * distExportRelUpdatable * Determine whether a foreign table supports INSERT, UPDATE and/or DELETE. */ +/* + * 鍔熻兘锛氭鏌ュ垎甯冨紡澶栭儴琛ㄧ殑鍙洿鏂版 + * + * 鍙傛暟鍒楄〃锛 + * rel锛氳妫鏌ョ殑鍏崇郴瀵硅薄 + * + * 杩斿洖鍊硷細 + * 杩斿洖琛ㄧず鍙洿鏂版х殑浣嶆帺鐮侊紝鏍规嵁鍙敤鐨勫懡浠よ屽畾 + * 浣嶆帺鐮佷负 CMD_INSERT锛岃〃绀哄彲浠ユ墽琛 INSERT 鎿嶄綔 + * 濡傛灉鍏崇郴瀵硅薄涓嶆槸鍒嗗竷寮忓閮ㄨ〃鎴栬呮槸鍙啓妯″紡锛岃繑鍥 0锛岃〃绀轰笉鍙洿鏂 + */ static int distExportRelUpdatable(Relation rel) { - // for dist foreign talbe, only checking table's permition is enough + // 瀵逛簬鍒嗗竷寮忓閮ㄨ〃锛屼粎妫鏌ヨ〃鐨勬潈闄愬嵆鍙 ForeignTable *table = GetForeignTable(RelationGetRelid(rel)); if (table != NULL && table->write_only) return (1 << CMD_INSERT); @@ -1677,61 +1951,109 @@ static int distExportRelUpdatable(Relation rel) * distExportPlan * Plan an INSERT operation on a foreign table */ +/* + * 鍔熻兘锛氱敓鎴愬垎甯冨紡瀵煎叆璁″垝 + * + * 鍙傛暟鍒楄〃锛 + * root锛歅lannerInfo 瀵硅薄锛岀敤浜庢煡璇㈣鍒掔殑淇℃伅 + * plan锛歁odifyTable 璁″垝鑺傜偣锛岃〃绀轰慨鏀硅〃鐨勬搷浣 + * resultRelation锛氱储寮曡〃绀虹粨鏋滃叧绯荤殑浣嶇疆 + * subplan_index锛氬瓙璁″垝鐨勭储寮 + * + * 杩斿洖鍊硷細 + * 杩斿洖涓涓寘鍚 FDW 绉佹湁鏁版嵁鐨勫垪琛 + * 濡傛灉鎿嶄綔鏄洿鏂 (CMD_UPDATE) 鎴栧垹闄 (CMD_DELETE)锛岃繑鍥炰竴涓┖鍒楄〃 (NIL) + * 濡傛灉鎿嶄綔鏄彃鍏 (CMD_INSERT) 骞朵笖浣嶇疆涓嶅湪鏈湴锛屽垯杩斿洖涓涓寘鍚細璇濆瘑閽ュ拰浠诲姟鍒楄〃鐨勫垪琛 + */ static List *distExportPlan(PlannerInfo *root, ModifyTable *plan, Index resultRelation, int subplan_index) { - CmdType operation = plan->operation; - List *fdwPriv = NIL; - DistImportPlanState *planstate = NULL; - RangeTblEntry *rte = NULL; - char *location = NULL; + CmdType operation = plan->operation; // 鑾峰彇鎿嶄綔绫诲瀷 + List *fdwPriv = NIL; // 鐢ㄤ簬瀛樺偍 FDW 绉佹湁鏁版嵁鐨勫垪琛 + DistImportPlanState *planstate = NULL; // 鍒嗗竷寮忓鍏ヨ鍒掔殑鐘舵 + RangeTblEntry *rte = NULL; // 鑼冨洿琛ㄦ潯鐩 + char *location = NULL; // 澶栭儴琛ㄧ殑浣嶇疆 + // 濡傛灉涓嶆槸娴佸紡璁″垝锛屽垯鎶涘嚭閿欒 if (!IS_STREAM_PLAN) - ereport(ERROR, (errcode(ERRCODE_FDW_ERROR), errmsg("Un-support feature"))); + ereport(ERROR, (errcode(ERRCODE_FDW_ERROR), errmsg("Unsupported feature"))); + // 濡傛灉鎿嶄綔鏄洿鏂 (CMD_UPDATE) 鎴栧垹闄 (CMD_DELETE)锛屽垯杩斿洖绌哄垪琛 if (CMD_UPDATE == operation || CMD_DELETE == operation) return NIL; + // 鏂█鎿嶄綔鏄彃鍏 (CMD_INSERT) Assert(CMD_INSERT == operation); + + // 鑾峰彇缁撴灉鍏崇郴鐨勮寖鍥磋〃鏉$洰 rte = planner_rt_fetch(resultRelation, root); + + // 鍒涘缓 DistImportPlanState 瀵硅薄骞跺垵濮嬪寲 planstate = (DistImportPlanState *)palloc0(sizeof(DistImportPlanState)); + + // 鑾峰彇澶栭儴琛ㄧ殑瀵煎叆閫夐」 GetDistImportOptions(rte->relid, planstate); + + // 鑾峰彇澶栭儴琛ㄧ殑浣嶇疆 location = strVal(lfirst(list_head(planstate->source))); + + // 濡傛灉澶栭儴琛ㄤ綅缃笉鍦ㄦ湰鍦 if (!is_local_location(location)) { uint32 distSessionKey; List *tasklist = NIL; // generate session key distSessionKey = generate_unique_id(>_sessionId); + // 灏嗕細璇濆瘑閽ユ坊鍔犲埌 FDW 绉佹湁鏁版嵁鍒楄〃涓 fdwPriv = lappend(fdwPriv, makeDefElem(pstrdup(optSessionKey), (Node *)makeInteger((long)distSessionKey))); // get task list - tasklist = assignTaskToDataNode(planstate->source, MODE_NORMAL, ((Plan *)plan)->exec_nodes->nodeList, 1, - planstate); + tasklist = + assignTaskToDataNode(planstate->source, MODE_NORMAL, ((Plan *)plan)->exec_nodes->nodeList, 1, planstate); + // 灏嗕换鍔″垪琛ㄦ坊鍔犲埌 FDW 绉佹湁鏁版嵁鍒楄〃涓 fdwPriv = lappend(fdwPriv, makeDefElem(pstrdup(optTaskList), (Node *)tasklist)); } - return fdwPriv; + return fdwPriv; // 杩斿洖 FDW 绉佹湁鏁版嵁鍒楄〃 } - +/* + * 鍔熻兘锛氬垵濮嬪寲鍒嗗竷寮忓鍑 + * + * 鍙傛暟鍒楄〃锛 + * mtstate锛歁odifyTableState 瀵硅薄锛岀敤浜庝慨鏀硅〃鐨勭姸鎬 + * rinfo锛歊esultRelInfo 瀵硅薄锛岃〃绀虹粨鏋滃叧绯荤殑淇℃伅 + * fdw_private锛欶DW 绉佹湁鏁版嵁鍒楄〃 + * subplan_index锛氬瓙璁″垝鐨勭储寮 + * eflags锛氭墽琛屾爣蹇 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庡垵濮嬪寲鍒嗗竷寮忓鍑烘搷浣滐紝鏍规嵁鎵ц鏍囧織鍜屽閮ㄨ〃鐨勪綅缃喅瀹氬浣曞鐞嗗鍑恒 + * 濡傛灉鎵ц鏍囧織鍖呮嫭 EXEC_FLAG_EXPLAIN_ONLY锛屽垯涓嶆墽琛屼换浣曟搷浣溿 + * 鍚﹀垯锛屾牴鎹閮ㄨ〃鐨勪綅缃喅瀹氭槸鏈湴瀵煎嚭杩樻槸杩滅▼瀵煎嚭锛屽苟鎵ц鐩稿簲鐨勬搷浣溿 + */ static void distExportBegin(ModifyTableState *mtstate, ResultRelInfo *rinfo, List *fdw_private, int subplan_index, int eflags) { + // 濡傛灉鎵ц鏍囧織鍖呮嫭 EXEC_FLAG_EXPLAIN_ONLY锛屽垯杩斿洖锛屼笉鎵ц浠讳綍鎿嶄綔 if ((uint32)eflags & EXEC_FLAG_EXPLAIN_ONLY) return; - List *options = NIL; - char *location = NULL; - Relation rel = rinfo->ri_RelationDesc; - bool isRemote = false; - uint32 sessionKey = 0; - List *tasklist = NIL; + List *options = NIL; // 澶栭儴琛ㄧ殑閫夐」鍒楄〃 + char *location = NULL; // 澶栭儴琛ㄧ殑浣嶇疆 + Relation rel = rinfo->ri_RelationDesc; // 缁撴灉鍏崇郴鐨勬弿杩扮 + bool isRemote = false; // 鏄惁涓鸿繙绋嬪鍑 + uint32 sessionKey = 0; // 浼氳瘽瀵嗛挜 + List *tasklist = NIL; // 浠诲姟鍒楄〃 + // 鑾峰彇澶栭儴琛ㄧ殑浣嶇疆鍜岄夐」 distGetOptions(RelationGetRelid(rel), &location, &options); + // 鍒ゆ柇鏄惁涓鸿繙绋嬪鍑 isRemote = !is_local_location(location); // Add decrpyt function for obs access key and security access key in obs options decryptOBSForeignTableOption(&options); + // 榛樿鐨勮緭鍑烘牸寮忓悗缂涓 strTextFormat const char *suffix = strTextFormat; + // 妫鏌ュ閮ㄨ〃閫夐」锛岃幏鍙栬緭鍑烘牸寮忓悗缂鍜屾牸寮忓寲鍣ㄩ夐」 ListCell *lc = NULL; foreach (lc, options) { DefElem *defel = (DefElem *)lfirst(lc); @@ -1741,13 +2063,16 @@ static void distExportBegin(ModifyTableState *mtstate, ResultRelInfo *rinfo, Lis UntransformFormatterOption(defel); } + // 閬嶅巻 FDW 绉佹湁鏁版嵁鍒楄〃锛岃幏鍙栦細璇濆瘑閽ュ拰浠诲姟鍒楄〃 foreach (lc, fdw_private) { DefElem *def = (DefElem *)lfirst(lc); if (strcasecmp(def->defname, optSessionKey) == 0) { if (IS_PGXC_COORDINATOR) { + // 濡傛灉鏄崗璋冭妭鐐癸紝鐢熸垚浼氳瘽瀵嗛挜骞惰缃埌 FDW 绉佹湁鏁版嵁涓 sessionKey = generate_unique_id(>_sessionId); def->arg = (Node *)makeInteger((long)sessionKey); } else { + // 濡傛灉鏄暟鎹妭鐐癸紝浠 FDW 绉佹湁鏁版嵁涓幏鍙栦細璇濆瘑閽 sessionKey = (uint32)intVal(def->arg); } ereport(DEBUG1, (errcode(ERRCODE_DEBUG), errmsg("Session id: %u", sessionKey))); @@ -1756,32 +2081,41 @@ static void distExportBegin(ModifyTableState *mtstate, ResultRelInfo *rinfo, Lis tasklist = (List *)def->arg; } + // 鍙嶅簭鍒楀寲澶栭儴琛ㄧ殑浣嶇疆锛岀敓鎴愪綅缃垪琛 List *locations = DeserializeLocations(location); Assert(list_length(locations) >= 1); // coordinator doesn't create any directory or file, and has no file handle. + // 濡傛灉鏄祦寮忚鍒掓垨杩滅▼瀵煎嚭锛屾墽琛岃繙绋嬪鍑烘搷浣 if (IS_STREAM_PLAN || isRemote) { char *filename = isRemote ? location : strVal(lfirst(list_head(locations))); + // 鍒濆鍖栧閮ㄥ鍑猴紝骞跺皢缁撴灉瀛樺偍鍒扮粨鏋滃叧绯荤殑 FDW 鐘舵佷腑 rinfo->ri_FdwState = (void *)beginExport(rel, filename, options, isRemote, sessionKey, tasklist); } else if (!isRemote) { const char *userExportDir = strVal(lfirst(list_head(locations))); + // 濡傛灉澶栭儴瀵煎嚭鐩綍浠 'file://' 鍓嶇紑寮澶达紝鍒欏幓闄ゅ墠缂 if (strncmp(userExportDir, LOCAL_PREFIX, LOCAL_PREFIX_LEN) == 0) { // remove the prefix string 'file://' userExportDir = userExportDir + LOCAL_PREFIX_LEN; } + // 鍒濆鍖栨湰鍦板鍑虹幆澧 InitExportEnvirnment(userExportDir); // outfile isn't allocated in CopyState memory context, so free it by calling pfree(); // later, when switching to new segment file, do the same thing again; char *relname = get_rel_name(RelationGetRelid(rel)); char *outfile = distExportNextFileName(t_thrd.bulk_cxt.distExportDataDir, relname, suffix); + // 鍒濆鍖栧閮ㄥ鍑猴紝骞跺皢缁撴灉瀛樺偍鍒扮粨鏋滃叧绯荤殑 FDW 鐘舵佷腑 rinfo->ri_FdwState = (void *)beginExport(rel, outfile, options, false, sessionKey, tasklist); + // 澶勭悊瀵煎嚭鏂囦欢澶撮儴 ProcessFileHeader((CopyState)rinfo->ri_FdwState); + // 閲婃斁鏂囦欢鍚嶅唴瀛 pfree(outfile); } #ifndef ENABLE_MULTIPLE_NODES + // 楠岃瘉鏄惁鏀寔 GDS (Gauss Data Service) CopyState cstate_for_verify = (CopyState)rinfo->ri_FdwState; if (cstate_for_verify->remoteExport && cstate_for_verify->copy_dest == COPY_GDS) { ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("Un-supported feature"), @@ -1789,7 +2123,22 @@ static void distExportBegin(ModifyTableState *mtstate, ResultRelInfo *rinfo, Lis } #endif } - +/* + * 鍔熻兘锛氭墽琛屽垎甯冨紡瀵煎嚭鎿嶄綔 + * + * 鍙傛暟鍒楄〃锛 + * estate锛欵State 瀵硅薄锛岀敤浜庢墽琛岃〃杈惧紡鍜岃鍒 + * resultRelInfo锛歊esultRelInfo 瀵硅薄锛岃〃绀虹粨鏋滃叧绯荤殑淇℃伅 + * slot锛歍upleTableSlot 瀵硅薄锛岃〃绀哄厓缁勬暟鎹殑妲 + * planSlot锛歍upleTableSlot 瀵硅薄锛岃〃绀鸿鍒掓暟鎹殑妲 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁版墽琛屽垎甯冨紡瀵煎嚭鎿嶄綔锛屽皢鍏冪粍鏁版嵁鍐欏叆澶栭儴瀵煎嚭鏂囦欢銆 + * 棣栧厛妫鏌ュ綋鍓嶅鍑烘枃浠剁殑澶у皬鏄惁瓒呰繃鎸囧畾鐨勬渶澶у垎娈靛ぇ灏忥紙distExportMaxSegSize锛夈 + * 濡傛灉瓒呰繃锛屽垯鍒囨崲鍒版柊鐨勫垎娈垫枃浠躲 + * 鐒跺悗璋冪敤 execExport 鍑芥暟灏嗗厓缁勬暟鎹啓鍏ュ鍑烘枃浠躲 + * 鏈鍚庤繑鍥炲厓缁勬暟鎹Ы銆 + */ static TupleTableSlot *distExportExec(EState *estate, ResultRelInfo *resultRelInfo, TupleTableSlot *slot, TupleTableSlot *planSlot) { @@ -1804,27 +2153,55 @@ static TupleTableSlot *distExportExec(EState *estate, ResultRelInfo *resultRelIn exportResetTotalSize(cstate); } + // 鎵ц瀵煎嚭鎿嶄綔锛屽皢鍏冪粍鏁版嵁鍐欏叆瀵煎嚭鏂囦欢 execExport(cstate, slot); + // 杩斿洖鍏冪粍鏁版嵁妲 return slot; } +/* + * 鍔熻兘锛氱粨鏉熷垎甯冨紡瀵煎嚭鎿嶄綔 + * + * 鍙傛暟鍒楄〃锛 + * estate锛欵State 瀵硅薄锛岀敤浜庢墽琛岃〃杈惧紡鍜岃鍒 + * resultRelInfo锛歊esultRelInfo 瀵硅薄锛岃〃绀虹粨鏋滃叧绯荤殑淇℃伅 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庣粨鏉熷垎甯冨紡瀵煎嚭鎿嶄綔锛岄噴鏀剧浉鍏宠祫婧愩傚畠妫鏌 resultRelInfo 缁撴瀯涓殑 ri_FdwState + * 鏄惁涓洪潪绌猴紝濡傛灉鏄紝鍒欒皟鐢 endExport 鍑芥暟缁撴潫瀵煎嚭鎿嶄綔骞堕噴鏀捐祫婧愩 + */ static void distExportEnd(EState *estate, ResultRelInfo *resultRelInfo) { if (resultRelInfo->ri_FdwState != NULL) { + // 璋冪敤 endExport 鍑芥暟缁撴潫瀵煎嚭鎿嶄綔骞堕噴鏀捐祫婧 endExport((CopyState)resultRelInfo->ri_FdwState); } } - +/* + * 鍔熻兘锛氬垏鎹㈠埌涓嬩竴涓鏂囦欢杩涜瀵煎嚭 + * + * 鍙傛暟鍒楄〃锛 + * cstate锛欳opyState 瀵硅薄锛岃〃绀哄鍒舵搷浣滅殑鐘舵 + * rel锛歊elation 瀵硅薄锛岃〃绀烘鍦ㄥ鍑虹殑鍏崇郴 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庡垏鎹㈠埌涓嬩竴涓鏂囦欢锛屼互缁х画鏁版嵁瀵煎嚭銆傚畠棣栧厛鑾峰彇鍏崇郴鐨勫鍑洪夐」锛屾煡鎵惧鍑烘牸寮忛夐」锛 + * 骞舵嵁姝ょ‘瀹氫笅涓涓鏂囦欢鐨勬枃浠跺悕鍚庣紑銆傜劧鍚庯紝瀹冭皟鐢 exportAllocNewFile 鍑芥暟鏉ュ垎閰嶆柊鐨勬枃浠讹紝 + * 鐢ㄤ簬鎺ヤ笅鏉ョ殑瀵煎嚭鎿嶄綔銆 + */ static void distExportSwitchSegment(CopyState cstate, Relation rel) { List *options = NULL; char *location = NULL; + // 鑾峰彇鍏崇郴鐨勫鍑洪夐」 distGetOptions(RelationGetRelid(rel), &location, &options); const char *suffix = strTextFormat; ListCell *lc = NULL; + // 鏌ユ壘瀵煎嚭鏍煎紡閫夐」 foreach (lc, options) { DefElem *defel = (DefElem *)lfirst(lc); + // 濡傛灉閫夐」鐨勫悕绉颁互 "FORMAT" 寮澶达紝鍒欐彁鍙栨枃浠跺悕鍚庣紑 if (strncasecmp(defel->defname, optFormat, 6) == 0) { suffix = FetchAndCheckFormat(defel); break; @@ -1833,12 +2210,28 @@ static void distExportSwitchSegment(CopyState cstate, Relation rel) // switch to next segment file to copy to char *relname = get_rel_name(RelationGetRelid(rel)); + // 鐢熸垚涓嬩竴涓鏂囦欢鐨勬枃浠跺悕 char *outfile = distExportNextFileName(t_thrd.bulk_cxt.distExportDataDir, relname, suffix); + // 鍒嗛厤鏂扮殑鏂囦欢锛岀敤浜庢帴涓嬫潵鐨勫鍑烘搷浣 exportAllocNewFile(cstate, outfile); + // 閲婃斁鏂囦欢鍚嶅唴瀛 pfree(outfile); } // File Name: table name + txid + datanode id + segment no + suffix +/* + * 鍔熻兘锛氱敓鎴愪笅涓涓鏂囦欢鐨勬枃浠跺悕 + * + * 鍙傛暟鍒楄〃锛 + * abspath锛氳〃绀虹粷瀵硅矾寰勭殑瀛楃涓 + * relname锛氳〃绀哄叧绯诲悕绉扮殑瀛楃涓 + * suffix锛氳〃绀烘枃浠跺悕鍚庣紑鐨勫瓧绗︿覆 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庣敓鎴愪笅涓涓鏂囦欢鐨勬枃浠跺悕锛屼互鐢ㄤ簬鏁版嵁瀵煎嚭鎿嶄綔銆傚湪鍚屼竴瀵煎嚭浜嬪姟涓紝娈电紪鍙凤紙segno锛 + * 鏄敓鎴愭枃浠跺悕鐨勫敮涓鍙橀噺銆 (abspath, relname, distExportCurrXid) 鍙敤浜庢爣璇嗗敮涓鐨勫鍑烘搷浣溿 + * (distExportTimestampStr, segno) 鍙敤浜庨伩鍏嶇浉鍚屾枃浠跺悕鐨勫啿绐併 + */ static char *distExportNextFileName(const char *abspath, const char *relname, const char *suffix) { // in the same export transaction, segment no is the only var for filenmae. @@ -1855,44 +2248,90 @@ static char *distExportNextFileName(const char *abspath, const char *relname, co return pstrdup(temp); } +/* + * 鍔熻兘锛氳幏鍙栧苟妫鏌ュ鍑烘牸寮忛夐」 + * + * 鍙傛暟鍒楄〃锛 + * defel锛氭寚鍚戝鍑烘牸寮忛夐」鐨 DefElem 缁撴瀯 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庤幏鍙栧苟妫鏌ュ鍑烘牸寮忛夐」锛岀‘淇濆畠鐨勫兼槸鏈夋晥鐨勫鍑烘牸寮忎箣涓锛"csv" 鎴 "text"锛夈 + * 濡傛灉鏍煎紡鏃犳晥锛屽皢鐢熸垚涓涓敊璇姤鍛娿傚鏋滄牸寮忔湁鏁堬紝鍒欒繑鍥炴牸寮忓瓧绗︿覆銆 + */ static const char *FetchAndCheckFormat(DefElem *defel) { + // 鑾峰彇瀵煎嚭鏍煎紡閫夐」鐨勫瓧绗︿覆鍊 char *format = defGetString(defel); + + // 妫鏌ユ牸寮忔槸鍚︿负 "csv"锛堜笉鍖哄垎澶у皬鍐欙級 if (0 == strncasecmp(format, strCsvFormat, 3)) return strCsvFormat; + // 妫鏌ユ牸寮忔槸鍚︿负 "text"锛堜笉鍖哄垎澶у皬鍐欙級 if (0 == strncasecmp(format, strTextFormat, 4)) return strTextFormat; - if (0 == strncasecmp(format, strFixedFormat, 5)) - return strFixedFormat; - + // 濡傛灉鏍煎紡鏃犳晥锛岀敓鎴愰敊璇姤鍛婂苟鎶涘嚭寮傚父 ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("only both text && csv formats are supported for foreign table"))); + + // 杩斿洖榛樿鐨勬枃鏈牸寮忥紝杩欓噷鐨勮繑鍥炶鍙ュ疄闄呬笂涓嶄細琚墽琛 return strTextFormat; /* make complier mute */ } +/* + * 鍔熻兘锛氱敓鎴愭椂闂存埑瀛楃涓 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庣敓鎴愪竴涓椂闂存埑瀛楃涓诧紝琛ㄧず褰撳墠鏃ユ湡鍜屾椂闂淬傚畠閫氳繃鑾峰彇褰撳墠鏃堕棿锛坱ime_t 绫诲瀷锛 + * 骞跺皢鍏舵牸寮忓寲涓烘寚瀹氭牸寮忕殑瀛楃涓诧紝鐒跺悗灏嗙粨鏋滃瓨鍌ㄥ湪鍏ㄥ眬鍙橀噺 t_thrd.bulk_cxt.distExportTimestampStr 涓 + * 濡傛灉鐢熸垚鐨勫瓧绗︿覆闀垮害涓嶇瓑浜 14锛屽皢鐢熸垚涓涓敊璇姤鍛娿 + */ static void getTimestampStr(void) { + // 鐢ㄤ簬瀛樺偍褰撳墠鏃堕棿鐨 time_t 鍙橀噺 time_t currTime; + + // 鐢ㄤ簬瀛樺偍鏃堕棿缁撴瀯鐨勭粨鏋 struct tm result; + + // 鑾峰彇褰撳墠鏃堕棿 currTime = time(NULL); + + // 灏嗗綋鍓嶆椂闂磋浆鎹负鏈湴鏃堕棿锛屽苟瀛樺偍鍦 result 缁撴瀯涓 localtime_r(&currTime, &result); + // 浣跨敤 strftime 鍑芥暟灏嗘椂闂存牸寮忓寲涓哄瓧绗︿覆锛屽苟杩斿洖鐢熸垚鐨勫瓧绗︽暟 size_t num = strftime(t_thrd.bulk_cxt.distExportTimestampStr, 15, "%Y%m%d%H%M%S", &result); + + // 妫鏌ョ敓鎴愮殑瀛楃涓查暱搴︽槸鍚︿负 14 if (num != 14) { ereport(ERROR, (errcode(ERRCODE_DATA_EXCEPTION), errmsg("invalid timestamp string length"))); } + // 鍦ㄧ敓鎴愮殑瀛楃涓叉湯灏炬坊鍔 null 缁堟绗 t_thrd.bulk_cxt.distExportTimestampStr[num] = '\0'; } - +/* + * 鍔熻兘锛氭鏌ュ苟鑾峰彇鐢ㄦ埛瀵煎嚭鐩綍 + * + * 鍙傛暟鍒楄〃锛 + * userExportDir锛氱敤鎴锋寚瀹氱殑瀵煎嚭鐩綍鐨勭粷瀵硅矾寰 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庢鏌ョ敤鎴锋寚瀹氱殑瀵煎嚭鐩綍鏄惁瀛樺湪锛屽苟灏嗗叾瀛樺偍鍦ㄥ叏灞鍙橀噺 t_thrd.bulk_cxt.distExportDataDir 涓 + * 鐢ㄦ埛瀵煎嚭鐩綍蹇呴』宸茬粡瀛樺湪锛屽苟涓旀槸涓涓洰褰曡屼笉鏄枃浠躲傚嚱鏁拌繕纭繚 distExportDataDir 浠ョ洰褰曞垎闅旂缁撳熬锛 + * 骞舵鏌ュ鍑虹洰褰曡矾寰勭殑闀垮害鏄惁瓒呰繃浜嗘渶澶ч檺鍒躲 + */ static void CheckAndGetUserExportDir(const char *userExportDir) { // user must have created data directory, otherwise error reported. // the filepath user defined must be an existing absolute path. + // 鐢ㄤ簬瀛樺偍鏂囦欢鐘舵佺殑缁撴瀯浣 struct stat st; + // 鐢ㄤ簬澶勭悊瀛楃涓叉搷浣滅殑閿欒鐮 errno_t rc = EOK; + // 浣跨敤 stat 鍑芥暟妫鏌ョ敤鎴峰鍑虹洰褰曟槸鍚﹀瓨鍦紝骞跺鐞嗙浉鍏抽敊璇 if (stat(userExportDir, &st) != 0 && errno != EEXIST) { ereport(ERROR, (errcode_for_file_access(), errmsg("%s doesn't exist, please create it first", userExportDir))); } else if (!S_ISDIR(st.st_mode)) { @@ -1916,10 +2355,22 @@ static void CheckAndGetUserExportDir(const char *userExportDir) ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("location filepath is too long when importing data to foreign table"))); } - +/* + * 鍔熻兘锛氬鏋滃繀瑕侊紝鍒涘缓鐩綍 + * + * 鍙傛暟鍒楄〃锛 + * mydir锛氳鍒涘缓鐨勭洰褰曠殑缁濆璺緞 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庢鏌ユ寚瀹氱殑鐩綍鏄惁瀛樺湪锛屽鏋滀笉瀛樺湪鍒欏垱寤恒傚鏋滅洰褰曞凡缁忓瓨鍦ㄤ絾涓嶆槸鐩綍绫诲瀷锛屽皢鎶ラ敊銆 + * 鍑芥暟棣栧厛浣跨敤 stat 鍑芥暟妫鏌ョ洰褰曟槸鍚﹀瓨鍦紝濡傛灉瀛樺湪浣嗕笉鏄洰褰曠被鍨嬶紝灏嗘姤閿欍傚鏋滅洰褰曚笉瀛樺湪锛 + * 灏嗕娇鐢 mkdir 鍑芥暟鍒涘缓鐩綍銆傚鏋滅洰褰曞凡缁忚鍏朵粬绾跨▼鍒涘缓锛屽嚱鏁颁細鍐嶆妫鏌ョ洰褰曟槸鍚﹀瓨鍦ㄤ互閬垮厤绔炴佹潯浠躲 + */ static void CreateDirIfNecessary(const char *mydir) { + // 鐢ㄤ簬瀛樺偍鏂囦欢鐘舵佺殑缁撴瀯浣 struct stat st; + // 浣跨敤 stat 鍑芥暟妫鏌ョ洰褰曟槸鍚﹀瓨鍦 if (0 == stat(mydir, &st)) { if (!S_ISDIR(st.st_mode)) ereport(ERROR, (errcode_for_file_access(), @@ -1933,30 +2384,49 @@ static void CreateDirIfNecessary(const char *mydir) if ((0 != mkdir(t_thrd.bulk_cxt.distExportDataDir, S_IRWXU)) && (errno != EEXIST)) ereport(ERROR, (errcode_for_file_access(), errmsg("could not create directory \"%s\": %m", mydir))); } - +/* + * 鍔熻兘锛氬垵濮嬪寲瀵煎嚭鐜 + * + * 鍙傛暟鍒楄〃锛 + * userExportDir锛氱敤鎴锋寚瀹氱殑瀵煎嚭鐩綍鐨勭粷瀵硅矾寰 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庡湪寮濮嬫柊鐨勪簨鍔℃椂閲嶇疆鎵鏈夊鍑虹幆澧冿紝浠ュ噯澶囨墽琛屽鍑烘搷浣溿傚鏋滃綋鍓嶄簨鍔′笌涓婁竴娆″鍑烘搷浣滅殑 + * 浜嬪姟涓嶅悓锛屽嚱鏁板皢閲嶇疆鐜锛屽寘鎷鍑虹殑娈垫枃浠剁紪鍙枫佸綋鍓嶄簨鍔$紪鍙枫佹椂闂存埑绛夈傚嚱鏁拌繕浼氭鏌ュ拰鑾峰彇 + * 鐢ㄦ埛鎸囧畾鐨勫鍑虹洰褰曪紝骞跺垱寤哄繀瑕佺殑鐩綍缁撴瀯锛屼互渚垮瓨鍌ㄥ鍑烘枃浠躲 + */ static void InitExportEnvirnment(const char *userExportDir) { // reset all environments to run exporting when start a new transaction TransactionId curXid = GetCurrentTransactionId(); + // 鐢ㄤ簬瀛楃涓叉搷浣滅殑杩斿洖鐮 errno_t rc = EOK; int ret; + // 濡傛灉褰撳墠浜嬪姟涓庝笂涓娆″鍑烘搷浣滅殑浜嬪姟涓嶅悓锛屾墽琛岀幆澧冮噸缃 if (t_thrd.bulk_cxt.distExportCurrXid != curXid) { // segment number alwarys increases by 1 within the same transaction, // even though there are one or more export actions in this transaction. t_thrd.bulk_cxt.distExportNextSegNo = 0; t_thrd.bulk_cxt.distExportCurrXid = curXid; + // 鑾峰彇褰撳墠鏃堕棿鐨勬椂闂存埑瀛楃涓诧紝鏍煎紡涓"YYYYMMDDHHMMSS" getTimestampStr(); + // 妫鏌ュ苟鑾峰彇鐢ㄦ埛鎸囧畾鐨勫鍑虹洰褰 CheckAndGetUserExportDir(userExportDir); + // 鑾峰彇褰撳墠瀵煎嚭鐩綍鐨勯暱搴 int lenOfDirName = strlen(t_thrd.bulk_cxt.distExportDataDir); + // 瀹氫箟椤剁骇鐩綍鍚嶇О鐨勯暱搴 int topDirLen = 8; char topDir[topDirLen + 1]; + // 浠庢椂闂存埑瀛楃涓蹭腑鑾峰彇鍓 8 涓瓧绗︿綔涓洪《绾х洰褰曞悕绉 rc = strncpy_s(topDir, topDirLen + 1, t_thrd.bulk_cxt.distExportTimestampStr, topDirLen); securec_check(rc, "\0", "\0"); topDir[topDirLen] = '\0'; + // 鑾峰彇褰撳墠鑺傜偣鍚嶇О鐨勯暱搴 int lenOfNodeName = (int)strlen(g_instance.attr.attr_common.PGXCNodeName); + // 濡傛灉瀵煎嚭鐩綍鐨勯暱搴﹀姞涓婇《绾х洰褰曞悕绉伴暱搴︺佽妭鐐瑰悕绉伴暱搴﹀拰鍒嗛殧绗︾殑闀垮害灏忎簬鏈澶ц矾寰勯暱搴 if (lenOfDirName + topDirLen + lenOfNodeName + 2 < MAX_PATH_LEN) { // set the 1-level directory and create it if necessary. // it's named by local date, excluding time info (hours, minutes or seconds). @@ -1969,6 +2439,7 @@ static void InitExportEnvirnment(const char *userExportDir) // set the 2-level directory and create it if necessary. // it's named by node name. + // 璁剧疆浜岀骇鐩綍骞跺湪蹇呰鏃跺垱寤哄畠锛屼互鑺傜偣鍚嶇О鍛藉悕 ret = strcat_s(t_thrd.bulk_cxt.distExportDataDir, MAX_PATH_LEN, g_instance.attr.attr_common.PGXCNodeName); securec_check(ret, "\0", "\0"); lenOfDirName += lenOfNodeName; @@ -1976,30 +2447,46 @@ static void InitExportEnvirnment(const char *userExportDir) t_thrd.bulk_cxt.distExportDataDir[lenOfDirName] = '\0'; CreateDirIfNecessary(t_thrd.bulk_cxt.distExportDataDir); } else + // 瀵煎嚭鐩綍璺緞杩囬暱锛屽鑷磋秴鍑烘渶澶ц矾寰勯暱搴︼紝鎶ラ敊 ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("location filepath is too long when importing data to foreign table"))); } } - +/* + * 鍔熻兘锛氳浆鎹㈠閮ㄨ〃鐨勬牸寮忓櫒閫夐」 + * + * 鍙傛暟鍒楄〃锛 + * stmt锛欳reateForeignTableStmt 瀵硅薄锛岃〃绀哄垱寤哄閮ㄨ〃鐨勮鍙 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庤浆鎹㈠閮ㄨ〃鍒楀畾涔変腑鐨勬牸寮忓寲閫夐」涓轰竴缁勯夐」锛屽苟灏嗗叾娣诲姞鍒板閮ㄨ〃鐨勯夐」鍒楄〃涓傛牸寮忓寲閫夐」 + * 閫氬父鐢ㄤ簬鎸囧畾鍒楃殑鏍煎紡鍖栨柟寮忥紝濡傚垪鍚嶃佷綅缃佸浐瀹氶暱搴︾瓑淇℃伅銆傝繖浜涢夐」鍙互鐢ㄤ簬鑷畾涔夊閮ㄨ〃鐨勬暟鎹牸寮 + * 浠ヤ究涓庡閮ㄦ暟鎹簮鍏煎銆 + */ static void TransformFormatterOptions(CreateForeignTableStmt *stmt) { ListCell *lc = NULL; - StringInfo str = makeStringInfo(); - bool hasFormatter = false; + StringInfo str = makeStringInfo(); // 鐢ㄤ簬鏋勫缓鏍煎紡鍖栭夐」瀛楃涓 + bool hasFormatter = false; // 鏍囪鏄惁瀛樺湪鏍煎紡鍖栭夐」 + // 閬嶅巻澶栭儴琛ㄥ垪瀹氫箟鍒楄〃 foreach (lc, stmt->base.tableElts) { ColumnDef *coldef = (ColumnDef *)lfirst(lc); + // 濡傛灉鍒楀畾涔変腑鍖呭惈浣嶇疆淇℃伅 if (coldef->position) { Position *pos = coldef->position; + // 濡傛灉涓嶆槸绗竴涓牸寮忓寲閫夐」锛屾坊鍔犲垎闅旂 '.' if (lc != list_head(stmt->base.tableElts)) appendStringInfoChar(str, '.'); + // 鏋勫缓鏍煎紡鍖栭夐」瀛楃涓诧紝鍖呮嫭鍒楀悕銆佷綅缃拰鍥哄畾闀垮害 appendStringInfo(str, "%s(%d,%d)", pos->colname, pos->position, pos->fixedlen); hasFormatter = true; } } + // 濡傛灉瀛樺湪鏍煎紡鍖栭夐」锛屽皢鍏舵坊鍔犲埌澶栭儴琛ㄧ殑閫夐」鍒楄〃涓 if (hasFormatter) stmt->options = lappend(stmt->options, makeDefElem(pstrdup(optFormatter), (Node *)makeString(str->data))); } @@ -2008,23 +2495,42 @@ static void TransformFormatterOptions(CreateForeignTableStmt *stmt) * brief: Validate table definition * input param @obj: A Obj including infomation to validate when alter tabel and create table. */ -static void distValidateAlterTableStmt(Node* Obj) +/* + * 鍔熻兘锛氶獙璇 ALTER TABLE 璇彞鏄惁鍚堟硶 + * + * 鍙傛暟鍒楄〃锛 + * Obj锛歂ode 瀵硅薄锛岃〃绀 ALTER TABLE 璇彞 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庨獙璇 ALTER TABLE 璇彞鏄惁鍚堟硶銆傚畠棣栧厛鑾峰彇鐩爣琛ㄧ殑 OID锛屽苟妫鏌ョ洰鏍囪〃鏄惁涓 OBS 澶栭儴琛ㄣ + * 濡傛灉鐩爣琛ㄦ槸 OBS 澶栭儴琛紝鍒欏彧鍏佽鎵ц鐗瑰畾绫诲瀷鐨 ALTER TABLE 瀛愬懡浠わ紝鍚﹀垯鍏佽鎵ц鍏朵粬绫诲瀷鐨 ALTER TABLE 瀛愬懡浠ゃ + * 姝ゅ锛屽嚱鏁拌繕妫鏌ユ槸鍚﹀瓨鍦ㄤ笉鏀寔鐨勯夐」锛屽苟绂佹璁剧疆銆佹坊鍔犳垨鍒犻櫎 error_table 鍜 write_only 閫夐」銆 + */ +static void distValidateAlterTableStmt(Node *Obj) { - ListCell* lc = NULL; - AlterTableStmt* stmt = (AlterTableStmt*)Obj; + ListCell *lc = NULL; + AlterTableStmt *stmt = (AlterTableStmt *)Obj; + // 鑾峰彇鐩爣琛ㄧ殑 OID Oid relId = RangeVarGetRelid(stmt->relation, NoLock, true); + // 妫鏌ョ洰鏍囪〃鏄惁涓 OBS 澶栭儴琛 bool obsTbl = IS_OBS_CSV_TXT_FOREIGN_TABLE(relId); + // 閬嶅巻 ALTER TABLE 瀛愬懡浠ゅ垪琛 foreach (lc, stmt->cmds) { - AlterTableCmd* cmd = (AlterTableCmd*)lfirst(lc); + AlterTableCmd *cmd = (AlterTableCmd *)lfirst(lc); + + // 濡傛灉鐩爣琛ㄦ槸 OBS 澶栭儴琛 if (obsTbl) { + // 鍙厑璁告墽琛岀壒瀹氱被鍨嬬殑 ALTER TABLE 瀛愬懡浠 if (!DIST_OBS_SUPPORT_AT_CMD(cmd->subtype)) { ereport(ERROR, (errcode(ERRCODE_FDW_ERROR), errmsg("Un-support feature"), errdetail("target table is a foreign table"))); } } else { + // 鐩爣琛ㄤ笉鏄 OBS 澶栭儴琛紝鍏佽鎵ц鍏朵粬绫诲瀷鐨 ALTER TABLE 瀛愬懡浠 if (!FOREIGNTABLE_SUPPORT_AT_CMD(cmd->subtype)) { + // 浣嗙姝㈡墽琛屼笉鏀寔鐨 ALTER TABLE 瀛愬懡浠わ紝闄ら潪鏄坊鍔犵储寮曟垨鍒犻櫎绾︽潫 if (!(AT_AddIndex == cmd->subtype || AT_DropConstraint == cmd->subtype)) { ereport(ERROR, (errcode(ERRCODE_FDW_ERROR), errmsg("Un-support feature"), errdetail("target table is a foreign table"))); @@ -2034,10 +2540,11 @@ static void distValidateAlterTableStmt(Node* Obj) /* error_table, write_only can not SET, ADD or DROP by ALTER FOREIGN TABLE OPTIONS */ if (cmd->subtype == AT_GenericOptions) { - List* defList = (List*)cmd->def; - ListCell* deflc = NULL; + List *defList = (List *)cmd->def; + ListCell *deflc = NULL; foreach (deflc, defList) { - DefElem* def = (DefElem*)lfirst(deflc); + DefElem *def = (DefElem *)lfirst(deflc); + // 绂佹璁剧疆銆佹坊鍔犳垨鍒犻櫎 error_table 鍜 write_only 閫夐」 if (strcmp(def->defname, optErrorRel) == 0 || strcmp(def->defname, optWriteOnly) == 0) { ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("Invalid option %s", def->defname))); } @@ -2045,84 +2552,117 @@ static void distValidateAlterTableStmt(Node* Obj) } } } - -static void distValidateCreateForeignTableStmt(Node* Obj) +/* + * 鍔熻兘锛氶獙璇 CREATE FOREIGN TABLE 璇彞鏄惁鍚堟硶 + * + * 鍙傛暟鍒楄〃锛 + * Obj锛歂ode 瀵硅薄锛岃〃绀 CREATE FOREIGN TABLE 璇彞 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庨獙璇 CREATE FOREIGN TABLE 璇彞鏄惁鍚堟硶銆傚畠棣栧厛妫鏌ュ垎甯冪被鍨嬫槸鍚︿负 ROUNDROBIN锛 + * 濡傛灉涓嶆槸锛屽垯鎶ラ敊鎻愮ず鍙敮鎸 ROUNDROBIN 鍒嗗竷绫诲瀷銆傜劧鍚庯紝鍑芥暟楠岃瘉鎸囧畾鐨勯夐」鏄惁鏈夋晥锛 + * 骞舵彁渚涙湁鏁堥夐」鐨勬彁绀恒傛帴鐫锛屽嚱鏁版鏌ユ槸鍚︽寚瀹氫簡 error_relation锛屽鏋滄槸鍒欐坊鍔犲埌鎵╁睍閫夐」鍒楄〃涓 + * 濡傛灉鎸囧畾浜 write_only 鏍囧織锛屽垯灏嗗叾娣诲姞鍒版墿灞曢夐」鍒楄〃涓傛渶鍚庯紝鍑芥暟妫鏌ユ槸鍚﹀垱寤轰簡鍒嗗尯琛紝濡傛灉鏄垯鎶ラ敊銆 + * 鍚屾椂锛屽嚱鏁拌繕浼氳皟鐢 TransformFormatterOptions 鍑芥暟鏉ュ鐞嗘牸寮忓寲閫夐」銆 + */ +static void distValidateCreateForeignTableStmt(Node *Obj) { - CreateForeignTableStmt* stmt = (CreateForeignTableStmt*)Obj; - ListCell* lc = NULL; - List* options_list = stmt->options; - Node* errLog = stmt->error_relation; + CreateForeignTableStmt *stmt = (CreateForeignTableStmt *)Obj; + ListCell *lc = NULL; + List *options_list = stmt->options; + Node *errLog = stmt->error_relation; Oid catalog = ForeignTableRelationId; - DistributeBy* DisByOp = ((CreateStmt*)Obj)->distributeby; + DistributeBy *DisByOp = ((CreateStmt *)Obj)->distributeby; + // 妫鏌ュ垎甯冪被鍨嬫槸鍚︿负 ROUNDROBIN if (NULL != DisByOp && DISTTYPE_ROUNDROBIN != DisByOp->disttype) { ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("Unsupport distribute type."), errdetail("Supported option value is \"roundrobin\"."))); } + // 閬嶅巻閫夐」鍒楄〃锛屾鏌ラ夐」鏄惁鏈夋晥 foreach (lc, options_list) { - DefElem* def = (DefElem*)lfirst(lc); + DefElem *def = (DefElem *)lfirst(lc); + // 妫鏌ラ夐」鏄惁鏈夋晥锛屽惁鍒欐姤閿 if (!is_valid_option(def->defname, catalog)) { - const struct DistFdwOption* opt = NULL; + const struct DistFdwOption *opt = NULL; StringInfoData buf; /* * Unknown option specified, complain about it. Provide a hint * with list of valid options for the object. */ + // 鏈煡閫夐」锛屾彁渚涙湁鏁堥夐」鐨勬彁绀 initStringInfo(&buf); for (opt = loader_valid_options; opt->optname; opt++) { if (catalog == opt->optcontext) appendStringInfo(&buf, "%s%s", (buf.len > 0) ? ", " : "", opt->optname); } - ereport(ERROR, - (errcode(ERRCODE_FDW_INVALID_OPTION_NAME), errmsg("invalid option \"%s\"", def->defname), - buf.len > 0 ? errhint("Valid options in this context are: %s", buf.data) - : errhint("There are no valid options in this context."))); + ereport(ERROR, (errcode(ERRCODE_FDW_INVALID_OPTION_NAME), errmsg("invalid option \"%s\"", def->defname), + buf.len > 0 ? errhint("Valid options in this context are: %s", buf.data) + : errhint("There are no valid options in this context."))); } } + // 澶勭悊 error_relation锛屽皢鍏舵坊鍔犲埌鎵╁睍閫夐」鍒楄〃涓 if (errLog != NULL) { if (IsA(errLog, DefElem)) stmt->extOptions = lappend(stmt->extOptions, errLog); else { RangeVar *rv = (RangeVar *)errLog; - stmt->extOptions = lappend(stmt->extOptions, makeDefElem(pstrdup(optErrorRel), - (Node *)makeString(pstrdup(rv->relname)))); + stmt->extOptions = + lappend(stmt->extOptions, makeDefElem(pstrdup(optErrorRel), (Node *)makeString(pstrdup(rv->relname)))); } } + // 濡傛灉璁剧疆浜 write_only 鏍囧織锛屽皢鍏舵坊鍔犲埌鎵╁睍閫夐」鍒楄〃涓 if (stmt->write_only) { - DefElem *writeOpt = makeDefElem(pstrdup(optWriteOnly), - (Node *)makeString(pstrdup(stmt->write_only ? "true" : "false"))); + DefElem *writeOpt = + makeDefElem(pstrdup(optWriteOnly), (Node *)makeString(pstrdup(stmt->write_only ? "true" : "false"))); stmt->extOptions = lappend(stmt->extOptions, writeOpt); } + // 妫鏌ユ槸鍚﹀垱寤轰簡鍒嗗尯琛紝濡傛灉鏄垯鎶ラ敊 if (stmt->part_state != NULL) { - ereport(ERROR, (errcode(ERRCODE_FDW_ERROR), - errmsg("It is not allowed to create partition on this foreign table."))); + ereport(ERROR, + (errcode(ERRCODE_FDW_ERROR), errmsg("It is not allowed to create partition on this foreign table."))); } + // 澶勭悊鏍煎紡鍖栭夐」 TransformFormatterOptions(stmt); stmt->options = list_concat(stmt->options, stmt->extOptions); } -static void distValidateTableDef(Node* Obj) +/* + * 鍔熻兘锛氶獙璇佽〃瀹氫箟鐩稿叧鐨勮妭鐐规槸鍚﹀悎娉 + * + * 鍙傛暟鍒楄〃锛 + * Obj锛歂ode 瀵硅薄锛岃〃绀哄緟楠岃瘉鐨勮〃瀹氫箟鐩稿叧鑺傜偣 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庨獙璇佽〃瀹氫箟鐩稿叧鐨勮妭鐐规槸鍚﹀悎娉曘傚畠鎺ュ彈涓涓 Node 瀵硅薄浣滀负鍙傛暟锛屾牴鎹妭鐐圭殑绫诲瀷 + * 璋冪敤鐩稿簲鐨勯獙璇佸嚱鏁拌繘琛岄獙璇併傛敮鎸佺殑鑺傜偣绫诲瀷鍖呮嫭 ALTER TABLE 璇彞鍜 CREATE FOREIGN TABLE 璇彞銆 + * 瀵逛簬鍏朵粬鏈煡鐨勮妭鐐圭被鍨嬶紝鍑芥暟灏嗘姤閿欍 + */ +static void distValidateTableDef(Node *Obj) { if (Obj == NULL) return; switch (nodeTag(Obj)) { case T_AlterTableStmt: { + // 瀵 ALTER TABLE 璇彞杩涜楠岃瘉 distValidateAlterTableStmt(Obj); break; } case T_CreateForeignTableStmt: { + // 瀵 CREATE FOREIGN TABLE 璇彞杩涜楠岃瘉 distValidateCreateForeignTableStmt(Obj); break; } default: + // 鏈煡鐨勮妭鐐圭被鍨嬶紝鎶ラ敊 ereport(ERROR, (errcode(ERRCODE_FDW_ERROR), errmsg("unrecognized node type: %d", (int)nodeTag(Obj)))); break; } @@ -2130,23 +2670,44 @@ static void distValidateTableDef(Node* Obj) extern char *TrimStr(const char *str); +/* + * 鍔熻兘锛氭鏌ョ粰瀹氱殑 URL 鏄惁浣跨敤 OBS 鍗忚 + * + * 鍙傛暟鍒楄〃锛 + * locations锛歝onst char 鎸囬拡锛岃〃绀哄緟妫鏌ョ殑 URL 瀛楃涓 + * + * 杩斿洖鍊硷細 + * 濡傛灉 URL 浣跨敤 OBS 鍗忚锛岃繑鍥 true锛涘惁鍒欒繑鍥 false銆 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庢鏌ョ粰瀹氱殑 URL 瀛楃涓叉槸鍚︿娇鐢 OBS (Object Storage Service) 鍗忚鎴 GSOBS 鍗忚銆 + * 瀹冮鍏堝 URL 杩涜淇壀锛岀劧鍚庢鏌ヤ慨鍓悗鐨勫瓧绗︿覆鏄惁浠 OBS 鍗忚鎴 GSOBS 鍗忚寮澶达紝濡傛灉鏄紝鍒欒繑鍥 true锛 + * 鍚﹀垯杩斿洖 false銆傚鏋滀紶閫掔殑 URL 涓 NULL 鎴栬呬慨鍓悗涓虹┖瀛楃涓诧紝鍑芥暟灏嗘姤閿欏苟鎶涘嚭寮傚父銆 + */ bool is_obs_protocol(const char *locations) { bool result = false; + // 鏂█杈撳叆 URL 闈炵┖ Assert(locations != NULL); - char *trimed_locations = TrimStr(locations); - if (trimed_locations == NULL) { - ereport(ERROR, (errcode(ERRCODE_FDW_ERROR), errmsg("Invalid URL \"%s\" in trimed LOCATION", trimed_locations))); + // 淇壀 URL 瀛楃涓 + char *trimmed_locations = TrimStr(locations); + + // 妫鏌ヤ慨鍓悗鐨 URL 鏄惁涓虹┖ + if (trimmed_locations == NULL) { + ereport(ERROR, + (errcode(ERRCODE_FDW_ERROR), errmsg("Invalid URL \"%s\" in trimmed LOCATION", trimmed_locations))); } - if (pg_strncasecmp(trimed_locations, GSOBS_PREFIX, GSOBS_PREFIX_LEN) == 0 || - pg_strncasecmp(trimed_locations, OBS_PREFIX, OBS_PREfIX_LEN) == 0) { + // 妫鏌 URL 鏄惁浠 OBS 鍗忚鎴 GSOBS 鍗忚寮澶 + if (pg_strncasecmp(trimmed_locations, GSOBS_PREFIX, GSOBS_PREFIX_LEN) == 0 || + pg_strncasecmp(trimmed_locations, OBS_PREFIX, OBS_PREFIX_LEN) == 0) { result = true; } - pfree(trimed_locations); + // 閲婃斁淇壀鍚庣殑 URL 鍐呭瓨 + pfree(trimmed_locations); return result; } diff --git a/src/gausskernel/storage/bulkload/foreignroutine.cpp b/src/gausskernel/storage/bulkload/foreignroutine.cpp index ce506a572..355d86d75 100644 --- a/src/gausskernel/storage/bulkload/foreignroutine.cpp +++ b/src/gausskernel/storage/bulkload/foreignroutine.cpp @@ -88,14 +88,31 @@ void checkGSOBSPrefixNoAllowRegionOption(bool hasRegion, List *LocationOPt); /* * all stuffs used for bulkload(end). */ -static void estimate_costs(PlannerInfo *root, const RelOptInfo *baserel, const DistImportPlanState *fdw_private, Cost *startup_cost, - Cost *total_cost); +static void estimate_costs(PlannerInfo *root, const RelOptInfo *baserel, const DistImportPlanState *fdw_private, + Cost *startup_cost, Cost *total_cost); +/* + * 鍔熻兘锛氫及绠楀閮ㄨ〃鐨勫ぇ灏忓拰琛屾暟 + * + * 鍙傛暟鍒楄〃锛 + * root锛歅lannerInfo 缁撴瀯浣擄紝鏌ヨ璁″垝鐨勪笂涓嬫枃淇℃伅 + * baserel锛歊elOptInfo 缁撴瀯浣擄紝鍏充簬澶栭儴琛ㄧ殑鍩烘湰鍏崇郴淇℃伅 + * fdw_private锛欴istImportPlanState 缁撴瀯浣擄紝澶栭儴琛ㄧ殑绉佹湁鐘舵佷俊鎭 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庝及绠楀閮ㄨ〃鐨勫ぇ灏忓拰琛屾暟锛屽苟瀛樺偍鍦 fdw_private 缁撴瀯浣撲腑銆 + * 瀹冮鍏堝皾璇曚粠 pg_class 琛ㄤ腑鑾峰彇澶栭儴琛ㄧ殑椤垫暟鍜屽厓缁勬暟浼扮畻鍊硷紝 + * 濡傛灉鏃犳硶鑾峰彇锛屽氨浣跨敤榛樿鐨勪及绠楀笺 + * 姝ラ锛 + * 灏濊瘯浠 pg_class 琛ㄤ腑鑾峰彇澶栭儴琛ㄧ殑椤垫暟鍜屽厓缁勬暟浼扮畻鍊笺 + * 濡傛灉鏃犳硶鑾峰彇锛屼娇鐢ㄩ粯璁ょ殑浼扮畻鍊笺 + * 浼扮畻琛屾暟骞跺瓨鍌ㄥ湪 RelOptInfo 缁撴瀯浣撲腑銆 + */ static void estimate_size(PlannerInfo *root, RelOptInfo *baserel, DistImportPlanState *fdw_private) { - struct stat stat_buf; - BlockNumber pages; - double ntuples; - double nrows; + struct stat stat_buf; // 瀛樺偍鏂囦欢淇℃伅鐨勭粨鏋勪綋 + BlockNumber pages; // 鏂囦欢鍗犵敤鐨勬暟鎹潡鏁 + double ntuples; // 鍏冪粍鏁颁及绠楀 + double nrows; // 琛屾暟浼扮畻鍊 /* * Estimate the number of tuples in the file. @@ -150,13 +167,32 @@ static void estimate_size(PlannerInfo *root, RelOptInfo *baserel, DistImportPlan /* Save the output-rows estimate for the planner */ baserel->rows = nrows; } - -static void estimate_costs(PlannerInfo *root, const RelOptInfo *baserel, const DistImportPlanState *fdw_private, Cost *startup_cost, - Cost *total_cost) +/* + * 鍔熻兘锛氫及绠楀閮ㄨ〃鐨勮闂垚鏈 + * + * 鍙傛暟鍒楄〃锛 + * root锛歅lannerInfo 缁撴瀯浣擄紝鏌ヨ璁″垝鐨勪笂涓嬫枃淇℃伅 + * baserel锛歊elOptInfo 缁撴瀯浣擄紝鍏充簬澶栭儴琛ㄧ殑鍩烘湰鍏崇郴淇℃伅 + * fdw_private锛欴istImportPlanState 缁撴瀯浣擄紝澶栭儴琛ㄧ殑绉佹湁鐘舵佷俊鎭 + * startup_cost锛欳ost 鎸囬拡锛岀敤浜庡瓨鍌ㄥ惎鍔ㄦ垚鏈及绠楀 + * total_cost锛欳ost 鎸囬拡锛岀敤浜庡瓨鍌ㄦ绘垚鏈及绠楀 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庝及绠楀閮ㄨ〃鐨勮闂垚鏈紝骞跺皢缁撴灉瀛樺偍鍦 startup_cost 鍜 total_cost 涓 + * 瀹冧及绠楁垚鏈殑鏂瑰紡绫讳技浜 cost_seqscan() 鍑芥暟锛屽亣璁 I/O 鎴愭湰绛夋晥浜庣浉鍚屽ぇ灏忕殑甯歌琛ㄦ枃浠躲 + * 涓嶈繃锛屼负浜嗚冭檻瑙f瀽璁板綍鐨勬垚鏈紝灏嗘瘡鍏冪粍鐨 CPU 鎴愭湰璁剧疆涓 seqscan 鐨10鍊嶃 + * 姝ラ锛 + * 1.鑾峰彇澶栭儴琛ㄧ殑鏁版嵁鍧楁暟鍜屽厓缁勬暟浼扮畻鍊笺 + * 2.鑾峰彇澶栭儴琛ㄧ殑鏁版嵁鍧楁暟鍜屽厓缁勬暟浼扮畻鍊笺 + * 3.鍩轰簬鍏冪粍鏁颁及绠 CPU 鎴愭湰锛屽苟鑰冭檻瑙f瀽璁板綍鐨勬垚鏈 + * 4.璁$畻鎬绘垚鏈紝鍖呮嫭鍚姩鎴愭湰鍜岃繍琛屾垚鏈 + */ +static void estimate_costs(PlannerInfo *root, const RelOptInfo *baserel, const DistImportPlanState *fdw_private, + Cost *startup_cost, Cost *total_cost) { - BlockNumber pages = fdw_private->pages; - double ntuples = fdw_private->ntuples; - Cost run_cost = 0; + BlockNumber pages = fdw_private->pages; // 澶栭儴琛ㄧ殑鏁版嵁鍧楁暟 + double ntuples = fdw_private->ntuples; // 澶栭儴琛ㄧ殑鍏冪粍鏁颁及绠楀 + Cost run_cost = 0; // 杩愯鎴愭湰 Cost cpu_per_tuple; /* @@ -167,42 +203,56 @@ static void estimate_costs(PlannerInfo *root, const RelOptInfo *baserel, const D */ run_cost += u_sess->attr.attr_sql.seq_page_cost * pages; - *startup_cost = baserel->baserestrictcost.startup; + *startup_cost = baserel->baserestrictcost.startup; // 鍚姩鎴愭湰 cpu_per_tuple = u_sess->attr.attr_sql.cpu_tuple_cost * 10 + baserel->baserestrictcost.per_tuple; - run_cost += cpu_per_tuple * ntuples; - *total_cost = *startup_cost + run_cost; + run_cost += cpu_per_tuple * ntuples; // CPU 鎴愭湰 + *total_cost = *startup_cost + run_cost; // 鎬绘垚鏈 } +/* + * 鍔熻兘锛氳鍑芥暟鐢ㄤ簬瑙f瀽鏍煎紡鍖栭夐」瀛楃涓诧紝骞跺皢鍏惰浆鍖栦负涓涓垪琛紝鍏朵腑鍖呭惈澶氫釜 Position 缁撴瀯鐨勫厓绱犮 + * 姣忎釜 Position 缁撴瀯鍖呮嫭鍒楀悕銆佸紑濮嬪亸绉婚噺鍜屽瓧娈甸暱搴︾瓑淇℃伅銆 + * + * 鍙傛暟: + * def: 涓涓 DefElem 缁撴瀯锛屽寘鍚簡鏍煎紡鍖栭夐」瀛楃涓层 + * + * 娉ㄦ剰: + * 璇ュ嚱鏁板皢瑙f瀽鍚庣殑缁撴灉瀛樺偍鍦 def->arg 涓紝鏇挎崲浜嗗師濮嬬殑瀛楃涓插弬鏁般 + * 濡傛灉瑙f瀽澶辫触锛屽嚱鏁颁細鎶涘嚭閿欒銆 + */ void UntransformFormatterOption(DefElem *def) { - char *s = pstrdup(strVal(def->arg)); - List *entries = NIL; - List *result = NIL; - ListCell *lc = NULL; - char *p = NULL; - char *token = NULL; + char *s = pstrdup(strVal(def->arg)); // 澶嶅埗浼犲叆鐨勫瓧绗︿覆鍙傛暟 + List *entries = NIL; // 鐢ㄤ簬瀛樺偍鍒嗗壊鍚庣殑瀛愬瓧绗︿覆 + List *result = NIL; // 鐢ㄤ簬瀛樺偍瑙f瀽鍚庣殑缁撴灉 + ListCell *lc = NULL; // 鐢ㄤ簬閬嶅巻 entries 鍒楄〃 + char *p = NULL; // 瀛楃涓插垏鍓茬殑鎸囬拡 + char *token = NULL; // 鐢ㄤ簬淇濆瓨鍒嗗壊鍚庣殑瀛愬瓧绗︿覆 - // get position string + // 浣跨敤 strtok_r 鍑芥暟灏嗗瓧绗︿覆鎸 "." 鍒嗗壊涓哄涓瓙瀛楃涓诧紝瀛樺偍鍦 entries 鍒楄〃涓 token = strtok_r(s, ".", &p); while (token != NULL) { entries = lappend(entries, token); token = strtok_r(NULL, ".", &p); } + // 閬嶅巻 entries 鍒楄〃涓殑姣忎釜瀛愬瓧绗︿覆锛屼緷娆¤В鏋愭牸寮忓寲閫夐」骞跺皢鍏惰浆鍖栦负 Position 缁撴瀯 foreach (lc, entries) { - Position *pos = (Position *)palloc0(sizeof(Position)); - char *end = NULL; + Position *pos = (Position *)palloc0(sizeof(Position)); // 鍒涘缓 Position 缁撴瀯 + char *end = NULL; // 鐢ㄤ簬妫鏌ヨ浆鍖栨槸鍚︽垚鍔 - s = (char *)lfirst(lc); + s = (char *)lfirst(lc); // 鑾峰彇褰撳墠瀛愬瓧绗︿覆 - // Get column name + // 鑾峰彇鍒楀悕锛屽垪鍚嶄綅浜庡瓙瀛楃涓蹭腑鐨 "(" 涔嬪墠 p = strchr(s, '('); if (p == NULL) ereport(ERROR, (errcode(ERRCODE_OPERATE_INVALID_PARAM), errmsg("Invalid formatter options \"%s\"", (char *)lfirst(lc)))); + + // 鎻愬彇鍒楀悕骞跺瓨鍌ㄥ湪 Position 缁撴瀯鐨 colname 瀛楁涓 pos->colname = pnstrdup(s, (Size)(p - s)); - // Get begin offset + // 鑾峰彇寮濮嬪亸绉婚噺锛屽紑濮嬪亸绉婚噺浣嶄簬 "(" 鍜 "," 涔嬮棿 s = p + 1; p = strchr(s, ','); if (p == NULL) @@ -210,12 +260,14 @@ void UntransformFormatterOption(DefElem *def) errmsg("Invalid formatter options \"%s\"", (char *)lfirst(lc)))); s = pnstrdup(s, p - s); pos->position = (int)strtol(s, &end, 10); + + // 妫鏌ヨ浆鍖栨槸鍚︽垚鍔 if ((end == NULL) || (*end != '\0')) ereport(ERROR, (errcode(ERRCODE_OPERATE_INVALID_PARAM), errmsg("Invalid formatter options \"%s\"", (char *)lfirst(lc)))); - pfree(s); + pfree(s); // 閲婃斁涓存椂瀛楃涓 - // Get length of field + // 鑾峰彇瀛楁闀垮害锛屽瓧娈甸暱搴︿綅浜 "," 鍜 ")" 涔嬮棿 s = p + 1; p = strchr(s, ')'); if (p == NULL) @@ -223,13 +275,21 @@ void UntransformFormatterOption(DefElem *def) errmsg("Invalid formatter options \"%s\"", (char *)lfirst(lc)))); s = pnstrdup(s, p - s); pos->fixedlen = (int)strtol(s, &end, 10); + + // 妫鏌ヨ浆鍖栨槸鍚︽垚鍔 if ((end == NULL) || *end != '\0') ereport(ERROR, (errcode(ERRCODE_OPERATE_INVALID_PARAM), errmsg("Invalid formatter options \"%s\"", (char *)lfirst(lc)))); - pfree(s); + pfree(s); // 閲婃斁涓存椂瀛楃涓 + + // 灏嗗畬鏁寸殑 Position 缁撴瀯娣诲姞鍒 result 鍒楄〃涓 result = lappend(result, pos); } + + // 閲婃斁 entries 鍒楄〃涓殑瀛楃涓 list_free_ext(entries); + + // 鏇存柊 def->arg 涓鸿В鏋愬悗鐨 result 鍒楄〃 def->arg = (Node *)result; } @@ -253,30 +313,70 @@ static const int URI_protocols_num = sizeof(URI_protocols) / sizeof(URI_protocol * @Return: index within global protocol map * @See also: */ -static int search_existing_procotols(const char *protocol) +/* + * 鍔熻兘锛氭悳绱㈢幇鏈夊崗璁暟缁勶紝鏌ユ壘鎸囧畾鍗忚鐨勭储寮 + * + * 鍙傛暟鍒楄〃锛 + * protocol锛歝onst char 鎸囬拡锛岃鏌ユ壘鐨勫崗璁悕绉 + * + * 杩斿洖鍊硷細 + * int 鍊硷紝鎸囧畾鍗忚鐨勭储寮曚綅缃 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庢悳绱㈢幇鏈夊崗璁暟缁勶紝浠ユ煡鎵炬寚瀹氬崗璁殑绱㈠紩浣嶇疆銆 + * 濡傛灉鎵惧埌鍖归厤鐨勫崗璁紝杩斿洖鍗忚鍦ㄦ暟缁勪腑鐨勭储寮曚綅缃 + * 濡傛灉鎵句笉鍒板尮閰嶇殑鍗忚锛屼娇鐢 Assert 鏂█瑙﹀彂閿欒銆 + * 姝ラ锛 + * 1. 鍒濆鍖栧彉閲 i 涓 0銆 + * 2. 浣跨敤寰幆閬嶅巻鍗忚鏁扮粍 URI_protocols銆 + * 3. 濡傛灉鎵惧埌涓 protocol 鐩哥瓑鐨勫崗璁紝璺冲嚭寰幆銆 + * 4. 浣跨敤 Assert 鏂█纭繚绱㈠紩 i 鐨勫煎湪鍚堟硶鑼冨洿鍐呫 + * 5. 杩斿洖鍗忚鐨勭储寮曚綅缃 i銆 + */ +static int search_existing_protocols(const char *protocol) { - int i = 0; + int i = 0; // 鍒濆鍖栧彉閲 i 涓 0 for (; i < URI_protocols_num; i++) { - if (0 == strcmp(protocol, URI_protocols[i])) { + if (0 == strcmp(protocol, URI_protocols[i])) { // 濡傛灉鎵惧埌涓 protocol 鐩哥瓑鐨勫崗璁紝璺冲嚭寰幆 break; } } - Assert(i >= 0 && i <= URI_protocols_num - 1); - return i; + Assert(i >= 0 && i <= URI_protocols_num - 1); // 浣跨敤 Assert 鏂█纭繚绱㈠紩 i 鐨勫煎湪鍚堟硶鑼冨洿鍐 + return i; // 杩斿洖鍗忚鐨勭储寮曚綅缃 i } +/* + * 鍔熻兘锛氭鏌ュ崗璁槸鍚﹀瓨鍦ㄥ啿绐 + * + * 鍙傛暟鍒楄〃锛 + * tmpuri锛欸DSUri 缁撴瀯浣擄紝琛ㄧず褰撳墠澶勭悊鐨 URI 淇℃伅 + * first_protocol_idx锛歩nt 鍊硷紝琛ㄧず绗竴涓崗璁殑绱㈠紩浣嶇疆 + * + * 杩斿洖鍊硷細 + * bool 鍊硷紝琛ㄧず鏄惁瀛樺湪鍐茬獊 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庢鏌ュ崗璁槸鍚﹀瓨鍦ㄥ啿绐併 + * 濡傛灉绗竴涓崗璁笉鏄 LOCAL_PREFIX锛屼絾鍚庨潰鐨勫崗璁槸 LOCAL_PREFIX锛屽垯瀛樺湪鍐茬獊銆 + * 濡傛灉绗竴涓崗璁笌鍚庨潰鐨勫崗璁笉鍚岋紝鍒欏瓨鍦ㄥ啿绐併 + * 姝ラ锛 + * 1. 濡傛灉 tmpuri 涓殑鍗忚涓虹┖锛屽苟涓旂涓涓崗璁储寮曚笉鏄 0锛岃〃绀哄瓨鍦ㄥ啿绐侊紝杩斿洖 true銆 + * 2. 濡傛灉 tmpuri 涓殑鍗忚涓嶄负绌猴紝骞朵笖涓庣涓涓崗璁笉鐩哥瓑锛岃〃绀哄瓨鍦ㄥ啿绐侊紝杩斿洖 true銆 + * 3. 濡傛灉浠ヤ笂涓ょ鎯呭喌閮戒笉婊¤冻锛岃〃绀烘病鏈夊啿绐侊紝杩斿洖 false銆 + */ + static bool ProtocolHasConflict(const GDSUri &tmpuri, int first_protocol_idx) { - /* conflict: the first is not LOCAL_PREFIX but the later one is */ + /* 鍐茬獊锛氱涓涓崗璁笉鏄 LOCAL_PREFIX锛屼絾鍚庨潰鐨勫崗璁槸 LOCAL_PREFIX */ if (tmpuri.m_protocol == NULL && first_protocol_idx != 0) { return true; } - /* conflict: the remaining are different from the first */ + /* 鍐茬獊锛氬悗闈㈢殑鍗忚涓庣涓涓崗璁笉鍚 */ if (tmpuri.m_protocol != NULL && strcmp(tmpuri.m_protocol, URI_protocols[first_protocol_idx]) != 0) { return true; } - return false; + return false; // 娌℃湁鍐茬獊 } /* @@ -285,6 +385,25 @@ static bool ProtocolHasConflict(const GDSUri &tmpuri, int first_protocol_idx) * @IN lcs: LOCATION options list * @See also: */ +/* + * 鍔熻兘锛氶獙璇 URI 鍒楄〃涓殑浣嶇疆淇℃伅 + * + * 鍙傛暟鍒楄〃锛 + * lcs锛歀ist 缁撴瀯浣撴寚閽堬紝鍖呭惈浣嶇疆淇℃伅鐨 URI 鍒楄〃 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庨獙璇 URI 鍒楄〃涓殑浣嶇疆淇℃伅鏄惁鍚堟硶銆 + * 棣栧厛妫鏌ョ涓涓綅缃槸鍚﹀悎娉曪紝鐒跺悗閫愪竴妫鏌ュ悗缁綅缃槸鍚︿笌绗竴涓綅缃崗璁浉鍚屻 + * 濡傛灉鍙戠幇浠讳綍浣嶇疆涓嶅悎娉曟垨涓庣涓涓綅缃崗璁笉鍚岋紝灏嗗紩鍙戦敊璇 + * + * 姝ラ锛 + * 1. 鑾峰彇绗竴涓綅缃俊鎭紝骞跺皢鍏惰浆鎹负瀛楃涓层 + * 2. 妫鏌ョ涓涓綅缃槸鍚﹀悎娉曪紝濡傛灉涓嶅悎娉曪紝寮曞彂閿欒銆 + * 3. 瑙f瀽绗竴涓綅缃殑 URI锛岃幏鍙栧叾鍗忚锛屽苟鍦ㄥ凡鐭ュ崗璁垪琛ㄤ腑鏌ユ壘瀵瑰簲鐨勭储寮曘 + * 4. 閬嶅巻 URI 鍒楄〃涓殑姣忎釜浣嶇疆銆 + * 5. 瀵逛簬姣忎釜浣嶇疆锛岃В鏋愬叾 URI锛屾鏌ュ崗璁槸鍚︿笌绗竴涓綅缃浉鍚岋紝濡傛灉涓嶅悓锛屽紩鍙戦敊璇 + */ + static void VerifyLocations(const List *lcs) { ListCell *lc = NULL; @@ -299,7 +418,7 @@ static void VerifyLocations(const List *lcs) GDSUri uri; uri.Parse(first); if (uri.m_protocol) { - first_protocol_idx = search_existing_procotols(uri.m_protocol); + first_protocol_idx = search_existing_protocols(uri.m_protocol); } else { /* at default it's a local protocol */ first_protocol_idx = 0; @@ -321,6 +440,23 @@ static void VerifyLocations(const List *lcs) * @param lcs location options list * @return void */ +/* + * 鍔熻兘锛氭鏌 URI 鍒楄〃涓槸鍚﹀瓨鍦ㄩ噸澶嶇殑浣嶇疆淇℃伅 + * + * 鍙傛暟鍒楄〃锛 + * lcs锛歀ist 缁撴瀯浣撴寚閽堬紝鍖呭惈浣嶇疆淇℃伅鐨 URI 鍒楄〃 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庢鏌 URI 鍒楄〃涓槸鍚﹀瓨鍦ㄩ噸澶嶇殑浣嶇疆淇℃伅銆 + * 瀹冮亶鍘 URI 鍒楄〃锛屽姣忎釜浣嶇疆淇℃伅杩涜瑙f瀽锛屽苟姣旇緝绔彛鍙峰拰涓绘満鍚嶆槸鍚︾浉鍚屻 + * 濡傛灉鍙戠幇閲嶅鐨勪綅缃俊鎭紝灏嗗紩鍙戦敊璇 + * + * 姝ラ锛 + * 1. 閬嶅巻 URI 鍒楄〃涓殑姣忎釜浣嶇疆銆 + * 2. 瑙f瀽姣忎釜浣嶇疆鐨 URI锛屽苟蹇界暐鏃犳晥鐨勪綅缃俊鎭 + * 3. 瀵逛簬姣忎釜鏈夋晥鐨勪綅缃俊鎭紝妫鏌ユ槸鍚︿笌涔嬪墠鐨勪綅缃俊鎭噸澶嶃 + * 4. 濡傛灉鍙戠幇閲嶅鐨勪綅缃俊鎭紝寮曞彂閿欒銆 + */ static void CheckDupLocations(const List *lcs) { ListCell *lc = NULL; @@ -370,33 +506,73 @@ DesErr: } } +/* + * 鍔熻兘锛氶獙璇佹枃浠跺ご閮ㄧ殑浣嶇疆淇℃伅鏄惁鍚堟硶 + * + * 鍙傛暟鍒楄〃锛 + * path锛歝onst char 鎸囬拡锛屽寘鍚枃浠跺ご閮ㄤ綅缃俊鎭殑璺緞 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庨獙璇佹枃浠跺ご閮ㄧ殑浣嶇疆淇℃伅鏄惁鍚堟硶銆 + * 瀹冮鍏堣В鏋愯矾寰勪腑鐨 URI 淇℃伅锛岀劧鍚庢鏌ュ崗璁拰璺緞鏄惁婊¤冻瑕佹眰銆 + * 濡傛灉浣嶇疆淇℃伅涓嶅悎娉曪紝灏嗗紩鍙戦敊璇 + */ + static void VerifyFileHeader(const char *path) { GDSUri uri; + // 瑙f瀽璺緞涓殑 URI 淇℃伅 uri.Parse(path); + + // 妫鏌ュ崗璁槸鍚﹀瓨鍦 if (uri.m_protocol != NULL) { + // 妫鏌ヨ矾寰勬槸鍚︿互鏂滄潬寮澶 if (uri.m_path == NULL || uri.m_path[0] != '/') { ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("invalid file header location \"%s\"", uri.m_uri))); } } } +/* + * 鍔熻兘锛氶獙璇佹枃浠跺悕鍓嶇紑鏄惁鍚堟硶 + * + * 鍙傛暟鍒楄〃锛 + * name锛歝onst char 鎸囬拡锛岃楠岃瘉鐨勬枃浠跺悕鍓嶇紑 + * isExport锛歜ool锛岃〃绀烘槸鍚︽槸瀵煎嚭鎿嶄綔 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庨獙璇佹枃浠跺悕鍓嶇紑鏄惁鍚堟硶銆 + * 楠岃瘉鐨勮鍒欏寘鎷互涓嬪嚑涓柟闈細 + * 1. 濡傛灉涓嶆槸瀵煎嚭鎿嶄綔锛屾枃浠跺悕鍓嶇紑鍙厑璁稿湪鍐欏叆鎿嶄綔鐨勫閮ㄨ〃涓娇鐢紝鍚﹀垯寮曞彂閿欒銆 + * 2. 鏂囦欢鍚嶅墠缂涓嶅厑璁镐负绌猴紝鍚﹀垯寮曞彂閿欒銆 + * 3. 鏂囦欢鍚嶅墠缂涓嶅厑璁稿寘鍚互涓嬬壒娈婂瓧绗︼細'/', '?', '*', ':', '|', '\\', '<', '>', '@', '#', '$', '&', '(', ')', '+', + * '-'銆 + * 4. 鏂囦欢鍚嶅墠缂涓嶅厑璁镐笌浠ヤ笅瀛楃涓茬浉鍚岋細"con", "aux", "nul", "prn", "com0", "com1", "com2", "com3", + * "com4", "com5", "com6", "com7", "com8", "com9", "lpt0", "lpt1", "lpt2", "lpt3", "lpt4", "lpt5", "lpt6", "lpt7", + * "lpt8", "lpt9"銆 + * 5. 鏂囦欢鍚嶅墠缂鍙厑璁稿寘鍚瓧姣嶃佹暟瀛楀拰涓嬪垝绾垮瓧绗 ('_')锛屽叾浠栧瓧绗﹀潎涓嶅厑璁搞 + */ static void VerifyFilenamePrefix(const char *name, bool isExport) { + // 妫鏌ュ弬鏁版槸鍚︽湁鏁 Assert(PointerIsValid(name)); + // 濡傛灉涓嶆槸瀵煎嚭鎿嶄綔锛屾枃浠跺悕鍓嶇紑鍙厑璁稿湪鍐欏叆鎿嶄綔鐨勫閮ㄨ〃涓娇鐢紝鍚﹀垯寮曞彂閿欒 if (!isExport) { ereport(ERROR, (errcode(ERRCODE_OPERATE_INVALID_PARAM), errmsg("out_filename_prefix is only allowed in write-only foreign tables"))); } + // 妫鏌ユ枃浠跺悕鍓嶇紑鏄惁涓虹┖锛屽鏋滀负绌哄垯寮曞彂閿欒 if (strlen(name) == 0) { ereport(ERROR, (errcode(ERRCODE_OPERATE_INVALID_PARAM), errmsg("out_filename_prefix should not be empty"))); } - const char illegalChars[16] = { '/', '?', '*', ':', '|', '\\', '<', '>', '@', '#', '$', '&', '(', ')', '+', '-' }; + // 瀹氫箟涓嶅厑璁稿寘鍚殑鐗规畩瀛楃鏁扮粍 + const char illegalChars[16] = {'/', '?', '*', ':', '|', '\\', '<', '>', '@', '#', '$', '&', '(', ')', '+', '-'}; + // 閬嶅巻涓嶅厑璁稿寘鍚殑鐗规畩瀛楃鏁扮粍锛屽鏋滄枃浠跺悕鍓嶇紑涓寘鍚叾涓箣涓锛屽紩鍙戦敊璇 for (int i = 0; i < 16; i++) { if (strchr(name, illegalChars[i]) != NULL) { ereport(ERROR, (errcode(ERRCODE_OPERATE_INVALID_PARAM), @@ -404,10 +580,12 @@ static void VerifyFilenamePrefix(const char *name, bool isExport) } } - const char *illegalStrings[24] = { - "con", "aux", "nul", "prn", "com0", "com1", "com2", "com3", "com4", "com5", "com6", "com7", - "com8", "com9", "lpt0", "lpt1", "lpt2", "lpt3", "lpt4", "lpt5", "lpt6", "lpt7", "lpt8", "lpt9" - }; + // 瀹氫箟涓嶅厑璁镐笌涔嬬浉鍚岀殑瀛楃涓叉暟缁 + const char *illegalStrings[24] = {"con", "aux", "nul", "prn", "com0", "com1", "com2", "com3", + "com4", "com5", "com6", "com7", "com8", "com9", "lpt0", "lpt1", + "lpt2", "lpt3", "lpt4", "lpt5", "lpt6", "lpt7", "lpt8", "lpt9"}; + + // 閬嶅巻涓嶅厑璁镐笌涔嬬浉鍚岀殑瀛楃涓叉暟缁勶紝濡傛灉鏂囦欢鍚嶅墠缂涓庡叾涓箣涓鐩稿悓锛屽紩鍙戦敊璇 for (int i = 0; i < 24; i++) { if (strcmp(name, illegalStrings[i]) == 0) { ereport(ERROR, (errcode(ERRCODE_OPERATE_INVALID_PARAM), @@ -415,6 +593,7 @@ static void VerifyFilenamePrefix(const char *name, bool isExport) } } + // 閬嶅巻鏂囦欢鍚嶅墠缂鐨勬瘡涓瓧绗︼紝濡傛灉鍖呭惈闈炲瓧姣嶃佹暟瀛楀拰涓嬪垝绾垮瓧绗 ('_')锛屽紩鍙戦敊璇 for (const char *c = name; *c; c++) { if (!((isalnum(*c) || (*c == '_')))) { ereport(ERROR, (errcode(ERRCODE_OPERATE_INVALID_PARAM), @@ -423,29 +602,67 @@ static void VerifyFilenamePrefix(const char *name, bool isExport) } } +/* + * 鍔熻兘锛氶獙璇佸榻愭柟寮忔槸鍚﹀悎娉 + * + * 鍙傛暟鍒楄〃锛 + * alignment锛歝onst char 鎸囬拡锛岃楠岃瘉鐨勫榻愭柟寮忓瓧绗︿覆 + * isExport锛歜ool锛岃〃绀烘槸鍚︽槸瀵煎嚭鎿嶄綔 + * format锛欶ileFormat锛岃〃绀烘枃浠舵牸寮 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庨獙璇佸榻愭柟寮忔槸鍚﹀悎娉曘 + * 楠岃瘉鐨勮鍒欏寘鎷互涓嬪嚑涓柟闈細 + * 1. 濡傛灉涓嶆槸瀵煎嚭鎿嶄綔锛屽榻愭柟寮忓彧鍏佽鍦ㄥ啓鍏ユ搷浣滅殑澶栭儴琛ㄤ腑浣跨敤锛屽惁鍒欏紩鍙戦敊璇 + * 2. 鍙湁鍦ㄦ枃浠舵牸寮忎负 FIXED 鏃讹紝鎵嶅厑璁镐娇鐢ㄥ榻愭柟寮忥紝鍚﹀垯寮曞彂閿欒銆 + * 3. 瀵归綈鏂瑰紡鍙厑璁镐负 "align_left" 鎴 "align_right"锛屽叾浠栧煎潎涓嶅厑璁搞 + */ static void VerifyFixAlignment(const char *alignment, bool isExport, FileFormat format) { + // 妫鏌ュ弬鏁版槸鍚︽湁鏁 Assert(PointerIsValid(alignment)); + + // 濡傛灉涓嶆槸瀵煎嚭鎿嶄綔锛屽榻愭柟寮忓彧鍏佽鍦ㄥ啓鍏ユ搷浣滅殑澶栭儴琛ㄤ腑浣跨敤锛屽惁鍒欏紩鍙戦敊璇 if (!isExport) { ereport(ERROR, (errcode(ERRCODE_OPERATE_INVALID_PARAM), errmsg("out_fix_alignment is only allowed in write-only foreign tables"))); } + // 鍙湁鍦ㄦ枃浠舵牸寮忎负 FIXED 鏃讹紝鎵嶅厑璁镐娇鐢ㄥ榻愭柟寮忥紝鍚﹀垯寮曞彂閿欒 if (format != FORMAT_FIXED) { ereport(ERROR, (errcode(ERRCODE_OPERATE_INVALID_PARAM), errmsg("out_fix_alignment is only allowed with fixed format"))); } - if (!(((strcmp(alignment, "align_left") == 0) || (strcmp(alignment, "align_right") == 0)))) { + // 瀵归綈鏂瑰紡鍙厑璁镐负 "align_left" 鎴 "align_right"锛屽叾浠栧煎潎涓嶅厑璁 + if (!((strcmp(alignment, "align_left") == 0) || (strcmp(alignment, "align_right") == 0))) { ereport(ERROR, (errcode(ERRCODE_OPERATE_INVALID_PARAM), errmsg("Only \"align_left\" and \"align_right\" is allowed in out_fix_alignment option"))); } } +/* + * 鍔熻兘锛氶獙璇佺敤鎴峰畾涔夊悕绉版槸鍚﹀悎娉 + * + * 鍙傛暟鍒楄〃锛 + * input锛歝onst char 鎸囬拡锛岃楠岃瘉鐨勭敤鎴峰畾涔夊悕绉板瓧绗︿覆 + * + * 杩斿洖鍊硷細 + * 鍚堟硶杩斿洖 true锛屽惁鍒欒繑鍥 false + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庨獙璇佺敤鎴峰畾涔夊悕绉版槸鍚﹀悎娉曘 + * 楠岃瘉鐨勮鍒欏寘鎷互涓嬪嚑涓柟闈細 + * 1. 鐢ㄦ埛瀹氫箟鍚嶇О鐨勭涓涓瓧绗︿笉鑳芥槸鏁板瓧锛'0' 鍒 '9'锛夋垨缇庡厓绗﹀彿 ('$')锛屽惁鍒欒繑鍥 false銆 + * 2. 鐢ㄦ埛瀹氫箟鍚嶇О鍙兘鍖呭惈灏忓啓瀛楁瘝銆佸ぇ鍐欏瓧姣嶃佹暟瀛椼佷笅鍒掔嚎 ('_')銆佺編鍏冪鍙 ('$') 鍜屽彞鐐 + * ('.')锛屽叾浠栧瓧绗﹀潎涓嶅厑璁革紝鍚﹀垯杩斿洖 false銆 + * 3. 濡傛灉鐢ㄦ埛瀹氫箟鍚嶇О绗﹀悎涓婅堪瑙勫垯锛屽垯杩斿洖 true锛岃〃绀哄悎娉曪紱鍚﹀垯杩斿洖 false锛岃〃绀轰笉鍚堟硶銆 + */ static bool IsValidUserDefineName(const char *input) { char c = input[0]; - /* The first character id numbers or dollar */ + + // 鐢ㄦ埛瀹氫箟鍚嶇О鐨勭涓涓瓧绗︿笉鑳芥槸鏁板瓧锛'0' 鍒 '9'锛夋垨缇庡厓绗﹀彿 ('$')锛屽惁鍒欒繑鍥 false if ((c >= '1' && c <= '9') || c == '$') { return false; } @@ -453,6 +670,9 @@ static bool IsValidUserDefineName(const char *input) int len = (int)strlen(input); for (int i = 0; i < len; i++) { c = input[i]; + + // 鐢ㄦ埛瀹氫箟鍚嶇О鍙兘鍖呭惈灏忓啓瀛楁瘝銆佸ぇ鍐欏瓧姣嶃佹暟瀛椼佷笅鍒掔嚎 ('_')銆佺編鍏冪鍙 ('$') 鍜屽彞鐐 + // ('.')锛屽叾浠栧瓧绗﹀潎涓嶅厑璁革紝鍚﹀垯杩斿洖 false if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || c == '_' || c == '$' || c == '.') { continue; @@ -469,14 +689,31 @@ static bool IsValidUserDefineName(const char *input) * @in LocationOPt, the location option list to be given. * @return none. */ +/* + * 鍔熻兘锛氭鏌ユ槸鍚﹀厑璁歌缃 region 閫夐」 + * + * 鍙傛暟鍒楄〃锛 + * hasRegion锛歜ool锛岃〃绀烘槸鍚﹀瓨鍦 region 閫夐」 + * LocationOPt锛歀ist 鎸囬拡锛屽寘鍚閮ㄨ〃鐨 location 閫夐」鍒楄〃 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庢鏌ユ槸鍚﹀厑璁歌缃 region 閫夐」銆傚鏋滃閮ㄨ〃鐨 location 閫夐」鍒楄〃涓寘鍚 "gsobs" 鍓嶇紑锛屽垯涓嶅厑璁歌缃 region + * 閫夐」銆 濡傛灉瀛樺湪 region 閫夐」涓斿寘鍚 "gsobs" 鍓嶇紑锛屽垯浼氭姏鍑洪敊璇 + * + * 杩斿洖鍊硷細 + * 鏃 + */ void checkGSOBSPrefixNoAllowRegionOption(bool hasRegion, List *LocationOPt) { + // 濡傛灉娌℃湁 region 閫夐」锛岀洿鎺ヨ繑鍥 if (hasRegion == false) { return; } + char *firstLocation = strVal(lfirst(list_head(LocationOPt))); char *tmpLocation = TrimStr(firstLocation); + // 妫鏌 location 閫夐」鏄惁浠 "gsobs" 鍓嶇紑寮澶达紝濡傛灉鏄紝鍒欐姏鍑洪敊璇 if (0 == pg_strncasecmp(tmpLocation, GSOBS_PREFIX, strlen(GSOBS_PREFIX))) { pfree(tmpLocation); ereport(ERROR, (errcode(ERRCODE_FDW_DYNAMIC_PARAMETER_VALUE_NEEDED), errmodule(MOD_OBS), @@ -487,39 +724,77 @@ void checkGSOBSPrefixNoAllowRegionOption(bool hasRegion, List *LocationOPt) pfree(tmpLocation); } -void processOBSNoAllowOptions(bool specifyMode, const char *fileheader, - const char *OutputFilenamePrefix, const char *OutputFixAlignment, bool doLogRemote) +/* + * 鍔熻兘锛氬鐞嗕笉鍏佽鐨 OBS 澶栭儴琛ㄩ夐」 + * + * 鍙傛暟鍒楄〃锛 + * specifyMode锛歜ool锛屾寚绀烘槸鍚︽寚瀹氫簡 mode 閫夐」 + * fileheader锛歝onst char 鎸囬拡锛岃〃绀烘枃浠跺ご閫夐」鍊 + * OutputFilenamePrefix锛歝onst char 鎸囬拡锛岃〃绀鸿緭鍑烘枃浠跺墠缂閫夐」鍊 + * OutputFixAlignment锛歝onst char 鎸囬拡锛岃〃绀鸿緭鍑哄浐瀹氬榻愰夐」鍊 + * doLogRemote锛歜ool锛屾寚绀烘槸鍚﹁缃簡 remote_log 閫夐」 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庡鐞嗕笉鍏佽鐨 OBS 澶栭儴琛ㄩ夐」銆傚鏋滄寚瀹氫簡涓嶅厑璁哥殑閫夐」锛屽嚱鏁颁細鎶涘嚭閿欒銆 + */ +void processOBSNoAllowOptions(bool specifyMode, const char *fileheader, const char *OutputFilenamePrefix, + const char *OutputFixAlignment, bool doLogRemote) { + // 濡傛灉鎸囧畾浜 mode 閫夐」锛屾姏鍑洪敊璇 if (specifyMode) { ereport(ERROR, (errcode(ERRCODE_OPERATE_INVALID_PARAM), errmsg("OBS foreign table does not support '%s' option", optMode))); - } else if (fileheader != NULL) { + } + // 濡傛灉鎸囧畾浜 fileheader 閫夐」锛屾姏鍑洪敊璇 + else if (fileheader != NULL) { ereport(ERROR, (errcode(ERRCODE_OPERATE_INVALID_PARAM), errmsg("OBS foreign table does not support '%s' option", optFileHeader))); - } else if (OutputFilenamePrefix != NULL) { + } + // 濡傛灉鎸囧畾浜 OutputFilenamePrefix 閫夐」锛屾姏鍑洪敊璇 + else if (OutputFilenamePrefix != NULL) { ereport(ERROR, (errcode(ERRCODE_OPERATE_INVALID_PARAM), errmsg("OBS foreign table does not support '%s' option", optOutputFilePrefix))); - } else if (OutputFixAlignment != NULL) { + } + // 濡傛灉鎸囧畾浜 OutputFixAlignment 閫夐」锛屾姏鍑洪敊璇 + else if (OutputFixAlignment != NULL) { ereport(ERROR, (errcode(ERRCODE_OPERATE_INVALID_PARAM), errmsg("OBS foreign table does not support '%s' option", optOutputFixAlignment))); - } else if (doLogRemote) { + } + // 濡傛灉璁剧疆浜 remote_log 閫夐」锛屾姏鍑洪敊璇 + else if (doLogRemote) { ereport(ERROR, (errcode(ERRCODE_OPERATE_INVALID_PARAM), errmsg("OBS foreign table does not support remote_log option"))); } } - -void processOBSHaveToOptions(const char *accessKeyStr, const char *secretAccessKeyStr, - FileFormat format, const char *encryptStr, const char *chunksizeStr, bool writeOnly) +/* + * 鍔熻兘锛氬鐞嗗繀闇鐨 OBS 澶栭儴琛ㄩ夐」 + * + * 鍙傛暟鍒楄〃锛 + * accessKeyStr锛歝onst char 鎸囬拡锛岃〃绀 accessKey 閫夐」鍊 + * secretAccessKeyStr锛歝onst char 鎸囬拡锛岃〃绀 secretAccessKey 閫夐」鍊 + * format锛欶ileFormat锛岃〃绀烘枃浠舵牸寮忛夐」鍊 + * encryptStr锛歝onst char 鎸囬拡锛岃〃绀 encrypt 閫夐」鍊 + * chunksizeStr锛歝onst char 鎸囬拡锛岃〃绀 chunksize 閫夐」鍊 + * writeOnly锛歜ool锛屾寚绀烘槸鍚︽槸鍙啓妯″紡 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庡鐞嗗繀闇鐨 OBS 澶栭儴琛ㄩ夐」銆傚鏋滃繀闇鐨勯夐」鏈寚瀹氭垨閫夐」鍊兼棤鏁堬紝鍑芥暟浼氭姏鍑洪敊璇 + */ +void processOBSHaveToOptions(const char *accessKeyStr, const char *secretAccessKeyStr, FileFormat format, + const char *encryptStr, const char *chunksizeStr, bool writeOnly) { // default FORMAT_UNKNOWN value is TEXT if (format == FORMAT_UNKNOWN) { format = FORMAT_TEXT; } + // 妫鏌 accessKey 閫夐」鏄惁鎸囧畾 if (accessKeyStr == NULL) { ereport(ERROR, (errcode(ERRCODE_OPERATE_INVALID_PARAM), errmsg("OBS foreign table have to specify '%s' option", optAccessKey))); - } else if (secretAccessKeyStr == NULL) { + } + // 妫鏌 secretAccessKey 閫夐」鏄惁鎸囧畾 + else if (secretAccessKeyStr == NULL) { ereport(ERROR, (errcode(ERRCODE_OPERATE_INVALID_PARAM), errmsg("OBS foreign table have to specify '%s' option", optSecretAccessKey))); } @@ -548,17 +823,29 @@ void processOBSHaveToOptions(const char *accessKeyStr, const char *secretAccessK /* Error-out unallowed rage */ if (chunksize < 8 || chunksize > 512) { - ereport(ERROR, - (errcode(ERRCODE_OPERATE_INVALID_PARAM), - (errmsg("Invalid 'chunksize' option value '%s' for OBS Read-Only table, valid range [8, 512] in MB", - chunksizeStr)))); + ereport( + ERROR, + (errcode(ERRCODE_OPERATE_INVALID_PARAM), + (errmsg("Invalid 'chunksize' option value '%s' for OBS Read-Only table, valid range [8, 512] in MB", + chunksizeStr)))); } else if (writeOnly) { ereport(ERROR, (errcode(ERRCODE_OPERATE_INVALID_PARAM), (errmsg("Option 'chunksize' is not allowed in OBS write-only table")))); } } } - +/* + * 鍔熻兘锛氬鐞 OBS 澶栭儴琛ㄧ殑浣嶇疆閫夐」 + * + * 鍙傛暟鍒楄〃锛 + * writeOnly锛歜ool锛屾寚绀烘槸鍚︽槸鍙啓妯″紡 + * source锛歀ist 鎸囬拡锛屽寘鍚閮ㄨ〃鐨勪綅缃夐」鍒楄〃 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庡鐞 OBS 澶栭儴琛ㄧ殑浣嶇疆閫夐」銆傛牴鎹笉鍚屾ā寮忥紙鍙鎴栧彧鍐欙級锛岃繘琛屼笉鍚岀殑楠岃瘉銆 + * 鍦ㄥ彧鍐欐ā寮忎笅锛屼笉鍏佽鎸囧畾澶氫釜浣嶇疆銆 + * 鍦ㄥ彧璇绘ā寮忎笅锛屼細妫鏌ヤ綅缃夐」鏄惁鏈夐噸澶嶃 + */ void processOBSLocationOptions(bool writeOnly, List *source) { if (writeOnly) { @@ -606,7 +893,7 @@ void processOBSLocationOptions(bool writeOnly, List *source) temp_location_list = lappend(temp_location_list, makeString(temp_location)); } -DesErr: + DesErr: foreach (temp_location_cell, temp_location_list) { char *tempstr = strVal(lfirst(temp_location_cell)); pfree(tempstr); @@ -616,9 +903,22 @@ DesErr: ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("duplicated URL \"%s\" in LOCATION", location))); } } - -void processNoneOBSOptions(const char *chunksizeStr, const char *encryptStr, - const char *accessKeyStr, const char *secretAccessKeyStr, bool hasRegion) +/* + * 鍔熻兘锛氬鐞嗛潪 OBS 澶栭儴琛ㄧ殑閫夐」 + * + * 鍙傛暟鍒楄〃锛 + * chunksizeStr锛歝onst char 鎸囬拡锛屾寚鍚戦夐」 chunksize 鐨勫瓧绗︿覆鍊 + * encryptStr锛歝onst char 鎸囬拡锛屾寚鍚戦夐」 encrypt 鐨勫瓧绗︿覆鍊 + * accessKeyStr锛歝onst char 鎸囬拡锛屾寚鍚戦夐」 accessKey 鐨勫瓧绗︿覆鍊 + * secretAccessKeyStr锛歝onst char 鎸囬拡锛屾寚鍚戦夐」 secretAccessKey 鐨勫瓧绗︿覆鍊 + * hasRegion锛歜ool锛屾寚绀烘槸鍚﹀寘鍚 region 閫夐」 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庡鐞嗛潪 OBS 澶栭儴琛ㄧ殑閫夐」銆傛牴鎹笉鍚岄夐」锛屾墽琛岀浉搴旂殑楠岃瘉銆 + * 濡傛灉閫夐」涓嶆敮鎸侊紝灏嗙敓鎴愰敊璇秷鎭姤鍛娿 + */ +void processNoneOBSOptions(const char *chunksizeStr, const char *encryptStr, const char *accessKeyStr, + const char *secretAccessKeyStr, bool hasRegion) { if (chunksizeStr != NULL) { ereport(ERROR, (errcode(ERRCODE_OPERATE_INVALID_PARAM), @@ -637,7 +937,18 @@ void processNoneOBSOptions(const char *chunksizeStr, const char *encryptStr, errmsg("None OBS foreign table does not support '%s' option", OPTION_NAME_REGION))); } } - +/* + * 鍔熻兘锛氬鐞嗗垎甯冨紡瀵煎叆璁″垝鐨勯夐」 + * + * 鍙傛暟鍒楄〃锛 + * planstate锛欴istImportPlanState 缁撴瀯浣撴寚閽堬紝鐢ㄤ簬瀛樺偍瀵煎叆璁″垝鐨勭姸鎬佷俊鎭 + * options锛氶夐」鍒楄〃锛屽寘鍚敤浜庨厤缃鍏ユ搷浣滅殑鍚勭閫夐」 + * isPropagateToFE锛氬竷灏斿硷紝琛ㄧず鏄惁闇瑕佸皢閫夐」浼犳挱鍒板墠绔 + * isValidate锛氬竷灏斿硷紝琛ㄧず鏄惁鎵ц楠岃瘉鎿嶄綔 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庡鐞嗗鍏ヨ鍒掔殑鍚勭閫夐」锛屽寘鎷獙璇侀夐」鐨勫悎娉曟с佽缃粯璁ゅ笺佸紩鍙戦敊璇垨璀﹀憡绛夈 + */ void ProcessDistImportOptions(DistImportPlanState *planstate, List *options, bool isPropagateToFE, bool isValidate) { ListCell *lc = NULL; @@ -679,372 +990,520 @@ void ProcessDistImportOptions(DistImportPlanState *planstate, List *options, boo planstate->fileEncoding = -1; + // 閬嶅巻閫夐」鍒楄〃 foreach (lc, options) { DefElem *def = (DefElem *)lfirst(lc); + // 妫鏌ラ夐」鍚嶇О鏄惁涓 optChunkSize if (pg_strcasecmp(def->defname, optChunkSize) == 0) { chunksizeStr = defGetString(def); - } else if (pg_strcasecmp(def->defname, optEncrypt) == 0) { + } + // 妫鏌ラ夐」鍚嶇О鏄惁涓 optEncrypt + else if (pg_strcasecmp(def->defname, optEncrypt) == 0) { encryptStr = defGetString(def); - } else if (pg_strcasecmp(def->defname, optAccessKey) == 0) { + } + // 妫鏌ラ夐」鍚嶇О鏄惁涓 optAccessKey + else if (pg_strcasecmp(def->defname, optAccessKey) == 0) { accessKeyStr = defGetString(def); - } else if (pg_strcasecmp(def->defname, optSecretAccessKey) == 0) { + } + // 妫鏌ラ夐」鍚嶇О鏄惁涓 optSecretAccessKey + else if (pg_strcasecmp(def->defname, optSecretAccessKey) == 0) { secretAccessKeyStr = defGetString(def); - } else if (pg_strcasecmp(def->defname, optLocation) == 0) { + } + // 妫鏌ラ夐」鍚嶇О鏄惁涓 optLocation + else if (pg_strcasecmp(def->defname, optLocation) == 0) { locations = defGetString(def); planstate->filename = pstrdup(locations); planstate->source = DeserializeLocations(locations); - } else if (pg_strcasecmp(def->defname, OPTION_NAME_REGION) == 0) { - hasRegion = true; - } else if (pg_strcasecmp(def->defname, optMode) == 0) { - if (strcasecmp(strVal(def->arg), "normal") == 0) - planstate->mode = MODE_NORMAL; - else if (strcasecmp(strVal(def->arg), "shared") == 0) - planstate->mode = MODE_SHARED; - else if (strcasecmp(strVal(def->arg), "private") == 0) - planstate->mode = MODE_PRIVATE; - else - ereport(ERROR, (errcode(ERRCODE_OPERATE_INVALID_PARAM), - errmsg("Loading mode \"%s\" not recognized", strVal(def->arg)))); - specifyMode = true; - rmList = lappend(rmList, def); - } else if (pg_strcasecmp(def->defname, optRejectLimit) == 0) { - if (rejectLimitSpecified) - ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("conflicting or redundant options"))); - if (pg_strcasecmp(defGetString(def), "unlimited") == 0) - planstate->rejectLimit = REJECT_UNLIMITED; - else { - char *value = defGetString(def); - int limit = pg_strtoint32(value); - planstate->rejectLimit = (limit > 0 ? limit : 0); - } - rejectLimitSpecified = true; - rmList = lappend(rmList, def); - } else if (pg_strcasecmp(def->defname, optErrorRel) == 0) { - if (planstate->errorName != NULL) - ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("conflicting or redundant options"))); - planstate->errorName = defGetString(def); - rmList = lappend(rmList, def); - } else if (pg_strcasecmp(def->defname, optWriteOnly) == 0) { - if (writeOnlySpecified) - ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("conflicting or redundant options"))); - writeOnlySpecified = true; - planstate->writeOnly = defGetBoolean(def); - rmList = lappend(rmList, def); - } else if (pg_strcasecmp(def->defname, optEncoding) == 0) { - // We just get the encoding here. Do not remove it from the options list. - if (planstate->fileEncoding >= 0) - ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("conflicting or redundant options"))); - planstate->fileEncoding = pg_char_to_encoding(defGetString(def)); - if (planstate->fileEncoding < 0) - ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("argument to option \"%s\" must be a valid encoding name", def->defname))); - } else if (pg_strcasecmp(def->defname, optFormat) == 0) { - char *fmt = defGetString(def); - - if (strcasecmp(fmt, "text") == 0) - format = FORMAT_TEXT; - else if (strcasecmp(fmt, "csv") == 0) - format = FORMAT_CSV; - else if (strcasecmp(fmt, "fixed") == 0) - format = FORMAT_FIXED; - else - ereport(ERROR, - (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("LOAD format \"%s\" not recognized", fmt))); - } else if (pg_strcasecmp(def->defname, optFormatter) == 0) - UntransformFormatterOption(def); - else if (pg_strcasecmp(def->defname, optFileHeader) == 0) { - if (fileheader != NULL) - ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("conflicting or redundant options"))); - fileheader = defGetString(def); - } else if (pg_strcasecmp(def->defname, optOutputFilePrefix) == 0) { - if (OutputFilenamePrefix != NULL) - ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("conflicting or redundant options"))); - OutputFilenamePrefix = defGetString(def); - } else if (pg_strcasecmp(def->defname, optOutputFixAlignment) == 0) { - if (OutputFixAlignment != NULL) - ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("conflicting or redundant options"))); - OutputFixAlignment = defGetString(def); - } else if (pg_strcasecmp(def->defname, optHeader) == 0) { - hasHeader = defGetBoolean(def); - } else if (pg_strcasecmp(def->defname, optLogRemote) == 0) { - if (planstate->doLogRemote) - ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("conflicting or redundant options"))); - planstate->remoteName = defGetString(def); - planstate->doLogRemote = true; - rmList = lappend(rmList, def); - } else if (pg_strcasecmp(def->defname, optFillMissFields) == 0) - specifyFillMissing = true; - else if (pg_strcasecmp(def->defname, optIgnoreExtraData) == 0) - specifyIgnoreExtraData = true; - /* - * check whether bulkload compatible illegal chars option exists or not. - */ - else if (pg_strcasecmp(def->defname, optCompatibleIllegalChars) == 0) - specifyCompatibleIllegalChars = true; - /* - * check whether bulkload datetime format options exists or not. - */ - else if (pg_strcasecmp(def->defname, optDateFormat) == 0) { - specifyDateFormat = true; - /* - * check whether date format is valid; - */ - check_datetime_format(defGetString(def)); - } else if (pg_strcasecmp(def->defname, optTimeFormat) == 0) { - specifyTimeFormat = true; - /* - * check whether time format is valid; - */ - check_datetime_format(defGetString(def)); - } else if (pg_strcasecmp(def->defname, optTimestampFormat) == 0) { - specifyTimestampFormat = true; - /* - * check whether timestamp format is valid; - */ - check_datetime_format(defGetString(def)); - } else if (pg_strcasecmp(def->defname, optSmalldatetimeFormat) == 0) { - specifySmalldatetimeFormat = true; - /* - * check whether smalldatetime format is valid; - */ - check_datetime_format(defGetString(def)); - } else if (pg_strcasecmp(def->defname, optFix) == 0) { - char *end = NULL; - force_fix_width = (int)strtol(defGetString(def), &end, 10); - if (*end != '\0') - ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("invalid value of FIX"))); } + // 妫鏌ラ夐」鍚嶇О鏄惁涓 OPTION_NAME_REGION + else if (pg_strcasecmp(def->defname, OPTION_NAME_REGION) == 0) { + hasRegion = true; + } + // 妫鏌ラ夐」鍚嶇О鏄惁涓 optMode } + else if (pg_strcasecmp(def->defname, optMode) == 0) + { + if (strcasecmp(strVal(def->arg), "normal") == 0) + planstate->mode = MODE_NORMAL; + else if (strcasecmp(strVal(def->arg), "shared") == 0) + planstate->mode = MODE_SHARED; + else if (strcasecmp(strVal(def->arg), "private") == 0) + planstate->mode = MODE_PRIVATE; + else + ereport(ERROR, (errcode(ERRCODE_OPERATE_INVALID_PARAM), + errmsg("Loading mode \"%s\" not recognized", strVal(def->arg)))); + specifyMode = true; + rmList = lappend(rmList, def); + } // 妫鏌ラ夐」鍚嶇О鏄惁涓 optRejectLimit + else if (pg_strcasecmp(def->defname, optRejectLimit) == 0) + { + // 濡傛灉宸茬粡鎸囧畾浜 rejectLimit 閫夐」锛屽垯鎶ュ憡鍐茬獊鎴栧浣欑殑閫夐」閿欒 + if (rejectLimitSpecified) + ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("conflicting or redundant options"))); + + // 濡傛灉閫夐」鍊间负 "unlimited"锛屽垯灏 planstate->rejectLimit 璁剧疆涓 REJECT_UNLIMITED + if (pg_strcasecmp(defGetString(def), "unlimited") == 0) + planstate->rejectLimit = REJECT_UNLIMITED; + else { + // 鍚﹀垯锛屽皾璇曞皢閫夐」鍊艰В鏋愪负鏁存暟 + char *value = defGetString(def); + int limit = pg_strtoint32(value); + // 濡傛灉瑙f瀽鎴愬姛锛屽皢 limit 璁剧疆涓烘鏁帮紝鍚﹀垯璁剧疆涓 0 + planstate->rejectLimit = (limit > 0 ? limit : 0); + } + + // 鏍囪 rejectLimitSpecified 涓 true锛岃〃绀哄凡缁忔寚瀹氫簡 rejectLimit 閫夐」 + rejectLimitSpecified = true; + + // 灏嗗綋鍓嶉夐」娣诲姞鍒 rmList 鍒楄〃涓紝浠ヤ究绋嶅悗浠庨夐」鍒楄〃涓Щ闄 + rmList = lappend(rmList, def); + } + // 妫鏌ラ夐」鍚嶇О鏄惁涓 optErrorRel + else if (pg_strcasecmp(def->defname, optErrorRel) == 0) + { + // 濡傛灉 planstate->errorName 宸茬粡琚缃紝鍒欐姤鍛婂啿绐佹垨澶氫綑鐨勯夐」閿欒 + if (planstate->errorName != NULL) + ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("conflicting or redundant options"))); + + // 灏嗛夐」鍊艰缃负 planstate->errorName锛岃〃绀洪敊璇叧绯荤殑鍚嶇О + planstate->errorName = defGetString(def); + + // 灏嗗綋鍓嶉夐」娣诲姞鍒 rmList 鍒楄〃涓紝浠ヤ究绋嶅悗浠庨夐」鍒楄〃涓Щ闄 + rmList = lappend(rmList, def); + } + // 妫鏌ラ夐」鍚嶇О鏄惁涓 optWriteOnly + else if (pg_strcasecmp(def->defname, optWriteOnly) == 0) + { + // 濡傛灉宸茬粡鎸囧畾浜 writeOnly 閫夐」锛屽垯鎶ュ憡鍐茬獊鎴栧浣欑殑閫夐」閿欒 + if (writeOnlySpecified) + ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("conflicting or redundant options"))); + + // 鏍囪 writeOnlySpecified 涓 true锛岃〃绀哄凡缁忔寚瀹氫簡 writeOnly 閫夐」 + writeOnlySpecified = true; + + // 灏嗛夐」鍊艰缃负 planstate->writeOnly锛岃〃绀烘槸鍚︿负鍙啓鎿嶄綔 + planstate->writeOnly = defGetBoolean(def); + + // 灏嗗綋鍓嶉夐」娣诲姞鍒 rmList 鍒楄〃涓紝浠ヤ究绋嶅悗浠庨夐」鍒楄〃涓Щ闄 + rmList = lappend(rmList, def); + } + // 妫鏌ラ夐」鍚嶇О鏄惁涓 optEncoding + else if (pg_strcasecmp(def->defname, optEncoding) == 0) + { + // 浠呰幏鍙栫紪鐮侊紝涓嶄粠閫夐」鍒楄〃涓Щ闄ゅ畠 + // 濡傛灉宸茬粡璁剧疆浜 planstate->fileEncoding锛屽垯鎶ュ憡鍐茬獊鎴栧浣欑殑閫夐」閿欒 + if (planstate->fileEncoding >= 0) + ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("conflicting or redundant options"))); + + // 灏嗛夐」鍊艰В鏋愪负缂栫爜鍊硷紝骞惰缃负 planstate->fileEncoding + planstate->fileEncoding = pg_char_to_encoding(defGetString(def)); + + // 濡傛灉缂栫爜鏃犳晥锛屾姤鍛婃棤鏁堢殑鍙傛暟鍊奸敊璇 + if (planstate->fileEncoding < 0) + ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("argument to option \"%s\" must be a valid encoding name", def->defname))); + } + // 妫鏌ラ夐」鍚嶇О鏄惁涓 optFormat + else if (pg_strcasecmp(def->defname, optFormat) == 0) + { + // 鑾峰彇閫夐」鍊间綔涓烘枃浠舵牸寮忕殑瀛楃涓茶〃绀 + char *fmt = defGetString(def); + + // 鏍规嵁瀛楃涓插艰缃枃浠舵牸寮 + if (strcasecmp(fmt, "text") == 0) + format = FORMAT_TEXT; + else if (strcasecmp(fmt, "csv") == 0) + format = FORMAT_CSV; + else if (strcasecmp(fmt, "fixed") == 0) + format = FORMAT_FIXED; + else + // 濡傛灉鏍煎紡涓嶈璇嗗埆锛屾姤鍛婃棤鏁堢殑鍙傛暟鍊奸敊璇 + ereport(ERROR, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("LOAD format \"%s\" not recognized", fmt))); + } + // 妫鏌ラ夐」鍚嶇О鏄惁涓 optFormatter锛屽苟璋冪敤 UntransformFormatterOption 杩涜澶勭悊 + else if (pg_strcasecmp(def->defname, optFormatter) == 0) UntransformFormatterOption(def); + // 妫鏌ラ夐」鍚嶇О鏄惁涓 optFileHeader + else if (pg_strcasecmp(def->defname, optFileHeader) == 0) + { + // 濡傛灉宸茬粡鎸囧畾浜 fileheader 閫夐」锛屽垯鎶ュ憡鍐茬獊鎴栧浣欑殑閫夐」閿欒 + if (fileheader != NULL) + ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("conflicting or redundant options"))); + + // 灏嗛夐」鍊艰缃负 fileheader锛岃〃绀烘枃浠跺ご淇℃伅 + fileheader = defGetString(def); + } + // 妫鏌ラ夐」鍚嶇О鏄惁涓 optOutputFilePrefix + else if (pg_strcasecmp(def->defname, optOutputFilePrefix) == 0) + { + // 濡傛灉宸茬粡鎸囧畾浜 OutputFilenamePrefix 閫夐」锛屽垯鎶ュ憡鍐茬獊鎴栧浣欑殑閫夐」閿欒 + if (OutputFilenamePrefix != NULL) + ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("conflicting or redundant options"))); + + // 灏嗛夐」鍊艰缃负 OutputFilenamePrefix锛岃〃绀鸿緭鍑烘枃浠跺悕鍓嶇紑 + OutputFilenamePrefix = defGetString(def); + } + // 妫鏌ラ夐」鍚嶇О鏄惁涓 optOutputFixAlignment + else if (pg_strcasecmp(def->defname, optOutputFixAlignment) == 0) + { + // 濡傛灉宸茬粡鎸囧畾浜 OutputFixAlignment 閫夐」锛屽垯鎶ュ憡鍐茬獊鎴栧浣欑殑閫夐」閿欒 + if (OutputFixAlignment != NULL) + ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("conflicting or redundant options"))); + + // 灏嗛夐」鍊艰缃负 OutputFixAlignment锛岃〃绀鸿緭鍑哄浐瀹氬搴﹀榻 + OutputFixAlignment = defGetString(def); + } + // 妫鏌ラ夐」鍚嶇О鏄惁涓 optHeader + else if (pg_strcasecmp(def->defname, optHeader) == 0) + { + // 鑾峰彇閫夐」鍊硷紝琛ㄧず鏄惁瀛樺湪鏂囦欢澶 + hasHeader = defGetBoolean(def); + } + // 妫鏌ラ夐」鍚嶇О鏄惁涓 optLogRemote + else if (pg_strcasecmp(def->defname, optLogRemote) == 0) + { + // 濡傛灉宸茬粡鎸囧畾浜 planstate->doLogRemote 閫夐」锛屽垯鎶ュ憡鍐茬獊鎴栧浣欑殑閫夐」閿欒 + if (planstate->doLogRemote) + ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("conflicting or redundant options"))); + + // 灏嗛夐」鍊艰缃负 planstate->remoteName锛岃〃绀鸿繙绋嬫棩蹇楄褰曞悕绉 + planstate->remoteName = defGetString(def); + + // 鏍囪 planstate->doLogRemote 涓 true锛岃〃绀洪渶瑕佽褰曡繙绋嬫搷浣 + planstate->doLogRemote = true; + + // 灏嗗綋鍓嶉夐」娣诲姞鍒 rmList 鍒楄〃涓紝浠ヤ究绋嶅悗浠庨夐」鍒楄〃涓Щ闄 + rmList = lappend(rmList, def); + } + // 妫鏌ラ夐」鍚嶇О鏄惁涓 optFillMissFields + else if (pg_strcasecmp(def->defname, optFillMissFields) == 0) + // 鏍囪 specifyFillMissing 涓 true锛岃〃绀洪渶瑕佸~鍏呯己澶卞瓧娈 + specifyFillMissing = true; + // 妫鏌ラ夐」鍚嶇О鏄惁涓 optIgnoreExtraData + else if (pg_strcasecmp(def->defname, optIgnoreExtraData) == 0) + // 鏍囪 specifyIgnoreExtraData 涓 true锛岃〃绀洪渶瑕佸拷鐣ュ浣欐暟鎹 + specifyIgnoreExtraData = true; /* - * Validate OBS related optionsi, we only have to so in coodinator node like - * DDL planning for a OBS fdw table access. + * check whether bulkload compatible illegal chars option exists or not. */ - if (IS_PGXC_COORDINATOR && !isValidate) { - if (locations == NULL || planstate->source == NULL) - ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("LOCATION is required for the foreign tables"))); - - if (is_obs_protocol(locations)) { - /* First, blocks all OBS foreign table not allowed options */ - processOBSNoAllowOptions(specifyMode, fileheader, OutputFilenamePrefix, OutputFixAlignment, - planstate->doLogRemote); - - checkGSOBSPrefixNoAllowRegionOption(hasRegion, planstate->source); - - /* Second, blocking any OBS have-to have options that user doesn't specify */ - processOBSHaveToOptions(accessKeyStr, secretAccessKeyStr, format, encryptStr, chunksizeStr, - planstate->writeOnly); - - /* Verify duplicated location and write only options */ - processOBSLocationOptions(planstate->writeOnly, planstate->source); - - if (planstate->writeOnly) { - /* Do write only table verification */ - if (list_length(planstate->source) > 1) { - ereport(ERROR, - (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("can not specify multiple locations"))); - } - } - } else { - /* - * Also not allow none none-OBS table with chunksize, async, access_key, - * secure_access_key, encrypt, region options - */ - processNoneOBSOptions(chunksizeStr, encryptStr, accessKeyStr, secretAccessKeyStr, hasRegion); - } + else if (pg_strcasecmp(def->defname, optCompatibleIllegalChars) == 0) specifyCompatibleIllegalChars = true; + /* + * check whether bulkload datetime format options exists or not. + */ + else if (pg_strcasecmp(def->defname, optDateFormat) == 0) + { + specifyDateFormat = true; + /* + * check whether date format is valid; + */ + check_datetime_format(defGetString(def)); } - - // set default values - if (planstate->writeOnly) - planstate->mode = MODE_INVALID; - else if (planstate->mode == MODE_INVALID) - planstate->mode = MODE_NORMAL; - - if (!rejectLimitSpecified) - planstate->rejectLimit = 0; - - if (planstate->fileEncoding < 0) - planstate->fileEncoding = pg_get_client_encoding(); - - /* In dist_fdw_validator(), verify options just for FOREIGN TABLE. */ - if (!isValidate) { - // verify options - if (locations == NULL || planstate->source == NULL) - ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("LOCATION is required for the foreign tables"))); - - VerifyLocations(planstate->source); - - if (fileheader != NULL) { - VerifyFileHeader(fileheader); - } - if (OutputFilenamePrefix != NULL) { - VerifyFilenamePrefix(OutputFilenamePrefix, planstate->writeOnly); - } - if (OutputFixAlignment != NULL) { - VerifyFixAlignment(OutputFixAlignment, planstate->writeOnly, format); - } - - if (rejectLimitSpecified && (planstate->rejectLimit == 0 || planstate->rejectLimit < REJECT_UNLIMITED)) - ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("PER NODE REJECT LIMIT must be greater than 0"))); - - if (planstate->remoteName && !IsValidUserDefineName(planstate->remoteName)) - ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), - errmsg("Invalid name \'%s\' in REMOTE LOG", planstate->remoteName))); - if (rejectLimitSpecified && planstate->writeOnly) - ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), - errmsg("PER NODE REJECT LIMIT only available on READ ONLY foreign table"))); - if (rejectLimitSpecified && !planstate->errorName && !planstate->doLogRemote) - ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), - errmsg("PER NODE REJECT LIMIT only available with LOG INTO or REMOTE LOG"))); - if (planstate->doLogRemote && planstate->writeOnly) - ereport(ERROR, - (errcode(ERRCODE_SYNTAX_ERROR), errmsg("REMOTE LOG only available on READ ONLY foreign table"))); - if (planstate->doLogRemote && is_local_location(strVal(lfirst(list_head(planstate->source))))) - ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("REMOTE LOG only available on in NORMAL mode"))); - if (planstate->doLogRemote && planstate->writeOnly) - ereport(ERROR, - (errcode(ERRCODE_SYNTAX_ERROR), errmsg("REMOTE LOG only available on READ ONLY foreign table"))); - if (specifyFillMissing && planstate->writeOnly) - ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), - errmsg("FILL_MISSING_FIELDS only available on READ ONLY foreign table"))); - if (specifyIgnoreExtraData && planstate->writeOnly) - ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), - errmsg("IGNORE_EXTRA_DATA only available on READ ONLY foreign table"))); + else if (pg_strcasecmp(def->defname, optTimeFormat) == 0) + { + specifyTimeFormat = true; /* - * bulkload compatible illegal chars option isn't allowed for exporting. + * check whether time format is valid; */ - if (specifyCompatibleIllegalChars && planstate->writeOnly) - ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), - errmsg("COMPATIBLE_ILLEGAL_CHARS only available on READ ONLY foreign table"))); - /* - * bulkload datetime format options aren't allowed for exporting. - */ - if (specifyDateFormat && planstate->writeOnly) - ereport(ERROR, - (errcode(ERRCODE_SYNTAX_ERROR), errmsg("DATE_FORMAT only available on READ ONLY foreign table"))); - if (specifyTimeFormat && planstate->writeOnly) - ereport(ERROR, - (errcode(ERRCODE_SYNTAX_ERROR), errmsg("TIME_FORMAT only available on READ ONLY foreign table"))); - if (specifyTimestampFormat && planstate->writeOnly) - ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), - errmsg("TIMESTAMP_FORMAT only available on READ ONLY foreign table"))); - if (specifySmalldatetimeFormat && planstate->writeOnly) - ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), - errmsg("SMALLDATETIME_FORMAT only available on READ ONLY foreign table"))); - if (specifyMode && planstate->writeOnly) - ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("MODE only available on READ ONLY foreign table"))); - if (planstate->errorName && planstate->writeOnly) - ereport(ERROR, - (errcode(ERRCODE_SYNTAX_ERROR), errmsg("LOG INTO only available on READ ONLY foreign table"))); - /* - * Verify the location option. - * Remote location(gsfs://xxxx) can not be used in SHARED and PRIVATE mode. - * */ - foreach (lc, planstate->source) { - if (!is_valid_location(strVal(lfirst(lc)))) - ereport(ERROR, - (errcode(ERRCODE_SYNTAX_ERROR), errmsg("location \"%s\" is invalid", strVal(lfirst(lc))))); - if (!is_local_location(strVal(lfirst(lc))) && IS_SHARED_MODE(planstate->mode)) - ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), - errmsg("SHARED mode can not use location \"%s\"", strVal(lfirst(lc))))); - if (!is_local_location(strVal(lfirst(lc))) && !is_roach_location(strVal(lfirst(lc))) && - IS_PRIVATE_MODE(planstate->mode)) - ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), - errmsg("PRIVATE mode can not use location \"%s\"", strVal(lfirst(lc))))); - if (is_local_location(strVal(lfirst(lc))) && IS_NORMAL_MODE(planstate->mode)) - ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), - errmsg("Normal mode can not use location \"%s\"", strVal(lfirst(lc))))); - } - - // maybe multi-locations are given, just gsfs locations are avaliable. - // can only specify one local location. - Assert(planstate->source); - Assert(list_length(planstate->source) >= 1); - if (planstate->writeOnly && is_local_location(strVal(lfirst(list_head(planstate->source))))) { - if (list_length(planstate->source) > 1) { - ereport(ERROR, - (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("can not specify multiple local locations"))); - } - - const char *localpath = strVal(lfirst(list_head(planstate->source))); - if (localpath[0] == '.') { - ereport(ERROR, - (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("can not specify relative local locations"))); - } - } - - if (is_roach_location(strVal(lfirst(list_head(planstate->source))))) { - if (list_length(planstate->source) > 1) { - ereport(ERROR, - (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("can not specify multiple local locations"))); - } - } - - // for gsfs locations, we should specify FILEHEADER at a time - if (planstate->writeOnly && hasHeader && (fileheader == NULL) && - !is_local_location(strVal(lfirst(list_head(planstate->source))))) - ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), - errmsg("HEADER needs FILEHEADER specification in WRITE ONLY foreign table"))); - - if (format == FORMAT_CSV && planstate->mode == MODE_SHARED) - ereport(ERROR, - (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("SHARED mode can not be used with CSV format"))); - - /* for gds import/export, duplication locations are not allowed. - * Note: This check depends on the above verifications. - */ - if (IS_NORMAL_MODE(planstate->mode) || IS_INVALID_MODE(planstate->mode)) - CheckDupLocations(planstate->source); - -#ifndef ENABLE_MULTIPLE_NODES - /* GDS foreign tables are simply no longer needed in single node mode */ - if ((planstate->mode == MODE_NORMAL) && (!is_obs_protocol(locations))) { - ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("Un-supported feature"), - errdetail("Gauss Data Service(GDS) are not supported in single node mode."))); - } -#endif - - /* - * To achieve warning checking and propagation only when a read-only GDS foreign table - * is created with format fixed but no specified fix option, we will have to do duplicate - * save and check in here and above, due to our poorly-implemented option check. But - * still we cannot skip this warning if any other option pop an error due to the current - * option check as well as the error stack mechanism. - */ - if (isPropagateToFE && !planstate->writeOnly && (format == FORMAT_FIXED) && force_fix_width == 0) - ereport(WARNING, - (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("The above Read-Only foreign table is using FIXED mode without specifying 'fix' option."), - errhint("Please use 'fix' option to specify expected fixed record length in order to parser the " - "data file correctly."))); - - if (((IS_SHARED_MODE(planstate->mode) || IS_PRIVATE_MODE(planstate->mode)) && !initialuser()) - && !(isOperatoradmin(GetUserId()) && u_sess->attr.attr_security.operation_mode)) { - ereport(ERROR, - (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), - errmsg("Shared mode and private mode are only available for the supper user and Operatoradmin"))); - } + check_datetime_format(defGetString(def)); + } + else if (pg_strcasecmp(def->defname, optTimestampFormat) == 0) + { + specifyTimestampFormat = true; + /* + * check whether timestamp format is valid; + */ + check_datetime_format(defGetString(def)); + } + else if (pg_strcasecmp(def->defname, optSmalldatetimeFormat) == 0) + { + specifySmalldatetimeFormat = true; + /* + * check whether smalldatetime format is valid; + */ + check_datetime_format(defGetString(def)); + } + else if (pg_strcasecmp(def->defname, optFix) == 0) + { + char *end = NULL; + force_fix_width = (int)strtol(defGetString(def), &end, 10); + if (*end != '\0') + ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("invalid value of FIX"))); } - - // Remove the options that only available in foreign table - foreach (lc, rmList) - options = list_delete(options, lfirst(lc)); - if (rmList != NIL) - list_free_deep(rmList); - - planstate->options = options; } +/* + * Validate OBS related optionsi, we only have to so in coodinator node like + * DDL planning for a OBS fdw table access. + */ +if (IS_PGXC_COORDINATOR && !isValidate) { + if (locations == NULL || planstate->source == NULL) + ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("LOCATION is required for the foreign tables"))); + + if (is_obs_protocol(locations)) { + /* First, blocks all OBS foreign table not allowed options */ + processOBSNoAllowOptions(specifyMode, fileheader, OutputFilenamePrefix, OutputFixAlignment, + planstate->doLogRemote); + + checkGSOBSPrefixNoAllowRegionOption(hasRegion, planstate->source); + + /* Second, blocking any OBS have-to have options that user doesn't specify */ + processOBSHaveToOptions(accessKeyStr, secretAccessKeyStr, format, encryptStr, chunksizeStr, + planstate->writeOnly); + + /* Verify duplicated location and write only options */ + processOBSLocationOptions(planstate->writeOnly, planstate->source); + + if (planstate->writeOnly) { + /* Do write only table verification */ + if (list_length(planstate->source) > 1) { + ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("can not specify multiple locations"))); + } + } + } else { + /* + * Also not allow none none-OBS table with chunksize, async, access_key, + * secure_access_key, encrypt, region options + */ + processNoneOBSOptions(chunksizeStr, encryptStr, accessKeyStr, secretAccessKeyStr, hasRegion); + } +} + +// set default values +if (planstate->writeOnly) + planstate->mode = MODE_INVALID; +else if (planstate->mode == MODE_INVALID) + planstate->mode = MODE_NORMAL; + +if (!rejectLimitSpecified) + planstate->rejectLimit = 0; + +if (planstate->fileEncoding < 0) + planstate->fileEncoding = pg_get_client_encoding(); + +/* In dist_fdw_validator(), verify options just for FOREIGN TABLE. */ +// 濡傛灉涓嶆槸楠岃瘉妯″紡锛坕sValidate 涓哄亣锛夛紝鍒欐墽琛屼互涓嬫搷浣 +if (!isValidate) { + // verify options + if (locations == NULL || planstate->source == NULL) + ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("LOCATION is required for the foreign tables"))); + + // 楠岃瘉鏂囦欢浣嶇疆鐨勬湁鏁堟 + VerifyLocations(planstate->source); + + // 濡傛灉瀛樺湪鏂囦欢澶翠俊鎭紝楠岃瘉鏂囦欢澶寸殑鏈夋晥鎬 + if (fileheader != NULL) { + VerifyFileHeader(fileheader); + } + // 濡傛灉瀛樺湪杈撳嚭鏂囦欢鍚嶅墠缂锛岄獙璇佸叾鏈夋晥鎬 + if (OutputFilenamePrefix != NULL) { + VerifyFilenamePrefix(OutputFilenamePrefix, planstate->writeOnly); + } + // 濡傛灉瀛樺湪杈撳嚭鍥哄畾瀹藉害瀵归綈閫夐」锛岄獙璇佸叾鏈夋晥鎬 + if (OutputFixAlignment != NULL) { + VerifyFixAlignment(OutputFixAlignment, planstate->writeOnly, format); + } + + // 楠岃瘉 PER NODE REJECT LIMIT 閫夐」鐨勬湁鏁堟 + if (rejectLimitSpecified && (planstate->rejectLimit == 0 || planstate->rejectLimit < REJECT_UNLIMITED)) + ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("PER NODE REJECT LIMIT must be greater than 0"))); + + // 楠岃瘉杩滅▼鏃ュ織璁板綍鍚嶇О鐨勬湁鏁堟 + if (planstate->remoteName && !IsValidUserDefineName(planstate->remoteName)) + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR), errmsg("Invalid name \'%s\' in REMOTE LOG", planstate->remoteName))); + + // 楠岃瘉 PER NODE REJECT LIMIT 閫夐」涓庡啓鍏ユ搷浣滅殑鍏煎鎬 + if (rejectLimitSpecified && planstate->writeOnly) + ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("PER NODE REJECT LIMIT only available on READ ONLY foreign table"))); + + // 楠岃瘉 PER NODE REJECT LIMIT 閫夐」涓庢棩蹇楄褰曢夐」鐨勫吋瀹规 + if (rejectLimitSpecified && !planstate->errorName && !planstate->doLogRemote) + ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("PER NODE REJECT LIMIT only available with LOG INTO or REMOTE LOG"))); + + // 楠岃瘉 REMOTE LOG 閫夐」涓庡啓鍏ユ搷浣滅殑鍏煎鎬 + if (planstate->doLogRemote && planstate->writeOnly) + ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("REMOTE LOG only available on READ ONLY foreign table"))); + + // 楠岃瘉 REMOTE LOG 閫夐」鏄惁鍦 NORMAL 妯″紡涓嬫湁鏁 + if (planstate->doLogRemote && is_local_location(strVal(lfirst(list_head(planstate->source))))) + ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("REMOTE LOG only available on in NORMAL mode"))); + + // 楠岃瘉 REMOTE LOG 閫夐」涓庡啓鍏ユ搷浣滅殑鍏煎鎬 + if (planstate->doLogRemote && planstate->writeOnly) + ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("REMOTE LOG only available on READ ONLY foreign table"))); + + // 楠岃瘉 FILL_MISSING_FIELDS 閫夐」鏄惁鍦ㄥ啓鍏ユ搷浣滀笅鏈夋晥 + if (specifyFillMissing && planstate->writeOnly) + ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("FILL_MISSING_FIELDS only available on READ ONLY foreign table"))); + + // 楠岃瘉 IGNORE_EXTRA_DATA 閫夐」鏄惁鍦ㄥ啓鍏ユ搷浣滀笅鏈夋晥 + if (specifyIgnoreExtraData && planstate->writeOnly) + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR), errmsg("IGNORE_EXTRA_DATA only available on READ ONLY foreign table"))); + + // 楠岃瘉 COMPATIBLE_ILLEGAL_CHARS 閫夐」鏄惁鍦ㄥ啓鍏ユ搷浣滀笅鏈夋晥 + if (specifyCompatibleIllegalChars && planstate->writeOnly) + ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("COMPATIBLE_ILLEGAL_CHARS only available on READ ONLY foreign table"))); + + // 楠岃瘉 DATE_FORMAT 閫夐」鏄惁鍦ㄥ啓鍏ユ搷浣滀笅鏈夋晥 + if (specifyDateFormat && planstate->writeOnly) + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR), errmsg("DATE_FORMAT only available on READ ONLY foreign table"))); + + // 楠岃瘉 TIME_FORMAT 閫夐」鏄惁鍦ㄥ啓鍏ユ搷浣滀笅鏈夋晥 + if (specifyTimeFormat && planstate->writeOnly) + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR), errmsg("TIME_FORMAT only available on READ ONLY foreign table"))); + + // 楠岃瘉 TIMESTAMP_FORMAT 閫夐」鏄惁鍦ㄥ啓鍏ユ搷浣滀笅鏈夋晥 + if (specifyTimestampFormat && planstate->writeOnly) + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR), errmsg("TIMESTAMP_FORMAT only available on READ ONLY foreign table"))); + + // 楠岃瘉 SMALLDATETIME_FORMAT 閫夐」鏄惁鍦ㄥ啓鍏ユ搷浣滀笅鏈夋晥 + if (specifySmalldatetimeFormat && planstate->writeOnly) + ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("SMALLDATETIME_FORMAT only available on READ ONLY foreign table"))); + + // 楠岃瘉 MODE 閫夐」鏄惁鍦ㄥ啓鍏ユ搷浣滀笅鏈夋晥 + if (specifyMode && planstate->writeOnly) + ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("MODE only available on READ ONLY foreign table"))); + + // 楠岃瘉 LOG INTO 閫夐」鏄惁鍦ㄥ啓鍏ユ搷浣滀笅鏈夋晥 + if (planstate->errorName && planstate->writeOnly) + ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("LOG INTO only available on READ ONLY foreign table"))); + /* + * Verify the location option. + * Remote location(gsfs://xxxx) can not be used in SHARED and PRIVATE mode. + * */ + foreach (lc, planstate->source) { + if (!is_valid_location(strVal(lfirst(lc)))) + ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("location \"%s\" is invalid", strVal(lfirst(lc))))); + if (!is_local_location(strVal(lfirst(lc))) && IS_SHARED_MODE(planstate->mode)) + ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("SHARED mode can not use location \"%s\"", strVal(lfirst(lc))))); + if (!is_local_location(strVal(lfirst(lc))) && !is_roach_location(strVal(lfirst(lc))) && + IS_PRIVATE_MODE(planstate->mode)) + ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("PRIVATE mode can not use location \"%s\"", strVal(lfirst(lc))))); + if (is_local_location(strVal(lfirst(lc))) && IS_NORMAL_MODE(planstate->mode)) + ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("Normal mode can not use location \"%s\"", strVal(lfirst(lc))))); + } + + // maybe multi-locations are given, just gsfs locations are avaliable. + // can only specify one local location. + Assert(planstate->source); + Assert(list_length(planstate->source) >= 1); + if (planstate->writeOnly && is_local_location(strVal(lfirst(list_head(planstate->source))))) { + if (list_length(planstate->source) > 1) { + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("can not specify multiple local locations"))); + } + + const char *localpath = strVal(lfirst(list_head(planstate->source))); + if (localpath[0] == '.') { + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("can not specify relative local locations"))); + } + } + + if (is_roach_location(strVal(lfirst(list_head(planstate->source))))) { + if (list_length(planstate->source) > 1) { + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("can not specify multiple local locations"))); + } + } + + // for gsfs locations, we should specify FILEHEADER at a time + // 閽堝 gsfs 浣嶇疆锛屼竴娆″彧鑳芥寚瀹氫竴涓 FILEHEADER 閫夐」 + if (planstate->writeOnly && hasHeader && (fileheader == NULL) && + !is_local_location(strVal(lfirst(list_head(planstate->source))))) + ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("HEADER needs FILEHEADER specification in WRITE ONLY foreign table"))); + + // 楠岃瘉 CSV 鏍煎紡涓 SHARED 妯″紡鐨勫吋瀹规 + if (format == FORMAT_CSV && planstate->mode == MODE_SHARED) + ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("SHARED mode can not be used with CSV format"))); + + /* for gds import/export, duplication locations are not allowed. + * Note: This check depends on the above verifications. + */ + if (IS_NORMAL_MODE(planstate->mode) || IS_INVALID_MODE(planstate->mode)) + CheckDupLocations(planstate->source); + +#ifndef ENABLE_MULTIPLE_NODES + /* GDS foreign tables are simply no longer needed in single node mode */ + if ((planstate->mode == MODE_NORMAL) && (!is_obs_protocol(locations))) { + ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("Un-supported feature"), + errdetail("Gauss Data Service(GDS) are not supported in single node mode."))); + } +#endif + + /* + * To achieve warning checking and propagation only when a read-only GDS foreign table + * is created with format fixed but no specified fix option, we will have to do duplicate + * save and check in here and above, due to our poorly-implemented option check. But + * still we cannot skip this warning if any other option pop an error due to the current + * option check as well as the error stack mechanism. + */ + if (isPropagateToFE && !planstate->writeOnly && (format == FORMAT_FIXED) && force_fix_width == 0) + ereport(WARNING, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("The above Read-Only foreign table is using FIXED mode without specifying 'fix' option."), + errhint("Please use 'fix' option to specify expected fixed record length in order to parser the " + "data file correctly."))); + + // 濡傛灉鏄叡浜ā寮忔垨绉佹湁妯″紡锛屽苟涓斾笉鏄垵濮嬬敤鎴凤紝鍒欓渶瑕佹鏌ョ壒鏉 + if (((IS_SHARED_MODE(planstate->mode) || IS_PRIVATE_MODE(planstate->mode)) && !initialuser()) && + !(isOperatoradmin(GetUserId()) && u_sess->attr.attr_security.operation_mode)) { + ereport(ERROR, + (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), + errmsg("Shared mode and private mode are only available for the supper user and Operatoradmin"))); + } +} + +// Remove the options that only available in foreign table +foreach (lc, rmList) + options = list_delete(options, lfirst(lc)); +if (rmList != NIL) + list_free_deep(rmList); + +planstate->options = options; +} +/* + * 鍔熻兘锛氳В瀵嗗瘑閽ュ瓧绗︿覆骞跺瓨鍌ㄨВ瀵嗗悗鐨勭粨鏋 + * + * 鍙傛暟鍒楄〃锛 + * keyStr锛歝onst char 鎸囬拡锛屾寚鍚戦渶瑕佽В瀵嗙殑瀵嗛挜瀛楃涓 + * destplainStr锛歝har 鏁扮粍锛岀敤浜庡瓨鍌ㄨВ瀵嗗悗鐨勭粨鏋滅殑鐩爣瀛楃涓 + * destplainLength锛歶int32锛岀洰鏍囧瓧绗︿覆鐨勯暱搴 + * obskey锛歝onst char 鎸囬拡锛岀敤浜庤В瀵嗙殑瀵嗛挜 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庤В瀵嗗瘑閽ュ瓧绗︿覆锛屾牴鎹瓧绗︿覆鍓嶇紑杩涜涓嶅悓澶勭悊銆 + * 濡傛灉瀛楃涓蹭互鎸囧畾鍓嶇紑寮澶达紝灏嗕娇鐢ㄥ瘑閽ヨ繘琛岃В瀵嗭紝骞跺皢缁撴灉瀛樺偍鍦 destplainStr 涓 + * 鍚﹀垯锛屽皢鍘熷瀛楃涓插鍒跺埌 destplainStr 涓 + * 璇风‘淇濆湪璋冪敤姝ゅ嚱鏁颁箣鍓嶅凡鍒嗛厤瓒冲鐨勫唴瀛樻潵瀛樺偍瑙e瘑鍚庣殑缁撴灉銆 + */ void decryptKeyString(const char *keyStr, char destplainStr[], uint32 destplainLength, const char *obskey) { + // 瀹氫箟涓涓墠缂鐢ㄤ簬璇嗗埆鍔犲瘑瀛楃涓 #define ENCRYPT_STR_PREFIX "encryptstr" if (unlikely(keyStr == NULL)) { ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("Invalid key string"))); } if (strncmp(keyStr, ENCRYPT_STR_PREFIX, strlen(ENCRYPT_STR_PREFIX)) == 0) { + // 濡傛灉瀛楃涓蹭互鎸囧畾鍓嶇紑寮澶达紝杩涜瑙e瘑 keyStr = keyStr + strlen(ENCRYPT_STR_PREFIX); } else { + // 鍚﹀垯锛屽皢鍘熷瀛楃涓插鍒跺埌鐩爣瀛楃涓蹭腑 errno_t rc = memcpy_s(destplainStr, destplainLength, keyStr, strlen(keyStr) + 1); securec_check(rc, "\0", "\0"); return; @@ -1061,56 +1520,86 @@ void decryptKeyString(const char *keyStr, char destplainStr[], uint32 destplainL * tuple into pg_foreign_table when creating foreign tables in obs protocol. * @Input: pointer to options list */ +/* + * 鍔熻兘锛氳В瀵 OBS 澶栭儴琛ㄩ夐」涓殑瀵嗛挜瀛楃涓 + * + * 鍙傛暟鍒楄〃锛 + * options锛氭寚鍚戦夐」鍒楄〃鐨勬寚閽堬紝鍖呭惈闇瑕佽В瀵嗙殑閫夐」 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庝粠 OBS 澶栭儴琛ㄩ夐」涓В瀵嗗瘑閽ュ瓧绗︿覆銆 + * 瀹冮鍏堟鏌ラ夐」鍒楄〃涓槸鍚﹀瓨鍦 "secret_access_key" 閫夐」锛 + * 濡傛灉瀛樺湪锛屽垯灏嗗叾瑙e瘑骞舵浛鎹负瑙e瘑鍚庣殑鍊笺 + * 瑙e瘑鍚庣殑鍊煎皢浣滀负鏂扮殑閫夐」娣诲姞鍒伴夐」鍒楄〃涓 + * 璇风‘淇濆湪璋冪敤姝ゅ嚱鏁颁箣鍓嶅凡鍒嗛厤瓒冲鐨勫唴瀛樻潵瀛樺偍瑙e瘑鍚庣殑鍊笺 + */ void decryptOBSForeignTableOption(List **options) { - char *keyStr = NULL; - GS_UINT32 keyStrLen = 0; + char *keyStr = NULL; // 瀛樺偍瀵嗛挜瀛楃涓 + GS_UINT32 keyStrLen = 0; // 瀵嗛挜瀛楃涓查暱搴 - /* The maximum string length of the encrypt access key or encrypt access key is 1024 */ - char decryptSecretAccessKeyStr[DEST_CIPHER_LENGTH] = "\0"; - char decryptpassWordStr[DEST_CIPHER_LENGTH] = "\0"; - bool haveSecretAccessKey = false; + /* 鍔犲瘑鍚庣殑瀵嗛挜瀛楃涓叉渶澶ч暱搴︿负 1024 */ + char decryptSecretAccessKeyStr[DEST_CIPHER_LENGTH] = "\0"; // 瑙e瘑鍚庣殑瀵嗛挜瀛楃涓 + char decryptpassWordStr[DEST_CIPHER_LENGTH] = "\0"; // 瑙e瘑鍚庣殑瀵嗙爜瀛楃涓 + bool haveSecretAccessKey = false; // 鏍囧織鏄惁瀛樺湪 "secret_access_key" 閫夐」 errno_t rc = EOK; - ListCell *lc = NULL; - ListCell *prev = NULL; + ListCell *lc = NULL; // 鐢ㄤ簬閬嶅巻閫夐」鍒楄〃鐨勫垪琛ㄥ厓绱犳寚閽 + ListCell *prev = NULL; // 鐢ㄤ簬淇濆瓨涓婁竴涓垪琛ㄥ厓绱犳寚閽 foreach (lc, *options) { - DefElem *def = (DefElem *)lfirst(lc); + DefElem *def = (DefElem *)lfirst(lc); // 鑾峰彇鍒楄〃鍏冪礌涓殑閫夐」瀹氫箟 + + // 妫鏌ラ夐」鍚嶇О鏄惁涓 "secret_access_key" if (pg_strcasecmp(def->defname, optSecretAccessKey) == 0) { - haveSecretAccessKey = true; + haveSecretAccessKey = true; // 鏍囧織鎵惧埌浜 "secret_access_key" 閫夐」 - keyStr = defGetString(def); - decryptKeyString(keyStr, decryptSecretAccessKeyStr, DEST_CIPHER_LENGTH, NULL); + keyStr = defGetString(def); // 鑾峰彇鍔犲瘑鐨勫瘑閽ュ瓧绗︿覆 + decryptKeyString(keyStr, decryptSecretAccessKeyStr, DEST_CIPHER_LENGTH, NULL); // 瑙e瘑瀵嗛挜瀛楃涓 - *options = list_delete_cell(*options, lc, prev); + *options = list_delete_cell(*options, lc, prev); // 浠庨夐」鍒楄〃涓垹闄 "secret_access_key" 閫夐」 break; } - prev = lc; + prev = lc; // 淇濆瓨褰撳墠鍒楄〃鍏冪礌鎸囬拡锛屼互渚垮湪鍒犻櫎閫夐」鏃朵娇鐢 } + // 濡傛灉瀛樺湪 "secret_access_key" 閫夐」锛屽皢瑙e瘑鍚庣殑鍊间綔涓烘柊閫夐」娣诲姞鍒板垪琛ㄤ腑 if (haveSecretAccessKey) { - *options = lappend(*options, makeDefElem(pstrdup(optSecretAccessKey), - (Node *)makeString(pstrdup(decryptSecretAccessKeyStr)))); + *options = lappend( + *options, makeDefElem(pstrdup(optSecretAccessKey), (Node *)makeString(pstrdup(decryptSecretAccessKeyStr)))); } if (keyStr != NULL) { - /* safty concern, empty keyStr manually. */ + /* 瀹夊叏鑰冭檻锛屾墜鍔ㄦ竻绌 keyStr銆 */ keyStrLen = strlen(keyStr); rc = memset_s(keyStr, keyStrLen, 0, keyStrLen); securec_check(rc, "", ""); - pfree(keyStr); + pfree(keyStr); // 閲婃斁鍔犲瘑鐨勫瘑閽ュ瓧绗︿覆鐨勫唴瀛 } - /* safty concern, empty decryptAccessKeyStr & decryptSecretAccessKeyStr manually. */ + /* 瀹夊叏鑰冭檻锛屾墜鍔ㄦ竻绌 decryptSecretAccessKeyStr 鍜 decryptpassWordStr銆 */ rc = memset_s(decryptSecretAccessKeyStr, DEST_CIPHER_LENGTH, 0, DEST_CIPHER_LENGTH); securec_check(rc, "", ""); rc = memset_s(decryptpassWordStr, DEST_CIPHER_LENGTH, '\0', DEST_CIPHER_LENGTH); securec_check(rc, "", ""); } - +/* + * 鍔熻兘锛氳幏鍙栧垎甯冨紡瀵煎叆璁″垝鐨勯夐」 + * + * 鍙傛暟鍒楄〃锛 + * relOid锛氬閮ㄨ〃鍏宠仈鐨勫璞℃爣璇嗙锛圤ID锛 + * planstate锛欴istImportPlanState 缁撴瀯鐨勬寚閽堬紝鐢ㄤ簬淇濆瓨瀵煎叆璁″垝鐨勭姸鎬佷俊鎭 + * fOptions锛欶oreignOptions 缁撴瀯鐨勬寚閽堬紝鍖呭惈澶栭儴琛ㄧ殑閫夐」 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庤幏鍙栧垎甯冨紡瀵煎叆璁″垝鐨勯夐」锛屼互渚挎墽琛屽垎甯冨紡鏁版嵁瀵煎叆鎿嶄綔銆 + * 濡傛灉 fOptions 涓 NULL锛屽垯浠庡閮ㄨ〃銆佸閮ㄦ湇鍔″櫒鍜屽閮ㄦ暟鎹寘瑁呭櫒涓彁鍙栭夐」锛屽苟鍚堝苟涓轰竴涓夐」鍒楄〃銆 + * 濡傛灉 fOptions 涓嶄负 NULL锛屽垯鐩存帴浣跨敤 fOptions 涓殑閫夐」鍒楄〃銆 + * 鍦ㄨ幏鍙栭夐」鍚庯紝杩樹細瀵 OBS 瀛樺偍璁块棶瀵嗛挜鍜屽畨鍏ㄨ闂瘑閽ヨ繘琛岃В瀵嗗鐞嗐 + * 鏈鍚庯紝璋冪敤 ProcessDistImportOptions 鍑芥暟澶勭悊閫夐」锛屼互鍒濆鍖栧鍏ヨ鍒掔殑鐘舵併 + */ void GetDistImportOptions(Oid relOid, DistImportPlanState *planstate, ForeignOptions *fOptions = NULL) { - List *options = NIL; + List *options = NIL; // 鐢ㄤ簬瀛樺偍閫夐」鐨勫垪琛 if (fOptions == NULL) { ForeignTable *table = NULL; ForeignServer *server = NULL; @@ -1124,45 +1613,59 @@ void GetDistImportOptions(Oid relOid, DistImportPlanState *planstate, ForeignOpt * no point in examining anything except the foreign table's own options. * Simplify?) */ - table = GetForeignTable(relOid); - server = GetForeignServer(table->serverid); - wrapper = GetForeignDataWrapper(server->fdwid); + table = GetForeignTable(relOid); // 鑾峰彇澶栭儴琛ㄤ俊鎭 + server = GetForeignServer(table->serverid); // 鑾峰彇澶栭儴鏈嶅姟鍣ㄤ俊鎭 + wrapper = GetForeignDataWrapper(server->fdwid); // 鑾峰彇澶栭儴鏁版嵁鍖呰鍣ㄤ俊鎭 - options = NIL; - options = list_concat(options, wrapper->options); - options = list_concat(options, server->options); - options = list_concat(options, table->options); + options = NIL; // 鍒濆鍖栭夐」鍒楄〃 + options = list_concat(options, wrapper->options); // 鍚堝苟鍖呰鍣ㄩ夐」 + options = list_concat(options, server->options); // 鍚堝苟鏈嶅姟鍣ㄩ夐」 + options = list_concat(options, table->options); // 鍚堝苟澶栭儴琛ㄩ夐」 - options = adaptOBSURL(options); + options = adaptOBSURL(options); // 澶勭悊 OBS URL 閫夐」 if (table->write_only) options = lappend(options, makeDefElem(pstrdup(optWriteOnly), (Node *)makeString(pstrdup("true")))); } else { Assert(fOptions->fOptions != NULL); - options = fOptions->fOptions; + options = fOptions->fOptions; // 鐩存帴浣跨敤鎻愪緵鐨勯夐」鍒楄〃 } + // 涓 OBS 瀛樺偍璁块棶瀵嗛挜鍜屽畨鍏ㄨ闂瘑閽ユ坊鍔犺В瀵嗗鐞 // Add decrpyt function for obs access key and security access key in obs options decryptOBSForeignTableOption(&options); - ProcessDistImportOptions(planstate, options, false); + ProcessDistImportOptions(planstate, options, false); // 澶勭悊閫夐」锛屽垵濮嬪寲瀵煎叆璁″垝鐘舵 } /* * distImportGetRelSize * Obtain relation size estimates for a foreign table */ +/* + * 鍔熻兘锛氳绠楀垎甯冨紡瀵煎叆澶栭儴琛ㄧ殑鍏崇郴澶у皬浼扮畻 + * + * 鍙傛暟鍒楄〃锛 + * root锛歅lannerInfo 缁撴瀯鐨勬寚閽堬紝鍖呭惈鏌ヨ瑙勫垝淇℃伅 + * baserel锛歊elOptInfo 缁撴瀯鐨勬寚閽堬紝鍖呭惈鍩烘湰鍏崇郴鐨勬煡璇㈣鍒掍俊鎭 + * foreigntableid锛氬閮ㄨ〃鐨勫璞℃爣璇嗙锛圤ID锛 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庤绠楀垎甯冨紡瀵煎叆澶栭儴琛ㄧ殑鍏崇郴澶у皬浼扮畻銆傞鍏堣幏鍙栧閮ㄨ〃鐨勯夐」锛岀劧鍚庢墽琛屽ぇ灏忎及绠椼 + * 鍑芥暟鍒嗛厤浜 DistImportPlanState 缁撴瀯骞跺皢鍏惰祴缁 baserel->fdw_private 浠ヤ繚瀛樺鍏ヨ鍒掔殑鐘舵佷俊鎭 + * 鏈鍚庯紝璋冪敤 estimate_size 鍑芥暟杩涜鍏崇郴澶у皬浼扮畻銆 + */ void distImportGetRelSize(PlannerInfo *root, RelOptInfo *baserel, Oid foreigntableid) { - DistImportPlanState *planstate = NULL; + DistImportPlanState *planstate = NULL; // 瀛樺偍瀵煎叆璁″垝鐨勭姸鎬佷俊鎭殑鎸囬拡 /* * Fetch options. We only need filename at this point, but we might as * well get everything and not need to re-fetch it later in planning. */ - planstate = (DistImportPlanState *)palloc0(sizeof(DistImportPlanState)); - GetDistImportOptions(foreigntableid, planstate); - baserel->fdw_private = (void *)planstate; + planstate = (DistImportPlanState *)palloc0(sizeof(DistImportPlanState)); // 鍒嗛厤瀵煎叆璁″垝鐘舵佺粨鏋勭殑鍐呭瓨 + GetDistImportOptions(foreigntableid, planstate); // 鑾峰彇澶栭儴琛ㄩ夐」 + baserel->fdw_private = (void *)planstate; // 灏嗗鍏ヨ鍒掔姸鎬佽祴缁欏熀鏈叧绯荤殑 fdw_private 瀛楁 /* Estimate relation size */ estimate_size(root, baserel, planstate); @@ -1176,13 +1679,26 @@ void distImportGetRelSize(PlannerInfo *root, RelOptInfo *baserel, Oid foreigntab * possible access path, which simply returns all records in the order in * the data file. */ +/* + * 鍔熻兘锛氱敓鎴愬垎甯冨紡瀵煎叆澶栭儴琛ㄧ殑鏌ヨ璺緞 + * + * 鍙傛暟鍒楄〃锛 + * root锛歅lannerInfo 缁撴瀯鐨勬寚閽堬紝鍖呭惈鏌ヨ瑙勫垝淇℃伅 + * baserel锛歊elOptInfo 缁撴瀯鐨勬寚閽堬紝鍖呭惈鍩烘湰鍏崇郴鐨勬煡璇㈣鍒掍俊鎭 + * foreigntableid锛氬閮ㄨ〃鐨勫璞℃爣璇嗙锛圤ID锛 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庣敓鎴愬垎甯冨紡瀵煎叆澶栭儴琛ㄧ殑鏌ヨ璺緞銆傚畠棣栧厛妫鏌ユ槸鍚﹀簲閫夋嫨鎬у湴鎵ц浜岃繘鍒惰浆鎹紝鐒跺悗浼扮畻鎴愭湰銆 + * 鎺ヤ笅鏉ワ紝瀹冨垱寤轰竴涓 ForeignPath 鑺傜偣锛屽苟灏嗗叾娣诲姞涓哄敮涓鐨勫彲鑳借矾寰勩傚畠浣跨敤 fdw_private 鍒楄〃鏉ユ惡甯 convert_selectively + * 閫夐」锛 璇ラ夐」灏嗕紶鎾埌 Plan 鑺傜偣鐨 fdw_private 鍒楄〃涓 + */ void distImportGetPaths(PlannerInfo *root, RelOptInfo *baserel, Oid foreigntableid) { - DistImportPlanState *planstate = (DistImportPlanState *)baserel->fdw_private; + DistImportPlanState *planstate = (DistImportPlanState *)baserel->fdw_private; // 鑾峰彇瀵煎叆璁″垝鐨勭姸鎬佷俊鎭 Cost startup_cost; Cost total_cost; - List *columns = NIL; - List *coptions = NIL; + List *columns = NIL; // 瀛樺偍闇瑕佽繘琛屼簩杩涘埗杞崲鐨勫垪 + List *coptions = NIL; // 瀛樺偍 convert_selectively 閫夐」 /* Decide whether to selectively perform binary conversion */ if (check_selective_binary_conversion(baserel, foreigntableid, &columns)) @@ -1206,6 +1722,21 @@ void distImportGetPaths(PlannerInfo *root, RelOptInfo *baserel, Oid foreigntable * distGetForeignPlan * Create a ForeignScan plan node for scanning the foreign table */ +/* + * 鍔熻兘锛氱敓鎴愬垎甯冨紡瀵煎叆澶栭儴琛ㄧ殑鏌ヨ璁″垝 + * + * 鍙傛暟鍒楄〃锛 + * root锛歅lannerInfo 缁撴瀯鐨勬寚閽堬紝鍖呭惈鏌ヨ瑙勫垝淇℃伅 + * baserel锛歊elOptInfo 缁撴瀯鐨勬寚閽堬紝鍖呭惈鍩烘湰鍏崇郴鐨勬煡璇㈣鍒掍俊鎭 + * foreigntableid锛氬閮ㄨ〃鐨勫璞℃爣璇嗙锛圤ID锛 + * best_path锛欶oreignPath 缁撴瀯鐨勬寚閽堬紝鍖呭惈鏈浣虫煡璇㈣矾寰勪俊鎭 + * tlist锛氱洰鏍囧垪琛紝琛ㄧず鏌ヨ鐨勭洰鏍囧垪 + * scan_clauses锛氭壂鎻忓瓙鍙ュ垪琛紝琛ㄧず鎵弿绾︽潫鏉′欢 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庣敓鎴愬垎甯冨紡瀵煎叆澶栭儴琛ㄧ殑鏌ヨ璁″垝銆傚畠棣栧厛妫鏌ユ墽琛岀幆澧冨拰绾︽潫鏉′欢锛 + * 鐒跺悗鍒涘缓 ForeignScan 鑺傜偣锛岃缃叾灞炴э紝骞惰繑鍥炶鑺傜偣銆 + */ ForeignScan *distImportGetPlan(PlannerInfo *root, RelOptInfo *baserel, Oid foreigntableid, ForeignPath *best_path, List *tlist, List *scan_clauses) { @@ -1290,6 +1821,16 @@ ForeignScan *distImportGetPlan(PlannerInfo *root, RelOptInfo *baserel, Oid forei * distExplainForeignScan * Produce extra output for EXPLAIN */ +/* + * 鍔熻兘锛氱敓鎴愮敤浜庤В閲婃煡璇㈣鍒掔殑淇℃伅 + * + * 鍙傛暟鍒楄〃锛 + * node锛欶oreignScanState 缁撴瀯鐨勬寚閽堬紝鍖呭惈澶栭儴鎵弿鐨勭姸鎬佷俊鎭 + * es锛欵xplainState 缁撴瀯鐨勬寚閽堬紝鍖呭惈鐢熸垚瑙i噴淇℃伅鐨勭姸鎬佷俊鎭 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庣敓鎴愮敤浜庤В閲婃煡璇㈣鍒掔殑淇℃伅銆傚畠鎻愬彇鏂囦欢鍚嶇瓑閫夐」淇℃伅锛屽苟灏嗗叾鍖呭惈鍦ㄨВ閲婅緭鍑轰腑銆 + */ void distImportExplain(ForeignScanState *node, ExplainState *es) { char *filename = NULL; @@ -1333,6 +1874,18 @@ void distImportExplain(ForeignScanState *node, ExplainState *es) * @OUT obs_copy_options: struct for ObsCopyOptions * @IN options: options list */ +/* + * 鍔熻兘锛氫粠澶栭儴琛ㄧ殑閫夐」鍒楄〃涓彁鍙 OBS 澶栭儴琛ㄧ殑閫夐」 + * + * 鍙傛暟鍒楄〃锛 + * obs_copy_options锛歄bsCopyOptions 缁撴瀯鐨勬寚閽堬紝鐢ㄤ簬瀛樺偍 OBS 澶栭儴琛ㄧ殑閫夐」 + * options锛氬閮ㄨ〃閫夐」鍒楄〃锛屽寘鍚 OBS 澶栭儴琛ㄧ殑鐩稿叧閫夐」 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庝粠澶栭儴琛ㄧ殑閫夐」鍒楄〃涓彁鍙 OBS 澶栭儴琛ㄧ殑閫夐」銆傚畠閬嶅巻閫夐」鍒楄〃锛屽皢閫夐」鐨勫艰В鏋愬苟瀛樺偍鍦 obs_copy_options + * 缁撴瀯涓紝 杩欎簺閫夐」鍖呮嫭 chunksize銆乪ncrypt銆乤ccess_key 鍜 secret_access_key銆傚鏋滈夐」鏈彁渚涳紝灏嗕娇鐢ㄩ粯璁ゅ笺 + * 鍑芥暟杩樻鏌ラ夐」鐨勫悎娉曟э紝骞跺湪鍙戠幇鏃犳晥鍊兼椂鐢熸垚閿欒娑堟伅鎶ュ憡銆 + */ void getOBSOptions(ObsCopyOptions *obs_copy_options, List *options) { char *accessKeyStr = NULL; @@ -1350,9 +1903,7 @@ void getOBSOptions(ObsCopyOptions *obs_copy_options, List *options) if (pg_strcasecmp(def->defname, optChunkSize) == 0) { uint32_t chunksize = atoi(defGetString(def)); if (chunksize > (PG_UINT32_MAX / (1024 * 1024))) { - ereport(ERROR, - (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("obs option chunksize is too large"))); + ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("obs option chunksize is too large"))); } obs_copy_options->chunksize = chunksize * 1024 * 1024; } else if (pg_strcasecmp(def->defname, optEncrypt) == 0) { @@ -1368,11 +1919,32 @@ void getOBSOptions(ObsCopyOptions *obs_copy_options, List *options) } /* Set obs options for data structure */ +/* + * 鍔熻兘锛氬垵濮嬪寲 OBS 瀵煎叆杩囩▼鐨勬墽琛岀姸鎬 + * + * 鍙傛暟鍒楄〃锛 + * importState锛欴istImportExecutionState 缁撴瀯鐨勬寚閽堬紝鐢ㄤ簬瀛樺偍瀵煎叆杩囩▼鐨勬墽琛岀姸鎬 + * planstate锛欴istImportPlanState 缁撴瀯鐨勬寚閽堬紝鍖呭惈瀵煎叆璁″垝鐨勭浉鍏充俊鎭 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庡垵濮嬪寲 OBS 瀵煎叆杩囩▼鐨勬墽琛岀姸鎬併傚湪瀵煎叆杩囩▼涓紝鏍规嵁瀵煎叆璁″垝涓殑鏂囦欢鍚嶅垽鏂槸鍚︿娇鐢 OBS 鍗忚銆 + * 濡傛灉浣跨敤 OBS 鍗忚锛屽嚱鏁颁細鎻愬彇骞跺瓨鍌 OBS 瀵煎叆閫夐」锛屽 chunksize銆乪ncrypt銆乤ccess_key 鍜 secret_access_key銆 + * 杩欎簺閫夐」灏嗗湪鍚庣画鐨勫鍏ヨ繃绋嬩腑浣跨敤銆傚鏋滀笉浣跨敤 OBS 鍗忚锛屽垯涓嶆墽琛屼换浣曟搷浣溿 + * + * OBS 瀵煎叆閫夐」瑙i噴锛 + * - chunksize锛氭寚瀹氬鍏ユ椂鐨勫潡澶у皬锛堜互瀛楄妭涓哄崟浣嶏級锛岀敤浜庢帶鍒跺鍏ユ暟鎹殑鍒嗗潡澶勭悊銆 + * - encrypt锛氭寚瀹氭槸鍚︿娇鐢ㄥ姞瀵嗘潵浼犺緭鏁版嵁銆 + * - access_key锛氱敤浜庤闂 OBS 瀛樺偍鐨勮闂瘑閽ャ + * - secret_access_key锛氱敤浜庤闂 OBS 瀛樺偍鐨勭瀵嗚闂瘑閽ャ + */ void distOBSImportBegin(DistImportExecutionState *importState, DistImportPlanState *planstate) { + // 纭繚浼犲叆鐨勬寚閽堝弬鏁颁笉涓虹┖ Assert(importState && planstate); + // 妫鏌ュ鍏ユ枃浠舵槸鍚︿娇鐢 OBS 鍗忚 if (is_obs_protocol(planstate->filename)) { + // 濡傛灉浣跨敤 OBS 鍗忚锛屽垯鎻愬彇 OBS 瀵煎叆閫夐」骞跺瓨鍌ㄥ埌 importState 涓 getOBSOptions(&importState->obs_copy_options, planstate->options); } } @@ -1381,6 +1953,19 @@ void distOBSImportBegin(DistImportExecutionState *importState, DistImportPlanSta * distBeginForeignScan * Initiate access to the file by creating CopyState */ +/* + * 鍔熻兘锛氬垵濮嬪寲鍒嗗竷寮忓鍏ョ殑鎵ц鐘舵佸苟璁剧疆瀵煎叆閫夐」 + * + * 鍙傛暟鍒楄〃锛 + * node锛欶oreignScanState 缁撴瀯鐨勬寚閽堬紝琛ㄧず鍒嗗竷寮忓鍏ョ殑鎵ц鐘舵 + * eflags锛氭墽琛屾爣蹇楋紝鐢ㄤ簬鍒ゆ柇鏄惁鍦 EXPLAIN 妯″紡涓嬫墽琛 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庡垵濮嬪寲鍒嗗竷寮忓鍏ョ殑鎵ц鐘舵侊紝鍚屾椂鏍规嵁瀵煎叆璁″垝涓殑閫夐」璁剧疆鎵ц鐘舵佺殑灞炴с傚嚱鏁板皢鍒嗗竷寮忓鍏 + * 鐨勬墽琛岀姸鎬佸瓨鍌ㄥ湪 node->fdw_state 涓紝浠ヤ究鍦ㄥ鍏ヨ繃绋嬩腑浣跨敤銆傝鍑芥暟杩樿礋璐f彁鍙 OBS 瀵煎叆閫夐」锛屽鏋滃鍏 + * 鐨勬枃浠朵娇鐢 OBS 鍗忚銆 + * + */ void distImportBegin(ForeignScanState *node, int eflags) { DistImportExecutionState *importState = NULL; @@ -1419,8 +2004,10 @@ void distImportBegin(ForeignScanState *node, int eflags) * It means that the current node has meta data. need to get options * from catalog. */ - GetDistImportOptions(RelationGetRelid(node->ss.ss_currentRelation), &planstate, NULL); + // 濡傛灉褰撳墠鑺傜偣娌℃湁鍏冩暟鎹紝浠庣洰褰曚腑鑾峰彇閫夐」 + GGetDistImportOptions(RelationGetRelid(node->ss.ss_currentRelation), &planstate, NULL); } else { + // 鍚﹀垯锛屼娇鐢 ForeignScan 鑺傜偣涓殑閫夐」 GetDistImportOptions(RelationGetRelid(node->ss.ss_currentRelation), &planstate, foreignScan->options); } @@ -1494,7 +2081,7 @@ void distImportBegin(ForeignScanState *node, int eflags) * Foreign Scan Thread don't unlink this cache file, * it just open and write error data into this cache file. */ - ErrLogInfo err_info = { u_sess->stream_cxt.smp_id, false }; + ErrLogInfo err_info = {u_sess->stream_cxt.smp_id, false}; importState->needSaveError = scan->needSaveError; if (!importState->needSaveError) @@ -1506,8 +2093,8 @@ void distImportBegin(ForeignScanState *node, int eflags) logger = New(CurrentMemoryContext) GDSErrorLogger; importState->elogger = lappend(importState->elogger, logger); if (strlen(planstate.remoteName) == 0) - remoteName = (char*)importState->cur_relname; - logger->Initialize((void*)importState->io_stream, (TupleDesc)remoteName, err_info); + remoteName = (char *)importState->cur_relname; + logger->Initialize((void *)importState->io_stream, (TupleDesc)remoteName, err_info); } if (scan->errCache != NULL) { @@ -1520,23 +2107,51 @@ void distImportBegin(ForeignScanState *node, int eflags) } } } - +/* + * 鍔熻兘锛氭娴嬪苟鎶ュ憡闈炴硶瀛楃寮傚父鐨勯槇鍊 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庣洃娴嬮潪娉曞瓧绗﹀紓甯哥殑鏁伴噺鏄惁瓒呰繃浜嗛瀹氱殑闃堝硷紝骞跺湪瓒呰繃闃堝兼椂鐢熸垚璀﹀憡娑堟伅銆 + * 杩欐湁鍔╀簬璀﹀憡鐢ㄦ埛鍙兘瀛樺湪鐨勬暟鎹崯鍧忔垨瑙g爜闂銆傚鏋滈潪娉曞瓧绗﹀紓甯哥殑鏁伴噺瓒呰繃浜嗛槇鍊硷紝 + * 鍒欏嚱鏁板皢鐢熸垚涓鏉¤鍛婃秷鎭紝鎻愰啋鐢ㄦ埛妫鏌ユ暟鎹殑缂栫爜璁剧疆鏄惁姝g‘銆 + */ void ReportIllegalCharExceptionThreshold() { + // 妫鏌ラ潪娉曞瓧绗﹀紓甯告暟閲忔槸鍚﹁秴杩囬槇鍊 if (t_thrd.bulk_cxt.illegal_character_err_cnt >= ILLEGAL_CHARACTERS_ERR_THRESHOLD && !t_thrd.bulk_cxt.illegal_character_err_threshold_reported) { + // 濡傛灉瓒呰繃闃堝间笖灏氭湭鎶ュ憡锛屽垯鐢熸垚璀﹀憡娑堟伅 ereport(WARNING, (errmodule(MOD_GDS), errmsg("Number of illegal character exceptions exceed the threshold."), errdetail("Please make sure that you are using right encoding setting to decode incomming data."))); + // 鏍囪宸叉姤鍛婅繃闃堝艰鍛婏紝浠ラ伩鍏嶉噸澶嶆姤鍛 t_thrd.bulk_cxt.illegal_character_err_threshold_reported = true; } } - /* * distterateForeignScan * Read next record from the data file and store it into the * ScanTupleSlot as a virtual tuple */ +/* + * 鍔熻兘锛氭墽琛屽垎甯冨紡瀵煎叆鎿嶄綔锛岃鍙栧閮ㄦ暟鎹苟濉厖鍏冪粍琛ㄦЫ + * + * 鍙傛暟鍒楄〃锛 + * node锛氬閮ㄦ壂鎻忕姸鎬 + * + * 杩斿洖鍊硷細 + * TupleTableSlot锛氬~鍏呯殑鍏冪粍琛ㄦЫ + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庢墽琛屽垎甯冨紡瀵煎叆鎿嶄綔锛屼粠澶栭儴鏁版嵁婧愯鍙栨暟鎹紝骞跺皢鏁版嵁濉厖鍒板厓缁勮〃妲戒腑銆 + * 鍑芥暟浣跨敤澶栭儴鎵弿鐘舵佷腑鐨勪俊鎭潵绠$悊瀵煎叆杩囩▼銆傚畠鍦ㄦ瘡娆¤皟鐢ㄦ椂浠庡閮ㄦ暟鎹簮璇诲彇涓琛屾暟鎹紝 + * 灏嗘暟鎹~鍏呭埌鍏冪粍琛ㄦЫ涓紝骞惰繑鍥炶鍏冪粍琛ㄦЫ銆 + * 鍑芥暟杩樺鐞嗕簡闈炴硶瀛楃寮傚父鍜岄敊璇仮澶嶇殑鎯呭喌銆 + * + * 绀轰緥鐢ㄦ硶锛 + * 閫氬父鍦ㄦ墽琛屽閮ㄦ暟鎹鍏ユ搷浣滄椂锛屽彲浠ラ噸澶嶈皟鐢ㄦ鍑芥暟浠ラ愯璇诲彇澶栭儴鏁版嵁骞跺~鍏呭厓缁勮〃妲姐 + * 濡傛灉鍙戠敓闈炴硶瀛楃寮傚父鎴栧叾浠栭敊璇紝鍑芥暟浼氳繘琛岄傚綋鐨勫鐞嗗拰鎭㈠銆 + */ TupleTableSlot *distExecImport(ForeignScanState *node) { DistImportExecutionState *importState = (DistImportExecutionState *)node->fdw_state; @@ -1633,6 +2248,19 @@ retry: * distEndForeignScan * Finish scanning foreign table and dispose objects used for this scan */ +/* + * 鍔熻兘锛氱粨鏉熷垎甯冨紡瀵煎叆鎿嶄綔锛岄噴鏀剧浉鍏宠祫婧 + * + * 鍙傛暟鍒楄〃锛 + * node锛氬閮ㄦ壂鎻忕姸鎬 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庣粨鏉熷垎甯冨紡瀵煎叆鎿嶄綔锛屽苟閲婃斁涓庝箣鐩稿叧鐨勮祫婧愩傚畠鎺ユ敹澶栭儴鎵弿鐘舵佷綔涓哄弬鏁帮紝 + * 骞舵牴鎹鐘舵佷腑鐨勪俊鎭繘琛屾竻鐞嗗拰璧勬簮閲婃斁鎿嶄綔銆 + * + * 绀轰緥鐢ㄦ硶锛 + * 閫氬父鍦ㄦ墽琛屽畬鍒嗗竷寮忓鍏ユ搷浣滃悗锛屽彲浠ヨ皟鐢ㄦ鍑芥暟鏉ョ‘淇濊祫婧愮殑閲婃斁鍜屾竻鐞嗐 + */ void distImportEnd(ForeignScanState *node) { DistImportExecutionState *importState = (DistImportExecutionState *)node->fdw_state; @@ -1649,4 +2277,3 @@ void distReImport(ForeignScanState *node) { // not implement yet } - diff --git a/src/gausskernel/storage/bulkload/importerror.cpp b/src/gausskernel/storage/bulkload/importerror.cpp index 85f26684b..4680cea78 100644 --- a/src/gausskernel/storage/bulkload/importerror.cpp +++ b/src/gausskernel/storage/bulkload/importerror.cpp @@ -49,16 +49,38 @@ char *generate_unique_cache_name_prefix(Oid oid, uint32 distSessionKey) tmpname[MAXPGPATH - 1] = '\0'; return pstrdup(tmpname); } - +/* + * 鍔熻兘锛氱敓鎴愬敮涓鐨勭紦瀛樺悕绉板墠缂 + * + * 鍙傛暟鍒楄〃锛 + * relname锛氬叧绯诲悕绉帮紝鐢ㄤ簬鏋勫缓缂撳瓨鍚嶇О鐨勪竴閮ㄥ垎 + * + * 杩斿洖鍊硷細 + * 鎸囧悜鐢熸垚鐨勭紦瀛樺悕绉板墠缂鐨勬寚閽 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庡垱寤轰竴涓敮涓鐨勭紦瀛樺悕绉板墠缂锛岄氬父鐢ㄤ簬鏍囪瘑缂撳瓨鏁版嵁鐨勫敮涓鎬с + * 缂撳瓨鍚嶇О鍓嶇紑鍖呮嫭鍏崇郴鍚嶃佹嫹璐滻D鍜岃繘绋婭D銆 + */ char *generate_unique_cache_name_prefix(const char *relname) { + // 鍒涘缓涓涓复鏃跺瓧绗︽暟缁勭敤浜庡瓨鍌ㄧ紦瀛樺悕绉板墠缂 char tmpname[MAXPGPATH]; + + // 鐢熸垚涓涓敮涓鐨勬嫹璐滻D锛岄氬父鐢ㄤ簬鏍囪瘑鏁版嵁鍓湰 uint32 copyId = generate_unique_id(>_copyId); - ; + + // 浣跨敤snprintf_s鍑芥暟鏋勯犵紦瀛樺悕绉板墠缂瀛楃涓诧紝鍖呮嫭鍏崇郴鍚嶃佹嫹璐滻D鍜岃繘绋婭D int rc = snprintf_s(tmpname, sizeof(tmpname), sizeof(tmpname) - 1, "%s.%u.%lu.cache", relname, copyId, t_thrd.proc_cxt.MyProcPid); + + // 妫鏌nprintf_s鐨勮繑鍥炲硷紝纭繚鏍煎紡鍖栨搷浣滄病鏈夊彂鐢熼敊璇 securec_check_ss(rc, "", ""); + + // 灏唗mpname瀛楃涓茬殑鏈鍚庝竴涓瓧绗﹁涓虹粓姝㈢锛屼互纭繚瀛楃涓茬殑姝g‘缁堟 tmpname[MAXPGPATH - 1] = '\0'; + + // 浣跨敤pstrdup鍑芥暟涓虹敓鎴愮殑瀛楃涓插垎閰嶅唴瀛樺苟杩斿洖 return pstrdup(tmpname); } @@ -90,185 +112,340 @@ void unlink_local_cache_file(const char *prefix, const uint32 smpId) UnlinkCacheFile(localfile); } +/* + * 鍔熻兘锛氬皢BaseError瀵硅薄鐨勬暟鎹簭鍒楀寲鍒癝tringInfo缂撳啿鍖轰腑 + * + * 鍙傛暟鍒楄〃锛 + * buf锛氱敤浜庡瓨鍌ㄥ簭鍒楀寲鏁版嵁鐨凷tringInfo缂撳啿鍖 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庡皢BaseError瀵硅薄鐨勬暟鎹簭鍒楀寲锛屼互渚垮悗缁紶杈撴垨瀛樺偍銆傚畠棣栧厛澶勭悊鏈澶у硷紝 + * 鐒跺悗瀵规瘡涓睘鎬ц繘琛屽鐞嗭紝鏍规嵁灞炴х殑绫诲瀷鍜岄暱搴﹀彂閫佺浉搴旂殑鏁版嵁鍒扮紦鍐插尯涓 + */ void BaseError::Serialize(StringInfo buf) { + // 鑾峰彇鍏崇郴鎻忚堪鍜屽睘鎬ф暟缁 Form_pg_attribute *attrs = m_desc->attrs; int natts = m_desc->natts; + // 鏂█灞炴ф暟閲忎笌鏈澶у煎尮閰 Assert(m_desc->natts == MaxNumOfValue); + + // 璋冪敤 serializeMaxNumOfValue 鍑芥暟锛屽皢鏌愮闄愬埗鍊煎簭鍒楀寲鍒扮紦鍐插尯 serializeMaxNumOfValue(buf); + // 寰幆澶勭悊姣忎釜灞炴 for (int i = 0; i < natts; ++i) { - Datum attr = m_values[i]; + Datum attr = m_values[i]; // 鑾峰彇灞炴х殑鏁版嵁 if (m_isNull[i]) { + // 濡傛灉灞炴т负NULL锛屽彂閫佺壒娈婃爣蹇 UNSIGNED_MINUS_ONE pq_sendint32(buf, UNSIGNED_MINUS_ONE); continue; } if (attrs[i]->attlen > 0 && attrs[i]->attlen <= 8) { - pq_sendint32(buf, attrs[i]->attlen); - pq_sendbytes(buf, (char *)&attr, attrs[i]->attlen); + // 濡傛灉灞炴ч暱搴﹀ぇ浜0涓斿皬浜庣瓑浜8锛屽彂閫佸睘鎬ч暱搴﹀拰灞炴ф暟鎹 + pq_sendint32(buf, attrs[i]->attlen); // 鍙戦佸睘鎬ч暱搴 + pq_sendbytes(buf, (char *)&attr, attrs[i]->attlen); // 鍙戦佸睘鎬ф暟鎹 } else if (attrs[i]->attlen > 8) { - pq_sendint32(buf, attrs[i]->attlen); - pq_sendbytes(buf, DatumGetPointer(attr), attrs[i]->attlen); + // 濡傛灉灞炴ч暱搴﹀ぇ浜8锛屽彂閫佸睘鎬ч暱搴﹀拰灞炴ф暟鎹 + pq_sendint32(buf, attrs[i]->attlen); // 鍙戦佸睘鎬ч暱搴 + pq_sendbytes(buf, DatumGetPointer(attr), attrs[i]->attlen); // 鍙戦佸睘鎬ф暟鎹 } else { - pq_sendint32(buf, VARSIZE(attr) - VARHDRSZ); - pq_sendbytes(buf, VARDATA(attr), VARSIZE(attr) - VARHDRSZ); + // 澶勭悊鍙橀暱灞炴э紝鍙戦佸睘鎬ф暟鎹殑闀垮害鍜屽睘鎬ф暟鎹 + pq_sendint32(buf, VARSIZE(attr) - VARHDRSZ); // 鍙戦佸睘鎬ф暟鎹殑闀垮害 + pq_sendbytes(buf, VARDATA(attr), VARSIZE(attr) - VARHDRSZ); // 鍙戦佸睘鎬ф暟鎹 } } } +/* + * 鍔熻兘锛氫粠StringInfo缂撳啿鍖轰腑鍙嶅簭鍒楀寲鏁版嵁鍒癇aseError瀵硅薄 + * + * 鍙傛暟鍒楄〃锛 + * buf锛氬寘鍚簭鍒楀寲鏁版嵁鐨凷tringInfo缂撳啿鍖 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庝粠StringInfo缂撳啿鍖轰腑璇诲彇搴忓垪鍖栨暟鎹紝骞跺皢鍏跺弽搴忓垪鍖栧埌BaseError瀵硅薄涓 + */ void BaseError::Deserialize(StringInfo buf) { - int natts; - Form_pg_attribute *attrs = m_desc->attrs; + int natts; // 灞炴ф暟閲 + Form_pg_attribute *attrs = m_desc->attrs; // 鍏崇郴鎻忚堪涓殑灞炴ф暟缁 + + // 浠庣紦鍐插尯涓幏鍙栧睘鎬ф暟閲 natts = pq_getmsgint(buf, 2); + + // 妫鏌ュ睘鎬ф暟閲忔槸鍚﹀悎娉 if (natts != MaxNumOfValue || natts != m_desc->natts) { - ereport(ERROR, (errcode(ERRCODE_OPERATE_RESULT_NOT_EXPECTED), errmsg("Found invalid error recored"))); + ereport(ERROR, (errcode(ERRCODE_OPERATE_RESULT_NOT_EXPECTED), errmsg("Found invalid error record"))); } + + // 寰幆澶勭悊姣忎釜灞炴 for (int i = 0; i < natts; ++i) { - int len = pq_getmsgint(buf, 4); + int len = pq_getmsgint(buf, 4); // 鑾峰彇灞炴ф暟鎹殑闀垮害 + if (len == -1) { + // 濡傛灉闀垮害涓-1锛岃〃绀哄睘鎬т负NULL m_isNull[i] = true; m_values[i] = (Datum)0; continue; } if (unlikely(len < 0)) { - ereport(ERROR, - (errcode(ERRCODE_OPERATE_RESULT_NOT_EXPECTED), - errmsg("Found invalid error recored: negative length that is not -1."))); + // 闀垮害灏忎簬0鏄棤鏁堢殑锛屾姏鍑洪敊璇 + ereport(ERROR, (errcode(ERRCODE_OPERATE_RESULT_NOT_EXPECTED), + errmsg("Found invalid error record: negative length that is not -1."))); } + m_isNull[i] = false; + if (attrs[i]->attlen > 0 && attrs[i]->attlen <= 8) { + // 澶勭悊瀹氶暱灞炴 if (unlikely(len != m_desc->attrs[i]->attlen)) { - ereport(ERROR, - (errcode(ERRCODE_OPERATE_RESULT_NOT_EXPECTED), - errmsg("Found invalid error recored: length is not the same as the attribute length."))); + // 闀垮害涓嶇瓑浜庡睘鎬ч暱搴︽槸鏃犳晥鐨勶紝鎶涘嚭閿欒 + ereport(ERROR, (errcode(ERRCODE_OPERATE_RESULT_NOT_EXPECTED), + errmsg("Found invalid error record: length is not the same as the attribute length."))); } - pq_copymsgbytes(buf, (char*)&m_values[i], len); + pq_copymsgbytes(buf, (char *)&m_values[i], len); // 浠庣紦鍐插尯澶嶅埗灞炴ф暟鎹 } else if (attrs[i]->attlen > 8) { + // 澶勭悊鍙橀暱灞炴 if (unlikely(len != m_desc->attrs[i]->attlen)) { - ereport(ERROR, - (errcode(ERRCODE_OPERATE_RESULT_NOT_EXPECTED), - errmsg("Found invalid error recored: length is not the same as the attribute length."))); + // 闀垮害涓嶇瓑浜庡睘鎬ч暱搴︽槸鏃犳晥鐨勶紝鎶涘嚭閿欒 + ereport(ERROR, (errcode(ERRCODE_OPERATE_RESULT_NOT_EXPECTED), + errmsg("Found invalid error record: length is not the same as the attribute length."))); } - m_values[i] = (Datum)palloc(len); - pq_copymsgbytes(buf, DatumGetPointer(m_values[i]), len); + m_values[i] = (Datum)palloc(len); // 鍒嗛厤鍐呭瓨浠ュ瓨鍌ㄥ睘鎬ф暟鎹 + pq_copymsgbytes(buf, DatumGetPointer(m_values[i]), len); // 浠庣紦鍐插尯澶嶅埗灞炴ф暟鎹 } else { - m_values[i] = (Datum)palloc(VARHDRSZ + len); - SET_VARSIZE(m_values[i], VARHDRSZ + len); - pq_copymsgbytes(buf, VARDATA(m_values[i]), len); + // 澶勭悊鍙橀暱灞炴 + m_values[i] = (Datum)palloc(VARHDRSZ + len); // 鍒嗛厤鍐呭瓨浠ュ瓨鍌ㄥ睘鎬ф暟鎹紙鍖呮嫭闀垮害淇℃伅锛 + SET_VARSIZE(m_values[i], VARHDRSZ + len); // 璁剧疆鍙橀暱鏁版嵁鐨勯暱搴︿俊鎭 + pq_copymsgbytes(buf, VARDATA(m_values[i]), len); // 浠庣紦鍐插尯澶嶅埗灞炴ф暟鎹 } } } +/* + * 鍔熻兘锛氶噸缃瓸aseError瀵硅薄鐨勭姸鎬 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庡皢BaseError瀵硅薄鐨勭姸鎬侀噸缃紝鍖呮嫭灏嗘墍鏈夊睘鎬х殑IsNull鏍囧織鍜屽兼竻闆躲 + */ void BaseError::Reset() { errno_t rc; + + // 浣跨敤memset_s鍑芥暟灏 m_isNull 鏁扮粍鐨勬墍鏈夊厓绱犳竻闆 rc = memset_s(m_isNull, sizeof(bool) * MaxNumOfValue, 0, sizeof(bool) * MaxNumOfValue); securec_check(rc, "", ""); + + // 浣跨敤memset_s鍑芥暟灏 m_values 鏁扮粍鐨勬墍鏈夊厓绱犳竻闆 rc = memset_s(m_values, sizeof(Datum) * MaxNumOfValue, 0, sizeof(Datum) * MaxNumOfValue); securec_check(rc, "", ""); } +/* + * 鍔熻兘锛氬皢鏈澶у硷紙MaxNumOfValue锛夊簭鍒楀寲鍒癝tringInfo缂撳啿鍖轰腑 + * + * 鍙傛暟鍒楄〃锛 + * buf锛氱敤浜庡瓨鍌ㄥ簭鍒楀寲鏁版嵁鐨凷tringInfo缂撳啿鍖 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庡皢棰勫畾涔夌殑鏈澶у硷紙MaxNumOfValue锛夊簭鍒楀寲鍒扮粰瀹氱殑StringInfo缂撳啿鍖轰腑锛 + * 浠ヤ究鍦ㄥ簭鍒楀寲閿欒淇℃伅鏃朵娇鐢ㄣ + */ void ImportError::serializeMaxNumOfValue(StringInfo buf) { + // 浣跨敤 pq_sendint16 鍑芥暟灏 MaxNumOfValue 搴忓垪鍖栦负涓涓16浣嶆暣鏁帮紝骞跺啓鍏ョ紦鍐插尯 pq_sendint16(buf, MaxNumOfValue); } +/* + * 鍔熻兘锛氬皢鏈澶у硷紙MaxNumOfValue锛夊簭鍒楀寲鍒癝tringInfo缂撳啿鍖轰腑 + * + * 鍙傛暟鍒楄〃锛 + * buf锛氱敤浜庡瓨鍌ㄥ簭鍒楀寲鏁版嵁鐨凷tringInfo缂撳啿鍖 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庡皢棰勫畾涔夌殑鏈澶у硷紙MaxNumOfValue锛夊簭鍒楀寲鍒扮粰瀹氱殑StringInfo缂撳啿鍖轰腑锛 + * 浠ヤ究鍦ㄥ簭鍒楀寲鎷疯礉閿欒淇℃伅鏃朵娇鐢ㄣ + */ void CopyError::serializeMaxNumOfValue(StringInfo buf) { + // 浣跨敤 pq_sendint 鍑芥暟灏 MaxNumOfValue 搴忓垪鍖栦负涓涓2瀛楄妭鏁存暟锛屽苟鍐欏叆缂撳啿鍖 pq_sendint(buf, MaxNumOfValue, 2); } - +/* + * 鍔熻兘锛氫粠鏂囦欢涓鍙栭敊璇褰曞苟灏嗗叾濉厖鍒癇aseError瀵硅薄涓 + * + * 鍙傛暟鍒楄〃锛 + * edata锛氱敤浜庡瓨鍌ㄩ敊璇褰曠殑BaseError瀵硅薄 + * + * 杩斿洖鍊硷細 + * 0 琛ㄧず鎴愬姛锛孍OF 琛ㄧず宸茶鍙栧埌鏂囦欢鏈熬锛屽叾浠栧艰〃绀哄嚭閿 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庝粠鏂囦欢涓鍙栭敊璇褰曪紝灏嗗叾鍙嶅簭鍒楀寲锛屽苟灏嗙粨鏋滃~鍏呭埌缁欏畾鐨凚aseError瀵硅薄涓 + * 濡傛灉璇诲彇鎴栧鐞嗗嚭閿欙紝灏嗘姏鍑虹浉搴旂殑閿欒銆 + */ int BaseErrorLogger::FetchError(BaseError *edata) { - AutoContextSwitch memGuard(m_memCxt); - int nread = 0; - uint32 len = 0; - Assert(m_buffer != NULL && edata != NULL); - MemoryContextReset(m_memCxt); - resetStringInfo(m_buffer); + AutoContextSwitch memGuard(m_memCxt); // 鑷姩鍐呭瓨涓婁笅鏂囧垏鎹 + int nread = 0; // 璇诲彇鐨勫瓧鑺傛暟 + uint32 len = 0; // 閿欒璁板綍鐨勯暱搴 + Assert(m_buffer != NULL && edata != NULL); // 鏂█妫鏌ヨ緭鍏ュ弬鏁扮殑鏈夋晥鎬 + MemoryContextReset(m_memCxt); // 閲嶇疆鍐呭瓨涓婁笅鏂 + resetStringInfo(m_buffer); // 閲嶇疆StringInfo缂撳啿鍖 + + // 浠庢枃浠朵腑璇诲彇閿欒璁板綍鐨勯暱搴︼紙4瀛楄妭锛 nread = FilePRead(m_fd, (char *)&len, 4, m_offset); if (nread == 0) { - return EOF; + return EOF; // 宸茶鍙栧埌鏂囦欢鏈熬 } else if (nread < 0) { - ereport(ERROR, (errcode_for_file_access(), errmsg("could not fetch error record:%m"))); + ereport(ERROR, (errcode_for_file_access(), errmsg("could not fetch error record:%m"))); // 鏂囦欢璇诲彇閿欒 } else if (nread < 4) { - ereport(ERROR, (errcode_for_file_access(), errmsg("could not fetch expected length:%m"))); + ereport(ERROR, + (errcode_for_file_access(), errmsg("could not fetch expected length:%m"))); // 鏈鍙栧埌棰勬湡鐨勯暱搴 } - m_offset += 4; - len = ntohl(len); - enlargeStringInfo(m_buffer, len + 1); + m_offset += 4; // 鏇存柊鏂囦欢鍋忕Щ閲 + len = ntohl(len); // 灏嗛暱搴︿粠缃戠粶瀛楄妭椤哄簭杞崲涓轰富鏈哄瓧鑺傞『搴 + enlargeStringInfo(m_buffer, len + 1); // 鎵╁睍StringInfo缂撳啿鍖轰互瀹圭撼閿欒璁板綍 + // 浠庢枃浠朵腑璇诲彇閿欒璁板綍鏁版嵁锛岀洿鍒扮紦鍐插尯闀垮害杈惧埌閿欒璁板綍闀垮害 while ((uint32)m_buffer->len < len) { nread = FilePRead(m_fd, m_buffer->data + m_buffer->len, len - m_buffer->len, m_offset); if (nread == 0) { - ereport(ERROR, (errcode_for_file_access(), errmsg("incomplete error record"))); + ereport(ERROR, (errcode_for_file_access(), errmsg("incomplete error record"))); // 鏈畬鏁磋鍙栭敊璇褰 } else if (nread < 0) { - ereport(ERROR, (errcode_for_file_access(), errmsg("could not fetch error record:%m"))); + ereport(ERROR, (errcode_for_file_access(), errmsg("could not fetch error record:%m"))); // 鏂囦欢璇诲彇閿欒 } - m_buffer->len += nread; - m_offset += nread; + m_buffer->len += nread; // 鏇存柊缂撳啿鍖洪暱搴 + m_offset += nread; // 鏇存柊鏂囦欢鍋忕Щ閲 } - m_buffer->data[m_buffer->len] = '\0'; - edata->Deserialize(m_buffer); - return 0; + m_buffer->data[m_buffer->len] = '\0'; // 灏嗙紦鍐插尯鐨勬渶鍚庝竴涓瓧绗﹁缃负'\0'锛屼互渚夸綔涓哄瓧绗︿覆浣跨敤 + edata->Deserialize(m_buffer); // 鍙嶅簭鍒楀寲閿欒璁板綍骞跺~鍏呭埌BaseError瀵硅薄涓 + return 0; // 鎴愬姛璇诲彇骞跺鐞嗛敊璇褰 } +/* + * 鍔熻兘锛氬皢BaseError瀵硅薄鐨勯敊璇俊鎭繚瀛樺埌鏂囦欢涓 + * + * 鍙傛暟鍒楄〃锛 + * edata锛氬寘鍚敊璇俊鎭殑BaseError瀵硅薄 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庡皢缁欏畾鐨凚aseError瀵硅薄鐨勯敊璇俊鎭簭鍒楀寲骞朵繚瀛樺埌鏂囦欢涓 + * 鍑芥暟閫氳繃灏嗛敊璇俊鎭殑闀垮害鍓嶇疆鍒版暟鎹箣鍓嶏紝骞跺啓鍏ユ枃浠舵潵瀹炵幇淇濆瓨鎿嶄綔銆 + */ void BaseErrorLogger::SaveError(BaseError *edata) { - int nwrite = 0; - int len = 0; + int nwrite = 0; // 鍐欏叆鐨勫瓧鑺傛暟 + int len = 0; // 褰撳墠宸插啓鍏ョ殑瀛楄妭鏁 - Assert(m_buffer != NULL && edata != NULL); - resetStringInfo(m_buffer); - appendStringInfoSpaces(m_buffer, 4); - edata->Serialize(m_buffer); - *((uint32 *)m_buffer->data) = htonl((uint32)(m_buffer->len - 4)); + Assert(m_buffer != NULL && edata != NULL); // 鏂█妫鏌ヨ緭鍏ュ弬鏁扮殑鏈夋晥鎬 + resetStringInfo(m_buffer); // 閲嶇疆StringInfo缂撳啿鍖 + appendStringInfoSpaces(m_buffer, 4); // 鍦ㄧ紦鍐插尯鍓嶆坊鍔4涓┖瀛楄妭锛堢敤浜庡瓨鍌ㄩ敊璇俊鎭殑闀垮害锛 + edata->Serialize(m_buffer); // 搴忓垪鍖栭敊璇俊鎭苟杩藉姞鍒扮紦鍐插尯 + *((uint32 *)m_buffer->data) = htonl((uint32)(m_buffer->len - 4)); // 灏嗛敊璇俊鎭殑闀垮害鍐欏叆缂撳啿鍖 + // 寰幆灏嗛敊璇俊鎭啓鍏ユ枃浠讹紝鐩村埌鎵鏈夋暟鎹兘鍐欏叆 while (len < m_buffer->len) { nwrite = FilePWrite(m_fd, m_buffer->data + len, m_buffer->len - len, m_offset); if (nwrite == 0 || nwrite < 0) { - ereport(ERROR, (errcode_for_file_access(), errmsg("could not cache error info:%m"))); + ereport(ERROR, (errcode_for_file_access(), errmsg("could not cache error info:%m"))); // 鏂囦欢鍐欏叆閿欒 } - len += nwrite; - m_offset += nwrite; + len += nwrite; // 鏇存柊宸插啓鍏ョ殑瀛楄妭鏁 + m_offset += nwrite; // 鏇存柊鏂囦欢鍋忕Щ閲 } } +/* + * 鍔熻兘锛氬垵濮嬪寲 ImportErrorLogger 瀵硅薄 + * + * 鍙傛暟鍒楄〃锛 + * output锛氳緭鍑哄弬鏁帮紙鏈娇鐢級 + * errDesc锛氶敊璇弿杩扮殑鍏冪粍鎻忚堪绗 + * errInfo锛氶敊璇棩蹇椾俊鎭紙鏈娇鐢級 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庡垵濮嬪寲 ImportErrorLogger 瀵硅薄锛岃缃浉鍏崇殑涓婁笅鏂囧拰灞炴с + * 杈撳嚭鍙傛暟 `output` 鍜岄敊璇棩蹇椾俊鎭 `errInfo` 鐩墠鏈浣跨敤銆 + */ void ImportErrorLogger::Initialize(const void *output, TupleDesc errDesc, ErrLogInfo &errInfo) { + // 鍒涘缓鍐呭瓨涓婁笅鏂 m_memCxt m_memCxt = AllocSetContextCreate(CurrentMemoryContext, "Import Error Context", ALLOCSET_DEFAULT_MINSIZE, ALLOCSET_DEFAULT_INITSIZE, ALLOCSET_DEFAULT_MAXSIZE); + + // 璁剧疆閿欒鎻忚堪鐨勫厓缁勬弿杩扮 m_errDesc m_errDesc = errDesc; + + // 蹇界暐鏈娇鐢ㄧ殑 errInfo 鍙傛暟 (void)errInfo; } +/* + * 鍔熻兘锛氶攢姣 ImportErrorLogger 瀵硅薄 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庨攢姣 ImportErrorLogger 瀵硅薄锛岄噴鏀剧浉鍏崇殑璧勬簮鍜屽唴瀛樹笂涓嬫枃銆 + */ void ImportErrorLogger::Destroy() { + // 鍒犻櫎鍐呭瓨涓婁笅鏂 m_memCxt锛屽悓鏃堕噴鏀剧浉鍏宠祫婧 MemoryContextDelete(m_memCxt); + + // 灏嗛敊璇弿杩扮殑鍏冪粍鎻忚堪绗 m_errDesc 璁剧疆涓 NULL m_errDesc = NULL; } +/* + * 鍔熻兘锛氬垵濮嬪寲 GDSErrorLogger 瀵硅薄 + * + * 鍙傛暟鍒楄〃锛 + * output锛氳緭鍑哄弬鏁帮紝閫氬父鏄竴涓 GDSStream 鎸囬拡 + * errDesc锛氶敊璇弿杩扮殑鍏冪粍鎻忚堪绗 + * errInfo锛氶敊璇棩蹇椾俊鎭 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庡垵濮嬪寲 GDSErrorLogger 瀵硅薄锛岃缃浉鍏崇殑灞炴у拰涓婁笅鏂囥 + * 杈撳嚭鍙傛暟 `output` 閫氬父鏄竴涓 GDSStream 鎸囬拡锛宍errDesc` 鐢ㄤ簬閿欒鎻忚堪鐨勫厓缁勬弿杩扮锛 + * `errInfo` 鐢ㄤ簬閿欒鏃ュ織淇℃伅锛堟湭浣跨敤锛夈 + */ void GDSErrorLogger::Initialize(const void *output, TupleDesc errDesc, ErrLogInfo &errInfo) { + // 灏嗚緭鍑哄弬鏁板己鍒惰浆鎹负 GDSStream 鎸囬拡骞跺瓨鍌ㄥ湪 m_output 涓 m_output = (GDSStream *)output; + + // 澶嶅埗閿欒鎻忚堪鐨勫厓缁勬弿杩扮鐨勫悕绉板苟瀛樺偍鍦 m_name 涓 m_name = pstrdup((char *)errDesc); + + // 璋冪敤 ImportErrorLogger 鐨 Initialize 鍑芥暟鍒濆鍖栧璞 ImportErrorLogger::Initialize(output, NULL, errInfo); + + // 鍦ㄤ娇鐢ㄦ柇瑷妫鏌ユ椂锛屽垵濮嬪寲璁℃暟鍣 m_counter 涓 0 #ifdef USE_ASSERT_CHECKING m_counter = 0; #endif } +/* + * 鍔熻兘锛氶攢姣 GDSErrorLogger 瀵硅薄 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庨攢姣 GDSErrorLogger 瀵硅薄锛屽悓鏃惰緭鍑烘棩蹇椾俊鎭紙褰撲娇鐢ㄦ柇瑷妫鏌ユ椂锛夈 + */ void GDSErrorLogger::Destroy() { + // 鍦ㄤ娇鐢ㄦ柇瑷妫鏌ユ椂锛岃緭鍑烘棩蹇椾俊鎭紝鏄剧ず宸插彂閫佺殑閿欒鏃ュ織琛屾暟 #ifdef USE_ASSERT_CHECKING ereport(LOG, (errcode(ERRCODE_LOG), errmsg("Error Log send %d lines", m_counter))); #endif + + // 璋冪敤 ImportErrorLogger 鐨 Destroy 鍑芥暟閿姣佸璞 ImportErrorLogger::Destroy(); } @@ -280,65 +457,144 @@ int GDSErrorLogger::FetchError(BaseError *edata) return 0; } +/* + * 鍔熻兘锛氫繚瀛橀敊璇俊鎭埌 GDSStream + * + * 鍙傛暟鍒楄〃锛 + * edata锛氬寘鍚敊璇俊鎭殑BaseError瀵硅薄 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庡皢缁欏畾鐨勯敊璇俊鎭繚瀛樺埌 GDSStream 涓紝鐢ㄤ簬杩滅▼鏃ュ織璁板綍銆 + * 瀹冮氳繃鑾峰彇閿欒淇℃伅鐨勫師濮嬫暟鎹紝灏嗗叾灏佽涓 CmdRemoteLog 缁撴瀯骞跺簭鍒楀寲锛 + * 鐒跺悗灏嗗簭鍒楀寲鍚庣殑鏁版嵁鍐欏叆 GDSStream 鐨勮緭鍑虹紦鍐插尯锛屽苟鍒锋柊缂撳啿鍖恒 + * 鍦ㄤ娇鐢ㄦ柇瑷妫鏌ユ椂锛屽鍔犺鏁板櫒 m_counter銆 + */ void GDSErrorLogger::SaveError(BaseError *edata) { - CmdRemoteLog dat; - Datum rawdata; + CmdRemoteLog dat; // 鐢ㄤ簬杩滅▼鏃ュ織璁板綍鐨勬暟鎹粨鏋 + Datum rawdata; // 鍘熷鏁版嵁 - Assert(edata != NULL); + Assert(edata != NULL); // 鏂█妫鏌ヨ緭鍏ュ弬鏁扮殑鏈夋晥鎬 + + // 濡傛灉閿欒淇℃伅鐨勫師濮嬫暟鎹负NULL锛屽垯涓嶈繘琛屼繚瀛 if (edata->m_isNull[BaseError::RawDataIdx]) return; + // 鑾峰彇閿欒淇℃伅鐨勫師濮嬫暟鎹 rawdata = edata->m_values[BaseError::RawDataIdx]; + + // 濉厖杩滅▼鏃ュ織璁板綍鏁版嵁缁撴瀯 dat.m_type = CMD_TYPE_REMOTELOG; dat.m_datasize = VARSIZE_ANY_EXHDR(DatumGetPointer(rawdata)); dat.m_data = VARDATA_ANY(DatumGetPointer(rawdata)); - dat.m_name = pstrdup(m_name); + dat.m_name = pstrdup(m_name); // 澶嶅埗閿欒鎻忚堪鐨勫悕绉 + + // 搴忓垪鍖栨暟鎹粨鏋勫苟灏嗗叾鍐欏叆 GDSStream 鐨勮緭鍑虹紦鍐插尯 SerializeCmd(&dat, m_output->m_outBuf); + + // 鍒锋柊杈撳嚭缂撳啿鍖猴紝灏嗘暟鎹彂閫佸埌杩滅▼鏃ュ織鏈嶅姟鍣 m_output->Flush(); + + // 鍦ㄤ娇鐢ㄦ柇瑷妫鏌ユ椂锛屽鍔犺鏁板櫒锛岀敤浜庤褰曞凡鍙戦佺殑閿欒鏃ュ織琛屾暟 #ifdef USE_ASSERT_CHECKING ++m_counter; #endif } +/* + * 鍔熻兘锛氱敓鎴愬鍏ラ敊璇殑閿欒淇℃伅 + * + * 鍙傛暟鍒楄〃锛 + * cstate锛氭嫹璐濈姸鎬佷俊鎭 + * begintime锛氬鍏ュ紑濮嬫椂闂 + * edata锛氬鍏ラ敊璇俊鎭殑BaseError瀵硅薄 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庣敓鎴愬鍏ラ敊璇殑閿欒淇℃伅锛屽皢鍏跺瓨鍌ㄥ湪缁欏畾鐨凚aseError瀵硅薄涓 + * 瀹冮鍏堝皢BaseError瀵硅薄閲嶇疆锛岀劧鍚庢牴鎹嫹璐濈姸鎬佷腑鐨勪俊鎭敓鎴愬師濮嬫暟鎹紝 + * 骞跺皢鍏跺瓨鍌ㄥ湪BaseError瀵硅薄涓傚悓鏃讹紝灏嗕竴浜涙爣蹇椾綅璁剧疆涓烘寚绀洪敊璇俊鎭槸鍚︿负绌恒 + */ void GDSErrorLogger::FormError(CopyState cstate, Datum begintime, ImportError *edata) { - Assert(edata != NULL); + Assert(edata != NULL); // 鏂█妫鏌ヨ緭鍏ュ弬鏁扮殑鏈夋晥鎬 + // 閲嶇疆BaseError瀵硅薄鐨勭姸鎬 edata->Reset(); + errno_t rc; + // 浣跨敤 memset_s 鍑芥暟灏 BaseError 瀵硅薄鐨 isNull 鏁扮粍鐨勬墍鏈夊厓绱犺缃负 1锛堣〃绀虹┖鍊硷級 rc = memset_s(edata->m_isNull, sizeof(bool) * ImportError::MaxNumOfValue, 1, sizeof(bool) * ImportError::MaxNumOfValue); securec_check(rc, "", ""); if (cstate->line_buf.len > 0) { int len = cstate->line_buf.len + VARHDRSZ + 1; + + // 鍒嗛厤鍐呭瓨鐢ㄤ簬瀛樺偍鍘熷鏁版嵁锛屽苟璁剧疆鍏堕暱搴 edata->m_values[ImportError::RawDataIdx] = (Datum)palloc(len); SET_VARSIZE(edata->m_values[ImportError::RawDataIdx], len); + + // 灏嗘嫹璐濈姸鎬佷腑鐨勬暟鎹鍒跺埌鍘熷鏁版嵁涓紝骞舵坊鍔犳崲琛岀 rc = memcpy_s(((char *)edata->m_values[ImportError::RawDataIdx]) + VARHDRSZ, len - VARHDRSZ, cstate->line_buf.data, cstate->line_buf.len); securec_check(rc, "", ""); ((char *)edata->m_values[ImportError::RawDataIdx])[len - 1] = '\n'; + + // 灏嗗師濮嬫暟鎹殑绌哄兼爣蹇楄缃负 false锛堣〃绀洪潪绌猴級 edata->m_isNull[ImportError::RawDataIdx] = false; } } +/* + * 鍔熻兘锛氬垵濮嬪寲 LocalErrorLogger 瀵硅薄 + * + * 鍙傛暟鍒楄〃锛 + * filename锛氱紦瀛樻枃浠剁殑鏂囦欢鍚 + * errDesc锛氶敊璇弿杩扮殑鍏冪粍鎻忚堪绗 + * errInfo锛氶敊璇棩蹇椾俊鎭 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庡垵濮嬪寲 LocalErrorLogger 瀵硅薄锛岃缃浉鍏崇殑灞炴у拰涓婁笅鏂囥 + * 瀹冮氳繃鐢熸垚鏈湴缂撳瓨鏂囦欢鐨勬枃浠跺悕锛屽苟鎵撳紑璇ユ枃浠舵潵瀛樺偍閿欒鏃ュ織銆 + * 鐒跺悗锛屽畠璋冪敤 ImportErrorLogger 鐨 Initialize 鍑芥暟鍒濆鍖栧璞° + */ void LocalErrorLogger::Initialize(const void *filename, TupleDesc errDesc, ErrLogInfo &errInfo) { - char cache_file[MAXPGPATH]; + char cache_file[MAXPGPATH]; // 鏈湴缂撳瓨鏂囦欢鐨勬枃浠跺悕 + + // 鐢熸垚鏈湴缂撳瓨鏂囦欢鐨勬枃浠跺悕 generate_local_cache_file((const char *)filename, errInfo.smp_id, cache_file); + // 鎵撳紑缂撳瓨鏂囦欢锛岃幏鍙栨枃浠舵弿杩扮 m_fd = OpenCacheFile(cache_file, errInfo.unlink_owner); + + // 鍒涘缓 StringInfo 缂撳啿鍖 m_buffer = makeStringInfo(); + + // 璋冪敤 ImportErrorLogger 鐨 Initialize 鍑芥暟鍒濆鍖栧璞★紝浼犻掔紦瀛樻枃浠剁殑鏂囦欢鍚 ImportErrorLogger::Initialize(cache_file, errDesc, errInfo); } +/* + * 鍔熻兘锛氶攢姣 LocalErrorLogger 瀵硅薄 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庨攢姣 LocalErrorLogger 瀵硅薄锛屽悓鏃堕噴鏀剧浉鍏崇殑璧勬簮銆 + * 瀹冮鍏堣皟鐢 ImportErrorLogger 鐨 Destroy 鍑芥暟閿姣佸璞★紝鐒跺悗閲婃斁 + * StringInfo 缂撳啿鍖虹殑鍐呭瓨锛屽叧闂紦瀛樻枃浠剁殑鏂囦欢鎻忚堪绗︼紝浣嗕笉鍒犻櫎鐗╃悊鏂囦欢銆 + */ void LocalErrorLogger::Destroy() { + // 璋冪敤 ImportErrorLogger 鐨 Destroy 鍑芥暟閿姣佸璞 ImportErrorLogger::Destroy(); + + // 濡傛灉 StringInfo 缂撳啿鍖轰笉涓虹┖ if (m_buffer != NULL) { + // 濡傛灉缂撳啿鍖虹殑鏁版嵁涓嶄负绌猴紝閲婃斁鏁版嵁鍐呭瓨 if (m_buffer->data != NULL) pfree(m_buffer->data); + + // 閲婃斁 StringInfo 缂撳啿鍖虹殑鍐呭瓨 pfree(m_buffer); m_buffer = NULL; } @@ -351,82 +607,161 @@ void LocalErrorLogger::Destroy() FileClose(m_fd); } +/* + * 鍔熻兘锛氱敓鎴愭湰鍦伴敊璇棩蹇楃殑閿欒淇℃伅 + * + * 鍙傛暟鍒楄〃锛 + * cstate锛氭嫹璐濈姸鎬佷俊鎭 + * begintime锛氬鍏ュ紑濮嬫椂闂 + * ierror锛氬鍏ラ敊璇俊鎭殑ImportError瀵硅薄 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庣敓鎴愭湰鍦伴敊璇棩蹇楃殑閿欒淇℃伅锛屽皢鍏跺瓨鍌ㄥ湪缁欏畾鐨処mportError瀵硅薄涓 + * 瀹冮鍏堥氳繃CopyErrorData鍑芥暟鑾峰彇閿欒淇℃伅锛岀劧鍚庡皢鐩稿叧淇℃伅濉厖鍒癐mportError瀵硅薄涓 + * 濡傛灉鏈夊師濮嬫暟鎹紝灏嗗叾瀛樺偍鍦≧awData瀛楁涓紝濡傛灉鏈夎缁嗕俊鎭紝灏嗗叾瀛樺偍鍦―etail瀛楁涓 + */ void LocalErrorLogger::FormError(CopyState cstate, Datum begintime, ImportError *ierror) { - ErrorData *edata = NULL; - int len = 0; - const char *detail = NULL; - int sqlerrcode; + ErrorData *edata = NULL; // 閿欒鏁版嵁 + int len = 0; // 闀垮害 + const char *detail = NULL; // 璇︾粏淇℃伅 + int sqlerrcode; // SQL閿欒浠g爜 errno_t rc; - Assert(ierror != NULL); + Assert(ierror != NULL); // 鏂█妫鏌ヨ緭鍏ュ弬鏁扮殑鏈夋晥鎬 + + // 鑾峰彇閿欒淇℃伅 edata = CopyErrorData(); + + // 鑾峰彇閿欒璇︾粏淇℃伅鍜孲QL閿欒浠g爜 detail = edata->message; sqlerrcode = edata->sqlerrcode; + + // 閲嶇疆ImportError瀵硅薄鐨勭姸鎬 ierror->Reset(); + + // 璁剧疆ImportError瀵硅薄鐨勬弿杩扮 ierror->m_desc = m_errDesc; + + // 濉厖ImportError瀵硅薄鐨勫瓧娈靛 ierror->m_values[ImportError::NodeIdIdx] = u_sess->pgxc_cxt.PGXCNodeId; ierror->m_values[ImportError::StartTimeIdx] = begintime; + + // 濉厖鏂囦欢鍚嶅瓧娈 len = strlen(cstate->filename) + VARHDRSZ; ierror->m_values[ImportError::FileNameIdx] = (Datum)palloc(len); SET_VARSIZE(ierror->m_values[ImportError::FileNameIdx], len); rc = memcpy_s(((char *)ierror->m_values[ImportError::FileNameIdx]) + VARHDRSZ, len - VARHDRSZ, cstate->filename, len - VARHDRSZ); securec_check(rc, "", ""); + + // 濉厖琛屽彿瀛楁 ierror->m_values[ImportError::LineNOIdx] = cstate->cur_lineno; + // 濡傛灉瀛樺湪鍘熷鏁版嵁骞朵笖SQL閿欒浠g爜涓嶈〃绀哄瓧绗︿笉鍦ㄧ紪鐮佷腑鎴栨棤娉曡浆鎹㈠瓧绗 if (cstate->line_buf.len > 0 && sqlerrcode != ERRCODE_CHARACTER_NOT_IN_REPERTOIRE && sqlerrcode != ERRCODE_UNTRANSLATABLE_CHARACTER) { char *rawDataVal = NULL; int rawDataValLen = 0; + + // 鑾峰彇闄愬埗闀垮害鐨勫師濮嬫暟鎹 rawDataVal = limit_printout_length(cstate->line_buf.data); rawDataValLen = strlen(rawDataVal); + + // 濉厖鍘熷鏁版嵁瀛楁 len = cstate->line_buf.len + VARHDRSZ; ierror->m_values[ImportError::RawDataIdx] = (Datum)palloc(len); SET_VARSIZE(ierror->m_values[ImportError::RawDataIdx], len); rc = memcpy_s(((char *)ierror->m_values[ImportError::RawDataIdx]) + VARHDRSZ, len - VARHDRSZ, cstate->line_buf.data, rawDataValLen); securec_check(rc, "", ""); - } else + } else { + // 鍘熷鏁版嵁涓虹┖ ierror->m_isNull[ImportError::RawDataIdx] = true; + } + + // 濡傛灉瀛樺湪璇︾粏淇℃伅锛屽~鍏呰缁嗕俊鎭瓧娈 if (detail != NULL) { char *detailVal = limit_printout_length(detail); int leng = strlen(detailVal); + ierror->m_values[ImportError::DetailIdx] = (Datum)palloc(leng + VARHDRSZ); SET_VARSIZE(ierror->m_values[ImportError::DetailIdx], leng + VARHDRSZ); rc = memcpy_s(((char *)ierror->m_values[ImportError::DetailIdx]) + VARHDRSZ, leng, detail, leng); securec_check(rc, "", ""); - } else + } else { + // 璇︾粏淇℃伅涓虹┖ ierror->m_isNull[ImportError::DetailIdx] = true; + } } - +/* + * 鍔熻兘锛氬垵濮嬪寲 CopyErrorLogger 瀵硅薄 + * + * 鍙傛暟鍒楄〃锛 + * cstate锛氭嫹璐濈姸鎬佷俊鎭 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庡垵濮嬪寲 CopyErrorLogger 瀵硅薄锛岃缃浉鍏崇殑灞炴у拰涓婁笅鏂囥 + * 瀹冮氳繃鐢熸垚涓涓敮涓鐨勭紦瀛樻枃浠跺悕锛屽苟鎵撳紑璇ユ枃浠舵潵瀛樺偍鎷疯礉閿欒鏃ュ織銆 + * 鍚屾椂锛屽垱寤 StringInfo 缂撳啿鍖猴紝鍒嗛厤鍐呭瓨涓婁笅鏂囷紝骞惰幏鍙栭敊璇〃鐨勫厓缁勬弿杩扮銆 + */ void CopyErrorLogger::Initialize(CopyState cstate) { /* Get ourselves a cache file */ char *cache_file = generate_unique_cache_name_prefix(RelationGetRelationName(cstate->rel)); + // 鎵撳紑缂撳瓨鏂囦欢锛岃幏鍙栨枃浠舵弿杩扮锛屽苟璁剧疆鑷姩鍒犻櫎鏍囧織涓 true m_fd = OpenCacheFile(cache_file, true); + + // 鍒涘缓 StringInfo 缂撳啿鍖 m_buffer = makeStringInfo(); + // 鍒涘缓鍐呭瓨涓婁笅鏂 m_memCxt = AllocSetContextCreate(CurrentMemoryContext, "Copy Import Error Context", ALLOCSET_DEFAULT_MINSIZE, ALLOCSET_DEFAULT_INITSIZE, ALLOCSET_DEFAULT_MAXSIZE); + + // 鑾峰彇閿欒琛ㄧ殑鍏冪粍鎻忚堪绗 m_errDesc = RelationGetDescr(cstate->err_table); } +/* + * 鍔熻兘锛氶噸缃 CopyErrorLogger 瀵硅薄鐨勭姸鎬 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庨噸缃 CopyErrorLogger 瀵硅薄鐨勭姸鎬侊紝鍖呮嫭缂撳啿鍖恒佸唴瀛樹笂涓嬫枃鍜屽亸绉婚噺銆 + * 瀹冨皢 StringInfo 缂撳啿鍖洪噸缃负绌猴紝閲嶇疆鍐呭瓨涓婁笅鏂囷紝骞跺皢鍋忕Щ閲忚缃负 0銆 + */ void CopyErrorLogger::Reset() { + // 閲嶇疆 StringInfo 缂撳啿鍖轰负绌 resetStringInfo(m_buffer); + + // 閲嶇疆鍐呭瓨涓婁笅鏂 MemoryContextReset(m_memCxt); + + // 灏嗗亸绉婚噺璁剧疆涓 0 m_offset = 0; } - +/* + * 鍔熻兘锛氶攢姣 CopyErrorLogger 瀵硅薄 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庨攢姣 CopyErrorLogger 瀵硅薄锛岄噴鏀剧浉鍏宠祫婧愶紝鍖呮嫭鍐呭瓨涓婁笅鏂囥佺紦鍐插尯銆侀敊璇弿杩扮鍜屾枃浠舵弿杩扮銆 + * 瀹冧細鍒犻櫎鍐呭瓨涓婁笅鏂囥侀噴鏀剧紦鍐插尯鐨勫唴瀛樸佸叧闂枃浠舵弿杩扮銆 + */ void CopyErrorLogger::Destroy() { + // 鍒犻櫎鍐呭瓨涓婁笅鏂 MemoryContextDelete(m_memCxt); + + // 娓呯┖閿欒鎻忚堪绗 m_errDesc = NULL; + + // 閲婃斁缂撳啿鍖虹浉鍏崇殑鍐呭瓨 if (m_buffer != NULL) { if (m_buffer->data != NULL) pfree(m_buffer->data); + pfree(m_buffer); m_buffer = NULL; } @@ -438,8 +773,21 @@ void CopyErrorLogger::Destroy() } } +/* + * 鍔熻兘锛氭牴鎹敊璇俊鎭敓鎴 CopyError 瀵硅薄 + * + * 鍙傛暟鍒楄〃锛 + * cstate锛氬綋鍓嶇殑澶嶅埗鐘舵 + * begintime锛氬紑濮嬫椂闂 + * ierror锛氭寚鍚 CopyError 瀵硅薄鐨勬寚閽堬紝鐢ㄤ簬瀛樺偍鐢熸垚鐨勯敊璇俊鎭 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庣敓鎴 CopyError 瀵硅薄锛屽皢閿欒淇℃伅濉厖鍒 CopyError 涓 + * 瀹冩牴鎹鍒剁姸鎬併佸紑濮嬫椂闂淬侀敊璇弿杩扮瓑淇℃伅鍒涘缓閿欒璁板綍銆 + */ void CopyErrorLogger::FormError(CopyState cstate, Datum begintime, CopyError *ierror) { + // 澹版槑 ErrorData 鎸囬拡鍜屽叾浠栧彉閲 ErrorData *edata = NULL; int len = 0; const char *detail = NULL; @@ -448,28 +796,38 @@ void CopyErrorLogger::FormError(CopyState cstate, Datum begintime, CopyError *ie errno_t rc; char *source = NULL; + // 鏂█纭繚浼犲叆鐨 CopyError 瀵硅薄闈炵┖ Assert(ierror != NULL); + + // 鑾峰彇褰撳墠閿欒淇℃伅 edata = CopyErrorData(); detail = edata->message; sqlerrcode = edata->sqlerrcode; + + // 閲嶇疆 CopyError 瀵硅薄锛屾竻绌轰箣鍓嶇殑鏁版嵁 ierror->Reset(); + // 璁剧疆 CopyError 鐨勬弿杩扮涓洪敊璇弿杩扮 ierror->m_desc = m_errDesc; + // 鏋勫缓鍏崇郴鍚嶏紝鏍煎紡涓 "鍛藉悕绌洪棿.琛ㄥ悕" relname = (char *)palloc(MAX_NAME_LEN); rc = snprintf_s(relname, MAX_NAME_LEN, MAX_NAME_LEN - 1, "%s.%s", cstate->logger->m_namespace, RelationGetRelationName(cstate->rel)); securec_check_ss(rc, "\0", "\0"); + // 鍒嗛厤骞惰缃叧绯诲悕 len = strlen(relname) + VARHDRSZ; ierror->m_values[CopyError::RelNameIdx] = (Datum)palloc(len); SET_VARSIZE(ierror->m_values[CopyError::RelNameIdx], len); - rc = memcpy_s(((char *)ierror->m_values[CopyError::RelNameIdx]) + VARHDRSZ, len - VARHDRSZ, relname, - len - VARHDRSZ); + rc = + memcpy_s(((char *)ierror->m_values[CopyError::RelNameIdx]) + VARHDRSZ, len - VARHDRSZ, relname, len - VARHDRSZ); securec_check_c(rc, "\0", "\0"); + // 璁剧疆寮濮嬫椂闂 ierror->m_values[CopyError::StartTimeIdx] = begintime; + // 璁剧疆鏂囦欢鍚 if (cstate->filename) source = cstate->filename; else { @@ -477,13 +835,15 @@ void CopyErrorLogger::FormError(CopyState cstate, Datum begintime, CopyError *ie source = "STDIN"; } + // 鍒嗛厤骞惰缃枃浠跺悕 len = strlen(source) + VARHDRSZ; ierror->m_values[CopyError::FileNameIdx] = (Datum)palloc(len); SET_VARSIZE(ierror->m_values[CopyError::FileNameIdx], len); - rc = memcpy_s(((char *)ierror->m_values[CopyError::FileNameIdx]) + VARHDRSZ, len - VARHDRSZ, source, - len - VARHDRSZ); + rc = + memcpy_s(((char *)ierror->m_values[CopyError::FileNameIdx]) + VARHDRSZ, len - VARHDRSZ, source, len - VARHDRSZ); securec_check_c(rc, "\0", "\0"); + // 璁剧疆琛屽彿 ierror->m_values[CopyError::LineNOIdx] = cstate->cur_lineno; /* save the raw data here */ @@ -503,6 +863,7 @@ void CopyErrorLogger::FormError(CopyState cstate, Datum begintime, CopyError *ie ierror->m_isNull[CopyError::RawDataIdx] = true; } + // 淇濆瓨璇︾粏淇℃伅锛堝鏋滃彲鐢級锛屾敞鎰忛檺鍒舵暟鎹暱搴 if (detail != NULL) { char *detailVal = limit_printout_length(detail); int leng = strlen(detailVal); @@ -513,30 +874,65 @@ void CopyErrorLogger::FormError(CopyState cstate, Datum begintime, CopyError *ie } else ierror->m_isNull[CopyError::DetailIdx] = true; + // 閲婃斁鍏崇郴鍚嶇殑鍐呭瓨 pfree(relname); } -void CopyErrorLogger::FormWhenLog(CopyState cstate, Datum begintime, CopyError *ierror) +/* + * 鍔熻兘锛氭牴鎹敊璇俊鎭敓鎴 CopyError 瀵硅薄 + * + * 鍙傛暟鍒楄〃锛 + * cstate锛氬綋鍓嶇殑澶嶅埗鐘舵 + * begintime锛氬紑濮嬫椂闂 + * ierror锛氭寚鍚 CopyError 瀵硅薄鐨勬寚閽堬紝鐢ㄤ簬瀛樺偍鐢熸垚鐨勯敊璇俊鎭 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庣敓鎴 CopyError 瀵硅薄锛屽皢閿欒淇℃伅濉厖鍒 CopyError 涓 + * 瀹冩牴鎹鍒剁姸鎬併佸紑濮嬫椂闂淬侀敊璇弿杩扮瓑淇℃伅鍒涘缓閿欒璁板綍銆 + */ +void CopyErrorLogger::FormError(CopyState cstate, Datum begintime, CopyError *ierror) { + // 澹版槑 ErrorData 鎸囬拡鍜屽叾浠栧彉閲 + ErrorData *edata = NULL; + int len = 0; const char *detail = NULL; char *relname = NULL; + int sqlerrcode; errno_t rc; char *source = NULL; + // 鏂█纭繚浼犲叆鐨 CopyError 瀵硅薄闈炵┖ Assert(ierror != NULL); - detail = "COPY_WHEN_ROWS"; + + // 鑾峰彇褰撳墠閿欒淇℃伅 + edata = CopyErrorData(); + detail = edata->message; + sqlerrcode = edata->sqlerrcode; + + // 閲嶇疆 CopyError 瀵硅薄锛屾竻绌轰箣鍓嶇殑鏁版嵁 ierror->Reset(); + // 璁剧疆 CopyError 鐨勬弿杩扮涓洪敊璇弿杩扮 ierror->m_desc = m_errDesc; + // 鏋勫缓鍏崇郴鍚嶏紝鏍煎紡涓 "鍛藉悕绌洪棿.琛ㄥ悕" relname = (char *)palloc(MAX_NAME_LEN); rc = snprintf_s(relname, MAX_NAME_LEN, MAX_NAME_LEN - 1, "%s.%s", cstate->logger->m_namespace, RelationGetRelationName(cstate->rel)); securec_check_ss(rc, "\0", "\0"); - ierror->m_values[CopyError::RelNameIdx] = PointerGetDatum(cstring_to_text_with_len(relname, strlen(relname))); + // 鍒嗛厤骞惰缃叧绯诲悕 + len = strlen(relname) + VARHDRSZ; + ierror->m_values[CopyError::RelNameIdx] = (Datum)palloc(len); + SET_VARSIZE(ierror->m_values[CopyError::RelNameIdx], len); + rc = + memcpy_s(((char *)ierror->m_values[CopyError::RelNameIdx]) + VARHDRSZ, len - VARHDRSZ, relname, len - VARHDRSZ); + securec_check_c(rc, "\0", "\0"); + + // 璁剧疆寮濮嬫椂闂 ierror->m_values[CopyError::StartTimeIdx] = begintime; + // 璁剧疆鏂囦欢鍚 if (cstate->filename) source = cstate->filename; else { @@ -544,25 +940,45 @@ void CopyErrorLogger::FormWhenLog(CopyState cstate, Datum begintime, CopyError * source = "STDIN"; } - ierror->m_values[CopyError::FileNameIdx] = PointerGetDatum(cstring_to_text_with_len(source, strlen(source))); + // 鍒嗛厤骞惰缃枃浠跺悕 + len = strlen(source) + VARHDRSZ; + ierror->m_values[CopyError::FileNameIdx] = (Datum)palloc(len); + SET_VARSIZE(ierror->m_values[CopyError::FileNameIdx], len); + rc = + memcpy_s(((char *)ierror->m_values[CopyError::FileNameIdx]) + VARHDRSZ, len - VARHDRSZ, source, len - VARHDRSZ); + securec_check_c(rc, "\0", "\0"); + + // 璁剧疆琛屽彿 ierror->m_values[CopyError::LineNOIdx] = cstate->cur_lineno; /* save the raw data here */ - if (cstate->line_buf.len > 0 && cstate->logErrorsData) { + if (cstate->line_buf.len > 0 && sqlerrcode != ERRCODE_CHARACTER_NOT_IN_REPERTOIRE && + sqlerrcode != ERRCODE_UNTRANSLATABLE_CHARACTER && cstate->logErrorsData) { char *rawDataVal = NULL; + int rawDataValLen = 0; rawDataVal = limit_printout_length(cstate->line_buf.data); - ierror->m_values[CopyError::RawDataIdx] = - PointerGetDatum(cstring_to_text_with_len(rawDataVal, strlen(rawDataVal))); - pfree(rawDataVal); + rawDataValLen = strlen(rawDataVal); + len = rawDataValLen + VARHDRSZ; + ierror->m_values[CopyError::RawDataIdx] = (Datum)palloc(len); + SET_VARSIZE(ierror->m_values[CopyError::RawDataIdx], len); + rc = memcpy_s(((char *)ierror->m_values[CopyError::RawDataIdx]) + VARHDRSZ, len - VARHDRSZ, rawDataVal, + rawDataValLen); + securec_check(rc, "", ""); } else { ierror->m_isNull[CopyError::RawDataIdx] = true; } + // 淇濆瓨璇︾粏淇℃伅锛堝鏋滃彲鐢級锛屾敞鎰忛檺鍒舵暟鎹暱搴 if (detail != NULL) { - ierror->m_values[CopyError::DetailIdx] = PointerGetDatum(cstring_to_text_with_len(detail, strlen(detail))); - } else { + char *detailVal = limit_printout_length(detail); + int leng = strlen(detailVal); + ierror->m_values[CopyError::DetailIdx] = (Datum)palloc(leng + VARHDRSZ); + SET_VARSIZE(ierror->m_values[CopyError::DetailIdx], leng + VARHDRSZ); + rc = memcpy_s(((char *)ierror->m_values[CopyError::DetailIdx]) + VARHDRSZ, leng, detail, leng); + securec_check_c(rc, "\0", "\0"); + } else ierror->m_isNull[CopyError::DetailIdx] = true; - } + // 閲婃斁鍏崇郴鍚嶇殑鍐呭瓨 pfree(relname); } diff --git a/src/gausskernel/storage/bulkload/parser.cpp b/src/gausskernel/storage/bulkload/parser.cpp index e716eb5e1..3745d8148 100644 --- a/src/gausskernel/storage/bulkload/parser.cpp +++ b/src/gausskernel/storage/bulkload/parser.cpp @@ -78,7 +78,7 @@ using namespace GDS; #ifdef GDS_SERVER extern gds_settings settings; -extern THR_LOCAL GDS_Connection* current_connection; +extern THR_LOCAL GDS_Connection *current_connection; /* GDS server required declearations */ #define parser_log gs_ereport @@ -86,10 +86,10 @@ extern THR_LOCAL GDS_Connection* current_connection; #define parser_securec_check_ss gds_securec_check_ss /* extern from gds_main.cpp */ -extern string UriToLocalPath(const char* strUri); +extern string UriToLocalPath(const char *strUri); extern size_t GetDataSegmentSize(); -extern char* gs_strerror(int errnum); -static void GetFileHeader(WritableParser* self, const char* path); +extern char *gs_strerror(int errnum); +static void GetFileHeader(WritableParser *self, const char *path); #endif #ifdef OBS_SERVER @@ -99,45 +99,70 @@ static void GetFileHeader(WritableParser* self, const char* path); #define parser_securec_check_ss(rc) securec_check_ss(rc, "\0", "\0") #ifndef ENABLE_LITE_MODE -static size_t SourceRead_OBS(Source* self, void* buffer, size_t len); -static bool SourceNext_OBS(Source* self); +static size_t SourceRead_OBS(Source *self, void *buffer, size_t len); +static bool SourceNext_OBS(Source *self); #endif #endif -static Source* CreateSource(const FileList* files, SourceType sourcetype); -static void DestroyParser(Parser* self); -static void DestroyReadableParser(ReadableParser* self); -static void DestroyWritableParser(WritableParser* self); -static void CleanupWritablParser(WritableParser* self); -static void NopCleanup(Parser* self); +static Source *CreateSource(const FileList *files, SourceType sourcetype); +static void DestroyParser(Parser *self); +static void DestroyReadableParser(ReadableParser *self); +static void DestroyWritableParser(WritableParser *self); +static void CleanupWritablParser(WritableParser *self); +static void NopCleanup(Parser *self); -static char* FindEolChar(char* s, size_t len, const char* eol, int* eol_cur, int* eol_cur_saved) +/* + * 鍔熻兘锛氭煡鎵惧瓧绗︿覆涓殑琛屽熬瀛楃 + * + * 鍙傛暟鍒楄〃锛 + * s锛歝har 鎸囬拡锛岃〃绀哄緟鏌ユ壘鐨勫瓧绗︿覆 + * len锛歴ize_t锛岃〃绀哄瓧绗︿覆鐨勯暱搴 + * eol锛歝onst char 鎸囬拡锛岃〃绀鸿灏惧瓧绗︾殑瀹氫箟 + * eol_cur锛歩nt 鎸囬拡锛岀敤浜庝繚瀛樺綋鍓嶈灏惧瓧绗︾殑浣嶇疆 + * eol_cur_saved锛歩nt 鎸囬拡锛岀敤浜庝繚瀛樹箣鍓嶇殑琛屽熬瀛楃鐨勪綅缃 + * + * 杩斿洖鍊硷細 + * 濡傛灉鎵惧埌琛屽熬瀛楃锛岃繑鍥炴寚鍚戣瀛楃鐨勬寚閽堬紱鍚﹀垯杩斿洖 NULL銆 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庡湪瀛楃涓蹭腑鏌ユ壘琛屽熬瀛楃锛岃灏惧瓧绗﹀彲浠ユ槸 '\r'銆'\n' 鎴栬嚜瀹氫箟鐨勫瓧绗︿覆銆 + * 褰 eol 鍙傛暟涓 NULL 鏃讹紝鍑芥暟浼氭煡鎵 '\r' 鎴 '\n'锛屽苟杩斿洖绗竴涓壘鍒扮殑瀛楃銆 + * 褰 eol 鍙傛暟涓嶄负 NULL 鏃讹紝鍑芥暟浼氭煡鎵捐嚜瀹氫箟鐨勮灏惧瓧绗︿覆锛屽苟杩斿洖鏁翠釜琛屽熬瀛楃涓茬殑璧峰浣嶇疆銆 + */ + +static char *FindEolChar(char *s, size_t len, const char *eol, int *eol_cur, int *eol_cur_saved) { - char* end = NULL; - char* cr = NULL; - char* lf = NULL; + char *end = NULL; + char *cr = NULL; + char *lf = NULL; end = s + len; + if (eol == NULL) { + // 濡傛灉 eol 涓 NULL锛屾煡鎵 '\r' 鎴 '\n' while (s < end) { size_t chunk = (s + CHUNK_SZ < end) ? CHUNK_SZ : (end - s); - cr = (char*)memchr(s, '\r', chunk); - lf = (char*)memchr(s, '\n', chunk); + cr = (char *)memchr(s, '\r', chunk); + lf = (char *)memchr(s, '\n', chunk); + if (cr != NULL) { if (lf != NULL && lf < cr) - return lf; - return cr; + return lf; // 杩斿洖鎵惧埌鐨 '\n' + return cr; // 杩斿洖鎵惧埌鐨 '\r' } else if (lf != NULL) - return lf; + return lf; // 杩斿洖鎵惧埌鐨 '\n' + s += CHUNK_SZ; } } else { int eol_len = strlen(eol); *eol_cur_saved = *eol_cur; + + // 鏌ユ壘鑷畾涔夌殑琛屽熬瀛楃涓 for (int i = 0; i < (int)len; i++) { if (s[i] == eol[*eol_cur]) { (*eol_cur)++; if (*eol_cur >= eol_len) { - return s + i + 1 + *eol_cur_saved - eol_len; + return s + i + 1 + *eol_cur_saved - eol_len; // 杩斿洖鏁翠釜琛屽熬瀛楃涓茬殑璧峰浣嶇疆 } continue; } else if (*eol_cur >= 1) { @@ -145,192 +170,333 @@ static char* FindEolChar(char* s, size_t len, const char* eol, int* eol_cur, int // Here we allow i back into -1, and on the beginning of the next loop it will be back to 0, as // expected. i--; + // 淇濊瘉姣忎釜瀛楃閮戒笌 eol 杩涜姣旇緝 + // 鍏佽 i 鍥為鍒 -1锛屽湪涓嬩竴娆″惊鐜紑濮嬫椂灏嗗叾閲嶇疆涓 0 + i--; } *eol_cur = 0; *eol_cur_saved = 0; } } - return NULL; + return NULL; // 鏈壘鍒拌灏惧瓧绗 } -static Source* CreateSource(const FileList* files, SourceType sourcetype) +/* + * 鍔熻兘锛氬垱寤烘簮瀵硅薄 + * + * 鍙傛暟鍒楄〃锛 + * files锛歝onst FileList 鎸囬拡锛岃〃绀烘枃浠跺垪琛 + * sourcetype锛歋ourceType锛岃〃绀烘簮绫诲瀷 + * + * 杩斿洖鍊硷細 + * 杩斿洖鎸囧悜鍒涘缓鐨 Source 瀵硅薄鐨勬寚閽堛 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庡垱寤轰竴涓 Source 瀵硅薄锛屽垵濮嬪寲鍏跺睘鎬э紝骞惰繑鍥炴寚鍚戣瀵硅薄鐨勬寚閽堛 + * 濡傛灉鍐呭瓨鍒嗛厤澶辫触锛屼細璁板綍閿欒鏃ュ織骞惰繑鍥 NULL銆 + */ + +static Source *CreateSource(const FileList *files, SourceType sourcetype) { - Source* self = NULL; + Source *self = NULL; // 澹版槑涓涓 Source 鎸囬拡骞跺垵濮嬪寲涓 NULL try { - self = new Source; - } catch (std::bad_alloc&) { + self = new Source; // 灏濊瘯鍒嗛厤鍐呭瓨骞跺垱寤 Source 瀵硅薄 + } catch (std::bad_alloc &) { + // 鎹曡幏鍐呭瓨鍒嗛厤寮傚父锛岃褰曢敊璇棩蹇楀苟杩斿洖 NULL parser_log(LEVEL_ERROR, "failed to create source, out of memory"); } if (files != NULL) - self->SetFileList(*files); - self->SetSourceType(sourcetype); - self->SourceInit(files == NULL); + self->SetFileList(*files); // 濡傛灉浼犲叆鐨勬枃浠跺垪琛ㄤ笉涓虹┖锛岃缃 Source 瀵硅薄鐨勬枃浠跺垪琛 - return self; + self->SetSourceType(sourcetype); // 璁剧疆 Source 瀵硅薄鐨勬簮绫诲瀷 + self->SourceInit(files == NULL); // 璋冪敤 SourceInit 鍑芥暟锛屽垵濮嬪寲 Source 瀵硅薄鐨勫叾浠栧睘鎬 + + return self; // 杩斿洖鍒涘缓鐨 Source 瀵硅薄鐨勬寚閽 } /* specified for general file source reading */ -static size_t SourceRead_File(Source* self, void* buffer, size_t len) +/* + * 鍔熻兘锛氫粠鏂囦欢婧愪腑璇诲彇鏁版嵁 + * + * 鍙傛暟鍒楄〃锛 + * self锛歋ource 鎸囬拡锛岃〃绀烘簮瀵硅薄 + * buffer锛歷oid 鎸囬拡锛岃〃绀烘暟鎹紦鍐插尯 + * len锛歴ize_t锛岃〃绀鸿璇诲彇鐨勬暟鎹暱搴 + * + * 杩斿洖鍊硷細 + * 杩斿洖瀹為檯璇诲彇鐨勬暟鎹暱搴︺ + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庝粠鏂囦欢婧愪腑璇诲彇鏁版嵁銆傚畠棣栧厛灏濊瘯鎵ц POSIX_FADVISE 鎿嶄綔锛岀劧鍚庝娇鐢 fread 鍑芥暟浠庢枃浠朵腑璇诲彇鏁版嵁銆 + * 濡傛灉鍦ㄨ鍙栨暟鎹椂鍙戠敓閿欒锛屼細璁板綍閿欒鏃ュ織銆 + */ + +static size_t SourceRead_File(Source *self, void *buffer, size_t len) { - size_t nread; - const char* err_file = self->m_files[self->m_current - 1].c_str(); + size_t nread; // 鐢ㄤ簬淇濆瓨瀹為檯璇诲彇鐨勬暟鎹暱搴 + const char *err_file = self->m_files[self->m_current - 1].c_str(); // 鑾峰彇褰撳墠鏂囦欢鍚 #if defined(USE_POSIX_FADVISE) - off_t offset = lseek(fileno(self->m_fd), 0, SEEK_CUR); + off_t offset = lseek(fileno(self->m_fd), 0, SEEK_CUR); // 鑾峰彇褰撳墠鏂囦欢鍋忕Щ閲 if (offset >= 0) (void)posix_fadvise(fileno(self->m_fd), offset + len, INITIAL_BUF_LEN, POSIX_FADV_WILLNEED); + // 鎵ц POSIX_FADVISE 鎿嶄綔锛屾彁鍓嶅姞杞芥枃浠舵暟鎹 #endif - nread = fread(buffer, 1, len, self->m_fd); - if (ferror(self->m_fd)) - parser_log(LEVEL_ERROR, "could not read source file: %s", err_file); - return nread; + nread = fread(buffer, 1, len, self->m_fd); // 浣跨敤 fread 鍑芥暟浠庢枃浠朵腑璇诲彇鏁版嵁 + if (ferror(self->m_fd)) + parser_log(LEVEL_ERROR, "could not read source file: %s", err_file); // 濡傛灉璇诲彇鍑洪敊锛岃褰曢敊璇棩蹇 + + return nread; // 杩斿洖瀹為檯璇诲彇鐨勬暟鎹暱搴 } /* specified for pipe source reading */ -static size_t SourceRead_FIFO(Source* self, void* buffer, size_t len) +/* + * 鍔熻兘锛氫粠 FIFO锛堝懡鍚嶇閬擄級婧愪腑璇诲彇鏁版嵁 + * + * 鍙傛暟鍒楄〃锛 + * self锛歋ource 鎸囬拡锛岃〃绀烘簮瀵硅薄 + * buffer锛歷oid 鎸囬拡锛岃〃绀烘暟鎹紦鍐插尯 + * len锛歴ize_t锛岃〃绀鸿璇诲彇鐨勬暟鎹暱搴 + * + * 杩斿洖鍊硷細 + * 杩斿洖瀹為檯璇诲彇鐨勬暟鎹暱搴︺ + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庝粠 FIFO锛堝懡鍚嶇閬擄級婧愪腑璇诲彇鏁版嵁銆傚畠浣跨敤 read 鍑芥暟浠庡懡鍚嶇閬撲腑璇诲彇鏁版嵁锛 + * 濡傛灉鍦ㄨ鍙栨暟鎹椂鍙戠敓閿欒锛屼細璁板綍閿欒鏃ュ織銆 + */ + +static size_t SourceRead_FIFO(Source *self, void *buffer, size_t len) { - const char* err_file = self->m_files[0].c_str(); + const char *err_file = self->m_files[0].c_str(); // 鑾峰彇绠¢亾鏂囦欢鍚 #ifndef WIN32 - ssize_t nread = read(self->m_fifo, buffer, len); + ssize_t nread = read(self->m_fifo, buffer, len); // 浣跨敤 read 鍑芥暟浠庡懡鍚嶇閬撲腑璇诲彇鏁版嵁 #else - int nread = read(self->m_fifo, buffer, len); + int nread = read(self->m_fifo, buffer, len); // 浣跨敤 read 鍑芥暟浠庡懡鍚嶇閬撲腑璇诲彇鏁版嵁 #endif + if (-1 == nread) - parser_log(LEVEL_ERROR, "could not read source file: %s", err_file); - return (size_t)nread; + parser_log(LEVEL_ERROR, "could not read source file: %s", err_file); // 濡傛灉璇诲彇鍑洪敊锛岃褰曢敊璇棩蹇 + + return (size_t)nread; // 杩斿洖瀹為檯璇诲彇鐨勬暟鎹暱搴 } /* specified for general file source checking next file */ -static bool SourceNext_File(Source* self) +/* + * 鍔熻兘锛氬垏鎹㈠埌涓嬩竴涓枃浠舵簮 + * + * 鍙傛暟鍒楄〃锛 + * self锛歋ource 鎸囬拡锛岃〃绀烘簮瀵硅薄 + * + * 杩斿洖鍊硷細 + * 濡傛灉鎴愬姛鍒囨崲鍒颁笅涓涓枃浠舵簮锛岃繑鍥 true锛涘惁鍒欒繑鍥 false銆 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庡垏鎹㈠埌涓嬩竴涓枃浠舵簮锛屽鏋滃綋鍓嶆枃浠舵簮宸茬粡鎵撳紑锛屽垯鍏抽棴瀹冦 + * 鐒跺悗灏濊瘯鎵撳紑涓嬩竴涓枃浠舵簮锛屽鏋滄墦寮澶辫触锛屼細璁板綍璀﹀憡鏃ュ織銆 + */ + +static bool SourceNext_File(Source *self) { - const char* err_file = NULL; - const char* current_file = NULL; + const char *err_file = NULL; // 鐢ㄤ簬璁板綍閿欒鏂囦欢鍚 + const char *current_file = NULL; // 鐢ㄤ簬璁板綍褰撳墠鏂囦欢鍚 if (self->m_fd != NULL) { - fclose(self->m_fd); + fclose(self->m_fd); // 濡傛灉褰撳墠鏂囦欢婧愬凡缁忔墦寮锛屽垯鍏抽棴瀹 self->m_fd = NULL; } if ((size_t)(self->m_current) >= self->m_files.size()) - return false; + return false; // 濡傛灉宸茬粡閬嶅巻瀹屾墍鏈夋枃浠舵簮锛岃繑鍥 false + while (self->m_fd == NULL && (size_t)(self->m_current) < self->m_files.size()) { - current_file = self->m_files[self->m_current++].c_str(); - self->m_fd = fopen(current_file, "r"); + current_file = self->m_files[self->m_current++].c_str(); // 鑾峰彇涓嬩竴涓枃浠跺悕 + self->m_fd = fopen(current_file, "r"); // 灏濊瘯鎵撳紑涓嬩竴涓枃浠舵簮 + if (self->m_fd == NULL) { - err_file = self->m_files[self->m_current - 1].c_str(); - parser_log(LEVEL_WARNING, "Unable to open %s", err_file); + err_file = self->m_files[self->m_current - 1].c_str(); // 鑾峰彇鎵撳紑澶辫触鐨勬枃浠跺悕 + parser_log(LEVEL_WARNING, "Unable to open %s", err_file); // 璁板綍璀﹀憡鏃ュ織 } } if (self->m_fd != NULL) { - self->m_filename = self->m_files[self->m_current - 1]; + self->m_filename = self->m_files[self->m_current - 1]; // 璁剧疆褰撳墠鏂囦欢鍚嶅睘鎬 #if defined(USE_POSIX_FADVISE) - (void)posix_fadvise( - fileno(self->m_fd), 0, INITIAL_BUF_LEN, POSIX_FADV_SEQUENTIAL | POSIX_FADV_NOREUSE | POSIX_FADV_WILLNEED); + (void)posix_fadvise(fileno(self->m_fd), 0, INITIAL_BUF_LEN, + POSIX_FADV_SEQUENTIAL | POSIX_FADV_NOREUSE | POSIX_FADV_WILLNEED); + // 鎵ц POSIX_FADVISE 鎿嶄綔锛屾彁鍓嶅姞杞芥枃浠舵暟鎹 #endif } - return self->m_fd != NULL; + return self->m_fd != NULL; // 杩斿洖鏄惁鎴愬姛鎵撳紑涓嬩竴涓枃浠舵簮 } /* specified for pipe source checking next file */ -static bool SourceNext_FIFO(Source* self) +static bool SourceNext_FIFO(Source *self) { return false; } #ifdef GDS_SERVER -void Source::SourceWrite(evbuffer* buffer, size_t len) +/* + * 鍔熻兘锛氬皢鏁版嵁鍐欏叆婧愮殑鍐欑紦鍐插尯 + * + * 鍙傛暟鍒楄〃锛 + * buffer锛歟vbuffer 鎸囬拡锛岃〃绀烘暟鎹紦鍐插尯 + * len锛歴ize_t锛岃〃绀鸿鍐欏叆鐨勬暟鎹暱搴 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庡皢鏁版嵁鍐欏叆婧愮殑鍐欑紦鍐插尯銆傚畠浼氬皾璇曞皢鏁版嵁浠庣紦鍐插尯涓鍒跺埌鍐欑紦鍐插尯銆 + * 濡傛灉澶嶅埗澶辫触锛屼細璁板綍閿欒鏃ュ織銆傚鏋滃彂鐜版棤鏁堢殑閿欒璁板綍锛屼篃浼氳褰曢敊璇棩蹇椼 + */ + +void Source::SourceWrite(evbuffer *buffer, size_t len) { - int nsave; - int result; + int nsave; // 鐢ㄤ簬淇濆瓨澶嶅埗鐨勬暟鎹暱搴 + int result; // 鐢ㄤ簬淇濆瓨澶嶅埗缁撴灉 while (len > 0) { if (m_wused == MAX_BUFFER_SIZE) - SourceFlush(); - nsave = Min(len, MAX_BUFFER_SIZE - m_wused); - result = evbuffer_remove(buffer, m_writeBuf + m_wused, nsave); + SourceFlush(); // 濡傛灉鍐欑紦鍐插尯宸叉弧锛屾墽琛屽啓鍏ユ搷浣 + + nsave = Min(len, MAX_BUFFER_SIZE - m_wused); // 璁$畻瑕佸鍒剁殑鏁版嵁闀垮害 + result = evbuffer_remove(buffer, m_writeBuf + m_wused, nsave); // 浠庢暟鎹紦鍐插尯澶嶅埗鏁版嵁鍒板啓缂撳啿鍖 + if (result == -1) - parser_log(LEVEL_ERROR, "failed to copy data to write buffer"); + parser_log(LEVEL_ERROR, "failed to copy data to write buffer"); // 濡傛灉澶嶅埗澶辫触锛岃褰曢敊璇棩蹇 else if (result == 0) - parser_log(LEVEL_ERROR, "invaild error recored"); - m_woffset += result; - len -= result; - m_wused += result; + parser_log(LEVEL_ERROR, "invalid error record"); // 濡傛灉鍙戠幇鏃犳晥鐨勯敊璇褰曪紝璁板綍閿欒鏃ュ織 + + m_woffset += result; // 鏇存柊鍐欏亸绉婚噺 + len -= result; // 鍑忓幓宸插鍒剁殑鏁版嵁闀垮害 + m_wused += result; // 鏇存柊鍐欑紦鍐插尯宸茬敤闀垮害 } } #endif -void Source::SourceWrite(const char* buffer, size_t len) +/* + * 鍔熻兘锛氬皢鏁版嵁鍐欏叆婧愮殑鍐欑紦鍐插尯 + * + * 鍙傛暟鍒楄〃锛 + * buffer锛歝onst char 鎸囬拡锛岃〃绀烘暟鎹紦鍐插尯 + * len锛歴ize_t锛岃〃绀鸿鍐欏叆鐨勬暟鎹暱搴 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庡皢鏁版嵁鍐欏叆婧愮殑鍐欑紦鍐插尯銆傚畠浼氬惊鐜皢鏁版嵁浠庣紦鍐插尯涓鍒跺埌鍐欑紦鍐插尯锛 + * 鐩村埌鎵鏈夋暟鎹兘琚啓鍏ユ垨鍐欑紦鍐插尯宸叉弧銆傚鏋滃鍒跺け璐ワ紝浼氳褰曢敊璇棩蹇椼 + */ + +void Source::SourceWrite(const char *buffer, size_t len) { - int nsave; - errno_t rc; + int nsave; // 鐢ㄤ簬淇濆瓨澶嶅埗鐨勬暟鎹暱搴 + errno_t rc; // 鐢ㄤ簬淇濆瓨澶嶅埗缁撴灉 while (len > 0) { if (m_wused == MAX_BUFFER_SIZE) - SourceFlush(); - nsave = Min(len, MAX_BUFFER_SIZE - m_wused); - rc = memcpy_s(m_writeBuf + m_wused, nsave, buffer, nsave); - parser_securec_check(rc); - m_woffset += nsave; - len -= nsave; - m_wused += nsave; + SourceFlush(); // 濡傛灉鍐欑紦鍐插尯宸叉弧锛屾墽琛屽啓鍏ユ搷浣 + nsave = Min(len, MAX_BUFFER_SIZE - m_wused); // 璁$畻瑕佸鍒剁殑鏁版嵁闀垮害 + rc = memcpy_s(m_writeBuf + m_wused, nsave, buffer, nsave); // 浠庢暟鎹紦鍐插尯澶嶅埗鏁版嵁鍒板啓缂撳啿鍖 + parser_securec_check(rc); // 妫鏌ュ鍒舵槸鍚︽垚鍔 + m_woffset += nsave; // 鏇存柊鍐欏亸绉婚噺 + len -= nsave; // 鍑忓幓宸插鍒剁殑鏁版嵁闀垮害 + m_wused += nsave; // 鏇存柊鍐欑紦鍐插尯宸茬敤闀垮害 } } -size_t Source::SourceWriteInternal(const void* buffer, size_t len) +/* + * 鍔熻兘锛氬皢鏁版嵁鍐欏叆褰撳墠鏂囦欢婧 + * + * 鍙傛暟鍒楄〃锛 + * buffer锛歝onst void 鎸囬拡锛岃〃绀烘暟鎹紦鍐插尯 + * len锛歴ize_t锛岃〃绀鸿鍐欏叆鐨勬暟鎹暱搴 + * + * 杩斿洖鍊硷細 + * 杩斿洖瀹為檯鍐欏叆鐨勬暟鎹暱搴︺ + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庡皢鏁版嵁鍐欏叆褰撳墠鏂囦欢婧愩傚畠棣栧厛妫鏌ユ枃浠舵弿杩扮鏄惁涓虹┖锛屽鏋滀负绌猴紝鍒欒褰曢敊璇棩蹇椼 + * 鐒跺悗浣跨敤 fwrite 鍑芥暟灏嗘暟鎹啓鍏ユ枃浠讹紝濡傛灉鍐欏叆鍑洪敊锛屼篃浼氳褰曢敊璇棩蹇椼 + */ + +size_t Source::SourceWriteInternal(const void *buffer, size_t len) { - size_t nwrite = 0; - const char* err_file = m_files[m_current - 1].c_str(); + size_t nwrite = 0; // 鐢ㄤ簬淇濆瓨瀹為檯鍐欏叆鐨勬暟鎹暱搴 + const char *err_file = m_files[m_current - 1].c_str(); // 鑾峰彇褰撳墠鏂囦欢鍚 + if (m_fd == NULL) { - parser_log(LEVEL_ERROR, "could not write file: %s, caused by fd empty.", err_file); + parser_log(LEVEL_ERROR, "could not write file: %s, caused by fd empty.", + err_file); // 濡傛灉鏂囦欢鎻忚堪绗︿负绌猴紝璁板綍閿欒鏃ュ織 } - nwrite = fwrite(buffer, 1, len, m_fd); + + nwrite = fwrite(buffer, 1, len, m_fd); // 浣跨敤 fwrite 鍑芥暟灏嗘暟鎹啓鍏ユ枃浠 if (ferror(m_fd)) { parser_log(LEVEL_ERROR, "could not write file %s with Error: %s", err_file, gs_strerror(errno)); + // 濡傛灉鍐欏叆鍑洪敊锛岃褰曢敊璇棩蹇 } - return nwrite; + + return nwrite; // 杩斿洖瀹為檯鍐欏叆鐨勬暟鎹暱搴 } -void Source::GenerateNewFile(const char* prefix, const char* suffix) -{ - char path[MAX_PATH_LEN] = {0}; - errno_t rc = EOK; +/* + * 鍔熻兘锛氱敓鎴愭柊鏂囦欢骞跺垏鎹负褰撳墠鏂囦欢婧 + * + * 鍙傛暟鍒楄〃锛 + * prefix锛歝onst char 鎸囬拡锛岃〃绀烘柊鏂囦欢鐨勫墠缂 + * suffix锛歝onst char 鎸囬拡锛岃〃绀烘柊鏂囦欢鐨勫悗缂 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庣敓鎴愭柊鏂囦欢骞跺垏鎹负褰撳墠鏂囦欢婧愩傚畠棣栧厛鏍规嵁鍓嶇紑鍜屽悗缂鐢熸垚鏂版枃浠剁殑璺緞銆 + * 鐒跺悗妫鏌ユ枃浠舵槸鍚﹀凡瀛樺湪锛屽鏋滃瓨鍦ㄥ垯缁х画鐢熸垚涓嬩竴涓枃浠躲 + * 鎺ョ潃鍏抽棴褰撳墠鏂囦欢锛屽皢鏂版枃浠惰矾寰勬坊鍔犲埌鏂囦欢鍒楄〃涓紝鐒跺悗灏濊瘯浠ュ啓妯″紡鎵撳紑鏂版枃浠躲 + * 濡傛灉鎵撳紑澶辫触锛屼細璁板綍閿欒鏃ュ織銆傜劧鍚庡皾璇曡缃柊鏂囦欢鐨勬潈闄愩 + * 鏈鍚庯紝閲嶇疆鍐欏亸绉婚噺涓0锛屽苟鍒囨崲涓烘柊鏂囦欢婧愩 + */ - ASSERT(prefix != NULL); +void Source::GenerateNewFile(const char *prefix, const char *suffix) +{ + char path[MAX_PATH_LEN] = {0}; // 鐢ㄤ簬淇濆瓨鏂版枃浠剁殑璺緞 + errno_t rc = EOK; // 鐢ㄤ簬淇濆瓨 snprintf_s 鍑芥暟鐨勮繑鍥炲 + + ASSERT(prefix != NULL); // 鏂█鍓嶇紑涓嶄负绌 for (int i = 0; i < MAX_SEGMENT_NUM; i++) { if (suffix != NULL) rc = snprintf_s(path, MAX_PATH_LEN, MAX_PATH_LEN - 1, "%s/%s.%s.%d", m_path.c_str(), prefix, suffix, i); else rc = snprintf_s(path, MAX_PATH_LEN, MAX_PATH_LEN - 1, "%s/%s.%d", m_path.c_str(), prefix, i); - parser_securec_check_ss(rc); -#ifdef WIN32 - LinuxPathToWin(path); -#endif - if (access(path, F_OK) != -1) - continue; + parser_securec_check_ss(rc); // 妫鏌 snprintf_s 鏄惁鎴愬姛 - CloseCurrentFile(); - m_files.push_back(path); +#ifdef WIN32 + LinuxPathToWin(path); // 灏嗚矾寰勮浆鎹负 Windows 鏍煎紡 +#endif + + if (access(path, F_OK) != -1) + continue; // 濡傛灉鏂囦欢宸插瓨鍦紝缁х画鐢熸垚涓嬩竴涓枃浠 + + CloseCurrentFile(); // 鍏抽棴褰撳墠鏂囦欢 + m_files.push_back(path); // 灏嗘柊鏂囦欢璺緞娣诲姞鍒版枃浠跺垪琛ㄤ腑 m_current++; - m_fd = fopen(path, "w"); + m_fd = fopen(path, "w"); // 灏濊瘯浠ュ啓妯″紡鎵撳紑鏂版枃浠 + if (m_fd == NULL) { - parser_log(LEVEL_ERROR, "failed to create new file %s", path); + parser_log(LEVEL_ERROR, "failed to create new file %s", path); // 濡傛灉鎵撳紑澶辫触锛岃褰曢敊璇棩蹇 } #ifndef WIN32 if (fchmod(fileno(m_fd), S_IRUSR | S_IWUSR) != 0) { - parser_log(LEVEL_ERROR, "failed to chmod file %s with Error: %s", path, gs_strerror(errno)); + parser_log(LEVEL_ERROR, "failed to chmod file %s with Error: %s", path, + gs_strerror(errno)); // 灏濊瘯璁剧疆鏂版枃浠剁殑鏉冮檺 } #endif - m_woffset = 0; - return; + + m_woffset = 0; // 閲嶇疆鍐欏亸绉婚噺涓0 + return; // 鍒囨崲涓烘柊鏂囦欢婧 } parser_log(LEVEL_ERROR, "failed to generate new file, because of too many files in directory"); + // 濡傛灉鐢熸垚鏂版枃浠跺け璐ワ紙鏂囦欢鏁拌繃澶氾級锛岃褰曢敊璇棩蹇 } /** @@ -341,117 +507,180 @@ void Source::GenerateNewFile(const char* prefix, const char* suffix) * @param suffix Export file path suffix. */ #ifdef GDS_SERVER -void Source::GenerateNewFileForExport(const char* prefix, const char* suffix) -{ - char path[MAX_PATH_LEN] = {0}; - errno_t rc = EOK; +/* + * 鍔熻兘锛氫负瀵煎嚭鐢熸垚鏂版枃浠跺苟鍒囨崲涓哄綋鍓嶆枃浠舵簮 + * + * 鍙傛暟鍒楄〃锛 + * prefix锛歝onst char 鎸囬拡锛岃〃绀烘柊鏂囦欢鐨勫墠缂 + * suffix锛歝onst char 鎸囬拡锛岃〃绀烘柊鏂囦欢鐨勫悗缂 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庝负瀵煎嚭鐢熸垚鏂版枃浠跺苟鍒囨崲涓哄綋鍓嶆枃浠舵簮銆傚畠棣栧厛鏍规嵁鍓嶇紑鍜屽悗缂鐢熸垚鏂版枃浠剁殑璺緞銆 + * 濡傛灉鍓嶇紑涓寘鍚棤鏁堢鍙凤紝鍒欒褰曢敊璇棩蹇椼傜劧鍚庢鏌ユ枃浠舵槸鍚﹀凡瀛樺湪锛屽鏋滃瓨鍦ㄥ垯缁х画鐢熸垚涓嬩竴涓枃浠躲 + * 瀵逛簬宸茬敓鎴愮殑鏂囦欢锛屽鏋滀笉瀛樺湪鍒欒褰曢敊璇棩蹇椼 + * 鎺ョ潃鍒犻櫎鏃ф枃浠讹紙濡傛灉瀛樺湪锛夛紝鍏抽棴褰撳墠鏂囦欢锛屽皢鏂版枃浠惰矾寰勬坊鍔犲埌鏂囦欢鍒楄〃涓紝鐒跺悗灏濊瘯浠ュ啓妯″紡鎵撳紑鏂版枃浠躲 + * 濡傛灉鎵撳紑澶辫触锛屼細璁板綍閿欒鏃ュ織銆傜劧鍚庡皾璇曡缃柊鏂囦欢鐨勬潈闄愩 + * 鏈鍚庯紝閲嶇疆鍐欏亸绉婚噺涓0锛屽苟鍒囨崲涓烘柊鏂囦欢婧愩 + */ - ASSERT(prefix != NULL); +void Source::GenerateNewFileForExport(const char *prefix, const char *suffix) +{ + char path[MAX_PATH_LEN] = {0}; // 鐢ㄤ簬淇濆瓨鏂版枃浠剁殑璺緞 + errno_t rc = EOK; // 鐢ㄤ簬淇濆瓨 snprintf_s 鍑芥暟鐨勮繑鍥炲 + + ASSERT(prefix != NULL); // 鏂█鍓嶇紑涓嶄负绌 if (strstr(prefix, InvalidSymbol) != NULL) { - parser_log(LEVEL_ERROR, "invalid path which include \"%s\"", InvalidSymbol); + parser_log(LEVEL_ERROR, "invalid path which include \"%s\"", + InvalidSymbol); // 濡傛灉鍓嶇紑鍖呭惈鏃犳晥绗﹀彿锛岃褰曢敊璇棩蹇 } + for (int i = 0; i < MAX_SEGMENT_NUM; i++) { if (suffix != NULL) { rc = snprintf_s(path, MAX_PATH_LEN, MAX_PATH_LEN - 1, "%s/%s.%s.%d", m_path.c_str(), prefix, suffix, i); } else { rc = snprintf_s(path, MAX_PATH_LEN, MAX_PATH_LEN - 1, "%s/%s.%d", m_path.c_str(), prefix, i); } - parser_securec_check_ss(rc); + parser_securec_check_ss(rc); // 妫鏌 snprintf_s 鏄惁鎴愬姛 + #ifdef WIN32 - LinuxPathToWin(path); + LinuxPathToWin(path); // 灏嗚矾寰勮浆鎹负 Windows 鏍煎紡 #endif + if (i < m_current) { if (access(path, F_OK) != 0) { parser_log(LEVEL_ERROR, - "export files incomplete because \"%s\" maybe deleted unexpected or no " - "permission to access,please delete rest of invalid export file.", - path); + "export files incomplete because \"%s\" maybe deleted unexpectedly or no " + "permission to access, please delete the rest of the invalid export files.", + path); // 瀵逛簬宸茬敓鎴愮殑鏂囦欢锛屽鏋滀笉瀛樺湪锛屽垯璁板綍閿欒鏃ュ織 } } else { if (access(path, F_OK) == 0) { - unlink(path); + unlink(path); // 鍒犻櫎鏃ф枃浠讹紙濡傛灉瀛樺湪锛 if (settings.debug_level >= DEBUG_NORMAL) { - gs_elog( - LEVEL_LOG, "delete export file during segment file generate for cn retry or repeat export."); + gs_elog(LEVEL_LOG, + "delete export file during segment file generation for CN retry or repeat export."); } } - CloseCurrentFile(); - m_files.push_back(path); + + CloseCurrentFile(); // 鍏抽棴褰撳墠鏂囦欢 + m_files.push_back(path); // 灏嗘柊鏂囦欢璺緞娣诲姞鍒版枃浠跺垪琛ㄤ腑 m_current++; - CanonicalizePath(path); - m_fd = fopen(path, "w"); + CanonicalizePath(path); // 瑙勮寖鍖栨枃浠惰矾寰 + m_fd = fopen(path, "w"); // 灏濊瘯浠ュ啓妯″紡鎵撳紑鏂版枃浠 + if (m_fd == NULL) { parser_log(LEVEL_ERROR, - "failed to create new file %s during segment file generate,please delete rest of invalid export " - "file with Error %s.", - path, - strerror(errno)); + "failed to create new file %s during segment file generation, please delete the rest of the " + "invalid export " + "files with Error: %s.", + path, strerror(errno)); // 濡傛灉鎵撳紑澶辫触锛岃褰曢敊璇棩蹇 } + #ifndef WIN32 if (fchmod(fileno(m_fd), LOG_PERM_GRPR) != 0) { - parser_log(LEVEL_ERROR,"Could not change permissions of file \"%s\"\n", path); + parser_log(LEVEL_ERROR, "Could not change permissions of file \"%s\"\n", path); // 灏濊瘯璁剧疆鏂版枃浠剁殑鏉冮檺 } #endif - m_woffset = 0; - return; + + m_woffset = 0; // 閲嶇疆鍐欏亸绉婚噺涓0 + return; // 鍒囨崲涓烘柊鏂囦欢婧 } } - parser_log(LEVEL_ERROR, "failed to generate new file, because of too many files in directory"); + parser_log(LEVEL_ERROR, "failed to generate new file, because there are too many files in the directory"); + // 濡傛灉鐢熸垚鏂版枃浠跺け璐ワ紙鏂囦欢鏁拌繃澶氾級锛岃褰曢敊璇棩蹇 } #endif +/* + * 鍔熻兘锛氬埛鏂版簮鐨勫啓缂撳啿鍖 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庡埛鏂版簮鐨勫啓缂撳啿鍖恒傚畠浼氬惊鐜皢鍐欑紦鍐插尯涓殑鏁版嵁鍐欏叆褰撳墠鏂囦欢婧愶紝 + * 鐩村埌鍐欑紦鍐插尯涓殑鏁版嵁鍏ㄩ儴鍐欏叆鎴栧啓鍏ュ嚭閿欍 + */ + void Source::SourceFlush() { - char* buf = m_writeBuf; + char *buf = m_writeBuf; // 鍒濆鍖栫紦鍐插尯鎸囬拡涓哄啓缂撳啿鍖虹殑璧峰鍦板潃 while (m_wused > 0) { - int nwrite = SourceWriteInternal(buf, m_wused); - buf += nwrite; - m_wused -= nwrite; + int nwrite = SourceWriteInternal(buf, m_wused); // 璋冪敤 SourceWriteInternal 鍑芥暟灏嗘暟鎹啓鍏ュ綋鍓嶆枃浠舵簮 + buf += nwrite; // 鏇存柊缂撳啿鍖烘寚閽 + m_wused -= nwrite; // 鏇存柊鍐欑紦鍐插尯宸茬敤闀垮害 } } +/* + * 鍔熻兘锛氬叧闂綋鍓嶆枃浠舵簮 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庡叧闂綋鍓嶆枃浠舵簮銆傞鍏堜細璋冪敤 SourceFlush 鍑芥暟鍒锋柊鍐欑紦鍐插尯锛 + * 鐒跺悗鍏抽棴鏂囦欢鎻忚堪绗︼紝骞跺皢鏂囦欢鍚嶅睘鎬ф竻绌恒 + */ + void Source::CloseCurrentFile() { - SourceFlush(); + SourceFlush(); // 鍒锋柊鍐欑紦鍐插尯 if (m_fd != NULL) { - fclose(m_fd); + fclose(m_fd); // 鍏抽棴鏂囦欢鎻忚堪绗 } - m_fd = NULL; + m_fd = NULL; // 灏嗘枃浠舵弿杩扮缃负绌 - m_filename = ""; + m_filename = ""; // 娓呯┖鏂囦欢鍚嶅睘鎬 } +/* + * 鍔熻兘锛氬叧闂綋鍓嶆枃浠舵簮锛堜笉鍒锋柊鍐欑紦鍐插尯锛 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庡叧闂綋鍓嶆枃浠舵簮锛屼絾涓嶄細鍒锋柊鍐欑紦鍐插尯銆傚畠浼氬叧闂枃浠舵弿杩扮锛 + * 骞跺皢鏂囦欢鍚嶅睘鎬ф竻绌猴紝鍚屾椂灏嗗啓缂撳啿鍖哄凡鐢ㄩ暱搴︾疆涓0銆 + */ + void Source::CloseCurrentFileNoFlush() { if (m_fd != NULL) { - fclose(m_fd); + fclose(m_fd); // 鍏抽棴鏂囦欢鎻忚堪绗 } - m_fd = NULL; - m_wused = 0; - m_filename = ""; + m_fd = NULL; // 灏嗘枃浠舵弿杩扮缃负绌 + m_wused = 0; // 灏嗗啓缂撳啿鍖哄凡鐢ㄩ暱搴︾疆涓0 + m_filename = ""; // 娓呯┖鏂囦欢鍚嶅睘鎬 } +/* + * 鍔熻兘锛氬垵濮嬪寲婧愬璞 + * + * 鍙傛暟鍒楄〃锛 + * isWrite锛歜ool锛岃〃绀烘槸鍚︽槸鍐欐搷浣 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庡垵濮嬪寲婧愬璞°傚鏋滄槸鍐欐搷浣滐紝浼氬垎閰嶅啓缂撳啿鍖哄唴瀛樸 + * 濡傛灉鏄鎿嶄綔锛屼細鏍规嵁涓嶅悓鐨勬儏鍐甸夋嫨婧愮殑璇诲彇鍜屼笅涓涓簮鐨勫嚱鏁般 + * 濡傛灉鏄粠绠¢亾涓鍙栨暟鎹紝鍒欎細灏嗚鍙栧拰涓嬩竴涓簮鐨勫嚱鏁拌缃负璇诲彇绠¢亾鐨勫嚱鏁般 + * 濡傛灉鏄粠鏂囦欢涓鍙栨暟鎹紝鍒欎細灏嗚鍙栧拰涓嬩竴涓簮鐨勫嚱鏁拌缃负浠庢枃浠朵腑璇诲彇鐨勫嚱鏁般 + * 鏈鍚庯紝濡傛灉娌℃湁鍙互鎵撳紑鐨勬枃浠讹紝浼氳褰曢敊璇棩蹇椼 + */ + void Source::SourceInit(bool isWrite) { if (isWrite) { - m_writeBuf = (char*)malloc(MAX_BUFFER_SIZE); + m_writeBuf = (char *)malloc(MAX_BUFFER_SIZE); // 鍒嗛厤鍐欑紦鍐插尯鍐呭瓨 if (m_writeBuf == NULL) - parser_log(LEVEL_ERROR, "failed to init source, out of memory"); + parser_log(LEVEL_ERROR, "failed to init source, out of memory"); // 濡傛灉鍒嗛厤鍐呭瓨澶辫触锛岃褰曢敊璇棩蹇 } else { #ifndef WIN32 if (1 == m_files.size() && m_sourcetype == SOURCE_TYPE_FILE) { struct stat status; - const char* pipe_file = m_files[0].c_str(); + const char *pipe_file = m_files[0].c_str(); if (stat(pipe_file, &status)) parser_log(LEVEL_ERROR, "failed to init source"); /* detect fifo */ if (S_ISFIFO(status.st_mode)) { if (-1 == (m_fifo = open(pipe_file, O_RDONLY))) parser_log(LEVEL_ERROR, "failed to init source"); - SourceRead = SourceRead_FIFO; - SourceNext = SourceNext_FIFO; + SourceRead = SourceRead_FIFO; // 璁剧疆璇诲彇鍑芥暟涓轰粠绠¢亾涓鍙栨暟鎹殑鍑芥暟 + SourceNext = SourceNext_FIFO; // 璁剧疆涓嬩竴涓簮鍑芥暟涓轰粠绠¢亾涓鍙栦笅涓涓簮鐨勫嚱鏁 return; } } @@ -479,14 +708,24 @@ void Source::SourceInit(bool isWrite) #endif if (!SourceNext(this)) - parser_log(LEVEL_ERROR, "No files can be opened"); + parser_log(LEVEL_ERROR, "No files can be opened"); // 濡傛灉娌℃湁鍙互鎵撳紑鐨勬枃浠讹紝璁板綍閿欒鏃ュ織 } } #ifdef WIN32 -void LinuxPathToWin(char* path) +/* + * 鍔熻兘锛氬皢 Linux 璺緞杞崲涓 Windows 璺緞 + * + * 鍙傛暟鍒楄〃锛 + * path锛歝har 鎸囬拡锛岃〃绀哄緟杞崲鐨勮矾寰勫瓧绗︿覆 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庡皢 Linux 璺緞杞崲涓 Windows 璺緞銆傚畠浼氬皢璺緞涓殑鎵鏈夋枩鏉'/'鏇挎崲涓哄弽鏂滄潬'\'銆 + */ + +void LinuxPathToWin(char *path) { - char* slash = NULL; + char *slash = NULL; if (path == NULL) return; while (1) { @@ -494,17 +733,40 @@ void LinuxPathToWin(char* path) if (slash == NULL) break; - *slash = '\\'; + *slash = '\\'; // 灏嗘枩鏉犳浛鎹负鍙嶆枩鏉 } } #endif -static void NopReadLine(Parser* self, LineBuffer& buf) +/* + * 鍔熻兘锛氱┖鎿嶄綔璇诲彇琛屽嚱鏁 + * + * 鍙傛暟鍒楄〃锛 + * self锛歅arser 鎸囬拡锛岃〃绀鸿В鏋愬櫒瀵硅薄 + * buf锛歀ineBuffer 寮曠敤锛岃〃绀鸿鍙栬鐨勭紦鍐插尯 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庤〃绀鸿В鏋愬櫒涓嶆敮鎸佽鍙栨搷浣滐紝浠呯敤浜庤褰曢敊璇棩蹇椼 + */ + +static void NopReadLine(Parser *self, LineBuffer &buf) { parser_log(LEVEL_ERROR, "parser doesn't support read"); } -static void NopWriteLine(Parser* self, struct evbuffer& buf, size_t len) +/* + * 鍔熻兘锛氭棤鎿嶄綔鍐欏叆琛 + * + * 鍙傛暟鍒楄〃锛 + * self锛歅arser 鎸囬拡锛岃〃绀鸿В鏋愬櫒瀵硅薄 + * buf锛歟vbuffer 寮曠敤锛岃〃绀哄緟鍐欏叆鐨勬暟鎹紦鍐插尯 + * len锛歴ize_t锛岃〃绀哄緟鍐欏叆鐨勬暟鎹暱搴 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庤〃绀鸿В鏋愬櫒涓嶆敮鎸佸啓鍏ユ搷浣滐紝鍥犳浼氳褰曢敊璇棩蹇椼 + */ + +static void NopWriteLine(Parser *self, struct evbuffer &buf, size_t len) { parser_log(LEVEL_ERROR, "parser doesn't support write"); } @@ -523,21 +785,21 @@ static void NopWriteLine(Parser* self, struct evbuffer& buf, size_t len) * (2) If the linebuffer is full a parsed complete line MUST BE put in linebuffer BEFORE next line parsing. */ template -inline static ParserResult CSVReadLine(CSVParser* self, LineBuffer& buf) +inline static ParserResult CSVReadLine(CSVParser *self, LineBuffer &buf) { bool need_data = false; - char* raw_buffer = self->rec_buf; + char *raw_buffer = self->rec_buf; char quotec = self->quote; char escapec = self->escape; - Source* source = self->source; + Source *source = self->source; /* * All the following flags MUST BE synchronized to appropriate state before * each parsed and completed line is to be added to LineBuffer. */ - bool* in_quote = &(self->in_quote); - bool* last_was_esc = &(self->lastWasEsc); - bool* in_cr = &(self->in_cr); + bool *in_quote = &(self->in_quote); + bool *last_was_esc = &(self->lastWasEsc); + bool *in_cr = &(self->in_cr); char c; int begin_index = self->cur; @@ -695,19 +957,35 @@ inline static ParserResult CSVReadLine(CSVParser* self, LineBuffer& buf) self->cur_need_flush = raw_buf_ptr; return RESULT_SUCCESS; } - +/* + * 鍔熻兘锛氭枃鏈鍙栬 + * + * 鍙傛暟鍒楄〃锛 + * self锛歊eadableParser 鎸囬拡锛岃〃绀哄彲璇昏В鏋愬櫒瀵硅薄 + * buf锛歀ineBuffer 寮曠敤锛岃〃绀虹敤浜庡瓨鍌ㄨ鍙栫殑琛屾暟鎹殑缂撳啿鍖 + * + * 杩斿洖鍊硷細 + * 杩斿洖 ParserResult 鏋氫妇鍊硷紝琛ㄧず璇诲彇琛岀殑缁撴灉锛屽彲鑳戒负 RESULT_EOF銆丷ESULT_BUFFER_FULL 鎴 RESULT_SUCCESS銆 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庢枃鏈鍙栬鎿嶄綔銆傛牴鎹弬鏁 skipData 鐨勫硷紝鍙互閫夋嫨鏄惁璺宠繃鏁版嵁銆 + * 鍑芥暟浼氬惊鐜鍙栨暟鎹苟鏌ユ壘琛屽熬瀛楃锛岀洿鍒版壘鍒拌灏惧瓧绗︽垨閬囧埌鏂囦欢缁撳熬銆 + * 濡傛灉鎵惧埌琛屽熬瀛楃锛屽垯灏嗚鏁版嵁瀛樺偍鍒扮紦鍐插尯 buf 涓紝骞惰繑鍥 RESULT_SUCCESS銆 + * 濡傛灉缂撳啿鍖轰笉瓒充互瀛樺偍鏁磋鏁版嵁锛屽垯杩斿洖 RESULT_BUFFER_FULL銆 + * 濡傛灉閬囧埌鏂囦欢缁撳熬锛屽垯杩斿洖 RESULT_EOF銆 + */ template -inline static ParserResult TextReadLine(ReadableParser* self, LineBuffer& buf) +inline static ParserResult TextReadLine(ReadableParser *self, LineBuffer &buf) { bool need_data = false; - char* eol = NULL; + char *eol = NULL; int remainLen; - char* raw_buffer = self->rec_buf; - Source* source = self->source; + char *raw_buffer = self->rec_buf; + Source *source = self->source; int eol_len = (self->eol == NULL) ? 1 : strlen(self->eol); while (true) { - char* end = NULL; + char *end = NULL; // if buffer is empty, read new data from files // @@ -785,13 +1063,28 @@ inline static ParserResult TextReadLine(ReadableParser* self, LineBuffer& buf) self->eol_cur_saved = 0; return RESULT_SUCCESS; } - -inline static ParserResult FixReadLine(FixParser* self, LineBuffer& buf) +/* + * 鍔熻兘锛氫慨澶嶈鍙栬 + * + * 鍙傛暟鍒楄〃锛 + * self锛欶ixParser 鎸囬拡锛岃〃绀轰慨澶嶈В鏋愬櫒瀵硅薄 + * buf锛歀ineBuffer 寮曠敤锛岃〃绀虹敤浜庡瓨鍌ㄨ鍙栫殑琛屾暟鎹殑缂撳啿鍖 + * + * 杩斿洖鍊硷細 + * 杩斿洖 ParserResult 鏋氫妇鍊硷紝琛ㄧず璇诲彇琛岀殑缁撴灉锛屽彲鑳戒负 RESULT_EOF銆丷ESULT_BUFFER_FULL 鎴 RESULT_SUCCESS銆 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庝慨澶嶈鍙栬鎿嶄綔銆傚嚱鏁颁細寰幆璇诲彇鏁版嵁锛屽苟灏嗘暟鎹瓨鍌ㄥ埌缂撳啿鍖 buf 涓 + * 濡傛灉缂撳啿鍖轰笉瓒充互瀛樺偍鏁磋鏁版嵁锛屽垯杩斿洖 RESULT_BUFFER_FULL銆 + * 濡傛灉閬囧埌鏂囦欢缁撳熬锛屽垯杩斿洖 RESULT_EOF銆 + * 濡傛灉鎴愬姛璇诲彇琛岋紝鍒欒繑鍥 RESULT_SUCCESS銆 + */ +inline static ParserResult FixReadLine(FixParser *self, LineBuffer &buf) { int remainLen; - char* raw_buffer = NULL; + char *raw_buffer = NULL; int needRead = self->rowSize; - Source* source = self->source; + Source *source = self->source; /* * skip the size of the un-completed row chunk which is already put in LineBuffer; @@ -856,17 +1149,32 @@ inline static ParserResult FixReadLine(FixParser* self, LineBuffer& buf) return RESULT_SUCCESS; } - +/* + * 鍔熻兘锛氶氱敤璇诲彇琛 + * + * 鍙傛暟鍒楄〃锛 + * self锛歅arser 鎸囬拡锛岃〃绀鸿В鏋愬櫒瀵硅薄 + * + * 杩斿洖鍊硷細 + * 杩斿洖 ParserResult 鏋氫妇鍊硷紝琛ㄧず璇诲彇琛岀殑缁撴灉锛屽彲鑳戒负 RESULT_EOF銆丷ESULT_BUFFER_FULL 鎴 RESULT_SUCCESS銆 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庨氱敤璇诲彇琛屾搷浣滐紝鏀寔涓嶅悓鐨勬枃浠舵牸寮忥紙format锛夈傛牴鎹 format 鍙傛暟鐨勫硷紝閫夋嫨鐩稿簲鐨勮璇诲彇鍑芥暟銆 + * 鍑芥暟浼氬惊鐜鍙栨暟鎹紝鐩村埌琛岀紦鍐插尯 line_buffers 琚~婊℃垨杈惧埌鏂囦欢缁撳熬銆 + * 濡傛灉鎴愬姛璇诲彇琛岋紝鍒欒繑鍥 RESULT_SUCCESS銆 + * 濡傛灉杈惧埌鏂囦欢缁撳熬涓旇繕鏈夋洿澶氭枃浠跺彲璇诲彇锛屽垯杩斿洖 RESULT_NEW_ONE銆 + * 濡傛灉琛岀紦鍐插尯涓嶈冻浠ュ瓨鍌ㄦ暣琛屾暟鎹紝鍒欒繑鍥 RESULT_BUFFER_FULL銆 + */ template ParserResult #ifdef GDS_SERVER - GenericReadLines(Parser* self, struct evbuffer& buf) + GenericReadLines(Parser *self, struct evbuffer &buf) #else - GenericReadLines(Parser* self) + GenericReadLines(Parser *self) #endif { - Source* source = self->source; - ReadableParser* parser = (ReadableParser*)self; + Source *source = self->source; + ReadableParser *parser = (ReadableParser *)self; if (parser->eof) return RESULT_EOF; @@ -876,11 +1184,11 @@ ParserResult ParserResult result = RESULT_SUCCESS; if (format == FORMAT_TEXT) - result = TextReadLine((ReadableParser*)self, self->line_buffers); + result = TextReadLine((ReadableParser *)self, self->line_buffers); else if (format == FORMAT_FIXED) - result = FixReadLine((FixParser*)self, self->line_buffers); + result = FixReadLine((FixParser *)self, self->line_buffers); else if (format == FORMAT_CSV) - result = CSVReadLine((CSVParser*)self, self->line_buffers); + result = CSVReadLine((CSVParser *)self, self->line_buffers); if (RESULT_EOF == result) { if (source->SourceNext(source)) { @@ -891,9 +1199,9 @@ ParserResult // if (self->hasHeader) { if (format == FORMAT_TEXT || format == FORMAT_FIXED) - (void)TextReadLine((ReadableParser*)self, self->line_buffers); + (void)TextReadLine((ReadableParser *)self, self->line_buffers); else - (void)CSVReadLine((CSVParser*)self, self->line_buffers); + (void)CSVReadLine((CSVParser *)self, self->line_buffers); } return RESULT_NEW_ONE; } else { @@ -905,18 +1213,35 @@ ParserResult } } } +/* + * 鍔熻兘锛氶氱敤鍐欏叆琛 + * + * 鍙傛暟鍒楄〃锛 + * self锛歅arser 鎸囬拡锛岃〃绀鸿В鏋愬櫒瀵硅薄 + * buf锛歟vbuffer 寮曠敤锛岃〃绀哄緟鍐欏叆鐨勬暟鎹紦鍐插尯 + * len锛氭暣鏁帮紝琛ㄧず寰呭啓鍏ユ暟鎹殑闀垮害 + * + * 杩斿洖鍊硷細 + * 杩斿洖 ParserResult 鏋氫妇鍊硷紝琛ㄧず鍐欏叆琛岀殑缁撴灉锛岄氬父涓 RESULT_SUCCESS銆 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庨氱敤鍐欏叆琛屾搷浣滐紝鏀寔涓嶅悓鐨勫啓鍏ユ柟寮忋 + * 鍦 GDS_SERVER 妯″紡涓嬶紝鍑芥暟浼氭牴鎹暟鎹澶у皬 `segSize` 鏉ュ垽鏂槸鍚﹂渶瑕佺敓鎴愭柊鐨勫鍑烘枃浠讹紝 + * 骞跺皢鏁版嵁鍐欏叆婧愭枃浠躲傚鏋滄湁澶撮儴鏁版嵁 `fileheader`锛屼細鍦ㄦ瘡涓柊鏂囦欢涓啓鍏ュご閮ㄦ暟鎹 + * 鍦ㄩ潪 GDS_SERVER 妯″紡涓嬶紝浼氳褰曢敊璇俊鎭紝琛ㄧず璇ヨ矾寰勭殑浠g爜鏈疄鐜般 + */ template -ParserResult GenericWriteLines(Parser* self, struct evbuffer& buf, int len) +ParserResult GenericWriteLines(Parser *self, struct evbuffer &buf, int len) { #ifdef GDS_SERVER - Source* source = self->source; + Source *source = self->source; size_t segSize = GetDataSegmentSize(); if (segSize > 0 && source->GetWriteOffset() > segSize) { - source->GenerateNewFileForExport(((WritableParser*)self)->prefix, "dat"); + source->GenerateNewFileForExport(((WritableParser *)self)->prefix, "dat"); if (hasHeader) - source->SourceWrite(((WritableParser*)self)->fileheader, ((WritableParser*)self)->headerSize); + source->SourceWrite(((WritableParser *)self)->fileheader, ((WritableParser *)self)->headerSize); } source->SourceWrite(&buf, len); @@ -925,44 +1250,72 @@ ParserResult GenericWriteLines(Parser* self, struct evbuffer& buf, int len) #endif return RESULT_SUCCESS; } - -static void ReadableParserInit(ReadableParser* self, CmdBegin* cmd, FileList* files, SourceType sourcetype) +/* + * 鍔熻兘锛氬垵濮嬪寲鍙瑙f瀽鍣 + * + * 鍙傛暟鍒楄〃锛 + * self锛歊eadableParser 鎸囬拡锛岃〃绀哄彲璇昏В鏋愬櫒瀵硅薄 + * cmd锛欳mdBegin 鎸囬拡锛岃〃绀哄懡浠ゅ紑濮嬩俊鎭 + * files锛欶ileList 鎸囬拡锛岃〃绀烘枃浠跺垪琛ㄤ俊鎭 + * sourcetype锛歋ourceType 鏋氫妇鍊硷紝琛ㄧず婧愮被鍨 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庡垵濮嬪寲鍙瑙f瀽鍣ㄥ璞°傛牴鎹弬鏁拌繘琛屽垵濮嬪寲鎿嶄綔锛屽寘鎷垎閰嶅唴瀛樸佽缃睘鎬х瓑銆 + */ +static void ReadableParserInit(ReadableParser *self, CmdBegin *cmd, FileList *files, SourceType sourcetype) { + // 鍒濆鍖栨枃浠剁粨鏉熸爣蹇椾负 false锛岃〃绀烘枃浠舵湭缁撴潫 self->eof = false; + + // 濡傛灉缂撳啿鍖洪暱搴︿负 0锛屽垯璁剧疆涓 INITIAL_BUF_LEN if (self->buf_len == 0) self->buf_len = INITIAL_BUF_LEN; - self->rec_buf = (char*)malloc(self->buf_len); + // 鍒嗛厤 rec_buf 缂撳啿鍖哄唴瀛橈紝鐢ㄤ簬瀛樺偍璇诲彇鐨勬暟鎹紝澶у皬涓 buf_len 瀛楄妭 + self->rec_buf = (char *)malloc(self->buf_len); if (self->rec_buf == NULL) { parser_log(LEVEL_ERROR, "memory alloc failed!\n"); } + + // 鍒濆鍖栧凡浣跨敤鏁版嵁闀垮害 used_len銆佸綋鍓嶄綅缃 cur銆丒OL 瀛楃褰撳墠浣嶇疆 eol_cur 鍜 EOL 瀛楃浣嶇疆淇濆瓨 eol_cur_saved self->used_len = 0; self->cur = 0; self->eol_cur = 0; self->eol_cur_saved = 0; + // 鏍规嵁鍛戒护涓殑 m_header 灞炴э紝璁剧疆鏄惁鏈夊ご閮ㄦ暟鎹殑鏍囧織 hasHeader self->hasHeader = cmd->m_header; #ifdef GDS_SERVER + // 濡傛灉鏄湇鍔″櫒妯″紡锛屽垱寤轰竴涓 libevent 鐨 evbuffer 鐢ㄤ簬瀛樺偍琛屾暟鎹 self->line_buffer = evbuffer_new(); if (self->line_buffer == NULL) parser_log(LEVEL_ERROR, "failed to init parser, out of memory"); #endif + + // 鍒涘缓鏁版嵁婧 source锛屾牴鎹 sourcetype 鍜 files 鍙傛暟杩涜鍒濆鍖 self->source = CreateSource(files, sourcetype); + + // 濡傛灉 sourcetype 涓嶆槸 SOURCE_TYPE_OBS 骞朵笖鍛戒护涓殑 m_prefix 涓嶄负 NULL锛屽垯澶嶅埗 m_prefix 鍒 prefix 灞炴 if (sourcetype != SOURCE_TYPE_OBS && (cmd->m_prefix != NULL)) { self->prefix = strdup(cmd->m_prefix); if (self->prefix == NULL) parser_log(LEVEL_ERROR, "failed to copy prefix, out of memory"); } + // 鍐嶆妫鏌 rec_buf 鏄惁涓 NULL锛屽鏋滄槸鍒欒褰曞唴瀛樺垎閰嶉敊璇 if (self->rec_buf == NULL) parser_log(LEVEL_ERROR, "failed to init parser, out of memory"); + + // 鍒濆鍖 rec_buf 鐨勭涓涓瓧绗︿负 '\0' self->rec_buf[0] = '\0'; + // 鍒濆鍖 line_buffers 鍜岀浉鍏冲睘鎬э紝鐢ㄤ簬绠$悊琛屾暟鎹 self->line_buffers.Init(); self->cur_need_flush = 0; self->is_cur_line_completed = false; + // 濡傛灉鍛戒护涓殑 m_eol 涓嶄负 NULL锛屽垯澶嶅埗 m_eol 鍒 eol 灞炴 if (cmd->m_eol != NULL) { self->eol = strdup(cmd->m_eol); if (self->eol == NULL) @@ -970,48 +1323,121 @@ static void ReadableParserInit(ReadableParser* self, CmdBegin* cmd, FileList* fi } } -static void CSVParserInit(CSVParser* self, CmdBegin* cmd, FileList* files, SourceType sourcetype) +/* + * 鍔熻兘锛氬垵濮嬪寲 CSV 瑙f瀽鍣 + * + * 鍙傛暟鍒楄〃锛 + * self锛欳SVParser 鎸囬拡锛岃〃绀 CSV 瑙f瀽鍣ㄥ璞 + * cmd锛欳mdBegin 鎸囬拡锛岃〃绀哄懡浠ゅ紑濮嬩俊鎭 + * files锛欶ileList 鎸囬拡锛岃〃绀烘枃浠跺垪琛ㄤ俊鎭 + * sourcetype锛歋ourceType 鏋氫妇鍊硷紝琛ㄧず婧愮被鍨 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庡垵濮嬪寲 CSV 瑙f瀽鍣ㄥ璞°傞鍏堣皟鐢 ReadableParserInit 杩涜閫氱敤灞炴у垵濮嬪寲锛岀劧鍚庢牴鎹懡浠や腑鐨 + * m_quote 鍜 m_escape 灞炴э紝璁剧疆 CSV 瑙f瀽鍣ㄧ殑寮曠敤瀛楃鍜岃浆涔夊瓧绗︺傚鏋滆繖浜涘睘鎬т负 NULL 鎴栫浉绛夛紝浼氳繘琛岄粯璁よ缃 + */ + +static void CSVParserInit(CSVParser *self, CmdBegin *cmd, FileList *files, SourceType sourcetype) { + // 璋冪敤閫氱敤鍙瑙f瀽鍣ㄧ殑鍒濆鍖栧嚱鏁拌繘琛岄氱敤灞炴х殑鍒濆鍖 ReadableParserInit(self, cmd, files, sourcetype); + + // 璁剧疆 CSV 瑙f瀽鍣ㄧ殑寮曠敤瀛楃鍜岃浆涔夊瓧绗 self->quote = cmd->m_quote; self->escape = cmd->m_escape; + + // 濡傛灉寮曠敤瀛楃涓虹┖锛屽垯榛樿涓哄弻寮曞彿 self->quote = self->quote ? self->quote : '"'; + + // 濡傛灉杞箟瀛楃涓虹┖锛屽垯榛樿涓哄弻寮曞彿 self->escape = self->escape ? self->escape : '"'; + + // 濡傛灉杞箟瀛楃涓庡紩鐢ㄥ瓧绗︾浉绛夛紝鍒欏皢杞箟瀛楃璁剧疆涓虹┖瀛楃 self->escape = self->escape == self->quote ? '\0' : self->escape; } -static void FixParserInit(FixParser* self, CmdBegin* cmd, FileList* files, SourceType sourcetype) +/* + * 鍔熻兘锛氬垵濮嬪寲鍥哄畾鏍煎紡瑙f瀽鍣 + * + * 鍙傛暟鍒楄〃锛 + * self锛欶ixParser 鎸囬拡锛岃〃绀哄浐瀹氭牸寮忚В鏋愬櫒瀵硅薄 + * cmd锛欳mdBegin 鎸囬拡锛岃〃绀哄懡浠ゅ紑濮嬩俊鎭 + * files锛欶ileList 鎸囬拡锛岃〃绀烘枃浠跺垪琛ㄤ俊鎭 + * sourcetype锛歋ourceType 鏋氫妇鍊硷紝琛ㄧず婧愮被鍨 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庡垵濮嬪寲鍥哄畾鏍煎紡瑙f瀽鍣ㄥ璞°傞鍏堣皟鐢 ReadableParserInit 杩涜閫氱敤灞炴у垵濮嬪寲锛岀劧鍚庢牴鎹懡浠や腑鐨 + * m_fixSize 灞炴э紝璁剧疆鍥哄畾鏍煎紡瑙f瀽鍣ㄧ殑琛屽ぇ灏忋傚鏋滆澶у皬涓 0锛屽垯灏嗚鍙栬澶勭悊鍑芥暟璁剧疆涓 + * GenericReadLines銆 + */ + +static void FixParserInit(FixParser *self, CmdBegin *cmd, FileList *files, SourceType sourcetype) { + // 璋冪敤閫氱敤鍙瑙f瀽鍣ㄧ殑鍒濆鍖栧嚱鏁拌繘琛岄氱敤灞炴х殑鍒濆鍖 ReadableParserInit(self, cmd, files, sourcetype); + + // 璁剧疆鍥哄畾鏍煎紡瑙f瀽鍣ㄧ殑琛屽ぇ灏 self->rowSize = cmd->m_fixSize; + + // 濡傛灉琛屽ぇ灏忎负 0锛屽垯灏嗚鍙栬澶勭悊鍑芥暟璁剧疆涓 GenericReadLines if (self->rowSize == 0) self->readlines = (ParserReadLineProc)GenericReadLines; } -static void WritableParserInit(WritableParser* self, CmdBegin* cmd, FileList* files) +/* + * 鍔熻兘锛氬垵濮嬪寲鍙啓瑙f瀽鍣 + * + * 鍙傛暟鍒楄〃锛 + * self锛歐ritableParser 鎸囬拡锛岃〃绀哄彲鍐欒В鏋愬櫒瀵硅薄 + * cmd锛欳mdBegin 鎸囬拡锛岃〃绀哄懡浠ゅ紑濮嬩俊鎭 + * files锛欶ileList 鎸囬拡锛岃〃绀烘枃浠跺垪琛ㄤ俊鎭 + * 鏃 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庡垵濮嬪寲鍙啓瑙f瀽鍣ㄥ璞°傞鍏堟牴鎹畯瀹氫箟鍒ゆ柇鏄惁鏀寔 GDS_SERVER锛岀劧鍚庤繘琛岀浉搴旂殑鍒濆鍖栨搷浣溿 + * 濡傛灉鏀寔 GDS_SERVER锛屽垯杩涜浠ヤ笅鎿嶄綔锛 + * 1. 璁剧疆 hasHeader 涓 false銆 + * 2. 鍒涘缓琛岀紦鍐插尯 line_buffer 鍜屾簮瀵硅薄 source銆 + * 3. 璁剧疆婧愬璞$殑璺緞涓哄懡浠や腑鐨 URL 缁忚繃 UriToLocalPath 澶勭悊鍚庣殑缁撴灉銆 + * 4. 澶嶅埗鍛戒护涓殑鍓嶇紑鍒 prefix 灞炴с + * 5. 濡傛灉鍛戒护涓瓨鍦ㄦ枃浠跺ご鏂囦欢锛屽垯鑾峰彇鏂囦欢澶翠俊鎭紝鐢熸垚鏂扮殑杈撳嚭鏂囦欢锛屽苟灏嗘枃浠跺ご鍐欏叆杈撳嚭鏂囦欢銆 + * 6. 濡傛灉鍛戒护涓瓨鍦ㄦ崲琛岀灞炴э紝鍒欏鍒跺埌 eol 灞炴с + */ + +static void WritableParserInit(WritableParser *self, CmdBegin *cmd, FileList *files) { #ifdef GDS_SERVER + // 璁剧疆 hasHeader 涓 false self->hasHeader = false; + + // 鍒涘缓琛岀紦鍐插尯 line_buffer 鍜屾簮瀵硅薄 source self->line_buffer = evbuffer_new(); self->source = CreateSource(NULL, SOURCE_TYPE_FILE); + // 妫鏌ユ槸鍚︽垚鍔熷垱寤鸿缂撳啿鍖哄拰婧愬璞 if ((self->line_buffer == NULL) || (self->source == NULL)) parser_log(LEVEL_ERROR, "failed to init parser, out of memory"); + // 璁剧疆婧愬璞$殑璺緞涓哄懡浠や腑鐨 URL 缁忚繃 UriToLocalPath 澶勭悊鍚庣殑缁撴灉 self->source->SetPath(UriToLocalPath(cmd->m_url)); + + // 澶嶅埗鍛戒护涓殑鍓嶇紑鍒 prefix 灞炴 if (cmd->m_prefix == NULL) { parser_log(LEVEL_ERROR, "the given prefix is NULL"); } self->prefix = strdup(cmd->m_prefix); if (self->prefix == NULL) parser_log(LEVEL_ERROR, "failed to copy prefix, out of memory"); - if (cmd->m_fileheader != NULL) - GetFileHeader(self, UriToLocalPath(cmd->m_fileheader).c_str()); - self->source->GenerateNewFileForExport(self->prefix, "dat"); + + // 濡傛灉鍛戒护涓瓨鍦ㄦ枃浠跺ご鏂囦欢锛屽垯鑾峰彇鏂囦欢澶翠俊鎭紝鐢熸垚鏂扮殑杈撳嚭鏂囦欢锛屽苟灏嗘枃浠跺ご鍐欏叆杈撳嚭鏂囦欢 if (cmd->m_fileheader != NULL) { + GetFileHeader(self, UriToLocalPath(cmd->m_fileheader).c_str()); + self->source->GenerateNewFileForExport(self->prefix, "dat"); self->source->SourceWrite(self->fileheader, self->headerSize); self->writelines = (ParserWriteLineProc)GenericWriteLines; } + + // 濡傛灉鍛戒护涓瓨鍦ㄦ崲琛岀灞炴э紝鍒欏鍒跺埌 eol 灞炴 if (cmd->m_eol != NULL) { self->eol = strdup(cmd->m_eol); if (self->eol == NULL) @@ -1022,85 +1448,212 @@ static void WritableParserInit(WritableParser* self, CmdBegin* cmd, FileList* fi #endif } -Parser* CreateCSVParser() +/* + * 鍔熻兘锛氬垱寤 CSV 瑙f瀽鍣ㄥ璞 + * + * 杩斿洖鍊硷細 + * 杩斿洖鍒涘缓鐨 CSV 瑙f瀽鍣ㄥ璞℃寚閽 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庡垱寤 CSV + * 瑙f瀽鍣ㄥ璞°傞鍏堝垎閰嶅唴瀛樼┖闂存潵瀛樺偍瑙f瀽鍣ㄥ璞★紝鐒跺悗杩涜鐩稿簲鐨勫垵濮嬪寲鎿嶄綔锛屽寘鎷缃嚱鏁版寚閽堝拰灞炴у笺 + * 鏈鍚庯紝杩斿洖鍒涘缓鐨勮В鏋愬櫒瀵硅薄鎸囬拡銆 + */ + +Parser *CreateCSVParser() { errno_t rc; - CSVParser* self = (CSVParser*)malloc(sizeof(CSVParser)); + // 鍒嗛厤鍐呭瓨绌洪棿鏉ュ瓨鍌 CSV 瑙f瀽鍣ㄥ璞 + CSVParser *self = (CSVParser *)malloc(sizeof(CSVParser)); + // 妫鏌ュ唴瀛樺垎閰嶆槸鍚︽垚鍔 if (NULL == self) parser_log(LEVEL_ERROR, "failed to create parser, out of memory"); + // 浣跨敤 memset_s 鍑芥暟灏嗚В鏋愬櫒瀵硅薄鐨勫唴瀛樻竻闆 rc = memset_s(self, sizeof(CSVParser), 0, sizeof(CSVParser)); parser_securec_check(rc); + + // 璁剧疆瑙f瀽鍣ㄥ璞$殑鍒濆鍖栧嚱鏁版寚閽堜负 CSVParserInit self->init = (ParserInitProc)CSVParserInit; + + // 璁剧疆瑙f瀽鍣ㄥ璞$殑璇诲彇琛屽嚱鏁版寚閽堜负 GenericReadLines self->readlines = (ParserReadLineProc)GenericReadLines; + + // 璁剧疆瑙f瀽鍣ㄥ璞$殑鍐欏叆琛屽嚱鏁版寚閽堜负 NopWriteLine self->writelines = (ParserWriteLineProc)NopWriteLine; + + // 璁剧疆瑙f瀽鍣ㄥ璞$殑閿姣佸嚱鏁版寚閽堜负 DestroyReadableParser self->destroy = (ParserDestroyProc)DestroyReadableParser; + + // 璁剧疆瑙f瀽鍣ㄥ璞$殑娓呯悊鍑芥暟鎸囬拡涓 NopCleanup self->cleanup = (ParserDestroyProc)NopCleanup; + + // 鍒濆鍖栬В鏋愬櫒瀵硅薄鐨勫睘鎬у self->in_quote = false; self->lastWasEsc = false; self->in_cr = false; - return (Parser*)self; + + // 杩斿洖鍒涘缓鐨 CSV 瑙f瀽鍣ㄥ璞℃寚閽 + return (Parser *)self; } -Parser* CreateTextParser() +/* + * 鍔熻兘锛氬垱寤烘枃鏈В鏋愬櫒瀵硅薄 + * + * 鍙傛暟鍒楄〃锛氭棤 + * + * 杩斿洖鍊硷細 + * 杩斿洖鍒涘缓鐨勬枃鏈В鏋愬櫒瀵硅薄鎸囬拡 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庡垱寤烘枃鏈В鏋愬櫒瀵硅薄銆傞鍏堝垎閰嶅唴瀛樼┖闂存潵瀛樺偍瑙f瀽鍣ㄥ璞★紝鐒跺悗杩涜鐩稿簲鐨勫垵濮嬪寲鎿嶄綔锛屽寘鎷缃嚱鏁版寚閽堝拰灞炴у笺 + * 鏈鍚庯紝杩斿洖鍒涘缓鐨勮В鏋愬櫒瀵硅薄鎸囬拡銆 + */ + +Parser *CreateTextParser() { errno_t rc; - ReadableParser* self = (ReadableParser*)malloc(sizeof(ReadableParser)); + // 鍒嗛厤鍐呭瓨绌洪棿鏉ュ瓨鍌ㄦ枃鏈В鏋愬櫒瀵硅薄 + ReadableParser *self = (ReadableParser *)malloc(sizeof(ReadableParser)); + // 妫鏌ュ唴瀛樺垎閰嶆槸鍚︽垚鍔 if (NULL == self) parser_log(LEVEL_ERROR, "failed to create parser, out of memory"); + // 浣跨敤 memset_s 鍑芥暟灏嗚В鏋愬櫒瀵硅薄鐨勫唴瀛樻竻闆 rc = memset_s(self, sizeof(ReadableParser), 0, sizeof(ReadableParser)); parser_securec_check(rc); + + // 璁剧疆瑙f瀽鍣ㄥ璞$殑鍒濆鍖栧嚱鏁版寚閽堜负 ReadableParserInit self->init = (ParserInitProc)ReadableParserInit; + + // 璁剧疆瑙f瀽鍣ㄥ璞$殑璇诲彇琛屽嚱鏁版寚閽堜负 GenericReadLines self->readlines = (ParserReadLineProc)GenericReadLines; + + // 璁剧疆瑙f瀽鍣ㄥ璞$殑鍐欏叆琛屽嚱鏁版寚閽堜负 NopWriteLine self->writelines = (ParserWriteLineProc)NopWriteLine; + + // 璁剧疆瑙f瀽鍣ㄥ璞$殑閿姣佸嚱鏁版寚閽堜负 DestroyReadableParser self->destroy = (ParserDestroyProc)DestroyReadableParser; + + // 璁剧疆瑙f瀽鍣ㄥ璞$殑娓呯悊鍑芥暟鎸囬拡涓 NopCleanup self->cleanup = (ParserDestroyProc)NopCleanup; - return (Parser*)self; + + // 杩斿洖鍒涘缓鐨勬枃鏈В鏋愬櫒瀵硅薄鎸囬拡 + return (Parser *)self; } -Parser* CreateFixedParser() +/* + * 鍔熻兘锛氬垱寤哄浐瀹氭牸寮忚В鏋愬櫒瀵硅薄 + * + * 鍙傛暟鍒楄〃锛氭棤 + * + * 杩斿洖鍊硷細 + * 杩斿洖鍒涘缓鐨勫浐瀹氭牸寮忚В鏋愬櫒瀵硅薄鎸囬拡 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庡垱寤哄浐瀹氭牸寮忚В鏋愬櫒瀵硅薄銆傞鍏堝垎閰嶅唴瀛樼┖闂存潵瀛樺偍瑙f瀽鍣ㄥ璞★紝鐒跺悗杩涜鐩稿簲鐨勫垵濮嬪寲鎿嶄綔锛屽寘鎷缃嚱鏁版寚閽堝拰灞炴у笺 + * 鏈鍚庯紝杩斿洖鍒涘缓鐨勮В鏋愬櫒瀵硅薄鎸囬拡銆 + */ + +Parser *CreateFixedParser() { errno_t rc; - FixParser* self = (FixParser*)malloc(sizeof(FixParser)); + // 鍒嗛厤鍐呭瓨绌洪棿鏉ュ瓨鍌ㄥ浐瀹氭牸寮忚В鏋愬櫒瀵硅薄 + FixParser *self = (FixParser *)malloc(sizeof(FixParser)); + // 妫鏌ュ唴瀛樺垎閰嶆槸鍚︽垚鍔 if (NULL == self) parser_log(LEVEL_ERROR, "failed to create parser, out of memory"); + // 浣跨敤 memset_s 鍑芥暟灏嗚В鏋愬櫒瀵硅薄鐨勫唴瀛樻竻闆 rc = memset_s(self, sizeof(FixParser), 0, sizeof(FixParser)); parser_securec_check(rc); + + // 璁剧疆瑙f瀽鍣ㄥ璞$殑鍒濆鍖栧嚱鏁版寚閽堜负 FixParserInit self->init = (ParserInitProc)FixParserInit; + + // 璁剧疆瑙f瀽鍣ㄥ璞$殑璇诲彇琛屽嚱鏁版寚閽堜负 GenericReadLines self->readlines = (ParserReadLineProc)GenericReadLines; + + // 璁剧疆瑙f瀽鍣ㄥ璞$殑鍐欏叆琛屽嚱鏁版寚閽堜负 NopWriteLine self->writelines = (ParserWriteLineProc)NopWriteLine; + + // 璁剧疆瑙f瀽鍣ㄥ璞$殑閿姣佸嚱鏁版寚閽堜负 DestroyReadableParser self->destroy = (ParserDestroyProc)DestroyReadableParser; + + // 璁剧疆瑙f瀽鍣ㄥ璞$殑娓呯悊鍑芥暟鎸囬拡涓 NopCleanup self->cleanup = (ParserDestroyProc)NopCleanup; - return (Parser*)self; + + // 杩斿洖鍒涘缓鐨勫浐瀹氭牸寮忚В鏋愬櫒瀵硅薄鎸囬拡 + return (Parser *)self; } -Parser* CreateWritableParser() +/* + * 鍔熻兘锛氬垱寤哄彲鍐欒В鏋愬櫒瀵硅薄 + * + * 鍙傛暟鍒楄〃锛氭棤 + * + * 杩斿洖鍊硷細 + * 杩斿洖鍒涘缓鐨勫彲鍐欒В鏋愬櫒瀵硅薄鎸囬拡 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庡垱寤哄彲鍐欒В鏋愬櫒瀵硅薄銆傞鍏堝垎閰嶅唴瀛樼┖闂存潵瀛樺偍瑙f瀽鍣ㄥ璞★紝鐒跺悗杩涜鐩稿簲鐨勫垵濮嬪寲鎿嶄綔锛屽寘鎷缃嚱鏁版寚閽堝拰灞炴у笺 + * 鏈鍚庯紝杩斿洖鍒涘缓鐨勮В鏋愬櫒瀵硅薄鎸囬拡銆 + */ + +Parser *CreateWritableParser() { errno_t rc; - WritableParser* self = (WritableParser*)malloc(sizeof(WritableParser)); + // 鍒嗛厤鍐呭瓨绌洪棿鏉ュ瓨鍌ㄥ彲鍐欒В鏋愬櫒瀵硅薄 + WritableParser *self = (WritableParser *)malloc(sizeof(WritableParser)); + // 妫鏌ュ唴瀛樺垎閰嶆槸鍚︽垚鍔 if (NULL == self) parser_log(LEVEL_ERROR, "failed to create parser, out of memory"); + // 浣跨敤 memset_s 鍑芥暟灏嗚В鏋愬櫒瀵硅薄鐨勫唴瀛樻竻闆 rc = memset_s(self, sizeof(WritableParser), 0, sizeof(WritableParser)); parser_securec_check(rc); + + // 璁剧疆瑙f瀽鍣ㄥ璞$殑鍒濆鍖栧嚱鏁版寚閽堜负 WritableParserInit self->init = (ParserInitProc)WritableParserInit; + + // 璁剧疆瑙f瀽鍣ㄥ璞$殑璇诲彇琛屽嚱鏁版寚閽堜负 NopReadLine self->readlines = (ParserReadLineProc)NopReadLine; + + // 璁剧疆瑙f瀽鍣ㄥ璞$殑鍐欏叆琛屽嚱鏁版寚閽堜负 GenericWriteLines self->writelines = (ParserWriteLineProc)GenericWriteLines; + + // 璁剧疆瑙f瀽鍣ㄥ璞$殑閿姣佸嚱鏁版寚閽堜负 DestroyWritableParser self->destroy = (ParserDestroyProc)DestroyWritableParser; + + // 璁剧疆瑙f瀽鍣ㄥ璞$殑娓呯悊鍑芥暟鎸囬拡涓 CleanupWritablParser self->cleanup = (ParserDestroyProc)CleanupWritablParser; - return (Parser*)self; + + // 杩斿洖鍒涘缓鐨勫彲鍐欒В鏋愬櫒瀵硅薄鎸囬拡 + return (Parser *)self; } -Parser* CreateParser(FileFormat format) -{ - Parser* parser = NULL; +/* + * 鍔熻兘锛氬垱寤鸿В鏋愬櫒瀵硅薄 + * + * 鍙傛暟鍒楄〃锛 + * format锛氭枃浠舵牸寮忥紙FORMAT_TEXT銆丗ORMAT_CSV銆丗ORMAT_FIXED銆丗ORMAT_REMOTEWRITE锛 + * + * 杩斿洖鍊硷細 + * 杩斿洖鍒涘缓鐨勮В鏋愬櫒瀵硅薄鎸囬拡 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庢牴鎹枃浠舵牸寮忓垱寤虹浉搴旂殑瑙f瀽鍣ㄥ璞°傛牴鎹紶鍏ョ殑鏂囦欢鏍煎紡锛岄夋嫨瀵瑰簲鐨勫垱寤哄嚱鏁版潵鍒涘缓瑙f瀽鍣ㄥ璞★紝鐒跺悗杩斿洖鍒涘缓鐨勮В鏋愬櫒瀵硅薄鎸囬拡銆 + */ +Parser *CreateParser(FileFormat format) +{ + Parser *parser = NULL; + + // 鏍规嵁鏂囦欢鏍煎紡閫夋嫨瀵瑰簲鐨勫垱寤哄嚱鏁版潵鍒涘缓瑙f瀽鍣ㄥ璞 switch (format) { case FORMAT_TEXT: parser = CreateTextParser(); @@ -1117,86 +1670,169 @@ Parser* CreateParser(FileFormat format) default: parser_log(LEVEL_ERROR, "un-support format."); } + + // 杩斿洖鍒涘缓鐨勮В鏋愬櫒瀵硅薄鎸囬拡 return parser; } -static void DestroyParser(Parser* self) +/* + * 鍔熻兘锛氶攢姣佽В鏋愬櫒瀵硅薄 + * + * 鍙傛暟鍒楄〃锛 + * self锛氳閿姣佺殑瑙f瀽鍣ㄥ璞℃寚閽 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庨攢姣佽В鏋愬櫒瀵硅薄浠ュ強鐩稿叧璧勬簮銆傞鍏堥噴鏀捐В鏋愬櫒瀵硅薄涓殑 source銆乴ine_buffer銆乸refix銆乪ol + * 绛夎祫婧愶紝骞舵渶缁堥噴鏀捐В鏋愬櫒瀵硅薄鑷韩鐨勫唴瀛樸 + */ + +static void DestroyParser(Parser *self) { + // 閲婃斁 source 瀵硅薄 if (self->source != NULL) { delete self->source; self->source = NULL; } + + // 閲婃斁 line_buffer 瀵硅薄锛堜粎鍦 GDS_SERVER 鎯呭喌涓嬪瓨鍦級 #ifdef GDS_SERVER if (self->line_buffer != NULL) { evbuffer_free(self->line_buffer); self->line_buffer = NULL; } #endif + + // 閲婃斁 prefix 瀛楃涓 if (self->prefix != NULL) { free(self->prefix); self->prefix = NULL; } + + // 閲婃斁 eol 瀛楃涓 if (self->eol != NULL) { free(self->eol); self->eol = NULL; } + + // 娓呯悊 line_buffers 瀵硅薄 self->line_buffers.Clean(); + + // 鏈鍚庨噴鏀捐В鏋愬櫒瀵硅薄鑷韩鐨勫唴瀛 free(self); } -static void DestroyReadableParser(ReadableParser* self) +/* + * 鍔熻兘锛氶攢姣佸彲璇昏В鏋愬櫒瀵硅薄 + * + * 鍙傛暟鍒楄〃锛 + * self锛氳閿姣佺殑鍙瑙f瀽鍣ㄥ璞℃寚閽 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庨攢姣佸彲璇昏В鏋愬櫒瀵硅薄浠ュ強鐩稿叧璧勬簮銆傞鍏堥噴鏀惧彲璇昏В鏋愬櫒瀵硅薄涓殑 rec_buf 缂撳啿鍖猴紝鐒跺悗璋冪敤 DestroyParser + * 鍑芥暟閲婃斁鍏朵粬璧勬簮锛屾渶缁堝皢瑙f瀽鍣ㄥ璞¤嚜韬寚閽堢疆涓 NULL銆 + */ + +static void DestroyReadableParser(ReadableParser *self) { + // 閲婃斁 rec_buf 缂撳啿鍖 if (self->rec_buf != NULL) { free(self->rec_buf); self->rec_buf = NULL; } + + // 璋冪敤 DestroyParser 鍑芥暟閲婃斁鍏朵粬璧勬簮 DestroyParser(self); + + // 灏嗚В鏋愬櫒瀵硅薄鑷韩鎸囬拡缃负 NULL self = NULL; } -static void DestroyWritableParser(WritableParser* self) +/* + * 鍔熻兘锛氶攢姣佸彲鍐欒В鏋愬櫒瀵硅薄 + * + * 鍙傛暟鍒楄〃锛 + * self锛氳閿姣佺殑鍙啓瑙f瀽鍣ㄥ璞℃寚閽 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庨攢姣佸彲鍐欒В鏋愬櫒瀵硅薄浠ュ強鐩稿叧璧勬簮銆傞鍏堥噴鏀惧彲鍐欒В鏋愬櫒瀵硅薄涓殑 fileheader 缂撳啿鍖猴紝鐒跺悗璋冪敤 SourceFlush + * 鍑芥暟鍒锋柊鏁版嵁鑷虫枃浠讹紝 鏈鍚庤皟鐢 DestroyParser 鍑芥暟閲婃斁鍏朵粬璧勬簮锛屾渶缁堝皢瑙f瀽鍣ㄥ璞¤嚜韬寚閽堢疆涓 NULL銆 + */ + +static void DestroyWritableParser(WritableParser *self) { + // 閲婃斁 fileheader 缂撳啿鍖 if (self->fileheader != NULL) { free(self->fileheader); self->fileheader = NULL; } + // 鍒锋柊鏁版嵁鑷虫枃浠 self->source->SourceFlush(); + + // 璋冪敤 DestroyParser 鍑芥暟閲婃斁鍏朵粬璧勬簮 DestroyParser(self); + + // 灏嗚В鏋愬櫒瀵硅薄鑷韩鎸囬拡缃负 NULL self = NULL; } -static void NopCleanup(Parser* self) +static void NopCleanup(Parser *self) {} -static void CleanupWritablParser(WritableParser* self) +/* + * 鍔熻兘锛氭竻鐞嗗彲鍐欒В鏋愬櫒瀵硅薄 + * + * 鍙傛暟鍒楄〃锛 + * self锛氳娓呯悊鐨勫彲鍐欒В鏋愬櫒瀵硅薄鎸囬拡 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庢竻鐞嗗彲鍐欒В鏋愬櫒瀵硅薄锛屼富瑕佸伐浣滃寘鎷叧闂綋鍓嶆枃浠朵絾涓嶅埛鏂版暟鎹紙浣跨敤 CloseCurrentFileNoFlush + * 鍑芥暟锛夊拰鍒犻櫎鏈彁浜ょ殑鏂囦欢銆 鍏蜂綋鎿嶄綔鍖呮嫭锛氳幏鍙栨枃浠跺垪琛紝鍏抽棴褰撳墠鏂囦欢浣嗕笉鍒锋柊鏁版嵁锛岄亶鍘嗘枃浠跺垪琛ㄥ垹闄ゆ湭鎻愪氦鐨勬枃浠躲 + */ + +static void CleanupWritablParser(WritableParser *self) { FileList::iterator i; - FileList* files = self->source->GetFileList(); + FileList *files = self->source->GetFileList(); + + // 鍏抽棴褰撳墠鏂囦欢浣嗕笉鍒锋柊鏁版嵁 self->source->CloseCurrentFileNoFlush(); - // Delete uncommited files - // + // 鍒犻櫎鏈彁浜ょ殑鏂囦欢 for (i = files->begin(); i != files->end(); i++) { (void)unlink(i->c_str()); } } #ifdef GDS_SERVER -static void GetFileHeader(WritableParser* self, const char* path) +/* + * 鍔熻兘锛氫粠鐢ㄦ埛瀹氫箟鐨勬枃浠跺ご涓幏鍙栨枃浠跺ご淇℃伅 + * + * 鍙傛暟鍒楄〃锛 + * self锛氬彲鍐欒В鏋愬櫒瀵硅薄鎸囬拡锛岀敤浜庡瓨鍌ㄦ枃浠跺ご淇℃伅 + * path锛氱敤鎴峰畾涔夌殑鏂囦欢澶存枃浠惰矾寰 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庝粠鐢ㄦ埛瀹氫箟鐨勬枃浠跺ご鏂囦欢涓幏鍙栨枃浠跺ご淇℃伅锛屼富瑕佸伐浣滃寘鎷細鎵撳紑鏂囦欢锛岃鍙栨枃浠跺ご鏁版嵁锛屽鐞嗗琛屾枃浠跺ご锛屽瓨鍌ㄦ枃浠跺ご淇℃伅銆 + * 鍏蜂綋鎿嶄綔鍖呮嫭锛氬垎閰嶆枃浠跺ご缂撳啿鍖猴紝鎵撳紑鏂囦欢锛岃鍙栨枃浠跺ご鏁版嵁锛屽鐞嗗琛屾枃浠跺ご锛屽瓨鍌ㄦ枃浠跺ご淇℃伅銆 + */ +static void GetFileHeader(WritableParser *self, const char *path) { - FILE* fd = NULL; + FILE *fd = NULL; int nread = 0; - char* eol = NULL; + char *eol = NULL; - self->fileheader = (char*)calloc(1, FILEHEADER_BUF_SIZE + 1); + // 鍒嗛厤鏂囦欢澶寸紦鍐插尯 + self->fileheader = (char *)calloc(1, FILEHEADER_BUF_SIZE + 1); if (self->fileheader == NULL) parser_log(LEVEL_ERROR, "out of memory"); + // 鎵撳紑鏂囦欢 fd = fopen(path, "r"); if (fd == NULL) parser_log(LEVEL_ERROR, "failed to open \"%s\"", path); + // 璇诲彇鏂囦欢澶存暟鎹 nread = fread(self->fileheader, 1, FILEHEADER_BUF_SIZE, fd); int err_no = ferror(fd); fclose(fd); @@ -1213,6 +1849,7 @@ static void GetFileHeader(WritableParser* self, const char* path) // if the user-define header file has multiple rows, // we will use the first row as the header line only. // + // 濡傛灉鐢ㄦ埛瀹氫箟鐨勬枃浠跺ご鏂囦欢鏈夊琛岋紝浠呬娇鐢ㄧ涓琛屼綔涓烘枃浠跺ご eol = FindEolChar(self->fileheader, nread, NULL, NULL, NULL); if (eol != NULL) { if (*eol != '\n' && *(eol + 1) == '\n') @@ -1225,54 +1862,106 @@ static void GetFileHeader(WritableParser* self, const char* path) parser_log(LEVEL_ERROR, "user-define header cannot longer than 1MB"); } #endif - +/* + * 鍔熻兘锛氬垵濮嬪寲琛岀紦鍐插尯 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庡垵濮嬪寲琛岀紦鍐插尯锛屼富瑕佸伐浣滃寘鎷細 + * 1. 鍒嗛厤琛岀紦鍐插尯鍐呭瓨 + * 2. 鍒濆鍖栫紦鍐插尯鍙傛暟鍜岀姸鎬 + * + * 鍏蜂綋鎿嶄綔鍖呮嫭锛氬垎閰嶈缂撳啿鍖哄唴瀛橈紝鍒濆鍖栧弬鏁板拰鐘舵併 + */ void GDS::LineBuffer::Init() { + // 璁剧疆缂撳啿鍖哄垵濮嬪ぇ灏忎负 MAX_BLK_SIZE m_buf_len = MAX_BLK_SIZE; - m_buf = (char*)malloc(m_buf_len); + + // 鍒嗛厤缂撳啿鍖哄唴瀛 + m_buf = (char *)malloc(m_buf_len); if (m_buf == NULL) parser_log(LEVEL_ERROR, "failed to init line buffer, out of memory"); + // 鍒濆鍖栧凡浣跨敤闀垮害鍜岃鏁 m_used_len = 0; m_row_num = 0; + // 鍒濆鍖栧綋鍓嶈鎸囬拡锛屽綋鍓嶈闀垮害锛屽綋鍓嶈鏄惁宸插畬鎴 m_cur_line = m_buf; m_cur_line_len = 0; m_cur_line_completed = true; + // 鍒濆鍖栬緭鍑烘寚閽堜负绌 m_output = NULL; #ifdef OBS_SERVER + // 鍒濆鍖栬鍙栦綅缃 m_read_pos = 0; + + // 鍒囨崲鍒 OBSParserContext 鍐呭瓨涓婁笅鏂 Assert(u_sess->cmd_cxt.OBSParserContext); MemoryContext oldcontext = MemoryContextSwitchTo(u_sess->cmd_cxt.OBSParserContext); + + // 鍒涘缓涓涓柊鐨 StringInfo 瀵硅薄锛岀敤浜庡鐞嗚繃杞界紦鍐插尯 m_overload_buf = makeStringInfo(); + + // 鍒囨崲鍥炲師鏉ョ殑鍐呭瓨涓婁笅鏂 MemoryContextSwitchTo(oldcontext); + + // 鍒濆鍖栬繃杞界紦鍐插尯鏄惁宸插畬鎴 m_overload_buf_completed = false; #endif } - +/* + * 鍔熻兘锛氶噸缃缂撳啿鍖虹姸鎬 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庨噸缃缂撳啿鍖虹殑鐘舵侊紝涓昏宸ヤ綔鍖呮嫭锛 + * 1. 绉诲姩鏈畬鎴愮殑琛屽埌缂撳啿鍖哄墠閮紙濡傛灉鏈夋湭瀹屾垚鐨勮锛 + * 2. 閲嶇疆缂撳啿鍖哄弬鏁板拰鐘舵 + * + * 鍏蜂綋鎿嶄綔鍖呮嫭锛氱Щ鍔ㄦ湭瀹屾垚鐨勮鍒扮紦鍐插尯鍓嶉儴锛堝鏋滄湁鏈畬鎴愮殑琛岋級锛岄噸缃弬鏁板拰鐘舵併 + */ void GDS::LineBuffer::Reset() { if (!m_cur_line_completed && (m_buf != m_cur_line)) { - // move uncomplete line to the front + // 灏嗘湭瀹屾垚鐨勮绉诲埌缂撳啿鍖哄墠閮 errno_t rc = memmove_s(m_buf, m_buf_len, m_cur_line, (m_cur_line_len + ROW_HEADER_SIZE)); parser_securec_check(rc); + // 鏇存柊宸蹭娇鐢ㄩ暱搴 m_used_len = m_cur_line_len + ROW_HEADER_SIZE; + + // 閲嶇疆褰撳墠琛屾寚閽堜负缂撳啿鍖鸿捣濮嬩綅缃 m_cur_line = m_buf; } else { + // 鏈湁鏈畬鎴愮殑琛岋紝閲嶆柊鍒濆鍖栨垚鍛樺彉閲 m_used_len = 0; m_cur_line = m_buf; m_cur_line_len = 0; } #ifdef OBS_SERVER + // 閲嶇疆璇诲彇浣嶇疆 m_read_pos = 0; #endif } - -int GDS::LineBuffer::AppendLine(const char* buf, int buf_len, bool isComplete) +/* + * 鍔熻兘锛氬悜琛岀紦鍐插尯杩藉姞鏁版嵁 + * + * 鍙傛暟鍒楄〃锛 + * buf锛氳杩藉姞鍒拌缂撳啿鍖虹殑鏁版嵁鐨勬寚閽 + * buf_len锛氳杩藉姞鐨勬暟鎹殑闀垮害 + * isComplete锛氭爣蹇楁槸鍚﹁拷鍔犵殑鏁版嵁缁勬垚浜嗕竴涓畬鏁寸殑琛 + * + * 杩斿洖鍊硷細 + * - 杩斿洖瀹為檯杩藉姞鍒拌缂撳啿鍖虹殑鏁版嵁闀垮害锛屽鏋滆拷鍔犲け璐ュ垯杩斿洖璐熸暟 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庡皢鏁版嵁杩藉姞鍒拌缂撳啿鍖猴紝涓昏宸ヤ綔鍖呮嫭锛氭鏌ュ弬鏁般佹鏌ョ紦鍐插尯绌洪棿銆佸鐞嗘暟鎹佹洿鏂拌澶翠俊鎭佹嫹璐濇暟鎹 + * 鍏蜂綋鎿嶄綔鍖呮嫭锛氭鏌ュ弬鏁般佹鏌ョ紦鍐插尯绌洪棿銆佸鐞嗘暟鎹佹洿鏂拌澶翠俊鎭佹嫹璐濇暟鎹 + */ +int GDS::LineBuffer::AppendLine(const char *buf, int buf_len, bool isComplete) { if (buf == NULL) return -1; @@ -1340,15 +2029,15 @@ int GDS::LineBuffer::AppendLine(const char* buf, int buf_len, bool isComplete) if (isComplete) { ++m_row_num; char row_header[ROW_HEADER_SIZE]; - *(uint32_t*)&row_header[0] = htonl((uint32_t)(m_cur_line_len + 4)); // add size of row_num - *(uint32_t*)&row_header[4] = htonl(m_row_num); + *(uint32_t *)&row_header[0] = htonl((uint32_t)(m_cur_line_len + 4)); // add size of row_num + *(uint32_t *)&row_header[4] = htonl(m_row_num); ASSERT(m_used_len >= ROW_HEADER_SIZE); rc = memcpy_s(m_cur_line, m_buf_len - (m_cur_line - m_buf), row_header, ROW_HEADER_SIZE); parser_securec_check(rc); } // copy data - char* cur_ptr = m_buf + m_used_len; + char *cur_ptr = m_buf + m_used_len; rc = memcpy_s(cur_ptr, (m_buf_len - m_used_len), buf, buf_len); parser_securec_check(rc); @@ -1358,7 +2047,21 @@ int GDS::LineBuffer::AppendLine(const char* buf, int buf_len, bool isComplete) } #ifdef GDS_SERVER -int GDS::LineBuffer::PackData(evbuffer* dest, bool isFlush) +/* + * 鍔熻兘锛氭墦鍖呮暟鎹苟鍙戦佽嚦鐩爣缂撳啿鍖 + * + * 鍙傛暟鍒楄〃锛 + * dest锛氱洰鏍囩紦鍐插尯 + * isFlush锛氭槸鍚﹁寮哄埗鍙戦 + * + * 杩斿洖鍊硷細 + * 鎴愬姛杩斿洖 0锛屽け璐ヨ繑鍥為敊璇爜 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庡皢鏁版嵁鎵撳寘骞跺彂閫佽嚦鐩爣缂撳啿鍖猴紝涓昏宸ヤ綔鍖呮嫭锛氳绠楀寘澶у皬銆佹瀯寤哄寘澶淬佸彂閫佹暟鎹侀噸缃缂撳啿鍖恒 + * 鍏蜂綋鎿嶄綔鍖呮嫭锛氳绠楀寘澶у皬銆佹瀯寤哄寘澶淬佸彂閫佹暟鎹侀噸缃缂撳啿鍖恒 + */ +int GDS::LineBuffer::PackData(evbuffer *dest, bool isFlush) { // 1. compute package size int package_size = (isFlush || m_cur_line_completed) ? m_used_len : (m_cur_line - m_buf); @@ -1372,8 +2075,8 @@ int GDS::LineBuffer::PackData(evbuffer* dest, bool isFlush) if (isFlush && !m_cur_line_completed) { char row_header[ROW_HEADER_SIZE]; - *(uint32_t*)&row_header[0] = htonl((uint32_t)(m_cur_line_len + 4)); // add size of row_num - *(uint32_t*)&row_header[4] = htonl(++m_row_num); + *(uint32_t *)&row_header[0] = htonl((uint32_t)(m_cur_line_len + 4)); // add size of row_num + *(uint32_t *)&row_header[4] = htonl(++m_row_num); rc = memcpy_s(m_cur_line, m_buf_len - (m_cur_line - m_buf), row_header, ROW_HEADER_SIZE); parser_securec_check(rc); @@ -1385,7 +2088,7 @@ int GDS::LineBuffer::PackData(evbuffer* dest, bool isFlush) char package_header[GDSCmdHeaderSize]; package_header[0] = CMD_TYPE_DATA; - *(uint32_t*)&package_header[1] = htonl((uint32_t)package_size); + *(uint32_t *)&package_header[1] = htonl((uint32_t)package_size); // 3. add to evbffer int retval = 0; @@ -1403,8 +2106,23 @@ int GDS::LineBuffer::PackData(evbuffer* dest, bool isFlush) return retval; } - -int GDS::LineBuffer::SendOverloadBuf(evbuffer* dest, const char* buf, int buf_len, bool isComplete) +/* + * 鍔熻兘锛氬彂閫佹孩鍑虹紦鍐插尯鑷崇洰鏍囩紦鍐插尯 + * + * 鍙傛暟鍒楄〃锛 + * dest锛氱洰鏍囩紦鍐插尯 + * buf锛氳鍙戦佺殑鏁版嵁鐨勬寚閽 + * buf_len锛氳鍙戦佺殑鏁版嵁鐨勯暱搴 + * isComplete锛氭爣蹇楁槸鍚﹁鍙戦佺殑鏁版嵁缁勬垚浜嗕竴涓畬鏁寸殑琛 + * + * 杩斿洖鍊硷細 + * 鎴愬姛杩斿洖 0锛屽け璐ヨ繑鍥為敊璇爜 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庡皢婧㈠嚭缂撳啿鍖虹殑鏁版嵁鍙戦佽嚦鐩爣缂撳啿鍖猴紝涓昏宸ヤ綔鍖呮嫭锛氭洿鏂拌澶淬佹瀯寤烘暟鎹寘澶淬佸彂閫佹暟鎹侀噸缃缂撳啿鍖恒 + * 鍏蜂綋鎿嶄綔鍖呮嫭锛氭洿鏂拌澶淬佹瀯寤烘暟鎹寘澶淬佸彂閫佹暟鎹侀噸缃缂撳啿鍖恒 + */ +int GDS::LineBuffer::SendOverloadBuf(evbuffer *dest, const char *buf, int buf_len, bool isComplete) { char row_header[ROW_HEADER_SIZE]; @@ -1414,8 +2132,8 @@ int GDS::LineBuffer::SendOverloadBuf(evbuffer* dest, const char* buf, int buf_le if (isComplete) ++m_row_num; - *(uint32_t*)&row_header[0] = htonl((uint32_t)(m_cur_line_len + buf_len + 4)); // add size of row_num - *(uint32_t*)&row_header[4] = htonl(m_row_num); + *(uint32_t *)&row_header[0] = htonl((uint32_t)(m_cur_line_len + buf_len + 4)); // add size of row_num + *(uint32_t *)&row_header[4] = htonl(m_row_num); /* * Send the buffer; @@ -1427,7 +2145,7 @@ int GDS::LineBuffer::SendOverloadBuf(evbuffer* dest, const char* buf, int buf_le else package_header[0] = CMD_TYPE_DATA_SEG; - *(uint32_t*)&package_header[1] = htonl((uint32_t)(m_cur_line_len + buf_len + ROW_HEADER_SIZE)); + *(uint32_t *)&package_header[1] = htonl((uint32_t)(m_cur_line_len + buf_len + ROW_HEADER_SIZE)); int retval = 0; @@ -1471,13 +2189,28 @@ int GDS::LineBuffer::SendOverloadBuf(evbuffer* dest, const char* buf, int buf_le #ifdef OBS_SERVER #ifndef ENABLE_LITE_MODE -static size_t SourceRead_OBS(Source* self, void* buffer, size_t len) +/* + * 鍔熻兘锛氫粠OBS锛圤bject Storage Service锛変腑璇诲彇鏁版嵁 + * + * 鍙傛暟鍒楄〃锛 + * self锛氭簮瀵硅薄鎸囬拡锛岀敤浜庡鐞哋BS璇诲彇 + * buffer锛氱洰鏍囩紦鍐插尯锛岀敤浜庡瓨鍌ㄨ鍙栧埌鐨勬暟鎹 + * len锛氳璇诲彇鐨勬暟鎹暱搴 + * + * 杩斿洖鍊硷細 + * 杩斿洖宸茶鍙栫殑鏁版嵁闀垮害 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庝粠OBS涓鍙栨暟鎹紝涓昏宸ヤ綔鍖呮嫭锛氭鏌ユ槸鍚﹀凡璇诲彇瀹屾瘯銆佸垱寤篛BS璇诲彇澶勭悊鍣ㄣ侀噸澶嶅皾璇曡鍙栨暟鎹佹爣璁版槸鍚﹀凡鍒拌揪瀵硅薄鐨勬湯灏俱 + * 鍏蜂綋鎿嶄綔鍖呮嫭锛氭鏌ユ槸鍚﹀凡璇诲彇瀹屾瘯銆佸垱寤篛BS璇诲彇澶勭悊鍣ㄣ侀噸澶嶅皾璇曡鍙栨暟鎹佹爣璁版槸鍚﹀凡鍒拌揪瀵硅薄鐨勬湯灏俱 + */ +static size_t SourceRead_OBS(Source *self, void *buffer, size_t len) { size_t nread = 0; size_t already_read = 0; if (self->m_obs_end) { - OBSReadWriteHandler* handler = self->GetOBSReadWriteHandler(); + OBSReadWriteHandler *handler = self->GetOBSReadWriteHandler(); if (handler != NULL) { DestroyObsReadWriteHandler(handler, false); @@ -1487,10 +2220,10 @@ static size_t SourceRead_OBS(Source* self, void* buffer, size_t len) return (size_t)0; } - OBSReadWriteHandler* handler = self->GetOBSReadWriteHandler(); + OBSReadWriteHandler *handler = self->GetOBSReadWriteHandler(); if (handler == NULL) { - const char* current_file = self->m_files[self->m_current - 1].c_str(); + const char *current_file = self->m_files[self->m_current - 1].c_str(); handler = CreateObsReadWriteHandler(current_file, OBS_READ, self->m_obs_options); self->SetOBSReadWriteHandler(handler); } @@ -1502,7 +2235,7 @@ static size_t SourceRead_OBS(Source* self, void* buffer, size_t len) PROFILING_OBS_START(); pgstat_report_waitevent(WAIT_EVENT_OBS_READ); do { - nread = read_bucket_object(handler, (char*)buffer + already_read, (len - already_read)); + nread = read_bucket_object(handler, (char *)buffer + already_read, (len - already_read)); already_read += nread; /* nread may be < 0 */ /* Mark we get the end of current object */ @@ -1514,10 +2247,22 @@ static size_t SourceRead_OBS(Source* self, void* buffer, size_t len) return already_read; } - -static bool SourceNext_OBS(Source* self) +/* + * 鍔熻兘锛氳幏鍙栦笅涓涓狾BS瀵硅薄 + * + * 鍙傛暟鍒楄〃锛 + * self锛氭簮瀵硅薄鎸囬拡锛岀敤浜庡鐞哋BS璇诲彇 + * + * 杩斿洖鍊硷細 + * 濡傛灉鎴愬姛鑾峰彇涓嬩竴涓狾BS瀵硅薄锛屽垯杩斿洖true锛涘惁鍒欒繑鍥瀎alse銆 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庤幏鍙栦笅涓涓狾BS瀵硅薄锛屼富瑕佸伐浣滃寘鎷細妫鏌ユ槸鍚﹀凡鍒拌揪鏂囦欢鍒楄〃鏈熬銆佸惊鐜亶鍘嗘枃浠跺垪琛ㄣ佽烦杩囩壒娈婃枃浠躲 + * 鍏蜂綋鎿嶄綔鍖呮嫭锛氭鏌ユ槸鍚﹀凡鍒拌揪鏂囦欢鍒楄〃鏈熬銆佸惊鐜亶鍘嗘枃浠跺垪琛ㄣ佽烦杩囩壒娈婃枃浠躲 + */ +static bool SourceNext_OBS(Source *self) { - const char* current_file = NULL; + const char *current_file = NULL; if ((size_t)(self->m_current) >= self->m_files.size()) return false; @@ -1579,19 +2324,19 @@ bool GDS::LineBuffer::GetNextLine(StringInfo output_line) Assert(m_read_pos < m_used_len); - char* buf = m_buf + m_read_pos; + char *buf = m_buf + m_read_pos; /* Parsing the tuple header part */ char header[ROW_HEADER_SIZE]; errno_t rc = memcpy_s(header, ROW_HEADER_SIZE, buf, ROW_HEADER_SIZE); parser_securec_check(rc); - int64_t tuplen = ntohl(*(uint32_t*)&(header[0])); - int64_t nth = ntohl(*(uint32_t*)&(header[4])); + int64_t tuplen = ntohl(*(uint32_t *)&(header[0])); + int64_t nth = ntohl(*(uint32_t *)&(header[4])); if (nth < 0 || (unsigned int64_t)nth > PG_UINT32_MAX || tuplen < 0 || (unsigned int64_t)tuplen > MaxAllocSize + GDS_HEADER_LEN) { - parser_log( - LEVEL_ERROR, "Linebuffer's content is trashed as tuple's ID %lu and length is not valid %lu", nth, tuplen); + parser_log(LEVEL_ERROR, "Linebuffer's content is trashed as tuple's ID %lu and length is not valid %lu", nth, + tuplen); } /* Minus the tuple id in current line buffer to the actual tuplelen */ @@ -1629,8 +2374,8 @@ void GDS::LineBuffer::MarkLastLineCompleted() /* just like PackData (dest, TRUE) , fill the ROW HEADER of the last uncompleted row, and mark it completed */ char row_header[ROW_HEADER_SIZE]; - *(uint32_t*)&row_header[0] = htonl((uint32_t)(m_cur_line_len + 4)); // add size of row_num - *(uint32_t*)&row_header[4] = htonl(++m_row_num); + *(uint32_t *)&row_header[0] = htonl((uint32_t)(m_cur_line_len + 4)); // add size of row_num + *(uint32_t *)&row_header[4] = htonl(++m_row_num); errno_t rc = memcpy_s(m_cur_line, m_buf_len - (m_cur_line - m_buf), row_header, ROW_HEADER_SIZE); parser_securec_check(rc); @@ -1659,7 +2404,7 @@ void GDS::LineBuffer::MarkLastLineCompleted() * * Important: THIS FOUNCTION JUST USE FOR OBS , DO NOT USE FOR GDS. */ -void GDS::LineBuffer::SaveOverloadBuf(StringInfo dest, const char* buf, int buf_len, bool isComplete) +void GDS::LineBuffer::SaveOverloadBuf(StringInfo dest, const char *buf, int buf_len, bool isComplete) { Assert((0 == m_used_len) || ((false == m_cur_line_completed) && (m_cur_line == m_buf))); diff --git a/src/gausskernel/storage/bulkload/roach_adpter.cpp b/src/gausskernel/storage/bulkload/roach_adpter.cpp index f27ab5a53..95b4a0436 100644 --- a/src/gausskernel/storage/bulkload/roach_adpter.cpp +++ b/src/gausskernel/storage/bulkload/roach_adpter.cpp @@ -32,7 +32,14 @@ template bool getNextRoach(CopyState cstate); template bool getNextRoach(CopyState cstate); template void initRoachState(CopyState cstate, const char *filename, List *totalTask); template void initRoachState(CopyState cstate, const char *filename, List *totalTask); - +/* + * Function: initRoachRoutine + * + * Initializes a RoachRoutine by looking up the "roach_handler" function and + * checking its return type. + * + * Returns: A RoachRoutine pointer. + */ RoachRoutine *initRoachRoutine() { Datum datum; @@ -50,7 +57,16 @@ RoachRoutine *initRoachRoutine() return routine; } - +/* + * Function: getNextRoach + * + * Gets the next Roach data to import or export in a COPY operation. + * + * Parameters: + * - cstate: The COPY operation's state. + * + * Returns: true if successful, false if there's no more data to process. + */ template bool getNextRoach(CopyState cstate) { @@ -78,7 +94,19 @@ bool getNextRoach(CopyState cstate) cstate->roach_context = roach_context; return true; } - +/* + * Function: copyGetRoachData + * + * Reads Roach data for a COPY operation. + * + * Parameters: + * - cstate: The COPY operation's state. + * - databuf: The data buffer to read into. + * - minread: The minimum number of bytes to read. + * - maxread: The maximum number of bytes to read. + * + * Returns: The number of bytes read. + */ int copyGetRoachData(CopyState cstate, void *databuf, int minread, int maxread) { Assert(cstate->roach_routine); @@ -91,7 +119,16 @@ int copyGetRoachData(CopyState cstate, void *databuf, int minread, int maxread) return bytesread; } - +/* + * Function: initRoachState + * + * Initializes the state for a Roach COPY operation. + * + * Parameters: + * - cstate: The COPY operation's state. + * - filename: The Roach file to import/export. + * - totalTask: The total tasks to process. + */ template void initRoachState(CopyState cstate, const char *filename, List *totalTask) { @@ -117,8 +154,8 @@ void initRoachState(CopyState cstate, const char *filename, List *totalTask) char roachPath[PATH_MAX + 1]; const char *pos = strstr(filename, ROACH_PREFIX); pos += ROACH_PREFIX_LEN; - errno_t ret = snprintf_s(roachPath, sizeof(roachPath), PATH_MAX, "%s/%s", pos, - g_instance.attr.attr_common.PGXCNodeName); + errno_t ret = + snprintf_s(roachPath, sizeof(roachPath), PATH_MAX, "%s/%s", pos, g_instance.attr.attr_common.PGXCNodeName); securec_check_ss(ret, "", ""); roachPath[PATH_MAX] = '\0'; @@ -137,7 +174,14 @@ void initRoachState(CopyState cstate, const char *filename, List *totalTask) (void)getNextRoach(cstate); } } - +/* + * Function: endRoachBulkLoad + * + * Ends a Roach bulk load operation. + * + * Parameters: + * - cstate: The COPY operation's state. + */ void endRoachBulkLoad(CopyState cstate) { if (IS_PGXC_DATANODE) { @@ -149,7 +193,14 @@ void endRoachBulkLoad(CopyState cstate) ereport(ERROR, (errcode_for_file_access(), errmsg("could not close roach %s", cstate->filename))); } } - +/* + * Function: exportRoach + * + * Exports data to Roach in a COPY operation. + * + * Parameters: + * - cstate: The COPY operation's state. + */ void exportRoach(CopyState cstate) { Assert(cstate->copy_dest == COPY_ROACH); @@ -196,7 +247,15 @@ void exportRoach(CopyState cstate) resetStringInfo(in); } - +/* + * Function: exportRoachFlushOut + * + * Flushes the data to Roach in a COPY operation. + * + * Parameters: + * - cstate: The COPY operation's state. + * - isWholeLineAtEnd: Indicates if the whole line is at the end. + */ void exportRoachFlushOut(CopyState cstate, bool isWholeLineAtEnd) { Assert(cstate->roach_routine); diff --git a/src/gausskernel/storage/bulkload/vecforeignroutine.cpp b/src/gausskernel/storage/bulkload/vecforeignroutine.cpp index f7e46dafa..13c39a6e2 100644 --- a/src/gausskernel/storage/bulkload/vecforeignroutine.cpp +++ b/src/gausskernel/storage/bulkload/vecforeignroutine.cpp @@ -52,40 +52,88 @@ extern void SyncBulkloadStates(CopyState cstate); extern void CleanBulkloadStates(); // all stuffs used for bulkload(end). // Try to save importing error if needed +/* + * 鍔熻兘锛氬皾璇曚繚瀛樺鍏ラ敊璇 + * + * 鍙傛暟鍒楄〃锛 + * importState锛氬鍏ユ墽琛岀姸鎬佹寚閽堬紝鍖呭惈瀵煎叆杩囩▼涓殑鐩稿叧淇℃伅 + * node锛氬閮ㄦ壂鎻忕姸鎬佹寚閽堬紝鐢ㄤ簬璁块棶澶栭儴鎵弿鐩稿叧淇℃伅 + * + * 杩斿洖鍊硷細 + * 濡傛灉鎴愬姛淇濆瓨瀵煎叆閿欒锛岃繑鍥瀟rue锛涘惁鍒欒繑鍥瀎alse銆 + * + * 娉ㄦ剰锛 + * 杩欎釜鍑芥暟鐢ㄤ簬灏濊瘯淇濆瓨瀵煎叆閿欒锛屽畠妫鏌ラ敊璇爜鏄惁涓烘暟鎹紓甯革紙Data Exception锛夊苟涓旀槸鍚﹀彲浠ユ帴鍙楅敊璇 + * 濡傛灉婊¤冻鏉′欢锛屽畠浼氫繚瀛橀敊璇褰曪紝骞跺湪蹇呰鏃舵竻闄ら敊璇姸鎬併 + */ bool TrySaveImportError(DistImportExecutionState *importState, ForeignScanState *node) { + // 妫鏌ュ綋鍓嶉敊璇爜鏄惁涓烘暟鎹紓甯革紙Data Exception锛 if ((ERRCODE_TO_CATEGORY((unsigned int)geterrcode()) == ERRCODE_DATA_EXCEPTION) && DoAcceptOneError(importState)) { + // 濡傛灉鏄暟鎹紓甯稿苟涓擠oAcceptOneError杩斿洖true锛岃〃绀哄彲浠ユ帴鍙楅敊璇 + + // 妫鏌ラ敊璇爜鏄惁涓哄瓧绗︿笉鍦ㄥ瓧绗﹂泦涓垨鑰呮棤娉曠炕璇戠殑瀛楃 if (geterrcode() == ERRCODE_CHARACTER_NOT_IN_REPERTOIRE || geterrcode() == ERRCODE_UNTRANSLATABLE_CHARACTER) t_thrd.bulk_cxt.illegal_character_err_cnt++; ListCell *lc = NULL; + // 閬嶅巻閿欒璁板綍鍣ㄥ垪琛紝澶勭悊姣忎釜閿欒璁板綍 foreach (lc, importState->elogger) { ImportErrorLogger *elogger = (ImportErrorLogger *)lfirst(lc); FormAndSaveImportError(importState, importState->errLogRel, importState->beginTime, elogger); } - // clear error state - // + // 娓呴櫎閿欒鐘舵 FlushErrorStateWithoutDeleteChildrenContext(); - return true; + return true; // 杩斿洖true琛ㄧず鎴愬姛淇濆瓨瀵煎叆閿欒 } - return false; + return false; // 杩斿洖false琛ㄧず娌℃湁淇濆瓨瀵煎叆閿欒 } - +/* + * 鍔熻兘锛氬皾璇曚繚瀛樺鍏ラ敊璇 + * + * 鍙傛暟鍒楄〃锛 + * cstate锛氬鍒剁姸鎬佹寚閽堬紝鍖呭惈澶嶅埗杩囩▼涓殑鐩稿叧淇℃伅 + * + * 杩斿洖鍊硷細 + * 濡傛灉鎴愬姛淇濆瓨瀵煎叆閿欒锛岃繑鍥瀟rue锛涘惁鍒欒繑鍥瀎alse銆 + * + * 娉ㄦ剰锛 + * 杩欎釜鍑芥暟鐢ㄤ簬灏濊瘯淇濆瓨瀵煎叆閿欒锛屽畠妫鏌ラ敊璇爜鏄惁涓烘暟鎹紓甯革紙Data Exception锛夊苟涓旀槸鍚﹀彲浠ユ帴鍙楅敊璇 + * 濡傛灉婊¤冻鏉′欢锛屽畠浼氫繚瀛橀敊璇褰曪紝骞跺湪蹇呰鏃舵竻闄ら敊璇姸鎬併 + */ bool TrySaveImportError(CopyState cstate) { + // 澧炲姞閿欒琛屾暟璁℃暟鍣 cstate->errorrows++; - if ((ERRCODE_TO_CATEGORY((unsigned int)geterrcode()) == ERRCODE_DATA_EXCEPTION) && DoAcceptOneError(cstate)) { - FormAndSaveImportError(cstate, cstate->err_table, cstate->copy_beginTime, cstate->logger); - // clear error state - // - FlushErrorStateWithoutDeleteChildrenContext(); - return true; - } - return false; -} + // 妫鏌ュ綋鍓嶉敊璇爜鏄惁涓烘暟鎹紓甯革紙Data Exception锛 + if ((ERRCODE_TO_CATEGORY((unsigned int)geterrcode()) == ERRCODE_DATA_EXCEPTION) && DoAcceptOneError(cstate)) { + // 濡傛灉鏄暟鎹紓甯稿苟涓擠oAcceptOneError杩斿洖true锛岃〃绀哄彲浠ユ帴鍙楅敊璇 + + // 璋冪敤鍑芥暟淇濆瓨瀵煎叆閿欒 + FormAndSaveImportError(cstate, cstate->err_table, cstate->copy_beginTime, cstate->logger); + + // 娓呴櫎閿欒鐘舵 + FlushErrorStateWithoutDeleteChildrenContext(); + return true; // 杩斿洖true琛ㄧず鎴愬姛淇濆瓨瀵煎叆閿欒 + } + return false; // 杩斿洖false琛ㄧず娌℃湁淇濆瓨瀵煎叆閿欒 +} +/* + * 鍔熻兘锛氭墽琛屽悜閲忓寲澶栭儴鏁版嵁瀵煎叆 + * + * 鍙傛暟鍒楄〃锛 + * node锛氬悜閲忓寲澶栭儴鎵弿鐘舵佹寚閽堬紝鍖呭惈瀵煎叆杩囩▼涓殑鐩稿叧淇℃伅 + * + * 杩斿洖鍊硷細 + * 杩斿洖鍖呭惈瀵煎叆鏁版嵁鐨勫悜閲忔壒娆★紙VectorBatch锛夈 + * + * 娉ㄦ剰锛 + * 杩欎釜鍑芥暟鐢ㄤ簬鎵ц鍚戦噺鍖栫殑澶栭儴鏁版嵁瀵煎叆鎿嶄綔銆傚畠浠庡閮ㄦ暟鎹簮涓鍙栨暟鎹苟灏嗗叾濉厖鍒癡ectorBatch涓 + * 鍚屾椂锛屽畠杩樺鐞嗛敊璇苟淇濆瓨瀵煎叆閿欒璁板綍銆 + */ VectorBatch *distExecVecImport(VecForeignScanState *node) { DistImportExecutionState *importState = (DistImportExecutionState *)node->fdw_state; @@ -97,60 +145,45 @@ VectorBatch *distExecVecImport(VecForeignScanState *node) MemoryContext oldMemoryContext; MemoryContext scanMcxt = node->scanMcxt; - /* Set up callback to identify error line number. */ + /* 璁剧疆閿欒鍥炶皟浠ヨ瘑鍒敊璇鍙 */ errcontext.callback = BulkloadErrorCallback; errcontext.arg = (void *)importState; errcontext.previous = t_thrd.log_cxt.error_context_stack; t_thrd.log_cxt.error_context_stack = &errcontext; - /* - * The protocol for loading a virtual tuple into a slot is first - * ExecClearTuple, then fill the values/isnull arrays, then - * ExecStoreVirtualTuple. If we don't find another row in the file, we - * just skip the last step, leaving the slot empty as required. - * - * We can pass ExprContext = NULL because we read all columns from the - * file, so no need to evaluate default expressions. - * - * We can also pass tupleOid = NULL because we don't allow oids for - * foreign tables. - */ batch->Reset(true); + if (node->m_done) { - /* Remove error callback. */ + /* 绉婚櫎閿欒鍥炶皟 */ t_thrd.log_cxt.error_context_stack = errcontext.previous; return batch; } MemoryContextReset(scanMcxt); oldMemoryContext = MemoryContextSwitchTo(scanMcxt); -#ifndef ENABLE_LITE_MODE - SetObsMemoryContext(((CopyState)importState)->copycontext); -#endif + for (batch->m_rows = 0; batch->m_rows < BatchMaxSize; batch->m_rows++) { -retry: + retry: PG_TRY(); { - /* - * Synchronize the current bulkload states. - */ + /* 鍚屾褰撳墠鎵归噺鍔犺浇鐘舵 */ SyncBulkloadStates((CopyState)importState); + + // 浠庡閮ㄦ暟鎹簮涓鍙栦笅涓琛屾暟鎹 found = NextCopyFrom((CopyState)importState, NULL, values, nulls, NULL); } PG_CATCH(); { - /* - * Clean the current bulkload states. - */ - CleanBulkloadStates(); + /* 娓呯悊褰撳墠鎵归噺鍔犺浇鐘舵 */ + // 灏濊瘯淇濆瓨瀵煎叆閿欒锛屽鏋滄垚鍔熷垯閲嶈瘯 if (TrySaveImportError(importState, node)) { (void)MemoryContextSwitchTo(scanMcxt); MemoryContextReset(scanMcxt); CHECK_FOR_INTERRUPTS(); goto retry; } else { - /* clean copy state and re throw */ + /* 娓呯悊澶嶅埗鐘舵佸苟閲嶆柊鎶涘嚭寮傚父 */ importState->isExceptionShutdown = true; EndDistImport(importState); PG_RE_THROW(); @@ -158,13 +191,13 @@ retry: } PG_END_TRY(); - /* - * Clean the current bulkload states. - */ + /* 娓呯悊褰撳墠鎵归噺鍔犺浇鐘舵 */ CleanBulkloadStates(); if (found) { int rows = batch->m_rows; + + // 灏嗚鍙栫殑鏁版嵁濉厖鍒癡ectorBatch涓 for (int i = 0; i < batch->m_cols; i++) { ScalarVector *vec = &(batch->m_arr[i]); if (nulls[i]) { @@ -187,7 +220,8 @@ retry: } (void)MemoryContextSwitchTo(oldMemoryContext); - /* Remove error callback. */ + + /* 绉婚櫎閿欒鍥炶皟 */ t_thrd.log_cxt.error_context_stack = errcontext.previous; return batch; diff --git a/src/gausskernel/storage/cmgr/cache_mgr.cpp b/src/gausskernel/storage/cmgr/cache_mgr.cpp index 048232838..b111c2684 100644 --- a/src/gausskernel/storage/cmgr/cache_mgr.cpp +++ b/src/gausskernel/storage/cmgr/cache_mgr.cpp @@ -93,12 +93,18 @@ int CacheMgrNumLocks(int64 cache_size, uint32 each_block_size) */ int64 CacheMgrCalcSizeByType(MgrCacheType type) { + // 计算元数据缓存大小为cstore缓冲区大小的1/4,但最大不超过2G + /* + * g_instance.attr.attr_storage.cstore_buffers:这是一个配置参数。 + * 表示 cstore 存储引擎的缓冲区大小,以块为单位。 + */ int64 size = g_instance.attr.attr_storage.cstore_buffers * 1024LL * 1 / 4; int64 cache_size = Min(size, MAX_METADATA_CACHE_SIZE); - if (!g_instance.attr.attr_sql.enable_orc_cache) { + //如果不启用 ORC 缓存(由配置参数 enable_orc_cache 控制),则将缓存大小设置为 1MB。 + if (!g_instance.attr.attr_sql.enable_orc_cache) { cache_size = 1024 * 1024; } - + // 如果缓存类型为数据缓存,将缓存大小设置为剩余的大小 if (type == MGR_CACHE_TYPE_DATA) { cache_size = g_instance.attr.attr_storage.cstore_buffers * 1024LL - cache_size; } @@ -118,19 +124,36 @@ void CacheMgr::Init(int64 cache_size, uint32 each_block_size, MgrCacheType type, int i = 0; int trancheId = LWTRANCHE_UNKNOWN; int32 total_slots = 0; - + // 设置缓存类型 m_cache_type = type; /* Must be greater than 0 */ m_CaccheSlotMax = 1; - m_cstoreCurrentSize = 0; - m_cstoreMaxSize = cache_size; - + m_cstoreCurrentSize = 0;//表示当前缓存的实际大小,初始值为 0,表示在初始化时缓存尚未使用。 + m_cstoreMaxSize = cache_size;//表示缓存的最大可用大小,它由传递给函数的 cache_size 参数指定,表示系统允许的最大缓存大小。 + + // 计算可用的缓存槽的总数,限制最大数量为 MAX_CACHE_SLOT_COUNT total_slots = Min(cache_size / each_block_size, MAX_CACHE_SLOT_COUNT); + + /* + *这行代码分配了一个连续的内存块,用于存储缓存槽的数据。 + * total_slots 表示缓存槽的总数 + * each_slot_length 表示每个缓存槽的长度,乘积得到了需要的总内存大小 + * palloc0 是一个内存分配函数,它将分配的内存块初始化为零 + * 这个数组将被用于存储每个缓存槽的数据。 + */ m_CacheSlots = (char *)palloc0(total_slots * each_slot_length); + + //这行代码分配了一个数组,用于存储缓存描述符。 m_CacheDesc = (CacheDesc *)palloc0(total_slots * sizeof(CacheDesc)); + + //这行代码将 m_CacheSlotsNum 设置为缓存槽的总数,以便后续的缓存管理操作可以使用这个值。 m_CacheSlotsNum = total_slots; + + //这行代码将 m_slot_length 设置为每个缓存槽的长度,以便在后续操作中可以正确处理每个缓存槽的数据。 m_slot_length = each_slot_length; + + // 遍历所有的缓存槽,初始化相关参数 for (i = 0; i < total_slots; ++i) { m_CacheDesc[i].m_usage_count = 0; m_CacheDesc[i].m_refcount = 0; @@ -144,11 +167,18 @@ void CacheMgr::Init(int64 cache_size, uint32 each_block_size, MgrCacheType type, } else if (type == MGR_CACHE_TYPE_INDEX) { trancheId = (int)LWTRANCHE_META_CACHE; } + + //分别为当前缓存描述符中的 m_iobusy_lock 和 m_compress_lock 字段分配了与缓存类型相关的轻量级锁。 m_CacheDesc[i].m_iobusy_lock = LWLockAssign(trancheId); m_CacheDesc[i].m_compress_lock = LWLockAssign(trancheId); + + //这行代码将缓存描述符中的 m_refreshing 字段初始化为 false。这个字段表示当前缓存块是否正在刷新中,刷新是指重新加载缓存块的数据。 m_CacheDesc[i].m_refreshing = false; + + //将缓存描述符中的 m_datablock_size 字段初始化为 0。这个字段用于记录缓存块中数据的大小。 m_CacheDesc[i].m_datablock_size = 0; - + + //初始化了缓存描述符中的自旋锁 m_slot_hdr_lock,该锁用于在缓存管理操作中保护缓存槽的头部信息。 SpinLockInit(&m_CacheDesc[i].m_slot_hdr_lock); } diff --git a/src/gausskernel/storage/cstore/cstore_allocspace.cpp b/src/gausskernel/storage/cstore/cstore_allocspace.cpp index 0d0710779..78eac70fd 100644 --- a/src/gausskernel/storage/cstore/cstore_allocspace.cpp +++ b/src/gausskernel/storage/cstore/cstore_allocspace.cpp @@ -460,28 +460,34 @@ void CStoreFreeSpace::Push(const CStoreFreeSpaceDesc& desc) m_descs[i] = desc; } -void CStoreFreeSpace::PopDescWithMaxSize(CStoreFreeSpaceDesc& desc) +/* + * 鍔熻兘锛氬脊鍑烘渶澶уぇ灏忕殑绌洪棽绌洪棿鎻忚堪 + * + * 鍙傛暟锛 + * desc锛氱敤浜庡瓨鍌ㄥ脊鍑虹殑绌洪棽绌洪棿鎻忚堪 + */ +void CStoreFreeSpace::PopDescWithMaxSize(CStoreFreeSpaceDesc &desc) { CStoreFreeSpaceDesc tmp; int i = 1; int subi = 2; if (m_descNum == 0) - return; + return; // 濡傛灉娌℃湁绌洪棽绌洪棿鎻忚堪锛岀洿鎺ヨ繑鍥 - desc = m_descs[1]; - tmp = m_descs[m_descNum--]; + desc = m_descs[1]; // 灏嗘牴鑺傜偣鐨勭┖闂茬┖闂存弿杩拌祴鍊肩粰浼犲叆鐨勫弬鏁 desc + tmp = m_descs[m_descNum--]; // 鍙栧嚭鏈鍚庝竴涓┖闂茬┖闂存弿杩帮紝骞跺噺灏戞弿杩版暟閲 while (subi <= m_descNum) { if (subi < m_descNum && m_descs[subi].size < m_descs[subi + 1].size) - subi++; + subi++; // 濡傛灉鍙冲瓙鑺傜偣姣斿乏瀛愯妭鐐瑰ぇ锛岄夋嫨鍙冲瓙鑺傜偣 if (tmp.size >= m_descs[subi].size) - break; - m_descs[i] = m_descs[subi]; + break; // 濡傛灉褰撳墠鑺傜偣姣斿瓙鑺傜偣澶э紝閫鍑哄惊鐜 + m_descs[i] = m_descs[subi]; // 鍚﹀垯灏嗗瓙鑺傜偣涓婄Щ i = subi; subi *= 2; } - m_descs[i] = tmp; + m_descs[i] = tmp; // 灏嗗師鏍硅妭鐐癸紙鏈澶х殑锛夋斁鍏ョ┖闂茬┖闂存弿杩版暟缁勭殑姝g‘浣嶇疆 } void CStoreFreeSpace::GetDescWithMaxSize(_out_ CStoreFreeSpaceDesc& desc) diff --git a/src/gausskernel/storage/dfs/obs/obs_connector.cpp b/src/gausskernel/storage/dfs/obs/obs_connector.cpp index 041485b67..99d2b4eee 100644 --- a/src/gausskernel/storage/dfs/obs/obs_connector.cpp +++ b/src/gausskernel/storage/dfs/obs/obs_connector.cpp @@ -30,9 +30,9 @@ #include "utils/plog.h" #if defined(__LP64__) || defined(__64BIT__) - typedef unsigned int GS_UINT32; +typedef unsigned int GS_UINT32; #else - typedef unsigned long GS_UINT32; +typedef unsigned long GS_UINT32; #endif #define OBS_NOT_IMPLEMENT \ @@ -41,25 +41,50 @@ HTAB *OBSConnectorCache = NULL; namespace dfs { +/* + * 鍔熻兘锛氬垱寤轰竴涓 OBS 杩炴帴鍣ㄥ璞 + * + * 鍙傛暟鍒楄〃锛 + * ctx锛氬唴瀛樹笂涓嬫枃锛岀敤浜庡唴瀛樼鐞 + * foreignTableId锛氬閮ㄨ〃鐨勫璞℃爣璇嗙 + */ OBSConnector::OBSConnector(MemoryContext ctx, Oid foreignTableId) : m_memcontext(ctx), m_handler(NULL), srvType(T_INVALID) { // build obs handler m_handler = searchConnectorCache(foreignTableId); } - +/* + * 鍔熻兘锛氬垱寤轰竴涓 OBS 杩炴帴鍣ㄥ璞 + * + * 鍙傛暟鍒楄〃锛 + * ctx锛氬唴瀛樹笂涓嬫枃锛岀敤浜庡唴瀛樼鐞 + * obsOptions锛歄BS 杩炴帴閫夐」锛屽寘鍚繛鎺ュ埌 OBS 鎵闇鐨勯厤缃俊鎭 + */ OBSConnector::OBSConnector(MemoryContext ctx, ObsOptions *obsOptions) : m_memcontext(ctx), m_handler(NULL), srvType(T_INVALID) { // build obs handler m_handler = createRWHandler(obsOptions); } - +/* + * 鍔熻兘锛氶攢姣 OBS 杩炴帴鍣ㄥ璞 + * + * 娉ㄦ剰锛氬湪瀵硅薄閿姣佹椂锛岃皟鐢ㄤ簡 Destroy() 鍑芥暟浠ユ墽琛屽繀瑕佺殑娓呯悊鎿嶄綔銆 + */ OBSConnector::~OBSConnector() { Destroy(); } - +/* + * 鍔熻兘锛氶攢姣 OBS 杩炴帴鍣ㄥ璞 + * + * 娉ㄦ剰锛 + * - 杩欎釜鍑芥暟鐢ㄤ簬閿姣 OBS 杩炴帴鍣ㄥ璞★紝鍖呮嫭娓呯悊涓庡璞$浉鍏崇殑璧勬簮銆 + * - 鍦ㄩ攢姣佸墠锛屽皢 m_handler->m_object_info.key 璁剧疆涓 NULL锛屼互閬垮厤鎮寕鎸囬拡銆 + * - 璋冪敤 DestroyObsReadWriteHandler() 鍑芥暟閿姣 OBS 璇诲啓澶勭悊绋嬪簭锛屽苟浼犻 true 鍙傛暟浠ョ‘淇濋噴鏀炬墍鏈夌浉鍏宠祫婧愩 + * - 鏈鍚庯紝灏 m_handler 鎸囬拡璁剧疆涓 NULL锛岄槻姝㈤噸澶嶉攢姣併 + */ void OBSConnector::Destroy() { // IMPORT: m_handler->m_prefix not alloc on this class 's memeory context @@ -315,47 +340,99 @@ List *OBSConnector::listObjectsStat(char *searchPath, const char *primitivePrefi return objectList; } - +/* + * 鍔熻兘锛氳幏鍙栨寚瀹氭枃浠剁殑 DFS 鍧椾俊鎭 + * + * 鍙傛暟鍒楄〃锛 + * filePath锛氳鏌ヨ鍧椾俊鎭殑鏂囦欢璺緞 + * + * 娉ㄦ剰锛 + * - 璇ュ嚱鏁板皻鏈疄鐜帮紝鍙槸涓涓崰浣嶇銆傚湪瀹炵幇姝ゅ姛鑳戒箣鍓嶏紝瀹冭繑鍥 NULL銆 + * - 涓鏃﹀疄鐜颁簡鑾峰彇鏂囦欢鐨 DFS 鍧椾俊鎭殑鍔熻兘锛屽簲璇ユ洿鏂版鍑芥暟浠ユ彁渚涙纭殑瀹炵幇銆 + * - DFS 鍧椾俊鎭氬父鍖呮嫭鍧楃殑浣嶇疆銆佸ぇ灏忕瓑鐩稿叧淇℃伅銆 + */ DFSBlockInfo *OBSConnector::getBlockLocations(char *filePath) { + // 浣跨敤 OBS_NOT_IMPLEMENT 鏍囪鍑芥暟鏈疄鐜 OBS_NOT_IMPLEMENT; + // 杩斿洖 NULL锛屽洜涓哄嚱鏁版湭瀹炵幇 return NULL; } - +/* + * 鍔熻兘锛氬垹闄ゆ寚瀹氳矾寰勭殑鐩綍锛堟湭瀹炵幇锛 + * + * 鍙傛暟鍒楄〃锛 + * path锛氳鍒犻櫎鐨勭洰褰曡矾寰 + * recursive锛氭槸鍚﹂掑綊鍒犻櫎瀛愮洰褰曪紙1 琛ㄧず閫掑綊鍒犻櫎锛0 琛ㄧず涓嶉掑綊锛 + */ int OBSConnector::dropDirectory(const char *path, int recursive) { + // 浣跨敤 OBS_NOT_IMPLEMENT 鏍囪鍑芥暟鏈疄鐜 OBS_NOT_IMPLEMENT; + // 杩斿洖 0锛岃〃绀哄垹闄ゆ垚鍔燂紙鍗犱綅杩斿洖鍊硷紝瀹為檯鍒犻櫎鏈疄鐜帮級 return 0; } - +/* + * 鍔熻兘锛氬垱寤烘寚瀹氳矾寰勭殑鐩綍锛堟湭瀹炵幇锛 + * + * 鍙傛暟鍒楄〃锛 + * path锛氳鍒涘缓鐨勭洰褰曡矾寰 + */ int OBSConnector::createDirectory(const char *path) { + // 浣跨敤 OBS_NOT_IMPLEMENT 鏍囪鍑芥暟鏈疄鐜 OBS_NOT_IMPLEMENT; + // 杩斿洖 0锛岃〃绀哄垱寤烘垚鍔燂紙鍗犱綅杩斿洖鍊硷紝瀹為檯鍒涘缓鏈疄鐜帮級 return 0; } - +/* + * 鍔熻兘锛氭墦寮鎸囧畾璺緞鐨勬枃浠 + * + * 鍙傛暟鍒楄〃锛 + * path锛氳鎵撳紑鐨勬枃浠惰矾寰 + * flag锛氭枃浠舵墦寮鏍囧織锛孫_RDONLY 琛ㄧず鍙锛屽叾浠栬〃绀哄叾浠栨搷浣 + */ int OBSConnector::openFile(const char *path, int flag) { + // 澹版槑 bucket 鍜 prefix 瀛楃涓叉寚閽堬紝骞跺垵濮嬪寲涓 NULL char *bucket = NULL; char *prefix = NULL; + // 閫氳繃 FetchUrlPropertiesForQuery 鍑芥暟鑾峰彇璺緞涓殑 bucket 鍜 prefix FetchUrlPropertiesForQuery(path, &bucket, &prefix); + // 璁剧疆瀛樺偍澶勭悊鍣ㄧ殑瀵硅薄淇℃伅鐨 key 涓 prefix m_handler->m_object_info.key = prefix; + + // 濡傛灉瀛樺偍澶勭悊鍣ㄧ殑閫夐」涓殑妗跺悕绉颁负绌猴紝灏嗗叾璁剧疆涓 bucket if (m_handler->m_option.bucket_options.bucket_name == NULL) m_handler->m_option.bucket_options.bucket_name = bucket; + // 鏍规嵁鎵撳紑鏍囧織璁剧疆瀛樺偍澶勭悊鍣ㄧ殑绫诲瀷涓鸿鍙栨垨鍐欏叆 if (flag == O_RDONLY) ObsReadWriteHandlerSetType(m_handler, OBS_READ); else ObsReadWriteHandlerSetType(m_handler, OBS_WRITE); + + // 杩斿洖 0锛岃〃绀烘墦寮鎴愬姛 return 0; } - +/* + * 鍔熻兘锛氬垹闄ゆ寚瀹氳矾寰勭殑鏂囦欢鎴栫洰褰 + * + * 鍙傛暟鍒楄〃锛 + * path锛氳鍒犻櫎鐨勬枃浠舵垨鐩綍鐨勮矾寰 + * recursive锛氶掑綊鍒犻櫎鏍囧織锛1 琛ㄧず閫掑綊鍒犻櫎锛0 琛ㄧず鍙垹闄ゆ寚瀹氭枃浠舵垨鐩綍 + * + * 杩斿洖鍊硷細 + * 0 琛ㄧず鍒犻櫎鎴愬姛锛屽叾浠栧艰〃绀哄垹闄ゅけ璐 + */ int OBSConnector::deleteFile(const char *path, int recursive) { int ret = 0; + // 璋冪敤 deleteOBSObject 鍑芥暟鍒犻櫎鎸囧畾璺緞鐨勬枃浠舵垨鐩綍锛屽苟灏嗙粨鏋滆祴缁 ret ret = deleteOBSObject(m_handler); + // 杩斿洖鍒犻櫎鎿嶄綔鐨勭粨鏋 return ret; } @@ -435,27 +512,57 @@ bool OBSConnector::existsFile(const char *path) return isExists; } - +/* + * 鍔熻兘锛氭鏌ユ槸鍚﹀瓨鍦ㄦ湁鏁堟枃浠 + * + * 杩斿洖鍊硷細 + * false 琛ㄧず涓嶅瓨鍦ㄦ湁鏁堟枃浠 + */ bool OBSConnector::hasValidFile() const { /* OBS_NOT_IMPLEMENT; */ return false; } - +/* + * 鍔熻兘锛氬皢鏁版嵁鍐欏叆褰撳墠鏂囦欢 + * + * 鍙傛暟鍒楄〃锛 + * buffer锛氳鍐欏叆鐨勬暟鎹殑缂撳啿鍖 + * length锛氳鍐欏叆鐨勬暟鎹殑闀垮害 + * + * 杩斿洖鍊硷細 + * 0 琛ㄧず鍐欏叆鎴愬姛锛屽叾浠栧艰〃绀哄啓鍏ュけ璐 + */ int OBSConnector::writeCurrentFile(const char *buffer, int length) { int ret = 0; + // 璋冪敤 writeObsTempFile 鍑芥暟灏嗘暟鎹啓鍏ュ綋鍓嶆枃浠讹紝骞跺皢缁撴灉璧嬬粰 ret ret = writeObsTempFile(m_handler, buffer, length); + + // 杩斿洖鍐欏叆鎿嶄綔鐨勭粨鏋 return ret; } - +/* + * 鍔熻兘锛氫粠褰撳墠鏂囦欢涓鍙栨暟鎹埌缂撳啿鍖猴紝鐩村埌璇诲彇鎸囧畾闀垮害鐨勬暟鎹垨杈惧埌鏂囦欢鏈熬 + * + * 鍙傛暟鍒楄〃锛 + * buffer锛氱敤浜庡瓨鍌ㄨ鍙栨暟鎹殑缂撳啿鍖 + * length锛氳璇诲彇鐨勬暟鎹殑闀垮害 + * offset锛氳鍙栨暟鎹殑璧峰鍋忕Щ閲忥紙鏈娇鐢級 + * + * 杩斿洖鍊硷細 + * 0 琛ㄧず鎴愬姛璇诲彇鎸囧畾闀垮害鐨勬暟鎹紝-1 琛ㄧず璇诲彇澶辫触鎴栬揪鍒版枃浠舵湯灏 + */ int OBSConnector::readCurrentFileFully(char *buffer, int length, int64 offset) { int ret = 0; + // 璋冪敤 read_bucket_object 鍑芥暟浠庡綋鍓嶆枃浠朵腑璇诲彇鏁版嵁鍒扮紦鍐插尯锛岃繑鍥炲凡璇诲彇鐨勬暟鎹暱搴 int readSize = (int)read_bucket_object(m_handler, buffer, length); + // 濡傛灉宸茶鍙栫殑鏁版嵁闀垮害涓嶇瓑浜庢寚瀹氱殑闀垮害锛屽皢杩斿洖鍊艰缃负-1锛岃〃绀鸿鍙栧け璐ユ垨杈惧埌鏂囦欢鏈熬 if (readSize != length) { ret = -1; } + // 杩斿洖璇诲彇鎿嶄綔鐨勭粨鏋 return ret; } @@ -533,19 +640,37 @@ OBSReadWriteHandler *OBSConnector::searchConnectorCache(Oid foreignTableId) return handler; } - +/* + * 鍔熻兘锛氬垱寤 OBS 璇诲啓澶勭悊绋嬪簭 + * + * 鍙傛暟鍒楄〃锛 + * obsOptions锛氬寘鍚 OBS 閰嶇疆淇℃伅鐨勯夐」缁撴瀯 + * + * 杩斿洖鍊硷細 + * 杩斿洖鏂板垱寤虹殑 OBS 璇诲啓澶勭悊绋嬪簭鐨勬寚閽 + */ OBSReadWriteHandler *OBSConnector::createRWHandler(ObsOptions *obsOptions) { + // 鍒囨崲鍐呭瓨涓婁笅鏂囧埌褰撳墠绫荤殑鍐呭瓨涓婁笅鏂 AutoContextSwitch memGuard(m_memcontext); OBSReadWriteHandler *handler = NULL; + // 鍒涘缓 OBS 璇诲啓澶勭悊绋嬪簭锛屽苟涓烘煡璇㈣繘琛岄厤缃 handler = CreateObsReadWriteHandlerForQuery(obsOptions); handler->in_computing = true; return handler; } - +/* + * 浠庣紦瀛樹腑鑾峰彇 OBS 杩炴帴閫夐」 + * + * 鍙傛暟鍒楄〃锛 + * foreignTableId锛氬閮ㄨ〃鐨 OID + * + * 杩斿洖鍊硷細 + * 杩斿洖 ObsOptions 缁撴瀯鐨勬寚閽堬紝鍖呭惈 OBS 杩炴帴閫夐」 + */ ObsOptions *OBSConnector::getOptionFromCache(Oid foreignTableId) { bool found = false; @@ -565,6 +690,7 @@ ObsOptions *OBSConnector::getOptionFromCache(Oid foreignTableId) if (found && (entry && entry->access_key != NULL && entry->secret_access_key != NULL && entry->address != NULL)) { GS_UINT32 outPutLen; ObsOptions *retOption = copyObsOptions(entry); + // 瑙g爜鍔犲瘑鐨勭瀵嗚闂瘑閽 pfree(retOption->secret_access_key); retOption->secret_access_key = SEC_decodeBase64(entry->secret_access_key, &outPutLen); return retOption; @@ -576,9 +702,11 @@ ObsOptions *OBSConnector::getOptionFromCache(Oid foreignTableId) /* Put the new connector info into the hash table. */ (void)LWLockAcquire(DfsConnectorCacheLock, LW_EXCLUSIVE); entry = (ObsOptions *)hash_search(OBSConnectorCache, (void *)&key, HASH_ENTER, &found); + // 濡傛灉鏈兘鎴愬姛娣诲姞鍒板搱甯岃〃锛屾姤閿 if (entry == NULL) ereport(PANIC, (errcode(ERRCODE_UNDEFINED_OBJECT), errmodule(MOD_OBS), errmsg("build global OBS connect cache hash table failed"))); + // 濡傛灉鍦ㄥ搱甯岃〃涓湭鎵惧埌杩炴帴閫夐」锛屽皢澶栭儴琛ㄧ殑閫夐」澶嶅埗鍒板搱甯岃〃涓 if (!found) { Assert(obsOptions != NULL); entry->address = obsOptions->address; @@ -591,6 +719,7 @@ ObsOptions *OBSConnector::getOptionFromCache(Oid foreignTableId) } LWLockRelease(DfsConnectorCacheLock); + // 杩斿洖杩炴帴閫夐」鐨勫壇鏈紝骞惰В鐮佸姞瀵嗙殑绉樺瘑璁块棶瀵嗛挜 ObsOptions *retOption = copyObsOptions(entry); GS_UINT32 outPutLen; pfree(retOption->secret_access_key); @@ -608,52 +737,82 @@ int OBSConnector::getType() { return (int)OBS_CONNECTOR; } - +/* + * 鍔熻兘锛氱敤浜庢暟鎹粨鏋勶紙濡傚搱甯岃〃鎴栨悳绱㈡爲锛変腑锛屼互甯姪纭畾鍏冪礌鐨勪綅缃垨鏌ユ壘鍏冪礌 + * 鍙傛暟璇存槑锛 + * key1锛氭寚鍚戠涓涓狾id鐨勬寚閽堛 + * key2锛氭寚鍚戠浜屼釜Oid鐨勬寚閽堛 + * keySize锛氳〃绀篛id鐨勫ぇ灏忥紝閫氬父鏄痵izeof(Oid)銆 + */ static int matchOid(const void *key1, const void *key2, Size keySize) { return (int)(*(Oid *)key1 - *(Oid *)key2); } - +/* + * 鍔熻兘锛氬垵濮嬪寲OBS杩炴帴鍣ㄧ紦瀛橀攣 + * + * 鏃犲弬鏁 + */ void InitOBSConnectorCacheLock() { - HASHCTL ctl; - errno_t rc = 0; + HASHCTL ctl; // 鍝堝笇琛ㄧ殑鎺у埗缁撴瀯 + errno_t rc = 0; // 閿欒鐮 if (OBSConnectorCache == NULL) { + // 娓呴浂鎺у埗缁撴瀯 rc = memset_s(&ctl, sizeof(ctl), 0, sizeof(ctl)); securec_check(rc, "\0", "\0"); - ctl.hcxt = g_instance.instance_context; - ctl.keysize = sizeof(Oid); - ctl.entrysize = sizeof(ObsOptions); - ctl.match = (HashCompareFunc)matchOid; - ctl.hash = (HashValueFunc)oid_hash; - OBSConnectorCache = hash_create("OBS connector cache", 50, &ctl, - HASH_ELEM | HASH_FUNCTION | HASH_COMPARE | HASH_SHRCTX); + ctl.hcxt = g_instance.instance_context; // 鍒嗛厤鍐呭瓨鐨勪笂涓嬫枃 + ctl.keysize = sizeof(Oid); // 閿殑澶у皬锛岄氬父鏄疧id鐨勫ぇ灏 + ctl.entrysize = sizeof(ObsOptions); // 鍝堝笇琛ㄤ腑姣忎釜鏉$洰鐨勫ぇ灏 + ctl.match = (HashCompareFunc)matchOid; // 鐢ㄤ簬姣旇緝閿殑鍑芥暟 + ctl.hash = (HashValueFunc)oid_hash; // 璁$畻鍝堝笇鍊肩殑鍑芥暟 + // 鍒涘缓鍝堝笇琛紝甯︽湁鎸囧畾鐨勬帶鍒堕夐」 + OBSConnectorCache = + hash_create("OBS connector cache", 50, &ctl, HASH_ELEM | HASH_FUNCTION | HASH_COMPARE | HASH_SHRCTX); + // 濡傛灉鍝堝笇琛ㄥ垱寤哄け璐ワ紝鍙戝嚭 PANIC 绾у埆鐨勯敊璇俊鎭 if (OBSConnectorCache == NULL) ereport(PANIC, (errmodule(MOD_HDFS), errmsg("could not initialize OBS connector hash table"))); } } - +/* + * 鍔熻兘锛氫娇 OBS 杩炴帴鍣ㄧ紦瀛樻棤鏁 + * + * 鍙傛暟鍒楄〃锛 + * serverOid锛氬閮ㄨ〃鎵鍦ㄧ殑鏈嶅姟鍣ㄧ殑瀵硅薄鏍囪瘑绗︼紙OID锛 + * + * 杩斿洖鍊硷細 + * 濡傛灉鎴愬姛娓呯悊缂撳瓨锛屽垯杩斿洖 true锛涘惁鍒欒繑鍥 false + */ bool InvalidOBSConnectorCache(Oid serverOid) { - bool realClean = false; + bool realClean = false; // 鐢ㄤ簬鏍囪鏄惁鐪熸娓呯悊浜嗙紦瀛 + // 鑾峰彇 DfsConnectorCacheLock 閿侊紝浠ョ嫭鍗犳ā寮 (void)LWLockAcquire(DfsConnectorCacheLock, LW_EXCLUSIVE); + // 鍦ㄥ搱甯岃〃 OBSConnectorCache 涓煡鎵惧苟绉婚櫎鎸囧畾鐨勯敭锛坰erverOid锛 ObsOptions *entry = (ObsOptions *)hash_search(OBSConnectorCache, (void *)&serverOid, HASH_REMOVE, NULL); + // 濡傛灉鎵惧埌浜嗘寚瀹氱殑閿紙entry 涓嶄负 NULL锛夛紝鍒欒繘琛屾竻鐞嗘搷浣 if (entry != NULL) { + // 濡傛灉 access_key 涓嶄负 NULL锛岄噴鏀惧叾鍐呭瓨 if (entry->access_key != NULL) { pfree_ext(entry->access_key); } + // 濡傛灉 secret_access_key 涓嶄负 NULL锛屼娇鐢 OPENSSL_free 閲婃斁鍏跺唴瀛橈紝骞跺皢鍏剁疆涓 NULL if (entry->secret_access_key != NULL) { OPENSSL_free(entry->secret_access_key); entry->secret_access_key = NULL; } + // 濡傛灉 address 涓嶄负 NULL锛岄噴鏀惧叾鍐呭瓨 if (entry->address != NULL) { pfree_ext(entry->address); } + // 鏍囪宸茬粡鎴愬姛娓呯悊缂撳瓨 realClean = true; } + // 閲婃斁 DfsConnectorCacheLock 閿 LWLockRelease(DfsConnectorCacheLock); + // 杩斿洖鏄惁鎴愬姛娓呯悊缂撳瓨鐨勬爣蹇 return realClean; } } // namespace dfs diff --git a/src/gausskernel/storage/dorado_operation/dorado_fd.cpp b/src/gausskernel/storage/dorado_operation/dorado_fd.cpp index 9a075d771..fbfd04698 100644 --- a/src/gausskernel/storage/dorado_operation/dorado_fd.cpp +++ b/src/gausskernel/storage/dorado_operation/dorado_fd.cpp @@ -34,58 +34,96 @@ void DoradoReadCtlInfo(ShareStorageXLogCtl *ctlInfo); int DoradoWriteXLog(XLogRecPtr startLsn, char *buf, int writeLen); int DoradoReadXLog(XLogRecPtr startLsn, char *buf, int expectReadLen); void DoradoFsync(); - +/* + * 鍔熻兘锛氬畾涔変竴涓潤鎬佸父閲忕粨鏋勪綋锛屽苟鍒濆鍖栧叾鎴愬憳鍑芥暟鎸囬拡 + */ static const ShareStorageOperateIf doradoOperateIf = { DoradoReadCtlInfo, DoradoWriteCtlInfo, DoradoReadXLog, DoradoWriteXLog, DoradoFsync, }; - +/* + * 鍔熻兘锛氳绠 Xlog 浣嶇疆 + * + * 鍙傛暟鍒楄〃锛 + * expect锛氳〃绀烘湡鏈涚殑 Xlog 浣嶇疆 + */ static inline uint64 GetXlogPos(uint64 expect) { + // 璁$畻 Xlog 浣嶇疆锛岄氳繃灏嗘湡鏈涚殑浣嶇疆鍔犱笂甯搁噺 DORADO_XLOG_START_POS 寰楀埌 return (expect + DORADO_XLOG_START_POS); } - +/* + * 鍔熻兘锛氬垵濮嬪寲 Dorado 瀛樺偍 + * + * 鍙傛暟鍒楄〃锛 + * filePath锛歑log 鏂囦欢鐨勮矾寰 + * fileSize锛歑log 鏂囦欢鐨勫ぇ灏 + */ void InitDoradoStorage(char *filePath, uint64 fileSize) { + // 鏂█纭繚鍏变韩瀛樺偍鎿嶄綔鎺у埗鍧楁病鏈夎鍒濆鍖 Assert(!g_instance.xlog_cxt.shareStorageopCtl.isInit); + // 璁剧疆 Xlog 鏂囦欢璺緞涓轰紶鍏ョ殑 filePath g_instance.xlog_cxt.shareStorageopCtl.xlogFilePath = filePath; - + + // 璁剧疆鍧楀ぇ灏忎负 MEMORY_ALIGNED_SIZE锛堜竴涓父閲忥級 g_instance.xlog_cxt.shareStorageopCtl.blkSize = MEMORY_ALIGNED_SIZE; + // 璁剧疆鎿嶄綔鎺ュ彛涓 doradoOperateIf锛堜箣鍓嶅畾涔夌殑缁撴瀯浣擄級 g_instance.xlog_cxt.shareStorageopCtl.opereateIf = &doradoOperateIf; + // 瑙勮寖鍖栨枃浠惰矾寰勶紝纭繚瀹冩槸缁濆璺緞 canonicalize_path(filePath); + // 鎵撳紑 Xlog 鏂囦欢锛屼互璇诲啓鏂瑰紡鎵撳紑锛屼簩杩涘埗妯″紡锛屼娇鐢 O_DIRECT 鏍囧織 + // S_IRUSR | S_IWUSR 琛ㄧず鏂囦欢鏉冮檺锛孲_IRUSR 琛ㄧず鐢ㄦ埛鏈夎鏉冮檺锛孲_IWUSR 琛ㄧず鐢ㄦ埛鏈夊啓鏉冮檺 g_instance.xlog_cxt.shareStorageopCtl.fd = open(filePath, O_RDWR | PG_BINARY | O_DIRECT, S_IRUSR | S_IWUSR); + // 濡傛灉鏂囦欢鎵撳紑澶辫触锛屾姤鍛婇敊璇苟涓旂粓姝㈢▼搴忥紙PANIC锛 if (g_instance.xlog_cxt.shareStorageopCtl.fd < 0) { ereport(PANIC, (errcode_for_file_access(), errmsg("could not open xlog file \"%s\" : %m", filePath))); } + // 璁剧疆鍏变韩瀛樺偍鎿嶄綔鎺у埗鍧楃殑鍒濆鍖栨爣蹇椾负 true g_instance.xlog_cxt.shareStorageopCtl.isInit = true; + // 濡傛灉姝e湪杩涜鏁版嵁搴撳垵濮嬪寲锛圛sInitdb 涓虹湡锛夛紝璁剧疆 Xlog 鏂囦欢澶у皬涓轰紶鍏ョ殑 fileSize if (IsInitdb) { g_instance.xlog_cxt.shareStorageopCtl.xlogFileSize = fileSize; } else { + // 鍚﹀垯锛屽鏋滀笉鏄垵濮嬪寲鏁版嵁搴擄紝鏂█纭繚鍏变韩瀛樺偍 XLog 鎺у埗鍧椾笉涓虹┖ Assert(g_instance.xlog_cxt.shareStorageXLogCtl != NULL); + // 璋冪敤 DoradoReadCtlInfo 鍑芥暟璇诲彇鍏变韩瀛樺偍 XLog 鎺у埗鍧楃殑淇℃伅锛屽苟璁剧疆 Xlog 鏂囦欢澶у皬 DoradoReadCtlInfo(g_instance.xlog_cxt.shareStorageXLogCtl); g_instance.xlog_cxt.shareStorageopCtl.xlogFileSize = g_instance.xlog_cxt.shareStorageXLogCtl->xlogFileSize; } } - +/* + * 鍔熻兘锛氬皢鍏变韩瀛樺偍鎺у埗淇℃伅鍐欏叆鏂囦欢 + * + * 鍙傛暟鍒楄〃锛 + * ctlInfo锛氬叡浜瓨鍌 XLog 鎺у埗鍧楃殑鎸囬拡 + */ void DoradoWriteCtlInfo(const ShareStorageXLogCtl *ctlInfo) { + // 鏂█纭繚鏂囦欢鎻忚堪绗﹀ぇ浜 0锛屽嵆鏂囦欢宸茬粡鎴愬姛鎵撳紑 Assert(g_instance.xlog_cxt.shareStorageopCtl.fd > 0); + // 妫鏌ュ叡浜瓨鍌ㄥ潡澶у皬鏄惁涓庢帶鍒跺潡澶у皬瀵归綈锛屽鏋滀笉瀵归綈锛屾姤鍛婇敊璇苟缁堟绋嬪簭 if (!IS_TYPE_ALIGINED(g_instance.xlog_cxt.shareStorageopCtl.blkSize, ctlInfo)) { ereport(PANIC, (errcode_for_file_access(), errmsg("dorado write control info ptr(%p) is not match,mask is %X", ctlInfo, g_instance.xlog_cxt.shareStorageopCtl.blkSize))); } + // 妫鏌ユ帶鍒跺潡鐨勯瓟鏁板拰妫楠岀爜鏄惁鍖归厤锛屽鏋滀笉鍖归厤锛屾姤鍛婅嚧鍛介敊璇 if (ctlInfo->magic != SHARE_STORAGE_CTL_MAGIC || ctlInfo->checkNumber != SHARE_STORAGE_CTL_CHCK_NUMBER) { ereport(FATAL, (errmsg("ShareStorageXLogCtl info in memory maybe damaged"))); } + // 璁$畻鎺у埗鍧楃殑 CRC 鏍¢獙鍊 pg_crc32c crc = CalShareStorageCtlInfoCrc(ctlInfo); + // 妫鏌ヨ绠楀緱鍒扮殑 CRC 鏄惁涓庢帶鍒跺潡涓殑 CRC 鐩稿尮閰嶏紝濡傛灉涓嶅尮閰嶏紝鎶ュ憡鑷村懡閿欒 if (!EQ_CRC32C(crc, ctlInfo->crc)) { ereport(FATAL, (errmsg("crc check fail for ShareStorageXLogCtl in DoradoWriteCtlInfo"))); } // write 512bytes + // 浣跨敤 pwrite 鍑芥暟灏嗘帶鍒跺潡鍐欏叆鏂囦欢锛屽啓鍏ュぇ灏忎负 DORADO_CTL_WRITE_SIZE 瀛楄妭锛屽亸绉婚噺涓 0 ssize_t actualBytes = pwrite(g_instance.xlog_cxt.shareStorageopCtl.fd, ctlInfo, DORADO_CTL_WRITE_SIZE, 0); + // 妫鏌ュ疄闄呭啓鍏ョ殑瀛楄妭鏁版槸鍚︿笌鏈熸湜鐨勫瓧鑺傛暟鐩稿尮閰嶏紝濡傛灉涓嶅尮閰嶏紝鎶ュ憡閿欒 if (actualBytes != (ssize_t)DORADO_CTL_WRITE_SIZE) { /* if write didn't set errno, assume no disk space */ if (errno == 0) { @@ -97,41 +135,68 @@ void DoradoWriteCtlInfo(const ShareStorageXLogCtl *ctlInfo) (unsigned long)actualBytes, (unsigned long)DORADO_CTL_WRITE_SIZE))); } } - +/* + * 鍔熻兘锛氫粠鏂囦欢涓鍙栧叡浜瓨鍌ㄦ帶鍒朵俊鎭 + * + * 鍙傛暟鍒楄〃锛 + * ctlInfo锛氬叡浜瓨鍌 XLog 鎺у埗鍧楃殑鎸囬拡 + */ void DoradoReadCtlInfo(ShareStorageXLogCtl *ctlInfo) { + // 鏂█纭繚鏂囦欢鎻忚堪绗﹀ぇ浜 0锛屽嵆鏂囦欢宸茬粡鎴愬姛鎵撳紑 Assert(g_instance.xlog_cxt.shareStorageopCtl.fd > 0); + // 妫鏌ュ叡浜瓨鍌ㄥ潡澶у皬鏄惁涓庢帶鍒跺潡澶у皬瀵归綈锛屽鏋滀笉瀵归綈锛屾姤鍛婇敊璇苟缁堟绋嬪簭 if (!IS_TYPE_ALIGINED(g_instance.xlog_cxt.shareStorageopCtl.blkSize, ctlInfo)) { ereport(PANIC, (errcode_for_file_access(), errmsg("dorado read control info ptr(%p) is not match,mask is %X", ctlInfo, g_instance.xlog_cxt.shareStorageopCtl.blkSize))); } + // 浣跨敤 pread 鍑芥暟浠庡凡鎵撳紑鐨勬枃浠朵腑璇诲彇鎺у埗鍧椾俊鎭紝璇诲彇澶у皬涓 DORADO_CTL_WRITE_SIZE 瀛楄妭锛屽亸绉婚噺涓 0 ssize_t actualBytes = pread(g_instance.xlog_cxt.shareStorageopCtl.fd, ctlInfo, DORADO_CTL_WRITE_SIZE, 0); + // 妫鏌ュ疄闄呰鍙栫殑瀛楄妭鏁版槸鍚︿笌鏈熸湜鐨勫瓧鑺傛暟鐩稿尮閰嶏紝濡傛灉涓嶅尮閰嶏紝鎶ュ憡閿欒骞剁粓姝㈢▼搴 if (actualBytes != (ssize_t)DORADO_CTL_WRITE_SIZE) { ereport(PANIC, (errcode_for_file_access(), errmsg("could not read dorado ctl info: %m"))); } + // 妫鏌ユ帶鍒跺潡鐨勯瓟鏁板拰妫楠岀爜鏄惁鍖归厤锛屽鏋滀笉鍖归厤锛屾姤鍛婅嚧鍛介敊璇 if (ctlInfo->magic != SHARE_STORAGE_CTL_MAGIC || ctlInfo->checkNumber != SHARE_STORAGE_CTL_CHCK_NUMBER) { ereport(FATAL, (errmsg("dorado ctl info maybe damaged"))); } + // 璁$畻鎺у埗鍧楃殑 CRC 鏍¢獙鍊 pg_crc32c crc = CalShareStorageCtlInfoCrc(ctlInfo); + // 妫鏌ヨ绠楀緱鍒扮殑 CRC 鏄惁涓庢帶鍒跺潡涓殑 CRC 鐩稿尮閰嶏紝濡傛灉涓嶅尮閰嶏紝鎶ュ憡鑷村懡閿欒 if (!EQ_CRC32C(crc, ctlInfo->crc)) { ereport(FATAL, (errmsg("crc check fail for ShareStorageXLogCtl in DoradoReadCtlInfo"))); } } - +/* + * 鍔熻兘锛氫粠鏂囦欢涓鍙 XLog 鏁版嵁 + * + * 鍙傛暟鍒楄〃锛 + * startLsn锛氬紑濮嬭鍙栫殑 XLog 璁板綍浣嶇疆 + * buf锛氱敤浜庡瓨鍌ㄨ鍙栨暟鎹殑缂撳啿鍖 + * expectReadLen锛氭湡鏈涜鍙栫殑鏁版嵁闀垮害 + * + * 杩斿洖鍊硷細鎴愬姛璇诲彇鐨勫瓧鑺傛暟锛屾垨鑰呴敊璇椂杩斿洖璐熷 + */ int DoradoReadXLog(XLogRecPtr startLsn, char *buf, int expectReadLen) { + // 鏂█纭繚鏂囦欢鎻忚堪绗﹀ぇ浜 0锛屽嵆鏂囦欢宸茬粡鎴愬姛鎵撳紑 Assert(g_instance.xlog_cxt.shareStorageopCtl.fd > 0); + // 妫鏌ュ叡浜瓨鍌ㄥ潡澶у皬鏄惁涓庣紦鍐插尯澶у皬瀵归綈锛屽鏋滀笉瀵归綈锛屾姤鍛婇敊璇苟缁堟绋嬪簭 if (!IS_TYPE_ALIGINED(g_instance.xlog_cxt.shareStorageopCtl.blkSize, buf)) { ereport(PANIC, (errcode_for_file_access(), errmsg("dorado read xlog ptr(%p) is not match,mask is %X", buf, g_instance.xlog_cxt.shareStorageopCtl.blkSize))); } + // 璁$畻璧峰浣嶇疆锛屽嵆 startLsn 瀵 XLog 鏂囦欢澶у皬鍙栨ā uint64 startPos = startLsn % g_instance.xlog_cxt.shareStorageopCtl.xlogFileSize; + // 濡傛灉鏈熸湜璇诲彇鐨勬暟鎹笉浼氳秴杩囨枃浠舵湯灏 if ((startPos + expectReadLen) <= g_instance.xlog_cxt.shareStorageopCtl.xlogFileSize) { + // 浣跨敤 pread 鍑芥暟浠庡凡鎵撳紑鐨勬枃浠朵腑璇诲彇鏁版嵁锛岃鍙栧ぇ灏忎负 expectReadLen 瀛楄妭锛岃捣濮嬩綅缃负 GetXlogPos(startPos) ssize_t actualBytes = pread(g_instance.xlog_cxt.shareStorageopCtl.fd, buf, expectReadLen, GetXlogPos(startPos)); + // 濡傛灉璇诲彇澶辫触锛屾姤鍛婇敊璇苟缁堟绋嬪簭 if (actualBytes < 0) { uint32 shiftSize = 32; ereport(PANIC, (errcode_for_file_access(), errmsg("read xlog(start:%X/%X, pos:%lu len:%d) failed : %m", @@ -139,11 +204,16 @@ int DoradoReadXLog(XLogRecPtr startLsn, char *buf, int expectReadLen) static_cast(startLsn), startPos, expectReadLen))); } + // 杩斿洖鎴愬姛璇诲彇鐨勫瓧鑺傛暟 return static_cast(actualBytes); - } else { + } else { // 濡傛灉鏈熸湜璇诲彇鐨勬暟鎹細瓒呰繃鏂囦欢鏈熬锛岄渶瑕佸垎涓ゆ璇诲彇 + // 绗竴娆¤鍙栫殑澶у皬锛屼粠 startPos 鍒版枃浠舵湯灏 int firstReadSize = g_instance.xlog_cxt.shareStorageopCtl.xlogFileSize - startPos; + // 绗簩娆¤鍙栫殑澶у皬锛屽墿浣欓儴鍒 int secondReadSize = expectReadLen - firstReadSize; + // 绗竴娆¤鍙栨暟鎹紝璧峰浣嶇疆涓 GetXlogPos(startPos) ssize_t actualBytes = pread(g_instance.xlog_cxt.shareStorageopCtl.fd, buf, firstReadSize, GetXlogPos(startPos)); + // 濡傛灉绗竴娆¤鍙栧け璐ワ紝鎶ュ憡閿欒骞剁粓姝㈢▼搴 if (actualBytes < 0) { uint32 shiftSize = 32; ereport(PANIC, (errcode_for_file_access(), errmsg("first read xlog(start:%X/%X, pos:%lu len:%d) failed:%m", @@ -151,11 +221,14 @@ int DoradoReadXLog(XLogRecPtr startLsn, char *buf, int expectReadLen) static_cast(startLsn), startPos, firstReadSize))); } + // 濡傛灉绗竴娆¤鍙栫殑瀛楄妭鏁颁笉瓒筹紝杩斿洖瀹為檯璇诲彇鐨勫瓧鑺傛暟 if (actualBytes < firstReadSize) { return static_cast(actualBytes); } + // 绗簩娆¤鍙栨暟鎹紝璧峰浣嶇疆涓 GetXlogPos(0) actualBytes = pread(t_thrd.xlog_cxt.openLogFile, buf + firstReadSize, secondReadSize, GetXlogPos(0)); + // 濡傛灉绗簩娆¤鍙栧け璐ワ紝鎶ュ憡閿欒骞剁粓姝㈢▼搴 if (actualBytes < 0) { uint32 shiftSize = 32; XLogRecPtr nextStartLsn = startLsn + firstReadSize; @@ -164,23 +237,40 @@ int DoradoReadXLog(XLogRecPtr startLsn, char *buf, int expectReadLen) static_cast(nextStartLsn), secondReadSize))); } + // 杩斿洖鎴愬姛璇诲彇鐨勫瓧鑺傛暟锛屽寘鎷涓娆″拰绗簩娆¤鍙栫殑閮ㄥ垎 return static_cast(actualBytes + firstReadSize); } } - +/* + * 鍔熻兘锛氬悜鏂囦欢涓啓鍏 XLog 鏁版嵁 + * + * 鍙傛暟鍒楄〃锛 + * startLsn锛氳鍐欏叆鐨 XLog 璁板綍鐨勮捣濮嬩綅缃 + * buf锛氬寘鍚鍐欏叆鐨勬暟鎹殑缂撳啿鍖 + * writeLen锛氳鍐欏叆鐨勬暟鎹暱搴 + * + * 杩斿洖鍊硷細鎴愬姛鍐欏叆鐨勬暟鎹暱搴︼紝鎴栬呴敊璇椂杩斿洖璐熷 + */ int DoradoWriteXLog(XLogRecPtr startLsn, char *buf, int writeLen) { + // 鏂█纭繚鏂囦欢鎻忚堪绗﹀ぇ浜 0锛屽嵆鏂囦欢宸茬粡鎴愬姛鎵撳紑 Assert(g_instance.xlog_cxt.shareStorageopCtl.fd > 0); + // 璁$畻璧峰浣嶇疆锛屽嵆 startLsn 瀵 XLog 鏂囦欢澶у皬鍙栨ā uint64 startPos = startLsn % g_instance.xlog_cxt.shareStorageopCtl.xlogFileSize; + // 妫鏌ュ叡浜瓨鍌ㄥ潡澶у皬鏄惁涓庣紦鍐插尯澶у皬瀵归綈锛屽鏋滀笉瀵归綈锛屾姤鍛婇敊璇苟缁堟绋嬪簭 if (!IS_TYPE_ALIGINED(g_instance.xlog_cxt.shareStorageopCtl.blkSize, buf)) { ereport(PANIC, (errcode_for_file_access(), errmsg("dorado write xlog ptr(%p) is not match,mask is %X", buf, g_instance.xlog_cxt.shareStorageopCtl.blkSize))); } + // 濡傛灉鍐欏叆鐨勬暟鎹笉浼氳秴杩囨枃浠舵湯灏 if ((startPos + writeLen) <= g_instance.xlog_cxt.shareStorageopCtl.xlogFileSize) { + // 浣跨敤 pwrite 鍑芥暟鍚戝凡鎵撳紑鐨勬枃浠朵腑鍐欏叆鏁版嵁锛屽啓鍏ュぇ灏忎负 writeLen 瀛楄妭锛岃捣濮嬩綅缃负 GetXlogPos(startPos) ssize_t actualBytes = pwrite(g_instance.xlog_cxt.shareStorageopCtl.fd, buf, writeLen, GetXlogPos(startPos)); + // 濡傛灉鍐欏叆鐨勫瓧鑺傛暟涓嶇瓑浜庢湡鏈涚殑瀛楄妭鏁帮紝鎶ュ憡閿欒骞剁粓姝㈢▼搴 if (actualBytes != writeLen) { + // 濡傛灉鍐欏叆鏈缃 errno锛屽亣瀹氭槸纾佺洏绌洪棿涓嶈冻 if (errno == 0) { errno = ENOSPC; } @@ -190,13 +280,18 @@ int DoradoWriteXLog(XLogRecPtr startLsn, char *buf, int writeLen) static_cast(startLsn >> shiftSize), static_cast(startLsn), startPos, writeLen))); } - } else { + } else { // 濡傛灉鍐欏叆鐨勬暟鎹細瓒呰繃鏂囦欢鏈熬锛岄渶瑕佸垎涓ゆ鍐欏叆 + // 绗竴娆″啓鍏ョ殑澶у皬锛屼粠 startPos 鍒版枃浠舵湯灏 int firstWriteSize = g_instance.xlog_cxt.shareStorageopCtl.xlogFileSize - startPos; + // 绗簩娆″啓鍏ョ殑澶у皬锛屽墿浣欓儴鍒 int secondWriteSize = writeLen - firstWriteSize; - ssize_t actualBytes = pwrite(g_instance.xlog_cxt.shareStorageopCtl.fd, buf, firstWriteSize, - GetXlogPos(startPos)); + // 绗竴娆″啓鍏ユ暟鎹紝璧峰浣嶇疆涓 GetXlogPos(startPos) + ssize_t actualBytes = + pwrite(g_instance.xlog_cxt.shareStorageopCtl.fd, buf, firstWriteSize, GetXlogPos(startPos)); + // 濡傛灉绗竴娆″啓鍏ョ殑瀛楄妭鏁颁笉绛変簬绗竴娆″啓鍏ョ殑澶у皬锛屾姤鍛婇敊璇苟缁堟绋嬪簭 if (actualBytes != firstWriteSize) { + // 濡傛灉鍐欏叆鏈缃 errno锛屽亣瀹氭槸纾佺洏绌洪棿涓嶈冻 if (errno == 0) { errno = ENOSPC; } @@ -207,9 +302,12 @@ int DoradoWriteXLog(XLogRecPtr startLsn, char *buf, int writeLen) static_cast(startLsn), startPos, firstWriteSize))); } - actualBytes = pwrite(g_instance.xlog_cxt.shareStorageopCtl.fd, buf + firstWriteSize, secondWriteSize, - GetXlogPos(0)); + // 绗簩娆″啓鍏ユ暟鎹紝璧峰浣嶇疆涓 GetXlogPos(0) + actualBytes = + pwrite(g_instance.xlog_cxt.shareStorageopCtl.fd, buf + firstWriteSize, secondWriteSize, GetXlogPos(0)); + // 濡傛灉绗簩娆″啓鍏ョ殑瀛楄妭鏁颁笉绛変簬绗簩娆″啓鍏ョ殑澶у皬锛屾姤鍛婇敊璇苟缁堟绋嬪簭 if (actualBytes != secondWriteSize) { + // 濡傛灉鍐欏叆鏈缃 errno锛屽亣瀹氭槸纾佺洏绌洪棿涓嶈冻 if (errno == 0) { errno = ENOSPC; } @@ -222,12 +320,20 @@ int DoradoWriteXLog(XLogRecPtr startLsn, char *buf, int writeLen) } } + // 杩斿洖鎴愬姛鍐欏叆鐨勬暟鎹暱搴 return writeLen; } +/* + * 鍔熻兘锛氬皢鍏变韩瀛樺偍鏂囦欢鐨勬暟鎹悓姝ュ埌纾佺洏 + */ + void DoradoFsync() { + // 鏂█纭繚鏂囦欢鎻忚堪绗﹀ぇ浜 0锛屽嵆鏂囦欢宸茬粡鎴愬姛鎵撳紑 Assert(g_instance.xlog_cxt.shareStorageopCtl.fd > 0); + + // 浣跨敤 fsync 鍑芥暟灏嗗叡浜瓨鍌ㄦ枃浠剁殑鏁版嵁鍚屾鍒扮鐩 if (fsync(g_instance.xlog_cxt.shareStorageopCtl.fd) != 0) { ereport(PANIC, (errcode_for_file_access(), errmsg("could not fsync dorado file %s: %m", g_instance.xlog_cxt.shareStorageopCtl.xlogFilePath))); diff --git a/src/gausskernel/storage/mot/core/concurrency_control/occ_transaction_manager.cpp b/src/gausskernel/storage/mot/core/concurrency_control/occ_transaction_manager.cpp index 80c70babf..14eefc2ec 100644 --- a/src/gausskernel/storage/mot/core/concurrency_control/occ_transaction_manager.cpp +++ b/src/gausskernel/storage/mot/core/concurrency_control/occ_transaction_manager.cpp @@ -54,20 +54,55 @@ OccTransactionManager::OccTransactionManager() OccTransactionManager::~OccTransactionManager() {} +/* + * 鍔熻兘锛氬垵濮嬪寲浜嬪姟绠$悊鍣 + * + * 杩斿洖鍊硷細 + * 濡傛灉鎴愬姛鍒濆鍖栦簨鍔$鐞嗗櫒锛岃繑鍥 true锛涘惁鍒欒繑鍥 false銆 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庡垵濮嬪寲浜嬪姟绠$悊鍣ㄧ殑鐘舵佸拰灞炴э紝浣嗗綋鍓嶇増鏈皻鏈墽琛屽叿浣撶殑鍒濆鍖栨搷浣溿 + * 鍦ㄥ皢鏉ョ殑鐗堟湰涓紝搴旀牴鎹渶姹傛坊鍔犳洿澶氱殑鍒濆鍖栦唬鐮併 + */ bool OccTransactionManager::Init() { - bool result = true; - return result; + bool result = true; // 鍒涘缓涓涓悕涓 result 鐨勫竷灏斿彉閲忓苟鍒濆鍖栦负 true銆 + + return result; // 杩斿洖 result 鍙橀噺鐨勫硷紝杩欓噷濮嬬粓杩斿洖 true銆 } -bool OccTransactionManager::CheckVersion(const Access* access) +/* + * 鍔熻兘锛氭鏌ヤ簨鍔$増鏈 + * + * 鍙傛暟鍒楄〃锛 + * access锛氳闂璞℃寚閽堬紝鍖呭惈瑕佹鏌ョ殑浜嬪姟淇℃伅 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庢鏌ョ粰瀹氫簨鍔℃槸鍚︿笌璁块棶瀵硅薄涓殑浜嬪姟ID鍖归厤銆傞氬父鐢ㄤ簬楠岃瘉宸叉彁浜ょ殑琛岀殑鐗堟湰銆 + * 濡傛灉浜嬪姟鐗堟湰鍖归厤锛岃繑鍥 true锛屽惁鍒欒繑鍥 false銆 + */ +bool OccTransactionManager::CheckVersion(const Access *access) { // We always validate on committed rows! - const Row* row = access->GetRowFromHeader(); + const Row *row = access->GetRowFromHeader(); + + // 妫鏌ヨ鐨勪簨鍔″簭鍒楀彿锛圕SN锛夋槸鍚︿笌璁块棶瀵硅薄涓殑浜嬪姟ID锛圱ID锛夊尮閰 return (row->m_rowHeader.GetCSN() == access->m_tid); } - -bool OccTransactionManager::QuickHeaderValidation(const Access* access) +/* + * 鍔熻兘锛氬揩閫熼獙璇佷簨鍔″ご淇℃伅 + * + * 鍙傛暟鍒楄〃锛 + * access锛氳闂璞℃寚閽堬紝鍖呭惈瑕侀獙璇佺殑浜嬪姟澶翠俊鎭 + * + * 杩斿洖鍊硷細 + * 濡傛灉浜嬪姟澶翠俊鎭獙璇侀氳繃锛岃繑鍥 true锛涘惁鍒欒繑鍥 false銆 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庡揩閫熼獙璇佽闂璞′腑鐨勪簨鍔″ご淇℃伅锛屼互鍐冲畾鏄惁鍙互缁х画澶勭悊浜嬪姟銆 + * 鍏蜂綋楠岃瘉閫昏緫鍖呮嫭妫鏌ユ搷浣滅被鍨嬨佷簨鍔$増鏈拰鍏朵粬鏉′欢锛屾牴鎹笉鍚岀殑鎯呭喌杩涜楠岃瘉銆 + */ +bool OccTransactionManager::QuickHeaderValidation(const Access *access) { if (access->m_type != INS) { // For WR/DEL/RD_FOR_UPDATE lets verify CSN @@ -76,7 +111,7 @@ bool OccTransactionManager::QuickHeaderValidation(const Access* access) // Lets verify the inserts // For upgrade we verify the row // csn has not changed! - Sentinel* sent = access->m_origSentinel; + Sentinel *sent = access->m_origSentinel; if (access->m_params.IsUpgradeInsert()) { if (access->m_params.IsDummyDeletedRow()) { // Check is sentinel is deleted and CSN is VALID - ABA problem @@ -104,78 +139,144 @@ bool OccTransactionManager::QuickHeaderValidation(const Access* access) return true; } -bool OccTransactionManager::ValidateReadSet(TxnManager* txMan) +/* + * 鍔熻兘锛氶獙璇佽鍙栭泦鍚 + * + * 鍙傛暟鍒楄〃锛 + * txMan锛氫簨鍔$鐞嗗櫒鎸囬拡锛屽寘鍚緟楠岃瘉鐨勮鍙栭泦鍚 + * + * 杩斿洖鍊硷細 + * 濡傛灉璇诲彇闆嗗悎涓殑鎵鏈夎鍙栨搷浣滈兘楠岃瘉閫氳繃锛岃繑鍥瀟rue锛涘惁鍒欒繑鍥瀎alse銆 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庨獙璇佷簨鍔$殑璇诲彇闆嗗悎涓殑璇诲彇鎿嶄綔鏄惁鏈夋晥銆 + * 瀹冮亶鍘嗘湁搴忕殑璁块棶闆嗗悎锛屽姣忎釜璇诲彇鎿嶄綔妫鏌ユ槸鍚︽湁鏁堛 + * 濡傛灉鎵鏈夎鍙栨搷浣滈兘楠岃瘉閫氳繃锛岃繑鍥瀟rue锛屽惁鍒欒繑鍥瀎alse銆 + */ +bool OccTransactionManager::ValidateReadSet(TxnManager *txMan) { - TxnOrderedSet_t& orderedSet = txMan->m_accessMgr->GetOrderedRowSet(); - for (const auto& raPair : orderedSet) { - const Access* ac = raPair.second; + TxnOrderedSet_t &orderedSet = txMan->m_accessMgr->GetOrderedRowSet(); + for (const auto &raPair : orderedSet) { + const Access *ac = raPair.second; if (ac->m_type != RD) { continue; } + // 楠岃瘉璇诲彇鎿嶄綔鐨勬湁鏁堟 if (!ac->GetRowFromHeader()->m_rowHeader.ValidateRead(ac->m_tid)) { return false; } } - return true; } -bool OccTransactionManager::ValidateWriteSet(TxnManager* txMan) +/* + * 鍔熻兘锛氶獙璇佸啓鍏ラ泦鍚 + * + * 鍙傛暟鍒楄〃锛 + * txMan锛氫簨鍔$鐞嗗櫒鎸囬拡锛屽寘鍚緟楠岃瘉鐨勫啓鍏ラ泦鍚 + * + * 杩斿洖鍊硷細 + * 濡傛灉鍐欏叆闆嗗悎涓殑鎵鏈夊啓鍏ユ搷浣滈兘楠岃瘉閫氳繃锛岃繑鍥瀟rue锛涘惁鍒欒繑鍥瀎alse銆 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庨獙璇佷簨鍔$殑鍐欏叆闆嗗悎涓殑鍐欏叆鎿嶄綔鏄惁鏈夋晥銆 + * 瀹冮亶鍘嗘湁搴忕殑璁块棶闆嗗悎锛屽姣忎釜鍐欏叆鎿嶄綔鎵ц蹇熼獙璇併 + * 濡傛灉鎵鏈夊啓鍏ユ搷浣滈兘楠岃瘉閫氳繃锛岃繑鍥瀟rue锛屽惁鍒欒繑鍥瀎alse銆 + */ +bool OccTransactionManager::ValidateWriteSet(TxnManager *txMan) { - TxnOrderedSet_t& orderedSet = txMan->m_accessMgr->GetOrderedRowSet(); - for (const auto& raPair : orderedSet) { - const Access* ac = raPair.second; + TxnOrderedSet_t &orderedSet = txMan->m_accessMgr->GetOrderedRowSet(); + for (const auto &raPair : orderedSet) { + const Access *ac = raPair.second; if (ac->m_type == RD) { continue; } - + // 鎵ц蹇熼獙璇 if (!QuickHeaderValidation(ac)) { return false; } } return true; } - -RC OccTransactionManager::LockRows(TxnManager* txMan, uint32_t& numRowsLock) +/* + * 鍔熻兘锛氶攣瀹氳 + * + * 鍙傛暟鍒楄〃锛 + * txMan锛氫簨鍔$鐞嗗櫒鎸囬拡锛屽寘鍚緟閿佸畾鐨勮 + * numRowsLock锛氱敤浜庡瓨鍌ㄩ攣瀹氱殑琛屾暟鐨勫紩鐢 + * + * 杩斿洖鍊硷細 + * 杩斿洖鎿嶄綔缁撴灉鐨勪唬鐮 (RC)锛岄氬父鏄 RC_OK 琛ㄧず鎴愬姛銆 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庨攣瀹氫簨鍔′腑闇瑕佷慨鏀圭殑琛屻 + * 瀹冮亶鍘嗘湁搴忕殑璁块棶闆嗗悎锛屽姣忎釜闇瑕侀攣瀹氱殑琛屾墽琛岄攣瀹氭搷浣溿 + * 鍦ㄩ攣瀹氳鍚庯紝浼氬皢閿佸畾鐨勮鏁板瓨鍌ㄥ湪 numRowsLock 寮曠敤涓紝骞惰繘琛屾柇瑷浠ラ獙璇侀攣瀹氱姸鎬併 + */ +RC OccTransactionManager::LockRows(TxnManager *txMan, uint32_t &numRowsLock) { - RC rc = RC_OK; - TxnOrderedSet_t& orderedSet = txMan->m_accessMgr->GetOrderedRowSet(); - numRowsLock = 0; - for (const auto& raPair : orderedSet) { - const Access* ac = raPair.second; - if (ac->m_type == RD) { + RC rc = RC_OK; // 鍒濆鍖栬繑鍥炰唬鐮佷负 RC_OK + TxnOrderedSet_t &orderedSet = txMan->m_accessMgr->GetOrderedRowSet(); // 鑾峰彇鏈夊簭鐨勮闂泦鍚 + numRowsLock = 0; // 鍒濆鍖栭攣瀹氱殑琛屾暟涓 0 + + // 閬嶅巻鏈夊簭鐨勮闂泦鍚 + for (const auto &raPair : orderedSet) { + const Access *ac = raPair.second; + + if (ac->m_type == RD) { // 濡傛灉鎿嶄綔绫诲瀷鏄鍙栵紝鍒欒烦杩 continue; } - if (ac->m_params.IsPrimarySentinel()) { - Row* row = ac->GetRowFromHeader(); - row->m_rowHeader.Lock(); - numRowsLock++; - MOT_ASSERT(row->GetPrimarySentinel()->IsLocked() == true); + + if (ac->m_params.IsPrimarySentinel()) { // 濡傛灉鏄富瑕佺殑 Sentinel + Row *row = ac->GetRowFromHeader(); // 鑾峰彇琛屽璞 + row->m_rowHeader.Lock(); // 閿佸畾琛 + numRowsLock++; // 澧炲姞閿佸畾鐨勮鏁拌鏁 + MOT_ASSERT(row->GetPrimarySentinel()->IsLocked() == true); // 鏂█楠岃瘉閿佸畾鐘舵 } } - return rc; + return rc; // 杩斿洖鎿嶄綔缁撴灉鐨勪唬鐮 } - -bool OccTransactionManager::LockHeadersNoWait(TxnManager* txMan, uint32_t& numSentinelsLock) +/* + * 鍔熻兘锛氭棤绛夊緟閿佸畾澶翠俊鎭 + * + * 鍙傛暟鍒楄〃锛 + * txMan锛氫簨鍔$鐞嗗櫒鎸囬拡锛屽寘鍚緟閿佸畾鐨勫ご淇℃伅 + * numSentinelsLock锛氱敤浜庡瓨鍌ㄩ攣瀹氱殑 Sentinel 鏁伴噺鐨勫紩鐢 + * + * 杩斿洖鍊硷細 + * 濡傛灉鎴愬姛閿佸畾鎵鏈夊ご淇℃伅锛岃繑鍥瀟rue锛涘惁鍒欒繑鍥瀎alse銆 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庢棤绛夊緟鏂瑰紡閿佸畾浜嬪姟涓渶瑕佷慨鏀圭殑澶翠俊鎭 + * 瀹冮亶鍘嗘湁搴忕殑璁块棶闆嗗悎锛屽姣忎釜闇瑕侀攣瀹氱殑澶翠俊鎭墽琛岄攣瀹氭搷浣溿 + * 濡傛灉閿佸畾澶辫触锛屼細杩涜閲嶈瘯锛屽鏋滈噸璇曟鏁拌秴杩囬槇鍊兼垨鑰呭彂鐢熷紓甯革紝鍒欒繑鍥瀎alse銆 + */ +bool OccTransactionManager::LockHeadersNoWait(TxnManager *txMan, uint32_t &numSentinelsLock) { - uint64_t sleepTime = 1; - uint64_t thdId = txMan->GetThdId(); - TxnOrderedSet_t& orderedSet = txMan->m_accessMgr->GetOrderedRowSet(); - numSentinelsLock = 0; - while (numSentinelsLock != m_writeSetSize) { - for (const auto& raPair : orderedSet) { - const Access* ac = raPair.second; - if (ac->m_type == RD) { + uint64_t sleepTime = 1; // 鍒濆浼戠湢鏃堕棿涓1 + uint64_t thdId = txMan->GetThdId(); // 鑾峰彇绾跨▼ID + TxnOrderedSet_t &orderedSet = txMan->m_accessMgr->GetOrderedRowSet(); // 鑾峰彇鏈夊簭鐨勮闂泦鍚 + numSentinelsLock = 0; // 鍒濆鍖栭攣瀹氱殑 Sentinel 鏁伴噺涓0 + + while (numSentinelsLock != m_writeSetSize) { // 褰撻攣瀹氱殑 Sentinel 鏁伴噺涓嶇瓑浜庡啓鍏ラ泦鍚堝ぇ灏忔椂杩涜寰幆 + for (const auto &raPair : orderedSet) { // 閬嶅巻鏈夊簭鐨勮闂泦鍚 + const Access *ac = raPair.second; + + if (ac->m_type == RD) { // 濡傛灉鎿嶄綔绫诲瀷鏄鍙栵紝鍒欒烦杩 continue; } - Sentinel* sent = ac->m_origSentinel; - if (!sent->TryLock(thdId)) { + + Sentinel *sent = ac->m_origSentinel; // 鑾峰彇鍘熷 Sentinel 瀵硅薄 + + if (!sent->TryLock(thdId)) { // 灏濊瘯閿佸畾 Sentinel break; } - numSentinelsLock++; - if (ac->m_params.IsPrimaryUpgrade()) { - ac->m_auxRow->m_rowHeader.Lock(); + + numSentinelsLock++; // 澧炲姞閿佸畾鐨 Sentinel 鏁伴噺璁℃暟 + + if (ac->m_params.IsPrimaryUpgrade()) { // 濡傛灉鏄富瑕佸崌绾ф搷浣 + ac->m_auxRow->m_rowHeader.Lock(); // 閿佸畾杈呭姪琛岀殑澶翠俊鎭 } // New insert row is already committed! // Check if row has changed in sentinel @@ -184,217 +285,308 @@ bool OccTransactionManager::LockHeadersNoWait(TxnManager* txMan, uint32_t& numSe } } - if (numSentinelsLock != m_writeSetSize) { - ReleaseHeaderLocks(txMan, numSentinelsLock); - numSentinelsLock = 0; - if (m_preAbort) { - for (const auto& acPair : orderedSet) { - const Access* ac = acPair.second; + if (numSentinelsLock != m_writeSetSize) { // 濡傛灉閿佸畾鐨 Sentinel 鏁伴噺涓嶇瓑浜庡啓鍏ラ泦鍚堝ぇ灏 + ReleaseHeaderLocks(txMan, numSentinelsLock); // 閲婃斁宸查攣瀹氱殑澶翠俊鎭 + numSentinelsLock = 0; // 閲嶇疆宸查攣瀹氱殑 Sentinel 鏁伴噺 + if (m_preAbort) { // 濡傛灉鏄缁堟浜嬪姟 + for (const auto &acPair : orderedSet) { // 閬嶅巻鏈夊簭鐨勮闂泦鍚 + const Access *ac = acPair.second; if (!QuickHeaderValidation(ac)) { return false; } } } - if (sleepTime > LOCK_TIME_OUT) { + if (sleepTime > LOCK_TIME_OUT) { // 濡傛灉浼戠湢鏃堕棿瓒呰繃闃堝 return false; } else { - if (IsHighContention() == false) { - CpuCyclesLevelTime::Sleep(5); + if (IsHighContention() == false) { // 濡傛灉涓嶆槸楂樼珵浜夌幆澧 + CpuCyclesLevelTime::Sleep(5); // 浼戠湢5涓狢PU鍛ㄦ湡 } else { - usleep(m_dynamicSleep); + usleep(m_dynamicSleep); // 鍚﹀垯浼戠湢鎸囧畾鐨勫井绉掓暟 } - sleepTime = sleepTime << 1; + sleepTime = sleepTime << 1; // 浼戠湢鏃堕棿缈诲 } } } - return true; + return true; // 杩斿洖閿佸畾鎴愬姛 } -RC OccTransactionManager::LockHeaders(TxnManager* txMan, uint32_t& numSentinelsLock) +/* + * 鍔熻兘锛氶攣瀹氬ご淇℃伅 + * + * 鍙傛暟鍒楄〃锛 + * txMan锛氫簨鍔$鐞嗗櫒鎸囬拡锛屽寘鍚緟閿佸畾鐨勫ご淇℃伅 + * numSentinelsLock锛氱敤浜庡瓨鍌ㄩ攣瀹氱殑 Sentinel 鏁伴噺鐨勫紩鐢 + * + * 杩斿洖鍊硷細 + * 杩斿洖鎿嶄綔缁撴灉鐨勪唬鐮 (RC)锛岄氬父鏄 RC_OK 琛ㄧず鎴愬姛銆 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庨攣瀹氫簨鍔′腑闇瑕佷慨鏀圭殑澶翠俊鎭 + * 瀹冮亶鍘嗘湁搴忕殑璁块棶闆嗗悎锛屽姣忎釜闇瑕侀攣瀹氱殑澶翠俊鎭墽琛岄攣瀹氭搷浣溿 + * 濡傛灉閿佸畾澶辫触锛屼細杩涜閲嶈瘯锛屽鏋滈噸璇曟鏁拌秴杩囬槇鍊兼垨鑰呭彂鐢熷紓甯革紝鍒欒繑鍥炵浉搴旂殑閿欒浠g爜銆 + */ +RC OccTransactionManager::LockHeaders(TxnManager *txMan, uint32_t &numSentinelsLock) { - RC rc = RC_OK; - uint64_t thdId = txMan->GetThdId(); - TxnOrderedSet_t& orderedSet = txMan->m_accessMgr->GetOrderedRowSet(); - numSentinelsLock = 0; - if (m_validationNoWait) { - if (!LockHeadersNoWait(txMan, numSentinelsLock)) { - rc = RC_ABORT; - goto final; + RC rc = RC_OK; // 鍒濆鍖栬繑鍥炰唬鐮佷负 RC_OK + uint64_t thdId = txMan->GetThdId(); // 鑾峰彇绾跨▼ID + TxnOrderedSet_t &orderedSet = txMan->m_accessMgr->GetOrderedRowSet(); // 鑾峰彇鏈夊簭鐨勮闂泦鍚 + numSentinelsLock = 0; // 鍒濆鍖栭攣瀹氱殑 Sentinel 鏁伴噺涓0 + + if (m_validationNoWait) { // 濡傛灉鍚敤鏃犵瓑寰呴攣瀹 + if (!LockHeadersNoWait(txMan, numSentinelsLock)) { // 璋冪敤鏃犵瓑寰呴攣瀹氬嚱鏁 + rc = RC_ABORT; // 閿佸畾澶辫触锛岃缃繑鍥炰唬鐮佷负 RC_ABORT + goto final; // 璺宠浆鍒 final 鏍囩 } } else { - for (const auto& raPair : orderedSet) { - const Access* ac = raPair.second; - if (ac->m_type == RD) { + for (const auto &raPair : orderedSet) { // 閬嶅巻鏈夊簭鐨勮闂泦鍚 + const Access *ac = raPair.second; + + if (ac->m_type == RD) { // 濡傛灉鎿嶄綔绫诲瀷鏄鍙栵紝鍒欒烦杩 continue; } - Sentinel* sent = ac->m_origSentinel; - sent->Lock(thdId); - numSentinelsLock++; - if (ac->m_params.IsPrimaryUpgrade()) { - ac->m_auxRow->m_rowHeader.Lock(); + + Sentinel *sent = ac->m_origSentinel; // 鑾峰彇鍘熷 Sentinel 瀵硅薄 + sent->Lock(thdId); // 閿佸畾 Sentinel + numSentinelsLock++; // 澧炲姞閿佸畾鐨 Sentinel 鏁伴噺璁℃暟 + + if (ac->m_params.IsPrimaryUpgrade()) { // 濡傛灉鏄富瑕佸崌绾ф搷浣 + ac->m_auxRow->m_rowHeader.Lock(); // 閿佸畾杈呭姪琛岀殑澶翠俊鎭 } // New insert row is already committed! // Check if row has chained in sentinel - if (!QuickHeaderValidation(ac)) { - rc = RC_ABORT; - goto final; + if (!QuickHeaderValidation(ac)) { // 璋冪敤蹇熼獙璇佸嚱鏁 + rc = RC_ABORT; // 楠岃瘉澶辫触锛岃缃繑鍥炰唬鐮佷负 RC_ABORT + goto final; // 璺宠浆鍒 final 鏍囩 } } } -final: - return rc; + +final: // final 鏍囩锛岀敤浜庡鐞嗘渶鍚庣殑娓呯悊鍜岃繑鍥 + return rc; // 杩斿洖鎿嶄綔缁撴灉鐨勪唬鐮 } -bool OccTransactionManager::PreAllocStableRow(TxnManager* txMan) +/* + * 鍔熻兘锛氶鍒嗛厤绋冲畾琛 + * + * 鍙傛暟鍒楄〃锛 + * txMan锛氫簨鍔$鐞嗗櫒鎸囬拡锛屽寘鍚渶瑕侀鍒嗛厤绋冲畾琛岀殑淇℃伅 + * + * 杩斿洖鍊硷細 + * 濡傛灉鎴愬姛棰勫垎閰嶇ǔ瀹氳锛岃繑鍥瀟rue锛涘惁鍒欒繑鍥瀎alse銆 + * + * 娉ㄦ剰锛 + * 濡傛灉鍚敤妫鏌ョ偣锛屾鍑芥暟鐢ㄤ簬鍦ㄦ彁浜や簨鍔″墠棰勫垎閰嶇ǔ瀹氳銆 + * 瀹冮亶鍘嗘湁搴忕殑璁块棶闆嗗悎锛屽姣忎釜闇瑕侀鍒嗛厤绋冲畾琛岀殑鎿嶄綔鎵ц棰勫垎閰嶆搷浣溿 + * 濡傛灉棰勫垎閰嶅け璐ワ紝浼氬洖婊氬凡鍒嗛厤鐨勭ǔ瀹氳骞惰繑鍥瀎alse銆 + */ +bool OccTransactionManager::PreAllocStableRow(TxnManager *txMan) { - if (GetGlobalConfiguration().m_enableCheckpoint) { - GetCheckpointManager()->BeginCommit(txMan); + if (GetGlobalConfiguration().m_enableCheckpoint) { // 濡傛灉鍚敤妫鏌ョ偣 + GetCheckpointManager()->BeginCommit(txMan); // 寮濮嬫彁浜ゆ鏌ョ偣 - TxnOrderedSet_t& orderedSet = txMan->m_accessMgr->GetOrderedRowSet(); - for (const auto& raPair : orderedSet) { - const Access* access = raPair.second; - if (access->m_type == RD) { + TxnOrderedSet_t &orderedSet = txMan->m_accessMgr->GetOrderedRowSet(); // 鑾峰彇鏈夊簭鐨勮闂泦鍚 + for (const auto &raPair : orderedSet) { // 閬嶅巻鏈夊簭鐨勮闂泦鍚 + const Access *access = raPair.second; + if (access->m_type == RD) { // 濡傛灉鎿嶄綔绫诲瀷鏄鍙栵紝鍒欒烦杩 continue; } - if (access->m_params.IsPrimarySentinel()) { - if (!GetCheckpointManager()->PreAllocStableRow(txMan, access->GetRowFromHeader(), access->m_type)) { - GetCheckpointManager()->FreePreAllocStableRows(txMan); - GetCheckpointManager()->EndCommit(txMan); - return false; + if (access->m_params.IsPrimarySentinel()) { // 濡傛灉鏄富瑕 Sentinel + if (!GetCheckpointManager()->PreAllocStableRow(txMan, access->GetRowFromHeader(), + access->m_type)) { // 棰勫垎閰嶇ǔ瀹氳 + GetCheckpointManager()->FreePreAllocStableRows(txMan); // 閲婃斁宸插垎閰嶇殑绋冲畾琛 + GetCheckpointManager()->EndCommit(txMan); // 缁撴潫鎻愪氦妫鏌ョ偣 + return false; // 棰勫垎閰嶅け璐ワ紝杩斿洖false } } } } - return true; + return true; // 杩斿洖棰勫垎閰嶆垚鍔 } -bool OccTransactionManager::QuickVersionCheck(TxnManager* txMan, uint32_t& readSetSize) +/* + * 鍔熻兘锛氬揩閫熺増鏈鏌 + * + * 鍙傛暟鍒楄〃锛 + * txMan锛氫簨鍔$鐞嗗櫒鎸囬拡锛屽寘鍚渶瑕佽繘琛岀増鏈鏌ョ殑淇℃伅 + * readSetSize锛氱敤浜庡瓨鍌ㄨ鍙栭泦鍚堝ぇ灏忕殑寮曠敤 + * + * 杩斿洖鍊硷細 + * 濡傛灉鐗堟湰妫鏌ユ垚鍔燂紝杩斿洖true锛涘惁鍒欒繑鍥瀎alse銆 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庡揩閫熸墽琛岀増鏈鏌ヤ互纭畾浜嬪姟鐨勮鍙栭泦鍚堝ぇ灏忋 + * 瀹冮亶鍘嗘湁搴忕殑璁块棶闆嗗悎锛屾牴鎹闂被鍨嬪拰闅旂绾у埆鏇存柊闆嗗悎澶у皬淇℃伅銆 + * 濡傛灉鍚敤棰勭粓姝紝杩樹細杩涜澶翠俊鎭獙璇併 + */ +bool OccTransactionManager::QuickVersionCheck(TxnManager *txMan, uint32_t &readSetSize) { - int isolationLevel = txMan->GetTxnIsoLevel(); - TxnOrderedSet_t& orderedSet = txMan->m_accessMgr->GetOrderedRowSet(); - readSetSize = 0; - for (const auto& raPair : orderedSet) { - const Access* ac = raPair.second; + int isolationLevel = txMan->GetTxnIsoLevel(); // 鑾峰彇浜嬪姟鐨勯殧绂荤骇鍒 + TxnOrderedSet_t &orderedSet = txMan->m_accessMgr->GetOrderedRowSet(); // 鑾峰彇鏈夊簭鐨勮闂泦鍚 + readSetSize = 0; // 鍒濆鍖栬鍙栭泦鍚堝ぇ灏忎负0 + + for (const auto &raPair : orderedSet) { // 閬嶅巻鏈夊簭鐨勮闂泦鍚 + const Access *ac = raPair.second; // 鑾峰彇璁块棶瀵硅薄 + if (ac->m_params.IsPrimarySentinel()) { - m_rowsSetSize++; + m_rowsSetSize++; // 濡傛灉鏄富瑕 Sentinel锛屽垯澧炲姞琛岄泦鍚堝ぇ灏忚鏁 } + switch (ac->m_type) { case RD_FOR_UPDATE: case WR: - m_writeSetSize++; + m_writeSetSize++; // 濡傛灉鏄啓鍏ョ被鍨嬶紝澧炲姞鍐欓泦鍚堝ぇ灏忚鏁 break; case DEL: - m_writeSetSize++; - m_deleteSetSize++; + m_writeSetSize++; // 濡傛灉鏄垹闄ょ被鍨嬶紝澧炲姞鍐欓泦鍚堝ぇ灏忚鏁 + m_deleteSetSize++; // 鍚屾椂澧炲姞鍒犻櫎闆嗗悎澶у皬璁℃暟 break; case INS: - m_insertSetSize++; - m_writeSetSize++; + m_insertSetSize++; // 濡傛灉鏄彃鍏ョ被鍨嬶紝澧炲姞鎻掑叆闆嗗悎澶у皬璁℃暟 + m_writeSetSize++; // 鍚屾椂澧炲姞鍐欓泦鍚堝ぇ灏忚鏁 break; case RD: - if (isolationLevel > READ_COMMITED) { - readSetSize++; + if (isolationLevel > READ_COMMITTED) { + readSetSize++; // 濡傛灉鏄鍙栫被鍨嬩笖闅旂绾у埆杈冮珮锛屽鍔犺鍙栭泦鍚堝ぇ灏忚鏁 } else { - continue; + continue; // 鍚﹀垯璺宠繃褰撳墠鎿嶄綔 } break; default: break; } - if (m_preAbort) { - if (!QuickHeaderValidation(ac)) { + if (m_preAbort) { // 濡傛灉鍚敤棰勭粓姝 + if (!QuickHeaderValidation(ac)) { // 杩涜澶翠俊鎭獙璇侊紝濡傛灉澶辫触鍒欒繑鍥瀎alse return false; } } } - return true; + return true; // 杩斿洖鐗堟湰妫鏌ユ垚鍔 } -RC OccTransactionManager::ValidateOcc(TxnManager* txMan) +/* + * 鍔熻兘锛氶獙璇 OCC锛圤ptimistic Concurrency Control锛 + * + * 鍙傛暟鍒楄〃锛 + * txMan锛氫簨鍔$鐞嗗櫒鎸囬拡锛屽寘鍚緟楠岃瘉鐨 OCC 淇℃伅 + * + * 杩斿洖鍊硷細 + * 杩斿洖鎿嶄綔缁撴灉鐨勪唬鐮 (RC)锛岄氬父鏄 RC_OK 琛ㄧず鎴愬姛銆 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庨獙璇 OCC 浜嬪姟锛屽寘鎷墽琛屽揩閫熺増鏈鏌ャ侀攣瀹氬ご淇℃伅銆侀獙璇佽鍙栭泦鍚堝拰鍐欏叆闆嗗悎銆侀鍒嗛厤绋冲畾琛岀瓑姝ラ銆 + * 瀹冭绠椾簨鍔$殑鍚勪釜闆嗗悎澶у皬锛屽苟鍦ㄩ獙璇佹垚鍔熸椂閿佸畾鐩稿叧鐨勫ご淇℃伅銆 + * 濡傛灉楠岃瘉澶辫触锛屼細鏍规嵁閿欒浠g爜杩涜鐩稿簲澶勭悊銆 + */ +RC OccTransactionManager::ValidateOcc(TxnManager *txMan) { - uint32_t numSentinelLock = 0; - m_rowsLocked = false; - TxnAccess* tx = txMan->m_accessMgr.Get(); - RC rc = RC_OK; - const uint32_t rowCount = tx->m_rowCnt; + uint32_t numSentinelLock = 0; // 鍒濆鍖栭攣瀹氱殑 Sentinel 鏁伴噺涓0 + m_rowsLocked = false; // 鍒濆鍖栬鏄惁宸查攣瀹氫负 false + TxnAccess *tx = txMan->m_accessMgr.Get(); // 鑾峰彇浜嬪姟鐨勮闂璞 + RC rc = RC_OK; // 鍒濆鍖栬繑鍥炰唬鐮佷负 RC_OK + const uint32_t rowCount = tx->m_rowCnt; // 鑾峰彇琛屾暟 - m_writeSetSize = 0; - m_rowsSetSize = 0; - m_deleteSetSize = 0; - m_insertSetSize = 0; - m_txnCounter++; + m_writeSetSize = 0; // 鍒濆鍖栧啓鍏ラ泦鍚堝ぇ灏忎负0 + m_rowsSetSize = 0; // 鍒濆鍖栬闆嗗悎澶у皬涓0 + m_deleteSetSize = 0; // 鍒濆鍖栧垹闄ら泦鍚堝ぇ灏忎负0 + m_insertSetSize = 0; // 鍒濆鍖栨彃鍏ラ泦鍚堝ぇ灏忎负0 + m_txnCounter++; // 浜嬪姟璁℃暟鍣ㄥ姞1 - if (rowCount == 0) { + if (rowCount == 0) { // 濡傛灉琛屾暟涓0锛屽垯涓哄彧璇讳簨鍔 // READONLY - return rc; + return rc; // 杩斿洖 RC_OK } - uint32_t readSetSize = 0; - TxnOrderedSet_t& orderedSet = tx->GetOrderedRowSet(); - MOT_ASSERT(rowCount == orderedSet.size()); + uint32_t readSetSize = 0; // 鍒濆鍖栬鍙栭泦鍚堝ぇ灏忎负0 + TxnOrderedSet_t &orderedSet = tx->GetOrderedRowSet(); // 鑾峰彇鏈夊簭鐨勮闂泦鍚 + MOT_ASSERT(rowCount == orderedSet.size()); // 鏂█琛屾暟鍜屾湁搴忛泦鍚堝ぇ灏忕浉绛 /* Perform Quick Version check */ - if (!QuickVersionCheck(txMan, readSetSize)) { - rc = RC_ABORT; - goto final; + if (!QuickVersionCheck(txMan, readSetSize)) { // 璋冪敤蹇熺増鏈鏌ュ嚱鏁 + rc = RC_ABORT; // 妫鏌ュけ璐ワ紝璁剧疆杩斿洖浠g爜涓 RC_ABORT + goto final; // 璺宠浆鍒 final 鏍囩 } - MOT_LOG_DEBUG("Validate OCC rowCnt=%u RD=%u WR=%u\n", tx->m_rowCnt, tx->m_rowCnt - m_writeSetSize, m_writeSetSize); - rc = LockHeaders(txMan, numSentinelLock); - if (rc != RC_OK) { - goto final; + MOT_LOG_DEBUG("Validate OCC rowCnt=%u RD=%u WR=%u\n", tx->m_rowCnt, tx->m_rowCnt - m_writeSetSize, + m_writeSetSize); // 璋冭瘯鏃ュ織 + + rc = LockHeaders(txMan, numSentinelLock); // 閿佸畾澶翠俊鎭 + if (rc != RC_OK) { // 濡傛灉閿佸畾澶辫触 + goto final; // 璺宠浆鍒 final 鏍囩 } // Validate rows in the read set and write set - if (readSetSize > 0) { - if (!ValidateReadSet(txMan)) { - rc = RC_ABORT; - goto final; + if (readSetSize > 0) { // 濡傛灉璇诲彇闆嗗悎澶у皬澶т簬0 + if (!ValidateReadSet(txMan)) { // 璋冪敤楠岃瘉璇诲彇闆嗗悎鍑芥暟 + rc = RC_ABORT; // 楠岃瘉澶辫触锛岃缃繑鍥炰唬鐮佷负 RC_ABORT + goto final; // 璺宠浆鍒 final 鏍囩 } } - if (!ValidateWriteSet(txMan)) { - rc = RC_ABORT; - goto final; + if (!ValidateWriteSet(txMan)) { // 楠岃瘉鍐欏叆闆嗗悎 + rc = RC_ABORT; // 楠岃瘉澶辫触锛岃缃繑鍥炰唬鐮佷负 RC_ABORT + goto final; // 璺宠浆鍒 final 鏍囩 } // Pre-allocate stable row according to the checkpoint state. - if (!PreAllocStableRow(txMan)) { - rc = RC_MEMORY_ALLOCATION_ERROR; - goto final; + if (!PreAllocStableRow(txMan)) { // 璋冪敤棰勫垎閰嶇ǔ瀹氳鍑芥暟 + rc = RC_MEMORY_ALLOCATION_ERROR; // 棰勫垎閰嶅け璐ワ紝璁剧疆杩斿洖浠g爜涓 RC_MEMORY_ALLOCATION_ERROR + goto final; // 璺宠浆鍒 final 鏍囩 } -final: - if (likely(rc == RC_OK)) { - MOT_ASSERT(numSentinelLock == m_writeSetSize); - m_rowsLocked = true; - } else { - ReleaseHeaderLocks(txMan, numSentinelLock); - if (likely(rc == RC_ABORT)) { - m_abortsCounter++; +final: // final 鏍囩锛岀敤浜庡鐞嗘渶鍚庣殑娓呯悊鍜岃繑鍥 + if (likely(rc == RC_OK)) { // 濡傛灉杩斿洖浠g爜涓 RC_OK + MOT_ASSERT(numSentinelLock == m_writeSetSize); // 鏂█閿佸畾鐨 Sentinel 鏁伴噺涓庡啓鍏ラ泦鍚堝ぇ灏忕浉绛 + m_rowsLocked = true; // 璁剧疆琛屽凡閿佸畾涓 true + } else { // 濡傛灉杩斿洖浠g爜涓嶄负 RC_OK + ReleaseHeaderLocks(txMan, numSentinelLock); // 閲婃斁澶翠俊鎭攣瀹 + if (likely(rc == RC_ABORT)) { // 濡傛灉杩斿洖浠g爜涓 RC_ABORT + m_abortsCounter++; // 澧炲姞涓璁℃暟鍣 } } - return rc; + return rc; // 杩斿洖鎿嶄綔缁撴灉鐨勪唬鐮 } -void OccTransactionManager::RollbackInserts(TxnManager* txMan) +/* + * 鍔熻兘锛氬洖婊氭彃鍏ユ搷浣 + * + * 鍙傛暟鍒楄〃锛 + * txMan锛氫簨鍔$鐞嗗櫒鎸囬拡锛屽寘鍚渶瑕佸洖婊氱殑鎻掑叆鎿嶄綔 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庡洖婊氫簨鍔′腑鐨勬彃鍏ユ搷浣滐紝閫氳繃璋冪敤浜嬪姟绠$悊鍣ㄧ殑 UndoInserts 鍑芥暟瀹炵幇銆 + * 鎻掑叆鎿嶄綔鐨勫洖婊氶氬父娑夊強閲婃斁鍒嗛厤鐨勮祫婧愶紝灏嗗叾鐘舵佹仮澶嶅埌浜嬪姟寮濮嬩箣鍓嶇殑鐘舵併 + */ +void OccTransactionManager::RollbackInserts(TxnManager *txMan) { return txMan->UndoInserts(); } -void OccTransactionManager::ApplyWrite(TxnManager* txMan) +/* + * 鍔熻兘锛氬簲鐢ㄥ啓鍏ユ搷浣 + * + * 鍙傛暟鍒楄〃锛 + * txMan锛氫簨鍔$鐞嗗櫒鎸囬拡锛屽寘鍚渶瑕佸簲鐢ㄧ殑鍐欏叆鎿嶄綔 + * + * 娉ㄦ剰锛 + * 濡傛灉鍚敤妫鏌ョ偣锛屾鍑芥暟鐢ㄤ簬搴旂敤浜嬪姟涓殑鍐欏叆鎿嶄綔銆 + * 瀹冮亶鍘嗘湁搴忕殑璁块棶闆嗗悎锛屽姣忎釜闇瑕佸簲鐢ㄧ殑鍐欏叆鎿嶄綔鎵ц搴旂敤鎿嶄綔銆 + * 瀵逛簬涓昏 Sentinel锛屼紶閫掑疄闄呯殑鍏ㄥ眬琛岋紙access->GetRowFromHeader()锛夛紝 + * 浠ヤ究绋冲畾琛屽叿鏈変笌淇敼涔嬪墠鐨勫師濮嬭鐩稿悓鐨 CSN銆乺owid 绛夊睘鎬с + */ +void OccTransactionManager::ApplyWrite(TxnManager *txMan) { - if (GetGlobalConfiguration().m_enableCheckpoint) { - TxnOrderedSet_t& orderedSet = txMan->m_accessMgr->GetOrderedRowSet(); - for (const auto& raPair : orderedSet) { - const Access* access = raPair.second; - if (access->m_type == RD) { + if (GetGlobalConfiguration().m_enableCheckpoint) { // 濡傛灉鍚敤妫鏌ョ偣 + TxnOrderedSet_t &orderedSet = txMan->m_accessMgr->GetOrderedRowSet(); // 鑾峰彇鏈夊簭鐨勮闂泦鍚 + for (const auto &raPair : orderedSet) { // 閬嶅巻鏈夊簭鐨勮闂泦鍚 + const Access *access = raPair.second; // 鑾峰彇璁块棶瀵硅薄 + if (access->m_type == RD) { // 濡傛灉鎿嶄綔绫诲瀷鏄鍙栵紝鍒欒烦杩 continue; } - if (access->m_params.IsPrimarySentinel()) { + if (access->m_params.IsPrimarySentinel()) { // 濡傛灉鏄富瑕 Sentinel // Pass the actual global row (access->GetRowFromHeader()), so that the stable row will have the // same CSN, rowid, etc as the original row before the modifications are applied. GetCheckpointManager()->ApplyWrite(txMan, access->GetRowFromHeader(), access->m_type); @@ -402,32 +594,44 @@ void OccTransactionManager::ApplyWrite(TxnManager* txMan) } } } - -void OccTransactionManager::WriteChanges(TxnManager* txMan) +/* + * 鍔熻兘锛氬啓鍏ヤ簨鍔′腑鐨勬洿鏀 + * + * 鍙傛暟鍒楄〃锛 + * txMan锛氫簨鍔$鐞嗗櫒鎸囬拡锛屽寘鍚渶瑕佸啓鍏ョ殑鏇存敼 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庡啓鍏ヤ簨鍔′腑鐨勬洿鏀癸紝鍖呮嫭閿佸畾琛屻佸簲鐢ㄥ啓鍏ャ佹洿鏂板叏灞琛岀殑 CSN 浠ュ強澶勭悊鎻掑叆鎿嶄綔绛夋楠ゃ + * 瀹冧細閬嶅巻鏈夊簭鐨勮闂泦鍚堬紝瀵规瘡涓闂墽琛岀浉搴旂殑鏇存敼鎿嶄綔銆 + */ +void OccTransactionManager::WriteChanges(TxnManager *txMan) { - if (m_writeSetSize == 0 && m_insertSetSize == 0) { + if (m_writeSetSize == 0 && m_insertSetSize == 0) { // 濡傛灉鍐欏叆闆嗗悎鍜屾彃鍏ラ泦鍚堝ぇ灏忛兘涓0锛屽垯鐩存帴杩斿洖 return; } - LockRows(txMan, m_rowsSetSize); + LockRows(txMan, m_rowsSetSize); // 閿佸畾琛 // Stable rows for checkpoint needs to be created (copied from original row) before modifying the global rows. - ApplyWrite(txMan); + ApplyWrite(txMan); // 搴旂敤鍐欏叆 - TxnOrderedSet_t& orderedSet = txMan->m_accessMgr->GetOrderedRowSet(); + TxnOrderedSet_t &orderedSet = txMan->m_accessMgr->GetOrderedRowSet(); // 鑾峰彇鏈夊簭鐨勮闂泦鍚 // Update CSN with all relevant information on global rows // For deletes invalidate sentinels - rows still locked! - for (const auto& raPair : orderedSet) { - const Access* access = raPair.second; - access->GetRowFromHeader()->m_rowHeader.WriteChangesToRow(access, txMan->GetCommitSequenceNumber()); + // 鏇存柊鍏ㄥ眬琛岀殑 CSN锛屽浜庡垹闄ゆ搷浣滐紝浣 Sentinel 澶辨晥锛堜粛鐒堕攣瀹氾級 + for (const auto &raPair : orderedSet) { // 閬嶅巻鏈夊簭鐨勮闂泦鍚 + const Access *access = raPair.second; // 鑾峰彇璁块棶瀵硅薄 + access->GetRowFromHeader()->m_rowHeader.WriteChangesToRow( + access, txMan->GetCommitSequenceNumber()); // 鏇存柊鍏ㄥ眬琛岀殑 CSN } // Treat Inserts - if (m_insertSetSize > 0) { - for (const auto& raPair : orderedSet) { - Access* access = raPair.second; - if (access->m_type != INS) { + // 澶勭悊鎻掑叆鎿嶄綔 + if (m_insertSetSize > 0) { // 濡傛灉鎻掑叆闆嗗悎澶у皬澶т簬0 + for (const auto &raPair : orderedSet) { // 鍐嶆閬嶅巻鏈夊簭鐨勮闂泦鍚 + Access *access = raPair.second; // 鑾峰彇璁块棶瀵硅薄 + if (access->m_type != INS) { // 濡傛灉鎿嶄綔绫诲瀷涓嶆槸鎻掑叆锛屽垯璺宠繃 continue; } MOT_ASSERT(access->m_origSentinel->IsLocked() == true); @@ -453,15 +657,12 @@ void OccTransactionManager::WriteChanges(TxnManager* txMan) * Save previous row in the access! * We need it for the row release! */ - Row* row = access->GetRowFromHeader(); + Row *row = access->GetRowFromHeader(); access->m_localInsertRow = row; access->m_origSentinel->SetNextPtr(access->m_auxRow); // Add row to GC! - txMan->GetGcSession()->GcRecordObject(row->GetTable()->GetPrimaryIndex()->GetIndexId(), - row, - nullptr, - Row::RowDtor, - ROW_SIZE_FROM_POOL(row->GetTable())); + txMan->GetGcSession()->GcRecordObject(row->GetTable()->GetPrimaryIndex()->GetIndexId(), row, + nullptr, Row::RowDtor, ROW_SIZE_FROM_POOL(row->GetTable())); } else { // Set Sentinel for access->m_origSentinel->SetNextPtr(access->m_auxRow->GetPrimarySentinel()); @@ -475,37 +676,49 @@ void OccTransactionManager::WriteChanges(TxnManager* txMan) } // Treat Inserts - if (m_insertSetSize > 0) { - for (const auto& raPair : orderedSet) { - const Access* access = raPair.second; - if (access->m_type != INS) { + if (m_insertSetSize > 0) { // 濡傛灉鎻掑叆闆嗗悎澶у皬澶т簬0 + for (const auto &raPair : orderedSet) { // 鍐嶆閬嶅巻鏈夊簭鐨勮闂泦鍚 + const Access *access = raPair.second; // 鑾峰彇璁块棶瀵硅薄 + if (access->m_type != INS) { // 濡傛灉鎿嶄綔绫诲瀷涓嶆槸鎻掑叆锛屽垯璺宠繃 continue; } - access->m_origSentinel->UnSetDirty(); + access->m_origSentinel->UnSetDirty(); // 鍙栨秷璁剧疆鑴忔爣蹇 } } - CleanRowsFromIndexes(txMan); + CleanRowsFromIndexes(txMan); // 浠庣储寮曚腑娓呴櫎琛 } -void OccTransactionManager::CleanRowsFromIndexes(TxnManager* txMan) +/* + * 鍔熻兘锛氫粠绱㈠紩涓竻闄よ + * + * 鍙傛暟鍒楄〃锛 + * txMan锛氫簨鍔$鐞嗗櫒鎸囬拡锛屽寘鍚渶瑕佹竻闄ょ殑琛 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庝粠绱㈠紩涓竻闄や簨鍔′腑鐨勮锛岀壒鍒槸鍒犻櫎鎿嶄綔銆 + * 瀹冮亶鍘嗘湁搴忕殑璁块棶闆嗗悎锛屽姣忎釜鍒犻櫎鎿嶄綔鎵ц娓呴櫎鎿嶄綔銆 + * 娓呴櫎鎿嶄綔鍖呮嫭浠庤〃涓噺灏戣鏁般佷粠绱㈠紩涓Щ闄ら敭绛夈 + */ +void OccTransactionManager::CleanRowsFromIndexes(TxnManager *txMan) { - if (m_deleteSetSize == 0) { + if (m_deleteSetSize == 0) { // 濡傛灉鍒犻櫎闆嗗悎澶у皬涓0锛屽垯鐩存帴杩斿洖 return; } - TxnAccess* tx = txMan->m_accessMgr.Get(); - TxnOrderedSet_t& orderedSet = tx->GetOrderedRowSet(); + TxnAccess *tx = txMan->m_accessMgr.Get(); + TxnOrderedSet_t &orderedSet = tx->GetOrderedRowSet(); // 鑾峰彇鏈夊簭鐨勮闂泦鍚 uint32_t numOfDeletes = m_deleteSetSize; - // use local counter to optimize - for (const auto& raPair : orderedSet) { - const Access* access = raPair.second; - if (access->m_type == DEL) { + // 浣跨敤鏈湴璁℃暟鍣ㄨ繘琛屼紭鍖 + for (const auto &raPair : orderedSet) { // 閬嶅巻鏈夊簭鐨勮闂泦鍚 + const Access *access = raPair.second; // 鑾峰彇璁块棶瀵硅薄 + if (access->m_type == DEL) { // 濡傛灉鎿嶄綔绫诲瀷鏄垹闄 numOfDeletes--; - access->GetTxnRow()->GetTable()->UpdateRowCount(-1); + access->GetTxnRow()->GetTable()->UpdateRowCount(-1); // 浠庤〃涓噺灏戣鏁 MOT_ASSERT(access->m_params.IsUpgradeInsert() == false); // Use Txn Row as row may change INSERT after DELETE leaves residue - txMan->RemoveKeyFromIndex(access->GetTxnRow(), access->m_origSentinel); + // 浣跨敤浜嬪姟琛岋紝鍥犱负鍦ㄥ垹闄ゆ搷浣滃悗锛屾彃鍏ユ搷浣滃彲鑳戒細鐣欎笅娈嬩綑 + txMan->RemoveKeyFromIndex(access->GetTxnRow(), access->m_origSentinel); // 浠庣储寮曚腑绉婚櫎閿 } if (!numOfDeletes) { break; @@ -513,24 +726,36 @@ void OccTransactionManager::CleanRowsFromIndexes(TxnManager* txMan) } } -void OccTransactionManager::ReleaseHeaderLocks(TxnManager* txMan, uint32_t numOfLocks) +/* + * 鍔熻兘锛氶噴鏀惧ご淇℃伅鐨勯攣 + * + * 鍙傛暟鍒楄〃锛 + * txMan锛氫簨鍔$鐞嗗櫒鎸囬拡锛屽寘鍚渶瑕侀噴鏀鹃攣鐨勫ご淇℃伅 + * numOfLocks锛氶渶瑕侀噴鏀剧殑閿佺殑鏁伴噺 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庨噴鏀句簨鍔′腑澶翠俊鎭殑閿侊紝鐗瑰埆鏄湪鍙戠敓鍥炴粴鎴栭噴鏀鹃攣鏃躲 + * 瀹冮亶鍘嗘湁搴忕殑璁块棶闆嗗悎锛屽姣忎釜闇瑕侀噴鏀鹃攣鐨勫ご淇℃伅鎵ц閲婃斁鎿嶄綔銆 + */ +void OccTransactionManager::ReleaseHeaderLocks(TxnManager *txMan, uint32_t numOfLocks) { - if (numOfLocks == 0) { + if (numOfLocks == 0) { // 濡傛灉闇瑕侀噴鏀剧殑閿佺殑鏁伴噺涓0锛屽垯鐩存帴杩斿洖 return; } - TxnAccess* tx = txMan->m_accessMgr.Get(); - TxnOrderedSet_t& orderedSet = tx->GetOrderedRowSet(); + TxnAccess *tx = txMan->m_accessMgr.Get(); + TxnOrderedSet_t &orderedSet = tx->GetOrderedRowSet(); // 鑾峰彇鏈夊簭鐨勮闂泦鍚 // use local counter to optimize - for (const auto& raPair : orderedSet) { - const Access* access = raPair.second; - if (access->m_type == RD) { + // 浣跨敤鏈湴璁℃暟鍣ㄨ繘琛屼紭鍖 + for (const auto &raPair : orderedSet) { // 閬嶅巻鏈夊簭鐨勮闂泦鍚 + const Access *access = raPair.second; // 鑾峰彇璁块棶瀵硅薄 + if (access->m_type == RD) { // 濡傛灉鎿嶄綔绫诲瀷鏄鍙栵紝鍒欑户缁笅涓娆″惊鐜 continue; } else { numOfLocks--; - access->m_origSentinel->Release(); + access->m_origSentinel->Release(); // 閲婃斁 Sentinel 閿 if (access->m_params.IsPrimaryUpgrade()) { - access->m_auxRow->m_rowHeader.Release(); + access->m_auxRow->m_rowHeader.Release(); // 閲婃斁杈呭姪琛岀殑閿 } } if (!numOfLocks) { @@ -539,29 +764,39 @@ void OccTransactionManager::ReleaseHeaderLocks(TxnManager* txMan, uint32_t numOf } } -void OccTransactionManager::ReleaseRowsLocks(TxnManager* txMan, uint32_t numOfLocks) +/* + * 鍔熻兘锛氶噴鏀捐鐨勯攣 + * + * 鍙傛暟鍒楄〃锛 + * txMan锛氫簨鍔$鐞嗗櫒鎸囬拡锛屽寘鍚渶瑕侀噴鏀鹃攣鐨勮 + * numOfLocks锛氶渶瑕侀噴鏀剧殑閿佺殑鏁伴噺 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庨噴鏀句簨鍔′腑琛岀殑閿侊紝鐗瑰埆鏄湪鍙戠敓鍥炴粴鎴栭噴鏀鹃攣鏃躲 + * 瀹冮亶鍘嗘湁搴忕殑璁块棶闆嗗悎锛屽姣忎釜闇瑕侀噴鏀鹃攣鐨勮鎵ц閲婃斁鎿嶄綔銆 + */ +void OccTransactionManager::ReleaseRowsLocks(TxnManager *txMan, uint32_t numOfLocks) { - if (numOfLocks == 0) { + if (numOfLocks == 0) { // 濡傛灉闇瑕侀噴鏀剧殑閿佺殑鏁伴噺涓0锛屽垯鐩存帴杩斿洖 return; } - TxnAccess* tx = txMan->m_accessMgr.Get(); - TxnOrderedSet_t& orderedSet = tx->GetOrderedRowSet(); - - // use local counter to optimize - for (const auto& raPair : orderedSet) { - const Access* access = raPair.second; - if (access->m_type == RD) { + TxnAccess *tx = txMan->m_accessMgr.Get(); + TxnOrderedSet_t &orderedSet = tx->GetOrderedRowSet(); // 鑾峰彇鏈夊簭鐨勮闂泦鍚 + // 浣跨敤鏈湴璁℃暟鍣ㄨ繘琛屼紭鍖 + for (const auto &raPair : orderedSet) { // 閬嶅巻鏈夊簭鐨勮闂泦鍚 + const Access *access = raPair.second; // 鑾峰彇璁块棶瀵硅薄 + if (access->m_type == RD) { // 濡傛灉鎿嶄綔绫诲瀷鏄鍙栵紝鍒欑户缁笅涓娆″惊鐜 continue; } - if (access->m_params.IsPrimarySentinel()) { + if (access->m_params.IsPrimarySentinel()) { // 濡傛灉鏄富瑕佺殑 Sentinel numOfLocks--; - access->GetRowFromHeader()->m_rowHeader.Release(); - if (access->m_params.IsUpgradeInsert()) { - // This is the global row that we switched! - // Currently it's in the gc! - access->m_localInsertRow->m_rowHeader.Release(); + access->GetRowFromHeader()->m_rowHeader.Release(); // 閲婃斁琛岀殑閿 + if (access->m_params.IsUpgradeInsert()) { // 濡傛灉鏄崌绾ф彃鍏ユ搷浣 + // 杩欐槸鎴戜滑鍒囨崲鐨勫叏灞琛岋紒 + // 鐩墠瀹冨湪鍨冨溇鍥炴敹涓紒 + access->m_localInsertRow->m_rowHeader.Release(); // 閲婃斁鎻掑叆琛岀殑閿 } } if (!numOfLocks) { @@ -570,10 +805,19 @@ void OccTransactionManager::ReleaseRowsLocks(TxnManager* txMan, uint32_t numOfLo } } +/* + * 鍔熻兘锛氭竻鐞嗕簨鍔$鐞嗗櫒鐨勭姸鎬 + * + * 鍙傛暟鍒楄〃锛 + * 鏃犲弬鏁 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庢竻鐞嗕簨鍔$鐞嗗櫒鐨勭姸鎬侊紝灏嗙浉鍏宠鏁板櫒閲嶇疆涓洪浂锛屼互鍑嗗澶勭悊涓嬩竴涓簨鍔° + */ void OccTransactionManager::CleanUp() { - m_writeSetSize = 0; - m_insertSetSize = 0; - m_rowsSetSize = 0; + m_writeSetSize = 0; // 閲嶇疆鍐欓泦鍚堝ぇ灏忎负0 + m_insertSetSize = 0; // 閲嶇疆鎻掑叆闆嗗悎澶у皬涓0 + m_rowsSetSize = 0; // 閲嶇疆琛岄泦鍚堝ぇ灏忎负0 } } // namespace MOT diff --git a/src/gausskernel/storage/mot/core/concurrency_control/row_header.cpp b/src/gausskernel/storage/mot/core/concurrency_control/row_header.cpp index ee10b1664..967cd4d3b 100644 --- a/src/gausskernel/storage/mot/core/concurrency_control/row_header.cpp +++ b/src/gausskernel/storage/mot/core/concurrency_control/row_header.cpp @@ -34,9 +34,25 @@ namespace MOT { DECLARE_LOGGER(RowHeader, ConcurrenyControl); - -RC RowHeader::GetLocalCopy( - TxnAccess* txn, AccessType type, Row* localRow, const Row* origRow, TransactionId& lastTid) const +/* + * 鍔熻兘锛氳幏鍙栬鐨勬湰鍦板壇鏈 + * + * 鍙傛暟鍒楄〃锛 + * txn锛氫簨鍔¤闂璞℃寚閽堬紝鍖呭惈褰撳墠浜嬪姟鐨勪俊鎭 + * type锛氳闂被鍨嬶紝鎸囩ず鎿嶄綔绫诲瀷锛堜緥濡傦細璇诲彇銆佸啓鍏ャ佹彃鍏ョ瓑锛 + * localRow锛氱敤浜庡瓨鍌ㄦ湰鍦板壇鏈殑琛屽璞℃寚閽 + * origRow锛氬師濮嬭瀵硅薄鐨勬寚閽堬紝浠庝腑鑾峰彇瑕佸鍒剁殑鍐呭 + * lastTid锛氱敤浜庡瓨鍌ㄦ渶鍚庝竴涓簨鍔℃爣璇嗙鐨勫紩鐢 + * + * 杩斿洖鍊硷細 + * 濡傛灉鎴愬姛鑾峰彇鏈湴鍓湰锛岃繑鍥 RC_OK锛涘惁鍒欒繑鍥 RC_ABORT銆 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庤幏鍙栬鐨勬湰鍦板壇鏈紝浠ユ敮鎸佸苟鍙戜簨鍔°傚畠鎵ц浜嗗娆″皾璇曪紝鐩村埌鎴愬姛鑾峰彇琛岀殑鏈湴鍓湰銆 + * 鍦ㄨ幏鍙栨湰鍦板壇鏈椂锛屼細妫鏌ヨ鐨勭姸鎬佸拰閿侊紝浠ョ‘淇濆畨鍏ㄥ湴璁块棶鍜屼慨鏀硅鐨勫唴瀹广 + */ +RC RowHeader::GetLocalCopy(TxnAccess *txn, AccessType type, Row *localRow, const Row *origRow, + TransactionId &lastTid) const { uint64_t sleepTime = 1; uint64_t v = 0; @@ -85,11 +101,37 @@ RC RowHeader::GetLocalCopy( return RC_OK; } +/* + * 鍔熻兘锛氶獙璇佸啓鎿嶄綔鐨勪簨鍔℃爣璇嗙 + * + * 鍙傛暟鍒楄〃锛 + * tid锛氫簨鍔℃爣璇嗙锛岀敤浜庝笌琛岀殑褰撳墠浜嬪姟鏍囪瘑绗﹁繘琛屾瘮杈 + * + * 杩斿洖鍊硷細 + * 濡傛灉缁欏畾鐨勪簨鍔℃爣璇嗙涓庤鐨勫綋鍓嶄簨鍔℃爣璇嗙鍖归厤锛岃繑鍥瀟rue锛涘惁鍒欒繑鍥瀎alse銆 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庨獙璇佸啓鎿嶄綔鐨勪簨鍔℃爣璇嗙鏄惁涓庤鐨勫綋鍓嶄簨鍔℃爣璇嗙鍖归厤銆 + * 濡傛灉鍖归厤锛岃〃绀哄彲浠ヨ繘琛屽啓鎿嶄綔锛涘鏋滀笉鍖归厤锛岃〃绀哄叾浠栦簨鍔″凡缁忎慨鏀逛簡琛屻 + */ bool RowHeader::ValidateWrite(TransactionId tid) const { return (tid == GetCSN()); } +/* + * 鍔熻兘锛氶獙璇佽鎿嶄綔鐨勪簨鍔℃爣璇嗙 + * + * 鍙傛暟鍒楄〃锛 + * tid锛氫簨鍔℃爣璇嗙锛岀敤浜庝笌琛岀殑褰撳墠浜嬪姟鏍囪瘑绗﹁繘琛屾瘮杈 + * + * 杩斿洖鍊硷細 + * 濡傛灉缁欏畾鐨勪簨鍔℃爣璇嗙涓庤鐨勫綋鍓嶄簨鍔℃爣璇嗙鍖归厤涓旇鏈閿佸畾锛岃繑鍥瀟rue锛涘惁鍒欒繑鍥瀎alse銆 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庨獙璇佽鎿嶄綔鐨勪簨鍔℃爣璇嗙鏄惁鏈夋晥銆傚畠妫鏌ヨ鏄惁宸茶閿佸畾锛屽鏋滈攣瀹氬垯杩斿洖false锛 + * 鍚﹀垯妫鏌ョ粰瀹氱殑浜嬪姟鏍囪瘑绗︽槸鍚︿笌琛岀殑褰撳墠浜嬪姟鏍囪瘑绗﹀尮閰嶃 + */ bool RowHeader::ValidateRead(TransactionId tid) const { if (IsLocked() or (tid != GetCSN())) { @@ -98,10 +140,19 @@ bool RowHeader::ValidateRead(TransactionId tid) const return true; } - -void RowHeader::WriteChangesToRow(const Access* access, uint64_t csn) +/* + * 鍔熻兘锛氬皢鏇存敼鍐欏叆琛 + * + * 鍙傛暟鍒楄〃锛 + * access锛氳闂璞℃寚閽堬紝鍖呭惈瑕佸啓鍏ヨ鐨勬洿鏀逛俊鎭 + * csn锛氭彁浜ゅ簭鍒楀彿锛岀敤浜庢爣璇嗗啓鍏ョ殑鐗堟湰 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庡皢鏇存敼鍐欏叆琛屻傚畠鏍规嵁璁块棶绫诲瀷鎵ц涓嶅悓鐨勬搷浣滐紝鍖呮嫭澶嶅埗鏁版嵁銆佽缃簨鍔℃爣璇嗙绛夈 + */ +void RowHeader::WriteChangesToRow(const Access *access, uint64_t csn) { - Row* row = access->GetRowFromHeader(); + Row *row = access->GetRowFromHeader(); AccessType type = access->m_type; if (type == RD) { @@ -112,8 +163,8 @@ void RowHeader::WriteChangesToRow(const Access* access, uint64_t csn) uint64_t v = m_csnWord; if (!MOTEngine::GetInstance()->IsRecovering()) { if (!(csn > GetCSN() && (v & LOCK_BIT))) { - MOT_LOG_ERROR( - "csn=%ld, v & LOCK_BIT=%ld, v & (~LOCK_BIT)=%ld\n", csn, (v & LOCK_BIT), (v & (~LOCK_BIT))); + MOT_LOG_ERROR("csn=%ld, v & LOCK_BIT=%ld, v & (~LOCK_BIT)=%ld\n", csn, (v & LOCK_BIT), + (v & (~LOCK_BIT))); MOT_ASSERT(false); } } @@ -152,7 +203,14 @@ void RowHeader::WriteChangesToRow(const Access* access, uint64_t csn) break; } } - +/* + * 鍔熻兘锛氶攣瀹氳澶翠俊鎭 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庨攣瀹氳澶翠俊鎭紝浠ョ‘淇濆叾浠栦簨鍔℃棤娉曞悓鏃朵慨鏀硅琛屻 + * 瀹冧娇鐢ㄥ師瀛愭搷浣滄潵璁剧疆琛屽ご涓殑閿佸畾浣嶏紙LOCK_BIT锛夈 + * 濡傛灉琛屽ご宸茬粡琚攣瀹氾紝鍒欎細绛夊緟鐩村埌鎴愬姛閿佸畾銆 + */ void RowHeader::Lock() { uint64_t v = m_csnWord; diff --git a/src/gausskernel/storage/mot/core/infra/config/cmdline_config_loader.cpp b/src/gausskernel/storage/mot/core/infra/config/cmdline_config_loader.cpp index e707226f7..d62bfd00e 100644 --- a/src/gausskernel/storage/mot/core/infra/config/cmdline_config_loader.cpp +++ b/src/gausskernel/storage/mot/core/infra/config/cmdline_config_loader.cpp @@ -32,25 +32,45 @@ DECLARE_LOGGER(CmdLineConfigLoader, Configuration) static const char CMDLINE_SEP = '-'; -static bool ParseCmdLineSectionName(const mot_string& line, mot_string& sectionPath, mot_string& keyValuePart) +/* + * 鍔熻兘锛氳В鏋愬懡浠よ涓殑閮ㄥ垎鍚嶇О + * + * 鍙傛暟鍒楄〃锛 + * line锛氬寘鍚儴鍒嗗悕绉扮殑杈撳叆瀛楃涓 + * sectionPath锛氱敤浜庡瓨鍌ㄩ儴鍒嗚矾寰勭殑杈撳嚭瀛楃涓 + * keyValuePart锛氱敤浜庡瓨鍌ㄩ敭鍊奸儴鍒嗙殑杈撳嚭瀛楃涓 + * + * 杩斿洖鍊硷細 + * 濡傛灉鎴愬姛瑙f瀽閮ㄥ垎鍚嶇О锛屽垯杩斿洖true锛涘惁鍒欒繑鍥瀎alse銆 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庝粠杈撳叆瀛楃涓蹭腑瑙f瀽閮ㄥ垎璺緞鍜岄敭鍊奸儴鍒嗐 + * 杈撳叆瀛楃涓插簲鍖呭惈涓涓垎闅旂锛圕MDLINE_SEP锛夛紝鐢ㄤ簬鍒嗛殧閮ㄥ垎璺緞鍜岄敭鍊奸儴鍒嗐 + * 濡傛灉瑙f瀽鎴愬姛锛岀粨鏋滃瓨鍌ㄥ湪sectionPath鍜宬eyValuePart涓紝骞惰繑鍥瀟rue銆 + * 濡傛灉瑙f瀽澶辫触锛屽皢璁板綍閿欒淇℃伅骞惰繑鍥瀎alse銆 + */ +static bool ParseCmdLineSectionName(const mot_string &line, mot_string §ionPath, mot_string &keyValuePart) { bool result = false; + // 鏌ユ壘鏈鍚庝竴涓垎闅旂鐨勪綅缃 uint32_t lastSlashPos = line.find_last_of(CMDLINE_SEP); + if (lastSlashPos != mot_string::npos) { + // 灏嗚緭鍏ュ瓧绗︿覆鐨勪竴閮ㄥ垎澶嶅埗鍒皊ectionPath涓 if (!line.substr(sectionPath, 0, lastSlashPos) || !line.substr(keyValuePart, lastSlashPos + 1)) { + // 濡傛灉澶嶅埗澶辫触锛岃褰曞唴瀛樺垎閰嶉敊璇 MOT_REPORT_ERROR(MOT_ERROR_OOM, "Load Configuration", "Failed to parse section name"); } else { + // 鍘婚櫎鍓嶅悗鐨勭┖鐧藉瓧绗 sectionPath.trim(); keyValuePart.trim(); - result = true; + result = true; // 瑙f瀽鎴愬姛 } } else { - MOT_REPORT_ERROR(MOT_ERROR_INVALID_CFG, - "Load Configuration", - "Malformed command line argument missing separator %c: %s", - CMDLINE_SEP, - line.c_str()); + // 濡傛灉鎵句笉鍒板垎闅旂锛岃褰曢厤缃棤鏁堢殑閿欒淇℃伅 + MOT_REPORT_ERROR(MOT_ERROR_INVALID_CFG, "Load Configuration", + "Malformed command line argument missing separator %c: %s", CMDLINE_SEP, line.c_str()); } return result; @@ -63,51 +83,100 @@ static bool ParseCmdLineSectionName(const mot_string& line, mot_string& sectionP break; \ } -static ConfigSection* GetCmdLineConfigSection( - const mot_string& sectionFullName, mot_list& parsedSections, ConfigSectionMap& sectionMap) +/* + * 鍔熻兘锛氭牴鎹儴鍒嗗叏鍚嶈幏鍙栧懡浠よ閰嶇疆閮ㄥ垎 + * + * 鍙傛暟鍒楄〃锛 + * sectionFullName锛氳鑾峰彇鐨勯儴鍒嗙殑鍏ㄥ悕 + * parsedSections锛氬凡瑙f瀽鐨勯儴鍒嗗垪琛紝鐢ㄤ簬瀛樺偍宸茶В鏋愮殑閮ㄥ垎瀵硅薄 + * sectionMap锛氶儴鍒嗘槧灏勶紝灏嗛儴鍒嗗叏鍚嶆槧灏勫埌閮ㄥ垎瀵硅薄 + * + * 杩斿洖鍊硷細 + * 濡傛灉鎴愬姛鑾峰彇鎴栧垱寤洪儴鍒嗗璞★紝鍒欒繑鍥炶閮ㄥ垎瀵硅薄鐨勬寚閽堬紱鍚﹀垯杩斿洖nullptr銆 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庢牴鎹儴鍒嗙殑鍏ㄥ悕鑾峰彇鐩稿簲鐨勯儴鍒嗗璞°傚鏋滈儴鍒嗗凡瀛樺湪浜巗ectionMap涓紝 + * 鍒欑洿鎺ヨ繑鍥炶閮ㄥ垎瀵硅薄锛涘惁鍒欙紝鏍规嵁鍏ㄥ悕鍒涘缓涓涓柊鐨勯儴鍒嗗璞″苟灏嗗叾鎻掑叆sectionMap涓 + * 濡傛灉鍑虹幇閿欒锛堝鍐呭瓨鍒嗛厤澶辫触鎴栨棤娉曡В鏋愰儴鍒嗗悕绉帮級锛屽皢璁板綍閿欒淇℃伅骞惰繑鍥瀗ullptr銆 + */ +static ConfigSection *GetCmdLineConfigSection(const mot_string §ionFullName, + mot_list &parsedSections, ConfigSectionMap §ionMap) { mot_string sectionPath; mot_string sectionName; + + // 灏濊瘯鏌ユ壘閮ㄥ垎鍏ㄥ悕鏄惁宸插湪sectionMap涓 ConfigSectionMap::iterator itr = sectionMap.find(sectionFullName); + if (itr == sectionMap.end()) { + // 濡傛灉閮ㄥ垎鍏ㄥ悕涓嶅瓨鍦ㄤ簬sectionMap涓 if (!ConfigFileParser::BreakSectionName(sectionFullName, sectionPath, sectionName, CMDLINE_SEP)) { + // 鏃犳硶瑙f瀽閮ㄥ垎鍚嶇О锛岃褰曢敊璇苟杩斿洖nullptr MOT_REPORT_ERROR(MOT_ERROR_INTERNAL, "Load Configuration", "Failed to parse section name"); return nullptr; } - ConfigSection* currentSection = ConfigSection::CreateConfigSection(sectionPath.c_str(), sectionName.c_str()); + // 鍒涘缓鏂扮殑閰嶇疆閮ㄥ垎瀵硅薄 + ConfigSection *currentSection = ConfigSection::CreateConfigSection(sectionPath.c_str(), sectionName.c_str()); if (currentSection == nullptr) { - MOT_REPORT_ERROR( - MOT_ERROR_OOM, "Load Configuration", "Failed to allocate memory for configuration section"); + // 鍐呭瓨鍒嗛厤澶辫触锛岃褰曢敊璇苟杩斿洖nullptr + MOT_REPORT_ERROR(MOT_ERROR_OOM, "Load Configuration", + "Failed to allocate memory for configuration section"); return nullptr; } + // 灏嗘柊鍒涘缓鐨勯儴鍒嗗璞℃坊鍔犲埌parsedSections鍒楄〃涓 if (!parsedSections.push_back(currentSection)) { + // 鎻掑叆澶辫触锛岃褰曢敊璇苟杩斿洖nullptr MOT_REPORT_ERROR(MOT_ERROR_OOM, "Load Configuration", "Failed to insert parsed section"); return nullptr; } + // 灏嗘柊鍒涘缓鐨勯儴鍒嗗璞℃彃鍏ectionMap涓紝浠ヤ究涓嬫鍙互鐩存帴鑾峰彇 itr = sectionMap.insert(ConfigSectionMap::value_type(sectionFullName, currentSection)).first; } + // 杩斿洖鑾峰彇鍒扮殑閮ㄥ垎瀵硅薄 return itr->second; } - -static bool AddCmdLineArrayConfigItem(ConfigSection* currentSection, const mot_string& sectionFullName, - const mot_string& key, const mot_string& value, uint64_t arrayIndex) +/* + * 鍔熻兘锛氭坊鍔犲懡浠よ鏁扮粍閰嶇疆椤 + * + * 鍙傛暟鍒楄〃锛 + * currentSection锛氬綋鍓嶉儴鍒嗗璞★紝琛ㄧず姝e湪鍔犺浇鐨勯儴鍒 + * sectionFullName锛氶儴鍒嗙殑鍏ㄥ悕锛岀敤浜庡敮涓鏍囪瘑閮ㄥ垎 + * key锛氶厤缃」鐨勯敭鍚嶇О + * value锛氶厤缃」鐨勫 + * arrayIndex锛氭暟缁勭储寮曪紝鐢ㄤ簬鎸囩ず閰嶇疆椤瑰湪鏁扮粍涓殑浣嶇疆 + * + * 杩斿洖鍊硷細 + * 濡傛灉鎴愬姛娣诲姞閰嶇疆椤癸紝鍒欒繑鍥瀟rue锛涘惁鍒欒繑鍥瀎alse銆 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庢坊鍔犲懡浠よ涓殑鏁扮粍閰嶇疆椤瑰埌閰嶇疆閮ㄥ垎涓 + * 濡傛灉鎸囧畾鐨勬暟缁勯厤缃」涓嶅瓨鍦紝灏嗕細鍒涘缓涓涓柊鐨勬暟缁勩 + * 濡傛灉鍒涘缓澶辫触鎴栨坊鍔犻厤缃」澶辫触锛屽皢璁板綍閿欒淇℃伅骞惰繑鍥瀎alse銆 + * 姝ゅ锛岃繕浼氭鏌ユ暟缁勯」鐨勯『搴忔槸鍚︽纭紝浠ョ‘淇濆畠浠寜椤哄簭娣诲姞鍒版暟缁勪腑銆 + */ +static bool AddCmdLineArrayConfigItem(ConfigSection *currentSection, const mot_string §ionFullName, + const mot_string &key, const mot_string &value, uint64_t arrayIndex) { // create array if not created yet - ConfigArray* configArray = currentSection->ModifyConfigArray(key.c_str()); + ConfigArray *configArray = currentSection->ModifyConfigArray(key.c_str()); if (configArray == nullptr) { + // 鍒涘缓鏂扮殑鏁扮粍閰嶇疆椤 configArray = ConfigArray::CreateConfigArray(sectionFullName.c_str(), key.c_str()); if (configArray == nullptr) { + // 鍐呭瓨鍒嗛厤澶辫触锛岃褰曢敊璇苟杩斿洖false MOT_REPORT_ERROR(MOT_ERROR_OOM, "Load Configuration", "Failed to allocate memory for configuration array"); return false; } + // 灏嗘暟缁勯厤缃」娣诲姞鍒板綋鍓嶉儴鍒 if (!currentSection->AddConfigItem(configArray)) { - MOT_REPORT_ERROR( - MOT_ERROR_OOM, "Load Configuration", "Failed to add configuration array to parent section"); + // 娣诲姞澶辫触锛岃褰曢敊璇苟杩斿洖false + MOT_REPORT_ERROR(MOT_ERROR_OOM, "Load Configuration", + "Failed to add configuration array to parent section"); return false; } } @@ -115,42 +184,56 @@ static bool AddCmdLineArrayConfigItem(ConfigSection* currentSection, const mot_s // create item and add it to array if (arrayIndex != configArray->GetConfigItemCount()) { // array items must be ordered - MOT_REPORT_ERROR(MOT_ERROR_INVALID_CFG, - "Load Configuration", + MOT_REPORT_ERROR( + MOT_ERROR_INVALID_CFG, "Load Configuration", "Failed to parse command line arguments: array %s items not well-ordered, expecting %u, got %" PRIu64, - configArray->GetName(), - configArray->GetConfigItemCount(), - arrayIndex); + configArray->GetName(), configArray->GetConfigItemCount(), arrayIndex); return false; } - ConfigItem* configItem = ConfigFileParser::MakeArrayConfigValue(sectionFullName, arrayIndex, value); + // 鍒涘缓閰嶇疆椤瑰苟娣诲姞鍒版暟缁勪腑 + ConfigItem *configItem = ConfigFileParser::MakeArrayConfigValue(sectionFullName, arrayIndex, value); if (configItem == nullptr) { - MOT_REPORT_ERROR(MOT_ERROR_OOM, - "Load Configuration", - "Failed to create array configuration value from raw value: %s", - value.c_str()); + // 鍒涘缓閰嶇疆椤瑰け璐ワ紝璁板綍閿欒骞惰繑鍥瀎alse + MOT_REPORT_ERROR(MOT_ERROR_OOM, "Load Configuration", + "Failed to create array configuration value from raw value: %s", value.c_str()); return false; } - + // 灏嗛厤缃」娣诲姞鍒版暟缁勪腑 if (!configArray->AddConfigItem(configItem)) { - MOT_REPORT_ERROR(MOT_ERROR_OOM, - "Load Configuration", - "Failed to add %" PRIu64 "th item to configuration array %s", - arrayIndex, - configArray->GetName()); + // 娣诲姞閰嶇疆椤瑰け璐ワ紝璁板綍閿欒骞惰繑鍥瀎alse + MOT_REPORT_ERROR(MOT_ERROR_OOM, "Load Configuration", + "Failed to add %" PRIu64 "th item to configuration array %s", arrayIndex, + configArray->GetName()); return false; } + // 閰嶇疆椤规坊鍔犳垚鍔 return true; } - -ConfigTree* CmdLineConfigLoader::ParseCmdLine(char** argv, int argc) +/* + * 鍔熻兘锛氳В鏋愬懡浠よ鍙傛暟骞舵瀯寤洪厤缃爲 + * + * 鍙傛暟鍒楄〃锛 + * argv锛氬懡浠よ鍙傛暟鏁扮粍 + * argc锛氬懡浠よ鍙傛暟鏁伴噺 + * + * 杩斿洖鍊硷細 + * 濡傛灉鎴愬姛瑙f瀽鍛戒护琛屽弬鏁板苟鏋勫缓閰嶇疆鏍戯紝鍒欒繑鍥為厤缃爲鎸囬拡锛涘惁鍒欒繑鍥瀗ullptr銆 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庤В鏋愬懡浠よ鍙傛暟锛屽苟鏋勫缓涓涓厤缃爲鏉ヨ〃绀鸿繖浜涘弬鏁般 + * 鍛戒护琛屽弬鏁板簲閬靛惊鏍煎紡锛--section1-section2-section3-key=value銆 + * 濡傛灉瑙f瀽杩囩▼涓嚭鐜伴敊璇紙濡傚唴瀛樺垎閰嶅け璐ャ佽В鏋愬け璐ョ瓑锛夛紝灏嗚褰曢敊璇俊鎭苟杩斿洖nullptr銆 + */ +ConfigTree *CmdLineConfigLoader::ParseCmdLine(char **argv, int argc) { // section names are separated by dashes, it is expected to have the format: // --section1-section2-section3-key=value - ConfigTree* cfgTree = ConfigTree::CreateConfigTree(GetPriority(), GetName(), true); + // 鍒涘缓閰嶇疆鏍戝璞★紝琛ㄧず鍛戒护琛屽弬鏁 + ConfigTree *cfgTree = ConfigTree::CreateConfigTree(GetPriority(), GetName(), true); if (cfgTree == nullptr) { + // 鍒涘缓閰嶇疆鏍戝け璐ワ紝璁板綍閿欒骞惰繑鍥瀗ullptr MOT_REPORT_ERROR(MOT_ERROR_OOM, "Load Configuration", "Failed to create configuration tree"); return nullptr; } @@ -158,8 +241,8 @@ ConfigTree* CmdLineConfigLoader::ParseCmdLine(char** argv, int argc) mot_string line; mot_string sectionFullName; mot_string keyValuePart; - ConfigSection* currentSection = nullptr; - mot_list parsedSections; + ConfigSection *currentSection = nullptr; + mot_list parsedSections; ConfigSectionMap sectionMap; mot_string key; mot_string value; @@ -168,16 +251,20 @@ ConfigTree* CmdLineConfigLoader::ParseCmdLine(char** argv, int argc) bool hasArrayIndex = false; for (int i = 0; i < argc && !parseError; ++i) { + // 灏嗗懡浠よ鍙傛暟杞崲涓哄瓧绗︿覆瀵硅薄 if (!line.assign(argv[i])) { - CMDLINE_REPORT_PARSE_ERROR_AND_BREAK( - MOT_ERROR_OOM, "Failed to allocate memory for next command line argument"); + CMDLINE_REPORT_PARSE_ERROR_AND_BREAK(MOT_ERROR_OOM, + "Failed to allocate memory for next command line argument"); } + // 妫鏌ュ懡浠よ鍙傛暟鏄惁浠"--"寮澶翠笖闀垮害涓嶅皬浜2 if ((line.length() <= 2) || line[0] != '-' || line[1] != '-') { + // 蹇界暐鏍煎紡涓嶆纭殑鍛戒护琛屽弬鏁 MOT_LOG_TRACE("Skipping ill-formed command line argument: %s", argv[i]); continue; } + // 瑙f瀽鍛戒护琛屽弬鏁扮殑閮ㄥ垎鍚嶇О if (!ParseCmdLineSectionName(line, sectionFullName, keyValuePart)) { CMDLINE_REPORT_PARSE_ERROR_AND_BREAK(MOT_ERROR_INTERNAL, "Failed to parse command line argument"); } @@ -196,31 +283,36 @@ ConfigTree* CmdLineConfigLoader::ParseCmdLine(char** argv, int argc) // check for array item if (!hasArrayIndex) { - ConfigItem* configItem = ConfigFileParser::MakeConfigValue(sectionFullName, key, value); + // 鍒涘缓閰嶇疆鍊煎璞″苟娣诲姞鍒伴儴鍒嗕腑 + ConfigItem *configItem = ConfigFileParser::MakeConfigValue(sectionFullName, key, value); if (configItem == nullptr) { + // 鍒涘缓閰嶇疆椤瑰け璐ワ紝璁板綍閿欒骞惰繑鍥瀎alse CMDLINE_REPORT_PARSE_ERROR_AND_BREAK(MOT_ERROR_INTERNAL, - "Failed to create configuration value from raw key/value: %s/%s", - key.c_str(), - value.c_str()); + "Failed to create configuration value from raw key/value: %s/%s", + key.c_str(), value.c_str()); } else if (!currentSection->AddConfigItem(configItem)) { - CMDLINE_REPORT_PARSE_ERROR_AND_BREAK( - MOT_ERROR_OOM, "Failed to add configuration value to parent section"); + // 娣诲姞閰嶇疆椤瑰け璐ワ紝璁板綍閿欒骞惰繑鍥瀎alse + CMDLINE_REPORT_PARSE_ERROR_AND_BREAK(MOT_ERROR_OOM, + "Failed to add configuration value to parent section"); } } else { + // 娣诲姞鏁扮粍閰嶇疆椤 if (!AddCmdLineArrayConfigItem(currentSection, sectionFullName, key, value, arrayIndex)) { - CMDLINE_REPORT_PARSE_ERROR_AND_BREAK(MOT_ERROR_INTERNAL, - "Failed to add array item with arrayIndex %lu (command line argument: %s)", - arrayIndex, - line.c_str()); + // 娣诲姞鏁扮粍椤瑰け璐ワ紝璁板綍閿欒骞惰繑鍥瀎alse + CMDLINE_REPORT_PARSE_ERROR_AND_BREAK( + MOT_ERROR_INTERNAL, "Failed to add array item with arrayIndex %lu (command line argument: %s)", + arrayIndex, line.c_str()); } } } if (parseError) { + // 瑙f瀽杩囩▼涓嚭鐜伴敊璇紝閲婃斁閰嶇疆鏍戝苟杩斿洖nullptr delete cfgTree; cfgTree = nullptr; } else { if (!cfgTree->Build(parsedSections)) { + // 鏋勫缓閰嶇疆鏍戝け璐ワ紝璁板綍閿欒骞堕噴鏀鹃厤缃爲 MOT_REPORT_ERROR(MOT_ERROR_INTERNAL, "Load Configuration", "Failed to build configuration tree"); delete cfgTree; cfgTree = nullptr; diff --git a/src/gausskernel/storage/mot/core/infra/config/config_array.cpp b/src/gausskernel/storage/mot/core/infra/config/config_array.cpp index 697660ba2..0a29fdf65 100644 --- a/src/gausskernel/storage/mot/core/infra/config/config_array.cpp +++ b/src/gausskernel/storage/mot/core/infra/config/config_array.cpp @@ -30,7 +30,18 @@ ConfigArray::ConfigArray() : ConfigItem(ConfigItemClass::CONFIG_ITEM_ARRAY) ConfigArray::~ConfigArray() {} - +/* + * 鍔熻兘锛氭墦鍗伴厤缃暟缁勭殑鍐呭 + * + * 鍙傛暟鍒楄〃锛 + * logLevel锛氭棩蹇楃骇鍒紝鎸囧畾鎵撳嵃鏃ュ織鐨勭骇鍒 + * fullPrint锛氭槸鍚﹀畬鏁存墦鍗帮紝濡傛灉涓篺alse锛屽垯鍙墦鍗伴儴鍒嗗悕绉帮紝鍚﹀垯鎵撳嵃瀹屾暣鍐呭 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庢墦鍗伴厤缃暟缁勭殑鍐呭銆傚彲浠ラ夋嫨鏄惁鎵撳嵃瀹屾暣鐨勬暟缁勫唴瀹广 + * 濡傛灉fullPrint涓篺alse锛屽皢浠呮墦鍗伴儴鍒嗗悕绉帮紝鍚﹀垯灏嗘墦鍗板畬鏁村唴瀹广 + * 鎵撳嵃鐨勫唴瀹瑰寘鎷暟缁勭殑閮ㄥ垎鍚嶇О鍜屾暟缁勯」鐨勫笺 + */ void ConfigArray::Print(LogLevel logLevel, bool fullPrint) const { // print indented section name @@ -43,28 +54,39 @@ void ConfigArray::Print(LogLevel logLevel, bool fullPrint) const if (!fullPrint) { MOT_LOG(logLevel, "%*s%s[%u]", GetDepth(), "", GetName(), i); } + // 鎵撳嵃鏁扮粍椤圭殑鍊 mItemArray[i]->Print(logLevel, fullPrint); } } -void ConfigArray::ForEach(ConfigItemVisitor& visitor) const +/* + * 鍔熻兘锛氭墦鍗伴厤缃暟缁勭殑鍐呭 + * + * 鍙傛暟鍒楄〃锛 + * logLevel锛氭棩蹇楃骇鍒紝鎸囧畾鎵撳嵃鏃ュ織鐨勭骇鍒 + * fullPrint锛氭槸鍚﹀畬鏁存墦鍗帮紝濡傛灉涓篺alse锛屽垯鍙墦鍗伴儴鍒嗗悕绉帮紝鍚﹀垯鎵撳嵃瀹屾暣鍐呭 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庢墦鍗伴厤缃暟缁勭殑鍐呭銆傚彲浠ラ夋嫨鏄惁鎵撳嵃瀹屾暣鐨勬暟缁勫唴瀹广 + * 濡傛灉fullPrint涓篺alse锛屽皢浠呮墦鍗伴儴鍒嗗悕绉帮紝鍚﹀垯灏嗘墦鍗板畬鏁村唴瀹广 + * 鎵撳嵃鐨勫唴瀹瑰寘鎷暟缁勭殑閮ㄥ垎鍚嶇О鍜屾暟缁勯」鐨勫笺 + */ +void ConfigArray::Print(LogLevel logLevel, bool fullPrint) const { - visitor.OnConfigItem(this); + // 鎵撳嵃缂╄繘鐨勯儴鍒嗗悕绉 + if (!fullPrint) { + MOT_LOG(logLevel, "%*s%s", GetDepth(), "", GetName()); + } + + // 鎵撳嵃鏁扮粍椤圭殑鍊 for (uint32_t i = 0; i < mItemArray.size(); ++i) { - const ConfigItem* configItem = mItemArray[i]; - switch (configItem->GetClass()) { - case ConfigItemClass::CONFIG_ITEM_SECTION: - static_cast(configItem)->ForEach(visitor); - break; - - case ConfigItemClass::CONFIG_ITEM_ARRAY: - static_cast(configItem)->ForEach(visitor); - break; - - default: - visitor.OnConfigItem(configItem); - break; + if (!fullPrint) { + MOT_LOG(logLevel, "%*s%s[%u]", GetDepth(), "", GetName(), i); } + + // 鎵撳嵃鏁扮粍椤圭殑鍊 + mItemArray[i]->Print(logLevel, fullPrint); } } + } // namespace MOT diff --git a/src/gausskernel/storage/mot/core/infra/config/config_file_loader.cpp b/src/gausskernel/storage/mot/core/infra/config/config_file_loader.cpp index 83171dacc..32c107f46 100644 --- a/src/gausskernel/storage/mot/core/infra/config/config_file_loader.cpp +++ b/src/gausskernel/storage/mot/core/infra/config/config_file_loader.cpp @@ -29,28 +29,57 @@ namespace MOT { DECLARE_LOGGER(ConfigFileLoader, Configuration) -static void FormatTime(uint64_t timeVal, char* buf, uint32_t len) +/* + * 鍔熻兘锛氬皢鏃堕棿鍊兼牸寮忓寲涓哄瓧绗︿覆 + * + * 鍙傛暟鍒楄〃锛 + * timeVal锛氭椂闂村硷紝浠ョ撼绉掍负鍗曚綅 + * buf锛氱敤浜庡瓨鍌ㄦ牸寮忓寲鍚庣殑鏃堕棿瀛楃涓茬殑缂撳啿鍖 + * len锛氱紦鍐插尯闀垮害 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庡皢鏃堕棿鍊兼牸寮忓寲涓哄瓧绗︿覆锛屽苟瀛樺偍鍦ㄧ粰瀹氱殑缂撳啿鍖轰腑銆 + * 鏃堕棿鍊间互绾崇涓哄崟浣嶏紝骞惰浆鎹负鏃ユ湡鏃堕棿鏍煎紡锛"%F %T.%09ld"锛夈 + * 濡傛灉杞崲鎴愬姛锛岀粨鏋滃瓨鍌ㄥ湪buf涓紱鍚﹀垯涓嶈繘琛屼换浣曟搷浣溿 + */ +static void FormatTime(uint64_t timeVal, char *buf, uint32_t len) { + // 灏嗙撼绉掓椂闂村艰浆鎹负timespec缁撴瀯 timespec ts = {(long int)(timeVal / 1000000000ULL), (long int)(timeVal % 1000000000ULL)}; struct tm t; + // 浣跨敤localtime_r鍑芥暟灏嗘椂闂村艰浆鎹负tm缁撴瀯 if (localtime_r(&(ts.tv_sec), &t) != NULL) { + // 浣跨敤strftime鍑芥暟灏唗m缁撴瀯鏍煎紡鍖栦负鏃ユ湡鏃堕棿瀛楃涓 size_t ret = strftime(buf, len, "%F %T", &t); if (ret != 0) { + // 濡傛灉strftime鎴愬姛锛岀户缁坊鍔犵撼绉掗儴鍒 len -= ret; errno_t erc = snprintf_s(buf + ret, len, len - 1, ".%09ld", ts.tv_nsec); + // 妫鏌nprintf_s鐨勮繑鍥炲 securec_check_ss(erc, "\0", "\0"); } } } -ConfigFileLoader::ConfigFileLoader( - const char* typeName, const char* name, uint32_t priority, const char* configFilePath) +ConfigFileLoader::ConfigFileLoader(const char *typeName, const char *name, uint32_t priority, + const char *configFilePath) : ConfigLoader(ComposeFullName(typeName, name, configFilePath).c_str(), priority), m_configFilePath(configFilePath), m_lastModTime(GetFileModificationTime()) {} +/* + * 鍔熻兘锛氭鏌ラ厤缃枃浠舵槸鍚﹀凡鏇存敼 + * + * 杩斿洖鍊硷細 + * 濡傛灉閰嶇疆鏂囦欢鐨勪慨鏀规椂闂磋緝涓婃妫鏌ュ彂鐢熶簡鏇存敼锛屽垯杩斿洖true锛涘惁鍒欒繑鍥瀎alse銆 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庢鏌ラ厤缃枃浠剁殑淇敼鏃堕棿鏄惁涓庝笂娆℃鏌ヤ笉鍚屻 + * 濡傛灉淇敼鏃堕棿鍙戠敓鏇存敼锛屽皢璁板綍鏃ュ織淇℃伅锛屾洿鏂颁笂娆℃鏌ョ殑鏃堕棿锛屽苟杩斿洖true锛 + * 鍚﹀垯锛岃繑鍥瀎alse銆 + */ bool ConfigFileLoader::HasChanged() { bool result = false; @@ -58,35 +87,68 @@ bool ConfigFileLoader::HasChanged() if (modTime > m_lastModTime) { char lastDate[32]; char newDate[32]; + + // 鏍煎紡鍖栦笂娆℃鏌ョ殑淇敼鏃堕棿鍜屾柊鐨勪慨鏀规椂闂 FormatTime(m_lastModTime, lastDate, sizeof(lastDate)); FormatTime(modTime, newDate, sizeof(newDate)); + + // 璁板綍閰嶇疆鏂囦欢鍙戠敓鏇存敼鐨勬棩蹇椾俊鎭 MOT_LOG_INFO("Detected change in configuration file: %s (modification time changed: %" PRIu64 " --> %" PRIu64 " [%s --> %s])", - m_configFilePath.c_str(), - m_lastModTime, - modTime, - lastDate, - newDate); + m_configFilePath.c_str(), m_lastModTime, modTime, lastDate, newDate); + + // 鏇存柊涓婃妫鏌ョ殑淇敼鏃堕棿 m_lastModTime = modTime; result = true; } return result; } -mot_string ConfigFileLoader::ComposeFullName(const char* typeName, const char* name, const char* configFilePath) +/* + * 鍔熻兘锛氱粍鍚堝畬鏁寸殑閰嶇疆椤瑰悕绉 + * + * 鍙傛暟鍒楄〃锛 + * typeName锛氶厤缃」绫诲瀷鐨勫悕绉 + * name锛氶厤缃」鐨勫悕绉 + * configFilePath锛氶厤缃枃浠剁殑璺緞 + * + * 杩斿洖鍊硷細 + * 杩斿洖缁勫悎鍚庣殑瀹屾暣閰嶇疆椤瑰悕绉帮紙mot_string瀵硅薄锛夈 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庡皢閰嶇疆椤圭殑绫诲瀷鍚嶇О銆佸悕绉板拰閰嶇疆鏂囦欢璺緞缁勫悎鎴愪竴涓畬鏁寸殑閰嶇疆椤瑰悕绉般 + * 閰嶇疆椤瑰悕绉扮殑鏍煎紡涓猴細"[]@"銆 + */ +mot_string ConfigFileLoader::ComposeFullName(const char *typeName, const char *name, const char *configFilePath) { mot_string result; + // 浣跨敤mot_string鐨刦ormat鏂规硶灏嗙被鍨嬪悕绉般佸悕绉板拰閰嶇疆鏂囦欢璺緞缁勫悎鎴愬畬鏁寸殑閰嶇疆椤瑰悕绉 result.format("%s[%s]@%s", typeName, name, configFilePath); return result; } +/* + * 鍔熻兘锛氳幏鍙栭厤缃枃浠剁殑淇敼鏃堕棿 + * + * 杩斿洖鍊硷細 + * 杩斿洖閰嶇疆鏂囦欢鐨勪慨鏀规椂闂达紝浠ョ撼绉掍负鍗曚綅銆 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庤幏鍙栭厤缃枃浠剁殑淇敼鏃堕棿锛屽苟灏嗗叾杞崲涓虹撼绉掍负鍗曚綅鐨勬椂闂村笺 + * 濡傛灉鎴愬姛鑾峰彇閰嶇疆鏂囦欢鐨勪慨鏀规椂闂达紝灏嗚繑鍥炴椂闂村硷紱鍚﹀垯杩斿洖0銆 + */ uint64_t ConfigFileLoader::GetFileModificationTime() { uint64_t filetime = 0; struct stat buf; + + // 浣跨敤stat鍑芥暟鑾峰彇鏂囦欢鐨勪俊鎭紝鍖呮嫭淇敼鏃堕棿 if (stat(m_configFilePath.c_str(), &buf) == 0) { + // 璁$畻绾崇绾у埆鐨勪慨鏀规椂闂 filetime = buf.st_mtim.tv_sec * 1000000000ULL + buf.st_mtim.tv_nsec; } + return filetime; } + } // namespace MOT diff --git a/src/gausskernel/storage/mot/core/infra/config/config_file_parser.cpp b/src/gausskernel/storage/mot/core/infra/config/config_file_parser.cpp index 7c58642b7..6782f6a05 100644 --- a/src/gausskernel/storage/mot/core/infra/config/config_file_parser.cpp +++ b/src/gausskernel/storage/mot/core/infra/config/config_file_parser.cpp @@ -37,38 +37,85 @@ namespace MOT { IMPLEMENT_CLASS_LOGGER(ConfigFileParser, Configuration) -bool ConfigFileParser::BreakSectionName(const mot_string& sectionFullName, mot_string& sectionPath, - mot_string& sectionName, char sep /* = ConfigItem::PATH_SEP */) +/* + * 鍔熻兘锛氬垎瑙i厤缃儴鍒嗗悕绉 + * + * 鍙傛暟鍒楄〃锛 + * sectionFullName锛氬畬鏁寸殑閰嶇疆閮ㄥ垎鍚嶇О + * sectionPath锛氱敤浜庡瓨鍌ㄩ厤缃儴鍒嗚矾寰勭殑mot_string瀵硅薄 + * sectionName锛氱敤浜庡瓨鍌ㄩ厤缃儴鍒嗗悕绉扮殑mot_string瀵硅薄 + * sep锛氬垎闅旂锛屾寚绀洪厤缃儴鍒嗚矾寰勫拰鍚嶇О涔嬮棿鐨勫垎闅旂锛岄粯璁や负ConfigItem::PATH_SEP + * + * 杩斿洖鍊硷細 + * 濡傛灉鎴愬姛鍒嗚В閰嶇疆閮ㄥ垎鍚嶇О锛岃繑鍥瀟rue锛涘惁鍒欒繑鍥瀎alse銆 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庡垎瑙e畬鏁寸殑閰嶇疆閮ㄥ垎鍚嶇О锛屽皢鍏舵媶鍒嗕负閰嶇疆閮ㄥ垎璺緞鍜屽悕绉般 + * 鍒嗛殧绗ep鐢ㄤ簬鎸囩ず閰嶇疆閮ㄥ垎璺緞鍜屽悕绉颁箣闂寸殑鍒嗛殧绗︼紝榛樿涓篊onfigItem::PATH_SEP銆 + * 濡傛灉鎴愬姛鍒嗚В鍚嶇О锛屽皢缁撴灉瀛樺偍鍦╯ectionPath鍜宻ectionName鍙傛暟涓紝骞惰繑鍥瀟rue锛 + * 鍚﹀垯锛岃繑鍥瀎alse锛屽苟璁板綍閿欒淇℃伅銆 + */ +bool ConfigFileParser::BreakSectionName(const mot_string §ionFullName, mot_string §ionPath, + mot_string §ionName, char sep /* = ConfigItem::PATH_SEP */) { bool result = true; + + // 鏌ユ壘鏈鍚庝竴涓垎闅旂鐨勪綅缃 uint32_t lastSlashPos = sectionFullName.find_last_of(sep); + if (lastSlashPos != mot_string::npos) { + // 濡傛灉鎵惧埌鍒嗛殧绗︼紝灏嗗瓧绗︿覆鍒嗗壊鎴愯矾寰勫拰鍚嶇О if (!sectionFullName.substr(sectionPath, 0, lastSlashPos) || !sectionFullName.substr(sectionName, lastSlashPos + 1)) { MOT_REPORT_ERROR(MOT_ERROR_OOM, "Load Configuration", "Failed to parse section name"); result = false; } else { + // 鍘婚櫎绌虹櫧瀛楃 sectionPath.trim(); sectionName.trim(); } - } else if (!sectionPath.assign("") || !sectionName.assign(sectionFullName)) { - MOT_REPORT_ERROR(MOT_ERROR_OOM, "Load Configuration", "Failed to parse section name"); - result = false; + } else { + // 濡傛灉娌℃湁鎵惧埌鍒嗛殧绗︼紝灏嗘暣涓瓧绗︿覆浣滀负鍚嶇О锛岃矾寰勪负绌 + if (!sectionPath.assign("") || !sectionName.assign(sectionFullName)) { + MOT_REPORT_ERROR(MOT_ERROR_OOM, "Load Configuration", "Failed to parse section name"); + result = false; + } } + return result; } -bool ConfigFileParser::ParseKeyValue(const mot_string& keyValuePart, const mot_string& section, mot_string& key, - mot_string& value, uint64_t& arrayIndex, bool& hasArrayIndex) +/* + * 鍔熻兘锛氳В鏋愰敭鍊煎瀛楃涓 + * + * 鍙傛暟鍒楄〃锛 + * keyValuePart锛氬寘鍚敭鍊煎鐨勫瓧绗︿覆 + * section锛氶厤缃儴鍒嗙殑鍚嶇О + * key锛氱敤浜庡瓨鍌ㄩ敭鐨刴ot_string瀵硅薄 + * value锛氱敤浜庡瓨鍌ㄥ肩殑mot_string瀵硅薄 + * arrayIndex锛氱敤浜庡瓨鍌ㄦ暟缁勭储寮曠殑鏁存暟鍊 + * hasArrayIndex锛氭寚绀烘槸鍚﹀寘鍚暟缁勭储寮曠殑甯冨皵鍊硷紝濡傛灉鍖呭惈鍒欎负true锛屽惁鍒欎负false + * + * 杩斿洖鍊硷細 + * 濡傛灉鎴愬姛瑙f瀽閿煎瀛楃涓诧紝杩斿洖true锛涘惁鍒欒繑鍥瀎alse銆 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庤В鏋愬寘鍚敭鍊煎鐨勫瓧绗︿覆锛屽苟灏嗛敭銆佸笺佹暟缁勭储寮曚俊鎭彁鍙栧嚭鏉ャ + * 濡傛灉鎴愬姛瑙f瀽锛屽皢缁撴灉瀛樺偍鍦╧ey銆乿alue銆乤rrayIndex鍜宧asArrayIndex鍙傛暟涓紝骞惰繑鍥瀟rue锛 + * 鍚﹀垯锛岃繑鍥瀎alse锛屽苟璁板綍閿欒淇℃伅銆 + */ +bool ConfigFileParser::ParseKeyValue(const mot_string &keyValuePart, const mot_string §ion, mot_string &key, + mot_string &value, uint64_t &arrayIndex, bool &hasArrayIndex) { bool result = false; hasArrayIndex = false; + + // 鏌ユ壘绛夊彿鐨勪綅缃紝鍒嗗壊閿煎 uint32_t equalPos = keyValuePart.find('='); + if (equalPos == mot_string::npos) { - MOT_REPORT_ERROR(MOT_ERROR_INTERNAL, - "Load Configuration", - "Failed to parse key/value: missing equal sign (%s)", - keyValuePart.c_str()); + MOT_REPORT_ERROR(MOT_ERROR_INTERNAL, "Load Configuration", "Failed to parse key/value: missing equal sign (%s)", + keyValuePart.c_str()); } else if (!keyValuePart.substr(key, 0, equalPos) || !keyValuePart.substr(value, equalPos + 1)) { MOT_REPORT_ERROR(MOT_ERROR_INTERNAL, "Load Configuration", "Failed to parse key/value"); } else { @@ -76,69 +123,127 @@ bool ConfigFileParser::ParseKeyValue(const mot_string& keyValuePart, const mot_s value.trim(); result = true; - // check for array item + // 妫鏌ユ槸鍚﹀寘鍚暟缁勭储寮 uint32_t poundPos = key.find('#'); if (poundPos != mot_string::npos) { result = false; mot_string intPart; + + // 鎻愬彇鏁扮粍绱㈠紩鐨勬暣鏁伴儴鍒 if (!key.substr(intPart, poundPos + 1)) { - MOT_REPORT_ERROR( - MOT_ERROR_INTERNAL, "Load Configuration", "Failed to parse integer part from array item specifier"); + MOT_REPORT_ERROR(MOT_ERROR_INTERNAL, "Load Configuration", + "Failed to parse integer part from array item specifier"); } else { + // 瑙f瀽鏁存暟閮ㄥ垎骞跺瓨鍌ㄥ埌arrayIndex涓 if (ParseUIntValue(section, key, intPart, arrayIndex, true)) { hasArrayIndex = true; key.substr_inplace(0, poundPos); result = true; } else { - MOT_REPORT_ERROR(MOT_ERROR_INVALID_CFG, - "Load Configuration", - "Invalid array item specifier encountered: %s", - key.c_str()); + MOT_REPORT_ERROR(MOT_ERROR_INVALID_CFG, "Load Configuration", + "Invalid array item specifier encountered: %s", key.c_str()); } } } } + return result; } -ConfigItem* ConfigFileParser::MakeConfigValue( - const mot_string& sectionFullName, const mot_string& key, const mot_string& value) +/* + * 鍔熻兘锛氬垱寤洪厤缃」鐨勯氱敤閰嶇疆鍊 + * + * 鍙傛暟鍒楄〃锛 + * sectionFullName锛氬畬鏁寸殑閰嶇疆閮ㄥ垎鍚嶇О + * key锛氶敭鐨勫悕绉 + * value锛氬肩殑瀛楃涓茶〃绀 + * + * 杩斿洖鍊硷細 + * 濡傛灉鎴愬姛鍒涘缓閰嶇疆椤圭殑閫氱敤閰嶇疆鍊硷紝杩斿洖鎸囧悜閰嶇疆椤圭殑鎸囬拡锛涘惁鍒欒繑鍥瀗ullptr銆 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庢牴鎹彁渚涚殑鍙傛暟鍒涘缓閫氱敤閰嶇疆鍊笺 + * 棣栧厛锛屽畠妫鏌ラ敭鏄惁鍖呭惈绫诲瀷鎸囩ず绗︼紝濡傛灉鍖呭惈鍒欒皟鐢∕akeTypedConfigValue鍑芥暟鏉ュ垱寤虹被鍨嬪寲鐨勯厤缃硷紱 + * 鍚﹀垯锛岃皟鐢∕akeUntypedConfigValue鍑芥暟鏉ュ垱寤洪潪绫诲瀷鍖栫殑閰嶇疆鍊笺 + */ +ConfigItem *ConfigFileParser::MakeConfigValue(const mot_string §ionFullName, const mot_string &key, + const mot_string &value) { - ConfigItem* result = nullptr; + ConfigItem *result = nullptr; - // key may have type specifier (in the format type:key=value) + // 妫鏌ラ敭鏄惁鍖呭惈绫诲瀷鎸囩ず绗︼紙绫诲瀷:key=value锛 uint32_t colonPos = key.find(':'); if (colonPos != mot_string::npos) { mot_string typeName; mot_string keyName; + + // 鎻愬彇绫诲瀷鍚嶇О鍜岄敭鍚嶇О if (!key.substr(typeName, 0, colonPos) || !key.substr(keyName, colonPos + 1)) { MOT_REPORT_ERROR(MOT_ERROR_INTERNAL, "Load Configuration", "Failed to parse typed key %s", key.c_str()); } else { + // 璋冪敤MakeTypedConfigValue鍑芥暟鍒涘缓绫诲瀷鍖栫殑閰嶇疆鍊 result = MakeTypedConfigValue(sectionFullName, typeName, keyName, value); } } else { + // 璋冪敤MakeUntypedConfigValue鍑芥暟鍒涘缓闈炵被鍨嬪寲鐨勯厤缃 result = MakeUntypedConfigValue(sectionFullName, key, value); } return result; } -ConfigItem* ConfigFileParser::MakeArrayConfigValue(const mot_string& path, uint64_t arrayIndex, const mot_string& value) +/* + * 鍔熻兘锛氬垱寤烘暟缁勯厤缃」鐨勯厤缃 + * + * 鍙傛暟鍒楄〃锛 + * path锛氬寘鍚暟缁勯厤缃」鐨勫畬鏁磋矾寰 + * arrayIndex锛氭暟缁勭储寮 + * value锛氬肩殑瀛楃涓茶〃绀 + * + * 杩斿洖鍊硷細 + * 濡傛灉鎴愬姛鍒涘缓鏁扮粍閰嶇疆椤圭殑閰嶇疆鍊硷紝杩斿洖鎸囧悜閰嶇疆椤圭殑鎸囬拡锛涘惁鍒欒繑鍥瀗ullptr銆 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庢牴鎹彁渚涚殑鍙傛暟鍒涘缓鏁扮粍閰嶇疆椤圭殑閰嶇疆鍊笺 + * 棣栧厛锛屽畠灏嗘暟缁勭储寮曡浆鎹负瀛楃涓叉牸寮忥紝骞跺皢鍏剁敤浣滈敭銆 + * 鐒跺悗锛岃皟鐢∕akeConfigValue鍑芥暟鏉ュ垱寤洪厤缃硷紝鍏朵腑璺緞涓哄寘鍚暟缁勯厤缃」鐨勫畬鏁磋矾寰勶紝閿负鏁扮粍绱㈠紩瀛楃涓层 + */ +ConfigItem *ConfigFileParser::MakeArrayConfigValue(const mot_string &path, uint64_t arrayIndex, const mot_string &value) { - ConfigItem* result = nullptr; + ConfigItem *result = nullptr; mot_string key; + + // 灏嗘暟缁勭储寮曡浆鎹负瀛楃涓叉牸寮忥紝骞朵綔涓洪敭 if (!key.format("%lu", arrayIndex)) { MOT_REPORT_ERROR(MOT_ERROR_INTERNAL, "Load Configuration", "Failed to format array index %lu", arrayIndex); } else { + // 璋冪敤MakeConfigValue鍑芥暟鍒涘缓閰嶇疆鍊 result = MakeConfigValue(path, key, value); } + return result; } -ConfigItem* ConfigFileParser::MakeIntConfigValue(const mot_string& path, const mot_string& name, int64_t value) +/* + * 鍔熻兘锛氬垱寤烘暣鏁扮被鍨嬬殑閰嶇疆椤归厤缃 + * + * 鍙傛暟鍒楄〃锛 + * path锛氶厤缃」鎵鍦ㄧ殑璺緞 + * name锛氶厤缃」鐨勫悕绉 + * value锛氭暣鏁板 + * + * 杩斿洖鍊硷細 + * 濡傛灉鎴愬姛鍒涘缓鏁存暟绫诲瀷鐨勯厤缃」閰嶇疆鍊硷紝杩斿洖鎸囧悜閰嶇疆椤圭殑鎸囬拡锛涘惁鍒欒繑鍥瀗ullptr銆 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庢牴鎹彁渚涚殑鍙傛暟鍒涘缓鏁存暟绫诲瀷鐨勯厤缃」閰嶇疆鍊笺 + * 棣栧厛锛屽畠灏濊瘯灏嗘暣鏁板艰В鏋愪负涓嶅悓鐨勬暣鏁扮被鍨嬶紙浠庡皬鍒板ぇ锛夛紝骞舵牴鎹В鏋愮粨鏋滃垱寤虹浉搴旂被鍨嬬殑閰嶇疆椤广 + * 濡傛灉瑙f瀽鍜屽垱寤烘垚鍔燂紝灏嗚繑鍥炵浉搴旂殑閰嶇疆椤规寚閽堬紱鍚﹀垯杩斿洖nullptr锛屽苟璁板綍閿欒淇℃伅銆 + */ +ConfigItem *ConfigFileParser::MakeIntConfigValue(const mot_string &path, const mot_string &name, int64_t value) { // try to parse value as integer starting from smallest type - ConfigItem* result = nullptr; + ConfigItem *result = nullptr; if ((value >= SCHAR_MIN) && (value <= SCHAR_MAX)) { result = CreateConfigValue(path.c_str(), name.c_str(), (int8_t)value); @@ -164,11 +269,26 @@ ConfigItem* ConfigFileParser::MakeIntConfigValue(const mot_string& path, const m return result; } - -ConfigItem* ConfigFileParser::MakeUIntConfigValue(const mot_string& path, const mot_string& name, uint64_t value) +/* + * 鍔熻兘锛氬垱寤烘棤绗﹀彿鏁存暟绫诲瀷鐨勯厤缃」閰嶇疆鍊 + * + * 鍙傛暟鍒楄〃锛 + * path锛氶厤缃」鎵鍦ㄧ殑璺緞 + * name锛氶厤缃」鐨勫悕绉 + * value锛氭棤绗﹀彿鏁存暟鍊 + * + * 杩斿洖鍊硷細 + * 濡傛灉鎴愬姛鍒涘缓鏃犵鍙锋暣鏁扮被鍨嬬殑閰嶇疆椤归厤缃硷紝杩斿洖鎸囧悜閰嶇疆椤圭殑鎸囬拡锛涘惁鍒欒繑鍥瀗ullptr銆 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庢牴鎹彁渚涚殑鍙傛暟鍒涘缓鏃犵鍙锋暣鏁扮被鍨嬬殑閰嶇疆椤归厤缃笺 + * 棣栧厛锛屽畠灏濊瘯灏嗘棤绗﹀彿鏁存暟鍊艰В鏋愪负涓嶅悓鐨勬棤绗﹀彿鏁存暟绫诲瀷锛堜粠灏忓埌澶э級锛屽苟鏍规嵁瑙f瀽缁撴灉鍒涘缓鐩稿簲绫诲瀷鐨勯厤缃」銆 + * 濡傛灉瑙f瀽鍜屽垱寤烘垚鍔燂紝灏嗚繑鍥炵浉搴旂殑閰嶇疆椤规寚閽堬紱鍚﹀垯杩斿洖nullptr锛屽苟璁板綍閿欒淇℃伅銆 + */ +ConfigItem *ConfigFileParser::MakeUIntConfigValue(const mot_string &path, const mot_string &name, uint64_t value) { // try to parse value as unsigned integer starting from smallest type - ConfigItem* result = nullptr; + ConfigItem *result = nullptr; if (value <= UCHAR_MAX) { result = CreateConfigValue(path.c_str(), name.c_str(), (uint8_t)value); @@ -195,21 +315,40 @@ ConfigItem* ConfigFileParser::MakeUIntConfigValue(const mot_string& path, const return result; } -bool ConfigFileParser::Split(const char* str, char sep, mot_string_list& tokens) +/* + * 鍔熻兘锛氬皢瀛楃涓叉寜鎸囧畾鍒嗛殧绗﹀垎鍓蹭负澶氫釜瀛愬瓧绗︿覆锛屽苟瀛樺偍鍦ㄥ瓧绗︿覆鍒楄〃涓 + * + * 鍙傛暟鍒楄〃锛 + * str锛氬緟鍒嗗壊鐨勫瓧绗︿覆 + * sep锛氬垎闅旂 + * tokens锛氱敤浜庡瓨鍌ㄥ垎鍓插悗鐨勫瓙瀛楃涓茬殑瀛楃涓插垪琛 + * + * 杩斿洖鍊硷細 + * 濡傛灉鎴愬姛鍒嗗壊骞跺瓨鍌ㄥ瓙瀛楃涓诧紝杩斿洖true锛涘惁鍒欒繑鍥瀎alse銆 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庡皢瀛楃涓叉寜鐓ф寚瀹氱殑鍒嗛殧绗﹁繘琛屽垎鍓诧紝骞跺皢鍒嗗壊鍚庣殑瀛愬瓧绗︿覆瀛樺偍鍦ㄥ瓧绗︿覆鍒楄〃涓 + * 瀹冧娇鐢ㄤ竴涓惊鐜潵澶勭悊瀛楃涓蹭腑鐨勬瘡涓垎闅旂锛屽苟灏嗗垎闅旂涔嬮棿鐨勯儴鍒嗕綔涓轰竴涓瓙瀛楃涓插瓨鍌ㄨ捣鏉ャ + * 鍦ㄥ鐞嗚繃绋嬩腑锛屼細璺宠繃绌哄瓧绗︿覆銆 + */ +bool ConfigFileParser::Split(const char *str, char sep, mot_string_list &tokens) { do { - const char* begin = str; + const char *begin = str; while (*str != sep && *str) { str++; } - // skip empty items + // 璺宠繃绌洪」 if (str != begin) { mot_string token; + + // 灏嗗瓙瀛楃涓蹭粠begin鍒皊tr鐨勪綅缃瓨鍌ㄥ埌token涓 if (!token.assign(begin, str - begin)) { MOT_REPORT_ERROR(MOT_ERROR_OOM, "Load Configuration", "Failed to push a token"); return false; } else { + // 灏唗oken娣诲姞鍒板瓧绗︿覆鍒楄〃涓 if (!tokens.push_back(token)) { MOT_REPORT_ERROR(MOT_ERROR_OOM, "Load Configuration", "Failed to push a token"); return false; @@ -217,14 +356,31 @@ bool ConfigFileParser::Split(const char* str, char sep, mot_string_list& tokens) } } } while (*str++ != 0); + return true; } - -ConfigItem* ConfigFileParser::MakeIntConfigValue( - const mot_string& sectionFullName, const mot_string& key, const mot_string& value) +/* + * 鍔熻兘锛氬垱寤烘暣鏁扮被鍨嬬殑閰嶇疆椤归厤缃 + * + * 鍙傛暟鍒楄〃锛 + * sectionFullName锛氶厤缃」鎵鍦ㄧ殑瀹屾暣璺緞 + * key锛氶厤缃」鐨勫悕绉 + * value锛氭暣鏁板肩殑瀛楃涓茶〃绀 + * + * 杩斿洖鍊硷細 + * 濡傛灉鎴愬姛鍒涘缓鏁存暟绫诲瀷鐨勯厤缃」閰嶇疆鍊硷紝杩斿洖鎸囧悜閰嶇疆椤圭殑鎸囬拡锛涘惁鍒欒繑鍥瀗ullptr銆 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庢牴鎹彁渚涚殑鍙傛暟鍒涘缓鏁存暟绫诲瀷鐨勯厤缃」閰嶇疆鍊笺 + * 瀹冮鍏堝皾璇曞皢鏁存暟鍊肩殑瀛楃涓茶〃绀鸿В鏋愪负int64_t绫诲瀷銆 + * 濡傛灉瑙f瀽鎴愬姛锛屽畠浼氭牴鎹В鏋愮粨鏋滅殑澶у皬閫夋嫨閫傚綋鐨勬暣鏁扮被鍨嬶紝骞跺垱寤虹浉搴旂被鍨嬬殑閰嶇疆椤广 + * 濡傛灉鍒涘缓鎴愬姛锛屽皢杩斿洖鐩稿簲鐨勯厤缃」鎸囬拡锛涘惁鍒欒繑鍥瀗ullptr锛屽苟璁板綍閿欒淇℃伅銆 + */ +ConfigItem *ConfigFileParser::MakeIntConfigValue(const mot_string §ionFullName, const mot_string &key, + const mot_string &value) { // try to parse value as integer - ConfigItem* result = nullptr; + ConfigItem *result = nullptr; int64_t intValue = 0; if (ParseIntValue(sectionFullName, key, value, intValue)) { if ((intValue >= SCHAR_MIN) && (intValue <= SCHAR_MAX)) { @@ -251,12 +407,28 @@ ConfigItem* ConfigFileParser::MakeIntConfigValue( } return result; } - -ConfigItem* ConfigFileParser::MakeUIntConfigValue( - const mot_string& sectionFullName, const mot_string& key, const mot_string& value) +/* + * 鍔熻兘锛氬垱寤烘棤绗﹀彿鏁存暟绫诲瀷鐨勯厤缃」閰嶇疆鍊 + * + * 鍙傛暟鍒楄〃锛 + * sectionFullName锛氶厤缃」鎵鍦ㄧ殑瀹屾暣璺緞 + * key锛氶厤缃」鐨勫悕绉 + * value锛氭棤绗﹀彿鏁存暟鍊肩殑瀛楃涓茶〃绀 + * + * 杩斿洖鍊硷細 + * 濡傛灉鎴愬姛鍒涘缓鏃犵鍙锋暣鏁扮被鍨嬬殑閰嶇疆椤归厤缃硷紝杩斿洖鎸囧悜閰嶇疆椤圭殑鎸囬拡锛涘惁鍒欒繑鍥瀗ullptr銆 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庢牴鎹彁渚涚殑鍙傛暟鍒涘缓鏃犵鍙锋暣鏁扮被鍨嬬殑閰嶇疆椤归厤缃笺 + * 瀹冮鍏堝皾璇曞皢鏃犵鍙锋暣鏁板肩殑瀛楃涓茶〃绀鸿В鏋愪负uint64_t绫诲瀷銆 + * 濡傛灉瑙f瀽鎴愬姛锛屽畠浼氭牴鎹В鏋愮粨鏋滅殑澶у皬閫夋嫨閫傚綋鐨勬棤绗﹀彿鏁存暟绫诲瀷锛屽苟鍒涘缓鐩稿簲绫诲瀷鐨勯厤缃」銆 + * 濡傛灉鍒涘缓鎴愬姛锛屽皢杩斿洖鐩稿簲鐨勯厤缃」鎸囬拡锛涘惁鍒欒繑鍥瀗ullptr锛屽苟璁板綍閿欒淇℃伅銆 + */ +ConfigItem *ConfigFileParser::MakeUIntConfigValue(const mot_string §ionFullName, const mot_string &key, + const mot_string &value) { // try to parse value as unsigned integer - ConfigItem* result = nullptr; + ConfigItem *result = nullptr; uint64_t intValue = 0; if (ParseUIntValue(sectionFullName, key, value, intValue)) { if (intValue <= UCHAR_MAX) { @@ -284,44 +456,81 @@ ConfigItem* ConfigFileParser::MakeUIntConfigValue( return result; } -ConfigItem* ConfigFileParser::MakeDoubleConfigValue( - const mot_string& sectionFullName, const mot_string& key, const mot_string& value) +/* + * 鍔熻兘锛氬垱寤哄弻绮惧害娴偣鏁扮被鍨嬬殑閰嶇疆椤归厤缃 + * + * 鍙傛暟鍒楄〃锛 + * sectionFullName锛氶厤缃」鎵鍦ㄧ殑瀹屾暣璺緞 + * key锛氶厤缃」鐨勫悕绉 + * value锛氬弻绮惧害娴偣鏁板肩殑瀛楃涓茶〃绀 + * + * 杩斿洖鍊硷細 + * 濡傛灉鎴愬姛鍒涘缓鍙岀簿搴︽诞鐐规暟绫诲瀷鐨勯厤缃」閰嶇疆鍊硷紝杩斿洖鎸囧悜閰嶇疆椤圭殑鎸囬拡锛涘惁鍒欒繑鍥瀗ullptr銆 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庢牴鎹彁渚涚殑鍙傛暟鍒涘缓鍙岀簿搴︽诞鐐规暟绫诲瀷鐨勯厤缃」閰嶇疆鍊笺 + * 瀹冮鍏堝皾璇曞皢鍙岀簿搴︽诞鐐规暟鍊肩殑瀛楃涓茶〃绀鸿В鏋愪负double绫诲瀷銆 + * 鍦ㄨВ鏋愯繃绋嬩腑锛屼細妫鏌ユ槸鍚﹀瓨鍦ㄤ笉鍚堟硶鐨勬儏鍐碉紝濡傜┖杈撳叆銆佹棤鏈夋晥鏁板瓧銆佷笉鍚堟硶鐨勫悗缁瓧绗﹀拰婧㈠嚭銆 + * 濡傛灉瑙f瀽鎴愬姛涓旀病鏈変笉鍚堟硶鎯呭喌锛屽垯鍒涘缓鐩稿簲绫诲瀷鐨勯厤缃」锛岃繑鍥炵浉搴旂殑閰嶇疆椤规寚閽堬紱 + * 鍚﹀垯杩斿洖nullptr锛屽苟璁板綍閿欒淇℃伅銆 + */ +ConfigItem *ConfigFileParser::MakeDoubleConfigValue(const mot_string §ionFullName, const mot_string &key, + const mot_string &value) { - // try to parse value as double - ConfigItem* result = nullptr; - char* endptr = NULL; + // 灏濊瘯瑙f瀽瀛楃涓插间负鍙岀簿搴︽诞鐐规暟 + ConfigItem *result = nullptr; + char *endptr = nullptr; double doubleValue = strtod(value.c_str(), &endptr); - if (*value.c_str() == 0) { // empty input + + // 绌鸿緭鍏 + if (*value.c_str() == 0) { MOT_LOG_TRACE("Configuration double at [section %s, key %s] is empty", sectionFullName.c_str(), key.c_str()); - } else if (endptr == value.c_str()) { // no valid digits + } + // 鏃犳湁鏁堟暟瀛 + else if (endptr == value.c_str()) { MOT_LOG_TRACE("Configuration double at [section %s, key %s] has no valid digits at all: %s", - sectionFullName.c_str(), - key.c_str(), - value.c_str()); - } else if (*endptr != 0) { // some invalid trailing digits + sectionFullName.c_str(), key.c_str(), value.c_str()); + } + // 瀛樺湪涓嶅悎娉曠殑鍚庣画瀛楃 + else if (*endptr != 0) { MOT_LOG_TRACE("Configuration double at [section %s, key %s] has invalid trailing characters: %s", - sectionFullName.c_str(), - key.c_str(), - value.c_str()); - } else if (((doubleValue == HUGE_VALF) || (doubleValue == HUGE_VALL)) && (errno == ERANGE)) { // overflow - MOT_LOG_TRACE("Configuration double at [section %s, key %s] overflows: %s", - sectionFullName.c_str(), - key.c_str(), - value.c_str()); + sectionFullName.c_str(), key.c_str(), value.c_str()); + } + // 婧㈠嚭 + else if (((doubleValue == HUGE_VALF) || (doubleValue == HUGE_VALL)) && (errno == ERANGE)) { + MOT_LOG_TRACE("Configuration double at [section %s, key %s] overflows: %s", sectionFullName.c_str(), + key.c_str(), value.c_str()); } else { result = CreateConfigValue(sectionFullName.c_str(), key.c_str(), doubleValue); if (result == nullptr) { MOT_REPORT_ERROR(MOT_ERROR_OOM, "Load Configuration", "Failed to allocate double configuration value"); } } + return result; } - -ConfigItem* ConfigFileParser::MakeBoolConfigValue( - const mot_string& sectionFullName, const mot_string& key, const mot_string& value) +/* + * 鍔熻兘锛氬垱寤哄竷灏旂被鍨嬬殑閰嶇疆椤归厤缃 + * + * 鍙傛暟鍒楄〃锛 + * sectionFullName锛氶厤缃」鎵鍦ㄧ殑瀹屾暣璺緞 + * key锛氶厤缃」鐨勫悕绉 + * value锛氬竷灏斿肩殑瀛楃涓茶〃绀 + * + * 杩斿洖鍊硷細 + * 濡傛灉鎴愬姛鍒涘缓甯冨皵绫诲瀷鐨勯厤缃」閰嶇疆鍊硷紝杩斿洖鎸囧悜閰嶇疆椤圭殑鎸囬拡锛涘惁鍒欒繑鍥瀗ullptr銆 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庢牴鎹彁渚涚殑鍙傛暟鍒涘缓甯冨皵绫诲瀷鐨勯厤缃」閰嶇疆鍊笺 + * 瀹冮鍏堝皾璇曞皢甯冨皵鍊肩殑瀛楃涓茶〃绀鸿В鏋愪负bool绫诲瀷锛屾敮鎸"true"/"on"/"yes"鍜"false"/"off"/"no"銆 + * 濡傛灉瑙f瀽鎴愬姛锛屽垯鍒涘缓鐩稿簲绫诲瀷鐨勯厤缃」锛岃繑鍥炵浉搴旂殑閰嶇疆椤规寚閽堬紱 + * 鍚﹀垯杩斿洖nullptr锛屽苟璁板綍閿欒淇℃伅銆 + */ +ConfigItem *ConfigFileParser::MakeBoolConfigValue(const mot_string §ionFullName, const mot_string &key, + const mot_string &value) { // try to parse value as Boolean - ConfigItem* result = nullptr; + ConfigItem *result = nullptr; if ((strcasecmp(value.c_str(), "true") == 0) || (strcasecmp(value.c_str(), "on") == 0) || (strcasecmp(value.c_str(), "yes") == 0)) { result = CreateConfigValue(sectionFullName.c_str(), key.c_str(), true); @@ -337,12 +546,28 @@ ConfigItem* ConfigFileParser::MakeBoolConfigValue( } return result; } - -ConfigItem* ConfigFileParser::MakeInt64ConfigValue( - const mot_string& sectionFullName, const mot_string& key, const mot_string& value) +/* + * 鍔熻兘锛氬垱寤篿nt64绫诲瀷鐨勯厤缃」閰嶇疆鍊 + * + * 鍙傛暟鍒楄〃锛 + * sectionFullName锛氶厤缃」鎵鍦ㄧ殑瀹屾暣璺緞 + * key锛氶厤缃」鐨勫悕绉 + * value锛歩nt64绫诲瀷鐨勫瓧绗︿覆琛ㄧず + * + * 杩斿洖鍊硷細 + * 濡傛灉鎴愬姛鍒涘缓int64绫诲瀷鐨勯厤缃」閰嶇疆鍊硷紝杩斿洖鎸囧悜閰嶇疆椤圭殑鎸囬拡锛涘惁鍒欒繑鍥瀗ullptr銆 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庢牴鎹彁渚涚殑鍙傛暟鍒涘缓int64绫诲瀷鐨勯厤缃」閰嶇疆鍊笺 + * 瀹冮鍏堝皾璇曞皢瀛楃涓插艰В鏋愪负int64绫诲瀷銆 + * 濡傛灉瑙f瀽鎴愬姛锛屽垯鍒涘缓int64绫诲瀷鐨勯厤缃」锛岃繑鍥炵浉搴旂殑閰嶇疆椤规寚閽堬紱 + * 鍚﹀垯杩斿洖nullptr锛屽苟璁板綍閿欒淇℃伅銆 + */ +ConfigItem *ConfigFileParser::MakeInt64ConfigValue(const mot_string §ionFullName, const mot_string &key, + const mot_string &value) { // try to parse value as int64_t - ConfigItem* result = nullptr; + ConfigItem *result = nullptr; int64_t intValue = 0; if (ParseIntValue(sectionFullName, key, value, intValue)) { result = CreateConfigValue(sectionFullName.c_str(), key.c_str(), intValue); @@ -353,11 +578,28 @@ ConfigItem* ConfigFileParser::MakeInt64ConfigValue( return result; } -ConfigItem* ConfigFileParser::MakeInt32ConfigValue( - const mot_string& sectionFullName, const mot_string& key, const mot_string& value) +/* + * 鍔熻兘锛氬垱寤篿nt32_t绫诲瀷鐨勯厤缃」閰嶇疆鍊 + * + * 鍙傛暟鍒楄〃锛 + * sectionFullName锛氶厤缃」鎵鍦ㄧ殑瀹屾暣璺緞 + * key锛氶厤缃」鐨勫悕绉 + * value锛歩nt32_t绫诲瀷鐨勫瓧绗︿覆琛ㄧず + * + * 杩斿洖鍊硷細 + * 濡傛灉鎴愬姛鍒涘缓int32_t绫诲瀷鐨勯厤缃」閰嶇疆鍊硷紝杩斿洖鎸囧悜閰嶇疆椤圭殑鎸囬拡锛涘惁鍒欒繑鍥瀗ullptr銆 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庢牴鎹彁渚涚殑鍙傛暟鍒涘缓int32_t绫诲瀷鐨勯厤缃」閰嶇疆鍊笺 + * 瀹冮鍏堝皾璇曞皢瀛楃涓插艰В鏋愪负int64_t绫诲瀷銆 + * 濡傛灉瑙f瀽鎴愬姛骞朵笖鍊煎湪int32_t鐨勮寖鍥村唴锛屽垯鍒涘缓int32_t绫诲瀷鐨勯厤缃」锛岃繑鍥炵浉搴旂殑閰嶇疆椤规寚閽堬紱 + * 鍚﹀垯杩斿洖nullptr锛屽苟璁板綍閿欒淇℃伅銆 + */ +ConfigItem *ConfigFileParser::MakeInt32ConfigValue(const mot_string §ionFullName, const mot_string &key, + const mot_string &value) { - // try to parse value as int32_t - ConfigItem* result = nullptr; + // 灏濊瘯瑙f瀽瀛楃涓插间负int64_t绫诲瀷 + ConfigItem *result = nullptr; int64_t intValue = 0; if (ParseIntValue(sectionFullName, key, value, intValue)) { if ((intValue >= INT_MIN) && (intValue <= INT_MAX)) { @@ -370,11 +612,28 @@ ConfigItem* ConfigFileParser::MakeInt32ConfigValue( return result; } -ConfigItem* ConfigFileParser::MakeInt16ConfigValue( - const mot_string& sectionFullName, const mot_string& key, const mot_string& value) +/* + * 鍔熻兘锛氬垱寤篿nt16_t绫诲瀷鐨勯厤缃」閰嶇疆鍊 + * + * 鍙傛暟鍒楄〃锛 + * sectionFullName锛氶厤缃」鎵鍦ㄧ殑瀹屾暣璺緞 + * key锛氶厤缃」鐨勫悕绉 + * value锛歩nt16_t绫诲瀷鐨勫瓧绗︿覆琛ㄧず + * + * 杩斿洖鍊硷細 + * 濡傛灉鎴愬姛鍒涘缓int16_t绫诲瀷鐨勯厤缃」閰嶇疆鍊硷紝杩斿洖鎸囧悜閰嶇疆椤圭殑鎸囬拡锛涘惁鍒欒繑鍥瀗ullptr銆 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庢牴鎹彁渚涚殑鍙傛暟鍒涘缓int16_t绫诲瀷鐨勯厤缃」閰嶇疆鍊笺 + * 瀹冮鍏堝皾璇曞皢瀛楃涓插艰В鏋愪负int64_t绫诲瀷銆 + * 濡傛灉瑙f瀽鎴愬姛骞朵笖鍊煎湪int16_t鐨勮寖鍥村唴锛屽垯鍒涘缓int16_t绫诲瀷鐨勯厤缃」锛岃繑鍥炵浉搴旂殑閰嶇疆椤规寚閽堬紱 + * 鍚﹀垯杩斿洖nullptr锛屽苟璁板綍閿欒淇℃伅銆 + */ +ConfigItem *ConfigFileParser::MakeInt16ConfigValue(const mot_string §ionFullName, const mot_string &key, + const mot_string &value) { - // try to parse value as int16_t - ConfigItem* result = nullptr; + // 灏濊瘯瑙f瀽瀛楃涓插间负int64_t绫诲瀷 + ConfigItem *result = nullptr; int64_t intValue = 0; if (ParseIntValue(sectionFullName, key, value, intValue)) { if ((intValue >= SHRT_MIN) && (intValue <= SHRT_MAX)) { @@ -387,11 +646,28 @@ ConfigItem* ConfigFileParser::MakeInt16ConfigValue( return result; } -ConfigItem* ConfigFileParser::MakeInt8ConfigValue( - const mot_string& sectionFullName, const mot_string& key, const mot_string& value) +/* + * 鍔熻兘锛氬垱寤篿nt8_t绫诲瀷鐨勯厤缃」閰嶇疆鍊 + * + * 鍙傛暟鍒楄〃锛 + * sectionFullName锛氶厤缃」鎵鍦ㄧ殑瀹屾暣璺緞 + * key锛氶厤缃」鐨勫悕绉 + * value锛歩nt8_t绫诲瀷鐨勫瓧绗︿覆琛ㄧず + * + * 杩斿洖鍊硷細 + * 濡傛灉鎴愬姛鍒涘缓int8_t绫诲瀷鐨勯厤缃」閰嶇疆鍊硷紝杩斿洖鎸囧悜閰嶇疆椤圭殑鎸囬拡锛涘惁鍒欒繑鍥瀗ullptr銆 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庢牴鎹彁渚涚殑鍙傛暟鍒涘缓int8_t绫诲瀷鐨勯厤缃」閰嶇疆鍊笺 + * 瀹冮鍏堝皾璇曞皢瀛楃涓插艰В鏋愪负int64_t绫诲瀷銆 + * 濡傛灉瑙f瀽鎴愬姛骞朵笖鍊煎湪int8_t鐨勮寖鍥村唴锛屽垯鍒涘缓int8_t绫诲瀷鐨勯厤缃」锛岃繑鍥炵浉搴旂殑閰嶇疆椤规寚閽堬紱 + * 鍚﹀垯杩斿洖nullptr锛屽苟璁板綍閿欒淇℃伅銆 + */ +ConfigItem *ConfigFileParser::MakeInt8ConfigValue(const mot_string §ionFullName, const mot_string &key, + const mot_string &value) { - // try to parse value as int8_t - ConfigItem* result = nullptr; + // 灏濊瘯瑙f瀽瀛楃涓插间负int64_t绫诲瀷 + ConfigItem *result = nullptr; int64_t intValue = 0; if (ParseIntValue(sectionFullName, key, value, intValue)) { if ((intValue >= SCHAR_MIN) && (intValue <= SCHAR_MAX)) { @@ -403,12 +679,28 @@ ConfigItem* ConfigFileParser::MakeInt8ConfigValue( } return result; } - -ConfigItem* ConfigFileParser::MakeUInt64ConfigValue( - const mot_string& sectionFullName, const mot_string& key, const mot_string& value) +/* + * 鍔熻兘锛氬垱寤簎int64_t绫诲瀷鐨勯厤缃」閰嶇疆鍊 + * + * 鍙傛暟鍒楄〃锛 + * sectionFullName锛氶厤缃」鎵鍦ㄧ殑瀹屾暣璺緞 + * key锛氶厤缃」鐨勫悕绉 + * value锛歶int64_t绫诲瀷鐨勫瓧绗︿覆琛ㄧず + * + * 杩斿洖鍊硷細 + * 濡傛灉鎴愬姛鍒涘缓uint64_t绫诲瀷鐨勯厤缃」閰嶇疆鍊硷紝杩斿洖鎸囧悜閰嶇疆椤圭殑鎸囬拡锛涘惁鍒欒繑鍥瀗ullptr銆 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庢牴鎹彁渚涚殑鍙傛暟鍒涘缓uint64_t绫诲瀷鐨勯厤缃」閰嶇疆鍊笺 + * 瀹冮鍏堝皾璇曞皢瀛楃涓插艰В鏋愪负uint64_t绫诲瀷銆 + * 濡傛灉瑙f瀽鎴愬姛锛屽垱寤簎int64_t绫诲瀷鐨勯厤缃」锛岃繑鍥炵浉搴旂殑閰嶇疆椤规寚閽堬紱 + * 鍚﹀垯杩斿洖nullptr锛屽苟璁板綍閿欒淇℃伅銆 + */ +ConfigItem *ConfigFileParser::MakeUInt64ConfigValue(const mot_string §ionFullName, const mot_string &key, + const mot_string &value) { // try to parse value as uint64_t - ConfigItem* result = nullptr; + ConfigItem *result = nullptr; uint64_t intValue = 0; if (ParseUIntValue(sectionFullName, key, value, intValue)) { result = CreateConfigValue(sectionFullName.c_str(), key.c_str(), intValue); @@ -418,12 +710,28 @@ ConfigItem* ConfigFileParser::MakeUInt64ConfigValue( } return result; } - -ConfigItem* ConfigFileParser::MakeUInt32ConfigValue( - const mot_string& sectionFullName, const mot_string& key, const mot_string& value) +/* + * 鍔熻兘锛氬垱寤簎int32_t绫诲瀷鐨勯厤缃」閰嶇疆鍊 + * + * 鍙傛暟鍒楄〃锛 + * sectionFullName锛氶厤缃」鎵鍦ㄧ殑瀹屾暣璺緞 + * key锛氶厤缃」鐨勫悕绉 + * value锛歶int32_t绫诲瀷鐨勫瓧绗︿覆琛ㄧず + * + * 杩斿洖鍊硷細 + * 濡傛灉鎴愬姛鍒涘缓uint32_t绫诲瀷鐨勯厤缃」閰嶇疆鍊硷紝杩斿洖鎸囧悜閰嶇疆椤圭殑鎸囬拡锛涘惁鍒欒繑鍥瀗ullptr銆 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庢牴鎹彁渚涚殑鍙傛暟鍒涘缓uint32_t绫诲瀷鐨勯厤缃」閰嶇疆鍊笺 + * 瀹冮鍏堝皾璇曞皢瀛楃涓插艰В鏋愪负uint64_t绫诲瀷銆 + * 濡傛灉瑙f瀽鎴愬姛涓斿煎湪uint32_t鐨勮寖鍥村唴锛屽垱寤簎int32_t绫诲瀷鐨勯厤缃」锛岃繑鍥炵浉搴旂殑閰嶇疆椤规寚閽堬紱 + * 鍚﹀垯杩斿洖nullptr锛屽苟璁板綍閿欒淇℃伅銆 + */ +ConfigItem *ConfigFileParser::MakeUInt32ConfigValue(const mot_string §ionFullName, const mot_string &key, + const mot_string &value) { // try to parse value as uint32_t - ConfigItem* result = nullptr; + ConfigItem *result = nullptr; uint64_t intValue = 0; if (ParseUIntValue(sectionFullName, key, value, intValue)) { if (intValue <= UINT_MAX) { @@ -435,12 +743,28 @@ ConfigItem* ConfigFileParser::MakeUInt32ConfigValue( } return result; } - -ConfigItem* ConfigFileParser::MakeUInt16ConfigValue( - const mot_string& sectionFullName, const mot_string& key, const mot_string& value) +/* + * 鍔熻兘锛氬垱寤簎int16_t绫诲瀷鐨勯厤缃」閰嶇疆鍊 + * + * 鍙傛暟鍒楄〃锛 + * sectionFullName锛氶厤缃」鎵鍦ㄧ殑瀹屾暣璺緞 + * key锛氶厤缃」鐨勫悕绉 + * value锛歶int16_t绫诲瀷鐨勫瓧绗︿覆琛ㄧず + * + * 杩斿洖鍊硷細 + * 濡傛灉鎴愬姛鍒涘缓uint16_t绫诲瀷鐨勯厤缃」閰嶇疆鍊硷紝杩斿洖鎸囧悜閰嶇疆椤圭殑鎸囬拡锛涘惁鍒欒繑鍥瀗ullptr銆 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庢牴鎹彁渚涚殑鍙傛暟鍒涘缓uint16_t绫诲瀷鐨勯厤缃」閰嶇疆鍊笺 + * 瀹冮鍏堝皾璇曞皢瀛楃涓插艰В鏋愪负uint64_t绫诲瀷銆 + * 濡傛灉瑙f瀽鎴愬姛涓斿煎湪uint16_t鐨勮寖鍥村唴锛屽垱寤簎int16_t绫诲瀷鐨勯厤缃」锛岃繑鍥炵浉搴旂殑閰嶇疆椤规寚閽堬紱 + * 鍚﹀垯杩斿洖nullptr锛屽苟璁板綍閿欒淇℃伅銆 + */ +ConfigItem *ConfigFileParser::MakeUInt16ConfigValue(const mot_string §ionFullName, const mot_string &key, + const mot_string &value) { // try to parse value as uint16_t - ConfigItem* result = nullptr; + ConfigItem *result = nullptr; uint64_t intValue = 0; if (ParseUIntValue(sectionFullName, key, value, intValue)) { if (intValue <= USHRT_MAX) { @@ -452,12 +776,28 @@ ConfigItem* ConfigFileParser::MakeUInt16ConfigValue( } return result; } - -ConfigItem* ConfigFileParser::MakeUInt8ConfigValue( - const mot_string& sectionFullName, const mot_string& key, const mot_string& value) +/* + * 鍔熻兘锛氬垱寤 uint8_t 绫诲瀷鐨勯厤缃」閰嶇疆鍊 + * + * 鍙傛暟鍒楄〃锛 + * sectionFullName锛氶厤缃」鎵鍦ㄧ殑瀹屾暣璺緞 + * key锛氶厤缃」鐨勫悕绉 + * value锛歶int8_t 绫诲瀷鐨勫瓧绗︿覆琛ㄧず + * + * 杩斿洖鍊硷細 + * 濡傛灉鎴愬姛鍒涘缓 uint8_t 绫诲瀷鐨勯厤缃」閰嶇疆鍊硷紝杩斿洖鎸囧悜閰嶇疆椤圭殑鎸囬拡锛涘惁鍒欒繑鍥 nullptr銆 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庢牴鎹彁渚涚殑鍙傛暟鍒涘缓 uint8_t 绫诲瀷鐨勯厤缃」閰嶇疆鍊笺 + * 瀹冮鍏堝皾璇曞皢瀛楃涓插艰В鏋愪负 uint64_t 绫诲瀷銆 + * 濡傛灉瑙f瀽鎴愬姛涓斿煎湪 uint8_t 鐨勮寖鍥村唴锛屽垱寤 uint8_t 绫诲瀷鐨勯厤缃」锛岃繑鍥炵浉搴旂殑閰嶇疆椤规寚閽堬紱 + * 鍚﹀垯杩斿洖 nullptr锛屽苟璁板綍閿欒淇℃伅銆 + */ +ConfigItem *ConfigFileParser::MakeUInt8ConfigValue(const mot_string §ionFullName, const mot_string &key, + const mot_string &value) { // try to parse value as uint8_t - ConfigItem* result = nullptr; + ConfigItem *result = nullptr; uint64_t intValue = 0; if (ParseUIntValue(sectionFullName, key, value, intValue)) { if (intValue <= UCHAR_MAX) { @@ -469,13 +809,29 @@ ConfigItem* ConfigFileParser::MakeUInt8ConfigValue( } return result; } - -ConfigItem* ConfigFileParser::MakeUntypedConfigValue( - const mot_string& sectionFullName, const mot_string& key, const mot_string& value) +/* + * 鍔熻兘锛氬垱寤烘湭鎸囧畾绫诲瀷鐨勯厤缃」閰嶇疆鍊 + * + * 鍙傛暟鍒楄〃锛 + * sectionFullName锛氶厤缃」鎵鍦ㄧ殑瀹屾暣璺緞 + * key锛氶厤缃」鐨勫悕绉 + * value锛氭湭鎸囧畾绫诲瀷鐨勫瓧绗︿覆琛ㄧず + * + * 杩斿洖鍊硷細 + * 濡傛灉鎴愬姛鍒涘缓閰嶇疆椤归厤缃硷紝杩斿洖鎸囧悜閰嶇疆椤圭殑鎸囬拡锛涘惁鍒欒繑鍥 nullptr銆 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庢牴鎹彁渚涚殑鍙傛暟鍒涘缓鏈寚瀹氱被鍨嬬殑閰嶇疆椤归厤缃笺 + * 瀹冨皾璇曟牴鎹瓧绗︿覆鍊肩殑鍐呭鎺ㄦ柇閰嶇疆椤圭殑鏁版嵁绫诲瀷锛岀劧鍚庡垱寤虹浉搴旂被鍨嬬殑閰嶇疆椤广 + * 濡傛灉鏃犳硶鎺ㄦ柇鍑烘暟鎹被鍨嬫垨鍒涘缓閰嶇疆椤瑰け璐ワ紝灏嗛粯璁ゅ垱寤轰竴涓 mot_string 绫诲瀷鐨勯厤缃」銆 + */ +ConfigItem *ConfigFileParser::MakeUntypedConfigValue(const mot_string §ionFullName, const mot_string &key, + const mot_string &value) { // try to infer the configuration value type + // 灏濊瘯鎺ㄦ柇閰嶇疆鍊肩殑鏁版嵁绫诲瀷 MOT_LOG_TRACE("Attempting to parse signed integer value"); - ConfigItem* result = MakeIntConfigValue(sectionFullName, key, value); + ConfigItem *result = MakeIntConfigValue(sectionFullName, key, value); if (result == nullptr) { MOT_LOG_TRACE("Attempting to parse unsigned integer value"); result = MakeUIntConfigValue(sectionFullName, key, value); @@ -490,6 +846,7 @@ ConfigItem* ConfigFileParser::MakeUntypedConfigValue( } if (result == nullptr) { MOT_LOG_TRACE("Defaulting to mot_string value"); + // 榛樿鍒涘缓涓涓 mot_string 绫诲瀷鐨勯厤缃」 result = CreateConfigValue(sectionFullName.c_str(), key.c_str(), value); if (result == nullptr) { MOT_REPORT_ERROR(MOT_ERROR_OOM, "Load Configuration", "Failed to allocate mot_string configuration value"); @@ -497,12 +854,27 @@ ConfigItem* ConfigFileParser::MakeUntypedConfigValue( } return result; } - -ConfigItem* ConfigFileParser::MakeTypedConfigValue( - const mot_string& sectionFullName, const mot_string& typeName, const mot_string& key, const mot_string& value) +/* + * 鍔熻兘锛氭牴鎹被鍨嬪悕绉板垱寤洪厤缃」閰嶇疆鍊 + * + * 鍙傛暟鍒楄〃锛 + * sectionFullName锛氶厤缃」鎵鍦ㄧ殑瀹屾暣璺緞 + * typeName锛氶厤缃」鐨勭被鍨嬪悕绉 + * key锛氶厤缃」鐨勫悕绉 + * value锛氶厤缃」鐨勫 + * + * 杩斿洖鍊硷細 + * 濡傛灉鎴愬姛鍒涘缓閰嶇疆椤归厤缃硷紝杩斿洖鎸囧悜閰嶇疆椤圭殑鎸囬拡锛涘惁鍒欒繑鍥 nullptr銆 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁版牴鎹彁渚涚殑绫诲瀷鍚嶇О锛屽垱寤虹浉搴旂被鍨嬬殑閰嶇疆椤归厤缃笺 + * 濡傛灉绫诲瀷鍚嶇О鏃犳晥鎴栨棤娉曞垱寤洪厤缃」閰嶇疆鍊硷紝灏嗙敓鎴愮浉搴旂殑閿欒鎶ュ憡骞惰繑鍥 nullptr銆 + */ +ConfigItem *ConfigFileParser::MakeTypedConfigValue(const mot_string §ionFullName, const mot_string &typeName, + const mot_string &key, const mot_string &value) { // build a configuration value by given type name - ConfigItem* result = nullptr; + ConfigItem *result = nullptr; ConfigValueType valueType = ConfigValueTypeFromString(typeName.c_str()); switch (valueType) { case ConfigValueType::CONFIG_VALUE_INT64: @@ -548,98 +920,107 @@ ConfigItem* ConfigFileParser::MakeTypedConfigValue( case ConfigValueType::CONFIG_VALUE_STRING: result = CreateConfigValue(sectionFullName.c_str(), key.c_str(), value); if (result == nullptr) { - MOT_REPORT_ERROR( - MOT_ERROR_OOM, "Load Configuration", "Failed to allocate mot_string configuration value"); + MOT_REPORT_ERROR(MOT_ERROR_OOM, "Load Configuration", + "Failed to allocate mot_string configuration value"); } break; default: - MOT_REPORT_ERROR(MOT_ERROR_INVALID_ARG, - "Load Configuration", - "Invalid configuration value type name: %s", - typeName.c_str()); + MOT_REPORT_ERROR(MOT_ERROR_INVALID_ARG, "Load Configuration", "Invalid configuration value type name: %s", + typeName.c_str()); break; } return result; } -bool ConfigFileParser::ParseIntValue( - const mot_string& sectionFullName, const mot_string& key, const mot_string& value, int64_t& intValue) +/* + * 鍔熻兘锛氬皾璇曞皢瀛楃涓插艰В鏋愪负 int64_t 绫诲瀷 + * + * 鍙傛暟鍒楄〃锛 + * sectionFullName锛氶厤缃」鎵鍦ㄧ殑瀹屾暣璺緞 + * key锛氶厤缃」鐨勫悕绉 + * value锛氬緟瑙f瀽鐨勫瓧绗︿覆鍊 + * intValue锛氭垚鍔熻В鏋愬悗瀛樺偍鏁存暟鍊肩殑寮曠敤 + * + * 杩斿洖鍊硷細 + * 濡傛灉鎴愬姛瑙f瀽鏁存暟鍊硷紝杩斿洖 true锛屽惁鍒欒繑鍥 false銆 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁板皾璇曞皢瀛楃涓插艰В鏋愪负 int64_t 绫诲瀷锛屽鏋滆В鏋愬け璐ワ紝浼氳褰曢敊璇俊鎭苟杩斿洖 false銆 + */ +bool ConfigFileParser::ParseIntValue(const mot_string §ionFullName, const mot_string &key, const mot_string &value, + int64_t &intValue) { bool result = false; - char* endptr = NULL; - intValue = strtoll(value.c_str(), &endptr, 0); - if (*value.c_str() == 0) { // empty input + char *endptr = NULL; + intValue = strtoll(value.c_str(), &endptr, 0); // 浣跨敤 strtoll 灏濊瘯瑙f瀽瀛楃涓蹭负 int64_t + + if (*value.c_str() == 0) { // 绌鸿緭鍏 MOT_LOG_DIAG2("Configuration integer at [section %s, key %s] is empty", sectionFullName.c_str(), key.c_str()); - } else if (endptr == value.c_str()) { // no valid digits + } else if (endptr == value.c_str()) { // 鏃犳湁鏁堟暟瀛 MOT_LOG_DIAG2("Configuration integer at [section %s, key %s] has no valid digits at all: %s", - sectionFullName.c_str(), - key.c_str(), - value.c_str()); - } else if (*endptr != 0) { // some invalid trailing digits + sectionFullName.c_str(), key.c_str(), value.c_str()); + } else if (*endptr != 0) { // 瀛樺湪鏃犳晥鐨勫悗缁瓧绗 MOT_LOG_DIAG2("Configuration integer at [section %s, key %s] has invalid trailing characters: %s", - sectionFullName.c_str(), - key.c_str(), - value.c_str()); - } else if (((intValue == LLONG_MIN) || (intValue == LLONG_MAX)) && (errno == ERANGE)) { // overflow + sectionFullName.c_str(), key.c_str(), value.c_str()); + } else if (((intValue == LLONG_MIN) || (intValue == LLONG_MAX)) && (errno == ERANGE)) { // 婧㈠嚭 MOT_LOG_DIAG2("Configuration integer at [section %s, key %s] overflows: %s", value.c_str()); } else { int err = errno; MOT_LOG_TRACE("Configuration integer at [section %s, key %s] is ok: %s --> %" PRId64 " (value = %p, endptr = %p, *endptr = %u, errno: %d)", - sectionFullName.c_str(), - key.c_str(), - value.c_str(), - intValue, - value.c_str(), - endptr, - (unsigned)*endptr, - err); + sectionFullName.c_str(), key.c_str(), value.c_str(), intValue, value.c_str(), endptr, + (unsigned)*endptr, err); result = true; } + return result; } - -bool ConfigFileParser::ParseUIntValue(const mot_string& sectionFullName, const mot_string& key, const mot_string& value, - uint64_t& intValue, bool arrayIndex /* = false */) +/* + * 鍔熻兘锛氬皾璇曞皢瀛楃涓插艰В鏋愪负 uint64_t 绫诲瀷 + * + * 鍙傛暟鍒楄〃锛 + * sectionFullName锛氶厤缃」鎵鍦ㄧ殑瀹屾暣璺緞 + * key锛氶厤缃」鐨勫悕绉 + * value锛氬緟瑙f瀽鐨勫瓧绗︿覆鍊 + * intValue锛氭垚鍔熻В鏋愬悗瀛樺偍鏃犵鍙锋暣鏁板肩殑寮曠敤 + * arrayIndex锛氭爣蹇楁槸鍚﹁В鏋愭暟缁勭储寮曪紙鍙夛紝榛樿涓 false锛 + * + * 杩斿洖鍊硷細 + * 濡傛灉鎴愬姛瑙f瀽鏃犵鍙锋暣鏁板硷紝杩斿洖 true锛屽惁鍒欒繑鍥 false銆 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁板皾璇曞皢瀛楃涓插艰В鏋愪负 uint64_t 绫诲瀷锛屽鏋滆В鏋愬け璐ワ紝浼氳褰曢敊璇俊鎭苟杩斿洖 false銆 + */ +bool ConfigFileParser::ParseUIntValue(const mot_string §ionFullName, const mot_string &key, const mot_string &value, + uint64_t &intValue, bool arrayIndex /* = false */) { bool result = false; - char* endptr = NULL; - intValue = strtoull(value.c_str(), &endptr, 0); - const char* itemName = arrayIndex ? "arrayIndex" : "integer"; - if (*value.c_str() == 0) { // empty input - MOT_LOG_DIAG2( - "Configuration %s at [section %s, key %s] is empty", itemName, sectionFullName.c_str(), key.c_str()); - } else if (endptr == value.c_str()) { // no valid digits - MOT_LOG_DIAG2("Configuration %s at [section %s, key %s] has no valid digits at all: %s", - itemName, - sectionFullName.c_str(), - key.c_str(), - value.c_str()); - } else if (*endptr != 0) { // some invalid trailing digits - MOT_LOG_DIAG2("Configuration %s at [section %s, key %s] has invalid trailing characters: %s", - itemName, - sectionFullName.c_str(), - key.c_str(), - value.c_str()); - } else if ((intValue == ULLONG_MAX) && (errno == ERANGE)) { // overflow + char *endptr = NULL; + intValue = strtoull(value.c_str(), &endptr, 0); // 浣跨敤 strtoull 灏濊瘯瑙f瀽瀛楃涓蹭负 uint64_t + const char *itemName = arrayIndex ? "arrayIndex" : "integer"; // 鏍规嵁鏄惁鏁扮粍绱㈠紩纭畾椤圭洰鍚嶇О + + if (*value.c_str() == 0) { // 绌鸿緭鍏 + MOT_LOG_DIAG2("Configuration %s at [section %s, key %s] is empty", itemName, sectionFullName.c_str(), + key.c_str()); + } else if (endptr == value.c_str()) { // 鏃犳湁鏁堟暟瀛 + MOT_LOG_DIAG2("Configuration %s at [section %s, key %s] has no valid digits at all: %s", itemName, + sectionFullName.c_str(), key.c_str(), value.c_str()); + } else if (*endptr != 0) { // 瀛樺湪鏃犳晥鐨勫悗缁瓧绗 + MOT_LOG_DIAG2("Configuration %s at [section %s, key %s] has invalid trailing characters: %s", itemName, + sectionFullName.c_str(), key.c_str(), value.c_str()); + } else if ((intValue == ULLONG_MAX) && (errno == ERANGE)) { // 婧㈠嚭 MOT_LOG_DIAG2("Configuration %s at [section %s, key %s] overflows: %s", itemName, value.c_str()); } else { int err = errno; MOT_LOG_TRACE("Configuration %s at [section %s, key %s] is ok: %s --> %" PRIu64 " (value = %p, endptr = %p, *endptr = %u, errno: %d)", - itemName, - sectionFullName.c_str(), - key.c_str(), - value.c_str(), - intValue, - value.c_str(), - endptr, - (unsigned)*endptr, - err); + itemName, sectionFullName.c_str(), key.c_str(), value.c_str(), intValue, value.c_str(), endptr, + (unsigned)*endptr, err); result = true; } + return result; } } // namespace MOT diff --git a/src/gausskernel/storage/mot/core/infra/config/config_item.cpp b/src/gausskernel/storage/mot/core/infra/config/config_item.cpp index 3d8ed98fe..a64b58ae8 100644 --- a/src/gausskernel/storage/mot/core/infra/config/config_item.cpp +++ b/src/gausskernel/storage/mot/core/infra/config/config_item.cpp @@ -28,7 +28,7 @@ namespace MOT { IMPLEMENT_CLASS_LOGGER(ConfigItem, Configuration) constexpr const char ConfigItem::PATH_SEP; -constexpr const char* ConfigItem::PATH_SEP_STR; +constexpr const char *ConfigItem::PATH_SEP_STR; constexpr size_t ConfigItem::CFG_MAX_PATH_LEN; constexpr size_t ConfigItem::CFG_MAX_NAME_LEN; constexpr size_t ConfigItem::CFG_MAX_FULL_PATH_LEN; @@ -41,38 +41,47 @@ ConfigItem::ConfigItem(ConfigItemClass itemClass) m_depth(0) {} -bool ConfigItem::Initialize(const char* path, const char* name) +/* + * 鍔熻兘锛氬垵濮嬪寲閰嶇疆椤圭殑璺緞鍜屽悕绉 + * + * 鍙傛暟鍒楄〃锛 + * path锛氶厤缃」鐨勮矾寰 + * name锛氶厤缃」鐨勫悕绉 + * + * 杩斿洖鍊硷細 + * 濡傛灉鍒濆鍖栨垚鍔燂紝杩斿洖 true锛涘惁鍒欒繑鍥 false銆 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庡垵濮嬪寲閰嶇疆椤圭殑璺緞銆佸悕绉板拰瀹屾暣璺緞鍚嶇О锛屼互鍙婅绠楅厤缃」鐨勬繁搴︺ + */ +bool ConfigItem::Initialize(const char *path, const char *name) { bool result = false; - if ((path[0] == 0) || (path[0] == PATH_SEP)) { // either empty or has leading slash - result = m_path.assign(path); - } else { // non-empty and missing leading slash - result = m_path.format("%s%s", PATH_SEP_STR, path); + if ((path[0] == 0) || (path[0] == PATH_SEP)) { // 妫鏌ヨ矾寰勬槸鍚︿负绌烘垨浠ユ枩鏉犲紑澶 + result = m_path.assign(path); // 浣跨敤浼犲叆鐨勮矾寰勫 + } else { // 璺緞闈炵┖涓旂己灏戞枩鏉犲紑澶 + result = m_path.format("%s%s", PATH_SEP_STR, path); // 鍦ㄨ矾寰勫墠鍔犱笂鏂滄潬 } - if (!result) { - MOT_REPORT_ERROR( - MOT_ERROR_INTERNAL, "Load Configuration", "Failed to initialize configuration path to: %s", path); + if (!result) { // 妫鏌ヨ矾寰勫垵濮嬪寲鏄惁鎴愬姛 + MOT_REPORT_ERROR(MOT_ERROR_INTERNAL, "Load Configuration", "Failed to initialize configuration path to: %s", + path); } else { - // safe copy without buffer overrun - result = m_name.assign(name); - if (!result) { - MOT_REPORT_ERROR( - MOT_ERROR_INTERNAL, "Load Configuration", "Failed to initialize configuration name to: %s", name); + // 瀹夊叏澶嶅埗閰嶇疆椤瑰悕绉帮紝閬垮厤缂撳啿鍖烘孩鍑 + result = m_name.assign(name); // 浣跨敤浼犲叆鐨勫悕绉板 + if (!result) { // 妫鏌ュ悕绉板垵濮嬪寲鏄惁鎴愬姛 + MOT_REPORT_ERROR(MOT_ERROR_INTERNAL, "Load Configuration", "Failed to initialize configuration name to: %s", + name); } else { - // safe format without buffer overrun - result = m_fullPathName.format("%s%s%s", m_path.c_str(), PATH_SEP_STR, m_name.c_str()); - if (!result) { - MOT_REPORT_ERROR(MOT_ERROR_INTERNAL, - "Load Configuration", - "Failed to initialize full configuration path to: %s%s%s", - name, - m_path.c_str(), - PATH_SEP_STR, - m_name.c_str()); + // 瀹夊叏鏍煎紡鍖栧畬鏁磋矾寰勫悕绉帮紝閬垮厤缂撳啿鍖烘孩鍑 + result = m_fullPathName.format("%s%s%s", m_path.c_str(), PATH_SEP_STR, m_name.c_str()); // 鍚堝苟璺緞鍜屽悕绉 + if (!result) { // 妫鏌ュ畬鏁磋矾寰勫悕绉板垵濮嬪寲鏄惁鎴愬姛 + MOT_REPORT_ERROR(MOT_ERROR_INTERNAL, "Load Configuration", + "Failed to initialize full configuration path to: %s%s%s", name, m_path.c_str(), + PATH_SEP_STR, m_name.c_str()); } else { - m_depth = ComputeDepth(); + m_depth = ComputeDepth(); // 璁$畻閰嶇疆椤圭殑娣卞害 } } } @@ -80,20 +89,25 @@ bool ConfigItem::Initialize(const char* path, const char* name) return result; } +/* + * 鍔熻兘锛氳绠楅厤缃」鐨勬繁搴 + * + * 杩斿洖鍊硷細 + * 杩斿洖閰嶇疆椤圭殑娣卞害浣滀负鏃犵鍙锋暣鏁般 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁版牴鎹畬鏁磋矾寰勫悕绉颁腑鐨勬枩鏉犳暟鏉ヨ绠楅厤缃」鐨勬繁搴︺傚鏋滃畬鏁磋矾寰勪负鏍圭洰褰曪紝鍒欐繁搴︿负 0銆 + */ uint32_t ConfigItem::ComputeDepth() { uint32_t result = 0; - if (m_fullPathName.compare(PATH_SEP_STR) != 0) { - result = m_fullPathName.count(PATH_SEP); + if (m_fullPathName.compare(PATH_SEP_STR) != 0) { // 妫鏌ュ畬鏁磋矾寰勬槸鍚︿负鏍圭洰褰 + result = m_fullPathName.count(PATH_SEP); // 璁$畻瀹屾暣璺緞涓枩鏉犵殑鏁伴噺锛屼綔涓烘繁搴 } - MOT_LOG_DEBUG("Computed depth in full path %s (@%p), path %s (@%p) and name %s (@%p): %u", - m_fullPathName.c_str(), - m_fullPathName.c_str(), - m_path.c_str(), - m_path.c_str(), - m_name.c_str(), - m_name.c_str(), - result); + // 璁板綍璁$畻寰楀埌鐨勬繁搴︿俊鎭 + MOT_LOG_DEBUG("Computed depth in full path %s (@%p), path %s (@%p) and name %s (@%p): %u", m_fullPathName.c_str(), + m_fullPathName.c_str(), m_path.c_str(), m_path.c_str(), m_name.c_str(), m_name.c_str(), result); return result; } + } // namespace MOT diff --git a/src/gausskernel/storage/mot/core/infra/config/config_item_class.cpp b/src/gausskernel/storage/mot/core/infra/config/config_item_class.cpp index f9d07b4ec..6c26f8eda 100644 --- a/src/gausskernel/storage/mot/core/infra/config/config_item_class.cpp +++ b/src/gausskernel/storage/mot/core/infra/config/config_item_class.cpp @@ -26,34 +26,63 @@ #include namespace MOT { -static const char* CONFIG_ITEM_SECTION_STR = "section"; -static const char* CONFIG_ITEM_VALUE_STR = "value"; -static const char* CONFIG_ITEM_ARRAY_STR = "array"; -static const char* CONFIG_ITEM_UNDEFINED_STR = "N/A"; +static const char *CONFIG_ITEM_SECTION_STR = "section"; +static const char *CONFIG_ITEM_VALUE_STR = "value"; +static const char *CONFIG_ITEM_ARRAY_STR = "array"; +static const char *CONFIG_ITEM_UNDEFINED_STR = "N/A"; -static const char* ITEM_CLASS_NAMES[] = { - CONFIG_ITEM_SECTION_STR, CONFIG_ITEM_VALUE_STR, CONFIG_ITEM_ARRAY_STR, CONFIG_ITEM_UNDEFINED_STR}; +static const char *ITEM_CLASS_NAMES[] = {CONFIG_ITEM_SECTION_STR, CONFIG_ITEM_VALUE_STR, CONFIG_ITEM_ARRAY_STR, + CONFIG_ITEM_UNDEFINED_STR}; -extern ConfigItemClass ConfigItemClassFromString(const char* itemClassStr) +/* + * 鍔熻兘锛氫粠瀛楃涓蹭腑瑙f瀽閰嶇疆椤圭被鍒 + * + * 鍙傛暟鍒楄〃锛 + * itemClassStr锛氳〃绀洪厤缃」绫诲埆鐨勫瓧绗︿覆 + * + * 杩斿洖鍊硷細 + * 杩斿洖 `ConfigItemClass` 鏋氫妇鍊硷紝琛ㄧず瑙f瀽寰楀埌鐨勯厤缃」绫诲埆銆傚鏋滄棤娉曡В鏋愶紝杩斿洖 + * `ConfigItemClass::CONFIG_ITEM_UNDEFINED`銆 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁伴氳繃姣旇緝杈撳叆鐨勫瓧绗︿覆涓庡凡鐭ョ殑閰嶇疆椤圭被鍒瓧绗︿覆锛堝 + * CONFIG_ITEM_SECTION_STR銆丆ONFIG_ITEM_VALUE_STR銆丆ONFIG_ITEM_ARRAY_STR锛夛紝 + * 鏉ョ‘瀹氳緭鍏ュ瓧绗︿覆琛ㄧず鐨勯厤缃」绫诲埆銆傚鏋滃尮閰嶆垚鍔燂紝灏嗚繑鍥炵浉搴旂殑鏋氫妇鍊硷紝鍚﹀垯杩斿洖 CONFIG_ITEM_UNDEFINED銆 + */ +extern ConfigItemClass ConfigItemClassFromString(const char *itemClassStr) { - ConfigItemClass result = ConfigItemClass::CONFIG_ITEM_UNDEFINED; + ConfigItemClass result = ConfigItemClass::CONFIG_ITEM_UNDEFINED; // 鍒濆鍖栫粨鏋滀负 CONFIG_ITEM_UNDEFINED - if (strcmp(itemClassStr, CONFIG_ITEM_SECTION_STR) == 0) { - result = ConfigItemClass::CONFIG_ITEM_SECTION; - } else if (strcmp(itemClassStr, CONFIG_ITEM_VALUE_STR) == 0) { - result = ConfigItemClass::CONFIG_ITEM_VALUE; - } else if (strcmp(itemClassStr, CONFIG_ITEM_ARRAY_STR) == 0) { - result = ConfigItemClass::CONFIG_ITEM_ARRAY; + if (strcmp(itemClassStr, CONFIG_ITEM_SECTION_STR) == 0) { // 妫鏌ユ槸鍚﹀尮閰 CONFIG_ITEM_SECTION_STR + result = ConfigItemClass::CONFIG_ITEM_SECTION; // 鍖归厤鎴愬姛锛岃缃粨鏋滀负 CONFIG_ITEM_SECTION + } else if (strcmp(itemClassStr, CONFIG_ITEM_VALUE_STR) == 0) { // 妫鏌ユ槸鍚﹀尮閰 CONFIG_ITEM_VALUE_STR + result = ConfigItemClass::CONFIG_ITEM_VALUE; // 鍖归厤鎴愬姛锛岃缃粨鏋滀负 CONFIG_ITEM_VALUE + } else if (strcmp(itemClassStr, CONFIG_ITEM_ARRAY_STR) == 0) { // 妫鏌ユ槸鍚﹀尮閰 CONFIG_ITEM_ARRAY_STR + result = ConfigItemClass::CONFIG_ITEM_ARRAY; // 鍖归厤鎴愬姛锛岃缃粨鏋滀负 CONFIG_ITEM_ARRAY } - return result; + return result; // 杩斿洖瑙f瀽寰楀埌鐨勯厤缃」绫诲埆 } -extern const char* ConfigItemClassToString(ConfigItemClass configItemClass) +/* + * 鍔熻兘锛氬皢閰嶇疆椤圭被鍒灇涓惧艰浆鎹负瀛楃涓茶〃绀 + * + * 鍙傛暟鍒楄〃锛 + * configItemClass锛氳〃绀洪厤缃」绫诲埆鐨勬灇涓惧 + * + * 杩斿洖鍊硷細 + * 杩斿洖涓涓寚鍚戣〃绀洪厤缃」绫诲埆鐨勫瓧绗︿覆鐨勬寚閽堛傚鏋滄灇涓惧兼棤鏁堬紝鍒欒繑鍥 CONFIG_ITEM_UNDEFINED_STR銆 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁伴氳繃灏嗘灇涓惧艰浆鎹负瀵瑰簲鐨勬暣鏁扮储寮曪紝鐒跺悗浣跨敤璇ョ储寮曟煡鎵鹃瀹氫箟鐨勫瓧绗︿覆鏁扮粍 ITEM_CLASS_NAMES锛 + * 鏉ヨ幏鍙栭厤缃」绫诲埆鐨勫瓧绗︿覆琛ㄧず銆傚鏋滄灇涓惧兼湁鏁堬紝灏嗚繑鍥炵浉搴旂殑瀛楃涓诧紝鍚﹀垯杩斿洖 CONFIG_ITEM_UNDEFINED_STR銆 + */ +extern const char *ConfigItemClassToString(ConfigItemClass configItemClass) { if (configItemClass < ConfigItemClass::CONFIG_ITEM_UNDEFINED) { - return ITEM_CLASS_NAMES[(uint32_t)configItemClass]; + return ITEM_CLASS_NAMES[(uint32_t)configItemClass]; // 浣跨敤鏁存暟绱㈠紩鏌ユ壘棰勫畾涔夌殑瀛楃涓叉暟缁 } - return CONFIG_ITEM_UNDEFINED_STR; + return CONFIG_ITEM_UNDEFINED_STR; // 鏋氫妇鍊兼棤鏁堬紝杩斿洖 CONFIG_ITEM_UNDEFINED_STR } + } // namespace MOT diff --git a/src/gausskernel/storage/mot/core/infra/config/config_loader.cpp b/src/gausskernel/storage/mot/core/infra/config/config_loader.cpp index b8d1bddc5..de46799a2 100644 --- a/src/gausskernel/storage/mot/core/infra/config/config_loader.cpp +++ b/src/gausskernel/storage/mot/core/infra/config/config_loader.cpp @@ -29,10 +29,26 @@ namespace MOT { -ConfigLoader::ConfigLoader(const char* name, uint32_t priority) : m_priority(priority), m_configTree(nullptr) +/* + * 鏋勯犲嚱鏁帮細ConfigLoader + * + * 鍙傛暟鍒楄〃锛 + * name: 閰嶇疆鍔犺浇鍣ㄧ殑鍚嶇О锛岀敤浜庢爣璇嗗姞杞藉櫒銆 + * priority: 閰嶇疆鍔犺浇鍣ㄧ殑浼樺厛绾э紝鐢ㄤ簬纭畾鍔犺浇椤哄簭銆 + * + * 鍔熻兘锛 + * 鍒濆鍖 ConfigLoader 绫荤殑鏂板疄渚嬨 + * 璁剧疆閰嶇疆鍔犺浇鍣ㄧ殑鍚嶇О鍜屼紭鍏堢骇锛屽苟鍒嗛厤鍐呴儴閰嶇疆鏍戞寚閽堛 + * + * 娉ㄦ剰锛 + * 璇ユ瀯閫犲嚱鏁颁娇鐢ㄤ簡 strncpy_s 鍑芥暟鏉ュ畨鍏ㄥ湴澶嶅埗鍚嶇О锛屼互纭繚涓嶄細鍙戠敓缂撳啿鍖烘孩鍑恒 + */ +ConfigLoader::ConfigLoader(const char *name, uint32_t priority) : m_priority(priority), m_configTree(nullptr) { + // 浣跨敤 strncpy_s 澶嶅埗鍚嶇О浠ョ‘淇濆畨鍏ㄦ errno_t erc = strncpy_s(m_name, MAX_CONFIG_LOADER_NAME, name, strlen(name)); securec_check(erc, "\0", "\0"); + // 纭繚鍚嶇О浠 null 缁堟 m_name[MAX_CONFIG_LOADER_NAME - 1] = 0; } diff --git a/src/gausskernel/storage/mot/core/infra/config/config_manager.cpp b/src/gausskernel/storage/mot/core/infra/config/config_manager.cpp index e4c05c052..e40245777 100644 --- a/src/gausskernel/storage/mot/core/infra/config/config_manager.cpp +++ b/src/gausskernel/storage/mot/core/infra/config/config_manager.cpp @@ -37,22 +37,45 @@ namespace MOT { DECLARE_LOGGER(ConfigManager, Configuration) -ConfigManager* ConfigManager::m_manager = nullptr; +ConfigManager *ConfigManager::m_manager = nullptr; +/* + * 鍔熻兘锛氬垵濮嬪寲 ConfigManager 绫荤殑鏂板疄渚嬶紝璁剧疆閰嶇疆鍔犺浇鍣ㄥ拰鐩戝惉鍣ㄧ殑鍒濆璁℃暟锛屼娇鐢 memset_s +鍑芥暟灏嗗姞杞藉櫒鍜岀洃鍚櫒鏁扮粍鍒濆鍖栦负闆躲 + * + * 娉ㄦ剰锛 + * 浣跨敤 memset_s 鍑芥暟鍙互纭繚鍒濆鍖栬繃绋嬫槸瀹夊叏鐨勶紝浠ラ槻姝㈡綔鍦ㄧ殑鍐呭瓨璁块棶闂銆 + * + * 瀹冩墽琛屼互涓嬫搷浣滐細 + * 1銆佸皢閰嶇疆鍔犺浇鍣ㄨ鏁 m_configLoaderCount 鍒濆鍖栦负闆躲 + * 2銆佸皢鐩戝惉鍣ㄨ鏁 m_listenerCount 鍒濆鍖栦负闆躲 + * 3銆佷娇鐢 memset_s 鍑芥暟灏嗛厤缃姞杞藉櫒鏁扮粍 m_configLoaders 鍒濆鍖栦负闆躲 + * 4銆佷娇鐢 memset_s 鍑芥暟灏嗙洃鍚櫒鏁扮粍 m_listeners 鍒濆鍖栦负闆躲 + */ ConfigManager::ConfigManager() : m_configLoaderCount(0), m_listenerCount(0) { + // 浣跨敤 memset_s 鍑芥暟灏嗛厤缃姞杞藉櫒鏁扮粍鍒濆鍖栦负闆 errno_t erc = memset_s(m_configLoaders, sizeof(m_configLoaders), 0, sizeof(m_configLoaders)); securec_check(erc, "\0", "\0"); + // 浣跨敤 memset_s 鍑芥暟灏嗙洃鍚櫒鏁扮粍鍒濆鍖栦负闆 erc = memset_s(m_listeners, sizeof(m_listeners), 0, sizeof(m_listeners)); securec_check(erc, "\0", "\0"); } +/* + * 鍔熻兘锛欳onfigManager 绫荤殑鏋愭瀯鍑芥暟锛岀敤浜庢竻鐞嗘墍鏈夐厤缃姞杞藉櫒鐨勮祫婧 + * + * 娉ㄦ剰锛 + * 鏋愭瀯鍑芥暟璐熻矗閲婃斁鎵鏈夐厤缃姞杞藉櫒鐨勮祫婧愩傚畠棣栧厛妫鏌ユ瘡涓姞杞藉櫒鏄惁涓虹┖鎸囬拡锛 + * 濡傛灉涓嶄负绌猴紝鍒欏皾璇曚粠閰嶇疆鍔犺浇鍣ㄤ腑鑾峰彇閰嶇疆锛屽苟璋ㄦ厧鍦板皢鍏朵粠鍒嗗眰閰嶇疆鏍戜腑绉婚櫎銆 + * 鏈鍚庯紝鍒犻櫎閰嶇疆鍔犺浇鍣ㄥ苟灏嗗叾璁剧疆涓 nullptr銆 + */ ConfigManager::~ConfigManager() { - // cleanup all configuration loaders + // 娓呯悊鎵鏈夐厤缃姞杞藉櫒 for (uint32_t i = 0; i < m_configLoaderCount; ++i) { if (m_configLoaders[i]) { - // remove configuration tree carefully (some might have failed to load) + // 璋ㄦ厧鍦扮Щ闄ら厤缃爲锛堟煇浜涘姞杞藉櫒鍙兘鍔犺浇澶辫触锛 if (m_configLoaders[i]->GetConfig() != nullptr) { m_layeredConfigTree.RemoveConfigTree(m_configLoaders[i]->GetConfig()); } @@ -62,46 +85,108 @@ ConfigManager::~ConfigManager() } } -bool ConfigManager::CreateInstance(char** argv /* = nullptr */, int argc /* = 0 */) +/* + * 鍔熻兘锛氬垱寤 ConfigManager 鐨勫崟渚嬪疄渚 + * + * 鍙傛暟鍒楄〃锛 + * argv锛氬懡浠よ鍙傛暟鏁扮粍鐨勬寚閽堬紝榛樿鍊间负 nullptr + * argc锛氬懡浠よ鍙傛暟鏁扮粍鐨勫ぇ灏忥紝榛樿鍊间负 0 + * + * 杩斿洖鍊硷細 + * 濡傛灉鎴愬姛鍒涘缓浜 ConfigManager 瀹炰緥锛屽垯杩斿洖 true锛涘惁鍒欒繑鍥 false銆 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁拌礋璐e垱寤 ConfigManager 鐨勫崟渚嬪疄渚嬶紝棣栧厛妫鏌 m_manager 鏄惁宸插垎閰嶃 + * 濡傛灉灏氭湭鍒嗛厤锛屽垯灏濊瘯涓 m_manager 鍒嗛厤鍐呭瓨銆傚鏋滃唴瀛樺垎閰嶅け璐ワ紝鍑芥暟浼氭姤鍛婂唴瀛樺垎閰嶉敊璇苟杩斿洖 false銆 + * 濡傛灉鎴愬姛鍒嗛厤鍐呭瓨锛屽皢璋冪敤 m_manager 鐨 Initialize 鏂规硶杩涜鍒濆鍖栥 + * 濡傛灉鍒濆鍖栧け璐ワ紝灏嗛噴鏀惧垎閰嶇殑鍐呭瓨锛屽苟灏 m_manager 璁剧疆涓 nullptr锛屽苟杩斿洖 false銆 + * 濡傛灉鍒濆鍖栨垚鍔燂紝鍑芥暟灏嗚繑鍥 true锛岃〃绀烘垚鍔熷垱寤轰簡 ConfigManager 瀹炰緥銆 + */ +bool ConfigManager::CreateInstance(char **argv /* = nullptr */, int argc /* = 0 */) { bool result = false; + + // 妫鏌 m_manager 鏄惁宸插垎閰 MOT_ASSERT(m_manager == nullptr); + if (m_manager == nullptr) { + // 灏濊瘯涓 m_manager 鍒嗛厤鍐呭瓨 m_manager = new (std::nothrow) ConfigManager(); + if (m_manager == nullptr) { - MOT_REPORT_ERROR( - MOT_ERROR_OOM, "Load Configuration", "Failed to allocate memory for configuration manager, aborting"); + // 鍐呭瓨鍒嗛厤澶辫触锛屾姤鍛婇敊璇苟杩斿洖 false + MOT_REPORT_ERROR(MOT_ERROR_OOM, "Load Configuration", + "Failed to allocate memory for configuration manager, aborting"); } else { + // 璋冪敤鍒濆鍖栨柟娉曡繘琛屽垵濮嬪寲 result = m_manager->Initialize(argv, argc); + if (!result) { + // 鍒濆鍖栧け璐ワ紝閲婃斁鍒嗛厤鐨勫唴瀛橈紝骞跺皢 m_manager 璁剧疆涓 nullptr delete m_manager; m_manager = nullptr; } } } + return result; } +/* + * 鍔熻兘锛氶攢姣 ConfigManager 鐨勫崟渚嬪疄渚 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁拌礋璐i攢姣 ConfigManager 鐨勫崟渚嬪疄渚嬨 + * 棣栧厛锛屽畠浼氭鏌 m_manager 鏄惁宸插垎閰嶏紝纭繚鍗曚緥瀹炰緥瀛樺湪銆 + * 鐒跺悗锛屽畠浼氬垹闄 m_manager锛岄噴鏀惧叾鍒嗛厤鐨勫唴瀛橈紝骞跺皢 m_manager 璁剧疆涓 nullptr锛屼互纭繚鍗曚緥瀹炰緥涓嶅啀瀛樺湪銆 + */ void ConfigManager::DestroyInstance() { MOT_ASSERT(m_manager != nullptr); + if (m_manager != nullptr) { + // 鍒犻櫎 m_manager锛岄噴鏀惧垎閰嶇殑鍐呭瓨锛屽苟灏 m_manager 璁剧疆涓 nullptr delete m_manager; m_manager = nullptr; } } - -ConfigManager& ConfigManager::GetInstance() +/* + * 鍔熻兘锛氳幏鍙 ConfigManager 鐨勫崟渚嬪疄渚 + * + * 鍙傛暟鍒楄〃锛氭棤 + * + * 杩斿洖鍊硷細杩斿洖 ConfigManager 鐨勫崟渚嬪疄渚嬬殑寮曠敤 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庤幏鍙 ConfigManager 鐨勫崟渚嬪疄渚嬨 + * 棣栧厛锛屽畠浼氭鏌 m_manager 鏄惁宸插垎閰嶏紝纭繚鍗曚緥瀹炰緥瀛樺湪銆 + * 鐒跺悗锛屽畠杩斿洖璇ュ崟渚嬪疄渚嬬殑寮曠敤锛屽厑璁稿鎴风浠g爜浣跨敤 ConfigManager 鐨勫姛鑳姐 + */ +ConfigManager &ConfigManager::GetInstance() { MOT_ASSERT(m_manager != nullptr); return *m_manager; } - -bool ConfigManager::AddConfigFile(const char* configFilePath, const char* name /* = "Main" */, - ConfigFileFormat configFileFormat /* = ConfigFileFormat::CONFIG_FILE_FORMAT_NONE */) +/* + * 鍔熻兘锛氬悜閰嶇疆绠$悊鍣ㄦ坊鍔犻厤缃枃浠跺姞杞藉櫒 + * + * 鍙傛暟鍒楄〃锛 + * configFilePath锛氶厤缃枃浠剁殑璺緞 + * name锛氶厤缃枃浠跺姞杞藉櫒鐨勫悕绉帮紝榛樿涓 "Main" + * configFileFormat锛氶厤缃枃浠剁殑鏍煎紡锛岄粯璁や负 ConfigFileFormat::CONFIG_FILE_FORMAT_NONE + * + * 杩斿洖鍊硷細濡傛灉鎴愬姛娣诲姞閰嶇疆鏂囦欢鍔犺浇鍣紝鍒欒繑鍥 true锛屽惁鍒欒繑鍥 false + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庡悜閰嶇疆绠$悊鍣ㄦ坊鍔犻厤缃枃浠跺姞杞藉櫒锛屼互渚垮姞杞介厤缃枃浠跺苟瑙f瀽鍏朵腑鐨勯厤缃」銆 + * 瀹冩牴鎹厤缃枃浠剁殑鏍煎紡鍒涘缓鐩稿簲鐨勯厤缃枃浠跺姞杞藉櫒銆 + * 濡傛灉鎴愬姛鍒涘缓鍜屾坊鍔犲姞杞藉櫒锛岃繑鍥 true锛屽惁鍒欒繑鍥 false 骞惰褰曢敊璇 + */ +bool ConfigManager::AddConfigFile(const char *configFilePath, const char *name /* = "Main" */, + ConfigFileFormat configFileFormat /* = ConfigFileFormat::CONFIG_FILE_FORMAT_NONE */) { bool result = false; - ConfigFileLoader* cfgFileLoader = nullptr; + ConfigFileLoader *cfgFileLoader = nullptr; switch (configFileFormat) { case ConfigFileFormat::CONFIG_FILE_PROPS: @@ -113,20 +198,16 @@ bool ConfigManager::AddConfigFile(const char* configFilePath, const char* name / break; default: - MOT_REPORT_ERROR(MOT_ERROR_INVALID_ARG, - "Load Configuration", - "Invalid configuration file format specification %d", - (int)configFileFormat); + MOT_REPORT_ERROR(MOT_ERROR_INVALID_ARG, "Load Configuration", + "Invalid configuration file format specification %d", (int)configFileFormat); return false; } if (cfgFileLoader != nullptr) { result = AddConfigLoader(cfgFileLoader); if (!result) { - MOT_REPORT_ERROR(MOT_ERROR_INVALID_ARG, - "Load Configuration", - "Failed to add configuration file loader by name %s (duplicate?)", - name); + MOT_REPORT_ERROR(MOT_ERROR_INVALID_ARG, "Load Configuration", + "Failed to add configuration file loader by name %s (duplicate?)", name); delete cfgFileLoader; } } else { @@ -136,8 +217,21 @@ bool ConfigManager::AddConfigFile(const char* configFilePath, const char* name / return result; } - -static bool CompareConfgLoaders(ConfigLoader* lhs, ConfigLoader* rhs) +/* + * 鍔熻兘锛氭瘮杈冧袱涓厤缃姞杞藉櫒鐨勪紭鍏堢骇 + * + * 鍙傛暟鍒楄〃锛 + * lhs锛氳姣旇緝鐨勭涓涓厤缃姞杞藉櫒 + * rhs锛氳姣旇緝鐨勭浜屼釜閰嶇疆鍔犺浇鍣 + * + * 杩斿洖鍊硷細濡傛灉绗竴涓厤缃姞杞藉櫒鐨勪紭鍏堢骇杈冧綆锛堟暟瀛楄緝楂橈級锛屽垯杩斿洖 true锛屽惁鍒欒繑鍥 false + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庢瘮杈冧袱涓厤缃姞杞藉櫒鐨勪紭鍏堢骇锛屼互纭畾瀹冧滑鍦ㄥ姞杞介『搴忎腑鐨勪綅缃 + * 浼樺厛绾ф暟瀛楄緝浣庣殑閰嶇疆鍔犺浇鍣紙鍗虫暟瀛楄緝楂橈級搴旇鍦ㄥ姞杞介『搴忎腑鎺掑湪鍓嶉潰銆 + * 濡傛灉绗竴涓厤缃姞杞藉櫒鐨勪紭鍏堢骇杈冧綆锛屽垯杩斿洖 true锛屽惁鍒欒繑鍥 false銆 + */ +static bool CompareConfgLoaders(ConfigLoader *lhs, ConfigLoader *rhs) { int lhsPriority = lhs->GetPriority(); int rhsPriority = rhs->GetPriority(); @@ -148,18 +242,29 @@ static bool CompareConfgLoaders(ConfigLoader* lhs, ConfigLoader* rhs) } return true; } - -bool ConfigManager::AddConfigLoader(ConfigLoader* configLoader) +/* + * 鍔熻兘锛氭坊鍔犻厤缃姞杞藉櫒鍒伴厤缃鐞嗗櫒 + * + * 鍙傛暟鍒楄〃锛 + * configLoader锛氳娣诲姞鐨勯厤缃姞杞藉櫒瀵硅薄鐨勬寚閽 + * + * 杩斿洖鍊硷細 + * 濡傛灉鎴愬姛娣诲姞閰嶇疆鍔犺浇鍣紝鍒欒繑鍥 true锛涘鏋滈厤缃姞杞藉櫒宸茶揪鍒版渶澶ф暟閲忛檺鍒舵垨娣诲姞澶辫触锛屽垯杩斿洖 false銆 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庡皢閰嶇疆鍔犺浇鍣ㄦ坊鍔犲埌閰嶇疆绠$悊鍣ㄤ腑銆傞厤缃姞杞藉櫒浼氭牴鎹叾浼樺厛绾у湪鍔犺浇閰嶇疆鏃惰繘琛屾帓搴忋 + * 杈冧綆浼樺厛绾х殑鍔犺浇鍣ㄥ皢棣栧厛鍔犺浇閰嶇疆锛屼互渚胯緝楂樹紭鍏堢骇鐨勫姞杞藉櫒鍙互鍩轰簬宸插姞杞界殑閰嶇疆璁剧疆鍏朵粬闄愬埗銆 + * 濡傛灉宸茶揪鍒伴厤缃姞杞藉櫒鐨勬渶澶ф暟閲忛檺鍒讹紝灏嗚繑鍥 false銆 + */ +bool ConfigManager::AddConfigLoader(ConfigLoader *configLoader) { bool result = false; MOT_LOG_TRACE("Adding configuration loader %s", configLoader->GetName()); if (m_configLoaderCount == MAX_CONFIG_LOADER_COUNT) { - MOT_REPORT_ERROR(MOT_ERROR_RESOURCE_LIMIT, - "Load Configuration", - "Cannot add configuration loader %s: Reached limit %u", - configLoader->GetName(), - (unsigned)MAX_CONFIG_LOADER_COUNT); + MOT_REPORT_ERROR(MOT_ERROR_RESOURCE_LIMIT, "Load Configuration", + "Cannot add configuration loader %s: Reached limit %u", configLoader->GetName(), + (unsigned)MAX_CONFIG_LOADER_COUNT); } else { // insert sorted in descending order - we want lower priority loaders to load configuration first, so higher // priority loaders can impose other limits based on configuration loaded already (as in external loaders that @@ -168,15 +273,27 @@ bool ConfigManager::AddConfigLoader(ConfigLoader* configLoader) std::sort(m_configLoaders, m_configLoaders + m_configLoaderCount, CompareConfgLoaders); uint32_t configLoaderPos = std::find(m_configLoaders, m_configLoaders + m_configLoaderCount, configLoader) - m_configLoaders; - MOT_LOG_TRACE( - "Configuration loader %s added successfully at slot %u", configLoader->GetName(), configLoaderPos); + MOT_LOG_TRACE("Configuration loader %s added successfully at slot %u", configLoader->GetName(), + configLoaderPos); result = true; } return result; } - -bool ConfigManager::RemoveConfigLoader(const char* configName) +/* + * 鍔熻兘锛氫粠閰嶇疆绠$悊鍣ㄤ腑鍒犻櫎鎸囧畾鍚嶇О鐨勯厤缃姞杞藉櫒 + * + * 鍙傛暟鍒楄〃锛 + * configName锛氳鍒犻櫎鐨勯厤缃姞杞藉櫒鐨勫悕绉 + * + * 杩斿洖鍊硷細 + * 濡傛灉鎴愬姛鍒犻櫎閰嶇疆鍔犺浇鍣紝鍒欒繑鍥 true锛涘鏋滈厤缃姞杞藉櫒鏈壘鍒版垨鍒犻櫎澶辫触锛屽垯杩斿洖 false銆 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庝粠閰嶇疆绠$悊鍣ㄤ腑鍒犻櫎鎸囧畾鍚嶇О鐨勯厤缃姞杞藉櫒銆傚鏋滈厤缃姞杞藉櫒琚垚鍔熷垹闄わ紝瀹冨皢浠庡唴閮ㄥ垪琛ㄤ腑绉婚櫎锛 + * 鍚屾椂涔熶細浠庨厤缃爲涓Щ闄や笌涔嬬浉鍏宠仈鐨勯厤缃傚鏋滈厤缃姞杞藉櫒鏈壘鍒版垨鍒犻櫎澶辫触锛屽皢杩斿洖 false銆 + */ +bool ConfigManager::RemoveConfigLoader(const char *configName) { bool result = false; MOT_LOG_TRACE("Removing configuration loader %s [%u registered]", configName, m_configLoaderCount); @@ -205,16 +322,26 @@ bool ConfigManager::RemoveConfigLoader(const char* configName) return result; } - -bool ConfigManager::AddConfigChangeListener(IConfigChangeListener* listener) +/* + * 鍔熻兘锛氬悜閰嶇疆绠$悊鍣ㄤ腑娣诲姞閰嶇疆鏇存敼鐩戝惉鍣 + * + * 鍙傛暟鍒楄〃锛 + * listener锛氳娣诲姞鐨勯厤缃洿鏀圭洃鍚櫒鐨勬寚閽 + * + * 杩斿洖鍊硷細 + * 濡傛灉鎴愬姛娣诲姞鐩戝惉鍣紝鍒欒繑鍥 true锛涘鏋滃凡杈惧埌鐩戝惉鍣ㄦ暟閲忎笂闄愭垨娣诲姞澶辫触锛屽垯杩斿洖 false銆 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庡悜閰嶇疆绠$悊鍣ㄤ腑娣诲姞閰嶇疆鏇存敼鐩戝惉鍣ㄣ傜洃鍚櫒浼氬湪閰嶇疆鏇存敼鏃惰閫氱煡锛屼互渚挎墽琛岀浉搴旂殑鎿嶄綔銆 + * 濡傛灉鎴愬姛娣诲姞鐩戝惉鍣紝灏嗚繑鍥 true锛涘鏋滃凡杈惧埌鐩戝惉鍣ㄦ暟閲忎笂闄愭垨娣诲姞澶辫触锛屽皢杩斿洖 false銆 + */ +bool ConfigManager::AddConfigChangeListener(IConfigChangeListener *listener) { bool result = false; if (m_listenerCount == MAX_CONFIG_LISTENER_COUNT) { - MOT_REPORT_ERROR(MOT_ERROR_RESOURCE_LIMIT, - "Load Configuration", - "Cannot add configuration listener: Reached limit %u", - (unsigned)MAX_CONFIG_LISTENER_COUNT); + MOT_REPORT_ERROR(MOT_ERROR_RESOURCE_LIMIT, "Load Configuration", + "Cannot add configuration listener: Reached limit %u", (unsigned)MAX_CONFIG_LISTENER_COUNT); } else { m_listeners[m_listenerCount++] = listener; result = true; @@ -223,7 +350,21 @@ bool ConfigManager::AddConfigChangeListener(IConfigChangeListener* listener) return result; } -bool ConfigManager::RemoveConfigChangeListener(IConfigChangeListener* listener) +/* + * 鍔熻兘锛氫粠閰嶇疆绠$悊鍣ㄤ腑绉婚櫎閰嶇疆鏇存敼鐩戝惉鍣 + * + * 鍙傛暟鍒楄〃锛 + * listener锛氳绉婚櫎鐨勯厤缃洿鏀圭洃鍚櫒鐨勬寚閽 + * + * 杩斿洖鍊硷細 + * 濡傛灉鎴愬姛绉婚櫎鐩戝惉鍣紝鍒欒繑鍥 true锛涘鏋滅洃鍚櫒鏈壘鍒版垨绉婚櫎澶辫触锛屽垯杩斿洖 false銆 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庝粠閰嶇疆绠$悊鍣ㄤ腑绉婚櫎閰嶇疆鏇存敼鐩戝惉鍣ㄣ傞鍏堬紝瀹冧細閬嶅巻鐩戝惉鍣ㄦ暟缁勶紝瀵绘壘涓庣粰瀹 listener 鎸囬拡鍖归厤鐨勭洃鍚櫒銆 + * 濡傛灉鎵惧埌鍖归厤鐨勭洃鍚櫒锛屽皢杩斿洖 true锛屽苟灏嗘暟缁勪腑鐨勭洃鍚櫒寰鍓嶇Щ鍔ㄤ竴涓綅缃紝浠ュ~琛ュ垹闄ょ殑浣嶇疆銆 + * 濡傛灉鐩戝惉鍣ㄦ湭鎵惧埌鎴栫Щ闄ゅけ璐ワ紝灏嗚繑鍥 false锛屽苟璁板綍閿欒娑堟伅銆 + */ +bool ConfigManager::RemoveConfigChangeListener(IConfigChangeListener *listener) { bool result = false; @@ -246,7 +387,17 @@ bool ConfigManager::RemoveConfigChangeListener(IConfigChangeListener* listener) return result; } - +/* + * 鍔熻兘锛氬垵濮嬪寲鍔犺浇閰嶇疆 + * + * 杩斿洖鍊硷細 + * 濡傛灉鎴愬姛鍒濆鍖栧姞杞介厤缃紝鍒欒繑鍥 true锛涘鏋滃姞杞介厤缃け璐ワ紝鍒欒繑鍥 false銆 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庡垵濮嬪寲鍔犺浇閰嶇疆銆傚畠棣栧厛灏濊瘯浠庢墍鏈夐厤缃姞杞藉櫒涓姞杞介厤缃紝鐒跺悗瑙﹀彂浠庡垰鍒氬姞杞界殑閰嶇疆鏇存柊锛堜粎瀵圭壒瀹氱洃鍚櫒锛夈 + * 濡傛灉鍔犺浇閰嶇疆澶辫触锛屽嚱鏁板皢璁板綍閿欒淇℃伅锛屼絾浼氱户缁娇鐢ㄩ粯璁ら厤缃苟杩斿洖 true銆 + * 濡傛灉鍔犺浇閰嶇疆鎴愬姛锛屽嚱鏁颁細楠岃瘉涓婚厤缃槸鍚︽湁鏁堬紝濡傛灉鏈夋晥鍒欒繑鍥 true銆 + */ bool ConfigManager::InitLoad() { bool result = false; @@ -262,7 +413,7 @@ bool ConfigManager::InitLoad() } else { // trigger update from just-loaded configuration (only to this specific listener). MOT_LOG_DEBUG("Reloaded MOTConfiguration from main configuration"); - MOTConfiguration& motCfg = GetGlobalConfiguration(); + MOTConfiguration &motCfg = GetGlobalConfiguration(); motCfg.OnConfigChange(); // now the main configuration is fully loaded, so let's validate it @@ -273,9 +424,22 @@ bool ConfigManager::InitLoad() return result; } -const ConfigTree* ConfigManager::GetConfigTree(const char* configName) const +/* + * 鍔熻兘锛氳幏鍙栨寚瀹氶厤缃悕绉扮殑閰嶇疆鏍 + * + * 鍙傛暟鍒楄〃锛 + * configName锛氶厤缃悕绉 + * + * 杩斿洖鍊硷細 + * 杩斿洖涓涓寚鍚戦厤缃爲鐨勬寚閽堬紝濡傛灉鎵句笉鍒版寚瀹氬悕绉扮殑閰嶇疆鍒欒繑鍥 nullptr銆 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庤幏鍙栨寚瀹氶厤缃悕绉扮殑閰嶇疆鏍戙傚畠浼氶亶鍘嗘墍鏈夐厤缃姞杞藉櫒锛屾煡鎵惧悕绉板尮閰嶇殑閰嶇疆鏍戙 + * 濡傛灉鎵惧埌鍖归厤鐨勯厤缃爲锛屽皢杩斿洖鎸囧悜璇ラ厤缃爲鐨勬寚閽堬紝鍚﹀垯杩斿洖 nullptr銆 + */ +const ConfigTree *ConfigManager::GetConfigTree(const char *configName) const { - const ConfigTree* result = nullptr; + const ConfigTree *result = nullptr; for (uint32_t i = 0; i < m_configLoaderCount; ++i) { if (strcmp(m_configLoaders[i]->GetName(), configName) == 0) { result = m_configLoaders[i]->GetConfig(); @@ -284,12 +448,27 @@ const ConfigTree* ConfigManager::GetConfigTree(const char* configName) const } return result; } - -bool ConfigManager::Initialize(char** argv, int argc) +/* + * 鍔熻兘锛氬垵濮嬪寲閰嶇疆绠$悊鍣 + * + * 鍙傛暟鍒楄〃锛 + * argv锛氭寚鍚戝懡浠よ鍙傛暟鐨勬寚閽堟暟缁 + * argc锛氬懡浠よ鍙傛暟鐨勬暟閲 + * + * 杩斿洖鍊硷細 + * 濡傛灉鍒濆鍖栨垚鍔燂紝杩斿洖 true锛涘惁鍒欒繑鍥 false銆 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庡垵濮嬪寲閰嶇疆绠$悊鍣ㄣ傚畠鍙互璁剧疆鏃ュ織绾у埆锛屾坊鍔犲懡浠よ閰嶇疆鍔犺浇鍣ㄧ瓑銆 + * 棣栧厛锛屽畠妫鏌ョ幆澧冨彉閲 "MOT_DEBUG_CFG_LOAD" 鏄惁璁剧疆涓 "TRUE"锛屽鏋滄槸鍒欏皢鏃ュ織缁勪欢 "Configuration" 鐨勬棩蹇楃骇鍒缃负 + * DEBUG銆 鐒跺悗锛屽鏋滀紶鍏ヤ簡鍛戒护琛屽弬鏁帮紝瀹冧細灏濊瘯娣诲姞鍛戒护琛岄厤缃姞杞藉櫒锛屼互瑙f瀽杩欎簺鍙傛暟銆 濡傛灉鍒濆鍖栨垚鍔燂紝杩斿洖 + * true锛涘惁鍒欒繑鍥 false銆 + */ +bool ConfigManager::Initialize(char **argv, int argc) { bool result = true; - char* envvar = getenv("MOT_DEBUG_CFG_LOAD"); + char *envvar = getenv("MOT_DEBUG_CFG_LOAD"); if (envvar && (strcmp(envvar, "TRUE") == 0)) { SetLogComponentLogLevel("Configuration", LogLevel::LL_DEBUG); } @@ -298,42 +477,71 @@ bool ConfigManager::Initialize(char** argv, int argc) if (argv != nullptr && argc != 0) { result = AddCmdLineConfigLoader(argv, argc); if (!result) { - MOT_REPORT_PANIC(MOT_ERROR_INTERNAL, - "Configuration Manager Initialization", - "Failed to create command line configuration loader"); + MOT_REPORT_PANIC(MOT_ERROR_INTERNAL, "Configuration Manager Initialization", + "Failed to create command line configuration loader"); } } return result; } - -bool ConfigManager::AddCmdLineConfigLoader(char** argv, int argc) +/* + * 鍔熻兘锛氭坊鍔犲懡浠よ閰嶇疆鍔犺浇鍣 + * + * 鍙傛暟鍒楄〃锛 + * argv锛氭寚鍚戝懡浠よ鍙傛暟鐨勬寚閽堟暟缁 + * argc锛氬懡浠よ鍙傛暟鐨勬暟閲 + * + * 杩斿洖鍊硷細 + * 濡傛灉娣诲姞鎴愬姛锛岃繑鍥 true锛涘惁鍒欒繑鍥 false銆 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庡垱寤哄苟娣诲姞涓涓懡浠よ閰嶇疆鍔犺浇鍣ㄣ傚懡浠よ閰嶇疆鍔犺浇鍣ㄥ皢瑙f瀽缁欏畾鐨勫懡浠よ鍙傛暟浠ュ姞杞介厤缃 + * 棣栧厛锛屽畠灏濊瘯鍒嗛厤鍐呭瓨浠ュ垱寤 `CmdLineConfigLoader` 鐨勫疄渚嬨 + * 濡傛灉鍒嗛厤鍐呭瓨澶辫触锛屽皢杩斿洖 false 骞舵姤鍛婂唴瀛樺垎閰嶉敊璇 + * 鍚﹀垯锛屽畠灏濊瘯閫氳繃璋冪敤 `AddConfigLoader` 鍑芥暟灏嗗姞杞藉櫒娣诲姞鍒伴厤缃鐞嗗櫒涓 + * 濡傛灉娣诲姞鎴愬姛锛岃繑鍥 true锛涘惁鍒欒繑鍥 false銆 + */ +bool ConfigManager::AddCmdLineConfigLoader(char **argv, int argc) { bool result = true; - ConfigLoader* cmdLineCfgLoader = new (std::nothrow) CmdLineConfigLoader(argv, argc); + ConfigLoader *cmdLineCfgLoader = new (std::nothrow) CmdLineConfigLoader(argv, argc); if (cmdLineCfgLoader == nullptr) { MOT_REPORT_ERROR(MOT_ERROR_OOM, "Load Configuration", "Failed to allocate command line configuration loader"); result = false; } else { result = AddConfigLoader(cmdLineCfgLoader); if (!result) { - MOT_REPORT_ERROR(MOT_ERROR_INTERNAL, - "Load Configuration", - "Failed to add command line configuration loader (duplicate?)"); + MOT_REPORT_ERROR(MOT_ERROR_INTERNAL, "Load Configuration", + "Failed to add command line configuration loader (duplicate?)"); delete cmdLineCfgLoader; } } return result; } - -ConfigFileLoader* ConfigManager::CreateConfigFileLoader(const char* configFilePath, const char* name) +/* + * 鍔熻兘锛氬垱寤洪厤缃枃浠跺姞杞藉櫒 + * + * 鍙傛暟鍒楄〃锛 + * configFilePath锛氶厤缃枃浠剁殑璺緞 + * name锛氶厤缃枃浠跺姞杞藉櫒鐨勫悕绉 + * + * 杩斿洖鍊硷細 + * 濡傛灉鎴愬姛鍒涘缓閰嶇疆鏂囦欢鍔犺浇鍣紝杩斿洖璇ュ姞杞藉櫒鐨勬寚閽堬紱鍚﹀垯杩斿洖 nullptr銆 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庢牴鎹厤缃枃浠剁殑璺緞鍜屽悕绉板垱寤轰竴涓厤缃枃浠跺姞杞藉櫒銆傞鍏堬紝瀹冩鏌ユ枃浠惰矾寰勪腑鐨勬枃浠跺悗缂銆 + * 濡傛灉鍚庣紑涓 "conf"锛屽垯鍒涘缓涓涓 `PropsConfigFileLoader` 瀹炰緥锛岃鍔犺浇鍣ㄧ敤浜庤В鏋 "conf" 鏍煎紡鐨勯厤缃枃浠躲 + * 鍚﹀垯锛屽嚱鏁颁細鎶ュ憡鏃犳晥鐨勫弬鏁伴敊璇苟杩斿洖 nullptr銆 + * 濡傛灉鎴愬姛鍒涘缓鍔犺浇鍣紝瀹冨皢杩斿洖鍔犺浇鍣ㄧ殑鎸囬拡锛涘惁鍒欒繑鍥 nullptr銆 + */ +ConfigFileLoader *ConfigManager::CreateConfigFileLoader(const char *configFilePath, const char *name) { - ConfigFileLoader* cfgFileLoader = nullptr; + ConfigFileLoader *cfgFileLoader = nullptr; std::string cfgPath(configFilePath); std::string::size_type dotPos = cfgPath.find_last_of('.'); if (dotPos == std::string::npos) { - MOT_REPORT_ERROR(MOT_ERROR_INVALID_ARG, - "Load Configuration", + MOT_REPORT_ERROR( + MOT_ERROR_INVALID_ARG, "Load Configuration", "Unable to load configuration file. Format not specified and configuration file does not contain suffix: " "%s", cfgPath.c_str()); @@ -343,8 +551,8 @@ ConfigFileLoader* ConfigManager::CreateConfigFileLoader(const char* configFilePa if (suffix.compare("conf") == 0) { cfgFileLoader = new (std::nothrow) PropsConfigFileLoader(name, CFG_FILE_CONFIG_PRIORITY, configFilePath); } else { - MOT_REPORT_ERROR(MOT_ERROR_INVALID_ARG, - "Load Configuration", + MOT_REPORT_ERROR( + MOT_ERROR_INVALID_ARG, "Load Configuration", "Unable to load configuration file: Format not specified and cannot be inferred from file suffix: %s", suffix.c_str()); return nullptr; @@ -358,24 +566,36 @@ ConfigFileLoader* ConfigManager::CreateConfigFileLoader(const char* configFilePa return cfgFileLoader; } +/* + * 鍔熻兘锛氶噸鏂板姞杞介厤缃 + * + * 鍙傛暟鍒楄〃锛 + * ignoreErrors锛氭槸鍚﹀拷鐣ラ厤缃姞杞借繃绋嬩腑鐨勯敊璇紝榛樿涓 true + * + * 杩斿洖鍊硷細 + * 濡傛灉鎴愬姛閲嶆柊鍔犺浇閰嶇疆锛岃繑鍥 true锛涘鏋滃湪鍔犺浇杩囩▼涓嚭鐜伴敊璇笖涓嶅拷鐣ラ敊璇紝杩斿洖 false銆 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庨噸鏂板姞杞介厤缃傚畠棣栧厛娓呴櫎閰嶇疆鏍戯紝鐒跺悗寰幆閬嶅巻鎵鏈夐厤缃姞杞藉櫒锛屽皾璇曚粠姣忎釜鍔犺浇鍣ㄤ腑鍔犺浇閰嶇疆鏍戙 + * 濡傛灉鍔犺浇鎴愬姛锛屽皢璇ラ厤缃爲娣诲姞鍒板眰娆″寲閰嶇疆鏍戜腑銆傚鏋滃姞杞藉け璐ヤ笖涓嶅拷鐣ラ敊璇紝鍑芥暟灏嗚繑鍥 false銆 + * 鏈鍚庯紝鍑芥暟鏍规嵁閰嶇疆涓殑鏃ュ織绾у埆鎵撳嵃宸插姞杞界殑閰嶇疆銆 + */ bool ConfigManager::ReloadConfig(bool ignoreErrors /* = true */) { bool result = true; MOT_LOG_DEBUG("Reloading configuration"); m_layeredConfigTree.Clear(); for (uint32_t i = 0; i < m_configLoaderCount; ++i) { - ConfigLoader* configLoader = m_configLoaders[i]; - ConfigTree* configTree = configLoader->Load(); + ConfigLoader *configLoader = m_configLoaders[i]; + ConfigTree *configTree = configLoader->Load(); if (configTree != nullptr) { - MOT_LOG_DEBUG("Adding configuration tree %p with priority %u from configuration loader %s", - configTree, - configTree->GetPriority(), - configLoader->GetName()); + MOT_LOG_DEBUG("Adding configuration tree %p with priority %u from configuration loader %s", configTree, + configTree->GetPriority(), configLoader->GetName()); m_layeredConfigTree.AddConfigTree(configTree); } else { MOT_LOG_WARN("Failed to load configuration tree from configuration loader %s, configuration from this " "loader will be ignored. Please fix configuration and trigger reload.", - configLoader->GetName()); + configLoader->GetName()); if (!ignoreErrors) { result = false; } @@ -392,6 +612,13 @@ bool ConfigManager::ReloadConfig(bool ignoreErrors /* = true */) return result; } +/* + * 鍔熻兘锛氶氱煡閰嶇疆鏇存敼 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庨氱煡閰嶇疆鏇存敼锛屽畠閬嶅巻鎵鏈夐厤缃洿鏀圭洃鍚櫒骞惰皟鐢ㄥ畠浠殑 OnConfigChange 鍑芥暟銆 + * 杩欎釜鍑芥暟閫氬父鍦ㄩ厤缃彂鐢熸洿鏀规椂琚皟鐢紝浠ラ氱煡瀹冧滑閰嶇疆宸叉洿鏀癸紝鍙互鎵ц鐩稿叧鐨勬搷浣溿 + */ void ConfigManager::NotifyConfigChange() { MOT_LOG_INFO("Propagating configuration changes"); @@ -399,4 +626,5 @@ void ConfigManager::NotifyConfigChange() m_listeners[i]->OnConfigChange(); } } + } // namespace MOT diff --git a/src/gausskernel/storage/mot/core/infra/config/config_section.cpp b/src/gausskernel/storage/mot/core/infra/config/config_section.cpp index be4a3a2fc..307479f2c 100644 --- a/src/gausskernel/storage/mot/core/infra/config/config_section.cpp +++ b/src/gausskernel/storage/mot/core/infra/config/config_section.cpp @@ -31,28 +31,39 @@ ConfigSection::ConfigSection() : ConfigItem(ConfigItemClass::CONFIG_ITEM_SECTION ConfigSection::~ConfigSection() { - // delete all direct values + // 鍒犻櫎鎵鏈夌洿鎺ュ硷紙ConfigValue 瀵硅薄锛 ConfigValueMap::iterator vitr = m_valueMap.begin(); while (vitr != m_valueMap.end()) { - delete vitr->second; + delete vitr->second; // 閲婃斁 ConfigValue 瀵硅薄鐨勫唴瀛 ++vitr; } - // delete all direct arrays + // 鍒犻櫎鎵鏈夌洿鎺ユ暟缁勶紙ConfigArray 瀵硅薄锛 ConfigArrayMap::iterator aitr = m_arrayMap.begin(); while (aitr != m_arrayMap.end()) { - delete aitr->second; + delete aitr->second; // 閲婃斁 ConfigArray 瀵硅薄鐨勫唴瀛 ++aitr; } - // delete all sub-sections + // 鍒犻櫎鎵鏈夊瓙閰嶇疆閮ㄥ垎锛圕onfigSection 瀵硅薄锛 ConfigSectionMap::iterator sitr = m_sectionMap.begin(); while (sitr != m_sectionMap.end()) { - delete sitr->second; + delete sitr->second; // 閲婃斁 ConfigSection 瀵硅薄鐨勫唴瀛 ++sitr; } } - +/* + * 鍔熻兘锛氭墦鍗伴厤缃妭 + * + * 鍙傛暟鍒楄〃锛 + * logLevel锛氳鐢ㄤ簬鎵撳嵃鐨勬棩蹇楃骇鍒 + * fullPrint锛氭槸鍚﹁繘琛屽畬鏁存墦鍗帮紝榛樿涓 false + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庢墦鍗伴厤缃妭鍙婂叾鍖呭惈鐨勫笺佹暟缁勫拰瀛愯妭銆 + * 棣栧厛锛屽畠鎵撳嵃缂╄繘鐨勮妭鍚嶇О銆傚鏋 fullPrint 鍙傛暟涓 false锛屽畠灏嗗彧鎵撳嵃鑺傚悕绉帮紝鍚﹀垯杩樹細鎵撳嵃鑺傚悕绉扮殑鍦板潃銆 + * 鐒跺悗锛屽畠寰幆閬嶅巻閰嶇疆鑺備腑鐨勫笺佹暟缁勫拰瀛愯妭锛屽苟鍒嗗埆鎵撳嵃瀹冧滑銆 + */ void ConfigSection::Print(LogLevel logLevel, bool fullPrint) const { // print indented section name @@ -83,91 +94,165 @@ void ConfigSection::Print(LogLevel logLevel, bool fullPrint) const ++itr3; } } +/* + * 鍔熻兘锛氳幏鍙栧綋鍓嶉厤缃妭涓墍鏈夊瓙鑺傜殑鍚嶇О + * + * 鍙傛暟鍒楄〃锛 + * sectionNames锛氳緭鍑哄弬鏁帮紝鍖呭惈瀛愯妭鍚嶇О鐨勫瓧绗︿覆鍒楄〃 + * + * 杩斿洖鍊硷細 + * 濡傛灉鎴愬姛鑾峰彇瀛愯妭鍚嶇О锛岃繑鍥 true锛涘鏋滃湪鑾峰彇杩囩▼涓嚭鐜伴敊璇紝杩斿洖 false銆 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庤幏鍙栧綋鍓嶉厤缃妭涓墍鏈夊瓙鑺傜殑鍚嶇О锛屽苟灏嗗畠浠瓨鍌ㄥ湪 sectionNames 鍒楄〃涓 + * 濡傛灉鎴愬姛鑾峰彇鎵鏈夊瓙鑺傚悕绉帮紝鍑芥暟杩斿洖 true銆傚鏋滃湪娣诲姞瀛愯妭鍚嶇О鍒板垪琛ㄦ椂閬囧埌鍐呭瓨鍒嗛厤閿欒锛 + * 鍑芥暟灏嗘姤鍛婇敊璇苟杩斿洖 false銆 + */ -bool ConfigSection::GetConfigSectionNames(mot_string_list& sectionNames) const +bool ConfigSection::GetConfigSectionNames(mot_string_list §ionNames) const { - bool result = true; - ConfigSectionMap::const_iterator itr = m_sectionMap.begin(); - while (itr != m_sectionMap.end()) { - result = sectionNames.push_back(itr->first); - if (!result) { - MOT_REPORT_ERROR(MOT_ERROR_OOM, - "Load Configuration", - "Failed to get section names (%u retrieved up to failed point)", - sectionNames.size()); - break; + bool result = true; // 鍒濆鍖栬繑鍥炲间负 true + ConfigSectionMap::const_iterator itr = m_sectionMap.begin(); // 鑾峰彇瀛愯妭鐨勮凯浠e櫒锛屽苟鍒濆鍖栦负寮濮嬩綅缃 + + while (itr != m_sectionMap.end()) { // 閬嶅巻瀛愯妭鏄犲皠 + result = sectionNames.push_back(itr->first); // 灏嗗瓙鑺傚悕绉版坊鍔犲埌缁撴灉鍒楄〃涓 + if (!result) { // 濡傛灉娣诲姞澶辫触锛岃鏄庡唴瀛樹笉瓒 + MOT_REPORT_ERROR(MOT_ERROR_OOM, "Load Configuration", + "Failed to get section names (%u retrieved up to failed point)", + sectionNames.size()); // 鎶ュ憡鍐呭瓨鍒嗛厤澶辫触 + break; // 閫鍑哄惊鐜 } - ++itr; + ++itr; // 绉诲姩鍒颁笅涓涓瓙鑺 } - return result; + + return result; // 杩斿洖鏄惁鎴愬姛 } -bool ConfigSection::GetConfigValueNames(mot_string_list& valueNames) const +/* + * 鍔熻兘锛氳幏鍙栧綋鍓嶉厤缃妭涓墍鏈夊煎拰鏁扮粍鐨勫悕绉 + * + * 鍙傛暟鍒楄〃锛 + * valueNames锛氳緭鍑哄弬鏁帮紝鍖呭惈鍊煎拰鏁扮粍鍚嶇О鐨勫瓧绗︿覆鍒楄〃 + * + * 杩斿洖鍊硷細 + * 濡傛灉鎴愬姛鑾峰彇鍊煎拰鏁扮粍鍚嶇О锛岃繑鍥 true锛涘鏋滃湪鑾峰彇杩囩▼涓嚭鐜伴敊璇紝杩斿洖 false銆 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庤幏鍙栧綋鍓嶉厤缃妭涓墍鏈夊煎拰鏁扮粍鐨勫悕绉帮紝骞跺皢瀹冧滑瀛樺偍鍦 valueNames 鍒楄〃涓 + * 濡傛灉鎴愬姛鑾峰彇鎵鏈夊悕绉帮紝鍑芥暟杩斿洖 true銆傚鏋滃湪娣诲姞鍚嶇О鍒板垪琛ㄦ椂閬囧埌鍐呭瓨鍒嗛厤閿欒锛 + * 鍑芥暟灏嗘姤鍛婇敊璇苟杩斿洖 false銆 + */ +bool ConfigSection::GetConfigValueNames(mot_string_list &valueNames) const { bool result = true; + + // 閬嶅巻鍊肩殑鏄犲皠骞舵坊鍔犲悕绉板埌鍒楄〃 ConfigValueMap::const_iterator itr = m_valueMap.begin(); while (itr != m_valueMap.end()) { if (!valueNames.push_back(itr->first)) { - MOT_REPORT_ERROR(MOT_ERROR_OOM, - "Load Configuration", - "Failed to get value names (%u retrieved up to failed point)", - valueNames.size()); + MOT_REPORT_ERROR(MOT_ERROR_OOM, "Load Configuration", + "Failed to get value names (%u retrieved up to failed point)", valueNames.size()); return false; } ++itr; } + + // 閬嶅巻鏁扮粍鐨勬槧灏勫苟娣诲姞鍚嶇О鍒板垪琛 ConfigArrayMap::const_iterator itr2 = m_arrayMap.begin(); while (itr2 != m_arrayMap.end()) { if (!valueNames.push_back(itr2->first)) { - MOT_REPORT_ERROR(MOT_ERROR_OOM, - "Load Configuration", - "Failed to get value names (%u retrieved up to failed point)", - valueNames.size()); + MOT_REPORT_ERROR(MOT_ERROR_OOM, "Load Configuration", + "Failed to get value names (%u retrieved up to failed point)", valueNames.size()); return false; } ++itr2; } + return true; } - -bool ConfigSection::AddConfigItem(ConfigItem* configItem, bool replaceIfExists /* = false */) +/* + * 鍔熻兘锛氬悜褰撳墠閰嶇疆鑺傛坊鍔犻厤缃」 + * + * 鍙傛暟鍒楄〃锛 + * configItem锛氳娣诲姞鐨勯厤缃」 + * replaceIfExists锛氬鏋滀负 true锛屽垯濡傛灉宸插瓨鍦ㄥ悓鍚嶇殑閰嶇疆椤癸紝灏嗘浛鎹㈠畠锛涘鏋滀负 false锛屽垯涓嶆浛鎹紝榛樿涓 false銆 + * + * 杩斿洖鍊硷細 + * 濡傛灉鎴愬姛娣诲姞閰嶇疆椤癸紝杩斿洖 true锛涘鏋滃湪娣诲姞杩囩▼涓嚭鐜伴敊璇垨閰嶇疆椤圭被鍒棤鏁堬紝杩斿洖 false銆 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庡悜褰撳墠閰嶇疆鑺傛坊鍔犻厤缃」锛屽彲浠ユ槸閰嶇疆鑺傘侀厤缃兼垨閰嶇疆鏁扮粍銆 + * 鏍规嵁閰嶇疆椤圭殑绫诲埆锛屽嚱鏁颁細鍒嗘淳缁欎笉鍚岀殑娣诲姞鍑芥暟鏉ュ鐞嗐 + * 濡傛灉 replaceIfExists 涓 true锛屽鏋滃凡瀛樺湪鍚屽悕鐨勯厤缃」锛屽皢鏇挎崲瀹冿紱 + * 濡傛灉涓 false锛屽鏋滃悓鍚嶉厤缃」宸插瓨鍦紝鍑芥暟灏嗚繑鍥 false銆 + */ +bool ConfigSection::AddConfigItem(ConfigItem *configItem, bool replaceIfExists /* = false */) { bool result = false; + // 鏍规嵁閰嶇疆椤圭殑绫诲埆鍒嗘淳鍒颁笉鍚岀殑娣诲姞鍑芥暟 switch (configItem->GetClass()) { case ConfigItemClass::CONFIG_ITEM_SECTION: - result = AddConfigSection(static_cast(configItem)); + result = AddConfigSection(static_cast(configItem)); break; case ConfigItemClass::CONFIG_ITEM_VALUE: - result = AddConfigValue(static_cast(configItem), replaceIfExists); + result = AddConfigValue(static_cast(configItem), replaceIfExists); break; case ConfigItemClass::CONFIG_ITEM_ARRAY: - result = AddConfigArray(static_cast(configItem)); + result = AddConfigArray(static_cast(configItem)); break; default: - MOT_REPORT_ERROR(MOT_ERROR_INTERNAL, - "Load Configuration", - "Invalid configuration item class %d", - (int)configItem->GetClass()); + MOT_REPORT_ERROR(MOT_ERROR_INTERNAL, "Load Configuration", "Invalid configuration item class %d", + (int)configItem->GetClass()); break; } return result; } -bool ConfigSection::Merge(ConfigSection* configSection) +/* + * 鍔熻兘锛氬悎骞堕厤缃妭 + * + * 鍙傛暟鍒楄〃锛 + * configSection锛氳鍚堝苟鐨勯厤缃妭 + * + * 杩斿洖鍊硷細 + * 濡傛灉鎴愬姛鍚堝苟閰嶇疆鑺備腑鐨勯厤缃」锛岃繑鍥 true锛涘惁鍒欒繑鍥 false銆 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庡悎骞朵袱涓厤缃妭鐨勯厤缃」锛屽寘鎷厤缃煎拰閰嶇疆鏁扮粍銆 + * 瀹冮鍏堝皾璇曞悎骞堕厤缃硷紝鐒跺悗鍚堝苟閰嶇疆鏁扮粍銆 + */ +bool ConfigSection::Merge(ConfigSection *configSection) { + // 璋冪敤鍚堝苟閰嶇疆鍊煎拰閰嶇疆鏁扮粍鐨勫嚱鏁帮紝涓よ呴兘鎴愬姛鎵嶈繑鍥 true return MergeValues(configSection) && MergeArrays(configSection); } -const ConfigItem* ConfigSection::GetConfigItem(const char* name) const +/* + * 鍔熻兘锛氳幏鍙栨寚瀹氬悕绉扮殑閰嶇疆椤 + * + * 鍙傛暟鍒楄〃锛 + * name锛氳鑾峰彇鐨勯厤缃」鐨勫悕绉 + * + * 杩斿洖鍊硷細 + * 杩斿洖鎸囧悜鍖归厤鍚嶇О鐨勯厤缃」鐨勬寚閽堬紝濡傛灉娌℃湁鎵惧埌鍖归厤椤瑰垯杩斿洖 nullptr銆 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庝粠閰嶇疆鑺備腑妫绱㈠叿鏈夋寚瀹氬悕绉扮殑閰嶇疆椤广 + * 瀹冮鍏堝湪瀛愯妭涓煡鎵撅紝鐒跺悗鍦ㄩ厤缃煎拰閰嶇疆鏁扮粍涓煡鎵惧尮閰嶉」銆 + */ +const ConfigItem *ConfigSection::GetConfigItem(const char *name) const { - const ConfigItem* result = nullptr; + const ConfigItem *result = nullptr; + + // 棣栧厛鍦ㄥ瓙鑺備腑鏌ユ壘 ConfigSectionMap::const_iterator itr = m_sectionMap.find(name); if (itr != m_sectionMap.end()) { result = itr->second; } else { + // 濡傛灉鍦ㄥ瓙鑺備腑娌℃湁鎵惧埌鍖归厤椤癸紝鍐嶅湪閰嶇疆鍊煎拰閰嶇疆鏁扮粍涓煡鎵 ConfigValueMap::const_iterator itr2 = m_valueMap.find(name); if (itr2 != m_valueMap.end()) { result = itr2->second; @@ -178,33 +263,80 @@ const ConfigItem* ConfigSection::GetConfigItem(const char* name) const } } } + return result; } -const ConfigSection* ConfigSection::GetConfigSection(const char* name) const +/* + * 鍔熻兘锛氳幏鍙栨寚瀹氬悕绉扮殑閰嶇疆鑺 + * + * 鍙傛暟鍒楄〃锛 + * name锛氳鑾峰彇鐨勯厤缃妭鐨勫悕绉 + * + * 杩斿洖鍊硷細 + * 杩斿洖鎸囧悜鍖归厤鍚嶇О鐨勯厤缃妭鐨勬寚閽堬紝濡傛灉娌℃湁鎵惧埌鍖归厤椤瑰垯杩斿洖 nullptr銆 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庝粠閰嶇疆鑺備腑妫绱㈠叿鏈夋寚瀹氬悕绉扮殑瀛愰厤缃妭銆 + * 瀹冨湪褰撳墠閰嶇疆鑺傜殑瀛愯妭鏄犲皠涓煡鎵惧尮閰嶉」锛屽鏋滄壘鍒板垯杩斿洖鐩稿簲鐨勬寚閽堬紝鍚﹀垯杩斿洖 nullptr銆 + */ +const ConfigSection *ConfigSection::GetConfigSection(const char *name) const { - const ConfigSection* result = nullptr; + const ConfigSection *result = nullptr; + + // 鍦ㄥ瓙鑺傛槧灏勪腑鏌ユ壘鍖归厤椤 ConfigSectionMap::const_iterator itr = m_sectionMap.find(name); if (itr != m_sectionMap.end()) { result = itr->second; } + return result; } -const ConfigArray* ConfigSection::GetConfigArray(const char* name) const +/* + * 鍔熻兘锛氳幏鍙栨寚瀹氬悕绉扮殑閰嶇疆鏁扮粍 + * + * 鍙傛暟鍒楄〃锛 + * name锛氳鑾峰彇鐨勯厤缃暟缁勭殑鍚嶇О + * + * 杩斿洖鍊硷細 + * 杩斿洖鎸囧悜鍖归厤鍚嶇О鐨勯厤缃暟缁勭殑鎸囬拡锛屽鏋滄病鏈夋壘鍒板尮閰嶉」鍒欒繑鍥 nullptr銆 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庝粠閰嶇疆鑺備腑妫绱㈠叿鏈夋寚瀹氬悕绉扮殑瀛愰厤缃暟缁勩 + * 瀹冨湪褰撳墠閰嶇疆鑺傜殑瀛愭暟缁勬槧灏勪腑鏌ユ壘鍖归厤椤癸紝濡傛灉鎵惧埌鍒欒繑鍥炵浉搴旂殑鎸囬拡锛屽惁鍒欒繑鍥 nullptr銆 + */ +const ConfigArray *ConfigSection::GetConfigArray(const char *name) const { - const ConfigArray* result = nullptr; + const ConfigArray *result = nullptr; + + // 鍦ㄥ瓙鏁扮粍鏄犲皠涓煡鎵惧尮閰嶉」 ConfigArrayMap::const_iterator itr = m_arrayMap.find(name); if (itr != m_arrayMap.end()) { result = itr->second; } + return result; } -ConfigItem* ConfigSection::ModifyConfigItem(const char* name) +/* + * 鍔熻兘锛氫慨鏀规寚瀹氬悕绉扮殑閰嶇疆椤 + * + * 鍙傛暟鍒楄〃锛 + * name锛氳淇敼鐨勯厤缃」鐨勫悕绉 + * + * 杩斿洖鍊硷細 + * 杩斿洖鎸囧悜鍖归厤鍚嶇О鐨勯厤缃」鐨勬寚閽堬紝濡傛灉娌℃湁鎵惧埌鍖归厤椤瑰垯杩斿洖 nullptr銆 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庝慨鏀归厤缃妭涓叿鏈夋寚瀹氬悕绉扮殑瀛愰厤缃」銆 + * 瀹冨湪褰撳墠閰嶇疆鑺傜殑瀛愰厤缃」鏄犲皠涓煡鎵惧尮閰嶉」锛屽鏋滄壘鍒板垯杩斿洖鐩稿簲鐨勬寚閽堬紝鍚﹀垯杩斿洖 nullptr銆 + */ +ConfigItem *ConfigSection::ModifyConfigItem(const char *name) { - ConfigItem* result = nullptr; + ConfigItem *result = nullptr; + // 鍦ㄥ瓙閰嶇疆椤规槧灏勪腑鏌ユ壘鍖归厤椤 ConfigSectionMap::iterator itr = m_sectionMap.find(name); if (itr != m_sectionMap.end()) { result = itr->second; @@ -223,166 +355,311 @@ ConfigItem* ConfigSection::ModifyConfigItem(const char* name) return result; } -ConfigSection* ConfigSection::ModifyConfigSection(const char* name) +/* + * 鍔熻兘锛氫慨鏀规寚瀹氬悕绉扮殑閰嶇疆鑺 + * + * 鍙傛暟鍒楄〃锛 + * name锛氳淇敼鐨勯厤缃妭鐨勫悕绉 + * + * 杩斿洖鍊硷細 + * 杩斿洖鎸囧悜鍖归厤鍚嶇О鐨勯厤缃妭鐨勬寚閽堬紝濡傛灉娌℃湁鎵惧埌鍖归厤椤瑰垯杩斿洖 nullptr銆 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庝慨鏀瑰綋鍓嶉厤缃妭涓叿鏈夋寚瀹氬悕绉扮殑瀛愰厤缃妭銆 + * 瀹冨湪褰撳墠閰嶇疆鑺傜殑瀛愰厤缃妭鏄犲皠涓煡鎵惧尮閰嶉」锛屽鏋滄壘鍒板垯杩斿洖鐩稿簲鐨勬寚閽堬紝鍚﹀垯杩斿洖 nullptr銆 + */ +ConfigSection *ConfigSection::ModifyConfigSection(const char *name) { - ConfigSection* result = nullptr; + ConfigSection *result = nullptr; + + // 鍦ㄥ瓙閰嶇疆鑺傛槧灏勪腑鏌ユ壘鍖归厤椤 ConfigSectionMap::iterator itr = m_sectionMap.find(name); if (itr != m_sectionMap.end()) { result = itr->second; } + return result; } -ConfigArray* ConfigSection::ModifyConfigArray(const char* name) +/* + * 鍔熻兘锛氫慨鏀规寚瀹氬悕绉扮殑閰嶇疆鏁扮粍 + * + * 鍙傛暟鍒楄〃锛 + * name锛氳淇敼鐨勯厤缃暟缁勭殑鍚嶇О + * + * 杩斿洖鍊硷細 + * 杩斿洖鎸囧悜鍖归厤鍚嶇О鐨勯厤缃暟缁勭殑鎸囬拡锛屽鏋滄病鏈夋壘鍒板尮閰嶉」鍒欒繑鍥 nullptr銆 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庝慨鏀瑰綋鍓嶉厤缃妭涓叿鏈夋寚瀹氬悕绉扮殑瀛愰厤缃暟缁勩 + * 瀹冨湪褰撳墠閰嶇疆鑺傜殑瀛愰厤缃暟缁勬槧灏勪腑鏌ユ壘鍖归厤椤癸紝濡傛灉鎵惧埌鍒欒繑鍥炵浉搴旂殑鎸囬拡锛屽惁鍒欒繑鍥 nullptr銆 + */ +ConfigArray *ConfigSection::ModifyConfigArray(const char *name) { - ConfigArray* result = nullptr; + ConfigArray *result = nullptr; + + // 鍦ㄥ瓙閰嶇疆鏁扮粍鏄犲皠涓煡鎵惧尮閰嶉」 ConfigArrayMap::iterator itr = m_arrayMap.find(name); if (itr != m_arrayMap.end()) { result = itr->second; } + return result; } -void ConfigSection::ForEach(ConfigItemVisitor& visitor) const +/* + * 鍔熻兘锛氬褰撳墠閰嶇疆鑺傚強鍏舵墍鏈夊瓙椤瑰簲鐢ㄨ闂呭璞$殑鎿嶄綔 + * + * 鍙傛暟鍒楄〃锛 + * visitor锛氱敤浜庤闂厤缃」鐨勮闂呭璞 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庨掑綊鍦伴亶鍘嗗綋鍓嶉厤缃妭鍙婂叾鎵鏈夊瓙椤癸紝骞跺姣忎釜閰嶇疆椤瑰簲鐢ㄨ闂呭璞$殑鎿嶄綔銆 + * 璁块棶鑰呭璞″繀椤诲疄鐜 `OnConfigItem` 鏂规硶浠ュ鐞嗛厤缃」銆 + * 瀵规瘡涓笺佹暟缁勫拰瀛愰厤缃妭锛屾鍑芥暟杩樹細鍒嗗埆璋冪敤閫傚綋鐨 `ForEachValue`銆乣ForEachArray` 鍜 `ForEachSection` 鏂规硶銆 + */ +void ConfigSection::ForEach(ConfigItemVisitor &visitor) const { + // 瀵瑰綋鍓嶉厤缃妭搴旂敤璁块棶鑰呭璞$殑鎿嶄綔 visitor.OnConfigItem(this); + + // 瀵瑰綋鍓嶉厤缃妭鐨勫煎簲鐢ㄨ闂呭璞$殑鎿嶄綔 ForEachValue(visitor); + + // 瀵瑰綋鍓嶉厤缃妭鐨勬暟缁勫簲鐢ㄨ闂呭璞$殑鎿嶄綔 ForEachArray(visitor); + + // 瀵瑰綋鍓嶉厤缃妭鐨勫瓙閰嶇疆鑺傚簲鐢ㄨ闂呭璞$殑鎿嶄綔 ForEachSection(visitor); } -bool ConfigSection::AddConfigSection(ConfigSection* configSection) +/* + * 鍔熻兘锛氬悜褰撳墠閰嶇疆鑺傛坊鍔犲瓙閰嶇疆鑺 + * + * 鍙傛暟鍒楄〃锛 + * configSection锛氳娣诲姞鐨勫瓙閰嶇疆鑺傚璞 + * + * 杩斿洖鍊硷細 + * 濡傛灉鎴愬姛娣诲姞瀛愰厤缃妭锛岃繑鍥 true锛涘鏋滃瓙閰嶇疆鑺傚凡瀛樺湪鎴栬揪鍒拌祫婧愰檺鍒讹紝杩斿洖 false銆 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庡悜褰撳墠閰嶇疆鑺傛坊鍔犲瓙閰嶇疆鑺傘傚鏋滄垚鍔熸坊鍔狅紝灏嗚繑鍥 true锛涘鏋滃瓙閰嶇疆鑺傚凡瀛樺湪锛屽皢璁板綍閿欒骞惰繑鍥 false銆 + * 濡傛灉杈惧埌浜嗚祫婧愰檺鍒讹紝涔熶細璁板綍閿欒骞惰繑鍥 false銆 + */ +bool ConfigSection::AddConfigSection(ConfigSection *configSection) { + // 灏濊瘯灏嗗瓙閰嶇疆鑺傛坊鍔犲埌褰撳墠閰嶇疆鑺傜殑鏄犲皠涓 ConfigSectionMap::pairis pairis = m_sectionMap.insert(ConfigSectionMap::value_type(configSection->GetName(), configSection)); + + // 澶勭悊鎻掑叆缁撴灉 if (pairis.second == INSERT_EXISTS) { - MOT_REPORT_ERROR(MOT_ERROR_INTERNAL, - "Load Configuration", - "Cannot add configuration section %s to section %s: section already exists", - configSection->GetName(), - GetName()); + // 濡傛灉瀛愰厤缃妭宸茬粡瀛樺湪锛岃褰曢敊璇 + MOT_REPORT_ERROR(MOT_ERROR_INTERNAL, "Load Configuration", + "Cannot add configuration section %s to section %s: section already exists", + configSection->GetName(), GetName()); } else if (pairis.second == INSERT_FAILED) { - MOT_REPORT_ERROR(MOT_ERROR_INTERNAL, - "Load Configuration", - "Failed to add configuration section %s to section %s: reached resource limit", - configSection->GetName(), - GetName()); + // 濡傛灉鎻掑叆澶辫触锛岃褰曢敊璇苟琛ㄧず宸茶揪鍒拌祫婧愰檺鍒 + MOT_REPORT_ERROR(MOT_ERROR_INTERNAL, "Load Configuration", + "Failed to add configuration section %s to section %s: reached resource limit", + configSection->GetName(), GetName()); } + + // 杩斿洖鏄惁鎴愬姛娣诲姞瀛愰厤缃妭 return (pairis.second == INSERT_SUCCESS); } -bool ConfigSection::AddConfigValue(ConfigValue* configValue, bool replaceIfExists) +/* + * 鍔熻兘锛氬悜褰撳墠閰嶇疆鑺傛坊鍔犻厤缃 + * + * 鍙傛暟鍒楄〃锛 + * configValue锛氳娣诲姞鐨勯厤缃煎璞 + * replaceIfExists锛氬鏋滈厤缃煎凡缁忓瓨鍦紝鏄惁鏇挎崲瀹冿紙榛樿涓 false锛 + * + * 杩斿洖鍊硷細 + * 濡傛灉鎴愬姛娣诲姞閰嶇疆鍊硷紝杩斿洖 true锛涘鏋滈厤缃煎凡瀛樺湪浣嗘湭鏇挎崲锛屾垨鑰呰揪鍒拌祫婧愰檺鍒讹紝杩斿洖 false銆 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庡悜褰撳墠閰嶇疆鑺傛坊鍔犻厤缃笺傚鏋滄垚鍔熸坊鍔狅紝灏嗚繑鍥 true锛涘鏋滈厤缃煎凡瀛樺湪浣嗘湭鏇挎崲涓 `replaceIfExists` + * 鍙傛暟涓 false锛屽皢璁板綍閿欒骞惰繑鍥 false銆傚鏋滆揪鍒颁簡璧勬簮闄愬埗锛屼篃浼氳褰曢敊璇苟杩斿洖 false銆 + * 濡傛灉 `replaceIfExists` 鍙傛暟涓 true锛屽垯浼氭浛鎹㈠凡瀛樺湪鐨勯厤缃笺 + */ +bool ConfigSection::AddConfigValue(ConfigValue *configValue, bool replaceIfExists) { + // 灏濊瘯灏嗛厤缃兼坊鍔犲埌褰撳墠閰嶇疆鑺傜殑鏄犲皠涓 ConfigValueMap::pairis pairis = m_valueMap.insert(ConfigValueMap::value_type(configValue->GetName(), configValue)); + + // 澶勭悊鎻掑叆缁撴灉 if (pairis.second == INSERT_EXISTS) { if (replaceIfExists) { - ConfigValue* prevValue = pairis.first->second; + // 濡傛灉閰嶇疆鍊煎凡缁忓瓨鍦紝骞朵笖鍏佽鏇挎崲锛屽垯鏇挎崲瀹 + ConfigValue *prevValue = pairis.first->second; pairis.first->second = configValue; delete prevValue; pairis.second = INSERT_SUCCESS; } else { - MOT_REPORT_ERROR(MOT_ERROR_INTERNAL, - "Load Configuration", - "Cannot add configuration value %s to section %s: value already exists", - configValue->GetName(), - GetName()); + // 濡傛灉閰嶇疆鍊煎凡缁忓瓨鍦ㄤ絾涓嶆浛鎹紝璁板綍閿欒 + MOT_REPORT_ERROR(MOT_ERROR_INTERNAL, "Load Configuration", + "Cannot add configuration value %s to section %s: value already exists", + configValue->GetName(), GetName()); } } else if (pairis.second == INSERT_FAILED) { - MOT_REPORT_ERROR(MOT_ERROR_INTERNAL, - "Load Configuration", - "Failed to add configuration value %s to section %s: reached resource limit", - configValue->GetName(), - GetName()); + // 濡傛灉鎻掑叆澶辫触锛岃褰曢敊璇苟琛ㄧず宸茶揪鍒拌祫婧愰檺鍒 + MOT_REPORT_ERROR(MOT_ERROR_INTERNAL, "Load Configuration", + "Failed to add configuration value %s to section %s: reached resource limit", + configValue->GetName(), GetName()); } + + // 杩斿洖鏄惁鎴愬姛娣诲姞閰嶇疆鍊 return (pairis.second == INSERT_SUCCESS); } -bool ConfigSection::AddConfigArray(ConfigArray* configArray) +/* + * 鍔熻兘锛氬悜褰撳墠閰嶇疆鑺傛坊鍔犻厤缃暟缁 + * + * 鍙傛暟鍒楄〃锛 + * configArray锛氳娣诲姞鐨勯厤缃暟缁勫璞 + * + * 杩斿洖鍊硷細 + * 濡傛灉鎴愬姛娣诲姞閰嶇疆鏁扮粍锛岃繑鍥 true锛涘鏋滈厤缃暟缁勫凡缁忓瓨鍦ㄦ垨鑰呰揪鍒拌祫婧愰檺鍒讹紝杩斿洖 false銆 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庡悜褰撳墠閰嶇疆鑺傛坊鍔犻厤缃暟缁勩傚鏋滄垚鍔熸坊鍔狅紝灏嗚繑鍥 true锛涘鏋滈厤缃暟缁勫凡缁忓瓨鍦紝灏嗚褰曢敊璇苟杩斿洖 false銆 + * 濡傛灉杈惧埌浜嗚祫婧愰檺鍒讹紝涔熶細璁板綍閿欒骞惰繑鍥 false銆 + */ +bool ConfigSection::AddConfigArray(ConfigArray *configArray) { + // 灏濊瘯灏嗛厤缃暟缁勬坊鍔犲埌褰撳墠閰嶇疆鑺傜殑鏄犲皠涓 ConfigArrayMap::pairis pairis = m_arrayMap.insert(ConfigArrayMap::value_type(configArray->GetName(), configArray)); + + // 澶勭悊鎻掑叆缁撴灉 if (pairis.second == INSERT_EXISTS) { - MOT_REPORT_ERROR(MOT_ERROR_INTERNAL, - "Load Configuration", - "Cannot add configuration array %s to section %s: array already exists", - configArray->GetName(), - GetName()); + // 濡傛灉閰嶇疆鏁扮粍宸茬粡瀛樺湪锛岃褰曢敊璇 + MOT_REPORT_ERROR(MOT_ERROR_INTERNAL, "Load Configuration", + "Cannot add configuration array %s to section %s: array already exists", + configArray->GetName(), GetName()); } else if (pairis.second == INSERT_FAILED) { - MOT_REPORT_ERROR(MOT_ERROR_INTERNAL, - "Load Configuration", - "Failed to add configuration array %s to section %s: reached resource limit", - configArray->GetName(), - GetName()); + // 濡傛灉鎻掑叆澶辫触锛岃褰曢敊璇苟琛ㄧず宸茶揪鍒拌祫婧愰檺鍒 + MOT_REPORT_ERROR(MOT_ERROR_INTERNAL, "Load Configuration", + "Failed to add configuration array %s to section %s: reached resource limit", + configArray->GetName(), GetName()); } + + // 杩斿洖鏄惁鎴愬姛娣诲姞閰嶇疆鏁扮粍 return (pairis.second == INSERT_SUCCESS); } -void ConfigSection::ForEachValue(ConfigItemVisitor& visitor) const +/* + * 鍔熻兘锛氶亶鍘嗗綋鍓嶉厤缃妭涓殑閰嶇疆鍊煎苟瀵瑰叾搴旂敤璁块棶鑰 + * + * 鍙傛暟鍒楄〃锛 + * visitor锛氫竴涓厤缃」璁块棶鑰呭璞★紝鐢ㄤ簬瀵归厤缃煎簲鐢ㄨ闂呮搷浣 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庨亶鍘嗗綋鍓嶉厤缃妭涓殑閰嶇疆鍊硷紝骞跺姣忎釜閰嶇疆鍊煎簲鐢ㄩ厤缃」璁块棶鑰呭璞′腑瀹氫箟鐨勬搷浣溿 + */ +void ConfigSection::ForEachValue(ConfigItemVisitor &visitor) const { + // 閬嶅巻閰嶇疆鍊兼槧灏 ConfigValueMap::const_iterator itr = m_valueMap.begin(); while (itr != m_valueMap.end()) { + // 瀵规瘡涓厤缃煎簲鐢ㄨ闂呮搷浣 visitor.OnConfigItem(itr->second); ++itr; } } -void ConfigSection::ForEachArray(ConfigItemVisitor& visitor) const +/* + * 鍔熻兘锛氶亶鍘嗗綋鍓嶉厤缃妭涓殑閰嶇疆鏁扮粍骞跺鍏跺簲鐢ㄨ闂 + * + * 鍙傛暟鍒楄〃锛 + * visitor锛氫竴涓厤缃」璁块棶鑰呭璞★紝鐢ㄤ簬瀵归厤缃暟缁勫簲鐢ㄨ闂呮搷浣 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庨亶鍘嗗綋鍓嶉厤缃妭涓殑閰嶇疆鏁扮粍锛屽苟瀵规瘡涓厤缃暟缁勫簲鐢ㄩ厤缃」璁块棶鑰呭璞′腑瀹氫箟鐨勬搷浣溿 + */ +void ConfigSection::ForEachArray(ConfigItemVisitor &visitor) const { + // 閬嶅巻閰嶇疆鏁扮粍鏄犲皠 ConfigArrayMap::const_iterator itr = m_arrayMap.begin(); while (itr != m_arrayMap.end()) { - static_cast(itr->second)->ForEach(visitor); + // 瀵规瘡涓厤缃暟缁勫簲鐢ㄨ闂呮搷浣 + static_cast(itr->second)->ForEach(visitor); ++itr; } } -void ConfigSection::ForEachSection(ConfigItemVisitor& visitor) const +/* + * 鍔熻兘锛氶亶鍘嗗綋鍓嶉厤缃妭涓殑瀛愰厤缃妭骞跺鍏跺簲鐢ㄨ闂 + * + * 鍙傛暟鍒楄〃锛 + * visitor锛氫竴涓厤缃」璁块棶鑰呭璞★紝鐢ㄤ簬瀵瑰瓙閰嶇疆鑺傚簲鐢ㄨ闂呮搷浣 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庨亶鍘嗗綋鍓嶉厤缃妭涓殑瀛愰厤缃妭锛屽苟瀵规瘡涓瓙閰嶇疆鑺傚簲鐢ㄩ厤缃」璁块棶鑰呭璞′腑瀹氫箟鐨勬搷浣溿 + */ +void ConfigSection::ForEachSection(ConfigItemVisitor &visitor) const { + // 閬嶅巻瀛愰厤缃妭鏄犲皠 ConfigSectionMap::const_iterator itr = m_sectionMap.begin(); while (itr != m_sectionMap.end()) { - static_cast(itr->second)->ForEach(visitor); + // 瀵规瘡涓瓙閰嶇疆鑺傚簲鐢ㄨ闂呮搷浣 + static_cast(itr->second)->ForEach(visitor); ++itr; } } -bool ConfigSection::MergeValues(ConfigSection* configSection) +/* + * 鍔熻兘锛氬皢鍙︿竴涓厤缃妭鐨勫煎悎骞跺埌褰撳墠閰嶇疆鑺備腑 + * + * 鍙傛暟鍒楄〃锛 + * configSection锛氬寘鍚鍚堝苟鐨勫肩殑鍙︿竴涓厤缃妭 + * + * 杩斿洖鍊硷細 + * 濡傛灉鎴愬姛鍚堝苟鍊硷紝杩斿洖 true锛涘惁鍒欒繑鍥 false銆 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庡皢鍙︿竴涓厤缃妭鐨勫煎悎骞跺埌褰撳墠閰嶇疆鑺備腑銆傚鏋滃悎骞剁殑鍊兼垚鍔燂紝灏嗚繑鍥 true锛涘惁鍒欙紝灏嗚繑鍥 false銆 + * 濡傛灉鍙戠敓閿欒锛屽嚱鏁颁細灏濊瘯鎶ュ憡閿欒骞跺洖婊氭搷浣溿 + */ +bool ConfigSection::MergeValues(ConfigSection *configSection) { + // 閬嶅巻瑕佸悎骞剁殑閰嶇疆鑺備腑鐨勫兼槧灏 ConfigValueMap::iterator itr = configSection->m_valueMap.begin(); while (itr != configSection->m_valueMap.end()) { - ConfigValue* configValue = itr->second; + ConfigValue *configValue = itr->second; + // 灏嗗兼彃鍏ュ埌褰撳墠閰嶇疆鑺傜殑鍊兼槧灏勪腑 ConfigValueMap::pairis pairis = m_valueMap.insert(ConfigValueMap::value_type(configValue->GetName(), configValue)); if (pairis.second == INSERT_SUCCESS) { MOT_LOG_DEBUG("Inserted new value: %s", configValue->GetName()); } else { if (MOT_IS_SEVERE()) { - MOT_REPORT_ERROR(MOT_ERROR_INTERNAL, - "Load Configuration", - "Failed to merge value %s into section %s", - configValue->GetName(), - GetFullPathName()); + // 鎶ュ憡鍚堝苟鍊煎け璐ョ殑涓ラ噸閿欒 + MOT_REPORT_ERROR(MOT_ERROR_INTERNAL, "Load Configuration", "Failed to merge value %s into section %s", + configValue->GetName(), GetFullPathName()); return false; } - // not inserted, so replace existing value - ConfigValueMap::iterator& itr2 = pairis.first; - ConfigValue* oldConfigValue = itr2->second; + // 鏈彃鍏ワ紝鍥犳鏇挎崲鐜版湁鍊 + ConfigValueMap::iterator &itr2 = pairis.first; + ConfigValue *oldConfigValue = itr2->second; MOT_LOG_DEBUG(" *** --> Deleting merged section value %s", oldConfigValue->GetFullPathName()); oldConfigValue->Print(LogLevel::LL_DEBUG, true); - m_valueMap.erase(itr2); + m_valueMap.erase(itr2); // 鍒犻櫎鏃у MOT_LOG_DEBUG(" *** --> Delete merged section value done"); - delete oldConfigValue; + delete oldConfigValue; // 鍒犻櫎鏃у肩殑鍐呭瓨 if (!m_valueMap.insert(ConfigValueMap::value_type(configValue->GetName(), configValue)).second) { if (MOT_IS_SEVERE()) { - MOT_REPORT_ERROR(MOT_ERROR_INTERNAL, - "Load Configuration", - "Failed to merge value %s into section %s (severe error)", - configValue->GetName(), - GetFullPathName()); + // 鎶ュ憡鍚堝苟鍊煎け璐ョ殑涓ラ噸閿欒 + MOT_REPORT_ERROR(MOT_ERROR_INTERNAL, "Load Configuration", + "Failed to merge value %s into section %s (severe error)", configValue->GetName(), + GetFullPathName()); return false; } - MOT_REPORT_ERROR(MOT_ERROR_INTERNAL, - "Load Configuration", - "Failed to merge value %s into section %s (unexpected duplicate)", - configValue->GetName(), - GetFullPathName()); + // 鎶ュ憡鍚堝苟鍊煎け璐ョ殑閿欒锛岃繖鏄竴涓笉搴旇鍙戠敓鐨勬剰澶栨儏鍐 + MOT_REPORT_ERROR(MOT_ERROR_INTERNAL, "Load Configuration", + "Failed to merge value %s into section %s (unexpected duplicate)", + configValue->GetName(), GetFullPathName()); MOT_ASSERT(false); return false; } else { @@ -392,51 +669,63 @@ bool ConfigSection::MergeValues(ConfigSection* configSection) } ++itr; } - configSection->m_valueMap.clear(); // required to make sure items are not deleted in destructor + configSection->m_valueMap.clear(); // 娓呯┖瑕佸悎骞剁殑閰嶇疆鑺備腑鐨勫兼槧灏勶紝纭繚涓嶄細鍦ㄦ瀽鏋勫嚱鏁颁腑鍒犻櫎杩欎簺椤 return true; } -bool ConfigSection::MergeArrays(ConfigSection* configSection) +/* + * 鍔熻兘锛氬皢鍙︿竴涓厤缃妭鐨勬暟缁勫悎骞跺埌褰撳墠閰嶇疆鑺備腑 + * + * 鍙傛暟鍒楄〃锛 + * configSection锛氬寘鍚鍚堝苟鐨勬暟缁勭殑鍙︿竴涓厤缃妭 + * + * 杩斿洖鍊硷細 + * 濡傛灉鎴愬姛鍚堝苟鏁扮粍锛岃繑鍥 true锛涘惁鍒欒繑鍥 false銆 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庡皢鍙︿竴涓厤缃妭鐨勬暟缁勫悎骞跺埌褰撳墠閰嶇疆鑺備腑銆傚鏋滃悎骞剁殑鏁扮粍鎴愬姛锛屽皢杩斿洖 true锛涘惁鍒欙紝灏嗚繑鍥 false銆 + * 濡傛灉鍙戠敓閿欒锛屽嚱鏁颁細灏濊瘯鎶ュ憡閿欒骞跺洖婊氭搷浣溿 + */ +bool ConfigSection::MergeArrays(ConfigSection *configSection) { + // 閬嶅巻瑕佸悎骞剁殑閰嶇疆鑺備腑鐨勬暟缁勬槧灏 ConfigArrayMap::iterator itr = configSection->m_arrayMap.begin(); while (itr != configSection->m_arrayMap.end()) { - ConfigArray* configArray = itr->second; + ConfigArray *configArray = itr->second; + // 灏嗘暟缁勬彃鍏ュ埌褰撳墠閰嶇疆鑺傜殑鏁扮粍鏄犲皠涓 ConfigArrayMap::pairis pairis = m_arrayMap.insert(ConfigArrayMap::value_type(configArray->GetName(), configArray)); if (pairis.second != INSERT_SUCCESS) { if (MOT_IS_SEVERE()) { - MOT_REPORT_ERROR(MOT_ERROR_INTERNAL, - "Load Configuration", - "Failed to merge array %s into section %s", - configArray->GetName(), - GetFullPathName()); + // 鎶ュ憡鍚堝苟鏁扮粍澶辫触鐨勪弗閲嶉敊璇 + MOT_REPORT_ERROR(MOT_ERROR_INTERNAL, "Load Configuration", "Failed to merge array %s into section %s", + configArray->GetName(), GetFullPathName()); return false; } - // not inserted, so replace existing value - ConfigArrayMap::iterator& itr2 = pairis.first; + // 鏈彃鍏ワ紝鍥犳鏇挎崲鐜版湁鏁扮粍 + ConfigArrayMap::iterator &itr2 = pairis.first; delete itr2->second; m_arrayMap.erase(itr2); if (!m_arrayMap.insert(ConfigArrayMap::value_type(configArray->GetName(), configArray)).second) { if (MOT_IS_SEVERE()) { - MOT_REPORT_ERROR(MOT_ERROR_INTERNAL, - "Load Configuration", - "Failed to merge array %s into section %s (severe error)", - configArray->GetName(), - GetFullPathName()); + // 鎶ュ憡鍚堝苟鏁扮粍澶辫触鐨勪弗閲嶉敊璇 + MOT_REPORT_ERROR(MOT_ERROR_INTERNAL, "Load Configuration", + "Failed to merge array %s into section %s (severe error)", configArray->GetName(), + GetFullPathName()); return false; } - MOT_REPORT_ERROR(MOT_ERROR_INTERNAL, - "Load Configuration", - "Failed to merge array %s into section %s (unexpected duplicate)", - configArray->GetName(), - GetFullPathName()); + // 鎶ュ憡鍚堝苟鏁扮粍澶辫触鐨勯敊璇紝杩欐槸涓涓笉搴旇鍙戠敓鐨勬剰澶栨儏鍐 + MOT_REPORT_ERROR(MOT_ERROR_INTERNAL, "Load Configuration", + "Failed to merge array %s into section %s (unexpected duplicate)", + configArray->GetName(), GetFullPathName()); MOT_ASSERT(false); return false; } } itr++; } - configSection->m_arrayMap.clear(); // required to make sure items are not deleted in destructor + configSection->m_arrayMap.clear(); // 娓呯┖瑕佸悎骞剁殑閰嶇疆鑺備腑鐨勬暟缁勬槧灏勶紝纭繚涓嶄細鍦ㄦ瀽鏋勫嚱鏁颁腑鍒犻櫎杩欎簺椤 return true; } + } // namespace MOT diff --git a/src/gausskernel/storage/mot/core/infra/config/config_tree.cpp b/src/gausskernel/storage/mot/core/infra/config/config_tree.cpp index 0e52a1bac..36fb4b149 100644 --- a/src/gausskernel/storage/mot/core/infra/config/config_tree.cpp +++ b/src/gausskernel/storage/mot/core/infra/config/config_tree.cpp @@ -32,53 +32,67 @@ IMPLEMENT_CLASS_LOGGER(ConfigTree, Configuration) /** @define Limit the depth of a section. */ #define MAX_SECTION_DEPTH 10 - -bool ConfigTree::ConsolidateParsedSections(mot_list& parsedSections, ConfigSectionMap& sectionMap) +/* + * 鍔熻兘锛氬皢瑙f瀽鐨勯厤缃妭鍚堝苟鍒伴厤缃爲涓 + * + * 鍙傛暟鍒楄〃锛 + * parsedSections锛氬寘鍚В鏋愮殑閰嶇疆鑺傜殑閾捐〃 + * sectionMap锛氬寘鍚厤缃爲涓凡鏈夐厤缃妭鐨勬槧灏 + * + * 杩斿洖鍊硷細 + * 濡傛灉鎴愬姛鍚堝苟閰嶇疆鑺傦紝杩斿洖 true锛涘惁鍒欒繑鍥 false銆 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庡皢瑙f瀽鐨勯厤缃妭鍚堝苟鍒伴厤缃爲涓傝В鏋愮殑閰嶇疆鑺傚寘鍚湪閾捐〃 `parsedSections` 涓紝鑰屽凡鏈夐厤缃妭鏄犲皠瀛樺偍鍦 + * `sectionMap` 涓 鍑芥暟棣栧厛灏嗘牴閰嶇疆鑺備笌瑙f瀽鐨勯厤缃妭鍚堝苟锛岀劧鍚庡皢鍏跺畠閰嶇疆鑺傛坊鍔犲埌鏄犲皠鎴栬呬笌宸叉湁閰嶇疆鑺傚悎骞躲 + * 濡傛灉鍚堝苟澶辫触鎴栬呭湪鍚堝苟杩囩▼涓彂鐢熼敊璇紝鍑芥暟灏嗗皾璇曟姤鍛婇敊璇苟娓呯悊璧勬簮銆 + */ +bool ConfigTree::ConsolidateParsedSections(mot_list &parsedSections, ConfigSectionMap §ionMap) { // consolidate all parsed section into a map: // 1. new sections are added to map and removed from the list (need to delete section from map in case of error) // 2. duplicate sections are merged and deleted (no need to delete merged section in case of error) // 3. iteration stops on first error, and all sections in section list and map are deleted // 4. on successful execution the section list should be empty + // 鍒濆鍖栫粨鏋滄爣蹇椾负 true bool result = true; - mot_list::iterator listItr = parsedSections.begin(); + // 閬嶅巻瑙f瀽鐨勯厤缃妭閾捐〃 + mot_list::iterator listItr = parsedSections.begin(); while (listItr != parsedSections.end()) { - ConfigSection* section = *listItr; - + ConfigSection *section = *listItr; // special case: root section if (section->GetDepth() == 0) { MOT_LOG_DEBUG("Merging root section"); + // 鍚堝苟鏍归厤缃妭 if (!m_rootSection.Merge(section)) { - MOT_REPORT_ERROR(MOT_ERROR_INTERNAL, - "Load Configuration", - "Malformed configuration file: failed to merge root section"); + MOT_REPORT_ERROR(MOT_ERROR_INTERNAL, "Load Configuration", + "Malformed configuration file: failed to merge root section"); result = false; break; // go to cleanup after error (currently iterated section will be cleaned up from list) } // cleanup merged section now, even if we fail later (because if we don't fail, this is a memory leak) delete section; } else { + // 鏌ユ壘鍦ㄦ槧灏勪腑鏄惁瀛樺湪褰撳墠閰嶇疆鑺 ConfigSectionMap::iterator mapItr = sectionMap.find(section->GetFullPathName()); if (mapItr == sectionMap.end()) { + // 鎻掑叆鏂伴厤缃妭鍒版槧灏 // insert new section MOT_LOG_DEBUG("Adding section: %s (name: %s)", section->GetFullPathName(), section->GetName()); if (!sectionMap.insert(ConfigSectionMap::value_type(section->GetFullPathName(), section)).second) { - MOT_REPORT_ERROR(MOT_ERROR_INTERNAL, - "Load Configuration", - "Failed to build configuration tree, cannot add section %s", - section->GetFullPathName()); + MOT_REPORT_ERROR(MOT_ERROR_INTERNAL, "Load Configuration", + "Failed to build configuration tree, cannot add section %s", + section->GetFullPathName()); result = false; break; // go to cleanup after error (currently iterated section will be cleaned up from list) } } else { // merge into existing section - ConfigSection* existingSection = mapItr->second; + ConfigSection *existingSection = mapItr->second; MOT_LOG_DEBUG("Merging section: %s (name: %s)", section->GetFullPathName(), section->GetName()); if (!existingSection->Merge(section)) { - MOT_REPORT_ERROR(MOT_ERROR_INTERNAL, - "Load Configuration", - "Failed to merge section %s", - section->GetFullPathName()); + MOT_REPORT_ERROR(MOT_ERROR_INTERNAL, "Load Configuration", "Failed to merge section %s", + section->GetFullPathName()); result = false; break; // go to cleanup after error (currently iterated section will be cleaned up from list) } @@ -98,14 +112,14 @@ bool ConfigTree::ConsolidateParsedSections(mot_list& parsedSecti // cleanup parsed sections and section map listItr = parsedSections.begin(); while (listItr != parsedSections.end()) { - ConfigSection* section = *listItr; + ConfigSection *section = *listItr; delete section; ++listItr; } parsedSections.clear(); ConfigSectionMap::iterator mapItr = sectionMap.begin(); while (mapItr != sectionMap.end()) { - ConfigSection* section = mapItr->second; + ConfigSection *section = mapItr->second; delete section; ++mapItr; } @@ -113,8 +127,22 @@ bool ConfigTree::ConsolidateParsedSections(mot_list& parsedSecti } return result; } - -bool ConfigTree::LinkConsolidatedSectionMap(ConfigSectionMap& sectionMap) +/* + * 鍔熻兘锛氶摼鎺ュ悎骞跺悗鐨勯厤缃妭鏄犲皠 + * + * 鍙傛暟鍒楄〃锛 + * sectionMap锛氬寘鍚悎骞跺悗鐨勯厤缃妭鏄犲皠 + * + * 杩斿洖鍊硷細 + * 濡傛灉鎴愬姛閾炬帴閰嶇疆鑺傦紝杩斿洖 true锛涘惁鍒欒繑鍥 false銆 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庨摼鎺ュ悎骞跺悗鐨勯厤缃妭鏄犲皠銆傚悎骞跺悗鐨勯厤缃妭鏄犲皠鍖呭惈鍦 `sectionMap` 涓 + * 鍑芥暟閬嶅巻鏄犲皠涓殑姣忎釜閰嶇疆鑺傦紝鎵惧埌鎴栧垱寤哄叾鐖堕厤缃妭锛岀劧鍚庡皢瀛愰厤缃妭娣诲姞鍒扮埗閰嶇疆鑺備腑鎴栦笌宸叉湁鐨勫瓙閰嶇疆鑺傚悎骞躲 + * 濡傛灉閾炬帴澶辫触鎴栧湪閾炬帴杩囩▼涓彂鐢熼敊璇紝鍑芥暟灏嗗皾璇曟姤鍛婇敊璇苟娓呯悊璧勬簮銆 + * 鍦ㄦ垚鍔熸墽琛屾椂锛岄厤缃妭鏄犲皠搴斾负绌恒 + */ +bool ConfigTree::LinkConsolidatedSectionMap(ConfigSectionMap §ionMap) { // link consolidated section map. for each iterated section: // 1. find or create parent section @@ -122,21 +150,21 @@ bool ConfigTree::LinkConsolidatedSectionMap(ConfigSectionMap& sectionMap) // 3. duplicate sub-sections are merged and deleted (no need to delete merged section in case of error) // 4. iteration stops on first error, and all sections in section map are deleted // 5. on successful execution the section map should be empty + // 鍒濆鍖栫粨鏋滄爣蹇椾负 true bool result = true; MOT_LOG_DEBUG("Linking sections"); + // 閬嶅巻閰嶇疆鑺傛槧灏 ConfigSectionMap::iterator mapItr = sectionMap.begin(); while (mapItr != sectionMap.end()) { - ConfigSection* section = mapItr->second; + ConfigSection *section = mapItr->second; MOT_LOG_DEBUG("Linking section %s with depth %u", section->GetFullPathName(), section->GetDepth()); bool created = false; // get the parent or create a new one (recursively) - ConfigSection* parent = GetOrCreateParent(section, 0, created); + ConfigSection *parent = GetOrCreateParent(section, 0, created); if (parent == nullptr) { - MOT_REPORT_ERROR(MOT_ERROR_INTERNAL, - "Load Configuration", - "Failed to get or create parent of section %s", - section->GetFullPathName()); + MOT_REPORT_ERROR(MOT_ERROR_INTERNAL, "Load Configuration", "Failed to get or create parent of section %s", + section->GetFullPathName()); result = false; break; } @@ -144,21 +172,16 @@ bool ConfigTree::LinkConsolidatedSectionMap(ConfigSectionMap& sectionMap) // add or merge the section into its parent if (!parent->ContainsConfigSection(section->GetName())) { if (!parent->AddConfigItem(section)) { - MOT_REPORT_ERROR(MOT_ERROR_INTERNAL, - "Load Configuration", - "Failed to add section %s to new parent %s", - section->GetFullPathName(), - parent->GetFullPathName()); + MOT_REPORT_ERROR(MOT_ERROR_INTERNAL, "Load Configuration", "Failed to add section %s to new parent %s", + section->GetFullPathName(), parent->GetFullPathName()); result = false; break; } } else { - ConfigSection* existingSection = (ConfigSection*)parent->GetConfigSection(section->GetName()); + ConfigSection *existingSection = (ConfigSection *)parent->GetConfigSection(section->GetName()); if (!existingSection->Merge(section)) { - MOT_REPORT_ERROR(MOT_ERROR_INTERNAL, - "Load Configuration", - "Failed to merge existing section %s", - section->GetFullPathName()); + MOT_REPORT_ERROR(MOT_ERROR_INTERNAL, "Load Configuration", "Failed to merge existing section %s", + section->GetFullPathName()); result = false; break; } @@ -176,7 +199,7 @@ bool ConfigTree::LinkConsolidatedSectionMap(ConfigSectionMap& sectionMap) if (!result) { mapItr = sectionMap.begin(); while (mapItr != sectionMap.end()) { - ConfigSection* section = mapItr->second; + ConfigSection *section = mapItr->second; delete section; ++mapItr; } @@ -184,18 +207,33 @@ bool ConfigTree::LinkConsolidatedSectionMap(ConfigSectionMap& sectionMap) } return result; } - -bool ConfigTree::Build(mot_list& parsedSections) +/* + * 鍔熻兘锛氭瀯寤洪厤缃爲 + * + * 鍙傛暟鍒楄〃锛 + * parsedSections锛氬寘鍚В鏋愬悗鐨勯厤缃妭鐨勯摼琛 + * + * 杩斿洖鍊硷細 + * 濡傛灉鎴愬姛鏋勫缓閰嶇疆鏍戯紝杩斿洖 true锛涘惁鍒欒繑鍥 false銆 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庢瀯寤洪厤缃爲銆傚畠棣栧厛灏嗘墍鏈夐厤缃妭鎸夌収瀹屾暣璺緞鍚嶆彃鍏ユ槧灏勪腑銆 + * 鐒跺悗锛屽畠灏濊瘯閾炬帴鍚堝苟鍚庣殑閰嶇疆鑺傛槧灏勶紝灏嗗瓙閰嶇疆鑺傛坊鍔犲埌鐖堕厤缃妭涓垨涓庡凡鏈夌殑瀛愰厤缃妭鍚堝苟銆 + * 濡傛灉鏋勫缓澶辫触锛屽嚱鏁板皢灏濊瘯鎶ュ憡閿欒锛屽苟杩斿洖 false銆 + */ +bool ConfigTree::Build(mot_list &parsedSections) { bool result = true; MOT_LOG_DEBUG("Building configuration tree"); // insert all section to map according to full path name + // 灏嗘墍鏈夐厤缃妭鎸夌収瀹屾暣璺緞鍚嶆彃鍏ユ槧灏勪腑 ConfigSectionMap sectionMap; if (!ConsolidateParsedSections(parsedSections, sectionMap)) { MOT_REPORT_ERROR(MOT_ERROR_INTERNAL, "Load Configuration", "Failed to consolidate parsed section list"); result = false; } else { + // 灏濊瘯閾炬帴鍚堝苟鍚庣殑閰嶇疆鑺傛槧灏 if (!LinkConsolidatedSectionMap(sectionMap)) { MOT_REPORT_ERROR(MOT_ERROR_INTERNAL, "Load Configuration", "Failed to build configuration tree"); result = false; @@ -211,25 +249,36 @@ bool ConfigTree::Build(mot_list& parsedSections) } return result; } - -const ConfigItem* ConfigTree::GetConfigItem(const char* fullPathName) const +/* + * 鍔熻兘锛氭牴鎹畬鏁磋矾寰勫悕鑾峰彇閰嶇疆椤 + * + * 鍙傛暟鍒楄〃锛 + * fullPathName锛氶厤缃」鐨勫畬鏁磋矾寰勫悕 + * + * 杩斿洖鍊硷細 + * 濡傛灉鎵惧埌鎸囧畾璺緞鐨勯厤缃」锛岃繑鍥炴寚鍚戣閰嶇疆椤圭殑鎸囬拡锛涘鏋滄湭鎵惧埌锛岃繑鍥 nullptr銆 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庝粠閰嶇疆鏍戜腑鑾峰彇鍏锋湁缁欏畾瀹屾暣璺緞鍚嶇殑閰嶇疆椤广傚畠棣栧厛灏嗚矾寰勫悕鍒嗗壊涓哄悇涓粍浠讹紝 + * 鐒跺悗閫愮骇閬嶅巻閰嶇疆鏍戜互鏌ユ壘鎸囧畾鐨勯厤缃」銆傚鏋滄壘鍒伴厤缃」锛屽嚱鏁板皢杩斿洖鎸囧悜璇ラ厤缃」鐨勬寚閽堬紱 + * 濡傛灉鏈壘鍒帮紝灏嗚繑鍥 nullptr銆 + */ +const ConfigItem *ConfigTree::GetConfigItem(const char *fullPathName) const { MOT_LOG_DEBUG("Getting from tree %s config item %s: starting", GetSource(), fullPathName); - const ConfigItem* result = nullptr; + const ConfigItem *result = nullptr; // break path name to components mot_string_list pathComponents; if (!ConfigFileParser::Split(fullPathName, ConfigItem::PATH_SEP, pathComponents)) { - MOT_REPORT_ERROR(MOT_ERROR_INTERNAL, - "Load Configuration", - "Failed to split configuration path %s into components", - fullPathName); + MOT_REPORT_ERROR(MOT_ERROR_INTERNAL, "Load Configuration", + "Failed to split configuration path %s into components", fullPathName); return nullptr; } MOT_LOG_DEBUG("Getting from tree %s config item %s: finished split", GetSource(), fullPathName); // dig into the tree - const ConfigSection* currentSection = &m_rootSection; + const ConfigSection *currentSection = &m_rootSection; mot_string_list::iterator itr = pathComponents.begin(); while (itr != pathComponents.end() && currentSection) { MOT_LOG_DEBUG("Getting from section %s config item %s", currentSection->GetFullPathName(), itr->c_str()); @@ -238,7 +287,7 @@ const ConfigItem* ConfigTree::GetConfigItem(const char* fullPathName) const break; } if (result->GetClass() == ConfigItemClass::CONFIG_ITEM_SECTION) { - currentSection = static_cast(result); + currentSection = static_cast(result); } else { currentSection = nullptr; } @@ -251,38 +300,50 @@ const ConfigItem* ConfigTree::GetConfigItem(const char* fullPathName) const return result; } - -ConfigSection* ConfigTree::GetOrCreateParent(ConfigSection* section, int depth, bool& created) +/* + * 鍔熻兘锛氳幏鍙栨垨鍒涘缓閰嶇疆椤圭殑鐖剁骇閮ㄥ垎 + * + * 鍙傛暟鍒楄〃锛 + * section锛氳鑾峰彇鎴栧垱寤虹埗绾ч儴鍒嗙殑閰嶇疆椤 + * depth锛氶掑綊娣卞害锛岀敤浜庨槻姝㈡棤闄愰掑綊璋冪敤 + * created锛氱敤浜庢寚绀烘槸鍚﹀凡鍒涘缓鏂扮殑鐖剁骇閮ㄥ垎 + * + * 杩斿洖鍊硷細 + * 濡傛灉鎴愬姛鑾峰彇鎴栧垱寤虹埗绾ч儴鍒嗭紝鍒欒繑鍥炴寚鍚戠埗绾ч儴鍒嗙殑鎸囬拡锛涘鏋滃嚭鐜伴敊璇紝鍒欒繑鍥 nullptr銆 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庤幏鍙栨垨鍒涘缓閰嶇疆椤圭殑鐖剁骇閮ㄥ垎銆傚畠鍙互閫掑綊鍦板垱寤虹埗绾ч儴鍒嗭紝濡傛灉鐖剁骇閮ㄥ垎涓嶅瓨鍦ㄧ殑璇濄 + * 濡傛灉閫掑綊娣卞害瓒呰繃浜嗘渶澶у厑璁稿硷紝鍑芥暟灏嗚繑鍥 nullptr 骞舵姤鍛婇敊璇 + * 濡傛灉鎴愬姛鑾峰彇鎴栧垱寤虹埗绾ч儴鍒嗭紝created 鍙傛暟灏嗘寚绀烘槸鍚﹀凡鍒涘缓浜嗘柊鐨勭埗绾ч儴鍒嗐 + */ +ConfigSection *ConfigTree::GetOrCreateParent(ConfigSection *section, int depth, bool &created) { MOT_LOG_DEBUG("Building recursive parent for section: %s", section->GetFullPathName()); // guard against endless recurring calls if (depth >= MAX_SECTION_DEPTH) { MOT_REPORT_ERROR(MOT_ERROR_INVALID_STATE, - "Load Configuration" - "Failed to get or create parent of section %s: section depth exceeds maximum allowed (%u)", - section->GetFullPathName(), - (unsigned)MAX_SECTION_DEPTH); + "Load Configuration" + "Failed to get or create parent of section %s: section depth exceeds maximum allowed (%u)", + section->GetFullPathName(), (unsigned)MAX_SECTION_DEPTH); return nullptr; } // get parent or create it (recursively) created = false; - ConfigSection* parent = nullptr; + ConfigSection *parent = nullptr; if (section->GetDepth() == 1) { MOT_LOG_DEBUG("Found root parent of section %s", section->GetFullPathName()); parent = &m_rootSection; } else { - parent = (ConfigSection*)GetConfigSection(section->GetPath()); + parent = (ConfigSection *)GetConfigSection(section->GetPath()); } if (parent == nullptr) { MOT_LOG_DEBUG("Parent of section %s not found, creating", section->GetFullPathName()); parent = CreateParent(section, depth); if (parent == nullptr) { - MOT_REPORT_ERROR(MOT_ERROR_INTERNAL, - "Load Configuration", - "Failed to create section path: %s", - section->GetFullPathName()); + MOT_REPORT_ERROR(MOT_ERROR_INTERNAL, "Load Configuration", "Failed to create section path: %s", + section->GetFullPathName()); return nullptr; } created = true; @@ -293,12 +354,9 @@ ConfigSection* ConfigTree::GetOrCreateParent(ConfigSection* section, int depth, if (depth > 0) { MOT_LOG_TRACE("Linking section %s to its parent %s", section->GetFullPathName(), parent->GetFullPathName()); if (!parent->AddConfigItem(section)) { - MOT_REPORT_ERROR(MOT_ERROR_INTERNAL, - "Load Configuration", - "Failed to add section %s to parent %s (call depth: %d)", - section->GetFullPathName(), - parent->GetFullPathName(), - depth); + MOT_REPORT_ERROR(MOT_ERROR_INTERNAL, "Load Configuration", + "Failed to add section %s to parent %s (call depth: %d)", section->GetFullPathName(), + parent->GetFullPathName(), depth); // if the parent was created, then we should not clean it up, since it is already linked to the tree return nullptr; } @@ -306,10 +364,23 @@ ConfigSection* ConfigTree::GetOrCreateParent(ConfigSection* section, int depth, return parent; } - -ConfigSection* ConfigTree::CreateParent(ConfigSection* section, int depth) +/* + * 鍔熻兘锛氬垱寤洪厤缃」鐨勭埗绾ч儴鍒 + * + * 鍙傛暟鍒楄〃锛 + * section锛氳鍒涘缓鐖剁骇閮ㄥ垎鐨勯厤缃」 + * depth锛氶掑綊娣卞害锛岀敤浜庨槻姝㈡棤闄愰掑綊璋冪敤 + * + * 杩斿洖鍊硷細 + * 濡傛灉鎴愬姛鍒涘缓鐖剁骇閮ㄥ垎锛屽垯杩斿洖鎸囧悜鐖剁骇閮ㄥ垎鐨勬寚閽堬紱濡傛灉鍑虹幇閿欒锛屽垯杩斿洖 nullptr銆 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庡垱寤洪厤缃」鐨勭埗绾ч儴鍒嗐傚畠鍙互閫掑綊鍦板垱寤虹埗绾ч儴鍒嗭紝濡傛灉鐖剁骇閮ㄥ垎涓嶅瓨鍦ㄧ殑璇濄 + * 濡傛灉閫掑綊娣卞害瓒呰繃浜嗘渶澶у厑璁稿硷紝鍑芥暟灏嗚繑鍥 nullptr 骞舵姤鍛婇敊璇 + */ +ConfigSection *ConfigTree::CreateParent(ConfigSection *section, int depth) { - ConfigSection* parent = nullptr; + ConfigSection *parent = nullptr; mot_string sectionPath; mot_string sectionName; @@ -318,17 +389,16 @@ ConfigSection* ConfigTree::CreateParent(ConfigSection* section, int depth) // guard against endless recurring calls if (depth >= MAX_SECTION_DEPTH) { MOT_REPORT_ERROR(MOT_ERROR_INVALID_STATE, - "Load Configuration" - "Failed to create parent of section %s: section depth exceeds maximum allowed (%u)", - section->GetFullPathName(), - (unsigned)MAX_SECTION_DEPTH); + "Load Configuration" + "Failed to create parent of section %s: section depth exceeds maximum allowed (%u)", + section->GetFullPathName(), (unsigned)MAX_SECTION_DEPTH); return nullptr; } // parse full section name of parent and create the parent if (!ConfigFileParser::BreakSectionName(section->GetPath(), sectionPath, sectionName)) { - MOT_REPORT_ERROR( - MOT_ERROR_INTERNAL, "Load Configuration", "Failed to parse section name: %s", section->GetPath()); + MOT_REPORT_ERROR(MOT_ERROR_INTERNAL, "Load Configuration", "Failed to parse section name: %s", + section->GetPath()); return nullptr; } parent = ConfigSection::CreateConfigSection(sectionPath.c_str(), sectionName.c_str()); @@ -339,12 +409,10 @@ ConfigSection* ConfigTree::CreateParent(ConfigSection* section, int depth) // get the parent of the new parent section (make sure it exists and linked to the parent we just created) bool parentCreated = false; - ConfigSection* grandParent = GetOrCreateParent(parent, depth + 1, parentCreated); + ConfigSection *grandParent = GetOrCreateParent(parent, depth + 1, parentCreated); if (grandParent == nullptr) { - MOT_REPORT_ERROR(MOT_ERROR_INTERNAL, - "Load Configuration", - "Failed to get or create parent of parent section %s", - parent->GetFullPathName()); + MOT_REPORT_ERROR(MOT_ERROR_INTERNAL, "Load Configuration", + "Failed to get or create parent of parent section %s", parent->GetFullPathName()); delete parent; return nullptr; } diff --git a/src/gausskernel/storage/mot/core/infra/config/config_value_type.cpp b/src/gausskernel/storage/mot/core/infra/config/config_value_type.cpp index e6417f8ca..057dccd32 100644 --- a/src/gausskernel/storage/mot/core/infra/config/config_value_type.cpp +++ b/src/gausskernel/storage/mot/core/infra/config/config_value_type.cpp @@ -26,33 +26,38 @@ #include "string.h" namespace MOT { -static const char* CONFIG_VALUE_INT64_STR = "int64"; -static const char* CONFIG_VALUE_INT32_STR = "int32"; -static const char* CONFIG_VALUE_INT16_STR = "int16"; -static const char* CONFIG_VALUE_INT8_STR = "int8"; -static const char* CONFIG_VALUE_UINT64_STR = "uint64"; -static const char* CONFIG_VALUE_UINT32_STR = "uint32"; -static const char* CONFIG_VALUE_UINT16_STR = "uint16"; -static const char* CONFIG_VALUE_UINT8_STR = "uint8"; -static const char* CONFIG_VALUE_DOUBLE_STR = "double"; -static const char* CONFIG_VALUE_BOOL_STR = "bool"; -static const char* CONFIG_VALUE_STRING_STR = "string"; -static const char* CONFIG_VALUE_UNDEFINED_STR = "N/A"; +static const char *CONFIG_VALUE_INT64_STR = "int64"; +static const char *CONFIG_VALUE_INT32_STR = "int32"; +static const char *CONFIG_VALUE_INT16_STR = "int16"; +static const char *CONFIG_VALUE_INT8_STR = "int8"; +static const char *CONFIG_VALUE_UINT64_STR = "uint64"; +static const char *CONFIG_VALUE_UINT32_STR = "uint32"; +static const char *CONFIG_VALUE_UINT16_STR = "uint16"; +static const char *CONFIG_VALUE_UINT8_STR = "uint8"; +static const char *CONFIG_VALUE_DOUBLE_STR = "double"; +static const char *CONFIG_VALUE_BOOL_STR = "bool"; +static const char *CONFIG_VALUE_STRING_STR = "string"; +static const char *CONFIG_VALUE_UNDEFINED_STR = "N/A"; -static const char* VALUE_TYPE_NAMES[] = {CONFIG_VALUE_INT64_STR, - CONFIG_VALUE_INT32_STR, - CONFIG_VALUE_INT16_STR, - CONFIG_VALUE_INT8_STR, - CONFIG_VALUE_UINT64_STR, - CONFIG_VALUE_UINT32_STR, - CONFIG_VALUE_UINT16_STR, - CONFIG_VALUE_UINT8_STR, - CONFIG_VALUE_DOUBLE_STR, - CONFIG_VALUE_BOOL_STR, - CONFIG_VALUE_STRING_STR, - CONFIG_VALUE_UNDEFINED_STR}; - -extern ConfigValueType ConfigValueTypeFromString(const char* valueTypeStr) +static const char *VALUE_TYPE_NAMES[] = {CONFIG_VALUE_INT64_STR, CONFIG_VALUE_INT32_STR, CONFIG_VALUE_INT16_STR, + CONFIG_VALUE_INT8_STR, CONFIG_VALUE_UINT64_STR, CONFIG_VALUE_UINT32_STR, + CONFIG_VALUE_UINT16_STR, CONFIG_VALUE_UINT8_STR, CONFIG_VALUE_DOUBLE_STR, + CONFIG_VALUE_BOOL_STR, CONFIG_VALUE_STRING_STR, CONFIG_VALUE_UNDEFINED_STR}; +/* + * 鍔熻兘锛氫粠瀛楃涓蹭腑瑙f瀽閰嶇疆鍊肩殑绫诲瀷 + * + * 鍙傛暟鍒楄〃锛 + * valueTypeStr锛氳瑙f瀽鐨勯厤缃肩被鍨嬬殑瀛楃涓茶〃绀 + * + * 杩斿洖鍊硷細 + * 杩斿洖浠庡瓧绗︿覆瑙f瀽鐨勯厤缃肩被鍨嬶紙`ConfigValueType` 鏋氫妇鍊硷級銆 + * 濡傛灉瀛楃涓叉棤娉曡瘑鍒紝鍒欒繑鍥 `CONFIG_VALUE_UNDEFINED`銆 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁版牴鎹緭鍏ョ殑瀛楃涓插艰繑鍥炵浉搴旂殑閰嶇疆鍊肩被鍨嬨 + * 濡傛灉杈撳叆瀛楃涓叉棤娉曡瘑鍒紝鍒欒繑鍥 `CONFIG_VALUE_UNDEFINED`銆 + */ +extern ConfigValueType ConfigValueTypeFromString(const char *valueTypeStr) { ConfigValueType result = ConfigValueType::CONFIG_VALUE_UNDEFINED; @@ -82,15 +87,40 @@ extern ConfigValueType ConfigValueTypeFromString(const char* valueTypeStr) return result; } - -extern const char* ConfigValueTypeToString(ConfigValueType valueType) +/* + * 鍔熻兘锛氬皢閰嶇疆鍊肩被鍨嬭浆鎹负瀛楃涓茶〃绀 + * + * 鍙傛暟鍒楄〃锛 + * valueType锛氳杞崲涓哄瓧绗︿覆鐨勯厤缃肩被鍨嬶紙`ConfigValueType` 鏋氫妇鍊硷級 + * + * 杩斿洖鍊硷細 + * 杩斿洖閰嶇疆鍊肩被鍨嬬殑瀛楃涓茶〃绀恒 + * 濡傛灉閰嶇疆鍊肩被鍨嬫棤鏁堬紝鍒欒繑鍥炶〃绀烘湭瀹氫箟閰嶇疆鍊肩被鍨嬬殑瀛楃涓层 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁板皢缁欏畾鐨勯厤缃肩被鍨嬭浆鎹负鐩稿簲鐨勫瓧绗︿覆琛ㄧず銆 + * 濡傛灉閰嶇疆鍊肩被鍨嬫棤鏁堬紝鍒欒繑鍥炶〃绀烘湭瀹氫箟閰嶇疆鍊肩被鍨嬬殑瀛楃涓层 + */ +extern const char *ConfigValueTypeToString(ConfigValueType valueType) { if (valueType < ConfigValueType::CONFIG_VALUE_UNDEFINED) { return VALUE_TYPE_NAMES[(uint32_t)valueType]; } return CONFIG_VALUE_UNDEFINED_STR; } - +/* + * 鍔熻兘锛氭鏌ラ厤缃肩被鍨嬫槸鍚︿负鏁存暟绫诲瀷 + * + * 鍙傛暟鍒楄〃锛 + * valueType锛氳妫鏌ョ殑閰嶇疆鍊肩被鍨嬶紙`ConfigValueType` 鏋氫妇鍊硷級 + * + * 杩斿洖鍊硷細 + * 濡傛灉閰嶇疆鍊肩被鍨嬫槸鏁存暟绫诲瀷锛屽垯杩斿洖 true锛屽惁鍒欒繑鍥 false銆 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庢鏌ョ粰瀹氱殑閰嶇疆鍊肩被鍨嬫槸鍚﹁〃绀烘暣鏁扮被鍨嬨 + * 濡傛灉閰嶇疆鍊肩被鍨嬩负鏁存暟绫诲瀷涔嬩竴锛屽垯杩斿洖 true锛屽惁鍒欒繑鍥 false銆 + */ extern bool IsConfigValueIntegral(ConfigValueType valueType) { bool result = false; diff --git a/src/gausskernel/storage/mot/core/infra/config/ext_config_loader.cpp b/src/gausskernel/storage/mot/core/infra/config/ext_config_loader.cpp index 2a96c64b5..a395e467f 100644 --- a/src/gausskernel/storage/mot/core/infra/config/ext_config_loader.cpp +++ b/src/gausskernel/storage/mot/core/infra/config/ext_config_loader.cpp @@ -27,7 +27,17 @@ namespace MOT { IMPLEMENT_CLASS_LOGGER(ExtConfigLoader, Configuration) - +/* + * 鍔熻兘锛氬姞杞藉閮ㄩ厤缃 + * + * 杩斿洖鍊硷細 + * 濡傛灉鎴愬姛鍔犺浇澶栭儴閰嶇疆锛屽垯杩斿洖 true锛屽惁鍒欒繑鍥 false銆 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庡姞杞藉閮ㄩ厤缃傚畠鍖呭惈浜嗗姞杞姐佸鐞嗗拰鏈缁堝寲澶栭儴閰嶇疆鐨勬楠ゃ + * 濡傛灉鍦ㄤ换浣曟楠や腑鍑虹幇閿欒锛屽嚱鏁板皢杩斿洖 false锛屽苟璁板綍閫傚綋鐨勯敊璇秷鎭 + * 濡傛灉鎴愬姛鍔犺浇澶栭儴閰嶇疆锛屽垯鏈缁堥厤缃俊鎭皢鎵撳嵃鍒版棩蹇楋紙濡傛灉鏃ュ織绾у埆涓 `LogLevel::LL_TRACE`锛夈 + */ bool ExtConfigLoader::LoadExtConfig() { bool result = false; @@ -41,11 +51,13 @@ bool ExtConfigLoader::LoadExtConfig() MOT_REPORT_ERROR(MOT_ERROR_INTERNAL, "Load Configuration", "Failed to load external configuration"); } else { // wrap up + // 瀹屾垚鍔犺浇澶栭儴閰嶇疆 result = EndExtConfigLoad(); if (!result) { - MOT_REPORT_ERROR( - MOT_ERROR_INTERNAL, "Load Configuration", "Failed to finalize external configuration loading"); + MOT_REPORT_ERROR(MOT_ERROR_INTERNAL, "Load Configuration", + "Failed to finalize external configuration loading"); } else { + // 濡傛灉鏃ュ織绾у埆涓 LogLevel::LL_TRACE锛屽垯鎵撳嵃宸插姞杞界殑澶栭儴閰嶇疆淇℃伅 if (MOT_CHECK_LOG_LEVEL(LogLevel::LL_TRACE)) { MOT_LOG_INFO("Loaded external configuration:"); m_extConfigTree->Print(LogLevel::LL_TRACE); @@ -56,73 +68,93 @@ bool ExtConfigLoader::LoadExtConfig() return result; } -bool ExtConfigLoader::AddExtStringConfigItem(const char* path, const char* key, const char* value) +bool ExtConfigLoader::AddExtStringConfigItem(const char *path, const char *key, const char *value) { return AddTypedConfigItem(path, key, value); } -bool ExtConfigLoader::AddExtUInt64ConfigItem(const char* path, const char* key, uint64_t value) +bool ExtConfigLoader::AddExtUInt64ConfigItem(const char *path, const char *key, uint64_t value) { return AddTypedConfigItem(path, key, value); } -bool ExtConfigLoader::AddExtUInt32ConfigItem(const char* path, const char* key, uint32_t value) +bool ExtConfigLoader::AddExtUInt32ConfigItem(const char *path, const char *key, uint32_t value) { return AddTypedConfigItem(path, key, value); } -bool ExtConfigLoader::AddExtUInt16ConfigItem(const char* path, const char* key, uint16_t value) +bool ExtConfigLoader::AddExtUInt16ConfigItem(const char *path, const char *key, uint16_t value) { return AddTypedConfigItem(path, key, value); } -bool ExtConfigLoader::AddExtUInt8ConfigItem(const char* path, const char* key, uint8_t value) +bool ExtConfigLoader::AddExtUInt8ConfigItem(const char *path, const char *key, uint8_t value) { return AddTypedConfigItem(path, key, value); } -bool ExtConfigLoader::AddExtInt64ConfigItem(const char* path, const char* key, int64_t value) +bool ExtConfigLoader::AddExtInt64ConfigItem(const char *path, const char *key, int64_t value) { return AddTypedConfigItem(path, key, value); } -bool ExtConfigLoader::AddExtInt32ConfigItem(const char* path, const char* key, int32_t value) +bool ExtConfigLoader::AddExtInt32ConfigItem(const char *path, const char *key, int32_t value) { return AddTypedConfigItem(path, key, value); } -bool ExtConfigLoader::AddExtInt16ConfigItem(const char* path, const char* key, int16_t value) +bool ExtConfigLoader::AddExtInt16ConfigItem(const char *path, const char *key, int16_t value) { return AddTypedConfigItem(path, key, value); } -bool ExtConfigLoader::AddExtInt8ConfigItem(const char* path, const char* key, int8_t value) +bool ExtConfigLoader::AddExtInt8ConfigItem(const char *path, const char *key, int8_t value) { return AddTypedConfigItem(path, key, value); } -bool ExtConfigLoader::AddExtDoubleConfigItem(const char* path, const char* key, double value) +bool ExtConfigLoader::AddExtDoubleConfigItem(const char *path, const char *key, double value) { return AddTypedConfigItem(path, key, value); } -bool ExtConfigLoader::AddExtBoolConfigItem(const char* path, const char* key, bool value) +bool ExtConfigLoader::AddExtBoolConfigItem(const char *path, const char *key, bool value) { return AddTypedConfigItem(path, key, value); } -bool ExtConfigLoader::AddExtConfigItem(ConfigItem* configItem) +/* + * 鍔熻兘锛氭坊鍔犲閮ㄩ厤缃」 + * + * 鍙傛暟锛 + * configItem - 瑕佹坊鍔犵殑澶栭儴閰嶇疆椤 + * + * 杩斿洖鍊硷細 + * 濡傛灉鎴愬姛娣诲姞閰嶇疆椤癸紝鍒欒繑鍥 true锛屽惁鍒欒繑鍥 false銆 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庢坊鍔犲閮ㄩ厤缃」銆傚畠棣栧厛鏌ユ壘閰嶇疆椤圭殑鐖堕儴鍒嗭紝濡傛灉涓嶅瓨鍦紝鍒欏垱寤烘柊鐨勭埗閮ㄥ垎銆 + * 鐒跺悗灏嗛厤缃」娣诲姞鍒扮埗閮ㄥ垎涓傚鏋滅埗閮ㄥ垎涓嶅瓨鍦紝鎴栬呮坊鍔犲け璐ワ紝鍒欏嚱鏁拌繑鍥 false銆 + * 濡傛灉閰嶇疆椤瑰凡瀛樺湪浜庣埗閮ㄥ垎涓紝瀹冨彲鑳戒細璁板綍璀﹀憡娑堟伅锛屼絾涓嶄細瀵艰嚧鍑芥暟澶辫触銆 + */ +bool ExtConfigLoader::AddExtConfigItem(ConfigItem *configItem) { - ConfigSection* section = nullptr; + ConfigSection *section = nullptr; ConfigSectionMap::iterator itr = m_sectionMap.find(configItem->GetPath()); + + // 濡傛灉閰嶇疆椤圭殑鐖堕儴鍒嗕笉瀛樺湪锛屽垱寤烘柊鐨勭埗閮ㄥ垎 if (itr == m_sectionMap.end()) { mot_string sectionPath; mot_string sectionName; - if (!ConfigFileParser::BreakSectionName( - configItem->GetPath(), sectionPath, sectionName, ConfigItem::PATH_SEP)) { + + // 瑙f瀽閰嶇疆椤圭殑璺緞锛屼互鑾峰彇鐖堕儴鍒嗙殑璺緞鍜屽悕绉 + if (!ConfigFileParser::BreakSectionName(configItem->GetPath(), sectionPath, sectionName, + ConfigItem::PATH_SEP)) { MOT_REPORT_ERROR(MOT_ERROR_INTERNAL, "Load Configuration", "Failed to parse external section name"); return false; } + + // 鍒涘缓鏂扮殑閰嶇疆閮ㄥ垎 section = ConfigSection::CreateConfigSection(sectionPath.c_str(), sectionName.c_str()); if (section == nullptr) { MOT_REPORT_ERROR(MOT_ERROR_OOM, "Load Configuration", "Failed to create new external section"); @@ -135,10 +167,8 @@ bool ExtConfigLoader::AddExtConfigItem(ConfigItem* configItem) } if (!m_sectionMap.insert(ConfigSectionMap::value_type(section->GetFullPathName(), section)).second) { if (MOT_IS_SEVERE()) { - MOT_REPORT_ERROR(MOT_ERROR_INTERNAL, - "Load Configuration", - "Failed to insert external section %s", - section->GetFullPathName()); + MOT_REPORT_ERROR(MOT_ERROR_INTERNAL, "Load Configuration", "Failed to insert external section %s", + section->GetFullPathName()); delete section; return false; } @@ -149,27 +179,39 @@ bool ExtConfigLoader::AddExtConfigItem(ConfigItem* configItem) section = itr->second; } + // 灏嗛厤缃」娣诲姞鍒扮埗閮ㄥ垎涓 if (!section->AddConfigItem(configItem)) { if (MOT_IS_SEVERE()) { - MOT_REPORT_ERROR(MOT_ERROR_INTERNAL, - "Load Configuration", - "Failed to add external configuration item %s to parent section %s", - configItem->GetPath(), - section->GetFullPathName()); + MOT_REPORT_ERROR(MOT_ERROR_INTERNAL, "Load Configuration", + "Failed to add external configuration item %s to parent section %s", configItem->GetPath(), + section->GetFullPathName()); return false; } MOT_LOG_WARN("Failed to add duplicate external configuration item %s to parent section %s", - configItem->GetPath(), - section->GetFullPathName()); + configItem->GetPath(), section->GetFullPathName()); } return true; } +/* + * 鍔熻兘锛氱粨鏉熷閮ㄩ厤缃姞杞 + * + * 杩斿洖鍊硷細 + * 濡傛灉鎴愬姛缁撴潫澶栭儴閰嶇疆鍔犺浇骞舵瀯寤洪厤缃爲锛屽垯杩斿洖 true锛屽惁鍒欒繑鍥 false銆 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庣粨鏉熷閮ㄩ厤缃姞杞借繃绋嬨傚畠鍒涘缓澶栭儴閰嶇疆鏍戝璞★紝骞朵娇鐢ㄥ凡瑙f瀽鐨勯儴鍒嗘瀯寤洪厤缃爲銆 + * 濡傛灉鎴愬姛鏋勫缓閰嶇疆鏍戯紝鍒欒繑鍥 true锛屽惁鍒欒繑鍥 false銆傚鏋滄瀯寤哄け璐ワ紝瀹冧細璁板綍閿欒娑堟伅骞舵竻鐞嗗凡鍒涘缓鐨勬爲瀵硅薄銆 + */ bool ExtConfigLoader::EndExtConfigLoad() { bool result = false; + + // 鍒涘缓澶栭儴閰嶇疆鏍戝璞 m_extConfigTree = ConfigTree::CreateConfigTree(GetPriority(), GetName(), false); if (m_extConfigTree != nullptr) { + + // 浣跨敤宸茶В鏋愮殑閮ㄥ垎鏋勫缓閰嶇疆鏍 result = m_extConfigTree->Build(m_parsedSections); if (!result) { MOT_REPORT_ERROR(MOT_ERROR_INTERNAL, "Load Configuration", "Failed to build external configuration tree"); @@ -182,13 +224,24 @@ bool ExtConfigLoader::EndExtConfigLoad() return result; } +/* + * 鍔熻兘锛氭竻鐞嗗閮ㄩ厤缃姞杞藉櫒鐨勭姸鎬 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庢竻鐞嗗閮ㄩ厤缃姞杞藉櫒鐨勭姸鎬併傚畠娓呯┖浜 `m_sectionMap` 鍜 `m_parsedSections`锛 + * 骞跺湪闇瑕佹椂鍒犻櫎澶栭儴閰嶇疆鏍戝璞 `m_extConfigTree`銆 + */ void ExtConfigLoader::Cleanup() noexcept { - m_sectionMap.clear(); - m_parsedSections.clear(); + // 娓呯┖澶栭儴閰嶇疆鍔犺浇鍣ㄧ殑鐘舵 + m_sectionMap.clear(); // 娓呯┖閰嶇疆鑺傛槧灏 + m_parsedSections.clear(); // 娓呯┖宸茶В鏋愮殑閰嶇疆鑺傚垪琛 + + // 鍒犻櫎澶栭儴閰嶇疆鏍戝璞 if (m_extConfigTree != nullptr) { - delete m_extConfigTree; - m_extConfigTree = nullptr; + delete m_extConfigTree; // 鍒犻櫎閰嶇疆鏍 + m_extConfigTree = nullptr; // 灏嗛厤缃爲鎸囬拡缃负绌烘寚閽 } } + } // namespace MOT diff --git a/src/gausskernel/storage/mot/core/infra/config/file_line_reader.cpp b/src/gausskernel/storage/mot/core/infra/config/file_line_reader.cpp index a6325f19f..32e583c6a 100644 --- a/src/gausskernel/storage/mot/core/infra/config/file_line_reader.cpp +++ b/src/gausskernel/storage/mot/core/infra/config/file_line_reader.cpp @@ -25,26 +25,41 @@ #include "file_line_reader.h" namespace MOT { -FileLineReader::FileLineReader(const char* configFilePath) - : m_configFilePath(configFilePath), m_configFile(configFilePath), m_lineItr(NULL), m_lineNumber(0) +/* + * 鏋勯犲嚱鏁帮細鍒涘缓 FileLineReader 瀵硅薄骞惰В鏋愰厤缃枃浠 + * + * @param configFilePath 閰嶇疆鏂囦欢鐨勮矾寰 + */ +FileLineReader::FileLineReader(const char *configFilePath) + : m_configFilePath(configFilePath), // 瀛樺偍閰嶇疆鏂囦欢璺緞 + m_configFile(configFilePath), // 閫氳繃鏂囦欢璺緞鍒涘缓閰嶇疆鏂囦欢瀵硅薄 + m_lineItr(NULL), // 灏嗚杩唬鍣ㄥ垵濮嬪寲涓 NULL + m_lineNumber(0) // 鍒濆鍖栬鍙蜂负 0 { + // 瑙f瀽閰嶇疆鏂囦欢鍐呭 ParseFile(); } FileLineReader::~FileLineReader() {} +/* + * 瑙f瀽閰嶇疆鏂囦欢鍐呭锛屽皢姣忎竴琛屽瓨鍌ㄥ埌瀹瑰櫒涓 + */ void FileLineReader::ParseFile() { if (m_configFile) { std::string line; while (std::getline(m_configFile, line)) { + // 璇诲彇閰嶇疆鏂囦欢涓殑姣忎竴琛屽苟瀛樺偍鍒 m_lines 瀹瑰櫒涓 m_lines.push_back(line.c_str()); } + // 鍒濆鍖栬杩唬鍣ㄤ负 m_lines 鐨勫紑澶达紝琛屽彿涓 1 m_lineItr = m_lines.cbegin(); m_lineNumber = 1; } else { + // 濡傛灉閰嶇疆鏂囦欢鏃犳硶鎵撳紑锛屽垯鍒濆鍖栬杩唬鍣ㄤ负 m_lines 鐨勭粨灏 m_lineItr = m_lines.cend(); } } diff --git a/src/gausskernel/storage/mot/core/infra/config/layered_config_tree.cpp b/src/gausskernel/storage/mot/core/infra/config/layered_config_tree.cpp index 28b9a54c0..a9f952874 100644 --- a/src/gausskernel/storage/mot/core/infra/config/layered_config_tree.cpp +++ b/src/gausskernel/storage/mot/core/infra/config/layered_config_tree.cpp @@ -39,7 +39,7 @@ IMPLEMENT_CLASS_LOGGER(LayeredConfigTree, Configuration) class PrintVisitor : public ConfigItemVisitor { public: /** @var The configuration list to build. */ - ConfigItemList* m_printList; + ConfigItemList *m_printList; /** @brief The set of all configuration items that were added. */ mot_set m_itemsAdded; @@ -51,7 +51,7 @@ public: * @brief Constructor. * @param printList The configuration list to build. */ - explicit PrintVisitor(ConfigItemList* printList) : m_printList(printList), m_status(true) + explicit PrintVisitor(ConfigItemList *printList) : m_printList(printList), m_status(true) {} ~PrintVisitor() override @@ -67,7 +67,7 @@ public: * @brief Adds configuration item to print list. * @param configItem The configuration item. */ - void OnConfigItem(const ConfigItem* configItem) override + void OnConfigItem(const ConfigItem *configItem) override { if (!m_status) { return; @@ -75,7 +75,7 @@ public: if (configItem->GetClass() == ConfigItemClass::CONFIG_ITEM_VALUE) { if (m_itemsAdded.find(configItem->GetFullPathName()) == m_itemsAdded.end()) { - if (!m_printList->push_back(const_cast(configItem))) { + if (!m_printList->push_back(const_cast(configItem))) { MOT_REPORT_ERROR(MOT_ERROR_INTERNAL, "Load Configuration", "Failed to add item to print list"); m_status = false; return; @@ -103,22 +103,31 @@ LayeredConfigTree::~LayeredConfigTree() { ClearConfigTrees(); } - -bool LayeredConfigTree::AddConfigTree(ConfigTree* configTree) +/* + * 鍔熻兘锛氬悜灞傛鍖栭厤缃爲涓坊鍔犻厤缃爲 + * + * 鍙傛暟鍒楄〃锛 + * configTree锛氳娣诲姞鐨勯厤缃爲鎸囬拡 + * + * 杩斿洖鍊硷細 + * 濡傛灉鎴愬姛娣诲姞閰嶇疆鏍戯紝杩斿洖 true锛涘惁鍒欒繑鍥 false銆 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庡皢閰嶇疆鏍戞坊鍔犲埌灞傛鍖栭厤缃爲涓傚畠灏嗛厤缃爲鏍规嵁鍏朵紭鍏堢骇鎻掑叆鍒伴傚綋鐨勪綅缃紝浠ョ‘淇濇寜鐓т紭鍏堢骇鎺掑簭銆 + */ +bool LayeredConfigTree::AddConfigTree(ConfigTree *configTree) { bool configTreeAdded = false; - MOT_LOG_DEBUG("Adding configuration tree %p %s with priority %d", - configTree, - configTree->GetSource(), - configTree->GetPriority()); + MOT_LOG_DEBUG("Adding configuration tree %p %s with priority %d", configTree, configTree->GetSource(), + configTree->GetPriority()); // insert sorted LayeredConfigTrees::iterator itr = m_configTrees.begin(); while (itr != m_configTrees.end()) { // check next list (get priority of first tree in the list (all trees in the list have same priority) - ConfigTreeList& configTreeList = *itr; + ConfigTreeList &configTreeList = *itr; MOT_ASSERT(!configTreeList.empty()); - ConfigTree* currConfigTree = *configTreeList.begin(); + ConfigTree *currConfigTree = *configTreeList.begin(); if (currConfigTree->GetPriority() == configTree->GetPriority()) { // matching list found, we are done configTreeAdded = AddConfigTreeToList(configTree, configTreeList); @@ -141,73 +150,121 @@ bool LayeredConfigTree::AddConfigTree(ConfigTree* configTree) return configTreeAdded; } -void LayeredConfigTree::RemoveConfigTree(ConfigTree* configTree) +/* + * 鍔熻兘锛氫粠灞傛鍖栭厤缃爲涓Щ闄ら厤缃爲 + * + * 鍙傛暟鍒楄〃锛 + * configTree锛氳绉婚櫎鐨勯厤缃爲鎸囬拡 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庝粠灞傛鍖栭厤缃爲涓Щ闄ゆ寚瀹氱殑閰嶇疆鏍戙傚畠浼氭牴鎹厤缃爲鐨勪紭鍏堢骇鍦ㄧ浉搴旂殑鍒楄〃涓煡鎵惧苟绉婚櫎銆 + */ +void LayeredConfigTree::RemoveConfigTree(ConfigTree *configTree) { int priority = 0; bool found = false; - MOT_LOG_DEBUG("Removing configuration tree %p %s with priority %d", - configTree, - configTree->GetSource(), - configTree->GetPriority()); + + // 璁板綍璋冭瘯淇℃伅锛岃〃绀烘鍦ㄧЩ闄ら厤缃爲 + MOT_LOG_DEBUG("Removing configuration tree %p %s with priority %d", configTree, configTree->GetSource(), + configTree->GetPriority()); + + // 閫愪釜妫鏌ラ厤缃爲鍒楄〃锛屾牴鎹厤缃爲鐨勪紭鍏堢骇绉婚櫎 LayeredConfigTrees::iterator itr = m_configTrees.begin(); while (itr != m_configTrees.end()) { - ConfigTreeList& configTreeList = *itr; + ConfigTreeList &configTreeList = *itr; MOT_ASSERT(!configTreeList.empty()); ConfigTreeList::iterator itr2 = std::find(configTreeList.begin(), configTreeList.end(), configTree); + if (itr2 == configTreeList.end()) { + // 閰嶇疆鏍戜笉鍦ㄥ綋鍓嶅垪琛ㄤ腑锛岀户缁煡鎵 MOT_LOG_TRACE( "Configuration tree %s not found in list priority %d in layered configuration tree (search continues)", - configTree->GetSource(), - priority); - ++itr; // keep searching - ++priority; // for debug printing + configTree->GetSource(), priority); + ++itr; // 缁х画鎼滅储 + ++priority; // 鐢ㄤ簬璋冭瘯鎵撳嵃 } else { + // 鎵惧埌閰嶇疆鏍戯紝浠庡垪琛ㄤ腑绉婚櫎 MOT_LOG_TRACE("Removing configuration tree %s from layered configuration tree", configTree->GetSource()); configTreeList.erase(itr2); + + // 濡傛灉鍒楄〃涓虹┖锛屽垯浠庡眰娆″寲閰嶇疆鏍戜腑绉婚櫎鏁翠釜鍒楄〃 if (configTreeList.empty()) { m_configTrees.erase(itr); } + found = true; - break; // stop searching + break; // 鍋滄鎼滅储 } } + if (!found) { + // 鏈壘鍒版寚瀹氱殑閰嶇疆鏍 MOT_LOG_WARN("Failed to remove configuration tree %s from layered configuration tree: not found", - configTree->GetSource()); + configTree->GetSource()); } } +/* + * 鍔熻兘锛氭墦鍗板眰娆″寲閰嶇疆鏍 + * + * 鍙傛暟鍒楄〃锛 + * logLevel锛氭墦鍗扮殑鏃ュ織绾у埆 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庝互鎸囧畾鐨勬棩蹇楃骇鍒墦鍗版暣涓眰娆″寲閰嶇疆鏍戙傚畠浼氳皟鐢 `BuildPrintList` 鍑芥暟鏋勫缓鎵撳嵃鍒楄〃锛 + * 鐒跺悗閫愪釜鎵撳嵃閰嶇疆椤广傚鏋滄瀯寤烘墦鍗板垪琛ㄥけ璐ワ紝鍑芥暟灏嗚褰曢敊璇俊鎭苟娓呴櫎閿欒鍫嗘爤銆 + */ void LayeredConfigTree::Print(LogLevel logLevel) const { MOT_LOG(logLevel, "Loaded configuration:"); + + // 濡傛灉鎵撳嵃鍒楄〃涓虹┖锛屽皾璇曟瀯寤哄畠 if (m_printList.empty()) { - if (!const_cast(this)->BuildPrintList()) { + if (!const_cast(this)->BuildPrintList()) { + // 鏋勫缓鎵撳嵃鍒楄〃澶辫触鏃惰褰曢敊璇俊鎭苟娓呴櫎閿欒鍫嗘爤 MOT_LOG_ERROR_STACK("Failed to build print list for layered configuration tree"); ClearErrorStack(); } } + + // 閬嶅巻鎵撳嵃鍒楄〃骞舵墦鍗版瘡涓厤缃」 ConfigItemList::const_iterator itr = m_printList.begin(); while (itr != m_printList.end()) { - const ConfigItem* configItem = *itr; + const ConfigItem *configItem = *itr; configItem->Print(logLevel, true); ++itr; } } -const ConfigItem* LayeredConfigTree::GetConfigItem(const char* fullPathName) const +/* + * 鍔熻兘锛氭牴鎹畬鏁磋矾寰勫悕鑾峰彇閰嶇疆椤 + * + * 鍙傛暟鍒楄〃锛 + * fullPathName锛氳鑾峰彇鐨勯厤缃」鐨勫畬鏁磋矾寰勫悕 + * + * 杩斿洖鍊硷細 + * 濡傛灉鎵惧埌鍖归厤鐨勯厤缃」锛屽垯杩斿洖璇ラ厤缃」锛涘惁鍒欒繑鍥 nullptr銆 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庡湪灞傛鍖栭厤缃爲涓煡鎵炬寚瀹氬畬鏁磋矾寰勫悕鐨勯厤缃」銆傚畠浼氫粠姣忎釜閰嶇疆鏍戜腑閫愬眰鏌ユ壘锛 + * 鐩村埌鎵惧埌鍖归厤鐨勯厤缃」鎴栨悳绱㈠畬鏁翠釜鏍戙傚鏋滄壘鍒板尮閰嶇殑閰嶇疆椤癸紝浼氬湪璋冭瘯鏃ュ織涓墦鍗颁俊鎭 + */ +const ConfigItem *LayeredConfigTree::GetConfigItem(const char *fullPathName) const { - const ConfigItem* result = nullptr; + const ConfigItem *result = nullptr; - // search item layer by layer + // 閫愬眰鎼滅储閰嶇疆椤 LayeredConfigTrees::const_iterator itr = m_configTrees.begin(); while (result == nullptr && itr != m_configTrees.end()) { - const ConfigTreeList& configTreeList = *itr; + const ConfigTreeList &configTreeList = *itr; ConfigTreeList::const_iterator itr2 = configTreeList.begin(); while (result == nullptr && itr2 != configTreeList.end()) { - const ConfigTree* configTree = *itr2; + const ConfigTree *configTree = *itr2; result = configTree->GetConfigItem(fullPathName); if (result != nullptr) { MOT_LOG_DEBUG("*** --> Found %s", fullPathName); + + // 濡傛灉鏃ュ織绾у埆涓 LL_DEBUG锛屽垯鎵撳嵃閰嶇疆椤逛俊鎭 if (MOT_CHECK_LOG_LEVEL(LogLevel::LL_DEBUG)) { result->Print(LogLevel::LL_DEBUG, true); } @@ -220,7 +277,16 @@ const ConfigItem* LayeredConfigTree::GetConfigItem(const char* fullPathName) con return result; } - +/* + * 鍔熻兘锛氭瀯寤哄眰娆″寲閰嶇疆鏍戠殑鎵撳嵃鍒楄〃 + * + * 杩斿洖鍊硷細 + * 濡傛灉鎴愬姛鏋勫缓鎵撳嵃鍒楄〃锛岃繑鍥 true锛涘惁鍒欒繑鍥 false銆 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庢瀯寤哄眰娆″寲閰嶇疆鏍戠殑鎵撳嵃鍒楄〃銆傚畠浼氶愬眰閬嶅巻姣忎釜閰嶇疆鏍戯紝灏嗛厤缃」娣诲姞鍒版墦鍗板垪琛ㄤ腑銆 + * 鍦ㄦ瀯寤鸿繃绋嬩腑锛屼娇鐢ㄩ厤缃」璁块棶鑰 PrintVisitor銆 + */ bool LayeredConfigTree::BuildPrintList() { // add configuration items layer by layer, only if not added already @@ -230,20 +296,16 @@ bool LayeredConfigTree::BuildPrintList() PrintVisitor pv(&m_printList); LayeredConfigTrees::const_iterator itr = m_configTrees.cbegin(); while (itr != m_configTrees.cend()) { - const ConfigTreeList& configTreeList = *itr; + const ConfigTreeList &configTreeList = *itr; ConfigTreeList::const_iterator itr2 = configTreeList.begin(); while (itr2 != configTreeList.end()) { - const ConfigTree* configTree = *itr2; - MOT_LOG_DEBUG("Scanning config tree %p %s with priority %d", - configTree, - configTree->GetSource(), - configTree->GetPriority()); + const ConfigTree *configTree = *itr2; + MOT_LOG_DEBUG("Scanning config tree %p %s with priority %d", configTree, configTree->GetSource(), + configTree->GetPriority()); configTree->ForEach(pv); if (!pv.GetStatus()) { - MOT_REPORT_ERROR(MOT_ERROR_INTERNAL, - "Load Configuration", - "Failed to build print list for configuration tree %s", - configTree->GetSource()); + MOT_REPORT_ERROR(MOT_ERROR_INTERNAL, "Load Configuration", + "Failed to build print list for configuration tree %s", configTree->GetSource()); return false; } ++itr2; @@ -252,16 +314,21 @@ bool LayeredConfigTree::BuildPrintList() } return true; } - +/* + * 鍔熻兘锛氭竻闄ゅ眰娆″寲閰嶇疆鏍戜腑鐨勬墍鏈夐厤缃爲 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庢竻闄ゅ眰娆″寲閰嶇疆鏍戜腑鐨勬墍鏈夐厤缃爲銆傚畠棣栧厛閬嶅巻鎵鏈夐厤缃爲锛屽垹闄ら潪闈欐侀厤缃爲锛岀劧鍚庢竻绌洪厤缃爲鍒楄〃鍜屾墦鍗板垪琛ㄣ + */ void LayeredConfigTree::ClearConfigTrees() { MOT_LOG_DEBUG("Clearing all configuration trees from layered configuration tree"); LayeredConfigTrees::iterator itr = m_configTrees.begin(); while (itr != m_configTrees.end()) { - ConfigTreeList& configTreeList = *itr; + ConfigTreeList &configTreeList = *itr; ConfigTreeList::iterator litr = configTreeList.begin(); while (litr != configTreeList.end()) { - ConfigTree* configTree = *litr; + ConfigTree *configTree = *litr; if (!configTree->IsStatic()) { MOT_LOG_DEBUG("Destroying configuration tree %p %s", configTree, configTree->GetSource()); delete configTree; @@ -274,26 +341,59 @@ void LayeredConfigTree::ClearConfigTrees() m_configTrees.clear(); m_printList.clear(); } - -bool LayeredConfigTree::AddNewConfigTreeAt(LayeredConfigTrees::iterator itr, ConfigTree* configTree) +/* + * 鍔熻兘锛氬湪鎸囧畾浣嶇疆娣诲姞鏂扮殑閰嶇疆鏍 + * + * 鍙傛暟鍒楄〃锛 + * itr锛氭寚鍚戞彃鍏ヤ綅缃殑杩唬鍣 + * configTree锛氳娣诲姞鐨勯厤缃爲鎸囬拡 + * + * 杩斿洖鍊硷細 + * 濡傛灉鎴愬姛娣诲姞閰嶇疆鏍戯紝杩斿洖 true锛涘惁鍒欒繑鍥 false銆 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庡湪鎸囧畾浣嶇疆娣诲姞鏂扮殑閰嶇疆鏍戙傚畠棣栧厛灏濊瘯灏嗘柊鐨勯厤缃爲鍒楄〃鎻掑叆鍒板眰娆″寲閰嶇疆鏍戜腑锛 + * 鐒跺悗鍦ㄩ厤缃爲鍒楄〃涓坊鍔犻厤缃爲銆傚鏋滄彃鍏ュ拰娣诲姞鎴愬姛锛屽垯杩斿洖 true銆 + */ +bool LayeredConfigTree::AddNewConfigTreeAt(LayeredConfigTrees::iterator itr, ConfigTree *configTree) { bool configTreeAdded = false; LayeredConfigTrees::pairib pb = m_configTrees.insert(itr, ConfigTreeList()); if (!pb.second) { MOT_REPORT_ERROR(MOT_ERROR_INTERNAL, "Load Configuration", "Failed to insert configuration tree list"); } else { - ConfigTreeList& configTreeList = *pb.first; + ConfigTreeList &configTreeList = *pb.first; configTreeAdded = AddConfigTreeToList(configTree, configTreeList); } return configTreeAdded; } -bool LayeredConfigTree::AddConfigTreeToList(ConfigTree* configTree, ConfigTreeList& configTreeList) +/* + * 鍔熻兘锛氬皢閰嶇疆鏍戞坊鍔犲埌閰嶇疆鏍戝垪琛ㄤ腑 + * + * 鍙傛暟鍒楄〃锛 + * configTree锛氳娣诲姞鐨勯厤缃爲鎸囬拡 + * configTreeList锛氶厤缃爲鍒楄〃锛屽皢鍦ㄥ叾涓坊鍔犻厤缃爲 + * + * 杩斿洖鍊硷細 + * 濡傛灉鎴愬姛娣诲姞閰嶇疆鏍戯紝杩斿洖 true锛涘惁鍒欒繑鍥 false銆 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庡皢閰嶇疆鏍戞坊鍔犲埌閰嶇疆鏍戝垪琛ㄤ腑銆傚畠棣栧厛灏濊瘯灏嗛厤缃爲娣诲姞鍒板垪琛ㄧ殑鏈熬锛 + * 濡傛灉娣诲姞鎴愬姛锛屽垯杩斿洖 true锛屽惁鍒欒繑鍥 false銆 + */ +bool LayeredConfigTree::AddConfigTreeToList(ConfigTree *configTree, ConfigTreeList &configTreeList) { + // 灏嗛厤缃爲娣诲姞鍒伴厤缃爲鍒楄〃鐨勬湯灏 bool configTreeAdded = configTreeList.push_back(configTree); + + // 妫鏌ユ槸鍚︽垚鍔熸坊鍔犻厤缃爲 if (!configTreeAdded) { + // 濡傛灉娣诲姞澶辫触锛屽垯鎶ュ憡鍐呴儴閿欒 MOT_REPORT_ERROR(MOT_ERROR_INTERNAL, "Load Configuration", "Failed to add configuration tree to new list"); } + return configTreeAdded; } + } // namespace MOT diff --git a/src/gausskernel/storage/mot/core/infra/config/props_config_file_loader.cpp b/src/gausskernel/storage/mot/core/infra/config/props_config_file_loader.cpp index abb8b1474..81b7e5cc0 100644 --- a/src/gausskernel/storage/mot/core/infra/config/props_config_file_loader.cpp +++ b/src/gausskernel/storage/mot/core/infra/config/props_config_file_loader.cpp @@ -29,28 +29,50 @@ namespace MOT { DECLARE_LOGGER(PropsConfigFileLoader, Configuration) - -static bool ParsePropsSectionName(const mot_string& line, mot_string& sectionPath, mot_string& keyValuePart) +/* + * 鍔熻兘锛氳В鏋愰厤缃」鐨勮妭鍚嶇О鍜岄敭鍊奸儴鍒 + * + * 鍙傛暟鍒楄〃锛 + * line锛氬寘鍚厤缃」鐨勫畬鏁磋 + * sectionPath锛氱敤浜庡瓨鍌ㄨВ鏋愬悗鐨勮妭鍚嶇О鐨勫瓧绗︿覆 + * keyValuePart锛氱敤浜庡瓨鍌ㄨВ鏋愬悗鐨勯敭鍊奸儴鍒嗙殑瀛楃涓 + * + * 杩斿洖鍊硷細 + * 濡傛灉鎴愬姛瑙f瀽閰嶇疆椤癸紝杩斿洖 true锛涘惁鍒欒繑鍥 false銆 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庤В鏋愰厤缃」鐨勮妭鍚嶇О鍜岄敭鍊奸儴鍒嗐傞厤缃」鐨勬牸寮忓簲涓衡滆妭鍚嶇О=閿尖濓紝鍏朵腑鑺傚悕绉板彲鑳藉寘鍚矾寰勪俊鎭 + * 鍑芥暟棣栧厛鏌ユ壘绛夊彿锛=锛夛紝纭繚瀹冨嚭鐜板湪璺緞鍒嗛殧绗︼紙濡傛灉鏈夌殑璇濓級涔嬪墠銆傜劧鍚庯紝瀹冨皢琛屽垎鍓蹭负鑺傚悕绉板拰閿奸儴鍒嗭紝 + * 骞跺瀹冧滑杩涜淇壀锛堝幓闄ゅ墠瀵煎拰灏鹃殢绌烘牸锛夈 + */ +static bool ParsePropsSectionName(const mot_string &line, mot_string §ionPath, mot_string &keyValuePart) { bool result = true; // since configuration value might have path names to disk, we need to make sure that section separator appears // BEFORE the equals sign + // 妫鏌ョ瓑鍙风殑浣嶇疆锛岀‘淇濈瓑鍙峰嚭鐜板湪璺緞鍒嗛殧绗︿箣鍓 uint32_t equalsPos = line.find('='); if (equalsPos == mot_string::npos) { // this is an illegal format, there must be an equals sign + // 鎶ュ憡鍐呴儴閿欒 MOT_REPORT_ERROR(MOT_ERROR_OOM, "Load Configuration", "Failed to parse section name: missing equals sign"); result = false; } else { + // 鏌ユ壘绛夊彿鍓嶇殑鏈鍚庝竴涓矾寰勫垎闅旂鐨勪綅缃 uint32_t lastSlashPos = line.find_last_of(ConfigItem::PATH_SEP, equalsPos); if (lastSlashPos != mot_string::npos) { + // 鎻愬彇鑺傚悕绉板拰閿奸儴鍒 if (!line.substr(sectionPath, 0, lastSlashPos) || !line.substr(keyValuePart, lastSlashPos + 1)) { + // 鎶ュ憡鍐呴儴閿欒 MOT_REPORT_ERROR(MOT_ERROR_OOM, "Load Configuration", "Failed to parse section name"); result = false; } else { + // 淇壀鑺傚悕绉板拰閿奸儴鍒嗭紝鍘婚櫎鍓嶅鍜屽熬闅忕┖鏍 sectionPath.trim(); keyValuePart.trim(); } } else { + // 琛屼腑娌℃湁璺緞鍒嗛殧绗︼紝灏嗚妭鍚嶇О璁剧疆涓虹┖瀛楃涓诧紝骞舵彁鍙栭敭鍊奸儴鍒 sectionPath.assign(""); keyValuePart.assign(line); keyValuePart.trim(); @@ -67,101 +89,169 @@ static bool ParsePropsSectionName(const mot_string& line, mot_string& sectionPat break; \ } -static ConfigSection* GetPropsConfigSection( - const mot_string& sectionFullName, mot_list& parsedSections, ConfigSectionMap& sectionMap) +/* + * 鍔熻兘锛氭牴鎹畬鏁寸殑鑺傚悕绉拌幏鍙栨垨鍒涘缓閰嶇疆鑺 + * + * 鍙傛暟鍒楄〃锛 + * sectionFullName锛氬畬鏁寸殑鑺傚悕绉帮紝鍖呮嫭鍙兘鐨勮矾寰 + * parsedSections锛氬瓨鍌ㄥ凡瑙f瀽鐨勯厤缃妭鐨勫垪琛 + * sectionMap锛氶厤缃妭鐨勬槧灏勶紝鐢ㄤ簬蹇熸煡鎵惧凡鍒涘缓鐨勯厤缃妭 + * + * 杩斿洖鍊硷細 + * 濡傛灉鎴愬姛鑾峰彇鎴栧垱寤洪厤缃妭锛岃繑鍥炴寚鍚戣閰嶇疆鑺傜殑鎸囬拡锛涘惁鍒欒繑鍥 nullptr銆 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁版牴鎹畬鏁寸殑鑺傚悕绉拌幏鍙栨垨鍒涘缓閰嶇疆鑺傘傚畠棣栧厛妫鏌ョ粰瀹氱殑鑺傚悕绉版槸鍚﹀凡瀛樺湪浜庨厤缃妭鏄犲皠锛坰ectionMap锛変腑锛 + * 濡傛灉宸插瓨鍦紝鍒欑洿鎺ヨ繑鍥炲凡鍒涘缓鐨勯厤缃妭銆傚鏋滆妭鍚嶇О涓嶅瓨鍦紝鍒欒В鏋愯妭鐨勮矾寰勫拰鍚嶇О锛屽垱寤烘柊鐨勯厤缃妭锛 + * 骞跺皢鍏舵坊鍔犲埌宸茶В鏋愮殑閰嶇疆鑺傚垪琛紙parsedSections锛夊拰閰嶇疆鑺傛槧灏勪腑銆傛渶鍚庯紝杩斿洖鎸囧悜鏂板垱寤烘垨宸插瓨鍦ㄧ殑閰嶇疆鑺傜殑鎸囬拡銆 + */ +static ConfigSection *GetPropsConfigSection(const mot_string §ionFullName, + mot_list &parsedSections, ConfigSectionMap §ionMap) { mot_string sectionPath; mot_string sectionName; - mot_map::iterator itr = sectionMap.find(sectionFullName); + + // 妫鏌ヨ妭鍚嶇О鏄惁宸插瓨鍦ㄤ簬閰嶇疆鑺傛槧灏勪腑 + mot_map::iterator itr = sectionMap.find(sectionFullName); if (itr == sectionMap.end()) { + // 鑺傚悕绉板皻鏈湪鏄犲皠涓壘鍒帮紝闇瑕佸垱寤烘柊鐨勯厤缃妭 if (!ConfigFileParser::BreakSectionName(sectionFullName, sectionPath, sectionName)) { + // 瑙f瀽鑺傚悕绉板け璐ワ紝鎶ュ憡鍐呴儴閿欒 MOT_REPORT_ERROR(MOT_ERROR_INTERNAL, "Load Configuration", "Failed to parse section name"); return nullptr; } - ConfigSection* currentSection = ConfigSection::CreateConfigSection(sectionPath.c_str(), sectionName.c_str()); + // 鍒涘缓鏂扮殑閰嶇疆鑺 + ConfigSection *currentSection = ConfigSection::CreateConfigSection(sectionPath.c_str(), sectionName.c_str()); if (currentSection == nullptr) { + // 鍒嗛厤閰嶇疆鑺傚唴瀛樺け璐ワ紝鎶ュ憡鍐呭瓨鍒嗛厤閿欒 MOT_REPORT_ERROR(MOT_ERROR_OOM, "Load Configuration", "Failed to allocate configuration section"); return nullptr; } + // 灏嗘柊鐨勯厤缃妭娣诲姞鍒板凡瑙f瀽鐨勯厤缃妭鍒楄〃涓 if (!parsedSections.push_back(currentSection)) { + // 娣诲姞鍒板凡瑙f瀽鐨勯厤缃妭鍒楄〃澶辫触锛屾姤鍛婂唴瀛樺垎閰嶉敊璇 MOT_REPORT_ERROR(MOT_ERROR_OOM, "Load Configuration", "Failed to add parsed section"); return nullptr; } + // 灏嗘柊鐨勯厤缃妭娣诲姞鍒伴厤缃妭鏄犲皠涓 itr = sectionMap.insert(ConfigSectionMap::value_type(sectionFullName, currentSection)).first; } + // 杩斿洖鎸囧悜鏂板垱寤烘垨宸插瓨鍦ㄧ殑閰嶇疆鑺傜殑鎸囬拡 return itr->second; } -static bool AddPropsArrayConfigItem(const char* configFilePath, const FileLineReader& reader, const mot_string& line, - ConfigSection* currentSection, const mot_string& sectionFullName, const mot_string& key, const mot_string& value, - uint64_t arrayIndex) +/* + * 鍔熻兘锛氬皢灞炴ф暟缁勯厤缃」娣诲姞鍒伴厤缃妭 + * + * 鍙傛暟鍒楄〃锛 + * configFilePath锛氶厤缃枃浠剁殑璺緞 + * reader锛氭枃浠惰璇诲彇鍣紝鐢ㄤ簬鑾峰彇褰撳墠琛屽彿 + * line锛氬寘鍚厤缃」鐨勬枃鏈 + * currentSection锛氬綋鍓嶉厤缃妭 + * sectionFullName锛氬畬鏁寸殑鑺傚悕绉帮紝鍖呮嫭鍙兘鐨勮矾寰 + * key锛氶厤缃」鐨勯敭 + * value锛氶厤缃」鐨勫 + * arrayIndex锛氶厤缃」鍦ㄦ暟缁勪腑鐨勭储寮 + * + * 杩斿洖鍊硷細 + * 濡傛灉鎴愬姛娣诲姞灞炴ф暟缁勯厤缃」锛岃繑鍥 true锛涘惁鍒欒繑鍥 false銆 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庡皢灞炴ф暟缁勯厤缃」娣诲姞鍒伴厤缃妭涓傞鍏堬紝瀹冨皾璇曡幏鍙栨垨鍒涘缓鍚嶄负 "key" 鐨勯厤缃暟缁勶紙ConfigArray锛夛紝 + * 濡傛灉璇ユ暟缁勪笉瀛樺湪锛屽垯鍒涘缓涓涓柊鐨勯厤缃暟缁勶紝骞跺皢鍏舵坊鍔犲埌褰撳墠閰嶇疆鑺備腑銆傛帴涓嬫潵锛屽畠妫鏌ユ暟缁勭殑绱㈠紩鏄惁涓 + * 棰勬湡鐨勭储寮曪紙arrayIndex锛夌浉鍖归厤锛屼互纭繚鏁扮粍椤规寜椤哄簭娣诲姞銆傜劧鍚庯紝瀹冧娇鐢ㄦ彁渚涚殑鍊煎垱寤洪厤缃」锛圕onfigItem锛夛紝 + * 骞跺皢鍏舵坊鍔犲埌閰嶇疆鏁扮粍涓傚鏋滀换浣曟楠ゅけ璐ワ紝鍑芥暟灏嗘姤鍛婇敊璇苟杩斿洖 false銆 + */ +static bool AddPropsArrayConfigItem(const char *configFilePath, const FileLineReader &reader, const mot_string &line, + ConfigSection *currentSection, const mot_string §ionFullName, + const mot_string &key, const mot_string &value, uint64_t arrayIndex) { - ConfigArray* configArray = currentSection->ModifyConfigArray(key.c_str()); + // 灏濊瘯鑾峰彇鎴栧垱寤哄悕涓 "key" 鐨勯厤缃暟缁 + ConfigArray *configArray = currentSection->ModifyConfigArray(key.c_str()); if (configArray == nullptr) { + // 閰嶇疆鏁扮粍涓嶅瓨鍦紝鍒涘缓涓涓柊鐨勯厤缃暟缁 configArray = ConfigArray::CreateConfigArray(sectionFullName.c_str(), key.c_str()); if (configArray == nullptr) { + // 鍒嗛厤閰嶇疆鏁扮粍鍐呭瓨澶辫触锛屾姤鍛婂唴瀛樺垎閰嶉敊璇 MOT_REPORT_ERROR(MOT_ERROR_OOM, "Load Configuration", "Failed to allocate configuration array"); return false; } + // 灏嗘柊鐨勯厤缃暟缁勬坊鍔犲埌褰撳墠閰嶇疆鑺備腑 if (!currentSection->AddConfigItem(configArray)) { - MOT_REPORT_ERROR( - MOT_ERROR_OOM, "Load Configuration", "Failed to add configuration array to parent section"); + // 娣诲姞閰嶇疆鏁扮粍鍒扮埗閰嶇疆鑺傚け璐ワ紝鎶ュ憡鍐呭瓨鍒嗛厤閿欒 + MOT_REPORT_ERROR(MOT_ERROR_OOM, "Load Configuration", + "Failed to add configuration array to parent section"); return false; } } + // 妫鏌ユ暟缁勯」鐨勭储寮曟槸鍚︽寜椤哄簭娣诲姞 if (arrayIndex != configArray->GetConfigItemCount()) { - // array items must be ordered - MOT_REPORT_ERROR(MOT_ERROR_INVALID_CFG, - "Load Configuration", - "Failed to parse configuration file %s at line %u: %s (array %s items not " - "well-ordered, expecting %u, got %" PRIu64 ")", - configFilePath, - reader.GetLineNumber(), - line.c_str(), - configArray->GetName(), - configArray->GetConfigItemCount(), - arrayIndex); + // 鏁扮粍椤圭殑绱㈠紩涓庨鏈熺殑绱㈠紩涓嶅尮閰嶏紝鎶ュ憡閰嶇疆鏂囦欢瑙f瀽閿欒 + MOT_REPORT_ERROR(MOT_ERROR_INVALID_CFG, "Load Configuration", + "Failed to parse configuration file %s at line %u: %s (array %s items not " + "well-ordered, expecting %u, got %" PRIu64 ")", + configFilePath, reader.GetLineNumber(), line.c_str(), configArray->GetName(), + configArray->GetConfigItemCount(), arrayIndex); return false; } - ConfigItem* configItem = ConfigFileParser::MakeArrayConfigValue(sectionFullName, arrayIndex, value); + // 浣跨敤鎻愪緵鐨勫煎垱寤洪厤缃」骞舵坊鍔犲埌閰嶇疆鏁扮粍涓 + ConfigItem *configItem = ConfigFileParser::MakeArrayConfigValue(sectionFullName, arrayIndex, value); if (configItem == nullptr) { + // 鍒涘缓閰嶇疆鏁扮粍鍊煎け璐ワ紝鎶ュ憡鍐呴儴閿欒 MOT_REPORT_ERROR(MOT_ERROR_INTERNAL, "Load Configuration", "Failed to create configuration array value"); return false; } if (!configArray->AddConfigItem(configItem)) { - MOT_REPORT_ERROR(MOT_ERROR_OOM, - "Load Configuration", - "Failed to add %" PRIu64 "th item to configuration array %s", - arrayIndex, - configArray->GetName()); + // 灏嗘暟缁勯」娣诲姞鍒伴厤缃暟缁勪腑澶辫触锛屾姤鍛婂唴瀛樺垎閰嶉敊璇 + MOT_REPORT_ERROR(MOT_ERROR_OOM, "Load Configuration", + "Failed to add %" PRIu64 "th item to configuration array %s", arrayIndex, + configArray->GetName()); return false; } return true; } - -ConfigTree* PropsConfigFileLoader::LoadConfigFile(const char* configFilePath) +/* + * 鍔熻兘锛氫粠PROPS閰嶇疆鏂囦欢鍔犺浇閰嶇疆骞舵瀯寤洪厤缃爲 + * + * 鍙傛暟鍒楄〃锛 + * configFilePath锛氳鍔犺浇鐨勯厤缃枃浠剁殑璺緞 + * + * 杩斿洖鍊硷細 + * 濡傛灉鎴愬姛鍔犺浇閰嶇疆鏂囦欢骞舵瀯寤洪厤缃爲锛岃繑鍥炰竴涓寚鍚戦厤缃爲鐨勬寚閽堬紱濡傛灉鍑虹幇閿欒锛屽垯杩斿洖nullptr銆 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁拌礋璐d粠鎸囧畾鐨凱ROPS閰嶇疆鏂囦欢涓姞杞介厤缃苟鏋勫缓閰嶇疆鏍戙傚畠棣栧厛鍒涘缓涓涓厤缃爲瀵硅薄锛岀劧鍚庨愯瑙f瀽閰嶇疆鏂囦欢锛 + * 灏嗛厤缃」娣诲姞鍒扮浉搴旂殑閰嶇疆鑺備腑銆傚鏋滈厤缃枃浠剁殑鏍煎紡涓嶆纭垨瑙f瀽杩囩▼涓彂鐢熼敊璇紝灏嗚繑鍥瀗ullptr銆傚惁鍒欙紝 + * 灏嗚繑鍥炴寚鍚戝凡鍔犺浇閰嶇疆鐨勯厤缃爲鎸囬拡銆 + */ +ConfigTree *PropsConfigFileLoader::LoadConfigFile(const char *configFilePath) { + // 璁板綍鍔犺浇 PROPS 閰嶇疆鏂囦欢鐨勮窡韪棩蹇 MOT_LOG_TRACE("Loading PROPS configuration file from: %s", configFilePath); - ConfigTree* configTree = ConfigTree::CreateConfigTree(GetPriority(), GetName(), false); + + // 鍒涘缓閰嶇疆鏍戯紝鐢ㄤ簬瀛樺偍浠庨厤缃枃浠跺姞杞界殑閰嶇疆椤 + ConfigTree *configTree = ConfigTree::CreateConfigTree(GetPriority(), GetName(), false); if (configTree == nullptr) { + // 鍐呭瓨鍒嗛厤澶辫触锛屾姤鍛婂唴瀛樺垎閰嶉敊璇 MOT_REPORT_ERROR(MOT_ERROR_OOM, "Load Configuration", "Failed to create configuration tree"); return nullptr; } + // 澹版槑涓浜涘彉閲忎互渚涘悗缁娇鐢 mot_string line; mot_string sectionFullName; mot_string keyValuePart; - ConfigSection* currentSection = nullptr; - mot_list parsedSections; + ConfigSection *currentSection = nullptr; + mot_list parsedSections; ConfigSectionMap sectionMap; mot_string key; mot_string value; @@ -169,86 +259,102 @@ ConfigTree* PropsConfigFileLoader::LoadConfigFile(const char* configFilePath) uint64_t arrayIndex = 0; bool hasArrayIndex = false; - // unsupported yet + // 鍒濆鍖栨枃浠惰璇诲彇鍣ㄤ互璇诲彇閰嶇疆鏂囦欢 + // 濡傛灉鏃犳硶鎵撳紑鏂囦欢锛屽皢鍙戝嚭璀﹀憡骞惰繑鍥炵┖鐨勯厤缃爲 FileLineReader reader(configFilePath); if (!reader.IsValid()) { MOT_LOG_WARN("Failed to load configuration file %s: unable to open file", configFilePath); - // we return an empty tree to avoid errors during startup, but a warning is still issued + // 涓轰簡閬垮厤鍦ㄥ惎鍔ㄨ繃绋嬩腑鍑虹幇閿欒锛屾垜浠繑鍥炰竴涓┖鐨勯厤缃爲锛屼絾浠嶇劧鍙戝嚭璀﹀憡 return configTree; } while (!reader.Eof() && !parseError) { - // parse next non-empty line + // 瑙f瀽涓嬩竴琛岄潪绌鸿 if (!line.assign(reader.GetLine().c_str())) { + // 鍐呭瓨鍒嗛厤澶辫触锛屾姤鍛婂唴瀛樺垎閰嶉敊璇苟涓柇瑙f瀽 PROPS_REPORT_PARSE_ERROR_AND_BREAK(MOT_ERROR_OOM, "Failed to allocate memory for next line"); } line.trim(); if (line.length() && line[0] != '#') { - // break tokens to section and key-value by last separator + // 妫鏌ヨ鏄惁涓虹┖骞朵笖涓嶆槸娉ㄩ噴琛岋紙浠 '#' 寮澶寸殑琛岋級 + + // 鍒嗚В琛屼互鑾峰彇閰嶇疆鑺傚悕绉板拰閿奸儴鍒 MOT_LOG_DEBUG("Parsing config line: %s", line.c_str()); if (!ParsePropsSectionName(line, sectionFullName, keyValuePart)) { - PROPS_REPORT_PARSE_ERROR_AND_BREAK(MOT_ERROR_INVALID_CFG, + // 閰嶇疆鏂囦欢鐨勮妭鍚嶇О琛屾牸寮忛敊璇紝鎶ュ憡閰嶇疆鏂囦欢瑙f瀽閿欒骞朵腑鏂В鏋 + PROPS_REPORT_PARSE_ERROR_AND_BREAK( + MOT_ERROR_INVALID_CFG, "Failed to parse configuration file %s at line %u: %s (section name line malformed)", - configFilePath, - reader.GetLineNumber(), - line.c_str()); + configFilePath, reader.GetLineNumber(), line.c_str()); } - // get the configuration section + // 鑾峰彇鎴栧垱寤洪厤缃妭锛圕onfigSection锛 currentSection = GetPropsConfigSection(sectionFullName, parsedSections, sectionMap); if (currentSection == nullptr) { + // 鑾峰彇鎴栧垱寤洪厤缃妭澶辫触锛屾姤鍛婂唴閮ㄩ敊璇苟涓柇瑙f瀽 PROPS_REPORT_PARSE_ERROR_AND_BREAK(MOT_ERROR_INTERNAL, "Failed to get configuration section"); } - // parse the key-value part - if (!ConfigFileParser::ParseKeyValue( - keyValuePart, sectionFullName, key, value, arrayIndex, hasArrayIndex)) { - // key-value line malformed - PROPS_REPORT_PARSE_ERROR_AND_BREAK(MOT_ERROR_INVALID_CFG, - "Failed to parse configuration file %s at line %u: %s (key/value malformed)", - configFilePath, - reader.GetLineNumber(), - line.c_str()); + // 瑙f瀽閿奸儴鍒 + if (!ConfigFileParser::ParseKeyValue(keyValuePart, sectionFullName, key, value, arrayIndex, + hasArrayIndex)) { + // 閿艰鏍煎紡閿欒锛屾姤鍛婇厤缃枃浠惰В鏋愰敊璇苟涓柇瑙f瀽 + PROPS_REPORT_PARSE_ERROR_AND_BREAK( + MOT_ERROR_INVALID_CFG, "Failed to parse configuration file %s at line %u: %s (key/value malformed)", + configFilePath, reader.GetLineNumber(), line.c_str()); } - // check for array item + // 妫鏌ユ槸鍚︿负鏁扮粍椤 if (!hasArrayIndex) { - ConfigItem* configItem = ConfigFileParser::MakeConfigValue(sectionFullName, key, value); + // 闈炴暟缁勯」 + + // 鍒涘缓閰嶇疆鍊奸」锛圕onfigItem锛夊苟灏嗗叾娣诲姞鍒板綋鍓嶉厤缃妭 + ConfigItem *configItem = ConfigFileParser::MakeConfigValue(sectionFullName, key, value); if (configItem == nullptr) { - PROPS_REPORT_PARSE_ERROR_AND_BREAK(MOT_ERROR_INTERNAL, - "Failed to parse configuration file %s at line %u: %s (invalid type specification?)", - configFilePath, - reader.GetLineNumber(), - line.c_str()); - } else if (!currentSection->AddConfigItem(configItem, true)) { + // 鍒涘缓閰嶇疆鍊奸」澶辫触锛屾姤鍛婂唴閮ㄩ敊璇苟涓柇瑙f瀽 PROPS_REPORT_PARSE_ERROR_AND_BREAK( - MOT_ERROR_OOM, "Failed to add configuration item to parent section"); + MOT_ERROR_INTERNAL, + "Failed to parse configuration file %s at line %u: %s (invalid type specification?)", + configFilePath, reader.GetLineNumber(), line.c_str()); + } else if (!currentSection->AddConfigItem(configItem, true)) { + // 灏嗛厤缃奸」娣诲姞鍒扮埗閰嶇疆鑺傚け璐ワ紝鎶ュ憡鍐呭瓨鍒嗛厤閿欒骞朵腑鏂В鏋 + PROPS_REPORT_PARSE_ERROR_AND_BREAK(MOT_ERROR_OOM, + "Failed to add configuration item to parent section"); } } else { - if (!AddPropsArrayConfigItem( - configFilePath, reader, line, currentSection, sectionFullName, key, value, arrayIndex)) { - PROPS_REPORT_PARSE_ERROR_AND_BREAK(MOT_ERROR_OOM, + // 鏁扮粍椤 + + // 娣诲姞灞炴ф暟缁勯厤缃」 + if (!AddPropsArrayConfigItem(configFilePath, reader, line, currentSection, sectionFullName, key, value, + arrayIndex)) { + // 娣诲姞灞炴ф暟缁勯厤缃」澶辫触锛屾姤鍛婂唴瀛樺垎閰嶉敊璇苟涓柇瑙f瀽 + PROPS_REPORT_PARSE_ERROR_AND_BREAK( + MOT_ERROR_OOM, "Failed to add array item with arrayIndex %lu in configuration file %s at line %u: %s", - arrayIndex, - configFilePath, - reader.GetLineNumber(), - line.c_str()); + arrayIndex, configFilePath, reader.GetLineNumber(), line.c_str()); } } } + // 璇诲彇涓嬩竴琛 reader.NextLine(); } + // 妫鏌ユ槸鍚﹀彂鐢熶簡瑙f瀽閿欒 if (parseError) { + // 瑙f瀽閿欒鍙戠敓锛岄噴鏀鹃厤缃爲鐨勫唴瀛樺苟杩斿洖绌烘寚閽 delete configTree; configTree = nullptr; } else { + // 瑙f瀽鎴愬姛锛屾瀯寤洪厤缃爲 if (!configTree->Build(parsedSections)) { + // 鏋勫缓閰嶇疆鏍戝け璐ワ紝鎶ュ憡鍐呴儴閿欒锛岄噴鏀鹃厤缃爲鐨勫唴瀛樺苟杩斿洖绌烘寚閽 MOT_REPORT_ERROR(MOT_ERROR_INTERNAL, "Load Configuration", "Failed to build configuration tree"); delete configTree; configTree = nullptr; } } + return configTree; } + } // namespace MOT diff --git a/src/gausskernel/storage/mot/core/infra/containers/bitmapset.cpp b/src/gausskernel/storage/mot/core/infra/containers/bitmapset.cpp index 684866523..b1b0e7600 100644 --- a/src/gausskernel/storage/mot/core/infra/containers/bitmapset.cpp +++ b/src/gausskernel/storage/mot/core/infra/containers/bitmapset.cpp @@ -36,16 +36,32 @@ BitmapSet::BitmapSet() Reset(); } -BitmapSet::BitmapSet(uint8_t* data, uint16_t size) : m_data(data), m_size(size), m_init(true) +BitmapSet::BitmapSet(uint8_t *data, uint16_t size) : m_data(data), m_size(size), m_init(true) {} BitmapSet::~BitmapSet() {} -void BitmapSet::Init(uint8_t* data, uint16_t size) +/* + * 鍔熻兘锛氬垵濮嬪寲浣嶅浘闆嗗悎瀵硅薄 + * + * 鍙傛暟鍒楄〃锛 + * data锛氭寚鍚戜綅鍥炬暟鎹殑鎸囬拡锛岀敤浜庡垵濮嬪寲浣嶅浘闆嗗悎 + * size锛氫綅鍥炬暟鎹殑澶у皬锛屼互瀛楄妭鏁拌〃绀 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庡垵濮嬪寲浣嶅浘闆嗗悎瀵硅薄锛岃缃綅鍥炬暟鎹拰澶у皬銆 + * 瀹冨皢杈撳叆鐨勬暟鎹拰澶у皬鍒嗛厤缁欎綅鍥鹃泦鍚堝璞$殑鎴愬憳鍙橀噺銆 + */ +void BitmapSet::Init(uint8_t *data, uint16_t size) { + // 璁剧疆浣嶅浘闆嗗悎瀵硅薄鐨勫ぇ灏忔垚鍛樺彉閲 m_size = size; + + // 璁剧疆浣嶅浘闆嗗悎瀵硅薄鐨勬暟鎹垚鍛樺彉閲 m_data = data; + + // 灏嗗垵濮嬪寲鏍囧織璁剧疆涓簍rue锛岃〃绀哄璞″凡鎴愬姛鍒濆鍖 m_init = true; } @@ -56,70 +72,196 @@ void BitmapSet::Reset() m_init = false; } +/* + * 鍔熻兘锛氶噸缃綅鍥鹃泦鍚堝璞 + * + * 鍙傛暟鍒楄〃锛 + * size锛氫綅鍥炬暟鎹殑鏂板ぇ灏忥紝浠ュ瓧鑺傛暟琛ㄧず + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庨噸缃綅鍥鹃泦鍚堝璞★紝灏嗗叾澶у皬鏇存敼涓烘柊鍊硷紝骞跺皢浣嶅浘鏁版嵁娓呴浂銆 + * 閲嶇疆鍓嶉渶瑕佺‘淇濆璞″凡鎴愬姛鍒濆鍖栵紙閫氳繃妫鏌ュ垵濮嬪寲鏍囧織锛夈 + */ void BitmapSet::Reset(uint16_t size) { + // 鏂█纭繚瀵硅薄宸叉垚鍔熷垵濮嬪寲 MOT_ASSERT(m_init); + + // 璁剧疆浣嶅浘闆嗗悎瀵硅薄鐨勫ぇ灏忔垚鍛樺彉閲忎负鏂板 m_size = size; + + // 浣跨敤 memset_s 鍑芥暟灏嗕綅鍥炬暟鎹竻闆 errno_t erc = memset_s(m_data, GetLength(), 0, GetLength()); securec_check(erc, "\0", "\0"); } +/* + * 鍔熻兘锛氭竻闄や綅鍥鹃泦鍚堝璞$殑鏁版嵁 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庡皢浣嶅浘闆嗗悎瀵硅薄鐨勬暟鎹竻闆躲 + * 鍦ㄨ皟鐢ㄦ鍑芥暟涔嬪墠锛岄渶瑕佺‘淇濆璞″凡鎴愬姛鍒濆鍖栵紙閫氳繃妫鏌ュ垵濮嬪寲鏍囧織锛夈 + */ void BitmapSet::Clear() { + // 浣跨敤 memset_s 鍑芥暟灏嗕綅鍥炬暟鎹竻闆 errno_t erc = memset_s(m_data, GetLength(), 0, GetLength()); securec_check(erc, "\0", "\0"); } +/* + * 鍔熻兘锛氭鏌ヤ綅鍥鹃泦鍚堝璞℃槸鍚﹀凡娓呴浂 + * + * 杩斿洖鍊硷細 + * 濡傛灉浣嶅浘闆嗗悎瀵硅薄宸叉竻闆讹紝鍒欒繑鍥瀟rue锛涘惁鍒欒繑鍥瀎alse銆 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庢鏌ヤ綅鍥鹃泦鍚堝璞$殑鏁版嵁鏄惁宸插畬鍏ㄦ竻闆躲 + * 鍦ㄨ皟鐢ㄦ鍑芥暟涔嬪墠锛岄渶瑕佺‘淇濆璞″凡鎴愬姛鍒濆鍖栵紙閫氳繃妫鏌ュ垵濮嬪寲鏍囧織锛夈 + */ bool BitmapSet::IsClear() { + // 鑾峰彇浣嶅浘鏁版嵁鐨勫瓧鑺傛暟 uint16_t numBytes = GetLength(); - for (uint16_t i = 0; i < numBytes; i++) + + // 閬嶅巻浣嶅浘鏁版嵁锛屾鏌ユ槸鍚︽湁闈為浂瀛楄妭 + for (uint16_t i = 0; i < numBytes; i++) { if (m_data[i] != 0) { return false; } + } + + // 濡傛灉鎵鏈夊瓧鑺傞兘涓洪浂锛岃繑鍥瀟rue锛岃〃绀哄凡娓呴浂 return true; } +/* + * 鍔熻兘锛氳缃綅鍥鹃泦鍚堝璞′腑鎸囧畾浣嶇殑鍊间负1 + * + * 鍙傛暟鍒楄〃锛 + * bit锛氳璁剧疆鐨勪綅鐨勭储寮 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庡皢浣嶅浘闆嗗悎瀵硅薄涓寚瀹氫綅鐨勫艰缃负1銆 + * 鍦ㄨ皟鐢ㄦ鍑芥暟涔嬪墠锛岄渶瑕佺‘淇濆璞″凡鎴愬姛鍒濆鍖栵紙閫氳繃妫鏌ュ垵濮嬪寲鏍囧織锛夈 + * 杩橀渶瑕佺‘淇濅紶閫掔粰鍑芥暟鐨勪綅绱㈠紩锛坆it锛夊皬浜庝綅鍥鹃泦鍚堝璞$殑澶у皬銆 + */ void BitmapSet::SetBit(uint16_t bit) { + // 浣跨敤鏂█纭繚浣嶇储寮曚笉瓒呭嚭浣嶅浘闆嗗悎瀵硅薄鐨勫ぇ灏 MOT_ASSERT(bit < m_size); + + // 璁$畻瀛楄妭绱㈠紩骞跺湪鐩稿簲瀛楄妭涓婅缃寚瀹氫綅 m_data[GetByteIndex(bit)] |= (1 << (bit & 0x07)); } +/* + * 鍔熻兘锛氬皢浣嶅浘闆嗗悎瀵硅薄涓寚瀹氫綅鐨勫艰缃负0 + * + * 鍙傛暟鍒楄〃锛 + * bit锛氳鍙栨秷璁剧疆鐨勪綅鐨勭储寮 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庡皢浣嶅浘闆嗗悎瀵硅薄涓寚瀹氫綅鐨勫艰缃负0銆 + * 鍦ㄨ皟鐢ㄦ鍑芥暟涔嬪墠锛岄渶瑕佺‘淇濆璞″凡鎴愬姛鍒濆鍖栵紙閫氳繃妫鏌ュ垵濮嬪寲鏍囧織锛夈 + * 杩橀渶瑕佺‘淇濅紶閫掔粰鍑芥暟鐨勪綅绱㈠紩锛坆it锛夊皬浜庝綅鍥鹃泦鍚堝璞$殑澶у皬銆 + */ void BitmapSet::UnsetBit(uint16_t bit) { + // 浣跨敤鏂█纭繚浣嶇储寮曚笉瓒呭嚭浣嶅浘闆嗗悎瀵硅薄鐨勫ぇ灏 MOT_ASSERT(bit < m_size); + + // 璁$畻瀛楄妭绱㈠紩骞跺湪鐩稿簲瀛楄妭涓婂彇娑堣缃寚瀹氫綅 m_data[GetByteIndex(bit)] &= ~(1 << (bit & 0x07)); } +/* + * 鍔熻兘锛氳幏鍙栦綅鍥鹃泦鍚堝璞′腑鎸囧畾浣嶇殑鍊 + * + * 鍙傛暟鍒楄〃锛 + * bit锛氳鑾峰彇鐨勪綅鐨勭储寮 + * + * 杩斿洖鍊硷細 + * 濡傛灉浣嶇殑鍊间负1锛屽垯杩斿洖1锛涘惁鍒欒繑鍥0銆 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庝粠浣嶅浘闆嗗悎瀵硅薄涓幏鍙栨寚瀹氫綅鐨勫笺 + * 鍦ㄨ皟鐢ㄦ鍑芥暟涔嬪墠锛岄渶瑕佺‘淇濆璞″凡鎴愬姛鍒濆鍖栵紙閫氳繃妫鏌ュ垵濮嬪寲鏍囧織锛夈 + * 杩橀渶瑕佺‘淇濅紶閫掔粰鍑芥暟鐨勪綅绱㈠紩锛坆it锛夊皬浜庝綅鍥鹃泦鍚堝璞$殑澶у皬銆 + */ uint8_t BitmapSet::GetBit(uint16_t bit) { + // 浣跨敤鏂█纭繚浣嶇储寮曚笉瓒呭嚭浣嶅浘闆嗗悎瀵硅薄鐨勫ぇ灏 MOT_ASSERT(bit < m_size); + + // 鑾峰彇鎸囧畾浣嶇殑鍊煎苟杩斿洖锛堝鏋滀綅鐨勫间负1锛屽垯杩斿洖1锛涘惁鍒欒繑鍥0锛 return (m_data[GetByteIndex(bit)] & (1 << (bit & 0x07))) != 0; } +/* + * 鍔熻兘锛氳绠楁寚瀹氫綅鐨勫瓧鑺傜储寮 + * + * 鍙傛暟鍒楄〃锛 + * bit锛氳璁$畻瀛楄妭绱㈠紩鐨勪綅鐨勭储寮 + * + * 杩斿洖鍊硷細 + * 杩斿洖浣嶇储寮曞搴旂殑瀛楄妭绱㈠紩銆 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庤绠椾綅鍥鹃泦鍚堝璞′腑鎸囧畾浣嶇殑瀛楄妭绱㈠紩銆 + * 浣嶇储寮曪紙bit锛夐氬父鐢ㄤ簬琛ㄧず鍦ㄤ綅鍥句腑鐨勬煇涓浣嶏紝鑰屽瓧鑺傜储寮曡〃绀鸿繖涓浣嶅湪瀛楄妭鏁扮粍涓殑浣嶇疆銆 + */ uint16_t BitmapSet::GetByteIndex(uint16_t bit) { + // 璁$畻浣嶇储寮曞搴旂殑瀛楄妭绱㈠紩锛屽苟杩斿洖 return (bit >> 3); } +/* + * 鍔熻兘锛氭寜浣嶆垨杩愮畻绗︼紙|=锛夐噸杞藉嚱鏁 + * + * 鍙傛暟鍒楄〃锛 + * bitmapSet锛氳涓庡綋鍓嶄綅鍥鹃泦鍚堝璞℃墽琛屾寜浣嶆垨杩愮畻鐨勫彟涓涓綅鍥鹃泦鍚堝璞 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庨噸杞芥寜浣嶆垨杩愮畻绗︼紙|=锛夛紝鐢ㄤ簬鎵ц涓や釜浣嶅浘闆嗗悎瀵硅薄涔嬮棿鐨勬寜浣嶆垨杩愮畻銆 + * 瀹冨皢褰撳墠浣嶅浘闆嗗悎瀵硅薄鐨勬瘡涓瓧鑺備笌鍙︿竴涓綅鍥鹃泦鍚堝璞$殑鐩稿簲瀛楄妭鎵ц鎸変綅鎴栬繍绠楋紝骞跺皢缁撴灉瀛樺偍鍦ㄥ綋鍓嶄綅鍥鹃泦鍚堝璞′腑銆 + * 鍦ㄦ墽琛屾鎿嶄綔涔嬪墠锛岄渶瑕佺‘淇濅袱涓綅鍥鹃泦鍚堝璞$殑澶у皬鐩稿悓銆 + */ void BitmapSet::operator|=(BitmapSet bitmapSet) { + // 鑾峰彇浣嶅浘闆嗗悎瀵硅薄鐨勫ぇ灏 uint16_t length = GetLength(); + + // 閬嶅巻姣忎釜瀛楄妭骞舵墽琛屾寜浣嶆垨杩愮畻 for (uint16_t i = 0; i < length; i++) { m_data[i] |= bitmapSet.m_data[i]; } } +/* + * 鍔熻兘锛氭寜浣嶄笌杩愮畻绗︼紙&=锛夐噸杞藉嚱鏁 + * + * 鍙傛暟鍒楄〃锛 + * bitmapSet锛氳涓庡綋鍓嶄綅鍥鹃泦鍚堝璞℃墽琛屾寜浣嶄笌杩愮畻鐨勫彟涓涓綅鍥鹃泦鍚堝璞 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庨噸杞芥寜浣嶄笌杩愮畻绗︼紙&=锛夛紝鐢ㄤ簬鎵ц涓や釜浣嶅浘闆嗗悎瀵硅薄涔嬮棿鐨勬寜浣嶄笌杩愮畻銆 + * 瀹冨皢褰撳墠浣嶅浘闆嗗悎瀵硅薄鐨勬瘡涓瓧鑺備笌鍙︿竴涓綅鍥鹃泦鍚堝璞$殑鐩稿簲瀛楄妭鎵ц鎸変綅涓庤繍绠楋紝骞跺皢缁撴灉瀛樺偍鍦ㄥ綋鍓嶄綅鍥鹃泦鍚堝璞′腑銆 + * 鍦ㄦ墽琛屾鎿嶄綔涔嬪墠锛岄渶瑕佺‘淇濅袱涓綅鍥鹃泦鍚堝璞$殑澶у皬鐩稿悓銆 + */ void BitmapSet::operator&=(BitmapSet bitmapSet) { + // 鑾峰彇浣嶅浘闆嗗悎瀵硅薄鐨勫ぇ灏 uint16_t length = GetLength(); + + // 閬嶅巻姣忎釜瀛楄妭骞舵墽琛屾寜浣嶄笌杩愮畻 for (uint16_t i = 0; i < length; i++) { m_data[i] &= bitmapSet.m_data[i]; } } -BitmapSet::BitmapSetIterator::BitmapSetIterator(const BitmapSet& bitmapSet) +BitmapSet::BitmapSetIterator::BitmapSetIterator(const BitmapSet &bitmapSet) : m_bms(&bitmapSet), m_data(m_bms->m_data), m_bitIndex(-1), m_byteCache(0), m_isSetCache(false) { Next(); @@ -139,20 +281,40 @@ bool BitmapSet::BitmapSetIterator::End() const return m_bitIndex >= m_bms->m_size; } +/* + * 鍔熻兘锛氳幏鍙栦笅涓涓缃綅鐨勮凯浠e櫒 + * + * 杩斿洖鍊硷細 + * 濡傛灉瀛樺湪涓嬩竴涓缃綅锛屽垯杩斿洖true锛涘惁鍒欒繑鍥瀎alse銆 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜 BitmapSet 瀵硅薄鐨勮凯浠e櫒锛岀敤浜庢煡鎵句笅涓涓缃綅銆 + * 杩唬鍣ㄤ細閫掑浣嶇储寮曪紝骞跺湪浣嶅浘涓煡鎵句笅涓涓缃綅鐨勪綅缃 + * 濡傛灉鎵惧埌涓嬩竴涓缃綅锛屽皢鍏剁姸鎬佸瓨鍌ㄥ湪杩唬鍣ㄧ殑缂撳瓨涓紝浠ヤ究鍚庣画鑾峰彇銆 + */ bool BitmapSet::BitmapSetIterator::Next() { + // 閫掑浣嶇储寮 m_bitIndex++; + + // 濡傛灉浣嶇储寮曡秴鍑轰綅鍥鹃泦鍚堝璞$殑澶у皬锛屽垯杩斿洖false if (m_bitIndex >= m_bms->m_size) { return false; } + // 濡傛灉褰撳墠浣嶇储寮曟槸瀛楄妭杈圭晫锛屽垯鏇存柊瀛楄妭缂撳瓨 if (m_bitIndex % SIZE_OF_BYTE == 0) { m_byteCache = m_data[GetByteIndex(m_bitIndex)]; } else { + // 鍚﹀垯鍙崇Щ瀛楄妭缂撳瓨涓浣 m_byteCache = m_byteCache >> 1; } + // 鏇存柊璁剧疆浣嶇紦瀛 m_isSetCache = (m_byteCache & 1) != 0; + + // 杩斿洖true琛ㄧず鎵惧埌涓嬩竴涓缃綅 return true; } + } // namespace MOT diff --git a/src/gausskernel/storage/mot/core/infra/stats/boolean_statistic_variable.cpp b/src/gausskernel/storage/mot/core/infra/stats/boolean_statistic_variable.cpp index 5d8897c2f..afa9a5fe5 100644 --- a/src/gausskernel/storage/mot/core/infra/stats/boolean_statistic_variable.cpp +++ b/src/gausskernel/storage/mot/core/infra/stats/boolean_statistic_variable.cpp @@ -28,42 +28,127 @@ #include namespace MOT { +/* + * 鍔熻兘锛氬甯冨皵缁熻鍙橀噺杩涜鎬荤粨 + * + * 鍙傛暟鍒楄〃锛 + * updateTstamp锛氫竴涓竷灏斿硷紝鎸囩ず鏄惁搴旇鏇存柊鏃堕棿鎴筹紙鍙夛級 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庡甯冨皵缁熻鍙橀噺杩涜鎬荤粨銆傚畠浼氳绠楃櫨鍒嗘瘮锛屽苟鍙夊湴鏇存柊鏃堕棿鎴充俊鎭 + * 鐧惧垎姣旇绠楁柟寮忎负 m_sum 闄や互 m_countSaved锛屽苟灏嗙粨鏋滀繚瀛樺湪 m_percentage 涓 + * 姝や唬鐮佷笉鍏紝缂哄皯涓庡弬鏁扮浉鍏崇殑鎿嶄綔銆 + */ void BooleanStatisticVariable::Summarize(bool updateTstamp) { + // 灏嗗綋鍓嶇殑 m_count 鍊间繚瀛樺埌 m_countSaved 涓 m_countSaved = m_count; + + // 璁$畻 m_percentage锛堢櫨鍒嗘瘮锛夛細灏 m_sum 杞崲涓 double 绫诲瀷骞堕櫎浠 m_countSaved m_percentage = ((double)m_sum) / ((double)m_countSaved); } +/* + * 鍔熻兘锛氫互鎸囧畾鐨勬棩蹇楃骇鍒墦鍗板竷灏旂粺璁″彉閲忕殑鎽樿淇℃伅 + * + * 鍙傛暟鍒楄〃锛 + * logLevel锛氳浣跨敤鐨勬棩蹇楃骇鍒紙渚嬪锛欼NFO銆丏EBUG銆丒RROR 绛夛級 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庢墦鍗板竷灏旂粺璁″彉閲忕殑鎽樿淇℃伅鍒版棩蹇椾腑銆傛憳瑕佸寘鎷彉閲忓悕绉般佹牱鏈暟銆佺櫨鍒嗘瘮銆 + * 鎵撳嵃鐨勪俊鎭牸寮忎负 "鍙橀噺鍚={ samples: 鏍锋湰鏁, percent: 鐧惧垎姣%}"銆 + */ void BooleanStatisticVariable::Print(LogLevel logLevel) const { + // 浣跨敤MOT_LOG瀹忎互鎸囧畾鐨勬棩蹇楃骇鍒墦鍗板竷灏旂粺璁″彉閲忕殑鎽樿淇℃伅 MOT_LOG(logLevel, "%s={ samples: %" PRIu64 ", percent: %0.4f%%}", m_name, m_countSaved, m_percentage * 100.0f); } -void BooleanStatisticVariable::Assign(const StatisticVariable& rhs) +/* + * 鍔熻兘锛氬皢甯冨皵缁熻鍙橀噺鐨勫间粠鍙︿竴涓粺璁″彉閲忓鍒跺埌褰撳墠鍙橀噺 + * + * 鍙傛暟鍒楄〃锛 + * rhs锛氳澶嶅埗鏁版嵁鐨勬簮缁熻鍙橀噺瀵硅薄 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庡皢甯冨皵缁熻鍙橀噺鐨勫间粠鍙︿竴涓粺璁″彉閲忓璞″鍒跺埌褰撳墠鍙橀噺瀵硅薄銆 + * 璇ュ嚱鏁板湪杩涜澶嶅埗鎿嶄綔涔嬪墠锛屽皢婧愬璞¤浆鎹负甯冨皵缁熻鍙橀噺绫诲瀷銆 + */ +void BooleanStatisticVariable::Assign(const StatisticVariable &rhs) { - const BooleanStatisticVariable& boolRhs = static_cast(rhs); + // 灏嗘簮缁熻鍙橀噺瀵硅薄杞崲涓哄竷灏旂粺璁″彉閲忕被鍨 + const BooleanStatisticVariable &boolRhs = static_cast(rhs); + + // 灏嗘簮缁熻鍙橀噺瀵硅薄鐨 m_sum 澶嶅埗鍒板綋鍓嶅璞$殑 m_sum m_sum = boolRhs.m_sum; + + // 灏嗘簮缁熻鍙橀噺瀵硅薄鐨 m_count 澶嶅埗鍒板綋鍓嶅璞$殑 m_count m_count = boolRhs.m_count; } -void BooleanStatisticVariable::Add(const StatisticVariable& rhs) +/* + * 鍔熻兘锛氬皢鍙︿竴涓竷灏旂粺璁″彉閲忕殑鍊兼坊鍔犲埌褰撳墠缁熻鍙橀噺鐨勫间笂 + * + * 鍙傛暟鍒楄〃锛 + * rhs锛氳娣诲姞鐨勬簮缁熻鍙橀噺瀵硅薄 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庡皢鍙︿竴涓竷灏旂粺璁″彉閲忕殑鍊硷紙鍖呮嫭 m_sum 鍜 m_count锛夋坊鍔犲埌褰撳墠缁熻鍙橀噺鐨勫间笂銆 + * 璇ュ嚱鏁板湪杩涜娣诲姞鎿嶄綔涔嬪墠锛屽皢婧愬璞¤浆鎹负甯冨皵缁熻鍙橀噺绫诲瀷銆 + */ +void BooleanStatisticVariable::Add(const StatisticVariable &rhs) { - const BooleanStatisticVariable& boolRhs = static_cast(rhs); + // 灏嗘簮缁熻鍙橀噺瀵硅薄杞崲涓哄竷灏旂粺璁″彉閲忕被鍨 + const BooleanStatisticVariable &boolRhs = static_cast(rhs); + + // 灏嗘簮缁熻鍙橀噺瀵硅薄鐨 m_sum 娣诲姞鍒板綋鍓嶅璞$殑 m_sum m_sum += boolRhs.m_sum; + + // 灏嗘簮缁熻鍙橀噺瀵硅薄鐨 m_count 娣诲姞鍒板綋鍓嶅璞$殑 m_count m_count += boolRhs.m_count; } -void BooleanStatisticVariable::Subtract(const StatisticVariable& rhs) +/* + * 鍔熻兘锛氫粠褰撳墠甯冨皵缁熻鍙橀噺鐨勫间腑鍑忓幓鍙︿竴涓竷灏旂粺璁″彉閲忕殑鍊 + * + * 鍙傛暟鍒楄〃锛 + * rhs锛氳浠庝腑鍑忓幓鐨勬簮缁熻鍙橀噺瀵硅薄 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庝粠褰撳墠甯冨皵缁熻鍙橀噺鐨勫间腑鍑忓幓鍙︿竴涓竷灏旂粺璁″彉閲忕殑鍊硷紙鍖呮嫭 m_sum 鍜 m_count锛夈 + * 璇ュ嚱鏁板湪杩涜鍑忔硶鎿嶄綔涔嬪墠锛屽皢婧愬璞¤浆鎹负甯冨皵缁熻鍙橀噺绫诲瀷銆 + */ +void BooleanStatisticVariable::Subtract(const StatisticVariable &rhs) { - const BooleanStatisticVariable& boolRhs = static_cast(rhs); + // 灏嗘簮缁熻鍙橀噺瀵硅薄杞崲涓哄竷灏旂粺璁″彉閲忕被鍨 + const BooleanStatisticVariable &boolRhs = static_cast(rhs); + + // 浠庡綋鍓嶅璞$殑 m_sum 涓噺鍘绘簮缁熻鍙橀噺瀵硅薄鐨 m_sum m_sum -= boolRhs.m_sum; + + // 浠庡綋鍓嶅璞$殑 m_count 涓噺鍘绘簮缁熻鍙橀噺瀵硅薄鐨 m_count m_count -= boolRhs.m_count; } +/* + * 鍔熻兘锛氬皢褰撳墠甯冨皵缁熻鍙橀噺鐨勫奸櫎浠ョ粰瀹氱殑鍥犲瓙 + * + * 鍙傛暟鍒楄〃锛 + * factor锛氶櫎鏁帮紝鐢ㄤ簬灏嗗綋鍓嶇粺璁″彉閲忕殑鍊奸櫎浠ュ畠 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庡皢褰撳墠甯冨皵缁熻鍙橀噺鐨勫奸櫎浠ョ粰瀹氱殑鍥犲瓙锛堝鏋滃洜瀛愬ぇ浜0锛夈 + * 瀹冨皢 m_count 鍜 m_sum 鎴愬憳鍙橀噺閮介櫎浠ュ洜瀛愶紝浠ユ洿鏂扮粺璁″笺 + * 濡傛灉鍥犲瓙涓0鎴栬礋鏁帮紝鍑芥暟涓嶆墽琛屼换浣曟搷浣溿 + */ void BooleanStatisticVariable::Divide(uint32_t factor) { + // 妫鏌ュ洜瀛愭槸鍚﹀ぇ浜0 if (factor > 0) { + // 灏嗗綋鍓嶅璞$殑 m_count 闄や互鍥犲瓙 m_count /= factor; + + // 灏嗗綋鍓嶅璞$殑 m_sum 闄や互鍥犲瓙 m_sum /= factor; } } diff --git a/src/gausskernel/storage/mot/core/infra/stats/frequency_statistic_variable.cpp b/src/gausskernel/storage/mot/core/infra/stats/frequency_statistic_variable.cpp index 4c5f5ab94..0aa73d690 100644 --- a/src/gausskernel/storage/mot/core/infra/stats/frequency_statistic_variable.cpp +++ b/src/gausskernel/storage/mot/core/infra/stats/frequency_statistic_variable.cpp @@ -29,52 +29,133 @@ #include "utilities.h" namespace MOT { +/* + * 鍔熻兘锛氳绠楅鐜囩粺璁″彉閲忕殑鎽樿淇℃伅 + * + * 鍙傛暟鍒楄〃锛 + * updateTstamp锛氫竴涓竷灏斿硷紝鎸囩ず鏄惁搴旇鏇存柊鏃堕棿鎴筹紙鍙夛級 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庤绠楅鐜囩粺璁″彉閲忕殑鎽樿淇℃伅锛屽寘鎷绠楅鐜囧煎拰鏃堕棿闂撮殧銆 + * 濡傛灉 updateTstamp 鍙傛暟涓 true锛屽垯鑾峰彇褰撳墠CPU鍛ㄦ湡璁℃暟浣滀负鏃堕棿鎴炽 + * 棰戠巼璁$畻鏂瑰紡涓哄皢鏍锋湰鏁 m_countSaved 闄や互鏃堕棿闂撮殧 m_intervalSeconds銆 + */ void FrequencyStatisticVariable::Summarize(bool updateTstamp) { + // 濡傛灉闇瑕佹洿鏂版椂闂存埑锛屽垯鑾峰彇褰撳墠CPU鍛ㄦ湡璁℃暟 if (updateTstamp) { m_tstamp = CpuCyclesLevelTime::Rdtscp(); } + // 灏嗗綋鍓嶇殑 m_count 鍊间繚瀛樺埌 m_countSaved 涓 m_countSaved = m_count; + // 璁$畻鏃堕棿闂撮殧锛堢锛夛細灏嗗綋鍓嶆椂闂存埑鍑忓幓鍒濆鏃堕棿鎴筹紝骞跺皢CPU鍛ㄦ湡杞崲涓虹 m_intervalSeconds = CpuCyclesLevelTime::CyclesToSeconds(m_tstamp - m_initTstamp); + // 璁$畻棰戠巼锛圚z锛夛細灏 m_countSaved 闄や互鏃堕棿闂撮殧 m_frequency = ((double)(m_countSaved)) / m_intervalSeconds; } - +/* + * 鍔熻兘锛氫互鎸囧畾鐨勬棩蹇楃骇鍒墦鍗伴鐜囩粺璁″彉閲忕殑鎽樿淇℃伅 + * + * 鍙傛暟鍒楄〃锛 + * logLevel锛氳浣跨敤鐨勬棩蹇楃骇鍒紙渚嬪锛欼NFO銆丏EBUG銆丒RROR 绛夛級 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庝互鎸囧畾鐨勬棩蹇楃骇鍒墦鍗伴鐜囩粺璁″彉閲忕殑鎽樿淇℃伅鍒版棩蹇椾腑銆 + * 鎽樿鍖呮嫭鍙橀噺鍚嶇О銆佹牱鏈暟銆佹椂闂撮棿闅斻侀鐜囧笺 + * 鎵撳嵃鐨勪俊鎭牸寮忎负 "鍙橀噺鍚={ samples: 鏍锋湰鏁, interval: 鏃堕棿闂撮殧 seconds, frequency: 棰戠巼 (evt/sec) }"銆 + */ void FrequencyStatisticVariable::Print(LogLevel logLevel) const { - MOT_LOG(logLevel, - "%s={ samples: %" PRIu64 ", interval: %0.2f seconds, frequency: %0.4f (evt/sec) }", - m_name, - m_countSaved, - m_intervalSeconds, - m_frequency); + // 浣跨敤MOT_LOG瀹忎互鎸囧畾鐨勬棩蹇楃骇鍒墦鍗伴鐜囩粺璁″彉閲忕殑鎽樿淇℃伅 + MOT_LOG(logLevel, "%s={ samples: %" PRIu64 ", interval: %0.2f seconds, frequency: %0.4f (evt/sec) }", + m_name, // 鍙橀噺鍚 + m_countSaved, // 鏍锋湰鏁 + m_intervalSeconds, // 鏃堕棿闂撮殧锛堢锛 + m_frequency // 棰戠巼锛堜簨浠/绉掞級 + ); } -void FrequencyStatisticVariable::Assign(const StatisticVariable& rhs) +/* + * 鍔熻兘锛氬皢棰戠巼缁熻鍙橀噺鐨勫间粠鍙︿竴涓粺璁″彉閲忓鍒跺埌褰撳墠鍙橀噺 + * + * 鍙傛暟鍒楄〃锛 + * rhs锛氳澶嶅埗鏁版嵁鐨勬簮缁熻鍙橀噺瀵硅薄 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庡皢棰戠巼缁熻鍙橀噺鐨勫间粠鍙︿竴涓粺璁″彉閲忓璞″鍒跺埌褰撳墠鍙橀噺瀵硅薄銆 + * 璇ュ嚱鏁板湪杩涜澶嶅埗鎿嶄綔涔嬪墠锛屽皢婧愬璞¤浆鎹负棰戠巼缁熻鍙橀噺绫诲瀷銆 + */ +void FrequencyStatisticVariable::Assign(const StatisticVariable &rhs) { - const FrequencyStatisticVariable& freqRhs = static_cast(rhs); + // 灏嗘簮缁熻鍙橀噺瀵硅薄杞崲涓洪鐜囩粺璁″彉閲忕被鍨 + const FrequencyStatisticVariable &freqRhs = static_cast(rhs); + + // 灏嗘簮缁熻鍙橀噺瀵硅薄鐨 m_count 澶嶅埗鍒板綋鍓嶅璞$殑 m_count m_count = freqRhs.m_count; + + // 灏嗘簮缁熻鍙橀噺瀵硅薄鐨 m_initTstamp 澶嶅埗鍒板綋鍓嶅璞$殑 m_initTstamp m_initTstamp = freqRhs.m_initTstamp; + + // 灏嗘簮缁熻鍙橀噺瀵硅薄鐨 m_tstamp 澶嶅埗鍒板綋鍓嶅璞$殑 m_tstamp m_tstamp = freqRhs.m_tstamp; + + // 灏嗘簮缁熻鍙橀噺瀵硅薄鐨 m_frequency 澶嶅埗鍒板綋鍓嶅璞$殑 m_frequency m_frequency = freqRhs.m_frequency; } -void FrequencyStatisticVariable::Add(const StatisticVariable& rhs) +/* + * 鍔熻兘锛氬皢鍙︿竴涓鐜囩粺璁″彉閲忕殑鍊兼坊鍔犲埌褰撳墠缁熻鍙橀噺鐨勫间笂 + * + * 鍙傛暟鍒楄〃锛 + * rhs锛氳娣诲姞鐨勬簮缁熻鍙橀噺瀵硅薄 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庡皢鍙︿竴涓鐜囩粺璁″彉閲忕殑鍊硷紙鍖呮嫭 m_count 鍜 m_frequency锛夋坊鍔犲埌褰撳墠缁熻鍙橀噺鐨勫间笂銆 + * 濡傛灉婧愬璞$殑 m_initTstamp 鏇存棭锛屽畠浼氭洿鏂板綋鍓嶅璞$殑 m_initTstamp銆 + * 濡傛灉婧愬璞$殑 m_tstamp 鏇存櫄锛屽畠浼氭洿鏂板綋鍓嶅璞$殑 m_tstamp銆 + */ +void FrequencyStatisticVariable::Add(const StatisticVariable &rhs) { - const FrequencyStatisticVariable& freqRhs = static_cast(rhs); + // 灏嗘簮缁熻鍙橀噺瀵硅薄杞崲涓洪鐜囩粺璁″彉閲忕被鍨 + const FrequencyStatisticVariable &freqRhs = static_cast(rhs); + + // 灏嗘簮缁熻鍙橀噺瀵硅薄鐨 m_count 娣诲姞鍒板綋鍓嶅璞$殑 m_count m_count += freqRhs.m_count; + + // 灏嗘簮缁熻鍙橀噺瀵硅薄鐨 m_frequency 娣诲姞鍒板綋鍓嶅璞$殑 m_frequency m_frequency += freqRhs.m_frequency; + + // 濡傛灉婧愮粺璁″彉閲忓璞$殑 m_initTstamp 鏇存棭锛屾洿鏂板綋鍓嶅璞$殑 m_initTstamp if ((m_initTstamp == 0) || ((freqRhs.m_initTstamp > 0) && (freqRhs.m_initTstamp < m_initTstamp))) { m_initTstamp = freqRhs.m_initTstamp; } + + // 濡傛灉婧愮粺璁″彉閲忓璞$殑 m_tstamp 鏇存櫄锛屾洿鏂板綋鍓嶅璞$殑 m_tstamp if (freqRhs.m_tstamp > m_tstamp) { m_tstamp = freqRhs.m_tstamp; } } -void FrequencyStatisticVariable::Subtract(const StatisticVariable& rhs) +/* + * 鍔熻兘锛氫粠褰撳墠棰戠巼缁熻鍙橀噺鐨勫间腑鍑忓幓鍙︿竴涓鐜囩粺璁″彉閲忕殑鍊 + * + * 鍙傛暟鍒楄〃锛 + * rhs锛氳浠庝腑鍑忓幓鐨勬簮缁熻鍙橀噺瀵硅薄 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庝粠褰撳墠棰戠巼缁熻鍙橀噺鐨勫间腑鍑忓幓鍙︿竴涓鐜囩粺璁″彉閲忕殑鍊硷紙鍖呮嫭 m_count锛夈 + * 濡傛灉婧愬璞$殑 m_tstamp 涓嶄负闆讹紝鍒欏皢鍏跺艰祴缁欏綋鍓嶅璞$殑 m_initTstamp銆 + * 璇锋敞鎰忥紝姝ゆ搷浣滃悗闇瑕佽皟鐢 Summarize 鍑芥暟浠ラ噸鏂拌绠楅鐜囥 + */ +void FrequencyStatisticVariable::Subtract(const StatisticVariable &rhs) { - const FrequencyStatisticVariable& freqRhs = static_cast(rhs); + // 灏嗘簮缁熻鍙橀噺瀵硅薄杞崲涓洪鐜囩粺璁″彉閲忕被鍨 + const FrequencyStatisticVariable &freqRhs = static_cast(rhs); + + // 浠庡綋鍓嶅璞$殑 m_count 鍑忓幓婧愮粺璁″彉閲忓璞$殑 m_count m_count -= freqRhs.m_count; + + // 濡傛灉婧愮粺璁″彉閲忓璞$殑 m_tstamp 涓嶄负闆讹紝灏嗗叾鍊艰祴缁欏綋鍓嶅璞$殑 m_initTstamp if (freqRhs.m_tstamp != 0) { m_initTstamp = freqRhs.m_tstamp; } diff --git a/src/gausskernel/storage/mot/core/infra/stats/global_statistics.cpp b/src/gausskernel/storage/mot/core/infra/stats/global_statistics.cpp index f3d62069c..1de1bdb37 100644 --- a/src/gausskernel/storage/mot/core/infra/stats/global_statistics.cpp +++ b/src/gausskernel/storage/mot/core/infra/stats/global_statistics.cpp @@ -27,22 +27,51 @@ namespace MOT { DECLARE_LOGGER(GlobalStatistics, Statistics) +/* + * 鍔熻兘锛氭眹鎬诲叏灞缁熻鏁版嵁 + * + * 鍙傛暟鍒楄〃锛 + * updateTstamp锛氫竴涓竷灏斿硷紝鎸囩ず鏄惁搴旇鏇存柊鏃堕棿鎴筹紙鍙夛級 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庢眹鎬诲叏灞缁熻鏁版嵁锛岄亶鍘嗘墍鏈夌粺璁″彉閲忓璞″苟璋冪敤瀹冧滑鐨 Summarize 鍑芥暟銆 + * 濡傛灉 updateTstamp 鍙傛暟涓 true锛屽垯浼氬皢鏇存柊鏃堕棿鎴崇殑璇锋眰浼犻掔粰鍚勪釜缁熻鍙橀噺銆 + */ void GlobalStatistics::Summarize(bool updateTstamp) { + // 鑾峰彇褰撳墠缁熻鍙橀噺鐨勬暟閲 uint32_t statCount = m_statVars.size(); + + // 閬嶅巻鎵鏈夌粺璁″彉閲忓苟璋冪敤鍏 Summarize 鍑芥暟 for (uint32_t i = 0; i < statCount; ++i) { m_statVars[i]->Summarize(updateTstamp); } } +/* + * 鍔熻兘锛氭墦鍗板叏灞缁熻鏁版嵁 + * + * 鍙傛暟鍒楄〃锛 + * statId锛氳鎵撳嵃鐨勭壒瀹氱粺璁″彉閲忕殑绱㈠紩锛堝彲閫夛級 + * logLevel锛氳浣跨敤鐨勬棩蹇楃骇鍒紙渚嬪锛欼NFO銆丏EBUG銆丒RROR 绛夛級 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庢墦鍗板叏灞缁熻鏁版嵁锛屽彲浠ラ夋嫨鎵撳嵃鐗瑰畾绱㈠紩鐨勭粺璁″彉閲忔垨鎵撳嵃鎵鏈夌粺璁″彉閲忋 + * 濡傛灉鎻愪緵 statId 鍙傛暟锛屽垯浠呮墦鍗版寚瀹氱储寮曠殑缁熻鍙橀噺锛堝鏋滃叾鏍锋湰鏁板ぇ浜0锛夈 + * 鍚﹀垯锛屽皢閬嶅巻鎵鏈夌粺璁″彉閲忓苟鎵撳嵃鏍锋湰鏁板ぇ浜0鐨勭粺璁″彉閲忋 + */ void GlobalStatistics::Print(uint32_t statId, LogLevel logLevel) const { + // 鑾峰彇褰撳墠缁熻鍙橀噺鐨勬暟閲 uint32_t statCount = m_statVars.size(); + + // 濡傛灉鎻愪緵 statId 鍙傛暟锛屽垯浠呮墦鍗版寚瀹氱储寮曠殑缁熻鍙橀噺锛堝鏋滃叾鏍锋湰鏁板ぇ浜0锛 if (statId < statCount) { if (m_statVars[statId]->GetSampleCount() > 0) { m_statVars[statId]->Print(logLevel); } } else { + // 鍚﹀垯锛岄亶鍘嗘墍鏈夌粺璁″彉閲忓苟鎵撳嵃鏍锋湰鏁板ぇ浜0鐨勭粺璁″彉閲 for (uint32_t i = 0; i < statCount; ++i) { if (m_statVars[i]->GetSampleCount() > 0) { m_statVars[i]->Print(logLevel); @@ -51,47 +80,117 @@ void GlobalStatistics::Print(uint32_t statId, LogLevel logLevel) const } } +/* + * 鍔熻兘锛氶噸缃叏灞缁熻鏁版嵁 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庨噸缃叏灞缁熻鏁版嵁锛屽畠浼氶亶鍘嗘墍鏈夌粺璁″彉閲忓璞″苟璋冪敤瀹冧滑鐨 Reset 鍑芥暟銆 + * 璋冪敤 Reset 鍑芥暟灏嗘竻闄ゆ墍鏈夌粺璁″彉閲忕殑璁℃暟鍜屾憳瑕佷俊鎭紝灏嗗畠浠噸缃负鍒濆鐘舵併 + */ void GlobalStatistics::Reset() { + // 鑾峰彇褰撳墠缁熻鍙橀噺鐨勬暟閲 uint32_t statCount = m_statVars.size(); + + // 閬嶅巻鎵鏈夌粺璁″彉閲忓苟璋冪敤鍏 Reset 鍑芥暟 for (uint32_t i = 0; i < statCount; ++i) { m_statVars[i]->Reset(); } } -void GlobalStatistics::Assign(const GlobalStatistics& rhs) +/* + * 鍔熻兘锛氬皢鍙︿竴涓叏灞缁熻瀵硅薄鐨勫煎垎閰嶇粰褰撳墠鍏ㄥ眬缁熻瀵硅薄 + * + * 鍙傛暟鍒楄〃锛 + * rhs锛氳浠庝腑澶嶅埗鏁版嵁鐨勬簮鍏ㄥ眬缁熻瀵硅薄 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庡皢鍙︿竴涓叏灞缁熻瀵硅薄鐨勫煎垎閰嶇粰褰撳墠鍏ㄥ眬缁熻瀵硅薄銆 + * 瀹冧細閬嶅巻鎵鏈夌粺璁″彉閲忓璞★紝骞惰皟鐢ㄥ畠浠殑 Assign 鍑芥暟浠ュ畬鎴愬垎閰嶆搷浣溿 + */ +void GlobalStatistics::Assign(const GlobalStatistics &rhs) { + // 鑾峰彇褰撳墠缁熻鍙橀噺鐨勬暟閲 uint32_t statCount = m_statVars.size(); + + // 閬嶅巻鎵鏈夌粺璁″彉閲忓苟璋冪敤鍏 Assign 鍑芥暟浠ュ畬鎴愬垎閰嶆搷浣 for (uint32_t i = 0; i < statCount; ++i) { m_statVars[i]->Assign(*rhs.m_statVars[i]); } } -void GlobalStatistics::Subtract(const GlobalStatistics& rhs) +/* + * 鍔熻兘锛氫粠褰撳墠鍏ㄥ眬缁熻瀵硅薄鐨勫间腑鍑忓幓鍙︿竴涓叏灞缁熻瀵硅薄鐨勫 + * + * 鍙傛暟鍒楄〃锛 + * rhs锛氳浠庝腑鍑忓幓鐨勬簮鍏ㄥ眬缁熻瀵硅薄 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庝粠褰撳墠鍏ㄥ眬缁熻瀵硅薄鐨勫间腑鍑忓幓鍙︿竴涓叏灞缁熻瀵硅薄鐨勫笺 + * 瀹冧細閬嶅巻鎵鏈夌粺璁″彉閲忓璞★紝骞惰皟鐢ㄥ畠浠殑 Subtract 鍑芥暟浠ュ畬鎴愬噺娉曟搷浣溿 + */ +void GlobalStatistics::Subtract(const GlobalStatistics &rhs) { + // 鑾峰彇褰撳墠缁熻鍙橀噺鐨勬暟閲 uint32_t statCount = m_statVars.size(); + + // 閬嶅巻鎵鏈夌粺璁″彉閲忓苟璋冪敤鍏 Subtract 鍑芥暟浠ュ畬鎴愬噺娉曟搷浣 for (uint32_t i = 0; i < statCount; ++i) { m_statVars[i]->Subtract(*rhs.m_statVars[i]); } } +/* + * 鍔熻兘锛氭鏌ユ槸鍚﹀瓨鍦ㄦ湁鏁堢殑鍏ㄥ眬缁熻鏍锋湰 + * + * 杩斿洖鍊硷細 + * 濡傛灉瀛樺湪鑷冲皯涓涓叿鏈夋湁鏁堟牱鏈殑鍏ㄥ眬缁熻鍙橀噺锛岃繑鍥 true锛涘惁鍒欒繑鍥 false銆 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庢鏌ユ槸鍚﹀瓨鍦ㄨ嚦灏戜竴涓叿鏈夋湁鏁堟牱鏈殑鍏ㄥ眬缁熻鍙橀噺銆 + * 瀹冧細閬嶅巻鎵鏈夌粺璁″彉閲忓璞★紝骞舵鏌ュ叾鏍锋湰鏁版槸鍚﹀ぇ浜0銆 + */ bool GlobalStatistics::HasValidSamples() const { + // 鍒濆鍖栫粨鏋滀负 false bool result = false; + + // 鑾峰彇褰撳墠缁熻鍙橀噺鐨勬暟閲 uint32_t statCount = m_statVars.size(); + + // 閬嶅巻鎵鏈夌粺璁″彉閲忓苟妫鏌ュ叾鏍锋湰鏁版槸鍚﹀ぇ浜0 for (uint32_t i = 0; i < statCount; ++i) { if (m_statVars[i]->GetSampleCount() > 0) { + // 濡傛灉鎵惧埌鑷冲皯涓涓叿鏈夋湁鏁堟牱鏈殑缁熻鍙橀噺锛屽皢缁撴灉璁句负 true 骞堕鍑哄惊鐜 result = true; break; } } + + // 杩斿洖缁撴灉 return result; } -mot_string GlobalStatistics::MakeName(const char* baseName, NamingScheme namingScheme) +/* + * 鍔熻兘锛氱敓鎴愬叏灞缁熻鍚嶇О + * + * 鍙傛暟鍒楄〃锛 + * baseName锛氬熀纭鍚嶇О锛岀敤浣滅敓鎴愬叏灞缁熻鍚嶇О鐨勫墠缂 + * namingScheme锛氬懡鍚嶆柟妗堬紝鎸囧畾鐢熸垚鍏ㄥ眬缁熻鍚嶇О鐨勬柟寮 + * + * 杩斿洖鍊硷細 + * 杩斿洖鐢熸垚鐨勫叏灞缁熻鍚嶇О銆 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庣敓鎴愬叏灞缁熻鍚嶇О锛屾牴鎹寚瀹氱殑鍛藉悕鏂规鐢熸垚鍚嶇О鐨勫悗缂銆 + * 鍩虹鍚嶇О baseName 鐢ㄤ綔鐢熸垚鍏ㄥ眬缁熻鍚嶇О鐨勫墠缂锛屾牴鎹笉鍚岀殑鍛藉悕鏂规娣诲姞涓嶅悓鐨勫悗缂銆 + */ +mot_string GlobalStatistics::MakeName(const char *baseName, NamingScheme namingScheme) { + // 鍒濆鍖栫粨鏋滃瓧绗︿覆 mot_string result; + // 鏍规嵁鍛藉悕鏂规鐢熸垚鍏ㄥ眬缁熻鍚嶇О if ((namingScheme == NamingScheme::NAMING_SCHEME_TOTAL) || (namingScheme == NamingScheme::NAMING_SCHEME_TOTAL_PREV)) { result.format("%s[TOTAL]", baseName); @@ -99,14 +198,28 @@ mot_string GlobalStatistics::MakeName(const char* baseName, NamingScheme namingS result.format("%s[DIFF]", baseName); } + // 杩斿洖鐢熸垚鐨勫叏灞缁熻鍚嶇О return result; } -void GlobalStatistics::RegisterStatistics(StatisticVariable* statVar) +/* + * 鍔熻兘锛氭敞鍐屽叏灞缁熻鍙橀噺 + * + * 鍙傛暟鍒楄〃锛 + * statVar锛氳娉ㄥ唽鐨勫叏灞缁熻鍙橀噺瀵硅薄鐨勬寚閽 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庢敞鍐屽叏灞缁熻鍙橀噺銆傚畠灏嗙粰瀹氱殑缁熻鍙橀噺瀵硅薄鎸囬拡娣诲姞鍒扮粺璁″彉閲忓垪琛ㄤ腑銆 + * 濡傛灉鏃犳硶娣诲姞缁熻鍙橀噺锛堢敱浜庡唴瀛樹笉瓒筹級锛屽皢鐢熸垚閿欒鏃ュ織銆 + */ +void GlobalStatistics::RegisterStatistics(StatisticVariable *statVar) { + // 灏嗙粰瀹氱殑缁熻鍙橀噺瀵硅薄鎸囬拡娣诲姞鍒扮粺璁″彉閲忓垪琛ㄤ腑 if (!m_statVars.push_back(statVar)) { - MOT_REPORT_ERROR( - MOT_ERROR_OOM, "Register Statistics", "Failed to register statistics variable %s", statVar->GetName()); + // 濡傛灉鏃犳硶娣诲姞缁熻鍙橀噺锛堢敱浜庡唴瀛樹笉瓒筹級锛岀敓鎴愰敊璇棩蹇 + MOT_REPORT_ERROR(MOT_ERROR_OOM, "Register Statistics", "Failed to register statistics variable %s", + statVar->GetName()); } } + } // namespace MOT diff --git a/src/gausskernel/storage/mot/core/infra/stats/level_statistic_variable.cpp b/src/gausskernel/storage/mot/core/infra/stats/level_statistic_variable.cpp index 637573810..f85c46f22 100644 --- a/src/gausskernel/storage/mot/core/infra/stats/level_statistic_variable.cpp +++ b/src/gausskernel/storage/mot/core/infra/stats/level_statistic_variable.cpp @@ -27,33 +27,69 @@ #include "level_statistic_variable.h" namespace MOT { +/* + * 鍔熻兘锛氭眹鎬荤骇鍒粺璁℃暟鎹 + * + * 鍙傛暟鍒楄〃锛 + * updateTstamp锛氫竴涓竷灏斿硷紝鎸囩ず鏄惁搴旇鏇存柊鏃堕棿鎴筹紙鍙夛級 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庢眹鎬荤骇鍒粺璁℃暟鎹紝瀹冧細鏍规嵁鎸囧畾鐨勫懡鍚嶆柟妗堢敓鎴愬悕绉扮殑鍚庣紑銆 + * 濡傛灉鎻愪緵 updateTstamp 鍙傛暟骞惰缃负 true锛屽垯浼氭洿鏂版椂闂存埑銆 + * 姹囨昏繃绋嬪寘鎷繚瀛樿鏁般佺骇鍒拰宄板硷紝璁$畻骞冲潎鍊煎拰璁$畻鏃堕棿闂撮殧銆 + */ void LevelStatisticVariable::Summarize(bool updateTstamp) { + // 濡傛灉鎻愪緵 updateTstamp 鍙傛暟骞惰缃负 true锛屽垯鏇存柊鏃堕棿鎴 if (updateTstamp) { m_tstamp = CpuCyclesLevelTime::Rdtscp(); } + + // 淇濆瓨璁℃暟銆佺骇鍒拰宄板 m_countSaved = m_count; m_levelSaved = m_level; m_peakSaved = m_peak; + + // 璁$畻骞冲潎鍊 m_avg = ((double)m_integral) / ((double)(m_tstamp - m_initTstamp)); + + // 璁$畻鏃堕棿闂撮殧 m_intervalSeconds = CpuCyclesLevelTime::CyclesToSeconds(m_tstamp - m_initTstamp); } +/* + * 鍔熻兘锛氭墦鍗扮骇鍒粺璁℃暟鎹 + * + * 鍙傛暟鍒楄〃锛 + * logLevel锛氳浣跨敤鐨勬棩蹇楃骇鍒紙渚嬪锛欼NFO銆丏EBUG銆丒RROR 绛夛級 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庢墦鍗扮骇鍒粺璁℃暟鎹紝鍖呮嫭褰撳墠绾у埆銆佸嘲鍊煎拰鏍锋湰鏁伴噺銆 + * 鎵撳嵃鐨勪俊鎭寘鎷粺璁″彉閲忕殑鍚嶇О銆佸綋鍓嶇骇鍒佸嘲鍊笺佸崟浣嶅拰鏍锋湰鏁伴噺銆 + */ void LevelStatisticVariable::Print(LogLevel logLevel) const { - MOT_LOG(logLevel, - "%s={ current level: %" PRId64 " %s, peak: %" PRIu64 " %s [%" PRIu64 " samples] }", - m_name, - m_levelSaved / m_factor, - m_units, - m_peakSaved / m_factor, - m_units, - m_countSaved); + // 浣跨敤鎸囧畾鐨勬棩蹇楃骇鍒墦鍗扮骇鍒粺璁℃暟鎹 + MOT_LOG(logLevel, "%s={ current level: %" PRId64 " %s, peak: %" PRIu64 " %s [%" PRIu64 " samples] }", m_name, + m_levelSaved / m_factor, m_units, m_peakSaved / m_factor, m_units, m_countSaved); } -void LevelStatisticVariable::Assign(const StatisticVariable& rhs) +/* + * 鍔熻兘锛氬皢鍙︿竴涓骇鍒粺璁″彉閲忕殑鍊煎垎閰嶇粰褰撳墠绾у埆缁熻鍙橀噺 + * + * 鍙傛暟鍒楄〃锛 + * rhs锛氳浠庝腑澶嶅埗鏁版嵁鐨勬簮绾у埆缁熻鍙橀噺 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庡皢鍙︿竴涓骇鍒粺璁″彉閲忕殑鍊煎垎閰嶇粰褰撳墠绾у埆缁熻鍙橀噺銆 + * 瀹冨皢婧愮骇鍒粺璁″彉閲忕殑鍚勪釜灞炴у煎鍒跺埌褰撳墠绾у埆缁熻鍙橀噺銆 + */ +void LevelStatisticVariable::Assign(const StatisticVariable &rhs) { - const LevelStatisticVariable& levelRhs = static_cast(rhs); + // 灏嗘簮绾у埆缁熻鍙橀噺寮哄埗杞崲涓 LevelStatisticVariable 绫诲瀷 + const LevelStatisticVariable &levelRhs = static_cast(rhs); + + // 澶嶅埗婧愮骇鍒粺璁″彉閲忕殑鍚勪釜灞炴у煎埌褰撳墠绾у埆缁熻鍙橀噺 m_level = levelRhs.m_level; m_peak = levelRhs.m_peak; m_tstamp = levelRhs.m_tstamp; @@ -62,33 +98,80 @@ void LevelStatisticVariable::Assign(const StatisticVariable& rhs) m_count = levelRhs.m_count; } -void LevelStatisticVariable::Add(const StatisticVariable& rhs) +/* + * 鍔熻兘锛氬皢鍙︿竴涓骇鍒粺璁″彉閲忕殑鍊兼坊鍔犲埌褰撳墠绾у埆缁熻鍙橀噺 + * + * 鍙傛暟鍒楄〃锛 + * rhs锛氳娣诲姞鍊肩殑婧愮骇鍒粺璁″彉閲 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庡皢鍙︿竴涓骇鍒粺璁″彉閲忕殑鍊兼坊鍔犲埌褰撳墠绾у埆缁熻鍙橀噺銆 + * 瀹冧細閫愪釜灞炴ц繘琛岀浉鍔狅紝骞跺湪蹇呰鏃舵洿鏂版椂闂存埑銆 + */ +void LevelStatisticVariable::Add(const StatisticVariable &rhs) { - const LevelStatisticVariable& levelRhs = static_cast(rhs); + // 灏嗘簮绾у埆缁熻鍙橀噺寮哄埗杞崲涓 LevelStatisticVariable 绫诲瀷 + const LevelStatisticVariable &levelRhs = static_cast(rhs); + + // 閫愪釜灞炴ц繘琛岀浉鍔 m_level += levelRhs.m_level; m_peak += levelRhs.m_peak; + + // 濡傛灉婧愮骇鍒粺璁″彉閲忕殑鏃堕棿鎴冲ぇ浜庡綋鍓嶇骇鍒粺璁″彉閲忕殑鏃堕棿鎴筹紝鍒欐洿鏂版椂闂存埑 if (levelRhs.m_tstamp > m_tstamp) { m_tstamp = levelRhs.m_tstamp; } + + // 濡傛灉婧愮骇鍒粺璁″彉閲忕殑鍒濆鏃堕棿鎴冲皬浜庡綋鍓嶇骇鍒粺璁″彉閲忕殑鍒濆鏃堕棿鎴筹紝鍒欐洿鏂板垵濮嬫椂闂存埑 if (levelRhs.m_initTstamp < m_initTstamp) { m_initTstamp = levelRhs.m_initTstamp; } + + // 閫愪釜灞炴ц繘琛岀浉鍔 m_integral += levelRhs.m_integral; m_count += levelRhs.m_count; } -void LevelStatisticVariable::Subtract(const StatisticVariable& rhs) +/* + * 鍔熻兘锛氫粠褰撳墠绾у埆缁熻鍙橀噺涓噺鍘诲彟涓涓骇鍒粺璁″彉閲忕殑鍊 + * + * 鍙傛暟鍒楄〃锛 + * rhs锛氳浠庝腑鍑忓幓鍊肩殑婧愮骇鍒粺璁″彉閲 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庝粠褰撳墠绾у埆缁熻鍙橀噺涓噺鍘诲彟涓涓骇鍒粺璁″彉閲忕殑鍊笺 + * 瀹冧細浠庡綋鍓嶇骇鍒粺璁″彉閲忕殑灞炴т腑鍑忓幓婧愮骇鍒粺璁″彉閲忕殑灞炴у硷紝 + * 浣嗕笉浼氬噺鍘荤骇鍒睘鎬э紝鍥犱负鍗充娇鍦ㄥ懆鏈熸у樊寮傛姤鍛婁腑锛屾垜浠粛鐒跺笇鏈涙樉绀哄綋鍓嶇骇鍒 + * 姝ゅ锛屽嘲鍊兼棤娉曞湪鏃堕棿闂撮殧鍐呮帹鏂紝闄ら潪鎴戜滑涓诲姩缁存姢瀹冦 + */ +void LevelStatisticVariable::Subtract(const StatisticVariable &rhs) { - const LevelStatisticVariable& levelRhs = static_cast(rhs); + // 灏嗘簮绾у埆缁熻鍙橀噺寮哄埗杞崲涓 LevelStatisticVariable 绫诲瀷 + const LevelStatisticVariable &levelRhs = static_cast(rhs); + + // 鏇存柊褰撳墠绾у埆缁熻鍙橀噺鐨勫垵濮嬫椂闂存埑 m_initTstamp = levelRhs.m_tstamp; + + // 浠庡綋鍓嶇骇鍒粺璁″彉閲忕殑灞炴т腑鍑忓幓婧愮骇鍒粺璁″彉閲忕殑灞炴у m_integral -= levelRhs.m_integral; m_count -= levelRhs.m_count; // we do not subtract level, since even in periodic diff report we would like to show current level // in addition, peak cannot be inferred within interval, unless we actively maintain it } +/* + * 鍔熻兘锛氬皢褰撳墠绾у埆缁熻鍙橀噺鐨勫奸櫎浠ユ寚瀹氬洜瀛 + * + * 鍙傛暟鍒楄〃锛 + * factor锛氳闄や互鐨勫洜瀛愬 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庡皢褰撳墠绾у埆缁熻鍙橀噺鐨勫睘鎬у奸櫎浠ユ寚瀹氱殑鍥犲瓙銆 + * 瀹冧細瀵硅鏁般佺骇鍒拰绉垎灞炴ц繘琛岄櫎娉曡繍绠楋紝鍓嶆彁鏄洜瀛愬ぇ浜庨浂銆 + */ void LevelStatisticVariable::Divide(uint32_t factor) { + // 濡傛灉鍥犲瓙澶т簬闆讹紝鍒欏皢褰撳墠绾у埆缁熻鍙橀噺鐨勫睘鎬у奸櫎浠ユ寚瀹氱殑鍥犲瓙 if (factor > 0) { m_count /= factor; m_level /= factor; diff --git a/src/gausskernel/storage/mot/core/infra/stats/memory_statistic_variable.cpp b/src/gausskernel/storage/mot/core/infra/stats/memory_statistic_variable.cpp index ee60df4ab..7698f3b4b 100644 --- a/src/gausskernel/storage/mot/core/infra/stats/memory_statistic_variable.cpp +++ b/src/gausskernel/storage/mot/core/infra/stats/memory_statistic_variable.cpp @@ -25,39 +25,117 @@ #include "memory_statistic_variable.h" namespace MOT { +/* + * 鍔熻兘锛氭墦鍗板唴瀛樼粺璁″彉閲忕殑淇℃伅 + * + * 鍙傛暟鍒楄〃锛 + * logLevel锛氳浣跨敤鐨勬棩蹇楃骇鍒紙渚嬪锛欼NFO銆丏EBUG銆丒RROR 绛夛級 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庢墦鍗板唴瀛樼粺璁″彉閲忕殑淇℃伅锛屽寘鎷唴瀛樼骇鍒拰鍐呭瓨閫熺巼銆 + * 瀹冧細鍒嗗埆鎵撳嵃鍐呭瓨绾у埆鍜屽唴瀛橀熺巼鐨勪俊鎭紝浣跨敤鎸囧畾鐨勬棩蹇楃骇鍒 + */ void MemoryStatisticVariable::Print(LogLevel logLevel) const { + // 鎵撳嵃鍐呭瓨绾у埆鐨勪俊鎭 m_level.Print(logLevel); + + // 鎵撳嵃鍐呭瓨閫熺巼鐨勪俊鎭 m_rate.Print(logLevel); } -void MemoryStatisticVariable::Assign(const StatisticVariable& rhs) +/* + * 鍔熻兘锛氬皢鍙︿竴涓唴瀛樼粺璁″彉閲忕殑鍊煎垎閰嶇粰褰撳墠鍐呭瓨缁熻鍙橀噺 + * + * 鍙傛暟鍒楄〃锛 + * rhs锛氳浠庝腑澶嶅埗鏁版嵁鐨勬簮鍐呭瓨缁熻鍙橀噺 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庡皢鍙︿竴涓唴瀛樼粺璁″彉閲忕殑鍊煎垎閰嶇粰褰撳墠鍐呭瓨缁熻鍙橀噺銆 + * 瀹冧細鍒嗗埆澶嶅埗璁℃暟銆佸唴瀛樼骇鍒拰鍐呭瓨閫熺巼鐨勫睘鎬у笺 + */ +void MemoryStatisticVariable::Assign(const StatisticVariable &rhs) { - const MemoryStatisticVariable& memRhs = (const MemoryStatisticVariable&)rhs; + // 灏嗘簮鍐呭瓨缁熻鍙橀噺寮哄埗杞崲涓 MemoryStatisticVariable 绫诲瀷 + const MemoryStatisticVariable &memRhs = (const MemoryStatisticVariable &)rhs; + + // 澶嶅埗璁℃暟灞炴у m_count = memRhs.m_count; + + // 璋冪敤 MemoryLevelStatisticVariable 瀵硅薄鐨 Assign 鍑芥暟锛屽鍒跺唴瀛樼骇鍒睘鎬у m_level.Assign(memRhs.m_level); + + // 璋冪敤 MemoryRateStatisticVariable 瀵硅薄鐨 Assign 鍑芥暟锛屽鍒跺唴瀛橀熺巼灞炴у m_rate.Assign(memRhs.m_rate); } -void MemoryStatisticVariable::Add(const StatisticVariable& rhs) +/* + * 鍔熻兘锛氬皢鍙︿竴涓唴瀛樼粺璁″彉閲忕殑鍊兼坊鍔犲埌褰撳墠鍐呭瓨缁熻鍙橀噺 + * + * 鍙傛暟鍒楄〃锛 + * rhs锛氳娣诲姞鍊肩殑婧愬唴瀛樼粺璁″彉閲 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庡皢鍙︿竴涓唴瀛樼粺璁″彉閲忕殑鍊兼坊鍔犲埌褰撳墠鍐呭瓨缁熻鍙橀噺銆 + * 瀹冧細鍒嗗埆瀵硅鏁般佸唴瀛樼骇鍒拰鍐呭瓨閫熺巼灞炴ц繘琛岀浉鍔犳搷浣溿 + */ +void MemoryStatisticVariable::Add(const StatisticVariable &rhs) { - const MemoryStatisticVariable& memRhs = (const MemoryStatisticVariable&)rhs; + // 灏嗘簮鍐呭瓨缁熻鍙橀噺寮哄埗杞崲涓 MemoryStatisticVariable 绫诲瀷 + const MemoryStatisticVariable &memRhs = (const MemoryStatisticVariable &)rhs; + + // 瀵硅鏁板睘鎬ц繘琛岀浉鍔犳搷浣 m_count += memRhs.m_count; + + // 璋冪敤 MemoryLevelStatisticVariable 瀵硅薄鐨 Add 鍑芥暟锛屽鍐呭瓨绾у埆灞炴ц繘琛岀浉鍔犳搷浣 m_level.Add(memRhs.m_level); + + // 璋冪敤 MemoryRateStatisticVariable 瀵硅薄鐨 Add 鍑芥暟锛屽鍐呭瓨閫熺巼灞炴ц繘琛岀浉鍔犳搷浣 m_rate.Add(memRhs.m_rate); } -void MemoryStatisticVariable::Subtract(const StatisticVariable& rhs) +/* + * 鍔熻兘锛氫粠褰撳墠鍐呭瓨缁熻鍙橀噺涓噺鍘诲彟涓涓唴瀛樼粺璁″彉閲忕殑鍊 + * + * 鍙傛暟鍒楄〃锛 + * rhs锛氳浠庝腑鍑忓幓鍊肩殑婧愬唴瀛樼粺璁″彉閲 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庝粠褰撳墠鍐呭瓨缁熻鍙橀噺涓噺鍘诲彟涓涓唴瀛樼粺璁″彉閲忕殑鍊笺 + * 瀹冧細鍒嗗埆瀵硅鏁般佸唴瀛樼骇鍒拰鍐呭瓨閫熺巼灞炴ц繘琛屽噺娉曡繍绠椼 + */ +void MemoryStatisticVariable::Subtract(const StatisticVariable &rhs) { - const MemoryStatisticVariable& memRhs = (const MemoryStatisticVariable&)rhs; + // 灏嗘簮鍐呭瓨缁熻鍙橀噺寮哄埗杞崲涓 MemoryStatisticVariable 绫诲瀷 + const MemoryStatisticVariable &memRhs = (const MemoryStatisticVariable &)rhs; + + // 瀵硅鏁板睘鎬ц繘琛屽噺娉曡繍绠 m_count -= memRhs.m_count; + + // 璋冪敤 MemoryLevelStatisticVariable 瀵硅薄鐨 Subtract 鍑芥暟锛屽鍐呭瓨绾у埆灞炴ц繘琛屽噺娉曡繍绠 m_level.Subtract(memRhs.m_level); + + // 璋冪敤 MemoryRateStatisticVariable 瀵硅薄鐨 Subtract 鍑芥暟锛屽鍐呭瓨閫熺巼灞炴ц繘琛屽噺娉曡繍绠 m_rate.Subtract(memRhs.m_rate); } +/* + * 鍔熻兘锛氬皢褰撳墠鍐呭瓨缁熻鍙橀噺鐨勫奸櫎浠ユ寚瀹氬洜瀛 + * + * 鍙傛暟鍒楄〃锛 + * factor锛氳闄や互鐨勫洜瀛愬 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庡皢褰撳墠鍐呭瓨缁熻鍙橀噺鐨勫睘鎬у奸櫎浠ユ寚瀹氱殑鍥犲瓙銆 + * 瀹冧細璋冪敤 MemoryLevelStatisticVariable 鍜 MemoryRateStatisticVariable 瀵硅薄鐨 + * Divide 鍑芥暟锛屽垎鍒鍐呭瓨绾у埆鍜屽唴瀛橀熺巼灞炴ц繘琛岄櫎娉曡繍绠椼 + */ void MemoryStatisticVariable::Divide(uint32_t factor) { + // 璋冪敤 MemoryLevelStatisticVariable 瀵硅薄鐨 Divide 鍑芥暟锛屽鍐呭瓨绾у埆灞炴ц繘琛岄櫎娉曡繍绠 m_level.Divide(factor); + + // 璋冪敤 MemoryRateStatisticVariable 瀵硅薄鐨 Divide 鍑芥暟锛屽鍐呭瓨閫熺巼灞炴ц繘琛岄櫎娉曡繍绠 m_rate.Divide(factor); } diff --git a/src/gausskernel/storage/mot/core/infra/stats/numeric_statistic_variable.cpp b/src/gausskernel/storage/mot/core/infra/stats/numeric_statistic_variable.cpp index 23c0e371b..02a07ea9c 100644 --- a/src/gausskernel/storage/mot/core/infra/stats/numeric_statistic_variable.cpp +++ b/src/gausskernel/storage/mot/core/infra/stats/numeric_statistic_variable.cpp @@ -29,79 +29,206 @@ namespace MOT { NumericStatisticVariable::NumericStatisticVariable( - const char* name, uint64_t factor /* = 1 */, const char* units /* = "" */, uint64_t limit /* = ULONG_LONG_MAX */) - : StatisticVariable(name), - m_factor(factor), - m_limit(limit), - m_sum(0), - m_squareSum(0), - m_avg(0.0f), - m_var(0.0f), - m_std(0.0f), - m_countSaved(0) + /* + * 鍔熻兘锛氭瀯閫犱竴涓唴瀛樼骇鍒粺璁″彉閲忓璞 + * + * 鍙傛暟鍒楄〃锛 + * name锛氱粺璁″彉閲忕殑鍚嶇О + * factor锛氱缉鏀惧洜瀛愶紝榛樿涓 1 + * units锛氬崟浣嶅瓧绗︿覆锛岄粯璁や负绌哄瓧绗︿覆 + * limit锛氱粺璁″彉閲忕殑涓婇檺锛岄粯璁や负 ULONG_LONG_MAX + * + * 娉ㄦ剰锛 + * 姝ゆ瀯閫犲嚱鏁扮敤浜庡垵濮嬪寲鍐呭瓨绾у埆缁熻鍙橀噺瀵硅薄鐨勫睘鎬с + * 瀹冩帴鍙楃粺璁″彉閲忕殑鍚嶇О銆佺缉鏀惧洜瀛愩佸崟浣嶅瓧绗︿覆鍜屼笂闄愬硷紝骞跺皢鍏惰缃负瀵硅薄鐨勫睘鎬с + */ +MemoryLevelStatisticVariable::MemoryLevelStatisticVariable(const char* name, uint64_t factor /* = 1 */, const char* units /* = "" */, uint64_t limit /* = ULONG_LONG_MAX */) + : StatisticVariable(name), // 璋冪敤鍩虹被 StatisticVariable 鐨勬瀯閫犲嚱鏁版潵鍒濆鍖栧悕绉板睘鎬 + m_factor(factor), // 鍒濆鍖栫缉鏀惧洜瀛愬睘鎬 + m_limit(limit), // 鍒濆鍖栦笂闄愬睘鎬 + m_sum(0), // 鍒濆鍖栨诲拰灞炴 + m_squareSum(0), // 鍒濆鍖栧钩鏂规诲拰灞炴 + m_avg(0.0f), // 鍒濆鍖栧钩鍧囧煎睘鎬 + m_var(0.0f), // 鍒濆鍖栨柟宸睘鎬 + m_std(0.0f), // 鍒濆鍖栨爣鍑嗗樊灞炴 + m_countSaved(0) // 鍒濆鍖栦繚瀛樿鏁板睘鎬 { + // 浣跨敤 snprintf_s 鍑芥暟灏嗗崟浣嶅瓧绗︿覆澶嶅埗鍒 m_units 灞炴т腑锛岀‘淇濅笉瓒呭嚭鏈澶ч暱搴 STAT_VAR_MAX_NAME_LEN errno_t erc = snprintf_s(m_units, STAT_VAR_MAX_NAME_LEN, STAT_VAR_MAX_NAME_LEN - 1, "%s", units); securec_check_ss(erc, "\0", "\0"); } + +/* + * 鍔熻兘锛氭眹鎬绘暟鍊肩粺璁″彉閲忕殑淇℃伅 + * + * 鍙傛暟鍒楄〃锛 + * updateTstamp锛氭槸鍚︽洿鏂版椂闂存埑锛屾鍙傛暟鏈娇鐢 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庢眹鎬绘暟鍊肩粺璁″彉閲忕殑淇℃伅锛屽寘鎷鏁般佸钩鍧囧笺佹柟宸拰鏍囧噯宸 + * 瀹冧細鏍规嵁褰撳墠鐨勬诲拰鍜岃鏁板睘鎬ц绠楀钩鍧囧硷紝鐒跺悗璁$畻鏂瑰樊鍜屾爣鍑嗗樊銆 + * 鍙傛暟 `updateTstamp` 鏈娇鐢ㄣ + */ void NumericStatisticVariable::Summarize(bool updateTstamp) { + // 鍙傛暟 `updateTstamp` 鏈娇鐢紝閬垮厤缂栬瘧鍣ㄨ鍛 (void)updateTstamp; + + // 灏嗗綋鍓嶈鏁板间繚瀛樺埌 m_countSaved 灞炴 m_countSaved = m_count; + + // 璁$畻骞冲潎鍊硷紝浣跨敤鎬诲拰灞炴у拰璁℃暟灞炴 m_avg = ((double)m_sum) / ((double)m_countSaved); + + // 璁$畻鏂瑰樊锛屼娇鐢ㄥ钩鏂规诲拰灞炴у拰骞冲潎鍊 m_var = ((double)m_squareSum) - m_avg * m_avg; + + // 璁$畻鏍囧噯宸紝浣跨敤鏂瑰樊骞惰皟鐢 sqrt 鍑芥暟 m_std = sqrt(m_var); } + +/* + * 鍔熻兘锛氭墦鍗版暟鍊肩粺璁″彉閲忕殑淇℃伅 + * + * 鍙傛暟鍒楄〃锛 + * logLevel锛氭棩蹇楃骇鍒紝鎸囧畾鎵撳嵃淇℃伅鐨勮缁嗙▼搴 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庡皢鏁板肩粺璁″彉閲忕殑淇℃伅浠ユ棩蹇楀舰寮忔墦鍗板嚭鏉ワ紝鍖呮嫭鏍锋湰鏁般佸钩鍧囧煎拰鏍囧噯宸 + * 瀹冨皢鎵撳嵃鐨勪俊鎭牸寮忓寲骞朵娇鐢ㄦ寚瀹氱殑鏃ュ織绾у埆杈撳嚭銆 + */ void NumericStatisticVariable::Print(LogLevel logLevel) const { - MOT_LOG(logLevel, - "%s={ samples: %" PRIu64 ", avg: %0.4f %s, std: %0.4f %s }", - m_name, - m_countSaved, - m_avg / m_factor, - m_units, - m_std / m_factor, - m_units); + // 浣跨敤 MOT_LOG 鍑芥暟灏嗘暟鍊肩粺璁″彉閲忕殑淇℃伅浠ユ寚瀹氭牸寮忓拰鏃ュ織绾у埆鎵撳嵃鍑烘潵 + MOT_LOG(logLevel, "%s={ samples: %" PRIu64 ", avg: %0.4f %s, std: %0.4f %s }", m_name, m_countSaved, + m_avg / m_factor, m_units, m_std / m_factor, m_units); } + +/* + * 鍔熻兘锛氬皢鏁板肩粺璁″彉閲忕殑鍊艰祴缁欏綋鍓嶆暟鍊肩粺璁″彉閲 + * + * 鍙傛暟鍒楄〃锛 + * rhs锛氳璧嬪肩殑婧愭暟鍊肩粺璁″彉閲忓璞 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庡皢婧愭暟鍊肩粺璁″彉閲忓璞$殑鍊艰祴缁欏綋鍓嶆暟鍊肩粺璁″彉閲忓璞° + * 瀹冨皢鎬诲拰銆佸钩鏂规诲拰鍜岃鏁板睘鎬у垎鍒祴鍊间负婧愬璞$殑瀵瑰簲灞炴у笺 + */ void NumericStatisticVariable::Assign(const StatisticVariable& rhs) { - auto numRhs = static_cast(rhs); + // 灏嗘簮瀵硅薄寮哄埗杞崲涓 NumericStatisticVariable 绫诲瀷 + auto numRhs = static_cast(rhs); + + // 灏嗘诲拰灞炴ц祴鍊间负婧愬璞$殑鎬诲拰灞炴у m_sum = numRhs.m_sum; + + // 灏嗗钩鏂规诲拰灞炴ц祴鍊间负婧愬璞$殑骞虫柟鎬诲拰灞炴у m_squareSum = numRhs.m_squareSum; + + // 灏嗚鏁板睘鎬ц祴鍊间负婧愬璞$殑璁℃暟灞炴у m_count = numRhs.m_count; } + +/* + * 鍔熻兘锛氬皢鍙︿竴涓暟鍊肩粺璁″彉閲忕殑鍊兼坊鍔犲埌褰撳墠鏁板肩粺璁″彉閲忕殑鍊间腑 + * + * 鍙傛暟鍒楄〃锛 + * rhs锛氳娣诲姞鐨勬簮鏁板肩粺璁″彉閲忓璞 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庡皢鍙︿竴涓暟鍊肩粺璁″彉閲忓璞$殑鍊兼坊鍔犲埌褰撳墠鏁板肩粺璁″彉閲忓璞$殑鍊间腑銆 + * 瀹冨皢鎬诲拰銆佸钩鏂规诲拰鍜岃鏁板睘鎬у垎鍒浉鍔犮 + */ void NumericStatisticVariable::Add(const StatisticVariable& rhs) { - auto numRhs = static_cast(rhs); + // 灏嗘簮瀵硅薄寮哄埗杞崲涓 NumericStatisticVariable 绫诲瀷 + auto numRhs = static_cast(rhs); + + // 灏嗘诲拰灞炴х浉鍔 m_sum += numRhs.m_sum; + + // 灏嗗钩鏂规诲拰灞炴х浉鍔 m_squareSum += numRhs.m_squareSum; + + // 灏嗚鏁板睘鎬х浉鍔 m_count += numRhs.m_count; } + +/* + * 鍔熻兘锛氫粠褰撳墠鏁板肩粺璁″彉閲忕殑鍊间腑鍑忓幓鍙︿竴涓暟鍊肩粺璁″彉閲忕殑鍊 + * + * 鍙傛暟鍒楄〃锛 + * rhs锛氳鍑忓幓鐨勬簮鏁板肩粺璁″彉閲忓璞 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庝粠褰撳墠鏁板肩粺璁″彉閲忓璞$殑鍊间腑鍑忓幓鍙︿竴涓暟鍊肩粺璁″彉閲忓璞$殑鍊笺 + * 瀹冨皢鎬诲拰銆佸钩鏂规诲拰鍜岃鏁板睘鎬у垎鍒噺鍘汇 + */ void NumericStatisticVariable::Subtract(const StatisticVariable& rhs) { - auto numRhs = static_cast(rhs); + // 灏嗘簮瀵硅薄寮哄埗杞崲涓 NumericStatisticVariable 绫诲瀷 + auto numRhs = static_cast(rhs); + + // 浠庢诲拰灞炴т腑鍑忓幓婧愬璞$殑鎬诲拰灞炴у m_sum -= numRhs.m_sum; + + // 浠庡钩鏂规诲拰灞炴т腑鍑忓幓婧愬璞$殑骞虫柟鎬诲拰灞炴у m_squareSum -= numRhs.m_squareSum; + + // 浠庤鏁板睘鎬т腑鍑忓幓婧愬璞$殑璁℃暟灞炴у m_count -= numRhs.m_count; } + +/* + * 鍔熻兘锛氬皢褰撳墠鏁板肩粺璁″彉閲忕殑鍊奸櫎浠ユ寚瀹氬洜瀛 + * + * 鍙傛暟鍒楄〃锛 + * factor锛氶櫎浠ョ殑鍥犲瓙锛屽繀椤诲ぇ浜庨浂 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庡皢褰撳墠鏁板肩粺璁″彉閲忓璞$殑鍊奸櫎浠ユ寚瀹氬洜瀛愩 + * 瀹冨皢璁℃暟灞炴с佹诲拰灞炴у拰骞虫柟鎬诲拰灞炴у垎鍒櫎浠ュ洜瀛愬笺 + */ void NumericStatisticVariable::Divide(uint32_t factor) { + // 妫鏌ュ洜瀛愭槸鍚﹀ぇ浜庨浂 if (factor > 0) { + // 灏嗚鏁板睘鎬ч櫎浠ュ洜瀛 m_count /= factor; + + // 灏嗘诲拰灞炴ч櫎浠ュ洜瀛 m_sum /= factor; + + // 灏嗗钩鏂规诲拰灞炴ч櫎浠ュ洜瀛 m_squareSum /= factor; } } + +/* + * 鍔熻兘锛氶噸缃暟鍊肩粺璁″彉閲忕殑鍊 + * + * 鍙傛暟鍒楄〃锛氭棤 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庡皢鏁板肩粺璁″彉閲忕殑鍊奸噸缃负闆躲傚畠灏嗘诲拰灞炴с佸钩鏂规诲拰灞炴у拰璁℃暟灞炴ч兘璁剧疆涓洪浂銆 + */ void NumericStatisticVariable::Reset() { + // 灏嗘诲拰灞炴ц缃负闆 m_sum = 0; + + // 灏嗗钩鏂规诲拰灞炴ц缃负闆 m_squareSum = 0; + + // 灏嗚鏁板睘鎬ц缃负闆 m_count = 0; } + } // namespace MOT diff --git a/src/gausskernel/storage/mot/core/infra/stats/rate_statistic_variable.cpp b/src/gausskernel/storage/mot/core/infra/stats/rate_statistic_variable.cpp index d9d74d5d2..ab4739bbf 100644 --- a/src/gausskernel/storage/mot/core/infra/stats/rate_statistic_variable.cpp +++ b/src/gausskernel/storage/mot/core/infra/stats/rate_statistic_variable.cpp @@ -28,85 +28,191 @@ #include "utilities.h" namespace MOT { +/* + * 鍔熻兘锛氳绠楅熺巼缁熻鍙橀噺鐨勬憳瑕佷俊鎭 + * + * 鍙傛暟鍒楄〃锛 + * updateTstamp锛氭寚绀烘槸鍚﹂渶瑕佹洿鏂版椂闂存埑 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庤绠楅熺巼缁熻鍙橀噺鐨勬憳瑕佷俊鎭紝鍖呮嫭閫熺巼銆侀鐜囩瓑淇℃伅銆 + * 瀹冨彲浠ラ夋嫨鏄惁鏇存柊鏃堕棿鎴筹紝骞舵牴鎹椂闂存埑璁$畻闂撮殧绉掓暟銆侀熺巼鍜岄鐜囥 + */ void RateStatisticVariable::Summarize(bool updateTstamp) { + // 濡傛灉闇瑕佹洿鏂版椂闂存埑 if (updateTstamp) { + // 鑾峰彇褰撳墠鏃堕棿鎴 m_tstamp = CpuCyclesLevelTime::Rdtscp(); } + // 淇濆瓨褰撳墠璁℃暟 m_countSaved = m_count; + // 淇濆瓨褰撳墠鎬诲拰 m_sumSaved = m_sum; + // 璁$畻闂撮殧绉掓暟 m_intervalSeconds = CpuCyclesLevelTime::CyclesToSeconds(m_tstamp - m_initTstamp); + // 璁$畻閫熺巼 m_rate = ((double)(m_sumSaved)) / m_intervalSeconds / m_factor; + // 璁$畻棰戠巼 m_frequency = ((double)(m_countSaved)) / m_intervalSeconds; } +/* + * 鍔熻兘锛氭墦鍗伴熺巼缁熻鍙橀噺鐨勪俊鎭 + * + * 鍙傛暟鍒楄〃锛 + * logLevel锛氭棩蹇楃骇鍒紝鎸囩ず鎵撳嵃淇℃伅鐨勮缁嗙▼搴 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庢墦鍗伴熺巼缁熻鍙橀噺鐨勪俊鎭紝鍖呮嫭閫熺巼銆侀鐜囧拰鏍锋湰鏁扮瓑淇℃伅銆 + */ void RateStatisticVariable::Print(LogLevel logLevel) const { - MOT_LOG(logLevel, - "%s={ rate: %0.4f (%s/sec), frequency: %0.4f (evt/sec) [%" PRIu64 " samples] }", - m_name, - m_rate, - m_units, - m_frequency, - m_countSaved); + // 浣跨敤鎸囧畾鐨勬棩蹇楃骇鍒墦鍗颁俊鎭 + MOT_LOG(logLevel, "%s={ rate: %0.4f (%s/sec), frequency: %0.4f (evt/sec) [%" PRIu64 " samples] }", m_name, m_rate, + m_units, m_frequency, m_countSaved); } -void RateStatisticVariable::Assign(const StatisticVariable& rhs) +/* + * 鍔熻兘锛氬皢鍙︿竴涓熺巼缁熻鍙橀噺鐨勫煎垎閰嶇粰褰撳墠閫熺巼缁熻鍙橀噺 + * + * 鍙傛暟鍒楄〃锛 + * rhs锛氳鍒嗛厤鐨勬簮閫熺巼缁熻鍙橀噺瀵硅薄 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庡皢鍙︿竴涓熺巼缁熻鍙橀噺瀵硅薄鐨勫煎垎閰嶇粰褰撳墠閫熺巼缁熻鍙橀噺瀵硅薄銆 + * 瀹冨皢璁℃暟銆佹诲拰銆佹椂闂存埑銆侀熺巼銆佹椂闂撮棿闅斻侀鐜囩瓑灞炴ч兘鍒嗛厤缁欏綋鍓嶅璞° + */ +void RateStatisticVariable::Assign(const StatisticVariable &rhs) { - auto rateRhs = static_cast(rhs); + // 灏嗘簮瀵硅薄寮哄埗杞崲涓 RateStatisticVariable 绫诲瀷 + auto rateRhs = static_cast(rhs); + // 鍒嗛厤璁℃暟灞炴 m_count = rateRhs.m_count; + // 鍒嗛厤鎬诲拰灞炴 m_sum = rateRhs.m_sum; + // 鍒嗛厤鍒濆鏃堕棿鎴冲睘鎬 m_initTstamp = rateRhs.m_initTstamp; + // 鍒嗛厤鏃堕棿鎴冲睘鎬 m_tstamp = rateRhs.m_tstamp; + // 鍒嗛厤閫熺巼灞炴 m_rate = rateRhs.m_rate; + // 鍒嗛厤鏃堕棿闂撮殧灞炴 m_intervalSeconds = rateRhs.m_intervalSeconds; + // 鍒嗛厤棰戠巼灞炴 m_frequency = rateRhs.m_frequency; + // 鍒嗛厤淇濆瓨鐨勮鏁板睘鎬 m_countSaved = rateRhs.m_count; + // 鍒嗛厤淇濆瓨鐨勬诲拰灞炴 m_sumSaved = rateRhs.m_sumSaved; } -void RateStatisticVariable::Add(const StatisticVariable& rhs) +/* + * 鍔熻兘锛氬皢鍙︿竴涓熺巼缁熻鍙橀噺鐨勫兼坊鍔犲埌褰撳墠閫熺巼缁熻鍙橀噺 + * + * 鍙傛暟鍒楄〃锛 + * rhs锛氳娣诲姞鐨勬簮閫熺巼缁熻鍙橀噺瀵硅薄 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庡皢鍙︿竴涓熺巼缁熻鍙橀噺瀵硅薄鐨勫兼坊鍔犲埌褰撳墠閫熺巼缁熻鍙橀噺瀵硅薄銆 + * 瀹冨皢璁℃暟銆佹诲拰銆侀熺巼銆侀鐜囥佹椂闂存埑绛夊睘鎬х浉搴斿湴娣诲姞鍒板綋鍓嶅璞★紝骞舵洿鏂板垵濮嬫椂闂存埑銆 + */ +void RateStatisticVariable::Add(const StatisticVariable &rhs) { - auto rateRhs = static_cast(rhs); + // 灏嗘簮瀵硅薄寮哄埗杞崲涓 RateStatisticVariable 绫诲瀷 + auto rateRhs = static_cast(rhs); + // 娣诲姞璁℃暟灞炴 m_count += rateRhs.m_countSaved; + // 娣诲姞鎬诲拰灞炴 m_sum += rateRhs.m_sumSaved; + // 娣诲姞閫熺巼灞炴 m_rate += rateRhs.m_rate; + // 娣诲姞棰戠巼灞炴 m_frequency += rateRhs.m_frequency; + // 濡傛灉褰撳墠瀵硅薄鐨勫垵濮嬫椂闂存埑涓洪浂锛屾垨鑰呮簮瀵硅薄鐨勫垵濮嬫椂闂存埑澶т簬闆朵笖灏忎簬褰撳墠瀵硅薄鐨勫垵濮嬫椂闂存埑 if ((m_initTstamp == 0) || ((rateRhs.m_initTstamp > 0) && (rateRhs.m_initTstamp < m_initTstamp))) { + // 鏇存柊褰撳墠瀵硅薄鐨勫垵濮嬫椂闂存埑 m_initTstamp = rateRhs.m_initTstamp; } + // 濡傛灉婧愬璞$殑鏃堕棿鎴冲ぇ浜庡綋鍓嶅璞$殑鏃堕棿鎴 if (rateRhs.m_tstamp > m_tstamp) { + // 鏇存柊褰撳墠瀵硅薄鐨勬椂闂存埑 m_tstamp = rateRhs.m_tstamp; } } -void RateStatisticVariable::Subtract(const StatisticVariable& rhs) +/* + * 鍔熻兘锛氫粠褰撳墠閫熺巼缁熻鍙橀噺涓噺鍘诲彟涓涓熺巼缁熻鍙橀噺鐨勫 + * + * 鍙傛暟鍒楄〃锛 + * rhs锛氳鍑忓幓鐨勬簮閫熺巼缁熻鍙橀噺瀵硅薄 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庝粠褰撳墠閫熺巼缁熻鍙橀噺瀵硅薄涓噺鍘诲彟涓涓熺巼缁熻鍙橀噺瀵硅薄鐨勫笺 + * 瀹冨噺鍘昏鏁般佹诲拰灞炴э紝骞跺湪闇瑕佹椂鏇存柊鍒濆鏃堕棿鎴炽 + */ +void RateStatisticVariable::Subtract(const StatisticVariable &rhs) { - auto rateRhs = static_cast(rhs); + // 灏嗘簮瀵硅薄寮哄埗杞崲涓 RateStatisticVariable 绫诲瀷 + auto rateRhs = static_cast(rhs); + // 鍑忓幓璁℃暟灞炴 m_count -= rateRhs.m_count; + // 鍑忓幓鎬诲拰灞炴 m_sum -= rateRhs.m_sum; + // 濡傛灉婧愬璞$殑鏃堕棿鎴充笉涓洪浂 if (rateRhs.m_tstamp != 0) { + // 鏇存柊褰撳墠瀵硅薄鐨勫垵濮嬫椂闂存埑涓烘簮瀵硅薄鐨勬椂闂存埑 m_initTstamp = rateRhs.m_tstamp; } } +/* + * 鍔熻兘锛氬皢褰撳墠閫熺巼缁熻鍙橀噺鐨勫睘鎬у奸櫎浠ユ寚瀹氱殑鍥犲瓙 + * + * 鍙傛暟鍒楄〃锛 + * factor锛氶櫎鏁板洜瀛愶紝鐢ㄤ簬闄や互褰撳墠閫熺巼缁熻鍙橀噺鐨勫睘鎬у + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庡皢褰撳墠閫熺巼缁熻鍙橀噺鐨勮鏁般侀熺巼銆侀鐜囧睘鎬у奸櫎浠ユ寚瀹氱殑鍥犲瓙銆 + * 濡傛灉鍥犲瓙澶т簬闆讹紝鍒欎細鎵ц闄ゆ硶鎿嶄綔锛屽惁鍒欎笉鎵ц鎿嶄綔銆 + */ void RateStatisticVariable::Divide(uint32_t factor) { + // 濡傛灉鍥犲瓙澶т簬闆 if (factor > 0) { + // 闄や互鎸囧畾鐨勫洜瀛愶紝鏇存柊璁℃暟灞炴 m_count /= factor; + // 闄や互鎸囧畾鐨勫洜瀛愶紝鏇存柊閫熺巼灞炴 m_rate /= factor; + // 闄や互鎸囧畾鐨勫洜瀛愶紝鏇存柊棰戠巼灞炴 m_frequency /= factor; } } +/* + * 鍔熻兘锛氶噸缃綋鍓嶉熺巼缁熻鍙橀噺鐨勫睘鎬у + * + * 鍙傛暟鍒楄〃锛氭棤 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庡皢褰撳墠閫熺巼缁熻鍙橀噺鐨勫睘鎬у奸噸缃负鍒濆鐘舵侊紝鍖呮嫭璁℃暟銆佹诲拰銆侀熺巼銆侀鐜囥佹椂闂存埑绛夊睘鎬с + */ void RateStatisticVariable::Reset() { + // 閲嶇疆璁℃暟灞炴т负闆 m_count = 0; + // 閲嶇疆鎬诲拰灞炴т负闆 m_sum = 0; + // 閲嶇疆閫熺巼灞炴т负闆 m_rate = 0.0f; + // 閲嶇疆棰戠巼灞炴т负闆 m_frequency = 0.0f; + // 閲嶇疆鍒濆鏃堕棿鎴冲睘鎬т负闆 m_initTstamp = 0; + // 閲嶇疆鏃堕棿鎴冲睘鎬т负闆 m_tstamp = 0; + // 閲嶇疆鏃堕棿闂撮殧灞炴т负闆 m_intervalSeconds = 0.0f; } + } // namespace MOT diff --git a/src/gausskernel/storage/mot/core/infra/stats/statistics_manager.cpp b/src/gausskernel/storage/mot/core/infra/stats/statistics_manager.cpp index c5eb1645c..4107cf62d 100644 --- a/src/gausskernel/storage/mot/core/infra/stats/statistics_manager.cpp +++ b/src/gausskernel/storage/mot/core/infra/stats/statistics_manager.cpp @@ -33,7 +33,7 @@ namespace MOT { DECLARE_LOGGER(StatisticsManager, Statistics) -StatisticsManager* StatisticsManager::m_manager = nullptr; +StatisticsManager *StatisticsManager::m_manager = nullptr; #define STAT_PRINT_CHECK_PERIOD_SECONDS 1 @@ -51,41 +51,66 @@ StatisticsManager* StatisticsManager::m_manager = nullptr; break; \ } -static bool CreateRecursiveMutex(pthread_mutex_t* mutex) +/* + * 鍔熻兘锛氬垱寤洪掑綊浜掓枼閿 + * + * 鍙傛暟鍒楄〃锛 + * mutex锛歱thread_mutex_t 绫诲瀷鐨勬寚閽堬紝鐢ㄤ簬瀛樺偍鍒涘缓鐨勪簰鏂ラ攣瀵硅薄 + * + * 杩斿洖鍊硷細 + * 濡傛灉鎴愬姛鍒涘缓浜掓枼閿侊紝鍒欒繑鍥 true锛涘惁鍒欒繑鍥 false + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庡垱寤轰竴涓掑綊浜掓枼閿侊紝骞跺皢鍏跺瓨鍌ㄥ湪鎻愪緵鐨 mutex 鎸囬拡涓 + * 濡傛灉鍒涘缓鎴愬姛锛屽嚱鏁拌繑鍥 true锛屽惁鍒欒繑鍥 false銆 + * 浜掓枼閿佸睘鎬ч厤缃负閫掑綊绫诲瀷锛屼互鏀寔閫掑綊閿佸畾銆 + */ +static bool CreateRecursiveMutex(pthread_mutex_t *mutex) { bool result = false; + // 鍒濆鍖栦簰鏂ラ攣灞炴 pthread_mutexattr_t lockattr; int rc = pthread_mutexattr_init(&lockattr); if (rc != 0) { - MOT_REPORT_SYSTEM_ERROR_CODE(rc, - pthread_mutexattr_init, - "Statistics Manager Initialization", - "Failed to initialize recursive mutex attribute for the statistics manager"); + // 鎶ュ憡鍒濆鍖栦簰鏂ラ攣灞炴уけ璐ョ殑绯荤粺閿欒 + MOT_REPORT_SYSTEM_ERROR_CODE(rc, pthread_mutexattr_init, "Statistics Manager Initialization", + "Failed to initialize recursive mutex attribute for the statistics manager"); } else { + // 閰嶇疆浜掓枼閿佸睘鎬т负閫掑綊绫诲瀷 rc = pthread_mutexattr_settype(&lockattr, PTHREAD_MUTEX_RECURSIVE); if (rc != 0) { - MOT_REPORT_SYSTEM_ERROR_CODE(rc, - pthread_mutexattr_settype, - "Statistics Manager Initialization", - "Failed to configure recursive mutex type for the statistics manager"); + // 鎶ュ憡閰嶇疆浜掓枼閿佺被鍨嬪け璐ョ殑绯荤粺閿欒 + MOT_REPORT_SYSTEM_ERROR_CODE(rc, pthread_mutexattr_settype, "Statistics Manager Initialization", + "Failed to configure recursive mutex type for the statistics manager"); } else { + // 鍒涘缓閫掑綊浜掓枼閿 rc = pthread_mutex_init(mutex, &lockattr); if (rc != 0) { - MOT_REPORT_SYSTEM_ERROR_CODE(rc, - pthread_mutex_init, - "Statistics Manager Initialization", - "Failed to create recursive mutex for the statistics manager"); + // 鎶ュ憡鍒涘缓浜掓枼閿佸け璐ョ殑绯荤粺閿欒 + MOT_REPORT_SYSTEM_ERROR_CODE(rc, pthread_mutex_init, "Statistics Manager Initialization", + "Failed to create recursive mutex for the statistics manager"); } else { result = true; } } + // 閿姣佷簰鏂ラ攣灞炴 pthread_mutexattr_destroy(&lockattr); } return result; } +/* + * 鍔熻兘锛氬垵濮嬪寲缁熻绠$悊鍣 + * + * 杩斿洖鍊硷細 + * 濡傛灉鍒濆鍖栨垚鍔燂紝杩斿洖 true锛涘惁鍒欒繑鍥 false + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庡垵濮嬪寲缁熻绠$悊鍣紝鍖呮嫭鍒涘缓浜掓枼閿併佹潯浠跺彉閲忓拰娉ㄥ唽閰嶇疆鏇存敼閫氱煡銆 + * 鍦ㄥ垵濮嬪寲鐨勮繃绋嬩腑锛屽嚱鏁颁細妫鏌ユ瘡涓楠ょ殑缁撴灉锛屽鏋滃嚭鐜伴敊璇紝灏嗚繑鍥 false銆 + */ bool StatisticsManager::Initialize() { bool result = true; @@ -102,6 +127,7 @@ bool StatisticsManager::Initialize() CHECK_INIT_STATUS(result, "Failed to create statistics printing lock"); m_initPhase = INIT_STAT_PRINT_LOCK; + // 鍒濆鍖栫粺璁℃墦鍗版潯浠跺彉閲 int rc = pthread_cond_init(&m_statsPrintCond, nullptr); result = (rc == 0); CHECK_SYS_INIT_STATUS(rc, pthread_cond_init, "Failed to initialize statistics printing condition variable"); @@ -126,7 +152,13 @@ StatisticsManager::StatisticsManager() { // the statistics thread should be started explicitly } - +/* + * 鍔熻兘锛氱粺璁$鐞嗗櫒鐨勬瀽鏋勫嚱鏁 + * + * 娉ㄦ剰锛 + * 姝ゆ瀽鏋勫嚱鏁扮敤浜庨噴鏀剧粺璁$鐞嗗櫒鐨勮祫婧愶紝鍖呮嫭鍋滄缁熻鎵撳嵃绾跨▼銆佸彇娑堟敞鍐岄厤缃洿鏀归氱煡銆 + * 閿姣佹潯浠跺彉閲忓拰浜掓枼閿併傚湪鏋愭瀯鐨勮繃绋嬩腑锛屾牴鎹垵濮嬪寲闃舵鎵ц鐩稿簲鐨勮祫婧愰噴鏀炬搷浣溿 + */ StatisticsManager::~StatisticsManager() { switch (m_initPhase) { @@ -151,53 +183,103 @@ StatisticsManager::~StatisticsManager() } } +/* + * 鍔熻兘锛氬垱寤 StatisticsManager 瀹炰緥 + * + * 杩斿洖鍊硷細 + * 濡傛灉鍒涘缓鎴愬姛锛岃繑鍥 true锛涘惁鍒欒繑鍥 false + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庡垱寤 StatisticsManager 瀹炰緥锛屽苟鍦ㄥ垱寤哄悗杩涜鍒濆鍖栥傚畠纭繚鍙湁涓涓疄渚嬭鍒涘缓銆 + * 濡傛灉鍐呭瓨鍒嗛厤鎴栧垵濮嬪寲澶辫触锛屽皢浼氳褰曢敊璇苟杩斿洖 false銆 + */ bool StatisticsManager::CreateInstance() { bool result = false; MOT_ASSERT(m_manager == nullptr); + + // 妫鏌ユ槸鍚﹀凡缁忓瓨鍦 StatisticsManager 瀹炰緥 if (m_manager == nullptr) { + // 灏濊瘯鍒嗛厤 StatisticsManager 瀹炰緥鍐呭瓨 m_manager = new (std::nothrow) StatisticsManager(); if (!m_manager) { MOT_LOG_ERROR("Failed to allocate memory for statistics manager, aborting"); SetLastError(MOT_ERROR_OOM, MOT_SEVERITY_FATAL); } else { + // 鍒濆鍖 StatisticsManager 瀹炰緥 result = m_manager->Initialize(); if (!result) { + // 鍒濆鍖栧け璐ワ紝閲婃斁宸插垎閰嶇殑鍐呭瓨 delete m_manager; m_manager = nullptr; } } } + return result; } +/* + * 鍔熻兘锛氶攢姣 StatisticsManager 瀹炰緥 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庨攢姣 StatisticsManager 瀹炰緥銆傚畠浼氶噴鏀惧疄渚嬬殑鍐呭瓨锛屽苟灏嗗疄渚嬫寚閽堣涓 nullptr銆 + * 鍦ㄩ攢姣佸墠锛屼細妫鏌ユ槸鍚﹀瓨鍦ㄦ湁鏁堢殑瀹炰緥锛屼互纭繚瀹夊叏閿姣併 + */ void StatisticsManager::DestroyInstance() { MOT_ASSERT(m_manager != nullptr); + // 妫鏌ユ槸鍚﹀瓨鍦ㄦ湁鏁堢殑瀹炰緥 if (m_manager != nullptr) { + // 閲婃斁瀹炰緥鍐呭瓨 delete m_manager; m_manager = nullptr; } } -StatisticsManager& StatisticsManager::GetInstance() +/* + * 鍔熻兘锛氳幏鍙 StatisticsManager 瀹炰緥鐨勫紩鐢 + * + * 杩斿洖鍊硷細 + * 杩斿洖 StatisticsManager 瀹炰緥鐨勫紩鐢 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庤幏鍙 StatisticsManager 瀹炰緥鐨勫紩鐢紝浠ヤ究鍦ㄥ簲鐢ㄧ▼搴忎腑浣跨敤鍗曚竴瀹炰緥杩涜缁熻绠$悊銆 + * 鍦ㄨ幏鍙栧紩鐢ㄥ墠锛屼細妫鏌ユ槸鍚﹀瓨鍦ㄦ湁鏁堢殑瀹炰緥锛屼互纭繚瀹夊叏浣跨敤銆 + */ +StatisticsManager &StatisticsManager::GetInstance() { MOT_ASSERT(m_manager != nullptr); + + // 妫鏌ユ槸鍚﹀瓨鍦ㄦ湁鏁堢殑瀹炰緥 return *m_manager; } -bool StatisticsManager::RegisterStatisticsProvider(StatisticsProvider* statisticsProvider) +/* + * 鍔熻兘锛氭敞鍐岀粺璁′俊鎭彁渚涜 + * + * 鍙傛暟鍒楄〃锛 + * statisticsProvider锛氳娉ㄥ唽鐨勭粺璁′俊鎭彁渚涜呭璞℃寚閽 + * + * 杩斿洖鍊硷細 + * 濡傛灉娉ㄥ唽鎴愬姛锛岃繑鍥 true锛涘惁鍒欒繑鍥 false + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庢敞鍐岀粺璁′俊鎭彁渚涜咃紝浠ヤ究缁熻绠$悊鍣ㄥ彲浠ユ敹闆嗗叾鎻愪緵鐨勭粺璁℃暟鎹 + * 鍦ㄦ敞鍐屾彁渚涜呭墠锛屼細妫鏌ユ槸鍚﹀凡缁忔敞鍐岋紝浠ョ‘淇濅笉浼氶噸澶嶆敞鍐屻 + */ +bool StatisticsManager::RegisterStatisticsProvider(StatisticsProvider *statisticsProvider) { bool result = false; pthread_mutex_lock(&m_providersLock); - mot_list::iterator itr = find(m_providers.begin(), m_providers.end(), statisticsProvider); + // 鏌ユ壘鎻愪緵鑰呮槸鍚﹀凡缁忔敞鍐 + mot_list::iterator itr = find(m_providers.begin(), m_providers.end(), statisticsProvider); if (itr == m_providers.end()) { + // 濡傛灉鎻愪緵鑰呭皻鏈敞鍐岋紝鍒欏皾璇曟敞鍐 if (!m_providers.push_back(statisticsProvider)) { - MOT_REPORT_ERROR(MOT_ERROR_OOM, - "Register Statistics", - "Failed to register statistics provider %s", - statisticsProvider->GetName()); + MOT_REPORT_ERROR(MOT_ERROR_OOM, "Register Statistics", "Failed to register statistics provider %s", + statisticsProvider->GetName()); } else { result = true; MOT_LOG_TRACE("Registered statistics provider: %s", statisticsProvider->GetName()); @@ -208,13 +290,28 @@ bool StatisticsManager::RegisterStatisticsProvider(StatisticsProvider* statistic return result; } -bool StatisticsManager::UnregisterStatisticsProvider(StatisticsProvider* statisticsProvider) +/* + * 鍔熻兘锛氬彇娑堟敞鍐岀粺璁′俊鎭彁渚涜 + * + * 鍙傛暟鍒楄〃锛 + * statisticsProvider锛氳鍙栨秷娉ㄥ唽鐨勭粺璁′俊鎭彁渚涜呭璞℃寚閽 + * + * 杩斿洖鍊硷細 + * 濡傛灉鍙栨秷娉ㄥ唽鎴愬姛锛岃繑鍥 true锛涘惁鍒欒繑鍥 false + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庡彇娑堟敞鍐岀粺璁′俊鎭彁渚涜咃紝浠ュ仠姝㈢粺璁$鐞嗗櫒鏀堕泦鍏舵彁渚涚殑缁熻鏁版嵁銆 + * 鍦ㄥ彇娑堟敞鍐屾彁渚涜呭墠锛屼細妫鏌ユ槸鍚﹀凡缁忔敞鍐岋紝浠ョ‘淇濅笉浼氶噸澶嶅彇娑堟敞鍐屻 + */ +bool StatisticsManager::UnregisterStatisticsProvider(StatisticsProvider *statisticsProvider) { bool result = false; pthread_mutex_lock(&m_providersLock); - mot_list::iterator itr = find(m_providers.begin(), m_providers.end(), statisticsProvider); + // 鏌ユ壘鎻愪緵鑰呮槸鍚﹀凡缁忔敞鍐 + mot_list::iterator itr = find(m_providers.begin(), m_providers.end(), statisticsProvider); if (itr != m_providers.end()) { + // 濡傛灉鎻愪緵鑰呭凡缁忔敞鍐岋紝鍒欏彇娑堟敞鍐 m_providers.erase(itr); MOT_LOG_TRACE("Unregistered statistics provider: %s", statisticsProvider->GetName()); result = true; @@ -224,26 +321,53 @@ bool StatisticsManager::UnregisterStatisticsProvider(StatisticsProvider* statist return result; } +/* + * 鍔熻兘锛氬鐞嗛厤缃洿鏀归氱煡 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庡搷搴旈厤缃洿鏀归氱煡锛屾洿鏂扮粺璁′俊鎭墦鍗扮殑鍛ㄦ湡鍙傛暟銆 + * 瀹冧細鏍规嵁鍏ㄥ眬閰嶇疆鏂囦欢涓殑閰嶇疆鍊硷紝鏇存柊缁熻淇℃伅鐨勬墦鍗板懆鏈熷拰鍏ㄩ噺缁熻淇℃伅鐨勬墦鍗板懆鏈熴 + */ void StatisticsManager::OnConfigChange() { + // 浠庡叏灞閰嶇疆涓幏鍙栫粺璁′俊鎭墦鍗板懆鏈熷弬鏁 m_statsPrintPeriodSeconds = GetGlobalConfiguration().m_statPrintPeriodSeconds; + // 浠庡叏灞閰嶇疆涓幏鍙栧叏閲忕粺璁′俊鎭墦鍗板懆鏈熷弬鏁 m_fullStatsPrintPeriodSeconds = GetGlobalConfiguration().m_statPrintFullPeriodSeconds; } // functor for std::find_if() struct StatisticsProviderFinder { - const char* m_name; + const char *m_name; - explicit StatisticsProviderFinder(const char* name) : m_name(name) + explicit StatisticsProviderFinder(const char *name) : m_name(name) {} - inline bool operator()(StatisticsProvider* const& provider) const + inline bool operator()(StatisticsProvider *const &provider) const { return strcmp(m_name, provider->GetName()) == 0; } }; // functor for std::for_each() +/* + * 缁撴瀯浣擄細StatisticsProviderPrinter + * + * 鍔熻兘锛氱敤浜庢墦鍗扮粺璁′俊鎭彁渚涜呯殑缁熻鏁版嵁 + * + * 鎴愬憳鍙橀噺锛 + * m_logLevel锛氭寚瀹氭墦鍗版棩蹇楃殑绾у埆 + * m_statOpts锛氭寚瀹氱粺璁¢夐」锛岀敤浜庤繃婊よ鎵撳嵃鐨勭粺璁℃暟鎹 + * + * 鏋勯犲嚱鏁帮細 + * StatisticsProviderPrinter(LogLevel logLevel, uint32_t statOpts)锛 + * 鍒濆鍖栫粨鏋勪綋鐨勬垚鍛樺彉閲忥紝鍖呮嫭鎵撳嵃鏃ュ織绾у埆鍜岀粺璁¢夐」銆 + * + * 鎿嶄綔绗﹂噸杞斤細 + * inline void operator()(StatisticsProvider* const& provider)锛 + * 鐢ㄤ簬璋冪敤缁熻淇℃伅鎻愪緵鑰呯殑鎵撳嵃缁熻鏁版嵁鍑芥暟锛屽墠鎻愭槸鎻愪緵鑰呭凡鍚敤銆 + * 濡傛灉鎻愪緵鑰呭凡鍚敤锛屽皢浣跨敤鎸囧畾鐨勬棩蹇楃骇鍒拰缁熻閫夐」鏉ユ墦鍗板叾缁熻鏁版嵁銆 + */ struct StatisticsProviderPrinter { LogLevel m_logLevel; @@ -253,7 +377,7 @@ struct StatisticsProviderPrinter { : m_logLevel(logLevel), m_statOpts(statOpts) {} - inline void operator()(StatisticsProvider* const& provider) + inline void operator()(StatisticsProvider *const &provider) { if (provider->IsEnabled()) { provider->PrintStatistics(m_logLevel, m_statOpts); @@ -261,13 +385,28 @@ struct StatisticsProviderPrinter { } }; -StatisticsProvider* StatisticsManager::GetStatisticsProvider(const char* name) +/* + * 鍔熻兘锛氭牴鎹悕绉拌幏鍙栫粺璁′俊鎭彁渚涜 + * + * 鍙傛暟鍒楄〃锛 + * name锛氳鏌ユ壘鐨勭粺璁′俊鎭彁渚涜呯殑鍚嶇О + * + * 杩斿洖鍊硷細 + * 濡傛灉鎵惧埌鍖归厤鍚嶇О鐨勭粺璁′俊鎭彁渚涜咃紝鍒欒繑鍥炶鎻愪緵鑰呯殑鎸囬拡锛涘惁鍒欒繑鍥 nullptr銆 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庢牴鎹悕绉版煡鎵惧苟鑾峰彇缁熻淇℃伅鎻愪緵鑰呯殑鎸囬拡銆 + */ +StatisticsProvider *StatisticsManager::GetStatisticsProvider(const char *name) { - StatisticsProvider* result = nullptr; + StatisticsProvider *result = nullptr; pthread_mutex_lock(&m_providersLock); - mot_list::iterator itr = + // 浣跨敤 find_if 鍑芥暟鏌ユ壘鍖归厤鍚嶇О鐨勭粺璁′俊鎭彁渚涜 + mot_list::iterator itr = find_if(m_providers.begin(), m_providers.end(), StatisticsProviderFinder(name)); + + // 濡傛灉鎵惧埌鍖归厤鍚嶇О鐨勬彁渚涜咃紝灏嗗叾璧嬪肩粰 result if (itr != m_providers.end()) { result = *itr; } @@ -276,73 +415,110 @@ StatisticsProvider* StatisticsManager::GetStatisticsProvider(const char* name) return result; } +/* + * 鍔熻兘锛氫负褰撳墠绾跨▼淇濈暀缁熻淇℃伅绾跨▼妲戒綅 + * + * 杩斿洖鍊硷細 + * 濡傛灉鎴愬姛淇濈暀绾跨▼妲戒綅锛岃繑鍥 true锛涘惁鍒欒繑鍥 false銆 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庝负褰撳墠绾跨▼淇濈暀缁熻淇℃伅绾跨▼妲戒綅锛屼互渚胯繘琛岀粺璁′俊鎭殑鏀堕泦鍜岃褰曘 + */ bool StatisticsManager::ReserveThreadSlot() { bool result = false; + // 鑾峰彇褰撳墠绾跨▼鐨勬爣璇嗙 MOTThreadId tid = MOTCurrThreadId; if (tid == INVALID_THREAD_ID) { - MOT_REPORT_ERROR(MOT_ERROR_INTERNAL, - "Reserve Thread Slot for Statistics", - "Invalid attempt to reserve statistics thread slot without current thread identifier denied"); + // 濡傛灉褰撳墠绾跨▼鏍囪瘑绗︽棤鏁堬紝鎶ュ憡閿欒骞舵嫆缁濅繚鐣欑嚎绋嬫Ы浣 + MOT_REPORT_ERROR(MOT_ERROR_INTERNAL, "Reserve Thread Slot for Statistics", + "Invalid attempt to reserve statistics thread slot without current thread identifier denied"); } else { + // 鑾峰彇缁熻淇℃伅鎻愪緵鑰呴攣锛岀‘淇濈嚎绋嬪畨鍏 pthread_mutex_lock(&m_providersLock); + // 榛樿鎯呭喌涓嬶紝鍋囪鎴愬姛淇濈暀绾跨▼妲戒綅 result = true; MOT_LOG_TRACE("Reserving statistics thread slot for thread id %" PRIu16, tid); - mot_list::iterator itr = m_providers.begin(); + + // 閬嶅巻缁熻淇℃伅鎻愪緵鑰呭垪琛紝涓烘瘡涓彁渚涜呬繚鐣欑嚎绋嬫Ы浣 + mot_list::iterator itr = m_providers.begin(); while (itr != m_providers.end()) { - StatisticsProvider* provider = *itr; + StatisticsProvider *provider = *itr; if (!provider->ReserveThreadSlot()) { + // 濡傛灉鏌愪釜鎻愪緵鑰呮棤娉曚繚鐣欑嚎绋嬫Ы浣嶏紝鍒欐爣璁扮粨鏋滀负澶辫触骞朵腑姝㈤亶鍘 result = false; break; } ++itr; } + // 閲婃斁缁熻淇℃伅鎻愪緵鑰呴攣锛岀粨鏉熷嚱鏁 pthread_mutex_unlock(&m_providersLock); } return result; } +/* + * 鍔熻兘锛氬彇娑堜负褰撳墠绾跨▼淇濈暀鐨勭粺璁′俊鎭嚎绋嬫Ы浣 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庡彇娑堝綋鍓嶇嚎绋嬩繚鐣欑殑缁熻淇℃伅绾跨▼妲戒綅锛屼互渚垮湪绾跨▼閫鍑烘椂閲婃斁鐩稿簲鐨勮祫婧愩 + */ void StatisticsManager::UnreserveThreadSlot() { MOTThreadId tid = MOTCurrThreadId; if (tid == INVALID_THREAD_ID) { + // 濡傛灉褰撳墠绾跨▼鏍囪瘑绗︽棤鏁堬紝鎶ュ憡閿欒 MOT_LOG_ERROR("Invalid attempt to un-reserve statistics thread slot without current thread identifier denied"); } else { + // 鑾峰彇缁熻淇℃伅鎻愪緵鑰呴攣锛岀‘淇濈嚎绋嬪畨鍏 pthread_mutex_lock(&m_providersLock); MOT_LOG_TRACE("Un-reserving statistics thread slot for thread id %" PRIu16, tid); - mot_list::iterator itr = m_providers.begin(); + // 閬嶅巻缁熻淇℃伅鎻愪緵鑰呭垪琛紝骞跺彇娑堜负褰撳墠绾跨▼淇濈暀鐨勭嚎绋嬫Ы浣 + mot_list::iterator itr = m_providers.begin(); while (itr != m_providers.end()) { - StatisticsProvider* provider = *itr; + StatisticsProvider *provider = *itr; provider->UnreserveThreadSlot(); ++itr; } + // 閲婃斁缁熻淇℃伅鎻愪緵鑰呴攣锛岀粨鏉熷嚱鏁 pthread_mutex_unlock(&m_providersLock); } } +/* + * 鍔熻兘锛氭墦鍗扮粺璁′俊鎭 + * + * 鍙傛暟鍒楄〃锛 + * logLevel锛氭棩蹇楃骇鍒紝鐢ㄤ簬纭畾瑕佽緭鍑虹殑鏃ュ織绾у埆 + * statOpts锛氱粺璁¢夐」锛屾寚绀鸿鎵撳嵃鐨勭粺璁′俊鎭被鍨 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庢墦鍗扮粺璁′俊鎭紝鏍规嵁涓嶅悓鐨勭粺璁¢夐」閫夋嫨涓嶅悓鐨勮緭鍑烘柟寮忋 + */ void StatisticsManager::PrintStatistics(LogLevel logLevel, uint32_t statOpts /* = STAT_OPT_DEFAULT */) { pthread_mutex_lock(&m_providersLock); - // make sure there is at least one enabled provider with some statistics + // 纭繚鑷冲皯鏈変竴涓惎鐢ㄧ殑鎻愪緵鑰呭叿鏈変竴浜涚粺璁′俊鎭 if (!m_providers.empty()) { bool hasEnabled = false; bool hasStats = false; - mot_list::iterator itr = m_providers.begin(); + mot_list::iterator itr = m_providers.begin(); while (itr != m_providers.end()) { - StatisticsProvider* provider = *itr; + StatisticsProvider *provider = *itr; if (provider->IsEnabled()) { hasEnabled = true; provider->Summarize(); if (provider->HasStatisticsFor(statOpts)) { hasStats = true; } + // 缁х画瀵瑰叾浠栫粺璁℃彁渚涜呰繘琛岀粺璁℃荤粨 // continue summarizing statistics for other statistics providers } ++itr; @@ -365,21 +541,31 @@ void StatisticsManager::PrintStatistics(LogLevel logLevel, uint32_t statOpts /* pthread_mutex_unlock(&m_providersLock); } - +/* + * 鍔熻兘锛氬惎鍔ㄧ粺璁′俊鎭墦鍗扮嚎绋 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庡垱寤哄拰鍚姩涓涓柊鐨勭嚎绋嬶紝璇ョ嚎绋嬭礋璐e畾鏈熸墦鍗扮粺璁′俊鎭 + */ bool StatisticsManager::StartStatsPrintThread() { if (!m_running) { int rc = pthread_create(&m_statsThread, nullptr, StatsPrintThreadStatic, this); if (rc != 0) { - MOT_REPORT_SYSTEM_ERROR_CODE( - rc, pthread_create, "Statistics Manager Initialization", "Failed to create statistics printing thread"); + MOT_REPORT_SYSTEM_ERROR_CODE(rc, pthread_create, "Statistics Manager Initialization", + "Failed to create statistics printing thread"); } else { m_running = true; } } return m_running; } - +/* + * 鍔熻兘锛氬仠姝㈢粺璁′俊鎭墦鍗扮嚎绋 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庡仠姝㈡鍦ㄨ繍琛岀殑缁熻淇℃伅鎵撳嵃绾跨▼銆傚畠浼氬彂閫佷俊鍙蜂互閫氱煡绾跨▼鍋滄锛屽苟绛夊緟绾跨▼缁撴潫銆 + */ void StatisticsManager::StopStatsPrintThread() { // signal done flag and wake up statistics printing thread @@ -394,14 +580,28 @@ void StatisticsManager::StopStatsPrintThread() } } -void* StatisticsManager::StatsPrintThreadStatic(void* param) +/* + * 鍔熻兘锛氱粺璁′俊鎭墦鍗扮嚎绋嬬殑闈欐佸洖璋冨嚱鏁 + * + * 鍙傛暟锛 + * param锛氭寚鍚 StatisticsManager 瀹炰緥鐨勬寚閽 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁版槸缁熻淇℃伅鎵撳嵃绾跨▼鐨勯潤鎬佸洖璋冨嚱鏁帮紝鐢ㄤ簬鍒涘缓绾跨▼骞惰皟鐢 StatisticsManager 瀹炰緥鐨 StatsPrintThread 鍑芥暟銆 + */ +void *StatisticsManager::StatsPrintThreadStatic(void *param) { - auto pThis = reinterpret_cast(param); + auto pThis = reinterpret_cast(param); knl_thread_mot_init(); pThis->StatsPrintThread(); return nullptr; } - +/* + * 鍔熻兘锛氭墽琛岀粺璁′俊鎭墦鍗扮殑绾跨▼鍑芥暟 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁版墽琛岀粺璁′俊鎭墦鍗扮殑绾跨▼鍔熻兘銆傚畠瀹氭湡鎵撳嵃缁熻淇℃伅鎶ュ憡锛屽寘鎷懆鏈熸ф姤鍛婂拰瀹屾暣鎶ュ憡锛屽苟鍦ㄩ鍑哄墠鏈鍚庢墦鍗颁竴娆″畬鏁存姤鍛娿 + */ void StatisticsManager::StatsPrintThread() { MOT_LOG_INFO("Statistics thread started"); @@ -439,19 +639,39 @@ void StatisticsManager::StatsPrintThread() MOT_LOG_INFO("Statistics thread stopped"); } +/* + * 鍔熻兘锛氱瓑寰呬笅涓娆℃墦鍗扮粺璁′俊鎭殑鏃堕棿鐐 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁拌绠楀苟绛夊緟涓嬩竴娆℃墦鍗扮粺璁′俊鎭殑鏃堕棿鐐广傚畠浣跨敤褰撳墠鏃堕棿鍜岄瀹氫箟鐨勭粺璁′俊鎭鏌ュ懆鏈熸潵璁$畻绛夊緟鏃堕棿銆 + * 绛夊緟鏃堕棿鍒拌揪鍚庯紝绾跨▼灏嗚鍞ら啋浠ユ墽琛岀粺璁′俊鎭墦鍗般 + */ void StatisticsManager::WaitNextPrint() { + // 鑾峰彇褰撳墠鏃堕棿 struct timeval now; gettimeofday(&now, nullptr); + // 璁$畻绛夊緟鏃堕棿锛屼娇鐢ㄥ綋鍓嶆椂闂村拰棰勫畾涔夌殑缁熻淇℃伅妫鏌ュ懆鏈 struct timespec ts = {(time_t)(now.tv_sec + STAT_PRINT_CHECK_PERIOD_SECONDS), now.tv_usec * 1000L}; - + // 鑾峰彇鎵撳嵃缁熻淇℃伅鐨勯攣锛屼互纭繚绾跨▼瀹夊叏 pthread_mutex_lock(&m_statsPrintLock); + // 绛夊緟涓嬩竴娆℃墦鍗版椂闂村埌杈撅紝鎴栬呯瓑寰呰鍏朵粬绾跨▼鍞ら啋 pthread_cond_timedwait(&m_statsPrintCond, &m_statsPrintLock, &ts); + // 閲婃斁鎵撳嵃缁熻淇℃伅鐨勯攣 pthread_mutex_unlock(&m_statsPrintLock); } + } // namespace MOT +/* + * 鍔熻兘锛氭墦鍗版墍鏈夌粺璁′俊鎭 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庝粠 MOT::StatisticsManager 鑾峰彇鎵鏈夌粺璁′俊鎭紝骞朵互鎸囧畾鐨勬棩蹇楃骇鍒(LL_INFO)鎵撳嵃鍑烘潵銆 + * 瀹冩槸涓涓畝渚跨殑鍑芥暟锛屽彲鐢ㄤ簬鍦ㄤ唬鐮佷腑璋冪敤浠ユ墦鍗板綋鍓嶇殑缁熻淇℃伅銆 + */ void dumpStats() { + // 鑾峰彇 StatisticsManager 瀹炰緥骞惰皟鐢 PrintAllStatistics 鏂规硶鎵撳嵃鎵鏈夌粺璁′俊鎭 MOT::StatisticsManager::GetInstance().PrintAllStatistics(MOT::LogLevel::LL_INFO); } diff --git a/src/gausskernel/storage/mot/core/infra/stats/statistics_provider.cpp b/src/gausskernel/storage/mot/core/infra/stats/statistics_provider.cpp index b13f06997..e474a73f5 100644 --- a/src/gausskernel/storage/mot/core/infra/stats/statistics_provider.cpp +++ b/src/gausskernel/storage/mot/core/infra/stats/statistics_provider.cpp @@ -33,9 +33,21 @@ namespace MOT { DECLARE_LOGGER(StatisticsProvider, Statistics) - -StatisticsProvider::StatisticsProvider( - const char* name, StatisticsGenerator* generator, bool enable, bool extended /* = false */) +/* + * 鍔熻兘锛歋tatisticsProvider 绫荤殑鏋勯犲嚱鏁 + * + * 鍙傛暟鍒楄〃锛 + * name锛氭彁渚涚▼搴忕殑鍚嶇О + * generator锛氫笌姝ゆ彁渚涚▼搴忓叧鑱旂殑缁熻鐢熸垚鍣 + * enable锛氭槸鍚﹀惎鐢ㄦ鎻愪緵绋嬪簭 + * extended锛氭槸鍚﹀惎鐢ㄦ墿灞曠粺璁′俊鎭紙榛樿涓 false锛 + * + * 娉ㄦ剰锛 + * 姝ゆ瀯閫犲嚱鏁扮敤浜庡垱寤 StatisticsProvider 鐨勫疄渚嬶紝瀹冩帴鍙楁彁渚涚▼搴忕殑鍚嶇О銆佷笌涔嬪叧鑱旂殑缁熻鐢熸垚鍣ㄣ + * 鍚敤鐘舵佷互鍙婃槸鍚﹀惎鐢ㄦ墿灞曠粺璁′俊鎭傚畠杩樺垵濮嬪寲浜嗘彁渚涚▼搴忕殑鍚勭缁熻淇℃伅瀵硅薄銆 + */ +StatisticsProvider::StatisticsProvider(const char *name, StatisticsGenerator *generator, bool enable, + bool extended /* = false */) : m_enable(enable), m_generator(generator), m_threadStats(nullptr), @@ -51,116 +63,158 @@ StatisticsProvider::StatisticsProvider( m_prevGlobalStats(nullptr), m_diffGlobalStats(nullptr) { + // 浣跨敤 snprintf_s 鍑芥暟灏嗘彁渚涚▼搴忕殑鍚嶇О澶嶅埗鍒版垚鍛樺彉閲 m_name 涓 errno_t erc = snprintf_s(m_name, MAX_PROVIDER_NAME, MAX_PROVIDER_NAME - 1, "%s", name); securec_check_ss(erc, "\0", "\0"); } +/* + * 鍔熻兘锛歋tatisticsProvider 绫荤殑鏋愭瀯鍑芥暟 + * + * 娉ㄦ剰锛 + * 姝ゆ瀽鏋勫嚱鏁扮敤浜庨攢姣 StatisticsProvider 鐨勫疄渚嬶紝閲婃斁涓庢彁渚涚▼搴忕浉鍏崇殑缁熻淇℃伅瀵硅薄鐨勫唴瀛樸 + */ StatisticsProvider::~StatisticsProvider() { + // 閲婃斁鍏ㄥ眬缁熻淇℃伅瀵硅薄鐨勫唴瀛 if (m_globalStats) { delete m_globalStats; } + + // 閲婃斁鍏堝墠鐨勫叏灞缁熻淇℃伅瀵硅薄鐨勫唴瀛 if (m_prevGlobalStats) { delete m_prevGlobalStats; } + + // 閲婃斁宸紓鍏ㄥ眬缁熻淇℃伅瀵硅薄鐨勫唴瀛 if (m_diffGlobalStats) { delete m_diffGlobalStats; } - + // 閲婃斁绾跨▼缁熻淇℃伅瀵硅薄鏁扮粍鐨勫唴瀛 if (m_threadStats) { for (uint32_t i = 0; i < m_threadStatCount; ++i) { if (m_threadStats[i] != nullptr) { + // 璋冪敤 FreeThreadStats 鍑芥暟閲婃斁绾跨▼缁熻淇℃伅瀵硅薄鐨勫唴瀛 FreeThreadStats(i, m_threadStats[i]); } } free(m_threadStats); } - + // 閲婃斁鑱氬悎缁熻淇℃伅瀵硅薄鐨勫唴瀛 if (m_aggregateStats) { delete m_aggregateStats; } + // 閲婃斁鍏堝墠鐨勮仛鍚堢粺璁′俊鎭璞$殑鍐呭瓨 if (m_prevAggregateStats) { delete m_prevAggregateStats; } + // 閲婃斁骞冲潎缁熻淇℃伅瀵硅薄鐨勫唴瀛 if (m_averageStats) { delete m_averageStats; } + // 閲婃斁宸紓缁熻淇℃伅瀵硅薄鐨勫唴瀛 if (m_diffStats) { delete m_diffStats; } + // 閲婃斁宸紓骞冲潎缁熻淇℃伅瀵硅薄鐨勫唴瀛 if (m_diffAverageStats) { delete m_diffAverageStats; } - + // 閲婃斁姝荤嚎绋嬬粺璁′俊鎭璞$殑鍐呭瓨 if (m_deadThreadStats) { delete m_deadThreadStats; } } +/* + * 鍔熻兘锛歋tatisticsProvider 绫荤殑鍒濆鍖栧嚱鏁 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庡垵濮嬪寲 StatisticsProvider 鐨勫疄渚嬶紝鍖呮嫭鍒涘缓鍚勭缁熻淇℃伅瀵硅薄浠ュ強鍒濆鍖栦簰鏂ラ攣銆 + * + * 杩斿洖鍊硷細 + * - 濡傛灉鍒濆鍖栨垚鍔燂紝杩斿洖 true銆 + * - 濡傛灉鍙戠敓閿欒锛堜緥濡傚唴瀛樺垎閰嶅け璐ユ垨浜掓枼閿佸垱寤哄け璐ワ級锛屽垯杩斿洖 false銆 + */ bool StatisticsProvider::Initialize() { + // 鍒涘缓绾跨▼鑱氬悎缁熻淇℃伅瀵硅薄 m_aggregateStats = m_generator->CreateThreadStatistics(ThreadStatistics::THREAD_ID_TOTAL); + // 鍒涘缓鍏堝墠绾跨▼鑱氬悎缁熻淇℃伅瀵硅薄 m_prevAggregateStats = m_generator->CreateThreadStatistics(ThreadStatistics::THREAD_ID_TOTAL); + // 鍒涘缓绾跨▼骞冲潎缁熻淇℃伅瀵硅薄 m_averageStats = m_generator->CreateThreadStatistics(ThreadStatistics::THREAD_ID_AVG); + // 鍒涘缓绾跨▼宸紓缁熻淇℃伅瀵硅薄 m_diffStats = m_generator->CreateThreadStatistics(ThreadStatistics::THREAD_ID_DIFF); + // 鍒涘缓绾跨▼宸紓骞冲潎缁熻淇℃伅瀵硅薄 m_diffAverageStats = m_generator->CreateThreadStatistics(ThreadStatistics::THREAD_ID_DIFF_AVG); + // 鍒涘缓姝荤嚎绋嬬粺璁′俊鎭璞 m_deadThreadStats = m_generator->CreateThreadStatistics(ThreadStatistics::THREAD_ID_TOTAL); + // 妫鏌ユ槸鍚︽垚鍔熷垱寤烘墍鏈夌嚎绋嬬粺璁′俊鎭璞 if (!m_aggregateStats || !m_prevAggregateStats || !m_averageStats || !m_diffStats || !m_diffAverageStats || !m_deadThreadStats) { MOT_REPORT_ERROR(MOT_ERROR_OOM, "Load Statistics", "Failed to create thread statistics object(s)"); - return false; // safe cleanup in object destruction + return false; // 鍦ㄥ璞¢攢姣佹椂杩涜瀹夊叏娓呯悊 } - + // 鑾峰彇鏈澶х嚎绋嬫暟骞跺垱寤虹嚎绋嬬粺璁′俊鎭璞℃暟缁 m_threadStatCount = GetGlobalConfiguration().m_maxThreads; - m_threadStats = (ThreadStatistics**)calloc(m_threadStatCount, sizeof(ThreadStatistics*)); + m_threadStats = (ThreadStatistics **)calloc(m_threadStatCount, sizeof(ThreadStatistics *)); if (!m_threadStats) { - MOT_REPORT_ERROR(MOT_ERROR_OOM, - "Load Statistics", - "Failed to create thread statistics array in size of %u slots", - m_threadStatCount); + MOT_REPORT_ERROR(MOT_ERROR_OOM, "Load Statistics", + "Failed to create thread statistics array in size of %u slots", m_threadStatCount); return false; } - + // 鍒涘缓鍏ㄥ眬缁熻淇℃伅瀵硅薄 m_globalStats = m_generator->CreateGlobalStatistics(GlobalStatistics::NamingScheme::NAMING_SCHEME_TOTAL); + // 鍒涘缓鍏堝墠鐨勫叏灞缁熻淇℃伅瀵硅薄 m_prevGlobalStats = m_generator->CreateGlobalStatistics(GlobalStatistics::NamingScheme::NAMING_SCHEME_TOTAL); + // 鍒涘缓宸紓鍏ㄥ眬缁熻淇℃伅瀵硅薄 m_diffGlobalStats = m_generator->CreateGlobalStatistics(GlobalStatistics::NamingScheme::NAMING_SCHEME_DIFF); + // 妫鏌ユ槸鍚︽垚鍔熷垱寤烘墍鏈夊叏灞缁熻淇℃伅瀵硅薄 if (!m_globalStats || !m_prevGlobalStats || !m_diffGlobalStats) { MOT_REPORT_ERROR(MOT_ERROR_OOM, "Load Statistics", "Failed to create global statistics object(s)"); return false; } - + // 鍒涘缓骞跺垵濮嬪寲浜掓枼閿 int rc = pthread_spin_init(&m_statLock, 0); if (rc != 0) { MOT_REPORT_SYSTEM_ERROR_CODE(rc, pthread_spin_init, "Load Statistics", "Failed to create statistics lock"); return false; } - return true; } +/* + * 鍔熻兘锛氫负缁熻鎻愪緵鑰呬繚鐣欑嚎绋嬫Ы + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庝负缁熻鎻愪緵鑰呯殑绾跨▼淇濈暀妲戒綅锛屼互瀛樺偍绾跨▼鐨勭粺璁′俊鎭 + */ bool StatisticsProvider::ReserveThreadSlot() { bool result = false; + // 鑾峰彇褰撳墠绾跨▼鐨勬爣璇嗙鍜岃妭鐐规爣璇嗙 MOTThreadId threadId = MOTCurrThreadId; int node = MOTCurrentNumaNodeId; + + // 妫鏌ョ嚎绋嬪拰鑺傜偣鏍囪瘑绗︽槸鍚︽湁鏁 if ((threadId == INVALID_THREAD_ID) || (node == MEM_INVALID_NODE)) { - MOT_REPORT_ERROR(MOT_ERROR_INTERNAL, - "Reserve Thread Slot for Statistics", + MOT_REPORT_ERROR( + MOT_ERROR_INTERNAL, "Reserve Thread Slot for Statistics", "Invalid attempt to reserve statistics thread slot without current thread/node identifier denied (thread " "id: %u, node id: %d)", - (unsigned)threadId, - node); + (unsigned)threadId, node); } else { // there is no race here because only the current thread modifies its own slot if (m_threadStats[threadId] != nullptr) { MOT_LOG_TRACE("Double attempt to reserve statistics thread slot for thread %" PRIu16 " silently ignored: thread slot already reserved", - threadId); + threadId); result = true; } else { MOT_LOG_TRACE("Reserving %s statistics thread slot for thread id %" PRIu16, GetName(), threadId); - void* buffer = nullptr; + void *buffer = nullptr; // since statistics provider is created before MemInit(), it is preferred to keep it clean from MM API calls if (GetGlobalConfiguration().m_numaNodes > 1) { buffer = MemNumaAllocLocal(m_generator->GetObjectSize(), node); @@ -168,10 +222,8 @@ bool StatisticsProvider::ReserveThreadSlot() buffer = malloc(m_generator->GetObjectSize()); } if (buffer == nullptr) { - MOT_REPORT_ERROR(MOT_ERROR_OOM, - "Reserve Thread Slot for Statistics", - "Failed to allocate buffer in size of %u bytes", - m_generator->GetObjectSize()); + MOT_REPORT_ERROR(MOT_ERROR_OOM, "Reserve Thread Slot for Statistics", + "Failed to allocate buffer in size of %u bytes", m_generator->GetObjectSize()); } else { pthread_spin_lock(&m_statLock); m_threadStats[threadId] = m_generator->CreateThreadStatistics(threadId, buffer); @@ -184,7 +236,13 @@ bool StatisticsProvider::ReserveThreadSlot() return result; } - +/* + * 鍔熻兘锛氬彇娑堜繚鐣欑嚎绋嬫Ы + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庡彇娑堜繚鐣欑嚎绋嬫Ы锛屽皢绾跨▼鐨勭粺璁′俊鎭Щ鍔ㄥ埌姝荤嚎绋嬪垪琛ㄤ腑銆 + * 缁熻淇℃伅灏嗕繚鐣欏湪閭i噷锛岀洿鍒颁笅涓娆℃憳瑕佹墦鍗帮紝鐒跺悗鍐嶆鍥炴敹銆 + */ void StatisticsProvider::UnreserveThreadSlot() { // move the statistics to the dead thread list @@ -196,11 +254,11 @@ void StatisticsProvider::UnreserveThreadSlot() if (m_threadStats[threadId] == nullptr) { MOT_LOG_TRACE("Attempt to unreserve statistics thread slot for thread %" PRIu16 " silently ignored: thread slot already unreserved", - threadId); + threadId); } else { // aggregate dead thread statistics and cleanup pthread_spin_lock(&m_statLock); - ThreadStatistics* threadStats = m_threadStats[threadId]; + ThreadStatistics *threadStats = m_threadStats[threadId]; m_deadThreadStats->Add(*threadStats); m_threadStats[threadId] = nullptr; // this must be guarded with a lock due to race with Summarize() pthread_spin_unlock(&m_statLock); @@ -210,10 +268,17 @@ void StatisticsProvider::UnreserveThreadSlot() } } +/* + * 鍔熻兘锛氭荤粨缁熻淇℃伅 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庢荤粨缁熻淇℃伅锛屽寘鎷嚎绋嬬骇鍒佸叏灞绾у埆鍜屽樊寮傜骇鍒殑缁熻淇℃伅銆 + */ void StatisticsProvider::Summarize() { pthread_spin_lock(&m_statLock); + // 澶囦唤骞堕噸缃仛鍚堢粺璁′俊鎭 m_prevAggregateStats->Assign(*m_aggregateStats); m_aggregateStats->Reset(); m_averageStats->Reset(); @@ -256,20 +321,39 @@ void StatisticsProvider::Summarize() m_prevGlobalStats->Assign(*m_globalStats); } +/* + * 鍔熻兘锛氭鏌ユ槸鍚﹀瓨鍦ㄦ弧瓒崇粰瀹氱粺璁¢夐」鐨勬湁鏁堢粺璁℃暟鎹 + * + * 鍙傛暟鍒楄〃锛 + * statOpts锛氭寚瀹氳妫鏌ョ殑缁熻閫夐」锛屽彲浠ユ槸澶氫釜閫夐」鐨勬寜浣嶇粍鍚 + * + * 杩斿洖鍊硷細 + * 濡傛灉瀛樺湪婊¤冻缁欏畾缁熻閫夐」鐨勬湁鏁堢粺璁℃暟鎹紝鍒欒繑鍥 true锛涘惁鍒欒繑鍥 false銆 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庢鏌ユ槸鍚﹀瓨鍦ㄦ弧瓒崇粰瀹氱粺璁¢夐」鐨勬湁鏁堢粺璁℃暟鎹傛牴鎹粺璁¢夐」鐨勪笉鍚岋紝浼氭鏌ヤ笉鍚岀殑缁熻鏁版嵁瀵硅薄銆 + */ bool StatisticsProvider::HasStatisticsFor(uint32_t statOpts) { bool result = m_hasExtendedStats; + + // 濡傛灉闇瑕佺嚎绋嬬骇鍒殑缁熻鏁版嵁 if (!result && (statOpts & STAT_OPT_SCOPE_THREAD)) { + // 妫鏌ユ憳瑕佺骇鍒殑宸紓缁熻鏁版嵁鏄惁鏈夋湁鏁堟牱鏈 if (statOpts & STAT_OPT_LEVEL_SUMMARY) { result = m_diffStats->HasValidSamples(); } + // 濡傛灉娌℃湁鎵惧埌婊¤冻鎽樿绾у埆瑕佹眰鐨勭粺璁℃暟鎹紝妫鏌ヨ缁嗙骇鍒殑宸紓骞冲潎缁熻鏁版嵁 if (!result && (statOpts & STAT_OPT_LEVEL_DETAIL)) { result = m_diffAverageStats->HasValidSamples(); } } + // 濡傛灉闇瑕佸叏灞绾у埆鐨勭粺璁℃暟鎹 if (!result && (statOpts & STAT_OPT_SCOPE_GLOBAL)) { + // 濡傛灉闇瑕佽缁嗙骇鍒殑缁熻鏁版嵁 if (statOpts & STAT_OPT_LEVEL_DETAIL) { + // 棣栧厛鑾峰彇閿佷互璁块棶绾跨▼绾у埆鐨勭粺璁℃暟鎹 pthread_spin_lock(&m_statLock); for (uint32_t i = 0; i < m_threadStatCount; ++i) { if (m_threadStats[i] != nullptr) { @@ -279,11 +363,16 @@ bool StatisticsProvider::HasStatisticsFor(uint32_t statOpts) } } } + // 閲婃斁閿 pthread_spin_unlock(&m_statLock); + + // 濡傛灉娌℃湁鎵惧埌婊¤冻璇︾粏绾у埆瑕佹眰鐨勭嚎绋嬬骇鍒殑缁熻鏁版嵁锛屾鏌ュ钩鍧囩粺璁℃暟鎹 if (!result) { result = m_averageStats->HasValidSamples(); } } + + // 濡傛灉娌℃湁鎵惧埌婊¤冻鎽樿绾у埆瑕佹眰鐨勭粺璁℃暟鎹紝妫鏌ヨ仛鍚堢粺璁℃暟鎹 if (!result && (statOpts & STAT_OPT_LEVEL_SUMMARY)) { result = m_aggregateStats->HasValidSamples(); } @@ -292,71 +381,135 @@ bool StatisticsProvider::HasStatisticsFor(uint32_t statOpts) return result; } +/* + * 鍔熻兘锛氭墦鍗扮粺璁℃暟鎹 + * + * 鍙傛暟鍒楄〃锛 + * logLevel锛氭寚瀹氳浣跨敤鐨勬棩蹇楃骇鍒紝鐢ㄤ簬鎵撳嵃缁熻鏁版嵁 + * statOpts锛氭寚瀹氳鎵撳嵃鐨勭粺璁¢夐」锛屽彲浠ユ槸澶氫釜閫夐」鐨勬寜浣嶇粍鍚堬紝榛樿涓 STAT_OPT_DEFAULT + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庢牴鎹粰瀹氱殑缁熻閫夐」鎵撳嵃缁熻鏁版嵁銆傛牴鎹粺璁¢夐」鐨勪笉鍚岋紝浼氭墦鍗扮嚎绋嬬骇鍒拰鍏ㄥ眬绾у埆鐨勭粺璁℃暟鎹 + */ void StatisticsProvider::PrintStatistics(LogLevel logLevel, uint32_t statOpts /* = STAT_OPT_DEFAULT */) { + // 濡傛灉闇瑕佺嚎绋嬬骇鍒殑缁熻鏁版嵁 if (statOpts & STAT_OPT_SCOPE_THREAD) { for (uint32_t statId = 0; statId < m_aggregateStats->GetStatCount(); ++statId) { + // 鎵撳嵃绾跨▼绾у埆鐨勭粺璁℃暟鎹 PrintThreadStats(statOpts, statId, logLevel); } } + + // 濡傛灉闇瑕佸叏灞绾у埆鐨勭粺璁℃暟鎹 if (statOpts & STAT_OPT_SCOPE_GLOBAL) { for (uint32_t statId = 0; statId < m_globalStats->GetStatCount(); ++statId) { + // 鎵撳嵃鍏ㄥ眬绾у埆鐨勭粺璁℃暟鎹 PrintGlobalStats(statOpts, statId, logLevel); } } + // 鎵撳嵃棰濆鐨勭粺璁℃暟鎹紙鏈彁渚涘叿浣撳疄鐜帮紝鍙兘鍦ㄥ悗缁唬鐮佷腑瀹氫箟锛 PrintStatisticsEx(); } +/* + * 鍔熻兘锛氭墦鍗扮嚎绋嬬骇鍒殑缁熻鏁版嵁 + * + * 鍙傛暟鍒楄〃锛 + * statOpts锛氭寚瀹氳鎵撳嵃鐨勭粺璁¢夐」锛屽彲浠ユ槸澶氫釜閫夐」鐨勬寜浣嶇粍鍚 + * statId锛氳鎵撳嵃鐨勭粺璁℃暟鎹爣璇嗙 + * logLevel锛氭寚瀹氳浣跨敤鐨勬棩蹇楃骇鍒紝鐢ㄤ簬鎵撳嵃缁熻鏁版嵁 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庢墦鍗扮嚎绋嬬骇鍒殑缁熻鏁版嵁锛屾牴鎹粰瀹氱殑缁熻閫夐」鍜岀粺璁℃暟鎹爣璇嗙鏉ョ‘瀹氳鎵撳嵃鍝簺鏁版嵁浠ュ強浣跨敤鍝釜鏃ュ織绾у埆銆 + */ void StatisticsProvider::PrintThreadStats(uint32_t statOpts, uint32_t statId, LogLevel logLevel) { - // print diff stats + // 濡傛灉闇瑕佹墦鍗板懆鏈熷樊寮傜粺璁℃暟鎹 if (statOpts & STAT_OPT_PERIOD_DIFF) { + // 濡傛灉闇瑕佹墦鍗版憳瑕佺骇鍒殑缁熻鏁版嵁 if (statOpts & STAT_OPT_LEVEL_SUMMARY) { + // 鎵撳嵃宸紓缁熻鏁版嵁 m_diffStats->Print(statId, logLevel); } + + // 濡傛灉闇瑕佹墦鍗拌缁嗙骇鍒殑缁熻鏁版嵁 if (statOpts & STAT_OPT_LEVEL_DETAIL) { + // 鎵撳嵃宸紓骞冲潎缁熻鏁版嵁 m_diffAverageStats->Print(statId, logLevel); } } - // print total stats + // 濡傛灉闇瑕佹墦鍗板懆鏈熸昏缁熻鏁版嵁 if (statOpts & STAT_OPT_PERIOD_TOTAL) { + // 濡傛灉闇瑕佹墦鍗拌缁嗙骇鍒殑缁熻鏁版嵁 if (statOpts & STAT_OPT_LEVEL_DETAIL) { pthread_spin_lock(&m_statLock); for (uint32_t i = 0; i < m_threadStatCount; ++i) { if (m_threadStats[i] != nullptr) { + // 鎵撳嵃绾跨▼绾у埆鐨勭粺璁℃暟鎹 m_threadStats[i]->Print(statId, logLevel); } } pthread_spin_unlock(&m_statLock); + + // 鎵撳嵃骞冲潎缁熻鏁版嵁 m_averageStats->Print(statId, logLevel); } + + // 濡傛灉闇瑕佹墦鍗版憳瑕佺骇鍒殑缁熻鏁版嵁 if (statOpts & STAT_OPT_LEVEL_SUMMARY) { + // 鎵撳嵃鑱氬悎缁熻鏁版嵁 m_aggregateStats->Print(statId, logLevel); } } } - +/* + * 鍔熻兘锛氭墦鍗板叏灞绾у埆鐨勭粺璁℃暟鎹 + * + * 鍙傛暟鍒楄〃锛 + * statOpts锛氭寚瀹氳鎵撳嵃鐨勭粺璁¢夐」锛屽彲浠ユ槸澶氫釜閫夐」鐨勬寜浣嶇粍鍚 + * statId锛氳鎵撳嵃鐨勭粺璁℃暟鎹爣璇嗙 + * logLevel锛氭寚瀹氳浣跨敤鐨勬棩蹇楃骇鍒紝鐢ㄤ簬鎵撳嵃缁熻鏁版嵁 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庢墦鍗板叏灞绾у埆鐨勭粺璁℃暟鎹紝鏍规嵁缁欏畾鐨勭粺璁¢夐」鍜岀粺璁℃暟鎹爣璇嗙鏉ョ‘瀹氳鎵撳嵃鍝簺鏁版嵁浠ュ強浣跨敤鍝釜鏃ュ織绾у埆銆 + */ void StatisticsProvider::PrintGlobalStats(uint32_t statOpts, uint32_t statId, LogLevel logLevel) { // print diff stats if (statOpts & STAT_OPT_PERIOD_DIFF) { + // 鎵撳嵃宸紓缁熻鏁版嵁 m_diffGlobalStats->Print(statId, logLevel); } // print total stats + // 濡傛灉闇瑕佹墦鍗板懆鏈熸昏缁熻鏁版嵁锛屽苟涓斾笉闇瑕佹墦鍗拌缁嗙骇鍒殑缁熻鏁版嵁 if ((statOpts & STAT_OPT_PERIOD_TOTAL) && !(statOpts & STAT_OPT_LEVEL_DETAIL)) { m_globalStats->Print(statId, logLevel); } } -void StatisticsProvider::FreeThreadStats(MOTThreadId threadId, ThreadStatistics* threadStats) +/* + * 鍔熻兘锛氶噴鏀剧嚎绋嬬粺璁℃暟鎹 + * + * 鍙傛暟鍒楄〃锛 + * threadId锛氳閲婃斁缁熻鏁版嵁鐨勭嚎绋嬫爣璇嗙 + * threadStats锛氭寚鍚戣閲婃斁鐨勭嚎绋嬬粺璁℃暟鎹璞$殑鎸囬拡 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庨噴鏀剧嚎绋嬬骇鍒殑缁熻鏁版嵁锛屽寘鎷唴瀛樼殑鍥炴敹銆傚畠鏍规嵁绾跨▼鏍囪瘑绗﹁幏鍙栬閲婃斁鐨勭粺璁℃暟鎹紝鐒跺悗鍥炴敹鐩稿叧鐨勫唴瀛樸 + */ +void StatisticsProvider::FreeThreadStats(MOTThreadId threadId, ThreadStatistics *threadStats) { MOT_LOG_TRACE("Reclaiming %s statistics thread slot for thread id %" PRIu16, GetName(), threadId); - void* buffer = (void*)threadStats->GetInPlaceBuffer(); + // 鑾峰彇瑕佸洖鏀剁殑鍐呭瓨缂撳啿鍖 + void *buffer = (void *)threadStats->GetInPlaceBuffer(); int node = threadStats->GetNodeId(); + // 閿姣佺嚎绋嬬粺璁℃暟鎹璞 threadStats->~ThreadStatistics(); + // 鏍规嵁閰嶇疆鐨凬UMA鑺傜偣鏁拌繘琛屽唴瀛樺洖鏀 if (GetGlobalConfiguration().m_numaNodes > 1) { MemNumaFreeLocal(buffer, m_generator->GetObjectSize(), node); } else { diff --git a/src/gausskernel/storage/mot/core/infra/stats/thread_statistics.cpp b/src/gausskernel/storage/mot/core/infra/stats/thread_statistics.cpp index 6a9ebb6bf..36ef52425 100644 --- a/src/gausskernel/storage/mot/core/infra/stats/thread_statistics.cpp +++ b/src/gausskernel/storage/mot/core/infra/stats/thread_statistics.cpp @@ -27,23 +27,53 @@ namespace MOT { DECLARE_LOGGER(ThreadStatistics, Statistics) +/* + * 鍔熻兘锛氭眹鎬荤嚎绋嬬粺璁℃暟鎹 + * + * 鍙傛暟鍒楄〃锛 + * updateTstamp锛氫竴涓竷灏斿硷紝鎸囩ず鏄惁闇瑕佹洿鏂版椂闂存埑 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庢眹鎬荤嚎绋嬬骇鍒殑缁熻鏁版嵁銆傚畠杩唬澶勭悊姣忎釜缁熻鍙橀噺锛屽苟瑕佹眰瀹冧滑鎵ц姹囨绘搷浣滐紝鍙夋嫨鏄惁鏇存柊鏃堕棿鎴炽 + */ void ThreadStatistics::Summarize(bool updateTstamp) { + // 鑾峰彇缁熻鍙橀噺鐨勬暟閲 uint32_t statCount = m_statVars.size(); + + // 閬嶅巻鎵鏈夌粺璁″彉閲忥紝鎵ц姹囨绘搷浣 for (uint32_t i = 0; i < statCount; ++i) { m_statVars[i]->Summarize(updateTstamp); } } +/* + * 鍔熻兘锛氭墦鍗扮嚎绋嬬粺璁℃暟鎹 + * + * 鍙傛暟鍒楄〃锛 + * statId锛氳鎵撳嵃鐨勭粺璁″彉閲忕殑ID + * logLevel锛氭棩蹇楃骇鍒紝鎸囩ず鎵撳嵃鐨勬棩蹇楃骇鍒 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庢墦鍗扮嚎绋嬬骇鍒殑缁熻鏁版嵁銆傚畠鏍规嵁缁欏畾鐨勭粺璁″彉閲廔D锛屾墦鍗扮壒瀹氱粺璁″彉閲忕殑鏁版嵁锛 + * 鎴栬呭鏋滄湭鎻愪緵ID锛屽垯鎵撳嵃鎵鏈夌粺璁″彉閲忕殑鏁版嵁銆 + */ void ThreadStatistics::Print(uint32_t statId, LogLevel logLevel) const { + // 鑾峰彇缁熻鍙橀噺鐨勬暟閲 uint32_t statCount = m_statVars.size(); + + // 濡傛灉鎻愪緵浜唖tatId锛屽彧鎵撳嵃鎸囧畾鐨勭粺璁″彉閲 if (statId < statCount) { + // 妫鏌ヨ缁熻鍙橀噺鏄惁鏈夋牱鏈暟鎹紝濡傛灉鏈夊垯鎵撳嵃 if (m_statVars[statId]->GetSampleCount() > 0) { m_statVars[statId]->Print(logLevel); } - } else { + } + // 濡傛灉鏈彁渚泂tatId锛屾墦鍗版墍鏈夌粺璁″彉閲忕殑鏁版嵁 + else { for (uint32_t i = 0; i < statCount; ++i) { + // 妫鏌ユ瘡涓粺璁″彉閲忔槸鍚︽湁鏍锋湰鏁版嵁锛屽鏋滄湁鍒欐墦鍗 if (m_statVars[i]->GetSampleCount() > 0) { m_statVars[i]->Print(logLevel); } @@ -51,57 +81,123 @@ void ThreadStatistics::Print(uint32_t statId, LogLevel logLevel) const } } +/* + * 鍔熻兘锛氶噸缃嚎绋嬬粺璁℃暟鎹 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庨噸缃嚎绋嬬骇鍒殑缁熻鏁版嵁銆傚畠灏嗘墍鏈夌粺璁″彉閲忕殑鏁版嵁閲嶇疆涓哄垵濮嬬姸鎬侊紝骞舵竻闄ゆ湁鏁堢嚎绋嬭鏁般 + */ void ThreadStatistics::Reset() { + // 鑾峰彇缁熻鍙橀噺鐨勬暟閲 uint32_t statCount = m_statVars.size(); + + // 閲嶇疆姣忎釜缁熻鍙橀噺鐨勬暟鎹紝骞舵竻闄ゆ湁鏁堢嚎绋嬭鏁 for (uint32_t i = 0; i < statCount; ++i) { m_statVars[i]->Reset(); m_validThreads[i] = 0; } } -void ThreadStatistics::Assign(const ThreadStatistics& rhs) +/* + * 鍔熻兘锛氬皢绾跨▼缁熻鏁版嵁璧嬪间负鍙︿竴涓嚎绋嬬粺璁℃暟鎹殑鍓湰 + * + * 鍙傛暟鍒楄〃锛 + * rhs锛氳璧嬪肩殑绾跨▼缁熻鏁版嵁瀵硅薄鐨勫紩鐢 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庡皢绾跨▼缁熻鏁版嵁璧嬪间负鍙︿竴涓嚎绋嬬粺璁℃暟鎹璞$殑鍓湰銆傚畠閫愪釜缁熻鍙橀噺鍦拌祴鍊硷紝骞朵繚鐣欐湁鏁堢嚎绋嬭鏁般 + */ +void ThreadStatistics::Assign(const ThreadStatistics &rhs) { + // 鑾峰彇缁熻鍙橀噺鐨勬暟閲 uint32_t statCount = m_statVars.size(); + + // 閫愪釜缁熻鍙橀噺鍦拌祴鍊硷紝骞朵繚鐣欐湁鏁堢嚎绋嬭鏁 for (uint32_t i = 0; i < statCount; ++i) { m_statVars[i]->Assign(*rhs.m_statVars[i]); m_validThreads[i] = rhs.m_validThreads[i]; } } -void ThreadStatistics::Add(const ThreadStatistics& rhs) +/* + * 鍔熻兘锛氬皢绾跨▼缁熻鏁版嵁绱姞鍒板綋鍓嶇嚎绋嬬粺璁℃暟鎹 + * + * 鍙傛暟鍒楄〃锛 + * rhs锛氳绱姞鐨勭嚎绋嬬粺璁℃暟鎹璞$殑寮曠敤 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庡皢绾跨▼缁熻鏁版嵁绱姞鍒板綋鍓嶇嚎绋嬬粺璁℃暟鎹璞′腑銆傚畠閫愪釜缁熻鍙橀噺鍦扮疮鍔狅紝骞舵洿鏂版湁鏁堢嚎绋嬭鏁般 + */ +void ThreadStatistics::Add(const ThreadStatistics &rhs) { + // 鑾峰彇缁熻鍙橀噺鐨勬暟閲 uint32_t statCount = m_statVars.size(); + + // 閫愪釜缁熻鍙橀噺鍦扮疮鍔狅紝骞舵洿鏂版湁鏁堢嚎绋嬭鏁 for (uint32_t i = 0; i < statCount; ++i) { m_statVars[i]->Add(*rhs.m_statVars[i]); - if (rhs.m_statVars[i]->GetSampleCount() > 0) + if (rhs.m_statVars[i]->GetSampleCount() > 0) { ++m_validThreads[i]; + } } } -void ThreadStatistics::Subtract(const ThreadStatistics& rhs) +/* + * 鍔熻兘锛氫粠褰撳墠绾跨▼缁熻鏁版嵁涓噺鍘诲彟涓涓嚎绋嬬粺璁℃暟鎹 + * + * 鍙傛暟鍒楄〃锛 + * rhs锛氳鍑忓幓鐨勭嚎绋嬬粺璁℃暟鎹璞$殑寮曠敤 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庝粠褰撳墠绾跨▼缁熻鏁版嵁涓噺鍘诲彟涓涓嚎绋嬬粺璁℃暟鎹璞°傚畠閫愪釜缁熻鍙橀噺鍦拌繘琛屽噺娉曟搷浣溿 + */ +void ThreadStatistics::Subtract(const ThreadStatistics &rhs) { + // 鑾峰彇缁熻鍙橀噺鐨勬暟閲 uint32_t statCount = m_statVars.size(); + + // 閫愪釜缁熻鍙橀噺鍦拌繘琛屽噺娉曟搷浣 for (uint32_t i = 0; i < statCount; ++i) { m_statVars[i]->Subtract(*rhs.m_statVars[i]); } } +/* + * 鍔熻兘锛氳鑼冨寲褰撳墠绾跨▼缁熻鏁版嵁 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庤鑼冨寲褰撳墠绾跨▼鐨勭粺璁℃暟鎹傚畠閫愪釜缁熻鍙橀噺鍦拌繘琛岃鑼冨寲鎿嶄綔锛屽皢姣忎釜鍙橀噺鐨勫奸櫎浠ユ湁鏁堢嚎绋嬫暟銆 + */ void ThreadStatistics::Normalize() { + // 鑾峰彇缁熻鍙橀噺鐨勬暟閲 uint32_t statCount = m_statVars.size(); + + // 閫愪釜缁熻鍙橀噺鍦拌繘琛岃鑼冨寲鎿嶄綔 for (uint32_t i = 0; i < statCount; ++i) { + // 濡傛灉鏈夋湁鏁堢嚎绋嬶紝灏嗙粺璁″彉閲忕殑鍊奸櫎浠ユ湁鏁堢嚎绋嬫暟 if (m_validThreads[i] > 0) { m_statVars[i]->Divide(m_validThreads[i]); } } } +/* + * 鍔熻兘锛氭鏌ユ槸鍚﹀瓨鍦ㄦ湁鏁堢殑缁熻鏍锋湰 + * + * 杩斿洖鍊硷細 + * 濡傛灉鑷冲皯涓涓粺璁″彉閲忓瓨鍦ㄦ湁鏁堢殑缁熻鏍锋湰锛屽垯杩斿洖 true锛涘惁鍒欒繑鍥 false銆 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庢鏌ュ綋鍓嶇嚎绋嬬殑缁熻鏁版嵁鏄惁鑷冲皯鏈変竴涓粺璁″彉閲忓寘鍚湁鏁堢殑缁熻鏍锋湰銆 + */ bool ThreadStatistics::HasValidSamples() const { bool result = false; uint32_t statCount = m_statVars.size(); for (uint32_t i = 0; i < statCount; ++i) { + // 濡傛灉缁熻鍙橀噺鐨勭粺璁℃牱鏈暟閲忓ぇ浜 0锛屽垯灏 result 璁剧疆涓 true 骞堕鍑哄惊鐜 if (m_statVars[i]->GetSampleCount() > 0) { result = true; break; @@ -110,34 +206,64 @@ bool ThreadStatistics::HasValidSamples() const return result; } -mot_string ThreadStatistics::MakeName(const char* baseName, uint64_t threadId) +/* + * 鍔熻兘锛氱敓鎴愮粺璁″彉閲忓悕绉 + * + * 鍙傛暟鍒楄〃锛 + * baseName锛氬熀鏈悕绉帮紝鐢ㄤ簬鏋勫缓缁熻鍙橀噺鍚嶇О + * threadId锛氱嚎绋嬫爣璇嗙锛岀敤浜庡尯鍒嗕笉鍚岀嚎绋嬬殑缁熻鍙橀噺鍚嶇О + * + * 杩斿洖鍊硷細 + * 杩斿洖涓涓寘鍚瀯寤虹殑缁熻鍙橀噺鍚嶇О鐨 mot_string 瀵硅薄銆 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庣敓鎴愮粺璁″彉閲忕殑鍚嶇О锛屾牴鎹粰瀹氱殑鍩烘湰鍚嶇О鍜岀嚎绋嬫爣璇嗙鏉ユ瀯寤轰笉鍚岀殑鍚嶇О銆 + */ +mot_string ThreadStatistics::MakeName(const char *baseName, uint64_t threadId) { mot_string result; if (threadId == THREAD_ID_TOTAL) { + // 濡傛灉绾跨▼鏍囪瘑绗︿负 THREAD_ID_TOTAL锛屽垯灏 [TOTAL] 娣诲姞鍒板熀鏈悕绉颁腑 result.format("%s[TOTAL]", baseName); } else if (threadId == THREAD_ID_AVG) { + // 濡傛灉绾跨▼鏍囪瘑绗︿负 THREAD_ID_AVG锛屽垯灏 [AVG] 娣诲姞鍒板熀鏈悕绉颁腑 result.format("%s[AVG]", baseName); } else if (threadId == THREAD_ID_DIFF) { + // 濡傛灉绾跨▼鏍囪瘑绗︿负 THREAD_ID_DIFF锛屽垯灏 [DIFF] 娣诲姞鍒板熀鏈悕绉颁腑 result.format("%s[DIFF]", baseName); } else if (threadId == THREAD_ID_DIFF_AVG) { + // 濡傛灉绾跨▼鏍囪瘑绗︿负 THREAD_ID_DIFF_AVG锛屽垯灏 [DIFF-AVG] 娣诲姞鍒板熀鏈悕绉颁腑 result.format("%s[DIFF-AVG]", baseName); } else { + // 鍚﹀垯锛屽皢绾跨▼鏍囪瘑绗︽坊鍔犲埌鍩烘湰鍚嶇О涓 result.format("%s[%u]", baseName, (unsigned)threadId); } return result; } -void ThreadStatistics::RegisterStatistics(StatisticVariable* statVar) +/* + * 鍔熻兘锛氭敞鍐岀粺璁″彉閲 + * + * 鍙傛暟鍒楄〃锛 + * statVar锛氳娉ㄥ唽鐨勭粺璁″彉閲忔寚閽 + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁扮敤浜庢敞鍐岀粺璁″彉閲忥紝灏嗙粺璁″彉閲忔坊鍔犲埌缁熻鍙橀噺鍒楄〃涓紝骞跺垎閰嶇浉搴旂殑鏈夋晥绾跨▼妲姐 + * 濡傛灉娣诲姞缁熻鍙橀噺鎴栨湁鏁堢嚎绋嬫Ы澶辫触锛屼細鎶ュ憡鍐呭瓨涓嶈冻閿欒銆 + */ +void ThreadStatistics::RegisterStatistics(StatisticVariable *statVar) { + // 灏嗙粺璁″彉閲忔坊鍔犲埌缁熻鍙橀噺鍒楄〃涓 if (!m_statVars.push_back(statVar)) { - MOT_REPORT_ERROR( - MOT_ERROR_OOM, "Register Statistics", "Failed to add statistic variable %s", statVar->GetName()); - } else if (!m_validThreads.push_back(0)) { - MOT_REPORT_ERROR(MOT_ERROR_OOM, - "Register Statistics", - "Failed to add valid thread slot for statistic variable %s", - statVar->GetName()); + MOT_REPORT_ERROR(MOT_ERROR_OOM, "Register Statistics", "Failed to add statistic variable %s", + statVar->GetName()); + } + // 涓虹粺璁″彉閲忓垎閰嶇浉搴旂殑鏈夋晥绾跨▼妲 + else if (!m_validThreads.push_back(0)) { + MOT_REPORT_ERROR(MOT_ERROR_OOM, "Register Statistics", + "Failed to add valid thread slot for statistic variable %s", statVar->GetName()); } } + } // namespace MOT diff --git a/src/gausskernel/storage/mot/core/infra/synchronization/affinity.cpp b/src/gausskernel/storage/mot/core/infra/synchronization/affinity.cpp index 5b1f944ac..1cb3970e0 100644 --- a/src/gausskernel/storage/mot/core/infra/synchronization/affinity.cpp +++ b/src/gausskernel/storage/mot/core/infra/synchronization/affinity.cpp @@ -47,18 +47,35 @@ void Affinity::Configure(uint64_t numaNodes, uint64_t physicalCoresNuma, Affinit m_affinityMode = affinityMode; } +/* + * 鍔熻兘锛氳幏鍙栦翰鍜屽鐞嗗櫒 + * + * 鍙傛暟鍒楄〃锛 + * threadId锛氱嚎绋嬫爣璇嗙锛岀敤浜庤绠椾翰鍜屽鐞嗗櫒 + * + * 杩斿洖鍊硷細 + * 杩斿洖浜插拰澶勭悊鍣ㄧ殑鏍囪瘑绗︼紝濡傛灉鏃犳晥鍒欒繑鍥 INVALID_CPU_ID + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁版牴鎹寚瀹氱殑浜插拰鎬фā寮忥紙m_affinityMode锛夊拰绾跨▼鏍囪瘑绗︼紙threadId锛夋潵璁$畻浜插拰澶勭悊鍣ㄣ + * 鏍规嵁涓嶅悓鐨勪翰鍜屾фā寮忥紝瀹冨彲浠ヨ繑鍥炰笉鍚岀殑浜插拰澶勭悊鍣ㄦ爣璇嗙銆 + * 濡傛灉鎸囧畾鐨勪翰鍜屾фā寮忔棤鏁堬紝浼氳褰曢敊璇苟杩斿洖 INVALID_CPU_ID銆 + */ uint32_t Affinity::GetAffineProcessor(uint64_t threadId) const { uint32_t result = INVALID_CPU_ID; threadId = threadId % (m_numaNodes * m_physicalCoresNuma); + // 鏍规嵁浜插拰鎬фā寮忛夋嫨鐩稿簲鐨勫鐞嗗櫒璁$畻鏂规硶 switch (m_affinityMode) { case AffinityMode::FILL_SOCKET_FIRST: { + // 浣跨敤 GetMappedCore 鏂规硶鑾峰彇浜插拰澶勭悊鍣 result = (uint32_t)GetGlobalConfiguration().GetMappedCore(threadId); break; } case AffinityMode::EQUAL_PER_SOCKET: { + // 璁$畻 NUMA 鑺傜偣鍜屾湰鍦板鐞嗗櫒绱㈠紩锛岀劧鍚庡悎骞惰绠楀嚭浜插拰澶勭悊鍣 threadId = threadId % (m_numaNodes * m_physicalCoresNuma); uint32_t numaId = threadId % m_numaNodes; uint32_t localProc = threadId / m_numaNodes; @@ -67,10 +84,12 @@ uint32_t Affinity::GetAffineProcessor(uint64_t threadId) const } case AffinityMode::FILL_PHYSICAL_FIRST: + // 浣跨敤 GetCoreByConnidFP 鏂规硶鑾峰彇浜插拰澶勭悊鍣 result = (uint32_t)GetGlobalConfiguration().GetCoreByConnidFP(threadId); break; default: + // 璁板綍閿欒骞惰繑鍥炴棤鏁堢殑澶勭悊鍣ㄦ爣璇嗙 MOT_LOG_ERROR("%s: Invalid affinity configuration: %d", __func__, (int)m_affinityMode); result = INVALID_CPU_ID; break; @@ -78,18 +97,35 @@ uint32_t Affinity::GetAffineProcessor(uint64_t threadId) const return result; } +/* + * 鍔熻兘锛氳幏鍙栦翰鍜 NUMA 鑺傜偣 + * + * 鍙傛暟鍒楄〃锛 + * threadId锛氱嚎绋嬫爣璇嗙锛岀敤浜庤绠椾翰鍜 NUMA 鑺傜偣 + * + * 杩斿洖鍊硷細 + * 杩斿洖浜插拰 NUMA 鑺傜偣鐨勬爣璇嗙锛屽鏋滄棤鏁堝垯杩斿洖 INVALID_NODE_ID + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁版牴鎹寚瀹氱殑浜插拰鎬фā寮忥紙m_affinityMode锛夊拰绾跨▼鏍囪瘑绗︼紙threadId锛夋潵璁$畻浜插拰 NUMA 鑺傜偣銆 + * 鏍规嵁涓嶅悓鐨勪翰鍜屾фā寮忥紝瀹冨彲浠ヨ繑鍥炰笉鍚岀殑 NUMA 鑺傜偣鏍囪瘑绗︺ + * 濡傛灉鎸囧畾鐨勪翰鍜屾фā寮忔棤鏁堬紝浼氳褰曢敊璇苟杩斿洖 INVALID_NODE_ID銆 + */ uint32_t Affinity::GetAffineNuma(uint64_t threadId) const { uint32_t result = INVALID_NODE_ID; threadId = threadId % (m_numaNodes * m_physicalCoresNuma); + // 鏍规嵁浜插拰鎬фā寮忛夋嫨鐩稿簲鐨 NUMA 鑺傜偣璁$畻鏂规硶 switch (m_affinityMode) { case AffinityMode::FILL_SOCKET_FIRST: { + // 浣跨敤 GetMappedCore 鏂规硶鑾峰彇浜插拰 NUMA 鑺傜偣 result = (uint32_t)GetGlobalConfiguration().GetCpuNode(GetGlobalConfiguration().GetMappedCore(threadId)); break; } case AffinityMode::EQUAL_PER_SOCKET: + // 鐩存帴璁$畻 NUMA 鑺傜偣 result = (uint32_t)threadId % m_numaNodes; break; @@ -106,6 +142,7 @@ uint32_t Affinity::GetAffineNuma(uint64_t threadId) const } default: + // 璁板綍閿欒骞惰繑鍥炴棤鏁堢殑 NUMA 鑺傜偣鏍囪瘑绗 MOT_LOG_ERROR("%s: Invalid affinity configuration: %d", __func__, (int)m_affinityMode); result = (uint32_t)INVALID_NODE_ID; break; @@ -113,8 +150,24 @@ uint32_t Affinity::GetAffineNuma(uint64_t threadId) const return result; } - -bool Affinity::SetAffinity(uint64_t threadId, uint32_t* threadCore /* = nullptr */) const +/* + * 鍔熻兘锛氳缃嚎绋嬬殑 CPU 浜插拰鎬 + * + * 鍙傛暟鍒楄〃锛 + * threadId锛氱嚎绋嬫爣璇嗙锛岀敤浜庤绠椾翰鍜 CPU + * threadCore锛氱敤浜庡瓨鍌ㄧ嚎绋嬫墍缁戝畾鐨 CPU 鐨勬寚閽堬紝榛樿涓 nullptr + * + * 杩斿洖鍊硷細 + * 濡傛灉鎴愬姛璁剧疆绾跨▼鐨 CPU 浜插拰鎬э紝鍒欒繑鍥 true锛屽惁鍒欒繑鍥 false + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁版牴鎹寚瀹氱殑绾跨▼鏍囪瘑绗︼紙threadId锛夎绠楃嚎绋嬪簲璇ョ粦瀹氱殑 CPU銆 + * 鐒跺悗锛屽畠鍒涘缓涓涓 CPU 闆嗗悎锛坢ask锛夊苟灏嗙洰鏍 CPU 鍔犲叆鍏朵腑锛屾渶鍚庝娇鐢 pthread_setaffinity_np 鍑芥暟 + * 鎴 sched_setaffinity 鍑芥暟璁剧疆绾跨▼鐨 CPU 浜插拰鎬с傚鏋滆缃け璐ワ紝鍑芥暟浼氬皾璇 sched_setaffinity 鍑芥暟銆 + * 濡傛灉浠嶇劧澶辫触锛屼細璁板綍閿欒骞惰繑鍥 false銆 + * 濡傛灉 threadCore 鍙傛暟涓嶄负绌猴紝瀹冨皢瀛樺偍绾跨▼鎵缁戝畾鐨 CPU 鏍稿績鏍囪瘑绗︺ + */ +bool Affinity::SetAffinity(uint64_t threadId, uint32_t *threadCore /* = nullptr */) const { bool result = true; uint32_t coreId = GetAffineProcessor(threadId); @@ -138,10 +191,8 @@ bool Affinity::SetAffinity(uint64_t threadId, uint32_t* threadCore /* = nullptr result = false; } } else { - MOT_LOG_TRACE("Set current thread %u affinity to core %u (socket %u)", - (unsigned)threadId, - (unsigned)coreId, - (unsigned)GetAffineNuma(threadId)); + MOT_LOG_TRACE("Set current thread %u affinity to core %u (socket %u)", (unsigned)threadId, (unsigned)coreId, + (unsigned)GetAffineNuma(threadId)); } if (threadCore) { @@ -149,7 +200,20 @@ bool Affinity::SetAffinity(uint64_t threadId, uint32_t* threadCore /* = nullptr } return result; } - +/* + * 鍔熻兘锛氳缃綋鍓嶇嚎绋嬬殑 NUMA 鑺傜偣浜插拰鎬 + * + * 鍙傛暟鍒楄〃锛 + * nodeId锛歂UMA 鑺傜偣鏍囪瘑绗︼紝鎸囧畾瑕佺粦瀹氬埌鐨 NUMA 鑺傜偣 + * + * 杩斿洖鍊硷細 + * 濡傛灉鎴愬姛璁剧疆绾跨▼鐨 NUMA 鑺傜偣浜插拰鎬э紝鍒欒繑鍥 true锛屽惁鍒欒繑鍥 false + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁板皢褰撳墠绾跨▼缁戝畾鍒版寚瀹氱殑 NUMA 鑺傜偣銆傚畠鍒涘缓涓涓 CPU 闆嗗悎锛坢ask锛夊苟灏嗚鑺傜偣鐨勬墍鏈 CPU 鍔犲叆鍏朵腑锛 + * 鐒跺悗浣跨敤 pthread_setaffinity_np 鍑芥暟鎴 sched_setaffinity 鍑芥暟璁剧疆绾跨▼鐨 NUMA 鑺傜偣浜插拰鎬с + * 濡傛灉璁剧疆澶辫触锛屽嚱鏁颁細灏濊瘯 sched_setaffinity 鍑芥暟銆傚鏋滀粛鐒跺け璐ワ紝浼氳褰曢敊璇苟杩斿洖 false銆 + */ bool Affinity::SetNodeAffinity(int nodeId) { bool result = true; @@ -173,14 +237,29 @@ bool Affinity::SetNodeAffinity(int nodeId) return result; } -static const char* AFFINITY_FILL_SOCKET_FIRST_STR = "fill-socket-first"; -static const char* AFFINITY_EQUAL_PER_SOCKET_STR = "equal-per-socket"; -static const char* AFFINITY_FILL_PHYSICAL_FIRST_STR = "fill-physical-first"; -static const char* AFFINITY_NONE_STR = "none"; +static const char *AFFINITY_FILL_SOCKET_FIRST_STR = "fill-socket-first"; +static const char *AFFINITY_EQUAL_PER_SOCKET_STR = "equal-per-socket"; +static const char *AFFINITY_FILL_PHYSICAL_FIRST_STR = "fill-physical-first"; +static const char *AFFINITY_NONE_STR = "none"; -extern AffinityMode AffinityModeFromString(const char* affinityModeStr) +/* + * 鍔熻兘锛氫粠瀛楃涓蹭腑瑙f瀽浜插拰鎬фā寮 + * + * 鍙傛暟鍒楄〃锛 + * affinityModeStr锛氬寘鍚翰鍜屾фā寮忔弿杩扮殑瀛楃涓 + * + * 杩斿洖鍊硷細 + * 瑙f瀽鐨勪翰鍜屾фā寮忥紝濡傛灉鏃犳硶瑙f瀽鍒欒繑鍥 AffinityMode::AFFINITY_INVALID + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁板皢杈撳叆鐨勫瓧绗︿覆涓庡凡鐭ョ殑浜插拰鎬фā寮忓瓧绗︿覆杩涜姣旇緝锛屼互纭畾缁欏畾瀛楃涓茶〃绀虹殑浜插拰鎬фā寮忋 + * 濡傛灉瀛楃涓蹭笌宸茬煡妯″紡鍖归厤锛屽垯杩斿洖鐩稿簲鐨 AffinityMode 鏋氫妇鍊硷紱鍚﹀垯杩斿洖 AFFINITY_INVALID銆 + */ +extern AffinityMode AffinityModeFromString(const char *affinityModeStr) { AffinityMode result = AffinityMode::AFFINITY_INVALID; + + // 浣跨敤strcmp鍑芥暟姣旇緝杈撳叆瀛楃涓蹭笌宸茬煡鐨勪翰鍜屾фā寮忓瓧绗︿覆 if (strcmp(affinityModeStr, AFFINITY_FILL_SOCKET_FIRST_STR) == 0) { result = AffinityMode::FILL_SOCKET_FIRST; } else if (strcmp(affinityModeStr, AFFINITY_EQUAL_PER_SOCKET_STR) == 0) { @@ -190,10 +269,24 @@ extern AffinityMode AffinityModeFromString(const char* affinityModeStr) } else if (strcmp(affinityModeStr, AFFINITY_NONE_STR) == 0) { result = AffinityMode::AFFINITY_NONE; } + return result; } -extern const char* AffinityModeToString(AffinityMode affinityMode) +/* + * 鍔熻兘锛氬皢浜插拰鎬фā寮忔灇涓捐浆鎹负瀛楃涓茶〃绀 + * + * 鍙傛暟鍒楄〃锛 + * affinityMode锛氳杞崲鐨勪翰鍜屾фā寮忔灇涓惧 + * + * 杩斿洖鍊硷細 + * 浜插拰鎬фā寮忕殑瀛楃涓茶〃绀猴紝濡傛灉鏋氫妇鍊兼棤鏁堝垯杩斿洖 "N/A" + * + * 娉ㄦ剰锛 + * 姝ゅ嚱鏁板皢杈撳叆鐨勪翰鍜屾фā寮忔灇涓惧兼槧灏勪负鐩稿簲鐨勫瓧绗︿覆锛屼互渚胯繘琛屾墦鍗版垨鏄剧ず銆 + * 濡傛灉杈撳叆鐨勬灇涓惧兼棤鏁堬紝鍒欒繑鍥 "N/A"銆 + */ +extern const char *AffinityModeToString(AffinityMode affinityMode) { switch (affinityMode) { case AffinityMode::FILL_SOCKET_FIRST: @@ -212,4 +305,5 @@ extern const char* AffinityModeToString(AffinityMode affinityMode) return "N/A"; } } + } // namespace MOT diff --git a/src/gausskernel/storage/page/checksum_impl.cpp b/src/gausskernel/storage/page/checksum_impl.cpp index bd7b4df4f..fc7498c89 100644 --- a/src/gausskernel/storage/page/checksum_impl.cpp +++ b/src/gausskernel/storage/page/checksum_impl.cpp @@ -17,20 +17,41 @@ #include "storage/checksum_impl.h" void ChecksumForZeroPadding(uint32 *sums, const uint32 *dataArr, uint32 currentLeft, uint32 alignSize); - +/* + * 鍔熻兘锛氬垵濮嬪寲鏍¢獙鍜岃绠 + * + * 鍙傛暟鍒楄〃锛 + * seed锛氱敤浜庡垵濮嬪寲鏍¢獙鍜岃绠楃殑绉嶅瓙鍊硷紝閫氬父鏄竴涓32浣嶆暣鏁 + * value锛氳璁$畻鏍¢獙鍜岀殑鍊硷紝閫氬父鏄竴涓32浣嶆暣鏁 + * + * 娉ㄦ剰浜嬮」锛 + * - 杩欐槸涓涓潤鎬佸唴鑱斿嚱鏁帮紝閫氬父鐢ㄤ簬鍦ㄧ紪璇戞椂杩涜浼樺寲锛屼互鎻愰珮鎬ц兘銆 + */ static inline uint32 pg_checksum_init(uint32 seed, uint32 value) { - CHECKSUM_COMP(seed, value); - return seed; + CHECKSUM_COMP(seed, value); // 浣跨敤瀹廋HECKSUM_COMP鎵ц鏍¢獙鍜岃绠 + return seed; // 杩斿洖鍒濆鍖栧悗鐨勬牎楠屽拰绉嶅瓙鍊 } - -uint32 DataBlockChecksum(char* data, uint32 size, bool zeroing) +/* + * 鍔熻兘锛氳绠楁暟鎹潡鐨勬牎楠屽拰 + * + * 鍙傛暟鍒楄〃锛 + * data锛氭寚鍚戞暟鎹潡鐨勬寚閽 + * size锛氭暟鎹潡鐨勫ぇ灏忥紝浠ュ瓧鑺備负鍗曚綅 + * zeroing锛氫竴涓竷灏斿硷紝鎸囩ず鏄惁闇瑕佽繘琛岄浂濉厖 + * + * 娉ㄦ剰浜嬮」锛 + * - 璇ュ嚱鏁扮敤浜庤绠楃粰瀹氭暟鎹潡鐨勬牎楠屽拰銆 + * - 濡傛灉闇瑕佽繘琛岄浂濉厖锛屽垯鏍规嵁鏁版嵁鍧楃殑瀹為檯澶у皬杩涜濉厖銆 + * - 鍑芥暟浣跨敤涓绯诲垪鏍¢獙鍜岃绠楁楠わ紝鍖呮嫭鍒濆鍖栥佷富璁$畻鍜屾渶缁堟贩鍚堛 + */ +uint32 DataBlockChecksum(char *data, uint32 size, bool zeroing) { - uint32 sums[N_SUMS]; - uint32* dataArr = (uint32*)data; - uint32 result = 0; + uint32 sums[N_SUMS]; // 鐢ㄤ簬瀛樺偍鏍¢獙鍜岀殑鏁扮粍 + uint32 *dataArr = (uint32 *)data; // 灏嗘暟鎹潡杞崲涓簎int32鏁扮粍 + uint32 result = 0; // 鐢ㄤ簬瀛樺偍鏈缁堢殑鏍¢獙鍜岀粨鏋 uint32 i, j; - uint32 currentLeft = size; + uint32 currentLeft = size; // 鐢ㄤ簬璺熻釜灏氭湭澶勭悊鐨勬暟鎹噺 /* ensure that the size is compatible with the algorithm */ uint32 alignSize = sizeof(uint32) * N_SUMS; @@ -42,10 +63,10 @@ uint32 DataBlockChecksum(char* data, uint32 size, bool zeroing) uint32 *initUint32 = NULL; char usedForInit[sizeof(uint32) * N_SUMS] = {0}; if (zeroing && size < alignSize) { - errno_t rc = memcpy_s(usedForInit, alignSize, (char *) dataArr, realSize); + errno_t rc = memcpy_s(usedForInit, alignSize, (char *)dataArr, realSize); securec_check(rc, "", ""); currentLeft -= realSize; - initUint32 = (uint32*)usedForInit; + initUint32 = (uint32 *)usedForInit; } else { initUint32 = dataArr; currentLeft -= alignSize; @@ -83,24 +104,53 @@ uint32 DataBlockChecksum(char* data, uint32 size, bool zeroing) return result; } - +/* + * 鍔熻兘锛氱敤浜庡鐞嗘暟鎹潡鐨勯浂濉厖鎯呭喌鐨勬牎楠屽拰璁$畻 + * + * 鍙傛暟鍒楄〃锛 + * - sums锛氭牎楠屽拰鏁扮粍锛岀敤浜庡瓨鍌ㄦ牎楠屽拰鐨勪腑闂寸粨鏋 + * - dataArr锛氭寚鍚戞暟鎹潡鐨剈int32鏁扮粍鎸囬拡 + * - currentLeft锛氬皻鏈鐞嗙殑鏁版嵁鍧楀ぇ灏忥紙浠ュ瓧鑺備负鍗曚綅锛 + * - alignSize锛氬榻愮殑澶у皬锛岄氬父涓簊izeof(uint32) * N_SUMS + * + * 娉ㄦ剰浜嬮」锛 + * - 璇ュ嚱鏁扮敤浜庡鐞嗘暟鎹潡鐨勯浂濉厖鎯呭喌锛屽畠浠庢暟鎹潡鐨勬湯灏捐幏鍙栨湭澶勭悊鐨勬暟鎹紝 + * 骞惰繘琛屾牎楠屽拰璁$畻浠ラ傚簲闆跺~鍏呫 + * - 鍑芥暟棣栧厛灏嗘湭澶勭悊鐨勬暟鎹鍒跺埌涓涓瓧绗︽暟缁勪腑锛岀劧鍚庢寜鐓_SUMS鐨勫亸绉诲 + * 璁$畻鏍¢獙鍜岋紝灏嗙粨鏋滃瓨鍌ㄥ湪sums鏁扮粍涓 + */ void ChecksumForZeroPadding(uint32 *sums, const uint32 *dataArr, uint32 currentLeft, uint32 alignSize) { auto maxLen = sizeof(uint32) * N_SUMS; char currentLeftChars[maxLen] = {0}; errno_t rc = memcpy_s(currentLeftChars, maxLen, (char *)dataArr, currentLeft); securec_check(rc, "", ""); + // 閽堝澶嶅埗鍚庣殑瀛楃鏁扮粍锛屾寜鐓_SUMS鐨勫亸绉诲艰绠楁牎楠屽拰 for (int j = 0; j < N_SUMS; j += 2) { CHECKSUM_COMP(sums[j], ((uint32 *)currentLeftChars)[j]); CHECKSUM_COMP(sums[j + 1], ((uint32 *)currentLeftChars)[j + 1]); } } - -uint32 pg_checksum_block(char* data, uint32 size) +/* + * 鍔熻兘锛氬鏁版嵁鍧楄繘琛屾牎楠屽拰璁$畻 + * + * 鍙傛暟鍒楄〃锛 + * - data锛氭寚鍚戞暟鎹潡鐨勬寚閽 + * - size锛氭暟鎹潡鐨勫ぇ灏忥紝浠ュ瓧鑺備负鍗曚綅 + * + * 杩斿洖鍊硷細 + * - 杩斿洖涓涓32浣嶆暣鏁帮紝琛ㄧず璁$畻寰楀埌鐨勬牎楠屽拰鍊 + * + * 娉ㄦ剰浜嬮」锛 + * - 璇ュ嚱鏁扮敤浜庡缁欏畾鐨勬暟鎹潡杩涜鏍¢獙鍜岃绠椼 + * - 鍑芥暟浣跨敤涓绯诲垪鐨勬牎楠屽拰璁$畻姝ラ锛屽寘鎷垵濮嬪寲銆佷富璁$畻鍜屾渶缁堟贩鍚堛 + * - 濡傛灉鏁版嵁鍧楃殑澶у皬涓嶆槸sizeof(uint32) * N_SUMS鐨勫嶆暟锛屽彲鑳戒細瀵艰嚧鏂█閿欒銆 + */ +uint32 pg_checksum_block(char *data, uint32 size) { - uint32 sums[N_SUMS]; - uint32* dataArr = (uint32*)data; - uint32 result = 0; + uint32 sums[N_SUMS]; // 鐢ㄤ簬瀛樺偍鏍¢獙鍜岀殑鏁扮粍 + uint32 *dataArr = (uint32 *)data; // 灏嗘暟鎹潡杞崲涓簎int32鏁扮粍 + uint32 result = 0; // 鐢ㄤ簬瀛樺偍鏈缁堢殑鏍¢獙鍜岀粨鏋 uint32 i, j; #ifndef ROACH_COMMON @@ -133,7 +183,7 @@ uint32 pg_checksum_block(char* data, uint32 size) result ^= sums[j]; } - return result; + return result; // 杩斿洖鏈缁堢殑鏍¢獙鍜岀粨鏋 } /* @@ -144,7 +194,7 @@ uint32 pg_checksum_block(char* data, uint32 size) * somehow moved to a different location), the page header (excluding the * checksum itself), and the page data. */ -uint16 pg_checksum_page(char* page, BlockNumber blkno) +uint16 pg_checksum_page(char *page, BlockNumber blkno) { PageHeader phdr = (PageHeader)page; uint16 save_checksum; diff --git a/src/gausskernel/storage/page/gs_xlogdump.cpp b/src/gausskernel/storage/page/gs_xlogdump.cpp index 3f3e92aa5..3827de052 100644 --- a/src/gausskernel/storage/page/gs_xlogdump.cpp +++ b/src/gausskernel/storage/page/gs_xlogdump.cpp @@ -40,93 +40,173 @@ #include "utils/palloc.h" #include "pageparse.h" +// 鐢ㄦ潵鍦ㄧ▼搴忎腑缁勭粐鍜屼紶閫掓湁鍏虫暟鎹簱鏃ュ織 (XLog) 鐨勭鏈変俊鎭 typedef struct XLogPrivate { - const char *datadir; - TimeLineID tli; + const char *datadir; // 鍌ㄥ瓨鏁版嵁鐩綍鐨勮矾寰 + TimeLineID tli; // 瀛樺偍鏃堕棿绾挎爣璇 } XLogPrivate; +// 鐢ㄤ簬鍦 XLog 澶勭悊涓寚瀹氳繃婊ゆ潯浠 typedef struct XLogFilter { - TransactionId by_xid; - bool by_xid_enabled; - bool by_tablepath_enabled; - bool by_block; - RelFileNode by_relfilenode; - BlockNumber blocknum; + TransactionId by_xid; // 瀛樺偍浜嬪姟鏍囪瘑 (Transaction ID) 鐨勫彉閲 + bool by_xid_enabled; // 鐢ㄤ簬琛ㄧず鏄惁鍚敤浜嗘寜浜嬪姟鏍囪瘑杩囨护鐨勫姛鑳 + bool by_tablepath_enabled; // 鐢ㄤ簬琛ㄧず鏄惁鍚敤浜嗘寜琛ㄨ矾寰勮繃婊ょ殑鍔熻兘 + bool by_block; // 鐢ㄤ簬琛ㄧず鏄惁鎸夌収鍧 (block) 杩涜杩囨护 + RelFileNode by_relfilenode; // 鐢ㄤ簬瀛樺偍鍏崇郴鏂囦欢鑺傜偣 (RelFileNode) 鐨勫彉閲 + BlockNumber blocknum; // 鐢ㄤ簬琛ㄧず鍦ㄨ〃涓殑鐗瑰畾鍧 } XLogFilter; - +/* + * 鍔熻兘锛氱敓鎴愯緭鍑烘枃浠跺悕 + * + * 鍙傛暟鍒楄〃锛 + * outputFilename锛氱敤浜庡瓨鍌ㄧ敓鎴愮殑杈撳嚭鏂囦欢鍚嶇殑瀛楃鏁扮粍 + * start_lsn_str锛氳捣濮婰SN锛圠og Sequence Number锛夌殑瀛楃涓茶〃绀 + * send_lsn_str锛氱粨鏉烲SN鐨勫瓧绗︿覆琛ㄧず + * + * 娉ㄦ剰浜嬮」锛 + * - 璇ュ嚱鏁扮敤浜庣敓鎴愪竴涓緭鍑烘枃浠跺悕锛屾牴鎹捣濮婰SN鍜岀粨鏉烲SN鏋勫缓鏂囦欢鍚嶃 + * - 鍑芥暟鍐呴儴浼氬杈撳叆鐨凩SN瀛楃涓茶繘琛屽鐞嗕互鎻愬彇闇瑕佺殑閮ㄥ垎锛屽苟鏋勫缓鏂囦欢鍚嶃 + */ static void GenerateOutputFileName(char *outputFilename, char *start_lsn_str, char *end_lsn_str) { - List *elemlist = NIL; + List *elemlist = NIL; // 鍒濆鍖栦竴涓┖鐨勫垪琛 + // 璋冪敤 SplitIdentifierString 鍑芥暟鍒嗗壊璧峰LSN瀛楃涓 SplitIdentifierString(start_lsn_str, '/', &elemlist); - char *start_lsn_str_p2 = (char *)lsecond(elemlist); - list_free_ext(elemlist); + char *start_lsn_str_p2 = (char *)lsecond(elemlist); // 鑾峰彇鍒嗗壊鍚庣殑绗簩閮ㄥ垎 + list_free_ext(elemlist); // 閲婃斁鍒嗗壊缁撴灉鍒楄〃鐨勫唴瀛 + // 鍐嶆璋冪敤 SplitIdentifierString 鍑芥暟鍒嗗壊缁撴潫LSN瀛楃涓 SplitIdentifierString(end_lsn_str, '/', &elemlist); - char *end_lsn_str_p2 = (char *)lsecond(elemlist); + char *end_lsn_str_p2 = (char *)lsecond(elemlist); // 鑾峰彇鍒嗗壊鍚庣殑绗簩閮ㄥ垎 + // 浣跨敤 snprintf_s 鍑芥暟鏋勫缓杈撳嚭鏂囦欢鍚 int rc = snprintf_s(outputFilename + (int)strlen(outputFilename), MAXFILENAME, MAXFILENAME - 1, "%s/%s_%s.xlog", - t_thrd.proc_cxt.DataDir, start_lsn_str_p2, end_lsn_str_p2); - securec_check_ss(rc, "\0", "\0"); + t_thrd.proc_cxt.DataDir, start_lsn_str_p2, end_lsn_str_p2); + securec_check_ss(rc, "\0", "\0"); // 妫鏌 snprintf_s 鐨勮繑鍥炲间互纭繚瀹夊叏 } - +/* + * 鍔熻兘锛氶獙璇丩SN锛圠og Sequence Number锛夊瓧绗︿覆骞惰В鏋愪负XLogRecPtr + * + * 鍙傛暟鍒楄〃锛 + * lsn_str锛歀SN瀛楃涓茶〃绀 + * lsn_ptr锛氱敤浜庡瓨鍌ㄨВ鏋愬悗鐨刋LogRecPtr鐨勬寚閽 + * + * 娉ㄦ剰浜嬮」锛 + * - 璇ュ嚱鏁扮敤浜庨獙璇丩SN瀛楃涓茬殑鏍煎紡锛屽苟灏嗗叾瑙f瀽涓篨LogRecPtr鏁版嵁绫诲瀷銆 + * - LSN瀛楃涓查氬父浠ュ崄鍏繘鍒舵暟瀛楀舰寮忚〃绀猴紝濡 "0/80001234"銆 + * - 鍑芥暟棣栧厛璋冪敤 validate_xlog_location 鍑芥暟楠岃瘉LSN瀛楃涓茬殑鏍煎紡銆 + * - 鐒跺悗浣跨敤 sscanf_s 鍑芥暟瑙f瀽LNS瀛楃涓插苟瀛樺偍鍒 lsn_ptr 涓 + * - 濡傛灉瑙f瀽澶辫触锛屽嚱鏁颁細鎶ラ敊銆 + */ static void ValidateLSN(char *lsn_str, XLogRecPtr *lsn_ptr) { - uint32 hi = 0; - uint32 lo = 0; - validate_xlog_location(lsn_str); - + uint32 hi = 0; // 鍒濆鍖栭珮浣嶉儴鍒嗕负0 + uint32 lo = 0; // 鍒濆鍖栦綆浣嶉儴鍒嗕负0 + validate_xlog_location(lsn_str); // 璋冪敤 validate_xlog_location 鍑芥暟楠岃瘉LSN瀛楃涓茬殑鏍煎紡 + // 浣跨敤 sscanf_s 鍑芥暟瑙f瀽LSN瀛楃涓诧紝灏嗚В鏋愮粨鏋滃瓨鍌ㄥ湪 hi 鍜 lo 涓 if (sscanf_s(lsn_str, "%X/%X", &hi, &lo) != TWO) ereport(ERROR, - (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("could not parse xlog location \"%s\"", lsn_str))); + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("could not parse xlog location \"%s\"", lsn_str))); + // 鏋勯 XLogRecPtr锛屽皢楂樹綅閮ㄥ垎宸︾Щ 32 浣嶅悗涓庝綆浣嶉儴鍒嗗悎骞讹紝骞跺瓨鍌ㄥ埌 lsn_ptr 涓 *lsn_ptr = (((uint64)hi) << XIDTHIRTYTWO) | lo; } - +/* + * 鍔熻兘锛氶獙璇佽捣濮婰SN鍜岀粨鏉烲SN瀛楃涓诧紝骞舵瘮杈冨畠浠殑澶у皬鍏崇郴 + * + * 鍙傛暟鍒楄〃锛 + * start_lsn_str锛氳捣濮婰SN锛圠og Sequence Number锛夊瓧绗︿覆琛ㄧず + * end_lsn_str锛氱粨鏉烲SN瀛楃涓茶〃绀 + * start_lsn锛氱敤浜庡瓨鍌ㄨВ鏋愬悗鐨勮捣濮婰SN鐨勬寚閽 + * end_lsn锛氱敤浜庡瓨鍌ㄨВ鏋愬悗鐨勭粨鏉烲SN鐨勬寚閽 + * + * 娉ㄦ剰浜嬮」锛 + * - 璇ュ嚱鏁扮敤浜庨獙璇佽捣濮婰SN鍜岀粨鏉烲SN瀛楃涓茬殑鏍煎紡锛屽苟姣旇緝瀹冧滑鐨勫ぇ灏忓叧绯汇 + * - 棣栧厛璋冪敤 ValidateLSN 鍑芥暟鍒嗗埆楠岃瘉璧峰LSN鍜岀粨鏉烲SN銆 + * - 鐒跺悗姣旇緝涓よ呯殑澶у皬鍏崇郴锛岀‘淇濊捣濮婰SN涓嶅ぇ浜庣粨鏉烲SN銆 + * - 濡傛灉涓嶆弧瓒虫潯浠讹紝鍑芥暟浼氭姤閿欍 + */ static void ValidateStartEndLSN(char *start_lsn_str, char *end_lsn_str, XLogRecPtr *start_lsn, XLogRecPtr *end_lsn) { + // 棣栧厛楠岃瘉璧峰LSN鍜岀粨鏉烲SN ValidateLSN(start_lsn_str, start_lsn); ValidateLSN(end_lsn_str, end_lsn); + // 姣旇緝璧峰LSN鍜岀粨鏉烲SN鐨勫ぇ灏忓叧绯 if (XLByteLT(*end_lsn, *start_lsn)) ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("start xlog location %X/%X should be smaller than or equal to end xlog location %X/%X", - (uint32)(*start_lsn >> XIDTHIRTYTWO), (uint32)(*start_lsn), (uint32)(*end_lsn >> XIDTHIRTYTWO), - (uint32)(*end_lsn)))); + errmsg("start xlog location %X/%X should be smaller than or equal to end xlog location %X/%X", + (uint32)(*start_lsn >> XIDTHIRTYTWO), (uint32)(*start_lsn), + (uint32)(*end_lsn >> XIDTHIRTYTWO), (uint32)(*end_lsn)))); } - +/* + * 鍔熻兘锛氳幏鍙栨渶灏忕殑LSN + * + * 娉ㄦ剰浜嬮」锛 + * - 璇ュ嚱鏁扮敤浜庤幏鍙栨渶灏忕殑LSN锛岄氬父鐢ㄤ簬纭畾瑕佷繚鐣欑殑XLog鏃ュ織鐨勮捣濮嬩綅缃 + * - 鍑芥暟棣栧厛鑾峰彇鏈鍚庝竴涓凡鍒犻櫎鐨刋Log娈电殑娈靛彿锛岀劧鍚庤绠楀綋鍓峀SN銆 + * - 鏈灏忕殑LSN閫氬父鏄笅涓涓猉Log娈电殑璧峰浣嶇疆銆 + */ static XLogRecPtr GetMinLSN() { - XLogSegNo lastRemovedSegNo = XLogGetLastRemovedSegno(); - XLogRecPtr current_recptr = (lastRemovedSegNo + 1) * XLogSegSize; - return current_recptr; + XLogSegNo lastRemovedSegNo = XLogGetLastRemovedSegno(); // 鑾峰彇鏈鍚庝竴涓凡鍒犻櫎鐨刋Log娈电殑娈靛彿 + XLogRecPtr current_recptr = (lastRemovedSegNo + 1) * XLogSegSize; // 璁$畻褰撳墠LSN + return current_recptr; // 杩斿洖鏈灏忕殑LSN } - +/* + * 鍔熻兘锛氳幏鍙栨渶澶х殑LSN锛圠og Sequence Number锛 + * + * 杩斿洖鍊硷細 + * - 杩斿洖涓涓猉LogRecPtr绫诲瀷鐨勫硷紝琛ㄧず鏈澶х殑LSN + * + * 娉ㄦ剰浜嬮」锛 + * - 璇ュ嚱鏁扮敤浜庤幏鍙栨渶澶х殑LSN锛岄氬父鐢ㄤ簬纭畾褰撳墠绯荤粺涓殑鏈鏂癤Log浣嶇疆銆 + * - 鍦ㄦ仮澶嶈繃绋嬩腑涓嶈兘鑾峰彇鏈澶х殑LSN锛屼細瀵艰嚧閿欒銆 + * - 鍑芥暟棣栧厛妫鏌ユ槸鍚﹀浜庢仮澶嶇姸鎬侊紝濡傛灉鏄紝鍒欐姤閿欍 + * - 鍚﹀垯锛屽嚱鏁拌皟鐢 GetXLogWriteRecPtr 鍑芥暟鑾峰彇褰撳墠鐨凩SN锛屽苟杩斿洖瀹冦 + */ static XLogRecPtr GetMaxLSN() { - if (RecoveryInProgress()) + if (RecoveryInProgress()) // 妫鏌ユ槸鍚﹀浜庢仮澶嶇姸鎬 ereport(ERROR, (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE), errmsg("recovery is in progress"), - errhint("Can't get local max LSN during recovery."))); - XLogRecPtr current_recptr = GetXLogWriteRecPtr(); - return current_recptr; + errhint("Can't get local max LSN during recovery."))); + XLogRecPtr current_recptr = GetXLogWriteRecPtr(); // 鑾峰彇褰撳墠鐨凩SN + return current_recptr; // 杩斿洖鏈澶х殑LSN } - +/* + * 鍔熻兘锛氭樉绀篨Log璁板綍鐨勪俊鎭 + * + * 鍙傛暟鍒楄〃锛 + * record锛歑Log璁板綍鐨勯槄璇荤姸鎬侊紙XLogReaderState锛 + * strOutput锛氱敤浜庡瓨鍌╔Log璁板綍淇℃伅鐨勫瓧绗︽暟缁 + * + * 娉ㄦ剰浜嬮」锛 + * - 璇ュ嚱鏁扮敤浜庡皢XLog璁板綍鐨勪俊鎭牸寮忓寲涓哄瓧绗︿覆骞跺瓨鍌ㄥ湪 strOutput 涓 + * - 鍑芥暟棣栧厛浣跨敤 snprintf_s + * 鍑芥暟鏍煎紡鍖栬褰曠殑璧峰LSN銆佺粨鏉烲SN銆佷簨鍔D銆乀erm銆佹婚暱搴﹀拰鎻忚堪绛変俊鎭紝骞跺皢鍏惰拷鍔犲埌strOutput銆 + * - 鐒跺悗鍒濆鍖栦竴涓瓧绗︿覆缂撳啿鍖 buf锛屽苟浣跨敤鐩稿簲鐨勫洖璋冨嚱鏁版牸寮忓寲XLog璁板綍鐨勬弿杩颁俊鎭紝骞惰拷鍔犲埌 strOutput銆 + * - 濡傛灉XLog璁板綍娌℃湁寮曠敤浠讳綍鍧楋紙block锛夛紝鍑芥暟鐩存帴杩斿洖銆 + * - 濡傛灉鏈夊潡寮曠敤锛屽嚱鏁颁細閬嶅巻姣忎釜鍧楀紩鐢ㄥ苟杩藉姞鐩稿叧淇℃伅鍒 strOutput銆 + */ static void XLogDumpDisplayRecord(XLogReaderState *record, char *strOutput) { - errno_t rc = snprintf_s(strOutput + (int)strlen(strOutput), MAXOUTPUTLEN, MAXOUTPUTLEN - 1, - "start_lsn: %X/%X \nend_lsn: %X/%X \nxid: " XID_FMT " \nterm: %u \ntotal length: %u \ndesc: %s - ", - (uint32)(record->ReadRecPtr >> XIDTHIRTYTWO), (uint32)record->ReadRecPtr, - (uint32)(record->EndRecPtr >> XIDTHIRTYTWO), (uint32)record->EndRecPtr, XLogRecGetXid(record), - XLogRecGetTerm(record), XLogRecGetTotalLen(record), RmgrTable[XLogRecGetRmid(record)].rm_name); + errno_t rc = + snprintf_s(strOutput + (int)strlen(strOutput), MAXOUTPUTLEN, MAXOUTPUTLEN - 1, + "start_lsn: %X/%X \nend_lsn: %X/%X \nxid: " XID_FMT " \nterm: %u \ntotal length: %u \ndesc: %s - ", + (uint32)(record->ReadRecPtr >> XIDTHIRTYTWO), (uint32)record->ReadRecPtr, + (uint32)(record->EndRecPtr >> XIDTHIRTYTWO), (uint32)record->EndRecPtr, XLogRecGetXid(record), + XLogRecGetTerm(record), XLogRecGetTotalLen(record), RmgrTable[XLogRecGetRmid(record)].rm_name); securec_check_ss(rc, "\0", "\0"); StringInfoData buf; initStringInfo(&buf); - RmgrTable[XLogRecGetRmid(record)].rm_desc(&buf, record); + // 浣跨敤鍥炶皟鍑芥暟灏哫Log璁板綍鐨勬弿杩颁俊鎭拷鍔犲埌 buf 涓 + RmgrTable[XLogRecGetRmid(record)].rm_desc(&buf, record); // 灏 buf 涓殑鎻忚堪淇℃伅杩藉姞鍒 strOutput 涓 rc = strcat_s(strOutput, MAXOUTPUTLEN, buf.data); securec_check(rc, "\0", "\0"); - if (!XLogRecHasAnyBlockRefs(record)) { + if (!XLogRecHasAnyBlockRefs(record)) { // 濡傛灉XLog璁板綍娌℃湁鍧楀紩鐢紝鐩存帴杩斿洖 rc = strcat_s(strOutput, MAXOUTPUTLEN, "\n\n"); securec_check(rc, "\0", "\0"); return; } - if (record->max_block_id >= 0) { + if (record->max_block_id >= 0) { // 濡傛灉XLog璁板綍寮曠敤浜嗗潡锛屾坊鍔犵浉鍏充俊鎭 rc = strcat_s(strOutput, MAXOUTPUTLEN, "\nothers: "); securec_check(rc, "\0", "\0"); } @@ -135,21 +215,22 @@ static void XLogDumpDisplayRecord(XLogReaderState *record, char *strOutput) if (!XLogRecHasBlockRef(record, block_id)) continue; /* Print format: others: rel %u/%u/%u/%d fork %s blk %u */ + // 鑾峰彇鍧楀紩鐢ㄧ殑鐩稿叧淇℃伅锛屽苟灏嗗叾杩藉姞鍒 strOutput 涓 RelFileNode rnode; ForkNumber forknum; BlockNumber blk; if (!XLogRecGetBlockTag(record, block_id, &rnode, &forknum, &blk)) continue; rc = snprintf_s(strOutput + (int)strlen(strOutput), MAXOUTPUTLEN, MAXOUTPUTLEN - 1, "\n\trel %u/%u/%u", - rnode.spcNode, rnode.dbNode, rnode.relNode); + rnode.spcNode, rnode.dbNode, rnode.relNode); securec_check_ss(rc, "\0", "\0"); if (IsBucketFileNode(rnode)) { /* check between InvalidBktId and SegmentBktId */ - rc = snprintf_s(strOutput + (int)strlen(strOutput), MAXOUTPUTLEN, MAXOUTPUTLEN - 1, - "/%d", rnode.bucketNode); + rc = + snprintf_s(strOutput + (int)strlen(strOutput), MAXOUTPUTLEN, MAXOUTPUTLEN - 1, "/%d", rnode.bucketNode); securec_check_ss(rc, "\0", "\0"); } rc = snprintf_s(strOutput + (int)strlen(strOutput), MAXOUTPUTLEN, MAXOUTPUTLEN - 1, ", fork %s", - forkNames[forknum]); + forkNames[forknum]); securec_check_ss(rc, "\0", "\0"); rc = snprintf_s(strOutput + (int)strlen(strOutput), MAXOUTPUTLEN, MAXOUTPUTLEN - 1, ", blk %u", blk); securec_check_ss(rc, "\0", "\0"); @@ -157,77 +238,153 @@ static void XLogDumpDisplayRecord(XLogReaderState *record, char *strOutput) XLogRecPtr lsn; XLogRecGetBlockLastLsn(record, block_id, &lsn); rc = snprintf_s(strOutput + (int)strlen(strOutput), MAXOUTPUTLEN, MAXOUTPUTLEN - 1, ", lastlsn %X/%X", - (uint32)(lsn >> XIDTHIRTYTWO), (uint32)lsn); + (uint32)(lsn >> XIDTHIRTYTWO), (uint32)lsn); securec_check_ss(rc, "\0", "\0"); } rc = strcat_s(strOutput, MAXOUTPUTLEN, "\n\n"); securec_check(rc, "\0", "\0"); } - +/* + * 鍔熻兘锛氭鏌ユ枃浠舵槸鍚︽垚鍔熸墦寮 + * + * 鍙傛暟鍒楄〃锛 + * outputfile锛氭寚鍚戝凡鎵撳紑鏂囦欢鐨勬寚閽 + * outputFilename锛氭枃浠跺悕鎴栬矾寰勭殑瀛楃涓茶〃绀 + * + * 娉ㄦ剰浜嬮」锛 + * - 璇ュ嚱鏁扮敤浜庢鏌ユ枃浠舵槸鍚︽垚鍔熸墦寮锛屽鏋滄枃浠舵寚閽堜负 NULL锛屽垯琛ㄧず鏂囦欢鏈垚鍔熸墦寮锛 + * 鍑芥暟灏嗙敓鎴愪竴涓敊璇姤鍛婂苟鎸囨槑鏃犳硶璇诲彇鐨勬枃浠跺悕銆 + */ void CheckOpenFile(FILE *outputfile, char *outputFilename) { - if (outputfile == NULL) + if (outputfile == NULL) // 妫鏌ユ枃浠舵寚閽堟槸鍚︿负 NULL ereport(ERROR, (errcode(ERRCODE_FILE_READ_FAILED), (errmsg("Cannot read %s", outputFilename)))); } - +/* + * 鍔熻兘锛氭鏌ユ枃浠跺啓鍏ユ槸鍚︽垚鍔 + * + * 鍙傛暟鍒楄〃锛 + * result锛氬啓鍏ユ搷浣滅殑缁撴灉锛岄氬父鏄啓鍏ョ殑瀛楄妭鏁 + * cnt_len锛氭湡鏈涚殑鍐欏叆瀛楄妭鏁 + * outputFilename锛氭枃浠跺悕鎴栬矾寰勭殑瀛楃涓茶〃绀 + * + * 娉ㄦ剰浜嬮」锛 + * - + * 璇ュ嚱鏁扮敤浜庢鏌ユ枃浠跺啓鍏ユ搷浣滄槸鍚︽垚鍔燂紝濡傛灉鍐欏叆瀛楄妭鏁颁笉绛変簬鏈熸湜鐨勫瓧鑺傛暟锛屽嚱鏁板皢鐢熸垚涓涓敊璇姤鍛婂苟鎸囨槑鏃犳硶鍐欏叆鐨勬枃浠跺悕銆 + */ void CheckWriteFile(int result, int cnt_len, char *outputFilename) { - if (result != cnt_len) + if (result != cnt_len) // 妫鏌ュ啓鍏ユ搷浣滅殑缁撴灉鏄惁绛変簬鏈熸湜鐨勫瓧鑺傛暟 ereport(ERROR, (errcode(ERRCODE_FILE_WRITE_FAILED), (errmsg("Cannot write %s", outputFilename)))); } - +/* + * 鍔熻兘锛氭鏌ユ枃浠跺叧闂槸鍚︽垚鍔 + * + * 鍙傛暟鍒楄〃锛 + * result锛氬叧闂搷浣滅殑缁撴灉锛岄氬父鏄0琛ㄧず鎴愬姛锛岄潪0琛ㄧず澶辫触 + * outputFilename锛氭枃浠跺悕鎴栬矾寰勭殑瀛楃涓茶〃绀 + * + * 娉ㄦ剰浜嬮」锛 + * - 璇ュ嚱鏁扮敤浜庢鏌ユ枃浠跺叧闂搷浣滄槸鍚︽垚鍔燂紝濡傛灉鍏抽棴鎿嶄綔缁撴灉闈0锛 + * 鍑芥暟灏嗙敓鎴愪竴涓敊璇姤鍛婂苟鎸囨槑鏃犳硶鍏抽棴鐨勬枃浠跺悕銆 + */ void CheckCloseFile(int result, char *outputFilename) { - if (0 != result) + if (0 != result) // 妫鏌ュ叧闂搷浣滅殑缁撴灉鏄惁闈0 ereport(ERROR, (errcode(ERRCODE_IO_ERROR), (errmsg("Cannot close %s", outputFilename)))); } - +/* + * 鍔熻兘锛氭鏌Log璁板綍鏄惁绗﹀悎杩囨护鏉′欢 + * + * 鍙傛暟鍒楄〃锛 + * xlogreader_state锛歑Log璁板綍鐨勯槄璇荤姸鎬 + * filter锛歑Log杩囨护鍣 + * + * 娉ㄦ剰浜嬮」锛 + * - 璇ュ嚱鏁扮敤浜庢鏌Log璁板綍鏄惁绗﹀悎缁欏畾鐨勮繃婊ゆ潯浠躲 + * - 鍑芥暟浼氶亶鍘哫Log璁板綍寮曠敤鐨勬墍鏈夊潡锛屾瘮杈冨潡鐨勬枃浠惰妭鐐瑰拰鍧楀彿涓庤繃婊ゅ櫒涓殑鏉′欢銆 + * - 濡傛灉鎵惧埌鍖归厤鐨勫潡锛屾牴鎹繃婊ゅ櫒涓殑鍙傛暟鍒ゆ柇鏄惁绗﹀悎鏉′欢銆 + * - 濡傛灉绗﹀悎鏉′欢锛屽嚱鏁拌繑鍥瀟rue锛屽惁鍒欒繑鍥瀎alse銆 + */ static bool CheckValidRecord(XLogReaderState *xlogreader_state, XLogFilter *filter) { - bool found = false; + bool found = false; // 鍒濆鍖 found 鍙橀噺涓 false for (int i = 0; i <= xlogreader_state->max_block_id; i++) { RelFileNode rnode; ForkNumber forknum; BlockNumber blk; if (!XLogRecGetBlockTag(xlogreader_state, i, &rnode, &forknum, &blk)) continue; - if (RelFileNodeEquals(rnode, filter->by_relfilenode)) + if (RelFileNodeEquals(rnode, filter->by_relfilenode)) // 妫鏌ユ枃浠惰妭鐐规槸鍚﹀尮閰嶈繃婊ゅ櫒涓殑鏉′欢 /* if equal to specific block or check all blocks, found = ture; */ - found = (!filter->by_block) || (blk == filter->blocknum); + found = (!filter->by_block) || (blk == filter->blocknum); // 妫鏌ュ潡鍙锋槸鍚﹀尮閰嶈繃婊ゅ櫒涓殑鏉′欢 if (found) { - return found; + return found; // 濡傛灉鎵惧埌鍖归厤鐨勫潡锛屾牴鎹繃婊ゅ櫒涓殑鍙傛暟鍒ゆ柇鏄惁绗﹀悎鏉′欢锛屽鏋滅鍚堟潯浠讹紝杩斿洖true } } - return found; + return found; // 濡傛灉娌℃湁鎵惧埌鍖归厤鐨勫潡锛岃繑鍥瀎alse } +/* + * 鍔熻兘锛氭洿鏂颁笅涓涓狶SN + * + * 鍙傛暟鍒楄〃锛 + * cur_lsn锛氬綋鍓峀SN + * end_lsn锛氱粨鏉烲SN + * xlogreader_state锛歑Log璁板綍鐨勯槄璇荤姸鎬侊紙XLogReaderState锛 + * found锛氫竴涓寚鍚戝竷灏斿肩殑鎸囬拡锛岀敤浜庢寚绀烘槸鍚︽壘鍒颁笅涓涓褰 + * + * 娉ㄦ剰浜嬮」锛 + * - 璇ュ嚱鏁扮敤浜庢洿鏂颁笅涓涓狶SN锛屼互渚跨户缁鎵剧鍚堟潯浠剁殑XLog璁板綍銆 + * - 鍑芥暟鍦ㄧ粰瀹氱殑灏濊瘯娆℃暟鍐咃紝浠庡綋鍓峀SN寮濮嬫煡鎵句笅涓涓褰曪紝纭繚瀹冨湪鎸囧畾鐨勭粨鏉烲SN涔嬪墠銆 + * - 濡傛灉鎵惧埌绗﹀悎鏉′欢鐨勮褰曪紝灏嗛氳繃 found 鎸囬拡杩斿洖 true銆 + * - 濡傛灉鍦ㄥ皾璇曟鏁板唴鏈壘鍒扮鍚堟潯浠剁殑璁板綍锛屽嚱鏁拌繑鍥濱nvalidXLogRecPtr銆 + */ static XLogRecPtr UpdateNextLSN(XLogRecPtr cur_lsn, XLogRecPtr end_lsn, XLogReaderState *xlogreader_state, bool *found) { - XLogRecPtr next_record = InvalidXLogRecPtr; - for (int tryTimes = 0; tryTimes < FIVE; tryTimes++) { - XLogRecPtr start_lsn = Max(cur_lsn, (g_instance.comm_cxt.predo_cxt.redoPf.oldest_segment) * XLogSegSize); - next_record = XLogFindNextRecord(xlogreader_state, start_lsn); - if (!XLByteEQ(next_record, InvalidXLogRecPtr) && XLByteLT(next_record, end_lsn)) { - *found = true; - return next_record; + XLogRecPtr next_record = InvalidXLogRecPtr; // 鍒濆鍖栦笅涓涓狶SN涓篒nvalidXLogRecPtr + + for (int tryTimes = 0; tryTimes < FIVE; tryTimes++) { // 杩涜鏈澶5娆″皾璇 + XLogRecPtr start_lsn = + Max(cur_lsn, (g_instance.comm_cxt.predo_cxt.redoPf.oldest_segment) * XLogSegSize); // 璁$畻璧峰LSN + next_record = XLogFindNextRecord(xlogreader_state, start_lsn); // 瀵绘壘涓嬩竴涓褰 + if (!XLByteEQ(next_record, InvalidXLogRecPtr) && XLByteLT(next_record, end_lsn)) { // 濡傛灉鎵惧埌绗﹀悎鏉′欢鐨勮褰 + *found = true; // 璁剧疆 found 涓 true + return next_record; // 杩斿洖涓嬩竴涓狶SN } } - return next_record; + return next_record; // 濡傛灉鍦ㄥ皾璇曟鏁板唴鏈壘鍒扮鍚堟潯浠剁殑璁板綍锛岃繑鍥濱nvalidXLogRecPtr } - +/* + * 鍔熻兘锛氬皢XLog璁板綍杞偍鍒版枃浠 + * + * 鍙傛暟鍒楄〃锛 + * start_lsn锛氳寮濮嬭浆鍌ㄧ殑XLog璁板綍鐨凩SN + * end_lsn锛氳缁撴潫杞偍鐨刋Log璁板綍鐨凩SN + * filter锛歑Log杩囨护鍣紝鐢ㄤ簬绛涢夎褰 + * outputFilename锛氳鍐欏叆鐨勮緭鍑烘枃浠跺悕 + * + * 娉ㄦ剰浜嬮」锛 + * - 璇ュ嚱鏁扮敤浜庡皢XLog璁板綍杞偍鍒版寚瀹氱殑杈撳嚭鏂囦欢銆 + * - 鍑芥暟棣栧厛鍒嗛厤XLog闃呰鍣ㄧ姸鎬侊紝鐒跺悗鏌ユ壘绗竴涓鍚堟潯浠剁殑XLog璁板綍銆 + * - 濡傛灉鏈壘鍒扮涓涓褰曪紝鍑芥暟浼氬皾璇曞娆℃煡鎵撅紝鐩村埌鎵惧埌鍚堥傜殑璁板綍銆 + * - 鎺ョ潃锛屽嚱鏁伴愪釜璇诲彇绗﹀悎鏉′欢鐨刋Log璁板綍锛屽苟灏嗗叾鍐欏叆杈撳嚭鏂囦欢銆 + * - 鏈鍚庯紝鍑芥暟鐢熸垚鎬荤粨淇℃伅锛屽寘鎷鍙栫殑璁板綍鏁伴噺鍜屾湁鏁堢殑璧峰鍜岀粨鏉烲SN銆 + */ static void XLogDump(XLogRecPtr start_lsn, XLogRecPtr end_lsn, XLogFilter *filter, char *outputFilename) { /* start reading */ errno_t rc = EOK; XLogPrivate readprivate; - rc = memset_s(&readprivate, sizeof(XLogPrivate), 0, sizeof(XLogPrivate)); + rc = memset_s(&readprivate, sizeof(XLogPrivate), 0, sizeof(XLogPrivate)); // 鍒濆鍖栬鍙栫鏈夋暟鎹 securec_check_c(rc, "\0", "\0"); - readprivate.datadir = t_thrd.proc_cxt.DataDir; - readprivate.tli = 1; + readprivate.datadir = t_thrd.proc_cxt.DataDir; // 璁剧疆鏁版嵁鐩綍璺緞 + readprivate.tli = 1; // 璁剧疆鏃堕棿绾縄D + // 鍒嗛厤XLog闃呰鍣ㄧ姸鎬 XLogReaderState *xlogreader_state = XLogReaderAllocate(&SimpleXLogPageRead, &readprivate); if (!xlogreader_state) ereport(ERROR, (errcode(ERRCODE_INSUFFICIENT_RESOURCES), - (errmsg("memory is temporarily unavailable while allocate xlog reader")))); + (errmsg("memory is temporarily unavailable while allocate xlog reader")))); /* get the first valid xlog record location */ XLogRecPtr first_record = XLogFindNextRecord(xlogreader_state, start_lsn); @@ -235,32 +392,32 @@ static void XLogDump(XLogRecPtr start_lsn, XLogRecPtr end_lsn, XLogFilter *filte * Hence, we need to update the min_lsn */ if (XLByteEQ(first_record, InvalidXLogRecPtr)) { ereport(WARNING, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - (errmsg("XLogFindNextRecord: could not find a valid record after %X/%X. Retry.", - (uint32)(start_lsn >> XIDTHIRTYTWO), (uint32)start_lsn)))); + (errmsg("XLogFindNextRecord: could not find a valid record after %X/%X. Retry.", + (uint32)(start_lsn >> XIDTHIRTYTWO), (uint32)start_lsn)))); bool found = false; + // 灏濊瘯鏌ユ壘涓嬩竴涓褰 first_record = UpdateNextLSN(start_lsn, end_lsn, xlogreader_state, &found); if (!found) - ereport(ERROR, - (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - (errmsg("XLogFindNextRecord: could not find a valid record between %X/%X and %X/%X.", - (uint32)(start_lsn >> XIDTHIRTYTWO), (uint32)start_lsn, - (uint32)(end_lsn >> XIDTHIRTYTWO), (uint32)end_lsn)))); + ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + (errmsg("XLogFindNextRecord: could not find a valid record between %X/%X and %X/%X.", + (uint32)(start_lsn >> XIDTHIRTYTWO), (uint32)start_lsn, + (uint32)(end_lsn >> XIDTHIRTYTWO), (uint32)end_lsn)))); } XLogRecPtr valid_start_lsn = first_record; XLogRecPtr valid_end_lsn = valid_start_lsn; - FILE *outputfile = fopen(outputFilename, "w"); - CheckOpenFile(outputfile, outputFilename); + FILE *outputfile = fopen(outputFilename, "w"); // 鎵撳紑杈撳嚭鏂囦欢 + CheckOpenFile(outputfile, outputFilename); // 妫鏌ユ枃浠舵槸鍚︽垚鍔熸墦寮 char *strOutput = (char *)palloc(MAXOUTPUTLEN * sizeof(char)); rc = memset_s(strOutput, MAXOUTPUTLEN, 0, MAXOUTPUTLEN); securec_check(rc, "\0", "\0"); /* valid first record is not the given one */ if (!XLByteEQ(first_record, start_lsn) && (start_lsn % XLogSegSize) != 0) { rc = snprintf_s(strOutput + (int)strlen(strOutput), MAXOUTPUTLEN, MAXOUTPUTLEN - 1, - "first record is after %X/%X, at %X/%X, skipping over %lu bytes\n", (uint32)(start_lsn >> XIDTHIRTYTWO), - (uint32)start_lsn, (uint32)(first_record >> XIDTHIRTYTWO), (uint32)first_record, - XLByteDifference(first_record, start_lsn)); + "first record is after %X/%X, at %X/%X, skipping over %lu bytes\n", + (uint32)(start_lsn >> XIDTHIRTYTWO), (uint32)start_lsn, (uint32)(first_record >> XIDTHIRTYTWO), + (uint32)first_record, XLByteDifference(first_record, start_lsn)); securec_check_ss(rc, "\0", "\0"); } CheckWriteFile(fwrite(strOutput, 1, strlen(strOutput), outputfile), strlen(strOutput), outputFilename); @@ -279,27 +436,23 @@ static void XLogDump(XLogRecPtr start_lsn, XLogRecPtr end_lsn, XLogFilter *filte XLogRecPtr temp_start_lsn = Max(xlogreader_state->EndRecPtr, start_lsn); first_record = UpdateNextLSN(temp_start_lsn, end_lsn, xlogreader_state, &found); if (found) { - ereport(WARNING, (errcode(ERRCODE_WARNING), - (errmsg("We cannot read %X/%X. After retried, we jump to read the next available %X/%X. " \ - "The missing part might be recycled or removed.", - (uint32)(temp_start_lsn >> XIDTHIRTYTWO), (uint32)temp_start_lsn, - (uint32)(first_record >> XIDTHIRTYTWO), (uint32)first_record)))); + ereport(WARNING, + (errcode(ERRCODE_WARNING), + (errmsg("We cannot read %X/%X. After retried, we jump to read the next available %X/%X. " + "The missing part might be recycled or removed.", + (uint32)(temp_start_lsn >> XIDTHIRTYTWO), (uint32)temp_start_lsn, + (uint32)(first_record >> XIDTHIRTYTWO), (uint32)first_record)))); continue; } if (errormsg != NULL) - ereport(LOG, - (errcode(ERRCODE_LOG), - (errmsg("could not read WAL record at %X/%X: %s", - (uint32)(xlogreader_state->ReadRecPtr >> XIDTHIRTYTWO), - (uint32)xlogreader_state->ReadRecPtr, - errormsg)))); + ereport(LOG, (errcode(ERRCODE_LOG), (errmsg("could not read WAL record at %X/%X: %s", + (uint32)(xlogreader_state->ReadRecPtr >> XIDTHIRTYTWO), + (uint32)xlogreader_state->ReadRecPtr, errormsg)))); else - ereport(LOG, - (errcode(ERRCODE_LOG), - (errmsg("could not read WAL record at %X/%X", - (uint32)(xlogreader_state->ReadRecPtr >> XIDTHIRTYTWO), - (uint32)xlogreader_state->ReadRecPtr)))); + ereport(LOG, (errcode(ERRCODE_LOG), (errmsg("could not read WAL record at %X/%X", + (uint32)(xlogreader_state->ReadRecPtr >> XIDTHIRTYTWO), + (uint32)xlogreader_state->ReadRecPtr)))); break; } first_record = InvalidXLogRecPtr; /* No explicit start point; read the record after the one we just read */ @@ -333,9 +486,9 @@ static void XLogDump(XLogRecPtr start_lsn, XLogRecPtr end_lsn, XLogFilter *filte /* Summary(xx total): valid start_lsn: xxx, valid end_lsn: xxx */ rc = snprintf_s(strOutput + (int)strlen(strOutput), MAXOUTPUTLEN, MAXOUTPUTLEN - 1, - "\nSummary (%d total): valid start_lsn: %X/%X, valid end_lsn: %X/%X\n", count, - (uint32)(valid_start_lsn >> XIDTHIRTYTWO), (uint32)(valid_start_lsn), (uint32)(valid_end_lsn >> XIDTHIRTYTWO), - (uint32)(valid_end_lsn)); + "\nSummary (%d total): valid start_lsn: %X/%X, valid end_lsn: %X/%X\n", count, + (uint32)(valid_start_lsn >> XIDTHIRTYTWO), (uint32)(valid_start_lsn), + (uint32)(valid_end_lsn >> XIDTHIRTYTWO), (uint32)(valid_end_lsn)); securec_check_ss(rc, "\0", "\0"); /* generate output file */ CheckWriteFile(fwrite(strOutput, 1, strlen(strOutput), outputfile), strlen(strOutput), outputFilename); @@ -345,29 +498,45 @@ static void XLogDump(XLogRecPtr start_lsn, XLogRecPtr end_lsn, XLogFilter *filte } /* There are only two parameters in PG_FUNCTION_ARGS: start_lsn and end_lsn */ +/* + * 鍔熻兘锛氬皢鎸囧畾LSN鑼冨洿鍐呯殑XLog璁板綍杞偍鍒版枃浠朵腑 + * + * 鍙傛暟鍒楄〃锛 + * start_lsn_str锛氭寚瀹氳寖鍥寸殑璧峰LSN鐨勫瓧绗︿覆琛ㄧず + * end_lsn_str锛氭寚瀹氳寖鍥寸殑缁撴潫LSN鐨勫瓧绗︿覆琛ㄧず + * + * 杩斿洖鍊硷細 + * - 杩斿洖涓涓枃鏈瓧绗︿覆锛岃〃绀虹敓鎴愮殑杈撳嚭鏂囦欢鍚 + * + * 娉ㄦ剰浜嬮」锛 + * - 璇ュ嚱鏁扮敤浜庡皢鎸囧畾LSN鑼冨洿鍐呯殑XLog璁板綍杞偍鍒版枃浠朵腑锛屼互渚垮垎鏋愬拰妫鏌ャ + * - 鍑芥暟浼氶獙璇丩SN鑼冨洿锛岀敓鎴愯緭鍑烘枃浠跺悕锛屽苟鍩轰簬褰撳墠鐨勬渶灏廘SN鍜屾渶澶SN鏉ユ洿鏂拌寖鍥淬 + * - 杈撳嚭鏂囦欢鍚嶅皢鍖呭惈鏁版嵁鐩綍璺緞鍜孡SN鑼冨洿銆 + * - 閫氬父鐢辩敤鎴疯皟鐢紝浠ヤ究鏍规嵁LSN鑼冨洿鏉ユ煡鐪媂Log璁板綍銆 + */ Datum gs_xlogdump_lsn(PG_FUNCTION_ARGS) { errno_t rc = EOK; /* check user's right */ const char fName[MAXFNAMELEN] = "gs_xlogdump_lsn"; - CheckUser(fName); + CheckUser(fName); // 妫鏌ョ敤鎴锋潈闄 /* read in parameters */ - char *start_lsn_str = text_to_cstring(PG_GETARG_TEXT_P(0)); - char *end_lsn_str = text_to_cstring(PG_GETARG_TEXT_P(1)); + char *start_lsn_str = text_to_cstring(PG_GETARG_TEXT_P(0)); // 璇诲彇璧峰LSN瀛楃涓 + char *end_lsn_str = text_to_cstring(PG_GETARG_TEXT_P(1)); // 璇诲彇缁撴潫LSN瀛楃涓 /* validate lsn */ XLogRecPtr start_lsn, end_lsn; - ValidateStartEndLSN(start_lsn_str, end_lsn_str, &start_lsn, &end_lsn); + ValidateStartEndLSN(start_lsn_str, end_lsn_str, &start_lsn, &end_lsn); // 楠岃瘉璧峰鍜岀粨鏉烲SN - char *outputFilename = (char *)palloc(MAXFILENAME * sizeof(char)); - rc = memset_s(outputFilename, MAXFILENAME, 0, MAXFILENAME); + char *outputFilename = (char *)palloc(MAXFILENAME * sizeof(char)); // 鍒嗛厤鐢ㄤ簬瀛樺偍杈撳嚭鏂囦欢鍚嶇殑鍐呭瓨 + rc = memset_s(outputFilename, MAXFILENAME, 0, MAXFILENAME); // 鍒濆鍖栬緭鍑烘枃浠跺悕 securec_check(rc, "\0", "\0"); - GenerateOutputFileName(outputFilename, start_lsn_str, end_lsn_str); + GenerateOutputFileName(outputFilename, start_lsn_str, end_lsn_str); // 鐢熸垚杈撳嚭鏂囦欢鍚 /* update start_lsn and end_lsn based on cur min_lsn and max_lsn */ - XLogRecPtr min_lsn = GetMinLSN(); - XLogRecPtr max_lsn = GetMaxLSN(); + XLogRecPtr min_lsn = GetMinLSN(); // 鑾峰彇鏈灏廘SN + XLogRecPtr max_lsn = GetMaxLSN(); // 鑾峰彇鏈澶SN if (XLByteLT(start_lsn, min_lsn)) { start_lsn = min_lsn; @@ -377,13 +546,28 @@ Datum gs_xlogdump_lsn(PG_FUNCTION_ARGS) } XLogFilter filter; - rc = memset_s(&filter, sizeof(XLogFilter), 0, sizeof(XLogFilter)); + rc = memset_s(&filter, sizeof(XLogFilter), 0, sizeof(XLogFilter)); // 鍒濆鍖朮Log杩囨护鍣 securec_check_ss(rc, "\0", "\0"); - XLogDump(start_lsn, end_lsn, &filter, outputFilename); - PG_RETURN_TEXT_P(cstring_to_text(outputFilename)); + XLogDump(start_lsn, end_lsn, &filter, outputFilename); // 鎵цXLog璁板綍杞偍鎿嶄綔 + PG_RETURN_TEXT_P(cstring_to_text(outputFilename)); // 灏嗚緭鍑烘枃浠跺悕杞崲涓烘枃鏈苟杩斿洖 } /* There are only one parameter in PG_FUNCTION_ARGS: c_xid */ +/* + * 鍔熻兘锛氬皢鎸囧畾浜嬪姟ID锛圶ID锛夎寖鍥村唴鐨刋Log璁板綍杞偍鍒版枃浠朵腑 + * + * 鍙傛暟鍒楄〃锛 + * c_xid锛氳杞偍鐨勮捣濮嬩簨鍔D + * + * 杩斿洖鍊硷細 + * - 杩斿洖涓涓枃鏈瓧绗︿覆锛岃〃绀虹敓鎴愮殑杈撳嚭鏂囦欢鍚 + * + * 娉ㄦ剰浜嬮」锛 + * - 璇ュ嚱鏁扮敤浜庡皢鎸囧畾浜嬪姟ID鑼冨洿鍐呯殑XLog璁板綍杞偍鍒版枃浠朵腑锛屼互渚垮垎鏋愬拰妫鏌ャ + * - 鍑芥暟浼氶獙璇佷簨鍔D鑼冨洿锛岀敓鎴愯緭鍑烘枃浠跺悕锛屽苟鍩轰簬褰撳墠鐨勬渶灏廘SN鍜屾渶澶SN鏉ユ洿鏂拌寖鍥淬 + * - 杈撳嚭鏂囦欢鍚嶅皢鍖呭惈鏁版嵁鐩綍璺緞鍜屼簨鍔D銆 + * - 閫氬父鐢辩敤鎴疯皟鐢紝浠ヤ究鏍规嵁浜嬪姟ID鑼冨洿鏉ユ煡鐪媂Log璁板綍銆 + */ Datum gs_xlogdump_xid(PG_FUNCTION_ARGS) { errno_t rc = EOK; @@ -396,15 +580,15 @@ Datum gs_xlogdump_xid(PG_FUNCTION_ARGS) /* check parameters */ TransactionId topXid = GetTopTransactionId(); if (TransactionIdPrecedes(topXid, c_xid)) - ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - (errmsg("Xid should less than or equal to %lu.", topXid)))); + ereport(ERROR, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), (errmsg("Xid should less than or equal to %lu.", topXid)))); /* generate output file name */ char *outputFilename = (char *)palloc(MAXFILENAME * sizeof(char)); rc = memset_s(outputFilename, MAXFILENAME, 0, MAXFILENAME); securec_check(rc, "\0", "\0"); rc = snprintf_s(outputFilename + (int)strlen(outputFilename), MAXFILENAME, MAXFILENAME - 1, "%s/%lu.xlog", - t_thrd.proc_cxt.DataDir, c_xid); + t_thrd.proc_cxt.DataDir, c_xid); securec_check_ss(rc, "\0", "\0"); /* update start_lsn and end_lsn based on cur min_lsn and max_lsn */ XLogRecPtr min_lsn = GetMinLSN(); @@ -433,7 +617,7 @@ Datum gs_xlogdump_tablepath(PG_FUNCTION_ARGS) /* check parameters */ if (blocknum > MaxBlockNumber || blocknum < -1) ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - (errmsg("Blocknum should be between -1 and %u.", MaxBlockNumber)))); + (errmsg("Blocknum should be between -1 and %u.", MaxBlockNumber)))); /* update start_lsn and end_lsn based on cur min_lsn and max_lsn */ XLogRecPtr min_lsn = GetMinLSN(); @@ -516,7 +700,8 @@ Datum gs_xlogdump_parsepage_tablepath(PG_FUNCTION_ARGS) securec_check(rc, "\0", "\0"); rc = snprintf_s(result + (int)strlen(result), outputLen, outputLen - 1, - "Output file for parsing xlog: %s\nOutput file for parsing data page: %s", outputFilename, outputFilenamePage); + "Output file for parsing xlog: %s\nOutput file for parsing data page: %s", outputFilename, + outputFilenamePage); securec_check_ss(rc, "\0", "\0"); pfree_ext(outputFilename); PG_RETURN_TEXT_P(cstring_to_text(result)); diff --git a/src/gausskernel/storage/page/pagecompress.cpp b/src/gausskernel/storage/page/pagecompress.cpp index f1d2112e0..b6232c491 100644 --- a/src/gausskernel/storage/page/pagecompress.cpp +++ b/src/gausskernel/storage/page/pagecompress.cpp @@ -50,32 +50,26 @@ static Datum int32Plus(Datum arg1, int64 arg2); static Datum uint32Plus(Datum arg1, int64 arg2); static Datum int64Plus(Datum arg1, int64 arg2); -static const NumberTypeOpt* binarySearch(Oid typeOid); +static const NumberTypeOpt *binarySearch(Oid typeOid); /* const array for number type. */ static const NumberTypeOpt g_number_types[] = { - { 20, int64Compare, int64Minus, int64Plus }, /* int8 */ - { 21, int16Compare, int16Minus, int16Plus }, /* int2 */ - { 23, int32Compare, int32Minus, int32Plus }, /* int4 */ - { 26, uint32Compare, uint32Minus, uint32Plus }, /* oid */ - { 1082, int32Compare, int32Minus, int32Plus }, /* date */ - { 1083, int64Compare, int64Minus, int64Plus }, /* time */ - { 1114, int64Compare, int64Minus, int64Plus }, /* timestamp */ - { 1184, int64Compare, int64Minus, int64Plus }, /* timestamptz */ - { 12089, int64Compare, int64Minus, int64Plus }, /* time_stamp */ + {20, int64Compare, int64Minus, int64Plus}, /* int8 */ + {21, int16Compare, int16Minus, int16Plus}, /* int2 */ + {23, int32Compare, int32Minus, int32Plus}, /* int4 */ + {26, uint32Compare, uint32Minus, uint32Plus}, /* oid */ + {1082, int32Compare, int32Minus, int32Plus}, /* date */ + {1083, int64Compare, int64Minus, int64Plus}, /* time */ + {1114, int64Compare, int64Minus, int64Plus}, /* timestamp */ + {1184, int64Compare, int64Minus, int64Plus}, /* timestamptz */ + {12089, int64Compare, int64Minus, int64Plus}, /* time_stamp */ }; static const int g_number_type_count = sizeof(g_number_types) / sizeof(NumberTypeOpt); /* Map about max values in byte for delta compression */ -static const int64 g_max_value_in_bytes[] = {0x0000000000000000, - 0x00000000000000FF, - 0x000000000000FFFF, - 0x0000000000FFFFFF, - 0x00000000FFFFFFFF, - 0x000000FFFFFFFFFF, - 0x0000FFFFFFFFFFFF, - 0x00FFFFFFFFFFFFFF - }; +static const int64 g_max_value_in_bytes[] = {0x0000000000000000, 0x00000000000000FF, 0x000000000000FFFF, + 0x0000000000FFFFFF, 0x00000000FFFFFFFF, 0x000000FFFFFFFFFF, + 0x0000FFFFFFFFFFFF, 0x00FFFFFFFFFFFFFF}; static const int64 g_number_max_value_in_bytes = (int64)(sizeof(g_max_value_in_bytes) / sizeof(int64)); #define getTupleSpace(_tuple) (sizeof(ItemIdData) + MAXALIGN((_tuple)->t_len)) @@ -123,10 +117,10 @@ static uint32 getBitsOfDelta(uint64 delta) #define DICT_ITEMID_SIZE 1 #define DICT_MISS_THRESHOLD 2 -static int matchDictItem(const void* left, const void* right, Size keysize) +static int matchDictItem(const void *left, const void *right, Size keysize) { - const DictItemData* leftItem = (DictItemData*)left; - const DictItemData* rightItem = (DictItemData*)right; + const DictItemData *leftItem = (DictItemData *)left; + const DictItemData *rightItem = (DictItemData *)right; Assert(leftItem != NULL && rightItem != NULL); /* we just care whether the result is 0 or not. */ @@ -137,14 +131,14 @@ static int matchDictItem(const void* left, const void* right, Size keysize) return memcmp(leftItem->itemData, rightItem->itemData, leftItem->itemSize); } -static uint32 hashDictItem(const void* key, Size keysize) +static uint32 hashDictItem(const void *key, Size keysize) { - const DictItemData* item = (const DictItemData*)key; - return DatumGetUInt32(hash_any((const unsigned char*)item->itemData, item->itemSize)); + const DictItemData *item = (const DictItemData *)key; + return DatumGetUInt32(hash_any((const unsigned char *)item->itemData, item->itemSize)); } /* create hash table for building dictionary */ -static HTAB* hashCreate(const char* name, MemoryContext memCxt, int nelem, int keysize, int entrysize) +static HTAB *hashCreate(const char *name, MemoryContext memCxt, int nelem, int keysize, int entrysize) { HASHCTL hashCtrl; errno_t rc = memset_s(&hashCtrl, sizeof(hashCtrl), 0, sizeof(hashCtrl)); @@ -159,29 +153,63 @@ static HTAB* hashCreate(const char* name, MemoryContext memCxt, int nelem, int k return hash_create(name, nelem, &hashCtrl, flags); } - +/* + * 鍔熻兘锛氭瀯寤哄瓧鍏搁」鍝堝笇琛 + * + * 鍙傛暟鍒楄〃锛 + * memCxt锛氬唴瀛樹笂涓嬫枃锛岀敤浜庡垎閰嶅搱甯岃〃鐨勫唴瀛 + * + * 娉ㄦ剰浜嬮」锛 + * - 璇ュ嚱鏁扮敤浜庡湪缁欏畾鐨勫唴瀛樹笂涓嬫枃涓瀯寤轰竴涓搱甯岃〃锛岀敤浜庡瓨鍌ㄥ瓧鍏搁」鏁版嵁銆 + * - 瀛楀吀椤瑰搱甯岃〃鐢ㄤ簬蹇熸煡鎵惧拰璁块棶瀛楀吀椤规暟鎹 + * - 瀛楀吀椤圭殑鏁伴噺蹇呴』涓嶈秴杩囨渶澶ч檺鍒讹紙MAX_DICITEMID锛夈 + * - 濡傛灉瀛楀吀椤瑰湪鍝堝笇琛ㄤ腑宸插瓨鍦紝鍒欎細鏇存柊鍏禝D銆 + */ void DictCmprMeta::BuildHashTbl(MemoryContext memCxt) { + // 鍒涘缓涓涓搱甯岃〃骞跺垎閰嶅唴瀛樹笂涓嬫枃 m_hash = hashCreate("DictInfo Hash", memCxt, dictItemNum + 16, sizeof(DictItemData), sizeof(ItemEntry)); + // 纭繚瀛楀吀椤规暟閲忎笉瓒呰繃鏈澶ч檺鍒 Assert(dictItemNum <= MAX_DICITEMID); + // 閬嶅巻瀛楀吀椤规暟缁勶紝灏嗘瘡涓瓧鍏搁」鎻掑叆鍝堝笇琛 for (int i = 0; i < dictItemNum; ++i) { - ItemEntry* dicItemEntry = (ItemEntry*)hash_search(m_hash, (const void*)(dictItems + i), HASH_ENTER, NULL); - Assert(dicItemEntry); - dicItemEntry->id = (unsigned char)i; + // 灏濊瘯鍦ㄥ搱甯岃〃涓煡鎵惧瓧鍏搁」锛屽鏋滀笉瀛樺湪鍒欏垱寤哄苟鎻掑叆 + ItemEntry *dicItemEntry = (ItemEntry *)hash_search(m_hash, (const void *)(dictItems + i), HASH_ENTER, NULL); + Assert(dicItemEntry); // 纭繚鎴愬姛鎻掑叆瀛楀吀椤 + dicItemEntry->id = (unsigned char)i; // 璁剧疆瀛楀吀椤圭殑ID } } - -unsigned char DictCmprMeta::GetDictItemId(DictItemData* key, bool& found) +/* + * 鍔熻兘锛氭牴鎹瓧鍏搁」鏌ユ壘鍏禝D + * + * 鍙傛暟鍒楄〃锛 + * key锛氳鏌ユ壘鐨勫瓧鍏搁」 + * found锛氱敤浜庤繑鍥炴煡鎵剧粨鏋滅殑甯冨皵鍊硷紝濡傛灉鎵惧埌鍒欎负true锛屽惁鍒欎负false + * + * 娉ㄦ剰浜嬮」锛 + * - 璇ュ嚱鏁扮敤浜庢牴鎹粰瀹氱殑瀛楀吀椤规煡鎵惧叾鍦ㄥ搱甯岃〃涓殑ID銆 + * - 鍙傛暟 found 浼氭寚绀烘槸鍚︽壘鍒颁簡瀛楀吀椤广 + */ +unsigned char DictCmprMeta::GetDictItemId(DictItemData *key, bool &found) { - ItemEntry* dicItemEntry = (ItemEntry*)hash_search(m_hash, (const void*)key, HASH_FIND, &found); + // 鍦ㄥ搱甯岃〃涓煡鎵惧瓧鍏搁」 + ItemEntry *dicItemEntry = (ItemEntry *)hash_search(m_hash, (const void *)key, HASH_FIND, &found); + // 濡傛灉鎵惧埌瀛楀吀椤癸紝鍒欒繑鍥炲叾ID锛涘惁鍒欒繑鍥0 if (found) return dicItemEntry->id; return 0; } - +/* + * 鍔熻兘锛氶攢姣佸瓧鍏搁」鍝堝笇琛 + * + * 娉ㄦ剰浜嬮」锛 + * - 璇ュ嚱鏁扮敤浜庨攢姣佸瓧鍏搁」鍝堝笇琛紝閲婃斁鐩稿叧鐨勫唴瀛樿祫婧愩 + * - 鍦ㄤ笉鍐嶉渶瑕佸瓧鍏搁」鍝堝笇琛ㄦ椂锛屽簲璋冪敤姝ゅ嚱鏁颁互閬垮厤鍐呭瓨娉勬紡銆 + */ void DictCmprMeta::Destroy() { + // 濡傛灉鍝堝笇琛ㄥ瓨鍦紝鍒欓攢姣佸畠骞跺皢鎸囬拡璁句负NULL if (m_hash) { hash_destroy(m_hash); m_hash = NULL; @@ -189,30 +217,55 @@ void DictCmprMeta::Destroy() } /* write all the dict metadata into given buffer */ -void DictCmprMeta::GetDictItems(char* buf) const +/* + * 鍔熻兘锛氳幏鍙栧瓧鍏搁」鏁版嵁 + * + * 鍙傛暟鍒楄〃锛 + * - buf锛氱敤浜庡瓨鍌ㄥ瓧鍏搁」鏁版嵁鐨勭紦鍐插尯 + * + * 娉ㄦ剰浜嬮」锛 + * - 璇ュ嚱鏁扮敤浜庡皢瀛楀吀椤规暟鎹鍒跺埌鎸囧畾鐨勭紦鍐插尯涓 + * - 缂撳啿鍖哄簲鍏锋湁瓒冲鐨勭┖闂存潵瀹圭撼鎵鏈夊瓧鍏搁」鏁版嵁銆 + */ +void DictCmprMeta::GetDictItems(char *buf) const { int offset = 0; errno_t rc = EOK; + // 閬嶅巻瀛楀吀椤规暟缁勶紝骞跺皢姣忎釜瀛楀吀椤圭殑鏁版嵁澶嶅埗鍒扮紦鍐插尯涓 for (int i = 0; i < dictItemNum; ++i) { rc = memcpy_s(buf + offset, (size_t)(BLCKSZ - offset), dictItems[i].itemData, (size_t)(dictItems[i].itemSize)); securec_check(rc, "", ""); offset += dictItems[i].itemSize; } } - +/* + * 鍔熻兘锛氬皢鏁板瓧瀛楃涓茶繘琛屽帇缂 + * + * 鍙傛暟鍒楄〃锛 + * src锛氳鍘嬬缉鐨勬簮鏁版嵁 + * outSize锛氳緭鍑虹殑鍘嬬缉鏁版嵁澶у皬 + * + * 娉ㄦ剰浜嬮」锛 + * - 璇ュ嚱鏁扮敤浜庡皢鏁板瓧瀛楃涓茶繘琛屽帇缂╋紝浠ュ噺灏忓瓨鍌ㄧ┖闂寸殑闇姹傘 + * - 鍘嬬缉瑙勫垯鏄皢涓や釜鏁板瓧瀛楃鍚堝苟鎴愪竴涓瓧鑺傦紝骞朵娇鐢ㄩ珮鍥涗綅琛ㄧず绗竴涓暟瀛楋紝浣庡洓浣嶈〃绀虹浜屼釜鏁板瓧銆 + * - 濡傛灉杈撳叆鐨勫瓧绗︿覆闀垮害涓哄鏁帮紝灏嗕娇鐢ㄩ珮鍥涗綅鐨勬渶楂樹綅琛ㄧず鏈鍚庝竴涓暟瀛椾负鍘熷鏁版嵁銆 + * - 濡傛灉杈撳叆鐨勫瓧绗︿覆涓嶆槸鏁板瓧瀛楃涓诧紝鍑芥暟灏嗚繑鍥0浣滀负閿欒鏍囧織銆 + */ template -Datum PageCompress::NumstrCompress(Datum src, int& outSize) +Datum PageCompress::NumstrCompress(Datum src, int &outSize) { uint32 evenLen; int destLen = 0; uint32 srcLen = 0; - char* srcPtr = NULL; - unsigned char* outBuf = NULL; - unsigned char* destPtr = NULL; + char *srcPtr = NULL; + unsigned char *outBuf = NULL; + unsigned char *destPtr = NULL; + // 鏂█妫鏌 attlen 鍙兘涓 -1 鎴 -2 Assert(attlen == -1 || attlen == -2); + // 鏍规嵁 attlen 鐨勫艰幏鍙栨簮鏁版嵁鐨勬寚閽堝拰闀垮害 if (attlen == -1) { - char* p = DatumGetPointer(src); + char *p = DatumGetPointer(src); Assert(p != NULL); srcPtr = VARDATA_ANY(p); srcLen = VARSIZE_ANY_EXHDR(p); @@ -233,7 +286,7 @@ Datum PageCompress::NumstrCompress(Datum src, int& outSize) * If the srcLen is odd, we need set the highest 4 bits for 1 for last byte * in order to distinguish the last byte is one original byte */ - unsigned char* srcData = (unsigned char*)srcPtr; + unsigned char *srcData = (unsigned char *)srcPtr; if (srcLen % 2 != 0) { if (!isDigital(srcData[srcLen - 1])) { outSize = 0; @@ -249,7 +302,7 @@ Datum PageCompress::NumstrCompress(Datum src, int& outSize) Assert(destLen >= 0); if (attlen == -1) { - outBuf = (unsigned char*)palloc((Size)(destLen + VARHDRSZ)); + outBuf = (unsigned char *)palloc((Size)(destLen + VARHDRSZ)); if (destLen + VARHDRSZ_SHORT <= VARATT_SHORT_MAX) { outSize = (int)(destLen + VARHDRSZ_SHORT); SET_VARSIZE_SHORT(outBuf, outSize); @@ -262,7 +315,7 @@ Datum PageCompress::NumstrCompress(Datum src, int& outSize) } else { /* Last byte has been set '\0' */ outSize = destLen + 1; - destPtr = outBuf = (unsigned char*)palloc0((Size)outSize); + destPtr = outBuf = (unsigned char *)palloc0((Size)outSize); } /* Two bytes combine one byte */ @@ -291,16 +344,33 @@ Datum PageCompress::NumstrCompress(Datum src, int& outSize) return PointerGetDatum(outBuf); } - -Datum PageCompress::NumstrUncompress( - Datum src, int attlen, int& cmprValSize, char* uncmprValBuf, int* dataLenWithPadding, char attalign) +/* + * 鍔熻兘锛氳В鍘嬬缉鏁板瓧瀛楃涓 + * + * 鍙傛暟鍒楄〃锛 + * src锛氳瑙e帇缂╃殑婧愭暟鎹 + * attlen锛氭簮鏁版嵁绫诲瀷鐨勯暱搴︼紝鍙栧间负 -1 鎴 -2 + * cmprValSize锛氳緭鍑虹殑瑙e帇缂╂暟鎹ぇ灏 + * uncmprValBuf锛氳В鍘嬬缉鍚庣殑鏁版嵁缂撳啿鍖 + * dataLenWithPadding锛氬寘鎷~鍏呭瓧鑺傜殑鏁版嵁闀垮害 + * attalign锛氭暟鎹榻愭柟寮 + * + * 娉ㄦ剰浜嬮」锛 + * - 璇ュ嚱鏁扮敤浜庤В鍘嬬缉鍘嬬缉杩囩殑鏁板瓧瀛楃涓层 + * - 鍘嬬缉瑙勫垯鏄皢涓や釜鏁板瓧瀛楃鍚堝苟鎴愪竴涓瓧鑺傦紝骞朵娇鐢ㄩ珮鍥涗綅琛ㄧず绗竴涓暟瀛楋紝浣庡洓浣嶈〃绀虹浜屼釜鏁板瓧銆 + * - 濡傛灉杈撳叆鐨勫瓧绗︿覆闀垮害涓哄鏁帮紝鍘嬬缉鏁版嵁鐨勬渶鍚庝竴涓瓧鑺傜殑楂樺洓浣嶇敤鏉ヨ〃绀烘渶鍚庝竴涓暟瀛椾负鍘熷鏁版嵁銆 + * - attlen 鍙傛暟鎸囧畾浜嗚緭鍑烘暟鎹殑绫诲瀷闀垮害锛-1 琛ㄧず鍙橀暱绫诲瀷锛-2 琛ㄧず瀹氶暱绫诲瀷銆 + * - 濡傛灉杈撳叆鐨勫瓧绗︿覆涓嶆槸鏁板瓧瀛楃涓诧紝鍑芥暟灏嗚繑鍥0浣滀负閿欒鏍囧織銆 + */ +Datum PageCompress::NumstrUncompress(Datum src, int attlen, int &cmprValSize, char *uncmprValBuf, + int *dataLenWithPadding, char attalign) { Assert(attlen == -1 || attlen == -2); uint32 srcLen = 0; - char* srcPtr = NULL; + char *srcPtr = NULL; if (attlen == -1) { - char* p = DatumGetPointer(src); + char *p = DatumGetPointer(src); Assert(p != NULL); srcPtr = VARDATA_ANY(p); srcLen = VARSIZE_ANY_EXHDR(p); @@ -312,9 +382,9 @@ Datum PageCompress::NumstrUncompress( } Assert(srcPtr != NULL && srcLen > 0 && cmprValSize > 0); - unsigned char* outBuf = NULL; - unsigned char* destPtr = NULL; - unsigned char* srcData = (unsigned char*)srcPtr; + unsigned char *outBuf = NULL; + unsigned char *destPtr = NULL; + unsigned char *srcData = (unsigned char *)srcPtr; int destLen; int padding_size = 0; int datum_size = 0; @@ -334,14 +404,14 @@ Datum PageCompress::NumstrUncompress( * NB: nothing to do if the datum header is 1B; */ if (uncmprValBuf) { - outBuf = (unsigned char*)uncmprValBuf; + outBuf = (unsigned char *)uncmprValBuf; Assert(dataLenWithPadding != NULL); *outBuf = 0; - outBuf = (unsigned char*)att_align_nominal(outBuf, attalign); - padding_size = int(outBuf - (unsigned char*)uncmprValBuf); + outBuf = (unsigned char *)att_align_nominal(outBuf, attalign); + padding_size = int(outBuf - (unsigned char *)uncmprValBuf); } else { - outBuf = (unsigned char*)palloc((Size)(destLen + VARHDRSZ)); + outBuf = (unsigned char *)palloc((Size)(destLen + VARHDRSZ)); } datum_size = destLen + VARHDRSZ; @@ -351,9 +421,9 @@ Datum PageCompress::NumstrUncompress( /* Last byte has been set '\0' */ datum_size = destLen + 1; if (uncmprValBuf) - destPtr = outBuf = (unsigned char*)uncmprValBuf; + destPtr = outBuf = (unsigned char *)uncmprValBuf; else - destPtr = outBuf = (unsigned char*)palloc((Size)datum_size); + destPtr = outBuf = (unsigned char *)palloc((Size)datum_size); errno_t rc = memset_s(destPtr, (size_t)datum_size, 0, (size_t)datum_size); securec_check(rc, "", ""); @@ -406,22 +476,22 @@ PageCompress::PageCompress(Relation rel, MemoryContext memCtx) MemoryContext oldMemCnxt = MemoryContextSwitchTo(memCtx); m_parentMemCxt = memCtx; - m_cmprHeaderData = (char*)palloc(BLCKSZ); - m_pageMemCnxt = AllocSetContextCreate( - memCtx, "PageCompression", ALLOCSET_DEFAULT_MINSIZE, ALLOCSET_DEFAULT_INITSIZE, ALLOCSET_DEFAULT_MAXSIZE); + m_cmprHeaderData = (char *)palloc(BLCKSZ); + m_pageMemCnxt = AllocSetContextCreate(memCtx, "PageCompression", ALLOCSET_DEFAULT_MINSIZE, + ALLOCSET_DEFAULT_INITSIZE, ALLOCSET_DEFAULT_MAXSIZE); int nattrs = RelationGetNumberOfAttributes(m_rel); - m_cmprMode = (char*)palloc0((Size)(nattrs * sizeof(char))); - m_cmprMeta = (void**)palloc0((Size)(nattrs * sizeof(void*))); - m_numTypeOpt = (const NumberTypeOpt**)palloc((Size)(nattrs * sizeof(NumberTypeOpt*))); - m_dictMiss = (uint32*)palloc0((Size)(nattrs * sizeof(uint32))); - m_dictItemId = (unsigned char*)palloc((Size)(nattrs * sizeof(unsigned char))); - m_deformVals = (Datum*)palloc((Size)(nattrs * sizeof(Datum))); - m_deformNulls = (bool*)palloc((Size)(nattrs * sizeof(bool))); + m_cmprMode = (char *)palloc0((Size)(nattrs * sizeof(char))); + m_cmprMeta = (void **)palloc0((Size)(nattrs * sizeof(void *))); + m_numTypeOpt = (const NumberTypeOpt **)palloc((Size)(nattrs * sizeof(NumberTypeOpt *))); + m_dictMiss = (uint32 *)palloc0((Size)(nattrs * sizeof(uint32))); + m_dictItemId = (unsigned char *)palloc((Size)(nattrs * sizeof(unsigned char))); + m_deformVals = (Datum *)palloc((Size)(nattrs * sizeof(Datum))); + m_deformNulls = (bool *)palloc((Size)(nattrs * sizeof(bool))); (void)MemoryContextSwitchTo(oldMemCnxt); - Form_pg_attribute* attrs = m_rel->rd_att->attrs; + Form_pg_attribute *attrs = m_rel->rd_att->attrs; for (int col = 0; col < nattrs; ++col) { m_numTypeOpt[col] = binarySearch(attrs[col]->atttypid); } @@ -453,16 +523,16 @@ PageCompress::~PageCompress() m_pageMemCnxt = NULL; } -ColArray* PageCompress::DeformTups(HeapTuple* tups, int nTups) +ColArray *PageCompress::DeformTups(HeapTuple *tups, int nTups) { int attrNum = RelationGetNumberOfAttributes(m_rel); TupleDesc desc = RelationGetDescr(m_rel); - ColArray* colArray = (ColArray*)palloc((Size)(sizeof(ColArray) * attrNum)); + ColArray *colArray = (ColArray *)palloc((Size)(sizeof(ColArray) * attrNum)); for (int i = 0; i < attrNum; ++i) { - colArray[i].nulls = (bool*)palloc0((Size)(sizeof(bool) * nTups)); - colArray[i].val = (Datum*)palloc0((Size)(sizeof(Datum) * nTups)); + colArray[i].nulls = (bool *)palloc0((Size)(sizeof(bool) * nTups)); + colArray[i].val = (Datum *)palloc0((Size)(sizeof(Datum) * nTups)); colArray[i].num = nTups; } @@ -491,11 +561,11 @@ ColArray* PageCompress::DeformTups(HeapTuple* tups, int nTups) * Delta Compression/Decompression Methods * --------------------------------------------------------------- */ -DeltaCmprMeta* PageCompress::DeltaGetCmprMeta(ColArray* colArray, const NumberTypeOpt* opt) const +DeltaCmprMeta *PageCompress::DeltaGetCmprMeta(ColArray *colArray, const NumberTypeOpt *opt) const { Datum minVal, maxVal; - Datum* values = colArray->val; - bool* isnulls = colArray->nulls; + Datum *values = colArray->val; + bool *isnulls = colArray->nulls; /* init min/max value. */ int i = 0; @@ -523,7 +593,7 @@ DeltaCmprMeta* PageCompress::DeltaGetCmprMeta(ColArray* colArray, const NumberTy return NULL; } - DeltaCmprMeta* deltaInfo = (DeltaCmprMeta*)palloc(sizeof(DeltaCmprMeta)); + DeltaCmprMeta *deltaInfo = (DeltaCmprMeta *)palloc(sizeof(DeltaCmprMeta)); deltaInfo->MinVal = minVal; deltaInfo->MaxVal = maxVal; deltaInfo->bytes = bytes; @@ -538,8 +608,8 @@ DeltaCmprMeta* PageCompress::DeltaGetCmprMeta(ColArray* colArray, const NumberTy * metaInfo, opt and val are the input parameters; and deltaBuf is the output * returning false means that delta compress fails. */ -bool PageCompress::DeltaCompress( - DeltaCmprMeta* metaInfo, const NumberTypeOpt* opt, Datum val, unsigned char* deltaBuf) const +bool PageCompress::DeltaCompress(DeltaCmprMeta *metaInfo, const NumberTypeOpt *opt, Datum val, + unsigned char *deltaBuf) const { int64 diff = opt->minus(val, metaInfo->MinVal); @@ -572,10 +642,10 @@ bool PageCompress::DeltaCompress( /* [IN]: metaInfo && opt && deltaBuf[] * delta decompress. */ -Datum PageCompress::DeltaUncompress(DeltaCmprMeta* metaInfo, const NumberTypeOpt* opt, unsigned char* deltaBuf) +Datum PageCompress::DeltaUncompress(DeltaCmprMeta *metaInfo, const NumberTypeOpt *opt, unsigned char *deltaBuf) { uint64 diff = 0; - unsigned char* delta = (unsigned char*)deltaBuf; + unsigned char *delta = (unsigned char *)deltaBuf; diff |= delta[0]; for (int i = 1; i < metaInfo->bytes; i++) { @@ -586,11 +656,11 @@ Datum PageCompress::DeltaUncompress(DeltaCmprMeta* metaInfo, const NumberTypeOpt return opt->plus(metaInfo->MinVal, (int64)diff); } -Datum PageCompress::DictUncompress(DictCmprMeta* metaInfo, const char* compressBuf, int attlen) +Datum PageCompress::DictUncompress(DictCmprMeta *metaInfo, const char *compressBuf, int attlen) { Datum res = 0; - unsigned char id = *((unsigned char*)compressBuf); - DictItemData* val = metaInfo->dictItems + id; + unsigned char id = *((unsigned char *)compressBuf); + DictItemData *val = metaInfo->dictItems + id; /* refer to fetch_att() */ if (attlen > 0) { @@ -600,20 +670,20 @@ Datum PageCompress::DictUncompress(DictCmprMeta* metaInfo, const char* compressB break; } case sizeof(int16): { - res = Int16GetDatum(*(int16*)val->itemData); + res = Int16GetDatum(*(int16 *)val->itemData); break; } case sizeof(int32): { - res = Int32GetDatum(*(int32*)val->itemData); + res = Int32GetDatum(*(int32 *)val->itemData); break; } case sizeof(Datum): { - res = *(Datum*)val->itemData; + res = *(Datum *)val->itemData; break; } default: - ereport(ERROR, - (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("unsupported byval length: %d", (int)(attlen)))); + ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("unsupported byval length: %d", (int)(attlen)))); } } else res = PointerGetDatum(val->itemData); @@ -628,15 +698,15 @@ Datum PageCompress::DictUncompress(DictCmprMeta* metaInfo, const char* compressB template int PageCompress::PrefixLen(Datum str1, Datum str2) { - char* strData1 = NULL; - char* strData2 = NULL; + char *strData1 = NULL; + char *strData2 = NULL; int maxPrefixLen = 0; int prefixLen = 0; /* Note that numeric column should not do this. */ if (attlen == -1) { - char* ptr1 = DatumGetPointer(str1); - char* ptr2 = DatumGetPointer(str2); + char *ptr1 = DatumGetPointer(str1); + char *ptr2 = DatumGetPointer(str2); strData1 = VARDATA_ANY(ptr1); strData2 = VARDATA_ANY(ptr2); maxPrefixLen = Min(VARSIZE_ANY_EXHDR(ptr1), VARSIZE_ANY_EXHDR(ptr2)); @@ -659,12 +729,12 @@ int PageCompress::PrefixLen(Datum str1, Datum str2) * This function outputs prefixLen and prefix string */ template -char* PageCompress::PrefixGetCmprMeta(ColArray* colArray, int& prefixLen) +char *PageCompress::PrefixGetCmprMeta(ColArray *colArray, int &prefixLen) { int prev = 0; int next = 0; int arrayLen = colArray->num; - char* prefixStr = NULL; + char *prefixStr = NULL; /* Initialize the prefixLen by comparing the first and second tuple */ while (prev < arrayLen && colArray->nulls[prev]) @@ -709,65 +779,81 @@ char* PageCompress::PrefixGetCmprMeta(ColArray* colArray, int& prefixLen) } return prefixStr; } - +/* + * 鍔熻兘锛氬杈撳叆鐨勬暟鎹繘琛屽墠缂鍘嬬缉 + * + * 鍙傛暟鍒楄〃锛 + * attlen锛氳緭鍏ユ暟鎹殑绫诲瀷闀垮害锛屽彇鍊间负 -1 鎴 -2 + * prefix锛氬墠缂鍘嬬缉鍏冩暟鎹粨鏋 + * val锛氳緭鍏ョ殑鏁版嵁 + * cmprsVal锛氬帇缂╁悗鐨勬暟鎹 + * cmprsValSize锛氬帇缂╁悗鐨勬暟鎹ぇ灏 + * + * 娉ㄦ剰浜嬮」锛 + * - 璇ュ嚱鏁扮敤浜庡杈撳叆鏁版嵁杩涜鍓嶇紑鍘嬬缉锛屾牴鎹緭鍏ョ殑 attlen 鍙傛暟纭畾杈撳叆鏁版嵁鐨勭被鍨嬮暱搴︺ + * - 濡傛灉鍓嶇紑涓庤緭鍏ユ暟鎹殑鍓嶇紑鍖归厤锛屽嚱鏁板皢杩涜鍘嬬缉锛屽惁鍒欒繑鍥 false銆 + * - 鍘嬬缉鍚庣殑鏁版嵁瀛樺偍鍦 cmprsVal 涓紝鍏跺ぇ灏忓瓨鍌ㄥ湪 cmprsValSize 涓 + */ template -bool PageCompress::PrefixCompress(PrefixCmprMeta* prefix, Datum val, Datum& cmprsVal, int& cmprsValSize) +bool PageCompress::PrefixCompress(PrefixCmprMeta *prefix, Datum val, Datum &cmprsVal, int &cmprsValSize) { - char* attStart = NULL; - int attSize; + char *attStart = NULL; // 杈撳叆鏁版嵁鐨勮捣濮嬪湴鍧 + int attSize; // 杈撳叆鏁版嵁鐨勫ぇ灏 if (-1 == attlen) { - char* ptr = DatumGetPointer(val); + char *ptr = DatumGetPointer(val); // 鑾峰彇杈撳叆鏁版嵁鐨勬寚閽 Assert(ptr != NULL); - attStart = VARDATA_ANY(ptr); - attSize = VARSIZE_ANY_EXHDR(ptr); + attStart = VARDATA_ANY(ptr); // 濡傛灉杈撳叆鏁版嵁鏄彉闀跨被鍨嬶紝鑾峰彇鏁版嵁鐨勬湁鏁堥儴鍒 + attSize = VARSIZE_ANY_EXHDR(ptr); // 鑾峰彇鏈夋晥鏁版嵁鐨勫ぇ灏忥紙涓嶅寘鎷ご閮ㄤ俊鎭級 } else { - attStart = DatumGetCString(val); - attSize = (int)(strlen(attStart) + 1); + attStart = DatumGetCString(val); // 濡傛灉杈撳叆鏁版嵁鏄畾闀跨被鍨嬶紝鐩存帴鑾峰彇瀛楃涓叉寚閽 + attSize = (int)(strlen(attStart) + 1); // 璁$畻瀛楃涓茬殑澶у皬锛堝寘鎷粓姝㈢锛 } - Assert(attStart != NULL && attSize >= 0); - Assert(prefix != NULL && prefix->len > 0 && prefix->prefixStr != NULL); + Assert(attStart != NULL && attSize >= 0); // 鏂█杈撳叆鏁版嵁鍚堟硶鎬 + Assert(prefix != NULL && prefix->len > 0 && prefix->prefixStr != NULL); // 鏂█鍓嶇紑鍏冩暟鎹悎娉曟 if (prefix->len > attSize || memcmp(prefix->prefixStr, attStart, (size_t)prefix->len)) { + // 濡傛灉鍓嶇紑涓庤緭鍏ユ暟鎹殑鍓嶇紑涓嶅尮閰嶏紝杩斿洖 false return false; } if (-1 == attlen) { - int suffixLen = attSize - prefix->len; - Assert(suffixLen >= 0); - char* suffix = (char*)palloc((Size)(suffixLen + VARHDRSZ)); + int suffixLen = attSize - prefix->len; // 璁$畻鍓╀綑鏁版嵁鐨勫ぇ灏 + Assert(suffixLen >= 0); // 鏂█鍓╀綑鏁版嵁澶у皬闈炶礋 + char *suffix = (char *)palloc((Size)(suffixLen + VARHDRSZ)); // 鍒嗛厤鍐呭瓨鐢ㄤ簬瀛樺偍鍘嬬缉鍚庣殑鏁版嵁 errno_t errorno = EOK; /* use one byte var-header as possible as much */ if (suffixLen + VARHDRSZ_SHORT <= VARATT_SHORT_MAX) { - SET_VARSIZE_SHORT(suffix, suffixLen + VARHDRSZ_SHORT); + SET_VARSIZE_SHORT(suffix, suffixLen + VARHDRSZ_SHORT); // 璁剧疆鍙橀暱澶撮儴澶у皬 if (suffixLen > 0) { - errorno = memcpy_s((suffix + VARHDRSZ_SHORT), (size_t)suffixLen, (attStart + prefix->len), (size_t)suffixLen); - securec_check(errorno, "\0", "\0"); + errorno = + memcpy_s((suffix + VARHDRSZ_SHORT), (size_t)suffixLen, (attStart + prefix->len), (size_t)suffixLen); + securec_check(errorno, "\0", "\0"); // 澶嶅埗鏁版嵁鍒板帇缂╁悗鐨勫唴瀛 } - cmprsValSize = (int)(suffixLen + VARHDRSZ_SHORT); + cmprsValSize = (int)(suffixLen + VARHDRSZ_SHORT); // 璁$畻鍘嬬缉鍚庣殑鏁版嵁澶у皬 } else { - SET_VARSIZE(suffix, suffixLen + VARHDRSZ); + SET_VARSIZE(suffix, suffixLen + VARHDRSZ); // 璁剧疆鍙橀暱澶撮儴澶у皬 errorno = memcpy_s((suffix + VARHDRSZ), (size_t)suffixLen, (attStart + prefix->len), (size_t)suffixLen); - securec_check(errorno, "\0", "\0"); - cmprsValSize = suffixLen + VARHDRSZ; + securec_check(errorno, "\0", "\0"); // 澶嶅埗鏁版嵁鍒板帇缂╁悗鐨勫唴瀛 + cmprsValSize = suffixLen + VARHDRSZ; // 璁$畻鍘嬬缉鍚庣殑鏁版嵁澶у皬 } - cmprsVal = PointerGetDatum(suffix); + cmprsVal = PointerGetDatum(suffix); // 灏嗗帇缂╁悗鐨勬暟鎹寚閽堝瓨鍌ㄥ湪 cmprsVal 涓 } else { - cmprsVal = CStringGetDatum(attStart + prefix->len); - cmprsValSize = (int)(strlen(attStart + prefix->len) + 1); + cmprsVal = CStringGetDatum(attStart + prefix->len); // 濡傛灉杈撳叆鏁版嵁鏄畾闀跨被鍨嬶紝鐩存帴鑾峰彇鍓╀綑閮ㄥ垎鐨勬寚閽 + cmprsValSize = (int)(strlen(attStart + prefix->len) + 1); // 璁$畻鍓╀綑閮ㄥ垎鐨勫ぇ灏忥紙鍖呮嫭缁堟绗︼級 } - Assert(cmprsValSize > 0); + Assert(cmprsValSize > 0); // 鏂█鍘嬬缉鍚庣殑鏁版嵁澶у皬闈炶礋 - return true; + return true; // 杩斿洖 true 琛ㄧず鎴愬姛杩涜鍓嶇紑鍘嬬缉 } -Datum PageCompress::PrefixUncompress(int attlen, PrefixCmprMeta* prefix, char* start, int* attrCmprsValSize, - char* uncmprValBuf, int* dataLenWithPadding, char attalign) +Datum PageCompress::PrefixUncompress(int attlen, PrefixCmprMeta *prefix, char *start, int *attrCmprsValSize, + char *uncmprValBuf, int *dataLenWithPadding, char attalign) { int attsize; - char* attdata = NULL; - char* attr = NULL; + char *attdata = NULL; + char *attr = NULL; int datum_size; int padding_size = 0; errno_t rc = EOK; @@ -777,7 +863,7 @@ Datum PageCompress::PrefixUncompress(int attlen, PrefixCmprMeta* prefix, char* s Assert(start != NULL && attrCmprsValSize != NULL); if (-1 == attlen) { - char* ptr = DatumGetPointer(start); + char *ptr = DatumGetPointer(start); attdata = VARDATA_ANY(ptr); attsize = VARSIZE_ANY_EXHDR(ptr); *attrCmprsValSize = VARSIZE_ANY(ptr); @@ -796,10 +882,10 @@ Datum PageCompress::PrefixUncompress(int attlen, PrefixCmprMeta* prefix, char* s Assert(dataLenWithPadding != NULL); *attr = 0; - attr = (char*)att_align_nominal(attr, attalign); + attr = (char *)att_align_nominal(attr, attalign); padding_size = (int)(attr - uncmprValBuf); } else { - attr = (char*)palloc((Size)(attRawLen + VARHDRSZ)); + attr = (char *)palloc((Size)(attRawLen + VARHDRSZ)); } datum_size = attRawLen + VARHDRSZ; @@ -823,7 +909,7 @@ Datum PageCompress::PrefixUncompress(int attlen, PrefixCmprMeta* prefix, char* s if (uncmprValBuf) attr = uncmprValBuf; else - attr = (char*)palloc((Size)datum_size); + attr = (char *)palloc((Size)datum_size); rc = memcpy_s(attr, (size_t)datum_size, prefix->prefixStr, (size_t)prefix->len); securec_check(rc, "", ""); if (attsize > 0) { @@ -845,7 +931,7 @@ Datum PageCompress::PrefixUncompress(int attlen, PrefixCmprMeta* prefix, char* s /* choose compression method between delta and dict. * we prefer delta method to dict method. */ -void PageCompress::ChooseMethodForFixedLenType(ColArray* colArray, int col) +void PageCompress::ChooseMethodForFixedLenType(ColArray *colArray, int col) { int hintMode = m_rel->rd_att->attrs[col]->attcmprmode; @@ -865,11 +951,11 @@ void PageCompress::ChooseMethodForFixedLenType(ColArray* colArray, int col) } template -void PageCompress::FillHashKey(DictItemData& key, const int& attlen, const Datum& attval) +void PageCompress::FillHashKey(DictItemData &key, const int &attlen, const Datum &attval) { if (attFlag > 0) { key.itemSize = (int16)attlen; - key.itemData = (char*)palloc((Size)attlen); + key.itemData = (char *)palloc((Size)attlen); store_att_byval(key.itemData, attval, attlen); } else if (-1 == attFlag) { key.itemData = DatumGetPointer(attval); @@ -882,7 +968,7 @@ void PageCompress::FillHashKey(DictItemData& key, const int& attlen, const Datum /* Choose dictinary items and put it into DictCmprMeta */ template -DictCmprMeta* PageCompress::DictGetCmprMeta(ColArray* colArray, int col, int attlen) +DictCmprMeta *PageCompress::DictGetCmprMeta(ColArray *colArray, int col, int attlen) { int i; @@ -893,10 +979,10 @@ DictCmprMeta* PageCompress::DictGetCmprMeta(ColArray* colArray, int col, int att if (m_dictMiss[col] > DICT_MISS_THRESHOLD) return NULL; - DictCmprMeta* dicInfo = (DictCmprMeta*)palloc0(sizeof(DictCmprMeta)); + DictCmprMeta *dicInfo = (DictCmprMeta *)palloc0(sizeof(DictCmprMeta)); int pos = 0; bool found = false; - HTAB* dictHash = + HTAB *dictHash = hashCreate("DictHash", m_pageMemCnxt, colArray->num + 16, sizeof(DictItemData), sizeof(DictItemEntry)); for (i = 0; i < colArray->num; ++i) { @@ -913,7 +999,7 @@ DictCmprMeta* PageCompress::DictGetCmprMeta(ColArray* colArray, int col, int att FillHashKey<-2>(key, attlen, colArray->val[i]); } - DictItemEntry* dicItemEntry = (DictItemEntry*)hash_search(dictHash, (const void*)&key, HASH_ENTER, &found); + DictItemEntry *dicItemEntry = (DictItemEntry *)hash_search(dictHash, (const void *)&key, HASH_ENTER, &found); Assert(dicItemEntry != NULL); if (!found) { dicItemEntry->hitCount = 1; @@ -951,23 +1037,23 @@ DictCmprMeta* PageCompress::DictGetCmprMeta(ColArray* colArray, int col, int att } template -bool PageCompress::NumstrEvaluate(ColArray* colArray) +bool PageCompress::NumstrEvaluate(ColArray *colArray) { int n = colArray->num; int numStr = 0; bool flag = true; - Datum* val = colArray->val; - bool* nulls = colArray->nulls; + Datum *val = colArray->val; + bool *nulls = colArray->nulls; for (int i = 0; i < n; ++i) { if (nulls[i]) continue; int len = 0; - char* dataPtr = NULL; + char *dataPtr = NULL; if (attlen == -1) { - char* p = DatumGetPointer(val[i]); + char *p = DatumGetPointer(val[i]); dataPtr = VARDATA_ANY(p); len = VARSIZE_ANY_EXHDR(p); } else if (attlen == -2) { @@ -1008,7 +1094,7 @@ bool PageCompress::NumstrEvaluate(ColArray* colArray) /* choose compression method between prefix and dict. * we prefer prefix method to dict method. */ -void PageCompress::ChooseMethodForVaryLenType(ColArray* colArray, int col) +void PageCompress::ChooseMethodForVaryLenType(ColArray *colArray, int col) { int hintMode = m_rel->rd_att->attrs[col]->attcmprmode; @@ -1039,15 +1125,15 @@ void PageCompress::ChooseMethodForVaryLenType(ColArray* colArray, int col) * we take it as a hint, and first try to get compression metadata using it. * but maybe it fails, and we have to try the other methods then. */ -bool PageCompress::SetCmprMethod(ColArray* colArray, int col, int mode) +bool PageCompress::SetCmprMethod(ColArray *colArray, int col, int mode) { - Form_pg_attribute* attrs = m_rel->rd_att->attrs; + Form_pg_attribute *attrs = m_rel->rd_att->attrs; int attlen = attrs[col]->attlen; switch (mode) { case CMPR_DELTA: { Assert(m_numTypeOpt[col] != NULL && attlen > 1); - DeltaCmprMeta* deltaInfo = DeltaGetCmprMeta(colArray, m_numTypeOpt[col]); + DeltaCmprMeta *deltaInfo = DeltaGetCmprMeta(colArray, m_numTypeOpt[col]); if (deltaInfo == NULL) return false; @@ -1068,7 +1154,7 @@ bool PageCompress::SetCmprMethod(ColArray* colArray, int col, int mode) } case CMPR_DICT: { - DictCmprMeta* dicInfo = NULL; + DictCmprMeta *dicInfo = NULL; if (-2 == attlen) dicInfo = DictGetCmprMeta<-2>(colArray, col, attlen); else if (-1 == attlen) @@ -1087,7 +1173,7 @@ bool PageCompress::SetCmprMethod(ColArray* colArray, int col, int mode) case CMPR_PREFIX: { int prefixLen = 0; - char* prefixStr = NULL; + char *prefixStr = NULL; Assert(-1 == attlen || -2 == attlen); if (-2 == attlen) @@ -1097,9 +1183,9 @@ bool PageCompress::SetCmprMethod(ColArray* colArray, int col, int mode) /* If this array has common prefix, we fill prefix compression meta information */ if (prefixLen > 0 && prefixLen < MAX_PREFIX_LEN) { - PrefixCmprMeta* prefixInfo = (PrefixCmprMeta*)palloc(sizeof(PrefixCmprMeta)); + PrefixCmprMeta *prefixInfo = (PrefixCmprMeta *)palloc(sizeof(PrefixCmprMeta)); prefixInfo->len = prefixLen; - prefixInfo->prefixStr = (char*)palloc((Size)prefixLen); + prefixInfo->prefixStr = (char *)palloc((Size)prefixLen); errno_t rc = memcpy_s(prefixInfo->prefixStr, (size_t)prefixLen, prefixStr, (size_t)prefixLen); securec_check(rc, "", ""); @@ -1132,10 +1218,10 @@ bool PageCompress::SetCmprMethod(ColArray* colArray, int col, int mode) } } -void PageCompress::ChooseCmprMethod(ColArray* colArrays) +void PageCompress::ChooseCmprMethod(ColArray *colArrays) { int attrNum = RelationGetNumberOfAttributes(m_rel); - Form_pg_attribute* attrs = m_rel->rd_att->attrs; + Form_pg_attribute *attrs = m_rel->rd_att->attrs; for (int col = 0; col < attrNum; ++col) { /* continue if this attribute shouldn't be compressed specified by user; */ @@ -1162,7 +1248,7 @@ void PageCompress::ChooseCmprMethod(ColArray* colArrays) void PageCompress::SetCmprHeaderData(void) { - Form_pg_attribute* atts = RelationGetDescr(m_rel)->attrs; + Form_pg_attribute *atts = RelationGetDescr(m_rel)->attrs; int nattrs = RelationGetNumberOfAttributes(m_rel); int offset = 0; int rawCols = 0; @@ -1173,7 +1259,7 @@ void PageCompress::SetCmprHeaderData(void) switch (m_cmprMode[col]) { case CMPR_DELTA: { - DeltaCmprMeta* deltaInfo = (DeltaCmprMeta*)m_cmprMeta[col]; + DeltaCmprMeta *deltaInfo = (DeltaCmprMeta *)m_cmprMeta[col]; int attrLen = atts[col]->attlen; Assert(deltaInfo->bytes < g_number_max_value_in_bytes); Assert(attrLen > 0); @@ -1187,7 +1273,7 @@ void PageCompress::SetCmprHeaderData(void) } case CMPR_DICT: { - DictCmprMeta* dicInfo = (DictCmprMeta*)m_cmprMeta[col]; + DictCmprMeta *dicInfo = (DictCmprMeta *)m_cmprMeta[col]; Assert(dicInfo->dictItemNum < 0xFF); /* how many dictionary items */ m_cmprHeaderData[offset++] = (char)dicInfo->dictItemNum; @@ -1199,12 +1285,13 @@ void PageCompress::SetCmprHeaderData(void) case CMPR_PREFIX: { Assert(-2 == atts[col]->attlen || -1 == atts[col]->attlen); - PrefixCmprMeta* prefixInfo = (PrefixCmprMeta*)m_cmprMeta[col]; + PrefixCmprMeta *prefixInfo = (PrefixCmprMeta *)m_cmprMeta[col]; Assert(prefixInfo->len > 0 && prefixInfo->len < MAX_PREFIX_LEN); /* how many bytes is used for prefix string */ m_cmprHeaderData[offset++] = (char)prefixInfo->len; /* data of prefix string */ - rc = memcpy_s(m_cmprHeaderData + offset, (size_t)(BLCKSZ - offset), prefixInfo->prefixStr, (size_t)(prefixInfo->len)); + rc = memcpy_s(m_cmprHeaderData + offset, (size_t)(BLCKSZ - offset), prefixInfo->prefixStr, + (size_t)(prefixInfo->len)); securec_check(rc, "", ""); offset += prefixInfo->len; break; @@ -1235,15 +1322,15 @@ void PageCompress::SetCmprHeaderData(void) * metaSize [OUT]: size of compression metadata within page for each attribute; * mode [OUT]: compression method; */ -void* PageCompress::FetchAttrCmprMeta(char* metaStart, const int attrRawLen, int* metaSize, char* mode) +void *PageCompress::FetchAttrCmprMeta(char *metaStart, const int attrRawLen, int *metaSize, char *mode) { int offset = 1; *mode = metaStart[0]; - void* retInfo = NULL; + void *retInfo = NULL; switch (*mode) { case CMPR_DELTA: { - DeltaCmprMeta* deltaInfo = &t_thrd.storage_cxt.cmprMetaInfo->deltaInfo; + DeltaCmprMeta *deltaInfo = &t_thrd.storage_cxt.cmprMetaInfo->deltaInfo; /* how many bytes is used for delta value */ deltaInfo->bytes = metaStart[offset]; @@ -1254,11 +1341,11 @@ void* PageCompress::FetchAttrCmprMeta(char* metaStart, const int attrRawLen, int deltaInfo->MinVal = fetch_att(metaStart + offset, true, attrRawLen); offset += attrRawLen; *metaSize = offset; - retInfo = (void*)deltaInfo; + retInfo = (void *)deltaInfo; break; } case CMPR_DICT: { - DictCmprMeta* dicInfo = &t_thrd.storage_cxt.cmprMetaInfo->dicInfo; + DictCmprMeta *dicInfo = &t_thrd.storage_cxt.cmprMetaInfo->dicInfo; dicInfo->dictItemNum = metaStart[offset++]; if (attrRawLen > 0) { @@ -1281,32 +1368,32 @@ void* PageCompress::FetchAttrCmprMeta(char* metaStart, const int attrRawLen, int } } *metaSize = offset; - retInfo = (void*)dicInfo; + retInfo = (void *)dicInfo; break; } case CMPR_PREFIX: { Assert(-2 == attrRawLen || -1 == attrRawLen); - PrefixCmprMeta* prefixInfo = &t_thrd.storage_cxt.cmprMetaInfo->prefixInfo; + PrefixCmprMeta *prefixInfo = &t_thrd.storage_cxt.cmprMetaInfo->prefixInfo; prefixInfo->len = (metaStart[offset] & 0x00FF); ++offset; prefixInfo->prefixStr = metaStart + offset; offset += prefixInfo->len; *metaSize = offset; - retInfo = (void*)prefixInfo; + retInfo = (void *)prefixInfo; break; } case CMPR_NUMSTR: case CMPR_NONE: { *metaSize = offset; - retInfo = (void*)NULL; + retInfo = (void *)NULL; break; } default: { Assert(false); - retInfo = (void*)NULL; + retInfo = (void *)NULL; break; } } @@ -1317,16 +1404,16 @@ void* PageCompress::FetchAttrCmprMeta(char* metaStart, const int attrRawLen, int /* according to compression mode and meta information, return the value size * of this attribute in the tuple. */ -int PageCompress::GetAttrCmprValSize(char mode, int attlen, void* metaInfo, const char* attrStart) +int PageCompress::GetAttrCmprValSize(char mode, int attlen, void *metaInfo, const char *attrStart) { switch (mode) { case CMPR_DELTA: { - DeltaCmprMeta* deltaInfo = (DeltaCmprMeta*)metaInfo; + DeltaCmprMeta *deltaInfo = (DeltaCmprMeta *)metaInfo; return deltaInfo->bytes; } case CMPR_DICT: { - DictCmprMeta* dicInfo = (DictCmprMeta*)metaInfo; + DictCmprMeta *dicInfo = (DictCmprMeta *)metaInfo; return (dicInfo->dictItemNum == 1) ? 0 : DICT_ITEMID_SIZE; } @@ -1356,8 +1443,8 @@ bool PageCompress::NeedExternalBuf(char mode) return ((mode == CMPR_PREFIX) || (mode == CMPR_NUMSTR)); } -int PageCompress::UncompressOneAttr( - char mode, char attalign, int attlen, void* metaInfo, char* attrStart, int* attrCmprsValSize, char* uncmprValBuf) +int PageCompress::UncompressOneAttr(char mode, char attalign, int attlen, void *metaInfo, char *attrStart, + int *attrCmprsValSize, char *uncmprValBuf) { int dataLenWithPadding = 0; @@ -1366,15 +1453,15 @@ int PageCompress::UncompressOneAttr( switch (mode) { case CMPR_PREFIX: { - PrefixCmprMeta* prefixInfo = (PrefixCmprMeta*)metaInfo; - (void)PrefixUncompress( - attlen, prefixInfo, attrStart, attrCmprsValSize, uncmprValBuf, &dataLenWithPadding, attalign); + PrefixCmprMeta *prefixInfo = (PrefixCmprMeta *)metaInfo; + (void)PrefixUncompress(attlen, prefixInfo, attrStart, attrCmprsValSize, uncmprValBuf, &dataLenWithPadding, + attalign); break; } case CMPR_NUMSTR: { - (void)NumstrUncompress( - PointerGetDatum(attrStart), attlen, *attrCmprsValSize, uncmprValBuf, &dataLenWithPadding, attalign); + (void)NumstrUncompress(PointerGetDatum(attrStart), attlen, *attrCmprsValSize, uncmprValBuf, + &dataLenWithPadding, attalign); break; } @@ -1395,12 +1482,12 @@ int PageCompress::UncompressOneAttr( * attrStart [IN]: start of attr data; * attrCmprsValSize [OUT]: length of compressed value; */ -Datum PageCompress::UncompressOneAttr( - char mode, void* metaInfo, Oid typeOid, int attlen, char* attrStart, int* attrCmprsValSize) +Datum PageCompress::UncompressOneAttr(char mode, void *metaInfo, Oid typeOid, int attlen, char *attrStart, + int *attrCmprsValSize) { switch (mode) { case CMPR_DELTA: { - DeltaCmprMeta* deltaInfo = (DeltaCmprMeta*)metaInfo; + DeltaCmprMeta *deltaInfo = (DeltaCmprMeta *)metaInfo; if (deltaInfo->bytes == 0) { *attrCmprsValSize = 0; return deltaInfo->MinVal; @@ -1420,12 +1507,12 @@ Datum PageCompress::UncompressOneAttr( return (Datum)0; } - const NumberTypeOpt* opt = binarySearch(typeOid); - return DeltaUncompress(deltaInfo, opt, (unsigned char*)attrStart); + const NumberTypeOpt *opt = binarySearch(typeOid); + return DeltaUncompress(deltaInfo, opt, (unsigned char *)attrStart); } case CMPR_DICT: { - DictCmprMeta* dicInfo = (DictCmprMeta*)metaInfo; + DictCmprMeta *dicInfo = (DictCmprMeta *)metaInfo; if (dicInfo->dictItemNum == 1) { *attrCmprsValSize = 0; @@ -1437,7 +1524,7 @@ Datum PageCompress::UncompressOneAttr( } case CMPR_PREFIX: { - PrefixCmprMeta* prefixInfo = (PrefixCmprMeta*)metaInfo; + PrefixCmprMeta *prefixInfo = (PrefixCmprMeta *)metaInfo; return PrefixUncompress(attlen, prefixInfo, attrStart, attrCmprsValSize); } @@ -1458,11 +1545,11 @@ Datum PageCompress::UncompressOneAttr( } /* Get dictionary item ID */ -bool PageCompress::DictCompress(int col, Datum val, unsigned char& dicItemId) +bool PageCompress::DictCompress(int col, Datum val, unsigned char &dicItemId) { bool found = false; int attlen = m_rel->rd_att->attrs[col]->attlen; - DictCmprMeta* dicInfo = (DictCmprMeta*)m_cmprMeta[col]; + DictCmprMeta *dicInfo = (DictCmprMeta *)m_cmprMeta[col]; DictItemData key; if (attlen > 0) @@ -1481,7 +1568,7 @@ bool PageCompress::DictCompress(int col, Datum val, unsigned char& dicItemId) } /* compress the col's attribute of one tuple, ouput data is written into formTuple */ -void PageCompress::CompressOneAttr(Datum val, bool null, FormCmprTupleData* formTuple, int col) +void PageCompress::CompressOneAttr(Datum val, bool null, FormCmprTupleData *formTuple, int col) { formTuple->compressed[col] = false; @@ -1491,15 +1578,15 @@ void PageCompress::CompressOneAttr(Datum val, bool null, FormCmprTupleData* form return; } - Form_pg_attribute* attrs = m_rel->rd_att->attrs; + Form_pg_attribute *attrs = m_rel->rd_att->attrs; formTuple->values[col] = val; formTuple->isnulls[col] = false; switch (m_cmprMode[col]) { case CMPR_DELTA: { - DeltaCmprMeta* metaInfo = (DeltaCmprMeta*)m_cmprMeta[col]; - const NumberTypeOpt* opt = m_numTypeOpt[col]; - unsigned char* deltaBuf = (unsigned char*)palloc((Size)metaInfo->bytes); + DeltaCmprMeta *metaInfo = (DeltaCmprMeta *)m_cmprMeta[col]; + const NumberTypeOpt *opt = m_numTypeOpt[col]; + unsigned char *deltaBuf = (unsigned char *)palloc((Size)metaInfo->bytes); if (DeltaCompress(metaInfo, opt, val, deltaBuf)) { formTuple->compressed[col] = true; if (metaInfo->bytes == 0) { @@ -1524,7 +1611,7 @@ void PageCompress::CompressOneAttr(Datum val, bool null, FormCmprTupleData* form case CMPR_DICT: { if (DictCompress(col, val, m_dictItemId[col])) { formTuple->compressed[col] = true; - DictCmprMeta* dicInfo = (DictCmprMeta*)m_cmprMeta[col]; + DictCmprMeta *dicInfo = (DictCmprMeta *)m_cmprMeta[col]; if (dicInfo->dictItemNum == 1) { formTuple->valsize[col] = 0; formTuple->values[col] = (Datum)0; @@ -1539,7 +1626,7 @@ void PageCompress::CompressOneAttr(Datum val, bool null, FormCmprTupleData* form case CMPR_PREFIX: { int attrLen = attrs[col]->attlen; Assert(attrLen == -1 || attrLen == -2); - PrefixCmprMeta* prefixInfo = (PrefixCmprMeta*)m_cmprMeta[col]; + PrefixCmprMeta *prefixInfo = (PrefixCmprMeta *)m_cmprMeta[col]; Datum cmprsVal; int cmprsValSize; bool successful = false; @@ -1604,11 +1691,11 @@ bool PageCompress::CompressOnePage(void) int thisToasts; MemoryContext oldMemCnxt; - ColArray* colArray = NULL; + ColArray *colArray = NULL; TupleDesc desc = RelationGetDescr(m_rel); FormCmprTupleData formTupleData; - Datum* values = NULL; - bool* isnulls = NULL; + Datum *values = NULL; + bool *isnulls = NULL; bool fillOnePage = false; bool hascmpr = false; bool remainBeforeCmpr = true; @@ -1677,10 +1764,10 @@ bool PageCompress::CompressOnePage(void) #endif /* Step 4: Compress the current batch rows. */ - formTupleData.compressed = (bool*)palloc((Size)(sizeof(bool) * attrNum)); - formTupleData.valsize = (int*)palloc((Size)(sizeof(int) * attrNum)); - formTupleData.values = (Datum*)palloc((Size)(sizeof(Datum) * attrNum)); - formTupleData.isnulls = (bool*)palloc((Size)(sizeof(bool) * attrNum)); + formTupleData.compressed = (bool *)palloc((Size)(sizeof(bool) * attrNum)); + formTupleData.valsize = (int *)palloc((Size)(sizeof(int) * attrNum)); + formTupleData.values = (Datum *)palloc((Size)(sizeof(Datum) * attrNum)); + formTupleData.isnulls = (bool *)palloc((Size)(sizeof(bool) * attrNum)); size = (int)MAXALIGN(SizeOfHeapPageHeaderData) + (int)MAXALIGN((uint32)m_cmprHeaderSize); for (row = 0; row < m_mappedTupsNum; ++row) { @@ -1699,7 +1786,9 @@ bool PageCompress::CompressOnePage(void) * or all compressed tuples fill part of one page. */ if (hascmpr) { - fillOnePage = Dispatch(m_mappedTups[row], (HeapTuple)tableam_tops_form_cmprs_tuple(desc, &formTupleData, HEAP_TUPLE), size, blksize); + fillOnePage = + Dispatch(m_mappedTups[row], (HeapTuple)tableam_tops_form_cmprs_tuple(desc, &formTupleData, HEAP_TUPLE), + size, blksize); } else { fillOnePage = Dispatch(m_mappedTups[row], size, blksize); } @@ -1723,8 +1812,8 @@ bool PageCompress::CompressOnePage(void) } Assert(row == m_mappedTupsNum); - values = (Datum*)palloc((Size)(sizeof(Datum) * attrNum)); - isnulls = (bool*)palloc((Size)(sizeof(bool) * attrNum)); + values = (Datum *)palloc((Size)(sizeof(Datum) * attrNum)); + isnulls = (bool *)palloc((Size)(sizeof(bool) * attrNum)); /* continue to read and compress following tuples, until one page is filled */ for (row = m_current + m_mappedTupsNum + (m_toastTupsNum - prevToastNum); row < m_inTupsNum; ++row) { @@ -1746,7 +1835,8 @@ bool PageCompress::CompressOnePage(void) } if (hascmpr) { - fillOnePage = Dispatch(raw, (HeapTuple)tableam_tops_form_cmprs_tuple(desc, &formTupleData, HEAP_TUPLE), size, blksize); + fillOnePage = Dispatch(raw, (HeapTuple)tableam_tops_form_cmprs_tuple(desc, &formTupleData, HEAP_TUPLE), + size, blksize); } else { fillOnePage = Dispatch(raw, size, blksize); } @@ -1805,9 +1895,7 @@ handle_remains: * step 1: collect these toasts in the front, make sure they are free * after they are written into pages by heap_multi_insert(). */ - rc = memcpy_s(m_inTups + m_current, - (size_t)(sizeof(HeapTuple) * thisToasts), - m_toastTups + prevToastNum, + rc = memcpy_s(m_inTups + m_current, (size_t)(sizeof(HeapTuple) * thisToasts), m_toastTups + prevToastNum, (size_t)(sizeof(HeapTuple) * thisToasts)); securec_check(rc, "", ""); m_current += thisToasts; @@ -1816,9 +1904,7 @@ handle_remains: /* step 2: collect raw tuples in the end, make sure they are moved ahead next buffer. */ if (remainBeforeCmpr) { /* case 3.2.1: raw tuples are all in m_mappedTups[m_mappedTupsNum] */ - rc = memcpy_s(m_inTups + m_current, - (size_t)(sizeof(HeapTuple) * m_mappedTupsNum), - m_mappedTups, + rc = memcpy_s(m_inTups + m_current, (size_t)(sizeof(HeapTuple) * m_mappedTupsNum), m_mappedTups, (size_t)(sizeof(HeapTuple) * m_mappedTupsNum)); securec_check(rc, "", ""); } else { @@ -1828,9 +1914,7 @@ handle_remains: */ int offset = m_current; if (m_cmprTupsNum > 0) { - rc = memcpy_s(m_inTups + offset, - (size_t)(sizeof(HeapTuple) * m_cmprTupsNum), - m_mappedTups, + rc = memcpy_s(m_inTups + offset, (size_t)(sizeof(HeapTuple) * m_cmprTupsNum), m_mappedTups, (size_t)(sizeof(HeapTuple) * m_cmprTupsNum)); securec_check(rc, "", ""); offset += m_cmprTupsNum; @@ -1899,18 +1983,16 @@ void PageCompress::OutputRawTupsAfterCmpr(int nToasts) m_outputTups = m_mappedTups; int uncmprNum = m_inTupsNum - m_uncmprTupIdx; if (uncmprNum > 0) { - errno_t rc = memcpy_s(m_mappedTups + m_cmprTupsNum, - (size_t)(sizeof(HeapTuple) * uncmprNum), - m_cmprTups + m_uncmprTupIdx, - (size_t)(sizeof(HeapTuple) * uncmprNum)); + errno_t rc = memcpy_s(m_mappedTups + m_cmprTupsNum, (size_t)(sizeof(HeapTuple) * uncmprNum), + m_cmprTups + m_uncmprTupIdx, (size_t)(sizeof(HeapTuple) * uncmprNum)); securec_check(rc, "", ""); } Assert((m_cmprTupsNum + uncmprNum) <= m_mappedTupsNum); m_outputTupsNum = m_mappedTupsNum; #ifdef USE_ASSERT_CHECKING - CheckOutputTups( - m_mappedTups, m_cmprTupsNum, (m_mappedTups + m_cmprTupsNum), (m_mappedTupsNum - m_cmprTupsNum), nToasts); + CheckOutputTups(m_mappedTups, m_cmprTupsNum, (m_mappedTups + m_cmprTupsNum), (m_mappedTupsNum - m_cmprTupsNum), + nToasts); #endif #ifdef TRACE_COMPRESS ++nLoops; @@ -1937,10 +2019,8 @@ void PageCompress::OutputCmprTups(int nToasts) else if (m_cmprTupsNum == m_uncmprTupIdx) m_outputTupsNum = m_inTupsNum; else { - errno_t rc = memmove_s(m_cmprTups + m_cmprTupsNum, - (size_t)(sizeof(HeapTuple) * uncmprNum), - m_cmprTups + m_uncmprTupIdx, - (size_t)(sizeof(HeapTuple) * uncmprNum)); + errno_t rc = memmove_s(m_cmprTups + m_cmprTupsNum, (size_t)(sizeof(HeapTuple) * uncmprNum), + m_cmprTups + m_uncmprTupIdx, (size_t)(sizeof(HeapTuple) * uncmprNum)); securec_check(rc, "", ""); m_outputTupsNum = m_cmprTupsNum + uncmprNum; } @@ -1975,7 +2055,7 @@ void PageCompress::OutputToasts(void) Assert(m_cmprTupsNum == 0); } -void PageCompress::SetBatchTuples(HeapTuple* tups, int ntups, bool isLast) +void PageCompress::SetBatchTuples(HeapTuple *tups, int ntups, bool isLast) { m_inTups = tups; m_inTupsNum = ntups; @@ -1988,9 +2068,9 @@ void PageCompress::SetBatchTuples(HeapTuple* tups, int ntups, bool isLast) */ MemoryContext oldMemCnxt = MemoryContextSwitchTo(m_parentMemCxt); - m_toastTups = (HeapTuple*)palloc((Size)(sizeof(HeapTuple) * ntups)); - m_mappedTups = (HeapTuple*)palloc((Size)(sizeof(HeapTuple) * ntups)); - m_cmprTups = (HeapTuple*)palloc((Size)(sizeof(HeapTuple) * ntups)); + m_toastTups = (HeapTuple *)palloc((Size)(sizeof(HeapTuple) * ntups)); + m_mappedTups = (HeapTuple *)palloc((Size)(sizeof(HeapTuple) * ntups)); + m_cmprTups = (HeapTuple *)palloc((Size)(sizeof(HeapTuple) * ntups)); m_toastTupsNum = 0; m_nextBatch = false; @@ -2004,7 +2084,7 @@ void PageCompress::ResetPerPage(void) /* Free everything by destroying dictionary */ for (int att = 0; att < attNum; ++att) { if (m_cmprMode[att] == CMPR_DICT && m_cmprMeta[att]) { - ((DictCmprMeta*)m_cmprMeta[att])->Destroy(); + ((DictCmprMeta *)m_cmprMeta[att])->Destroy(); m_cmprMeta[att] = NULL; } } @@ -2058,12 +2138,11 @@ void PageCompress::ForwardWrite(void) Assert(dest->t_hoff == src->t_hoff); Assert(HeapTupleHeaderGetNatts(dest, m_rel->rd_att) == HeapTupleHeaderGetNatts(src, m_rel->rd_att)); Assert((0x000F & dest->t_infomask) == (0x000F & src->t_infomask)); - Assert( - (0 == (dest->t_infomask & HEAP_HASNULL)) || - 0 == memcmp( - (char*)dest->t_bits, (char*)src->t_bits, BITMAPLEN(HeapTupleHeaderGetNatts(src, m_rel->rd_att)))); + Assert((0 == (dest->t_infomask & HEAP_HASNULL)) || + 0 == memcmp((char *)dest->t_bits, (char *)src->t_bits, + BITMAPLEN(HeapTupleHeaderGetNatts(src, m_rel->rd_att)))); - rc = memcpy_s((char*)dest, src->t_hoff, (char*)src, src->t_hoff); + rc = memcpy_s((char *)dest, src->t_hoff, (char *)src, src->t_hoff); securec_check(rc, "", ""); HEAP_TUPLE_SET_COMPRESSED(dest); } @@ -2093,7 +2172,7 @@ void PageCompress::BackWrite(void) Assert((0x000F & dest->t_infomask) == (0x000F & src->t_infomask)); Assert(HeapTupleHasNulls(m_mappedTups[i]) == HeapTupleHasNulls(m_cmprTups[i])); - rc = memcpy_s((char*)dest, src->t_hoff, (char*)src, src->t_hoff); + rc = memcpy_s((char *)dest, src->t_hoff, (char *)src, src->t_hoff); securec_check(rc, "", ""); HEAP_TUPLE_CLEAR_COMPRESSED(dest); m_mappedTups[i]->t_self = m_cmprTups[i]->t_self; @@ -2104,7 +2183,7 @@ void PageCompress::BackWrite(void) } } -bool PageCompress::Dispatch(HeapTuple raw, HeapTuple cmpr, int& nowSize, const int& blksize) +bool PageCompress::Dispatch(HeapTuple raw, HeapTuple cmpr, int &nowSize, const int &blksize) { Assert(HEAP_TUPLE_IS_COMPRESSED(cmpr->t_data)); int needSize = (int)getTupleSpace(cmpr); @@ -2123,7 +2202,7 @@ bool PageCompress::Dispatch(HeapTuple raw, HeapTuple cmpr, int& nowSize, const i return false; } -bool PageCompress::Dispatch(HeapTuple raw, int& nowSize, const int& blksize) +bool PageCompress::Dispatch(HeapTuple raw, int &nowSize, const int &blksize) { Assert(!HEAP_TUPLE_IS_COMPRESSED(raw->t_data)); int needSize = (int)getTupleSpace(raw); @@ -2186,8 +2265,8 @@ void PageCompress::CheckCmprDatum(Datum arg1, Datum arg2, Form_pg_attribute attr } } - char* ptr1 = DatumGetPointer(arg1); - char* ptr2 = DatumGetPointer(arg2); + char *ptr1 = DatumGetPointer(arg1); + char *ptr2 = DatumGetPointer(arg2); int size1 = 0; int size2 = 0; @@ -2204,7 +2283,7 @@ void PageCompress::CheckCmprDatum(Datum arg1, Datum arg2, Form_pg_attribute attr return; } -void PageCompress::CheckCmprAttr(Datum rawVal, bool rawNull, int col, FormCmprTupleData* formTuple) +void PageCompress::CheckCmprAttr(Datum rawVal, bool rawNull, int col, FormCmprTupleData *formTuple) { Assert(rawNull == formTuple->isnulls[col]); if (rawNull) { @@ -2218,15 +2297,11 @@ void PageCompress::CheckCmprAttr(Datum rawVal, bool rawNull, int col, FormCmprTu } Assert(m_cmprMode[col] != CMPR_UNDEF); - Form_pg_attribute* atts = RelationGetDescr(m_rel)->attrs; + Form_pg_attribute *atts = RelationGetDescr(m_rel)->attrs; Assert(1 != atts[col]->attlen); int cmprSize; - Datum value = UncompressOneAttr(m_cmprMode[col], - m_cmprMeta[col], - atts[col]->atttypid, - atts[col]->attlen, - DatumGetPointer(formTuple->values[col]), - &cmprSize); + Datum value = UncompressOneAttr(m_cmprMode[col], m_cmprMeta[col], atts[col]->atttypid, atts[col]->attlen, + DatumGetPointer(formTuple->values[col]), &cmprSize); Assert(cmprSize == formTuple->valsize[col]); CheckCmprDatum(rawVal, value, atts[col]); @@ -2235,13 +2310,13 @@ void PageCompress::CheckCmprAttr(Datum rawVal, bool rawNull, int col, FormCmprTu void PageCompress::CheckCmprTuple(HeapTuple rawTup, HeapTuple cmprTup) { TupleDesc desc = RelationGetDescr(m_rel); - Form_pg_attribute* atts = desc->attrs; + Form_pg_attribute *atts = desc->attrs; int nattrs = desc->natts; - Datum* values = (Datum*)palloc(sizeof(Datum) * nattrs); - Datum* values2 = (Datum*)palloc(sizeof(Datum) * nattrs); - bool* isnulls = (bool*)palloc(sizeof(bool) * nattrs); - bool* isnulls2 = (bool*)palloc(sizeof(bool) * nattrs); + Datum *values = (Datum *)palloc(sizeof(Datum) * nattrs); + Datum *values2 = (Datum *)palloc(sizeof(Datum) * nattrs); + bool *isnulls = (bool *)palloc(sizeof(bool) * nattrs); + bool *isnulls2 = (bool *)palloc(sizeof(bool) * nattrs); heap_deform_cmprs_tuple(cmprTup, desc, values, isnulls, m_cmprHeaderData); heap_deform_tuple(rawTup, desc, values2, isnulls2); @@ -2269,10 +2344,10 @@ void PageCompress::CheckCmprHeaderData(void) return; } - Form_pg_attribute* atts = RelationGetDescr(m_rel)->attrs; + Form_pg_attribute *atts = RelationGetDescr(m_rel)->attrs; int nattrs = RelationGetNumberOfAttributes(m_rel); int cmprsOff = 0; /* pointer to the start of compression meta */ - void* metaInfo = NULL; + void *metaInfo = NULL; char mode = 0; for (int col = 0; col < nattrs; ++col) { @@ -2283,8 +2358,8 @@ void PageCompress::CheckCmprHeaderData(void) Assert(mode != CMPR_UNDEF && m_cmprMode[col] == mode); switch (mode) { case CMPR_DELTA: { - DeltaCmprMeta* deltaInfo = (DeltaCmprMeta*)metaInfo; - DeltaCmprMeta* target = (DeltaCmprMeta*)m_cmprMeta[col]; + DeltaCmprMeta *deltaInfo = (DeltaCmprMeta *)metaInfo; + DeltaCmprMeta *target = (DeltaCmprMeta *)m_cmprMeta[col]; Assert(deltaInfo->bytes == target->bytes); Assert(deltaInfo->MinVal == target->MinVal); @@ -2292,8 +2367,8 @@ void PageCompress::CheckCmprHeaderData(void) } case CMPR_DICT: { - DictCmprMeta* dictMeta = (DictCmprMeta*)metaInfo; - DictCmprMeta* target = (DictCmprMeta*)m_cmprMeta[col]; + DictCmprMeta *dictMeta = (DictCmprMeta *)metaInfo; + DictCmprMeta *target = (DictCmprMeta *)m_cmprMeta[col]; Assert(dictMeta->dictItemNum == target->dictItemNum); for (int i = 0; i < dictMeta->dictItemNum; ++i) { @@ -2306,8 +2381,8 @@ void PageCompress::CheckCmprHeaderData(void) } case CMPR_PREFIX: { - PrefixCmprMeta* prefixMeta = (PrefixCmprMeta*)metaInfo; - PrefixCmprMeta* target = (PrefixCmprMeta*)m_cmprMeta[col]; + PrefixCmprMeta *prefixMeta = (PrefixCmprMeta *)metaInfo; + PrefixCmprMeta *target = (PrefixCmprMeta *)m_cmprMeta[col]; Assert(prefixMeta->len == target->len); Assert(0 == memcmp(prefixMeta->prefixStr, target->prefixStr, target->len)); @@ -2333,7 +2408,7 @@ void PageCompress::CheckCmprHeaderData(void) * 3. compress and then mapped to mapped arrays; * Important: call before m_current is modified and changed. */ -void PageCompress::CheckOutputTups(HeapTuple* mapped, int nMapped, HeapTuple* uncmpr, int nUncmpr, int nToasts) +void PageCompress::CheckOutputTups(HeapTuple *mapped, int nMapped, HeapTuple *uncmpr, int nUncmpr, int nToasts) { int start = m_current; int end = m_current + m_outputTupsNum + nToasts; @@ -2390,15 +2465,15 @@ void PageCompress::CheckOutputTups(HeapTuple* mapped, int nMapped, HeapTuple* un #ifdef TRACE_COMPRESS -void PageCompress::TraceCmprPage( - int flag, HeapTuple* cmpr, HeapTuple* mapped, int nCmpr, HeapTuple* uncmpr, int nUncmpr, int nToasts) +void PageCompress::TraceCmprPage(int flag, HeapTuple *cmpr, HeapTuple *mapped, int nCmpr, HeapTuple *uncmpr, + int nUncmpr, int nToasts) { int start = m_current; int end = m_current + m_outputTupsNum + nToasts; int nattrs = RelationGetNumberOfAttributes(m_rel); - Form_pg_attribute* atts = RelationGetDescr(m_rel)->attrs; + Form_pg_attribute *atts = RelationGetDescr(m_rel)->attrs; - char* tag = NULL; + char *tag = NULL; if (flag == 0) tag = "Tag: Raw Tuples Before Compress"; else if (flag == 1) @@ -2409,9 +2484,9 @@ void PageCompress::TraceCmprPage( tag = "Tag: Toast Tuples"; ereport(INFO, (errmsg("Loop %d, range[%d - %d], %s", nLoops, start, (end - 1), tag))); - DeltaCmprMeta* deltaMeta = NULL; - PrefixCmprMeta* prefixMeta = NULL; - DictCmprMeta* dictMeta = NULL; + DeltaCmprMeta *deltaMeta = NULL; + PrefixCmprMeta *prefixMeta = NULL; + DictCmprMeta *dictMeta = NULL; for (int col = 0; col < nattrs; ++col) { switch (m_cmprMode[col]) { @@ -2420,12 +2495,9 @@ void PageCompress::TraceCmprPage( break; case CMPR_DELTA: - deltaMeta = (DeltaCmprMeta*)m_cmprMeta[col]; - ereport(INFO, - (errmsg("COL %d: Delta Compress, attrlen %d, delta bytes %d", - col, - atts[col]->attlen, - deltaMeta->bytes))); + deltaMeta = (DeltaCmprMeta *)m_cmprMeta[col]; + ereport(INFO, (errmsg("COL %d: Delta Compress, attrlen %d, delta bytes %d", col, atts[col]->attlen, + deltaMeta->bytes))); break; case CMPR_NUMSTR: @@ -2433,14 +2505,14 @@ void PageCompress::TraceCmprPage( break; case CMPR_PREFIX: - prefixMeta = (PrefixCmprMeta*)m_cmprMeta[col]; + prefixMeta = (PrefixCmprMeta *)m_cmprMeta[col]; ereport(INFO, (errmsg("COL %d: Prefix Compress, len %d", col, prefixMeta->len))); break; case CMPR_DICT: - dictMeta = (DictCmprMeta*)m_cmprMeta[col]; + dictMeta = (DictCmprMeta *)m_cmprMeta[col]; char str[0xFF * (sizeof(int16) + 1) + 1] = {0}; - char* p = str; + char *p = str; for (int i = 0; i < dictMeta->dictItemNum; ++i) { (void)sprintf_s(p, sizeof(str), "%2d ", dictMeta->dictItems[i].itemSize); p = p + 3; @@ -2488,7 +2560,7 @@ void PageCompress::TraceCmprPage( /* binary search. * negative will be returned if search fails. Otherwise return the position of oid. */ -static const NumberTypeOpt* binarySearch(Oid typeOid) +static const NumberTypeOpt *binarySearch(Oid typeOid) { int left = 0; int right = g_number_type_count - 1; diff --git a/src/gausskernel/storage/page/pageparse.cpp b/src/gausskernel/storage/page/pageparse.cpp index 7cfd4130a..db2aaf144 100644 --- a/src/gausskernel/storage/page/pageparse.cpp +++ b/src/gausskernel/storage/page/pageparse.cpp @@ -48,17 +48,13 @@ #include "utils/relmapper.h" #include "pageparse.h" -typedef enum { - BTREE_INDEX = 0, - UBTREE_INDEX, - INDEX_BOTT -} INDEX_TYPE; +typedef enum { BTREE_INDEX = 0, UBTREE_INDEX, INDEX_BOTT } INDEX_TYPE; void CheckUser(const char *fName) { if (!superuser() && !(isOperatoradmin(GetUserId()) && u_sess->attr.attr_security.operation_mode)) ereport(ERROR, (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), - (errmsg("Must be system admin or operator admin in operation mode can use %s.", fName)))); + (errmsg("Must be system admin or operator admin in operation mode can use %s.", fName)))); } static void ParseUHeapPageHeader(void *page, BlockNumber blkno, BlockNumber endBlk, char *output); @@ -82,28 +78,63 @@ static void ParseIndexPageSpecialInfo(void *page, int type, char *output); static void ParseIndexPageData(void *page, int type, char *output); static void ParseIndexPage(void *page, int type, BlockNumber blkno, BlockNumber endBlk, char *output); - +/* + * 鍔熻兘锛氬皢浜岃繘鍒朵綅鍥炬牸寮忓寲涓哄瓧绗︿覆琛ㄧず + * + * 鍙傛暟鍒楄〃锛 + * start锛氭寚鍚戜簩杩涘埗浣嶅浘鏁版嵁鐨勬寚閽 + * len锛氫簩杩涘埗浣嶅浘鏁版嵁鐨勯暱搴 + * bit1锛氳〃绀轰綅涓 1 鏃朵娇鐢ㄧ殑瀛楃 + * bit0锛氳〃绀轰綅涓 0 鏃朵娇鐢ㄧ殑瀛楃 + * strOutput锛氱敤浜庡瓨鍌ㄦ牸寮忓寲鍚庣殑瀛楃涓茬殑缂撳啿鍖 + * + * 娉ㄦ剰浜嬮」锛 + * - 璇ュ嚱鏁扮敤浜庡皢浜岃繘鍒朵綅鍥炬暟鎹浆鎹负瀛楃涓茶〃绀猴紝浠ヤ究杈撳嚭鍜屾樉绀恒 + * - 鍙傛暟 `bit1` 鍜 `bit0` 鍒嗗埆鎸囧畾浜嗕綅涓 1 鍜 0 鏃朵娇鐢ㄧ殑瀛楃銆 + * - 鍑芥暟灏嗕簩杩涘埗浣嶅浘涓殑姣忎釜浣嶉兘鏍煎紡鍖栦负瀛楃锛屾瘡 8 浣嶄箣闂存坊鍔犱竴涓┖鏍笺 + * - 缁撴灉瀛楃涓插皢瀛樺偍鍦 `strOutput` 涓 + */ static void formatBitmap(const unsigned char *start, int len, char bit1, char bit0, char *strOutput) { errno_t rc = EOK; for (int i = 0; i < len; ++i) { - unsigned char ch = start[i]; - unsigned char bitmask = 1; + unsigned char ch = start[i]; // 鑾峰彇浜岃繘鍒朵綅鍥句腑鐨勪竴涓瓧鑺 + unsigned char bitmask = 1; // 鍒濆鍖栨帺鐮佷负 1 /* print 8 bits within a loop */ do { rc = snprintf_s(strOutput + (int)strlen(strOutput), MAXOUTPUTLEN, MAXOUTPUTLEN - 1, "%c", - ((ch & bitmask) ? bit1 : bit0)); - securec_check_ss(rc, "\0", "\0"); - bitmask <<= 1; - } while (bitmask != 0); - rc = snprintf_s(strOutput + (int)strlen(strOutput), MAXOUTPUTLEN, MAXOUTPUTLEN - 1, " "); - securec_check_ss(rc, "\0", "\0"); + ((ch & bitmask) ? bit1 : bit0)); // 鏍规嵁浣嶅奸夋嫨鐩稿簲鐨勫瓧绗﹀苟娣诲姞鍒扮粨鏋滃瓧绗︿覆 + securec_check_ss(rc, "\0", "\0"); // 妫鏌 snprintf_s 鐨勮繑鍥炲 + bitmask <<= 1; // 绉诲姩鎺╃爜鍒颁笅涓涓綅 + } while (bitmask != 0); // 缁х画鐩村埌澶勭悊瀹屾墍鏈 8 浣 + rc = snprintf_s(strOutput + (int)strlen(strOutput), MAXOUTPUTLEN, MAXOUTPUTLEN - 1, + " "); // 鍦ㄦ瘡 8 浣嶄箣鍚庢坊鍔犱竴涓┖鏍 + securec_check_ss(rc, "\0", "\0"); // 妫鏌 snprintf_s 鐨勮繑鍥炲 } } /* init RelFileNode and outputFilename */ +/* + * 鍔熻兘锛氫负璇诲彇鏂囦欢鍋氬噯澶囷紝璁剧疆鏂囦欢璺緞銆佽〃鍏宠仈绫诲瀷绛変俊鎭 + * + * 鍙傛暟鍒楄〃锛 + * path锛氭枃浠惰矾寰 + * blocknum锛氬潡鍙 + * relation_type锛氳〃鍏宠仈绫诲瀷锛屼緥濡 "segment" + * outputFilename锛氳緭鍑烘枃浠跺悕鐨勭紦鍐插尯 + * relnode锛氳〃鍏宠仈鐨勬枃浠惰妭鐐逛俊鎭 + * parse_page锛氭槸鍚﹁В鏋愰〉闈紙甯冨皵鍊硷級 + + * 娉ㄦ剰浜嬮」锛 + * - 璇ュ嚱鏁扮敤浜庝负璇诲彇鏂囦欢鍋氬噯澶囷紝璁剧疆杈撳嚭鏂囦欢鍚嶃佹枃浠惰妭鐐逛俊鎭瓑銆 + * - 濡傛灉璁$畻鍘嬬缉涓诲垎鏀殑澶у皬涓嶄负 0锛屽垯鎶涘嚭閿欒锛屼笉鍏佽鍦ㄨ繖閲屼娇鐢ㄥ帇缂╄〃鏂囦欢銆 + * - 鏍规嵁琛ㄥ叧鑱旂被鍨嬭缃 `relnode->bucketNode`锛屽苟浠庢枃浠惰矾寰勪腑鎻愬彇妗跺彿銆 + * - 鏍规嵁鏂囦欢璺緞璁$畻 `relfilenode`銆 + * - 濡傛灉琛ㄧ┖闂 oid 涓 0锛屽垯鎶涘嚭閿欒銆 + * - 鏍规嵁瑙f瀽椤甸潰鏍囧織鍜岃〃绌洪棿淇℃伅璁剧疆杈撳嚭鏂囦欢鍚嶃 + */ void PrepForRead(char *path, int64 blocknum, char *relation_type, char *outputFilename, RelFileNode *relnode, - bool parse_page) + bool parse_page) { if (CalculateCompressMainForkSize(path, true) != 0) { ereport(ERROR, @@ -120,7 +151,7 @@ void PrepForRead(char *path, int64 blocknum, char *relation_type, char *outputFi bucketNodestr += TWO; /* delete first two chars: _b */ relnode->bucketNode = (int4)pg_strtouint64(bucketNodestr, NULL, TENBASE); rc = strncpy_s(pathFirstpart, strlen(path) - strlen(bucketNodestr) - 1, path, - strlen(path) - strlen(bucketNodestr) - TWO); + strlen(path) - strlen(bucketNodestr) - TWO); securec_check(rc, "\0", "\0"); } } else { @@ -134,40 +165,63 @@ void PrepForRead(char *path, int64 blocknum, char *relation_type, char *outputFi } if (relfilenode.rnode.node.spcNode == 0) ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - (errmsg("The tablespace oid is 0. Please check the first parameter path. " - "If you are not sure about the table path, please check pg_relation_filepath.")))); + (errmsg("The tablespace oid is 0. Please check the first parameter path. " + "If you are not sure about the table path, please check pg_relation_filepath.")))); RelFileNodeRelCopy(*relnode, relfilenode.rnode.node); relnode->opt = 0; char *pagesuffix = "page"; char *xlogsuffix = "xlog"; rc = snprintf_s(outputFilename + (int)strlen(outputFilename), MAXFILENAME, MAXFILENAME - 1, "%s/%u_%u_%u_%d.%s", - t_thrd.proc_cxt.DataDir, relnode->spcNode, relnode->dbNode, relnode->relNode, blocknum, - (parse_page ? pagesuffix : xlogsuffix)); + t_thrd.proc_cxt.DataDir, relnode->spcNode, relnode->dbNode, relnode->relNode, blocknum, + (parse_page ? pagesuffix : xlogsuffix)); securec_check_ss(rc, "\0", "\0"); pfree_ext(pathFirstpart); } +/* + * 鍔熻兘锛氳В鏋愬爢椤甸潰澶翠俊鎭苟鐢熸垚瀛楃涓茶緭鍑 + * + * 鍙傛暟鍒楄〃锛 + * - page锛氬爢椤甸潰澶存寚閽 + * - strOutput锛氱敤浜庡瓨鍌ㄨ緭鍑轰俊鎭殑缂撳啿鍖 + * - blockNum锛氬潡鍙 + * - block_endpoint锛氬潡鐨勭粨鏉熷彿 + * 娉ㄦ剰浜嬮」锛 + * - 璇ュ嚱鏁扮敤浜庤В鏋愬爢椤甸潰澶寸殑淇℃伅骞跺皢缁撴灉瀛樺偍鍦ㄨ緭鍑哄瓧绗︿覆涓 + * - 浣跨敤 snprintf_s 鍑芥暟鏍煎紡鍖栬緭鍑轰俊鎭埌 `strOutput` 缂撳啿鍖恒 + * - 杈撳嚭鍧楀彿鍜屽潡缁撴潫鍙蜂綔涓洪〉闈俊鎭殑涓閮ㄥ垎銆 + * - 璁$畻鍜岃緭鍑洪〉闈㈢殑 LSN锛堟棩蹇楀簭鍒楀彿锛夈 + * - 妫鏌ラ〉闈㈢殑鏍¢獙鍜屾槸鍚﹀尮閰嶃 + * - 杈撳嚭椤甸潰鏍囧織鐨勭浉鍏充俊鎭紝濡傛槸鍚︽湁绌洪棽琛屾寚閽堛侀〉闈㈡槸鍚︽弧銆佹槸鍚﹀叏閮ㄥ彲瑙佺瓑銆 + * - 杈撳嚭椤甸潰鐨勮竟鐣屼俊鎭拰澶у皬銆 + * - 杈撳嚭椤甸潰鐨勭壒娈婃暟鎹潡澶у皬鍜岀増鏈俊鎭 + * - 杈撳嚭椤甸潰澶寸殑鍏朵粬淇℃伅锛屽 xid 鍩烘暟銆佸鐗堟湰鍩烘暟銆佹竻鐞 xid 绛夈 + */ static void ParseHeapHeader(const PageHeader page, char *strOutput, BlockNumber blockNum, BlockNumber block_endpoint) { errno_t rc = EOK; + // 杈撳嚭鍧楀彿鍜屽潡缁撴潫鍙 rc = snprintf_s(strOutput + (int)strlen(strOutput), MAXOUTPUTLEN, MAXOUTPUTLEN - 1, - "Page information of block %u/%u", blockNum, block_endpoint); + "Page information of block %u/%u", blockNum, block_endpoint); securec_check_ss(rc, "\0", "\0"); + // 杈撳嚭椤甸潰鐨 LSN rc = snprintf_s(strOutput + (int)strlen(strOutput), MAXOUTPUTLEN, MAXOUTPUTLEN - 1, "\n\tpd_lsn: %X/%X", - (uint32)(PageGetLSN(page) >> XIDTHIRTYTWO), (uint32)PageGetLSN(page)); + (uint32)(PageGetLSN(page) >> XIDTHIRTYTWO), (uint32)PageGetLSN(page)); securec_check_ss(rc, "\0", "\0"); bool checksum_matched = false; + // 妫鏌ラ〉闈㈡牎楠屽拰鏄惁鍖归厤 if (CheckPageZeroCases(page)) { uint16 checksum = pg_checksum_page((char *)page, (BlockNumber)blockNum); checksum_matched = (checksum == page->pd_checksum); } rc = snprintf_s(strOutput + (int)strlen(strOutput), MAXOUTPUTLEN, MAXOUTPUTLEN - 1, - "\n\tpd_checksum: 0x%X, verify %s", page->pd_checksum, checksum_matched ? "success" : "fail"); + "\n\tpd_checksum: 0x%X, verify %s", page->pd_checksum, checksum_matched ? "success" : "fail"); securec_check_ss(rc, "\0", "\0"); rc = strcat_s(strOutput, MAXOUTPUTLEN, "\n\tpd_flags: "); securec_check(rc, "\0", "\0"); + // 杈撳嚭椤甸潰鏍囧織鐨勭浉鍏充俊鎭 if (PageHasFreeLinePointers(page)) { rc = strcat_s(strOutput, MAXOUTPUTLEN, "PD_HAS_FREE_LINES "); securec_check(rc, "\0", "\0"); @@ -192,79 +246,109 @@ static void ParseHeapHeader(const PageHeader page, char *strOutput, BlockNumber rc = strcat_s(strOutput, MAXOUTPUTLEN, "PD_ENCRYPT_PAGE "); securec_check(rc, "\0", "\0"); } + // 杈撳嚭椤甸潰鐨勮竟鐣屼俊鎭拰鏄惁涓虹┖ rc = snprintf_s(strOutput + (int)strlen(strOutput), MAXOUTPUTLEN, MAXOUTPUTLEN - 1, "\n\tpd_lower: %u, %s", - page->pd_lower, PageIsEmpty(page) ? "empty" : "non-empty"); + page->pd_lower, PageIsEmpty(page) ? "empty" : "non-empty"); securec_check_ss(rc, "\0", "\0"); rc = snprintf_s(strOutput + (int)strlen(strOutput), MAXOUTPUTLEN, MAXOUTPUTLEN - 1, "\n\tpd_upper: %u, %s", - page->pd_upper, PageIsNew(page) ? "new" : "old"); + page->pd_upper, PageIsNew(page) ? "new" : "old"); securec_check_ss(rc, "\0", "\0"); + // 杈撳嚭椤甸潰鐨勭壒娈婃暟鎹潡澶у皬鍜岀増鏈俊鎭 rc = snprintf_s(strOutput + (int)strlen(strOutput), MAXOUTPUTLEN, MAXOUTPUTLEN - 1, "\n\tpd_special: %u, size %u", - page->pd_special, PageGetSpecialSize(page)); + page->pd_special, PageGetSpecialSize(page)); securec_check_ss(rc, "\0", "\0"); rc = snprintf_s(strOutput + (int)strlen(strOutput), MAXOUTPUTLEN, MAXOUTPUTLEN - 1, - "\n\tPage size & version: %u, %u", (uint16)PageGetPageSize(page), (uint16)PageGetPageLayoutVersion(page)); + "\n\tPage size & version: %u, %u", (uint16)PageGetPageSize(page), + (uint16)PageGetPageLayoutVersion(page)); securec_check_ss(rc, "\0", "\0"); + // 杈撳嚭椤甸潰澶寸殑鍏朵粬淇℃伅锛屽 xid 鍩烘暟銆佸鐗堟湰鍩烘暟銆佹竻鐞 xid 绛 rc = snprintf_s(strOutput + (int)strlen(strOutput), MAXOUTPUTLEN, MAXOUTPUTLEN - 1, - "\n\tpd_xid_base: %lu, pd_multi_base: %lu", ((HeapPageHeader)(page))->pd_xid_base, - ((HeapPageHeader)(page))->pd_multi_base); + "\n\tpd_xid_base: %lu, pd_multi_base: %lu", ((HeapPageHeader)(page))->pd_xid_base, + ((HeapPageHeader)(page))->pd_multi_base); securec_check_ss(rc, "\0", "\0"); rc = snprintf_s(strOutput + (int)strlen(strOutput), MAXOUTPUTLEN, MAXOUTPUTLEN - 1, "\n\tpd_prune_xid: %lu", - ((HeapPageHeader)(page))->pd_prune_xid + ((HeapPageHeader)(page))->pd_xid_base); + ((HeapPageHeader)(page))->pd_prune_xid + ((HeapPageHeader)(page))->pd_xid_base); securec_check_ss(rc, "\0", "\0"); } - +/* + * 鍔熻兘锛氭墦鍗板爢鍏冪粍澶寸殑 infomask 淇℃伅 + * + * 鍙傛暟鍒楄〃锛 + * - tup锛氬爢鍏冪粍澶存寚閽 + * - strOutput锛氱敤浜庡瓨鍌ㄨ緭鍑轰俊鎭殑缂撳啿鍖 + * + * 娉ㄦ剰浜嬮」锛 + * - 璇ュ嚱鏁扮敤浜庤В鏋愬苟鎵撳嵃鍫嗗厓缁勫ご鐨 infomask 瀛楁鐨勪俊鎭 + * - 浣跨敤 strcat_s 鍜 snprintf_s 鍑芥暟灏嗕俊鎭坊鍔犲埌 `strOutput` 缂撳啿鍖轰腑銆 + * - 杈撳嚭鍖呮嫭 infomask 鐨勫悇涓爣蹇椾綅锛屽鏄惁鍖呭惈 NULL銆佹槸鍚︽湁鍙樺瀛楁銆佹槸鍚︽湁澶栭儴瀛楁绛夈 + * - 杩樿緭鍑轰簡鍏朵粬鏍囧織浣嶏紝濡傛槸鍚﹀寘鍚 OID銆佹槸鍚﹀帇缂┿佹槸鍚︿负 ComboCID 绛夈 + * - 鏈鍚庤緭鍑 t_infomask2 鐨勪俊鎭紝鍖呮嫭鏄惁鐑洿鏂般佹槸鍚︿粎涓哄敮涓鍏冪粍銆 + */ static void PrintInfomask(HeapTupleHeader tup, char *strOutput) { errno_t rc = EOK; + // 杈撳嚭鏄惁鍖呭惈 NULL 鏍囧織浣 if (tup->t_infomask & HEAP_HASNULL) { rc = strcat_s(strOutput, MAXOUTPUTLEN, "HEAP_HASNULL "); securec_check(rc, "\0", "\0"); } + // 杈撳嚭鏄惁鏈夊彉瀹藉瓧娈垫爣蹇椾綅 if (tup->t_infomask & HEAP_HASVARWIDTH) { rc = strcat_s(strOutput, MAXOUTPUTLEN, "HEAP_HASVARWIDTH "); securec_check(rc, "\0", "\0"); } + // 杈撳嚭鏄惁鏈夊閮ㄥ瓧娈垫爣蹇椾綅 if (tup->t_infomask & HEAP_HASEXTERNAL) { rc = strcat_s(strOutput, MAXOUTPUTLEN, "HEAP_HASEXTERNAL "); securec_check(rc, "\0", "\0"); } + // 杈撳嚭鏄惁鍖呭惈 OID 浠ュ強 OID 鐨勫 if (tup->t_infomask & HEAP_HASOID) { rc = snprintf_s(strOutput + (int)strlen(strOutput), MAXOUTPUTLEN, MAXOUTPUTLEN - 1, "HEAP_HASOID(%d) ", - HeapTupleHeaderGetOid(tup)); + HeapTupleHeaderGetOid(tup)); securec_check_ss(rc, "\0", "\0"); } + // 杈撳嚭鏄惁鍘嬬缉鏍囧織浣 if (tup->t_infomask & HEAP_COMPRESSED) { rc = strcat_s(strOutput, MAXOUTPUTLEN, "HEAP_COMPRESSED "); securec_check(rc, "\0", "\0"); } + // 杈撳嚭鏄惁涓 ComboCID 鏍囧織浣 if (tup->t_infomask & HEAP_COMBOCID) { rc = strcat_s(strOutput, MAXOUTPUTLEN, "HEAP_COMBOCID "); securec_check(rc, "\0", "\0"); } + // 杈撳嚭鏄惁鍏锋湁鎺掍粬閿佹爣蹇椾綅 if (tup->t_infomask & HEAP_XMAX_EXCL_LOCK) { rc = strcat_s(strOutput, MAXOUTPUTLEN, "HEAP_XMAX_EXCL_LOCK "); securec_check(rc, "\0", "\0"); } + // 杈撳嚭鏄惁鍏锋湁鍏变韩閿佹爣蹇椾綅 if (tup->t_infomask & HEAP_XMAX_SHARED_LOCK) { rc = strcat_s(strOutput, MAXOUTPUTLEN, "HEAP_XMAX_SHARED_LOCK "); securec_check(rc, "\0", "\0"); } + // 杈撳嚭鏄惁 XMIN 涓哄凡鎻愪氦鏍囧織浣 if (tup->t_infomask & HEAP_XMIN_COMMITTED) { rc = strcat_s(strOutput, MAXOUTPUTLEN, "HEAP_XMIN_COMMITTED "); securec_check(rc, "\0", "\0"); } + // 杈撳嚭鏄惁 XMIN 涓烘棤鏁堟爣蹇椾綅 if (tup->t_infomask & HEAP_XMIN_INVALID) { rc = strcat_s(strOutput, MAXOUTPUTLEN, "HEAP_XMIN_INVALID "); securec_check(rc, "\0", "\0"); } + // 杈撳嚭鏄惁 XMAX 涓哄凡鎻愪氦鏍囧織浣 if (tup->t_infomask & HEAP_XMAX_COMMITTED) { rc = strcat_s(strOutput, MAXOUTPUTLEN, "HEAP_XMAX_COMMITTED "); securec_check(rc, "\0", "\0"); } + // 杈撳嚭鏄惁 XMAX 涓烘棤鏁堟爣蹇椾綅 if (tup->t_infomask & HEAP_XMAX_INVALID) { rc = strcat_s(strOutput, MAXOUTPUTLEN, "HEAP_XMAX_INVALID "); securec_check(rc, "\0", "\0"); } + // 杈撳嚭鏄惁 XMAX 涓哄鐗堟湰鏍囧織浣 if (tup->t_infomask & HEAP_XMAX_IS_MULTI) { rc = strcat_s(strOutput, MAXOUTPUTLEN, "HEAP_XMAX_IS_MULTI "); securec_check(rc, "\0", "\0"); @@ -291,154 +375,276 @@ static void PrintInfomask(HeapTupleHeader tup, char *strOutput) securec_check(rc, "\0", "\0"); } } - +/* + * 鍔熻兘锛氳В鏋愬苟鎵撳嵃鍫嗗厓缁勫ご鐨勪俊鎭 + * + * 鍙傛暟鍒楄〃锛 + * page锛氶〉澶存寚閽堬紝鍖呭惈鍫嗗厓缁勭殑淇℃伅 + * lineno锛氬厓缁勫湪椤典腑鐨勮鍙 + * strOutput锛氱敤浜庡瓨鍌ㄨ緭鍑轰俊鎭殑缂撳啿鍖 + * + * 娉ㄦ剰浜嬮」锛 + * - 璇ュ嚱鏁扮敤浜庤В鏋愬苟鎵撳嵃鍫嗗厓缁勭殑淇℃伅锛屽寘鎷厓缁勭紪鍙枫侀暱搴︺佸亸绉婚噺绛夈 + * - 浣跨敤 snprintf_s 鍑芥暟灏嗕俊鎭坊鍔犲埌 `strOutput` 缂撳啿鍖轰腑銆 + * - 杈撳嚭鍖呮嫭鍏冪粍缂栧彿銆侀暱搴︺佸亸绉婚噺銆乆min銆乆max銆丆ID 绛変俊鎭 + * - 杩樿緭鍑轰簡 ctid锛堝潡鍙峰拰鍋忕Щ閲忥級浠ュ強 t_infomask 鐨勪俊鎭 + * - 璋冪敤 `PrintInfomask` 鍑芥暟鎵撳嵃 t_infomask 涓悇涓爣蹇椾綅鐨勪俊鎭 + * - 杈撳嚭灞炴ф暟閲忓拰 t_hoff锛堝睘鎬у亸绉婚噺锛夈 + * - 鏈鍚庤緭鍑 t_bits 鐨勪俊鎭紝閫氳繃璋冪敤 `formatBitmap` 鍑芥暟鎵撳嵃浣嶅浘淇℃伅銆 + */ static void ParseTupleHeader(const PageHeader page, uint lineno, char *strOutput) { errno_t rc = EOK; + // 鑾峰彇鍏冪粍瀵瑰簲鐨 ItemId ItemId lp = PageGetItemId(page, lineno); + // 杈撳嚭鍏冪粍鐨勫熀鏈俊鎭紝鍖呮嫭缂栧彿銆侀暱搴﹀拰鍋忕Щ閲 rc = snprintf_s(strOutput + (int)strlen(strOutput), MAXOUTPUTLEN, MAXOUTPUTLEN - 1, - "\n\n\t\tTuple #%u is normal: length %u, offset %u", lineno, ItemIdGetLength(lp), ItemIdGetOffset(lp)); + "\n\n\t\tTuple #%u is normal: length %u, offset %u", lineno, ItemIdGetLength(lp), + ItemIdGetOffset(lp)); securec_check_ss(rc, "\0", "\0"); + // 鍒涘缓涓涓櫄鎷 HeapTupleData 缁撴瀯 HeapTupleData dummyTuple; HeapTupleHeader tup = (HeapTupleHeader)(PageGetItem(page, lp)); dummyTuple.t_data = tup; dummyTuple.t_xid_base = ((HeapPageHeader)(page))->pd_xid_base; dummyTuple.t_multi_base = ((HeapPageHeader)(page))->pd_multi_base; + // 杈撳嚭 Xmin銆乆max 鍜 CID 鐨勪俊鎭 rc = snprintf_s(strOutput + (int)strlen(strOutput), MAXOUTPUTLEN, MAXOUTPUTLEN - 1, - "\n\t\t\tt_xmin/t_xmax/t_cid: %lu/%lu/%u", HeapTupleGetRawXmin(&dummyTuple), HeapTupleGetRawXmax(&dummyTuple), - HeapTupleHeaderGetRawCommandId(tup)); + "\n\t\t\tt_xmin/t_xmax/t_cid: %lu/%lu/%u", HeapTupleGetRawXmin(&dummyTuple), + HeapTupleGetRawXmax(&dummyTuple), HeapTupleHeaderGetRawCommandId(tup)); securec_check_ss(rc, "\0", "\0"); + // 杈撳嚭 ctid锛堝潡鍙峰拰鍋忕Щ閲忥級鐨勪俊鎭 rc = snprintf_s(strOutput + (int)strlen(strOutput), MAXOUTPUTLEN, MAXOUTPUTLEN - 1, - "\n\t\t\tctid:(block %u/%u, offset %u)", tup->t_ctid.ip_blkid.bi_hi, tup->t_ctid.ip_blkid.bi_lo, - tup->t_ctid.ip_posid); + "\n\t\t\tctid:(block %u/%u, offset %u)", tup->t_ctid.ip_blkid.bi_hi, tup->t_ctid.ip_blkid.bi_lo, + tup->t_ctid.ip_posid); securec_check_ss(rc, "\0", "\0"); + // 杈撳嚭 t_infomask 鐨勪俊鎭 rc = strcat_s(strOutput, MAXOUTPUTLEN, "\n\t\t\tt_infomask: "); securec_check(rc, "\0", "\0"); + // 璋冪敤 PrintInfomask 鍑芥暟鎵撳嵃 t_infomask 鐨勫悇涓爣蹇椾綅淇℃伅 PrintInfomask(tup, strOutput); + // 杈撳嚭灞炴ф暟閲 rc = snprintf_s(strOutput + (int)strlen(strOutput), MAXOUTPUTLEN, MAXOUTPUTLEN - 1, "Attrs Num: %d", - HeapTupleHeaderGetNatts(tup, NULL)); + HeapTupleHeaderGetNatts(tup, NULL)); securec_check_ss(rc, "\0", "\0"); + // 杈撳嚭灞炴у亸绉婚噺 rc = snprintf_s(strOutput + (int)strlen(strOutput), MAXOUTPUTLEN, MAXOUTPUTLEN - 1, "\n\t\t\tt_hoff: %u", - tup->t_hoff); + tup->t_hoff); securec_check_ss(rc, "\0", "\0"); + // 杈撳嚭 t_bits 鐨勪綅鍥句俊鎭 rc = strcat_s(strOutput, MAXOUTPUTLEN, "\n\t\t\tt_bits: "); securec_check(rc, "\0", "\0"); + // 璋冪敤 formatBitmap 鍑芥暟鎵撳嵃浣嶅浘淇℃伅 formatBitmap((const unsigned char *)tup->t_bits, BITMAPLEN(HeapTupleHeaderGetNatts(tup, NULL)), 'V', 'N', - strOutput); + strOutput); } - +/* + * 鍔熻兘锛氳В鏋愬苟鎵撳嵃鍫嗛〉闈㈢殑淇℃伅锛屽寘鎷〉澶村拰鍏冪粍淇℃伅 + * + * 鍙傛暟鍒楄〃锛 + * page锛氶〉澶存寚閽堬紝鍖呭惈鍫嗛〉闈㈢殑淇℃伅 + * blockNum锛氬綋鍓嶉〉闈㈢殑鍧楃紪鍙 + * strOutput锛氱敤浜庡瓨鍌ㄨ緭鍑轰俊鎭殑缂撳啿鍖 + * block_endpoint锛氬潡鐨勭粨鏉熶綅缃 + * + * 娉ㄦ剰浜嬮」锛 + * - 璇ュ嚱鏁扮敤浜庤В鏋愬苟鎵撳嵃鍫嗛〉闈㈢殑淇℃伅锛屽寘鎷〉澶翠俊鎭佸厓缁勫ご淇℃伅浠ュ強鍏冪粍鏁版嵁銆 + * - 浣跨敤 snprintf_s 鍑芥暟灏嗕俊鎭坊鍔犲埌 `strOutput` 缂撳啿鍖轰腑銆 + * - 棣栧厛妫鏌ラ〉闈㈡寚閽堟槸鍚︽湁鏁堬紝浠ュ強椤甸潰鏁版嵁鏄惁鎹熷潖銆 + * - 璋冪敤 `ParseHeapHeader` 鍑芥暟鎵撳嵃椤甸潰鐨勯〉澶翠俊鎭 + * - 鐒跺悗瑙f瀽鍏冪粍澶翠俊鎭紝鍖呮嫭鍏冪粍缂栧彿銆侀暱搴︺佸亸绉婚噺銆乆min銆乆max銆丆ID 绛変俊鎭 + * - 鏈鍚庤緭鍑哄厓缁勭殑鎬绘暟銆佹甯稿厓缁勬暟銆佹湭浣跨敤鍏冪粍鏁板拰姝讳骸鍏冪粍鏁般 + */ static void ParseHeapPage(const PageHeader page, BlockNumber blockNum, char *strOutput, BlockNumber block_endpoint) { errno_t rc = EOK; + // 妫鏌ラ〉闈㈡寚閽堟槸鍚︽湁鏁堬紝浠ュ強椤甸潰鏁版嵁鏄惁鎹熷潖 if (page->pd_lower < GetPageHeaderSize(page) || page->pd_lower > page->pd_upper || page->pd_upper > page->pd_special || page->pd_special > BLCKSZ || page->pd_special != MAXALIGN(page->pd_special)) { - rc = snprintf_s(strOutput + (int)strlen(strOutput), - MAXOUTPUTLEN, - MAXOUTPUTLEN - 1, - "The page data is corrupted, corrupted page pointers: lower = %u, upper = %u, special = %u\n", - page->pd_lower, - page->pd_upper, - page->pd_special); + rc = snprintf_s(strOutput + (int)strlen(strOutput), MAXOUTPUTLEN, MAXOUTPUTLEN - 1, + "The page data is corrupted, corrupted page pointers: lower = %u, upper = %u, special = %u\n", + page->pd_lower, page->pd_upper, page->pd_special); securec_check_ss(rc, "\0", "\0"); return; } + // 瑙f瀽骞舵墦鍗板爢椤甸潰鐨勯〉澶翠俊鎭 ParseHeapHeader(page, strOutput, blockNum, block_endpoint); /* parse tuple header */ + // 杈撳嚭鍫嗛〉闈腑鐨勫厓缁勪俊鎭儴鍒嗘爣棰 rc = strcat_s(strOutput, MAXOUTPUTLEN, "\n\n\tHeap tuple information on this page"); securec_check(rc, "\0", "\0"); + // 鑾峰彇椤甸潰涓殑鍏冪粍鎬绘暟 uint nline = PageGetMaxOffsetNumber((Page)page); uint nunused = 0, nnormal = 0, ndead = 0; + // 閬嶅巻椤甸潰涓殑姣忎釜鍏冪粍 for (uint i = (OffsetNumber)1; i <= nline; i++) { ItemId lp = PageGetItemId(page, i); + // 濡傛灉鍏冪粍鏍囪涓烘甯 if (ItemIdIsNormal(lp)) { nnormal++; + // 瑙f瀽骞舵墦鍗板厓缁勫ご淇℃伅 ParseTupleHeader(page, i, strOutput); - } else if (ItemIdIsDead(lp)) { + } + // 濡傛灉鍏冪粍鏍囪涓烘浜 + else if (ItemIdIsDead(lp)) { ndead++; + // 濡傛灉鍏冪粍鏍囪涓烘浜 rc = snprintf_s(strOutput + (int)strlen(strOutput), MAXOUTPUTLEN, MAXOUTPUTLEN - 1, - "\n\n\t\tTuple #%u is dead: length %u, offset %u", i, ItemIdGetLength(lp), ItemIdGetOffset(lp)); + "\n\n\t\tTuple #%u is dead: length %u, offset %u", i, ItemIdGetLength(lp), + ItemIdGetOffset(lp)); securec_check_ss(rc, "\0", "\0"); - } else { + } + // 濡傛灉鍏冪粍鏍囪涓烘湭浣跨敤 + else { nunused++; + // 杈撳嚭鏈娇鐢ㄥ厓缁勭殑淇℃伅锛屽寘鎷紪鍙 rc = snprintf_s(strOutput + (int)strlen(strOutput), MAXOUTPUTLEN, MAXOUTPUTLEN - 1, - "\n\n\t\tTuple #%u is nunused: ", i); + "\n\n\t\tTuple #%u is nunused: ", i); securec_check_ss(rc, "\0", "\0"); } } - rc = snprintf_s(strOutput + (int)strlen(strOutput), MAXOUTPUTLEN, MAXOUTPUTLEN - 1, + // 杈撳嚭鍏冪粍鐨勬绘暟銆佹甯稿厓缁勬暟銆佹湭浣跨敤鍏冪粍鏁板拰姝讳骸鍏冪粍鏁扮殑姹囨讳俊鎭 + rc = snprintf_s( + strOutput + (int)strlen(strOutput), MAXOUTPUTLEN, MAXOUTPUTLEN - 1, "\n\tSummary (%u total): %u normal, %u unused, %u dead\n\nNormal Heap Page, special space is %u\n\n", nline, nnormal, nunused, ndead, (uint)PageGetSpecialSize(page)); securec_check_ss(rc, "\0", "\0"); } - +/* + * 鍔熻兘锛氳В鏋愬苟鎵撳嵃涓涓〉闈㈢殑淇℃伅锛屾牴鎹叧绯荤被鍨嬩笉鍚岄噰鐢ㄤ笉鍚岀殑瑙f瀽鏂瑰紡 + * + * 鍙傛暟鍒楄〃锛 + * page锛氶〉澶存寚閽堬紝鍖呭惈瑕佽В鏋愮殑椤甸潰鐨勪俊鎭 + * blockNum锛氬綋鍓嶉〉闈㈢殑鍧楃紪鍙 + * strOutput锛氱敤浜庡瓨鍌ㄨ緭鍑轰俊鎭殑缂撳啿鍖 + * relation_type锛氶〉闈㈡墍灞炵殑鍏崇郴绫诲瀷锛屽 "heap", "uheap", "btree" 绛 + * block_endpoint锛氬潡鐨勭粨鏉熶綅缃 + * + * 娉ㄦ剰浜嬮」锛 + * - 璇ュ嚱鏁版牴鎹叧绯荤被鍨嬮夋嫨涓嶅悓鐨勮В鏋愭柟寮忥紝鏀寔鐨勫叧绯荤被鍨嬪寘鎷 "heap", "uheap", "btree", "ubtree", "segment"銆 + * - 浣跨敤 strcmp 鍑芥暟姣旇緝鍏崇郴绫诲瀷锛屾牴鎹笉鍚岀被鍨嬮夋嫨鐩稿簲鐨勮В鏋愬嚱鏁般 + * - 濡傛灉鍏崇郴绫诲瀷涓嶅湪鏀寔鑼冨洿鍐咃紝灏嗕骇鐢熼敊璇姤鍛娿 + */ static void ParseOnePage(const PageHeader page, BlockNumber blockNum, char *strOutput, char *relation_type, - BlockNumber block_endpoint) + BlockNumber block_endpoint) { errno_t rc = EOK; + // 妫鏌ュ叧绯荤被鍨嬪苟鏍规嵁涓嶅悓绫诲瀷閫夋嫨鐩稿簲鐨勮В鏋愭柟寮 if (strcmp(relation_type, "heap") == 0) { + // 妫鏌ュ叧绯荤被鍨嬪苟鏍规嵁涓嶅悓绫诲瀷閫夋嫨鐩稿簲鐨勮В鏋愭柟寮 if (PG_HEAP_PAGE_LAYOUT_VERSION != (uint16)PageGetPageLayoutVersion(page) || PageGetSpecialSize(page) != 0) { + // 妫鏌ラ〉闈㈢殑甯冨眬鐗堟湰鍜岀壒娈婄┖闂村ぇ灏忥紝濡傛灉涓嶇鍚堥鏈燂紝浜х敓閿欒鎶ュ憡 ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - (errmsg("The target page is not heap, the given page version is: %u", - (uint16)PageGetPageLayoutVersion(page))))); + (errmsg("The target page is not heap, the given page version is: %u", + (uint16)PageGetPageLayoutVersion(page))))); } + // 璋冪敤瑙f瀽鍫嗛〉闈㈢殑鍑芥暟 ParseHeapPage(page, blockNum, strOutput, block_endpoint); } else if (strcmp(relation_type, "uheap") == 0) { + // 濡傛灉鏄棤閿佸爢鍏崇郴绫诲瀷 if (PG_UHEAP_PAGE_LAYOUT_VERSION != (uint16)PageGetPageLayoutVersion(page) || PageGetSpecialSize(page) != 0) { + // 妫鏌ラ〉闈㈢殑甯冨眬鐗堟湰鍜岀壒娈婄┖闂村ぇ灏忥紝濡傛灉涓嶇鍚堥鏈燂紝浜х敓閿欒鎶ュ憡 ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - (errmsg("The target page is not uheap, the given page version is: %u", - (uint16)PageGetPageLayoutVersion(page))))); + (errmsg("The target page is not uheap, the given page version is: %u", + (uint16)PageGetPageLayoutVersion(page))))); } + // 璋冪敤瑙f瀽鏃犻攣鍫嗛〉闈㈢殑鍑芥暟 ParseUHeapPage((void *)page, blockNum, block_endpoint, strOutput); } else if (strcmp(relation_type, "btree") == 0) { + // 濡傛灉鏄疊鏍戝叧绯荤被鍨 if (PG_COMM_PAGE_LAYOUT_VERSION != (uint16)PageGetPageLayoutVersion(page) || PageGetSpecialSize(page) == 0) { + // 妫鏌ラ〉闈㈢殑甯冨眬鐗堟湰鍜岀壒娈婄┖闂村ぇ灏忥紝濡傛灉涓嶇鍚堥鏈燂紝浜х敓閿欒鎶ュ憡 ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - (errmsg("The target page is not btree, the given page version is: %u", - (uint16)PageGetPageLayoutVersion(page))))); + (errmsg("The target page is not btree, the given page version is: %u", + (uint16)PageGetPageLayoutVersion(page))))); } + // 璋冪敤瑙f瀽B鏍戦〉闈㈢殑鍑芥暟 ParseIndexPage((void *)page, BTREE_INDEX, blockNum, block_endpoint, strOutput); } else if (strcmp(relation_type, "ubtree") == 0) { + // 濡傛灉鏄棤閿丅鏍戝叧绯荤被鍨 if (PG_COMM_PAGE_LAYOUT_VERSION != (uint16)PageGetPageLayoutVersion(page) || PageGetSpecialSize(page) == 0) { + // 妫鏌ラ〉闈㈢殑甯冨眬鐗堟湰鍜岀壒娈婄┖闂村ぇ灏忥紝濡傛灉涓嶇鍚堥鏈燂紝浜х敓閿欒鎶ュ憡 ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - (errmsg("The target page is not ubtree, the given page version is: %u", - (uint16)PageGetPageLayoutVersion(page))))); + (errmsg("The target page is not ubtree, the given page version is: %u", + (uint16)PageGetPageLayoutVersion(page))))); } + // 璋冪敤瑙f瀽鏃犻攣B鏍戦〉闈㈢殑鍑芥暟 ParseIndexPage((void *)page, UBTREE_INDEX, blockNum, block_endpoint, strOutput); } else if (strcmp(relation_type, "segment") == 0) { + // 濡傛灉鏄鍏崇郴绫诲瀷 rc = strcat_s(strOutput, MAXOUTPUTLEN, "Parse segment table."); securec_check(rc, "\0", "\0"); + // 璋冪敤瑙f瀽鍫嗛〉闈㈢殑鍑芥暟 ParseHeapPage(page, blockNum, strOutput, block_endpoint); } else { + // 濡傛灉鍏崇郴绫诲瀷涓嶅湪鏀寔鑼冨洿鍐咃紝浜х敓閿欒鎶ュ憡 ereport(ERROR, - (errcode(ERRCODE_UNDEFINED_PARAMETER), (errmsg("Only support heap, uheap, btree, ubtree, segment.")))); + (errcode(ERRCODE_UNDEFINED_PARAMETER), (errmsg("Only support heap, uheap, btree, ubtree, segment.")))); } } - +/* + * 鍔熻兘锛氭鏌MGR璇诲彇鐘舵侊紝鏍规嵁鐘舵佷笉鍚岀敓鎴愮浉搴旂殑杈撳嚭淇℃伅 + * + * 鍙傛暟鍒楄〃锛 + * rdStatus锛歋MGR璇诲彇鐘舵侊紝琛ㄧず璇诲彇椤甸潰鐨勭粨鏋滅姸鎬 + * blockNum锛氬綋鍓嶉〉闈㈢殑鍧楃紪鍙 + * page锛氶〉澶存寚閽堬紝鍖呭惈瑕佹鏌ョ殑椤甸潰鐨勪俊鎭 + * strOutput1锛氱敤浜庡瓨鍌ㄨ緭鍑轰俊鎭殑缂撳啿鍖 + * + * 娉ㄦ剰浜嬮」锛 + * - 璇ュ嚱鏁版牴鎹甋MGR璇诲彇鐘舵佺敓鎴愪笉鍚岀殑杈撳嚭淇℃伅锛屼富瑕佺敤浜庢鏌ラ〉闈㈢殑璇诲彇鐘舵併 + * - 濡傛灉SMGR璇诲彇鐘舵佷负SMGR_RD_CRC_ERROR锛岃〃绀洪〉闈㈡牎楠屽け璐ワ紝浼氳绠楁牎楠屽拰骞朵笌鏈熸湜鐨勬牎楠屽拰杩涜姣旇緝銆 + * - 濡傛灉SMGR璇诲彇鐘舵佷负SMGR_RD_NO_BLOCK锛岃〃绀洪〉闈笉瀛樺湪銆 + * - 杈撳嚭淇℃伅瀛樺偍鍦╯trOutput1缂撳啿鍖轰腑銆 + */ static void check_rdStatus(SMGR_READ_STATUS rdStatus, BlockNumber blockNum, const PageHeader page, char *strOutput1) { errno_t rc = EOK; if (rdStatus == SMGR_RD_CRC_ERROR) { + // 濡傛灉SMGR璇诲彇鐘舵佷负CRC鏍¢獙閿欒 uint16 checksum = pg_checksum_page((char *)page, blockNum); + // 鐢熸垚鍖呭惈鏍¢獙缁撴灉鐨勮緭鍑轰俊鎭 rc = snprintf_s(strOutput1, SHORTOUTPUTLEN, SHORTOUTPUTLEN - 1, "\nFor page %u, page verification failed, calculated checksum 0x%X but expected 0x%X.\n", blockNum, checksum, page->pd_checksum); securec_check_ss(rc, "\0", "\0"); } else if (rdStatus == SMGR_RD_NO_BLOCK) { + // 濡傛灉SMGR璇诲彇鐘舵佷负鏈壘鍒板潡 + // 鐢熸垚椤甸潰涓嶅瓨鍦ㄧ殑杈撳嚭淇℃伅 rc = snprintf_s(strOutput1, SHORTOUTPUTLEN, SHORTOUTPUTLEN - 1, "\tThe page %u does not exist.\n", blockNum); securec_check_ss(rc, "\0", "\0"); } } - +/* + * 鍔熻兘锛氫粠鍐呭瓨涓鍙栭〉闈㈠唴瀹癸紝濡傛灉椤甸潰鍦ㄥ唴瀛樹腑瀛樺湪锛屽垯鐢熸垚杈撳嚭淇℃伅骞惰繑鍥瀟rue锛涘惁鍒欒繑鍥瀎alse + * + * 鍙傛暟鍒楄〃锛 + * smgr锛歋MgrRelation缁撴瀯锛岃〃绀哄瓨鍌ㄧ鐞嗗櫒鍏崇郴 + * forkNum锛欶orkNumber锛岃〃绀洪〉闈㈡墍灞炵殑Fork绫诲瀷 + * blockNum锛欱lockNumber锛岃〃绀洪〉闈㈢殑鍧楃紪鍙 + * relation_type锛氬叧绯荤被鍨嬬殑瀛楃涓诧紝濡 "segment"銆"heap"銆"uheap" 绛 + * strOutput锛氱敤浜庡瓨鍌ㄨ緭鍑轰俊鎭殑缂撳啿鍖 + * outputfile锛氭枃浠舵寚閽堬紝鐢ㄤ簬杈撳嚭淇℃伅鍒版枃浠 + * outputFilename锛氳緭鍑烘枃浠剁殑鍚嶇О + * + * 娉ㄦ剰浜嬮」锛 + * - 璇ュ嚱鏁伴鍏堟鏌ラ〉闈㈡槸鍚﹀湪鍐呭瓨涓瓨鍦紝濡傛灉瀛樺湪鍒欑敓鎴愯緭鍑轰俊鎭紝骞惰繑鍥瀟rue锛涘惁鍒欒繑鍥瀎alse銆 + * - 濡傛灉椤甸潰鍦ㄥ唴瀛樹腑瀛樺湪锛屽嚱鏁颁細鏍规嵁鍏崇郴绫诲瀷璋冪敤涓嶅悓鐨勮В鏋愬嚱鏁扮敓鎴愯緭鍑轰俊鎭 + * - 鍑芥暟浼氫娇鐢ㄩ攣鏉ラ伩鍏嶅苟鍙戣/鍐欍 + * - 鐢熸垚鐨勮緭鍑轰俊鎭瓨鍌ㄥ湪strOutput缂撳啿鍖轰腑锛岀劧鍚庤緭鍑哄埌鏂囦欢涓 + * - 鍑芥暟杩斿洖true琛ㄧず鎴愬姛璇诲彇椤甸潰骞剁敓鎴愪簡杈撳嚭淇℃伅锛岃繑鍥瀎alse琛ㄧず椤甸潰涓嶅瓨鍦ㄦ垨璇诲彇澶辫触銆 + */ static bool readFromMemory(SMgrRelation smgr, ForkNumber forkNum, BlockNumber blockNum, char *relation_type, - char *strOutput, FILE *outputfile, char *outputFilename) + char *strOutput, FILE *outputfile, char *outputFilename) { errno_t rc = EOK; SegPageLocation loc; @@ -485,52 +691,101 @@ static bool readFromMemory(SMgrRelation smgr, ForkNumber forkNum, BlockNumber bl LWLockRelease(partition_lock); return false; } - +/* + * 鍔熻兘锛氭鏌ユ鏂囦欢鐨勬湁鏁堟у拰涓鑷存 + * + * 鍙傛暟鍒楄〃锛 + * relnode锛歊elFileNode 缁撴瀯锛岃〃绀烘鏂囦欢鐨勮妭鐐逛俊鎭 + * forkNum锛欶orkNumber锛岃〃绀烘鏂囦欢鐨凢ork绫诲瀷 + * + * 娉ㄦ剰浜嬮」锛 + * - 璇ュ嚱鏁扮敤浜庢鏌ユ鏂囦欢鐨勬湁鏁堟у拰涓鑷存э紝纭繚椤甸潰瀛樺湪锛屽苟涓旈〉澶翠笌娈电被鍨嬪尮閰嶃 + * - 濡傛灉娈垫枃浠朵笉瀛樺湪鎴栭〉闈笉鍖归厤锛屽垯鍑芥暟浼氭姏鍑洪敊璇 + */ static void CheckSegment(RelFileNode *relnode, ForkNumber forkNum) { SegSpace *spc = spc_open(relnode->spcNode, relnode->dbNode, false); + // 妫鏌ユ鏄惁瀛樺湪 if (spc == NULL || !spc_datafile_exist(spc, 1, forkNum)) ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), (errmsg("Page doesn't exist.")))); BlockNumber size = spc_size(spc, 1, forkNum); + // 妫鏌ョ洰鏍囬〉闈㈢紪鍙锋槸鍚﹀湪鏈夋晥鑼冨洿鍐 if (relnode->relNode >= size) - ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - (errmsg("The target page %u doesn't exist, the current max is %u.", relnode->relNode, size - 1)))); + ereport(ERROR, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + (errmsg("The target page %u doesn't exist, the current max is %u.", relnode->relNode, size - 1)))); + // 鍒涘缓鐢ㄤ簬璁块棶娈靛ご鐨凴elFileNode RelFileNode *relnodeHead = (RelFileNode *)palloc(sizeof(RelFileNode)); relnodeHead->spcNode = relnode->spcNode; relnodeHead->dbNode = relnode->dbNode; - relnodeHead->relNode = 1; + relnodeHead->relNode = 1; // 娈靛ご鐨勫潡缂栧彿涓1 relnodeHead->bucketNode = relnode->bucketNode; relnodeHead->opt = relnode->opt; + // 璇诲彇娈靛ご鐨勭紦鍐插尯 Buffer buffer_temp = ReadBufferFast(spc, *relnodeHead, forkNum, relnode->relNode, RBM_NORMAL); + // 妫鏌ユ澶寸紦鍐插尯鏄惁鏈夋晥 if (!BufferIsValid(buffer_temp)) - ereport(ERROR, (errcode_for_file_access(), errmsg("Segment Head is invalid %u/%u/%u %d %u", - relnodeHead->spcNode, relnodeHead->dbNode, relnodeHead->relNode, forkNum, relnode->relNode))); + ereport(ERROR, (errcode_for_file_access(), + errmsg("Segment Head is invalid %u/%u/%u %d %u", relnodeHead->spcNode, relnodeHead->dbNode, + relnodeHead->relNode, forkNum, relnode->relNode))); + // 閲婃斁娈靛ご缂撳啿鍖 pfree_ext(relnodeHead); SegmentHead *head = (SegmentHead *)PageGetContents(BufferGetPage(buffer_temp)); SegReleaseBuffer(buffer_temp); + // 妫鏌ユ澶存槸鍚﹀尮閰嶆绫诲瀷 if (!(IsNormalSegmentHead(head) && relnode->bucketNode == SegmentBktId) && !(IsBucketMainHead(head) && IsBucketFileNode(*relnode))) - ereport(ERROR, - (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - (errmsg("Page header does not match with corresponding segment type.")))); + ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + (errmsg("Page header does not match with corresponding segment type.")))); } - +/* + * 鍔熻兘锛氶獙璇佸弬鏁拌矾寰勪笌鏂囦欢璺緞鐨勪竴鑷存 + * + * 鍙傛暟鍒楄〃锛 + * rnode锛歊elFileNode 缁撴瀯锛岃〃绀烘枃浠剁殑鑺傜偣淇℃伅 + * str锛歝har 鎸囬拡锛岃〃绀鸿楠岃瘉鐨勬枃浠惰矾寰勫瓧绗︿覆 + * + * 娉ㄦ剰浜嬮」锛 + * - 璇ュ嚱鏁扮敤浜庨獙璇佸弬鏁拌矾寰勪笌瀹為檯鏂囦欢璺緞鏄惁涓鑷达紝濡傛灉涓嶄竴鑷村垯鎶涘嚭閿欒銆 + * - 鍑芥暟棣栧厛鏍规嵁 rnode 鏋勫缓瀹為檯鏂囦欢璺緞锛岀劧鍚庡皢鍏朵笌浼犲叆鐨 str 杩涜姣旇緝銆 + * - 濡傛灉涓嶄竴鑷达紝鍒欐姏鍑洪敊璇 + */ void ValidateParameterPath(RelFileNode rnode, char *str) { + // 鏍规嵁 rnode 鏋勫缓瀹為檯鏂囦欢璺緞 char *path = relpathbackend(rnode, InvalidBackendId, MAIN_FORKNUM); + // 妫鏌ュ弬鏁拌矾寰勪笌瀹為檯鏂囦欢璺緞鏄惁涓鑷达紝濡傛灉涓嶄竴鑷村垯鎶涘嚭閿欒 if ((strcmp(path, str) != 0)) ereport(ERROR, (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), errmsg("\"%s\" is invalid input", str))); } - +/* + * 鍔熻兘锛氳В鏋愭寚瀹氭枃浠剁殑涓涓垨澶氫釜椤甸潰锛岃緭鍑鸿В鏋愮粨鏋滃埌鏂囦欢 + * + * 鍙傛暟鍒楄〃锛 + * path锛歝har 鎸囬拡锛岃〃绀鸿瑙f瀽鐨勬枃浠惰矾寰 + * blocknum锛歩nt64锛岃〃绀鸿瑙f瀽鐨勯〉闈㈢殑鍧楀彿锛-1 琛ㄧず瑙f瀽鎵鏈夐〉闈 + * relation_type锛歝har 鎸囬拡锛岃〃绀烘枃浠剁殑鍏崇郴绫诲瀷 + * read_memory锛歜ool锛岃〃绀烘槸鍚﹀皾璇曚粠鍐呭瓨涓鍙栭〉闈 + * + * 娉ㄦ剰浜嬮」锛 + * - 璇ュ嚱鏁扮敤浜庤В鏋愭寚瀹氭枃浠剁殑涓涓垨澶氫釜椤甸潰锛岃緭鍑鸿В鏋愮粨鏋滃埌鏂囦欢銆 + * - 鍑芥暟棣栧厛楠岃瘉鍙傛暟锛岀劧鍚庡垵濮嬪寲涓浜涘繀瑕佺殑鏁版嵁缁撴瀯銆 + * - 濡傛灉鎸囧畾鐨勯〉闈㈠湪鍐呭瓨涓彲鐢ㄤ笖 read_memory 涓 true锛屽垯灏濊瘯浠庡唴瀛樹腑璇诲彇椤甸潰锛 + * 鍚﹀垯浠庣鐩樹腑璇诲彇椤甸潰銆 + * - 濡傛灉瑙f瀽鎵鏈夐〉闈紝鍒欏惊鐜鍙栧苟瑙f瀽鎵鏈夐〉闈€ + * - 鏈鍚庯紝鍑芥暟杩斿洖杈撳嚭缁撴灉鐨勬枃浠惰矾寰勩 + */ char *ParsePage(char *path, int64 blocknum, char *relation_type, bool read_memory) { + // 楠岃瘉鍙傛暟鏄惁鍚堟硶 errno_t rc = EOK; /* check parameters */ if (blocknum > MaxBlockNumber || blocknum < -1) ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - (errmsg("Blocknum should be between -1 and %u.", MaxBlockNumber)))); + (errmsg("Blocknum should be between -1 and %u.", MaxBlockNumber)))); /* initialize */ + // 鍒濆鍖栬緭鍑哄瓧绗︿覆鍜屾枃浠剁浉鍏崇殑鏁版嵁缁撴瀯 char *strOutput = (char *)palloc(MAXOUTPUTLEN * sizeof(char)); rc = memset_s(strOutput, MAXOUTPUTLEN, 0, MAXOUTPUTLEN); securec_check(rc, "\0", "\0"); @@ -541,6 +796,7 @@ char *ParsePage(char *path, int64 blocknum, char *relation_type, bool read_memor rc = memset_s(outputFilename, MAXFILENAME, 0, MAXFILENAME); securec_check(rc, "\0", "\0"); + // 鍑嗗瑙f瀽鎵闇鐨勬暟鎹 PrepForRead(path, blocknum, relation_type, outputFilename, relnode, true); ValidateParameterPath(*relnode, path); @@ -549,21 +805,25 @@ char *ParsePage(char *path, int64 blocknum, char *relation_type, bool read_memor ForkNumber forkNum = MAIN_FORKNUM; SMgrRelation smgr = smgropen(*relnode, InvalidBackendId, GetColumnNum(forkNum)); + // 閽堝鐗规畩鎯呭喌杩涜楠岃瘉 if (strcmp(relation_type, "segment") == 0) CheckSegment(relnode, forkNum); BlockNumber maxBlockNum = smgrnblocks(smgr, forkNum) - 1; + // 楠岃瘉 blocknum 鏄惁鍦ㄥ悎娉曡寖鍥村唴 if (blocknum > maxBlockNum) ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - (errmsg("Blocknum should be between -1 and %u.", maxBlockNum)))); + (errmsg("Blocknum should be between -1 and %u.", maxBlockNum)))); pfree_ext(relnode); BlockNumber blockNum = 0; BlockNumber block_endpoint = 0; /* only parse one block, check if it is in memory */ + // 濡傛灉 read_memory 涓 true锛屽垯灏濊瘯浠庡唴瀛樹腑璇诲彇椤甸潰 if (read_memory) { blockNum = (BlockNumber)blocknum; if (readFromMemory(smgr, forkNum, blockNum, relation_type, strOutput, outputfile, outputFilename)) { /* found in memory */ + // 浠庡唴瀛樹腑鎵惧埌椤甸潰锛屽叧闂枃浠跺苟杩斿洖 CheckCloseFile(fclose(outputfile), outputFilename); smgrcloseall(); return outputFilename; @@ -574,6 +834,7 @@ char *ParsePage(char *path, int64 blocknum, char *relation_type, bool read_memor securec_check(rc, "\0", "\0"); CheckWriteFile(fwrite(strOutput, 1, strlen(strOutput), outputfile), strlen(strOutput), outputFilename); pfree_ext(strOutput); + // 濡傛灉 blocknum >= 0锛屽彧瑙f瀽涓涓〉闈紝鍚﹀垯瑙f瀽鎵鏈夐〉闈 if (blocknum >= 0) { /* only parse one block */ blockNum = blocknum; block_endpoint = blocknum; @@ -581,19 +842,24 @@ char *ParsePage(char *path, int64 blocknum, char *relation_type, bool read_memor block_endpoint = maxBlockNum; } /* if not declare a single block, then loop all blocks */ + // 寰幆璇诲彇骞惰В鏋愰〉闈 while (blockNum <= block_endpoint) { char *strOutput = (char *)palloc(MAXOUTPUTLEN * sizeof(char)); rc = memset_s(strOutput, MAXOUTPUTLEN, 0, MAXOUTPUTLEN); securec_check(rc, "\0", "\0"); char *buffer = (char *)palloc0(BLCKSZ); + // 浠庣鐩樹腑璇诲彇椤甸潰 SMGR_READ_STATUS rdStatus = smgrread(smgr, forkNum, blockNum, buffer); const PageHeader page = (const PageHeader)buffer; char *strOutput1 = (char *)palloc(MAXOUTPUTLEN * sizeof(char)); rc = memset_s(strOutput1, SHORTOUTPUTLEN, 0, SHORTOUTPUTLEN); securec_check(rc, "\0", "\0"); + // 妫鏌ヨ鍙栭〉闈㈢殑鐘舵 check_rdStatus(rdStatus, blockNum, page, strOutput1); + // 灏嗚В鏋愮粨鏋滃啓鍏ユ枃浠 CheckWriteFile(fwrite(strOutput1, 1, strlen(strOutput1), outputfile), strlen(strOutput1), outputFilename); pfree_ext(strOutput1); + // 鏍规嵁鍏崇郴绫诲瀷瑙f瀽椤甸潰 if (strcmp(relation_type, "segment") == 0) { SegPageLocation loc = seg_get_physical_location(smgr->smgr_rnode.node, forkNum, blockNum); SegPageLocation endloc = seg_get_physical_location(smgr->smgr_rnode.node, forkNum, block_endpoint); @@ -601,16 +867,30 @@ char *ParsePage(char *path, int64 blocknum, char *relation_type, bool read_memor } else ParseOnePage(page, blockNum, strOutput, relation_type, block_endpoint); + // 灏嗚В鏋愮粨鏋滃啓鍏ユ枃浠 CheckWriteFile(fwrite(strOutput, 1, strlen(strOutput), outputfile), strlen(strOutput), outputFilename); pfree_ext(strOutput); pfree_ext(buffer); blockNum++; } + // 鍏抽棴鏂囦欢鍜岄噴鏀捐祫婧 CheckCloseFile(fclose(outputfile), outputFilename); smgrcloseall(); return outputFilename; } - +/* + * 鍔熻兘锛氳В鏋 UHeap 椤甸潰澶撮儴淇℃伅 + * + * 鍙傛暟鍒楄〃锛 + * page锛歷oid 鎸囬拡锛岃〃绀鸿瑙f瀽鐨勯〉闈 + * blkno锛欱lockNumber锛岃〃绀洪〉闈㈢殑鍧楀彿 + * endBlk锛欱lockNumber锛岃〃绀虹粨鏉熷潡鍙 + * output锛歝har 鎸囬拡锛岃〃绀鸿緭鍑鸿В鏋愮粨鏋滅殑瀛楃涓 + * + * 娉ㄦ剰浜嬮」锛 + * - 璇ュ嚱鏁扮敤浜庤В鏋 UHeap 椤甸潰鐨勫ご閮ㄤ俊鎭紝鍖呮嫭椤甸潰鐨勫悇绉嶅睘鎬с + * - 鍑芥暟灏嗚В鏋愮粨鏋滆緭鍑哄埌鎸囧畾鐨勫瓧绗︿覆 `output` 涓 + */ static void ParseUHeapPageHeader(void *page, BlockNumber blkno, BlockNumber endBlk, char *output) { errno_t rc = EOK; @@ -621,23 +901,28 @@ static void ParseUHeapPageHeader(void *page, BlockNumber blkno, BlockNumber endB return; } + // 灏嗚緭鍏ョ殑椤甸潰杞崲涓 UHeapPageHeader 绫诲瀷 pageHeader = (UHeapPageHeader)page; + // 杈撳嚭椤甸潰鍧楀彿淇℃伅 rc = snprintf_s(output + (int)strlen(output), MAXOUTPUTLEN, MAXOUTPUTLEN, "Page information of block %u/%u\n", - blkno, endBlk); + blkno, endBlk); securec_check_ss(rc, "\0", "\0"); + // 杈撳嚭 LSN 淇℃伅 rc = snprintf_s(output + (int)strlen(output), MAXOUTPUTLEN, MAXOUTPUTLEN, "\tpd_lsn: %X/%X\n", - (uint32)(PageGetLSN(pageHeader) >> XIDTHIRTYTWO), (uint32)PageGetLSN(pageHeader)); + (uint32)(PageGetLSN(pageHeader) >> XIDTHIRTYTWO), (uint32)PageGetLSN(pageHeader)); securec_check_ss(rc, "\0", "\0"); + // 濡傛灉椤甸潰鐨勬牎楠屽拰涓嶄负绌猴紝楠岃瘉鏍¢獙鍜 if (CheckPageZeroCases((PageHeader)pageHeader)) { uint16 checksum = pg_checksum_page((char *)pageHeader, (BlockNumber)blkno); chksumResult = (checksum == pageHeader->pd_checksum); } rc = snprintf_s(output + (int)strlen(output), MAXOUTPUTLEN, MAXOUTPUTLEN, "\tpd_checksum: 0x%X, verify %s\n", - pageHeader->pd_checksum, chksumResult ? "success" : "fail"); + pageHeader->pd_checksum, chksumResult ? "success" : "fail"); securec_check_ss(rc, "\0", "\0"); + // 杈撳嚭椤甸潰鐨勫叾浠栧睘鎬т俊鎭 if (UPageHasFreeLinePointers(pageHeader)) { rc = snprintf_s(output + (int)strlen(output), MAXOUTPUTLEN, MAXOUTPUTLEN, "PAGE_HAS_FREE_LINES."); securec_check_ss(rc, "\0", "\0"); @@ -649,27 +934,39 @@ static void ParseUHeapPageHeader(void *page, BlockNumber blkno, BlockNumber endB } rc = snprintf_s(output + (int)strlen(output), MAXOUTPUTLEN, MAXOUTPUTLEN, - "\tpd_lower: %u, %s\n\tpd_upper: %u, %s\n\tpd_special: %u, size %u\n", pageHeader->pd_lower, - PageIsEmpty(pageHeader) ? "empty" : "non-empty", pageHeader->pd_upper, - PageIsNew(pageHeader) ? "new page" : "old page", pageHeader->pd_special, PageGetSpecialSize(pageHeader)); + "\tpd_lower: %u, %s\n\tpd_upper: %u, %s\n\tpd_special: %u, size %u\n", pageHeader->pd_lower, + PageIsEmpty(pageHeader) ? "empty" : "non-empty", pageHeader->pd_upper, + PageIsNew(pageHeader) ? "new page" : "old page", pageHeader->pd_special, + PageGetSpecialSize(pageHeader)); securec_check_ss(rc, "\0", "\0"); rc = snprintf_s(output + (int)strlen(output), MAXOUTPUTLEN, MAXOUTPUTLEN, "\tPage size & version: %u, %u\n", - (uint16)PageGetPageSize(pageHeader), (uint16)PageGetPageLayoutVersion(pageHeader)); + (uint16)PageGetPageSize(pageHeader), (uint16)PageGetPageLayoutVersion(pageHeader)); securec_check_ss(rc, "\0", "\0"); rc = snprintf_s(output + (int)strlen(output), MAXOUTPUTLEN, MAXOUTPUTLEN, "\tpotential_freespace: %u\n", - pageHeader->potential_freespace); + pageHeader->potential_freespace); securec_check_ss(rc, "\0", "\0"); rc = snprintf_s(output + (int)strlen(output), MAXOUTPUTLEN, MAXOUTPUTLEN, "\ttd_count: %u\n", pageHeader->td_count); securec_check_ss(rc, "\0", "\0"); rc = snprintf_s(output + (int)strlen(output), MAXOUTPUTLEN, MAXOUTPUTLEN, "\tpd_prune_xid: %lu\n", - pageHeader->pd_prune_xid); + pageHeader->pd_prune_xid); securec_check_ss(rc, "\0", "\0"); rc = snprintf_s(output + (int)strlen(output), MAXOUTPUTLEN, MAXOUTPUTLEN, - "\tpd_xid_base: %lu, pd_multi_base: %lu\n", pageHeader->pd_xid_base, pageHeader->pd_multi_base); + "\tpd_xid_base: %lu, pd_multi_base: %lu\n", pageHeader->pd_xid_base, pageHeader->pd_multi_base); securec_check_ss(rc, "\0", "\0"); return; } - +/* + * 鍔熻兘锛氳В鏋 UHeap 椤甸潰涓殑 TD锛圱ransaction Delta锛変俊鎭 + * + * 鍙傛暟鍒楄〃锛 + * page锛歷oid 鎸囬拡锛岃〃绀鸿瑙f瀽鐨勯〉闈 + * output锛歝har 鎸囬拡锛岃〃绀鸿緭鍑鸿В鏋愮粨鏋滅殑瀛楃涓 + * + * 娉ㄦ剰浜嬮」锛 + * - 璇ュ嚱鏁扮敤浜庤В鏋 UHeap 椤甸潰涓殑 TD 淇℃伅锛屽寘鎷 TD Slot 鐨勬暟閲忋佹瘡涓 TD Slot 鐨勪簨鍔 + * ID锛坸id锛夊拰鎾ら攢璁板綍鎸囬拡锛坲ndo_record_ptr锛夈 + * - 鍑芥暟灏嗚В鏋愮粨鏋滆緭鍑哄埌鎸囧畾鐨勫瓧绗︿覆 `output` 涓 + */ static void ParseUHeapPageTDInfo(void *page, char *output) { TD *tdInfo = NULL; @@ -682,37 +979,56 @@ static void ParseUHeapPageTDInfo(void *page, char *output) return; } + // 灏嗚緭鍏ョ殑椤甸潰杞崲涓 UHeapPageHeader 绫诲瀷 pageHeader = (UHeapPageHeader)page; + // 鑾峰彇椤甸潰涓殑 TD 淇℃伅 tdPtr = (UHeapPageTDData *)PageGetTDPointer(page); tdCount = pageHeader->td_count; + // 杈撳嚭 TD 淇℃伅鐨勬爣棰 rc = snprintf_s(output + (int)strlen(output), MAXOUTPUTLEN, MAXOUTPUTLEN, - "\n\n\tUHeap Page TD information, nTDSlots = %u\n", tdCount); + "\n\n\tUHeap Page TD information, nTDSlots = %u\n", tdCount); securec_check_ss(rc, "\0", "\0"); + // 閬嶅巻姣忎釜 TD Slot锛岃緭鍑轰簨鍔 ID锛坸id锛夊拰鎾ら攢璁板綍鎸囬拡锛坲ndo_record_ptr锛 for (uint16 i = 0; i < tdCount; i++) { tdInfo = &(tdPtr->td_info[i]); rc = snprintf_s(output + (int)strlen(output), MAXOUTPUTLEN, MAXOUTPUTLEN, - "\n\t\t TD Slot #%d, xid:%lu, urp:%lu\n", i + 1, tdInfo->xactid, tdInfo->undo_record_ptr); + "\n\t\t TD Slot #%d, xid:%lu, urp:%lu\n", i + 1, tdInfo->xactid, tdInfo->undo_record_ptr); securec_check_ss(rc, "\0", "\0"); } return; } - +/* + * 鍔熻兘锛氳В鏋 UHeap 椤甸潰涓殑椤癸紙item锛変俊鎭 + * + * 鍙傛暟鍒楄〃锛 + * item锛欼tem锛岃〃绀鸿瑙f瀽鐨勯」 + * tuple锛歎HeapTuple锛岃〃绀 UHeap 鍏冪粍 + * output锛歝har 鎸囬拡锛岃〃绀鸿緭鍑鸿В鏋愮粨鏋滅殑瀛楃涓 + * + * 娉ㄦ剰浜嬮」锛 + * - 璇ュ嚱鏁扮敤浜庤В鏋 UHeap 椤甸潰涓殑椤癸紝鍖呮嫭椤圭殑灞炴у浜嬪姟 ID锛坸id锛夈侀攣瀹氳呯殑 TD锛圱ransaction Delta锛塈D 绛夈 + * - 鍑芥暟灏嗚В鏋愮粨鏋滆緭鍑哄埌鎸囧畾鐨勫瓧绗︿覆 `output` 涓 + */ static void ParseUHeapPageItem(Item item, UHeapTuple tuple, char *output) { if (item == NULL || tuple == NULL || output == NULL) { return; } + // 灏嗚緭鍏ョ殑椤硅浆鎹负 UHeapDiskTuple 绫诲瀷 UHeapDiskTuple diskTuple = (UHeapDiskTuple)item; errno_t rc = EOK; + // 灏嗗厓缁勭殑 disk_tuple 鎸囬拡璁剧疆涓鸿В鏋愬悗鐨 UHeapDiskTuple tuple->disk_tuple = diskTuple; + // 杈撳嚭椤圭殑淇℃伅锛屽寘鎷簨鍔 ID锛坸id锛夈乀D ID銆侀攣瀹氳 TD ID 绛 rc = snprintf_s(output + (int)strlen(output), MAXOUTPUTLEN, MAXOUTPUTLEN, "\t\t\txid:%lu, td:%d, locker_td %d\n", - UHeapTupleGetRawXid(tuple), diskTuple->td_id, diskTuple->locker_td_id); + UHeapTupleGetRawXid(tuple), diskTuple->td_id, diskTuple->locker_td_id); securec_check_ss(rc, "\0", "\0"); rc = snprintf_s(output + (int)strlen(output), MAXOUTPUTLEN, MAXOUTPUTLEN, "\t\t\tFlag:%u", diskTuple->flag); securec_check_ss(rc, "\0", "\0"); + // 妫鏌ラ」鐨勬爣蹇楀苟杈撳嚭鐩稿簲鐨勪俊鎭 if (diskTuple->flag & UHEAP_HAS_NULL) { rc = snprintf_s(output + (int)strlen(output), MAXOUTPUTLEN, MAXOUTPUTLEN, "\n\t\t\tUHEAP_HASNULL"); securec_check_ss(rc, "\0", "\0"); @@ -755,20 +1071,31 @@ static void ParseUHeapPageItem(Item item, UHeapTuple tuple, char *output) } if (diskTuple->flag & SINGLE_LOCKER_XID_IS_SUBXACT) { rc = snprintf_s(output + (int)strlen(output), MAXOUTPUTLEN, MAXOUTPUTLEN, - "\n\t\t\tSINGLE_LOCKER_XID_IS_SUBXACT "); + "\n\t\t\tSINGLE_LOCKER_XID_IS_SUBXACT "); securec_check_ss(rc, "\0", "\0"); } rc = snprintf_s(output + (int)strlen(output), MAXOUTPUTLEN, MAXOUTPUTLEN, "\n\t\t\tFlag2:"); securec_check_ss(rc, "\0", "\0"); + // 杈撳嚭椤圭殑灞炴э紝鍖呮嫭鍒楁暟鍜 Hoff 鍊 rc = snprintf_s(output + (int)strlen(output), MAXOUTPUTLEN, MAXOUTPUTLEN, "\n\t\t\tNumber of columns:: %d\n", - UHeapTupleHeaderGetNatts(diskTuple)); + UHeapTupleHeaderGetNatts(diskTuple)); securec_check_ss(rc, "\0", "\0"); rc = snprintf_s(output + (int)strlen(output), MAXOUTPUTLEN, MAXOUTPUTLEN, "\t\t\tHoff: %u\n", diskTuple->t_hoff); securec_check_ss(rc, "\0", "\0"); return; } - +/* + * 鍔熻兘锛氳В鏋 UHeap 椤甸潰涓婄殑鏁版嵁锛屽寘鎷 UHeap 鍏冪粍鐨勪俊鎭 + * + * 鍙傛暟鍒楄〃锛 + * page锛歷oid 鎸囬拡锛岃〃绀 UHeap 椤甸潰鐨勬寚閽 + * output锛歝har 鎸囬拡锛岃〃绀鸿緭鍑鸿В鏋愮粨鏋滅殑瀛楃涓 + * + * 娉ㄦ剰浜嬮」锛 + * - 璇ュ嚱鏁扮敤浜庤В鏋 UHeap 椤甸潰涓婄殑鏁版嵁锛屽寘鎷悇涓 UHeap 鍏冪粍鐨勪俊鎭紝濡傚瓨鍌ㄧ姸鎬併侀暱搴︺佸亸绉荤瓑銆 + * - 鍑芥暟灏嗚В鏋愮粨鏋滆緭鍑哄埌鎸囧畾鐨勫瓧绗︿覆 `output` 涓 + */ static void ParseUHeapPageData(void *page, char *output) { errno_t rc; @@ -787,7 +1114,9 @@ static void ParseUHeapPageData(void *page, char *output) return; } + // 灏嗚緭鍏ョ殑椤甸潰鎸囬拡杞崲涓 UHeapPageHeader 绫诲瀷 pageHeader = (UHeapPageHeader)page; + // 璁$畻琛屾寚閽堬紙RowPtr锛夌殑鏁伴噺 if (pageHeader->pd_lower <= SizeOfUHeapPageHeaderData) { rowPtrCnt = 0; } else { @@ -796,9 +1125,10 @@ static void ParseUHeapPageData(void *page, char *output) } rc = snprintf_s(output + (int)strlen(output), MAXOUTPUTLEN, MAXOUTPUTLEN, - "\n\tUHeap tuple information on this page\n"); + "\n\tUHeap tuple information on this page\n"); securec_check_ss(rc, "\0", "\0"); + // 閬嶅巻 UHeap 椤甸潰涓婄殑姣忎釜琛屾寚閽 for (uint32 i = FirstOffsetNumber; i <= rowPtrCnt; i++) { rowptr = UPageGetRowPtr(pageHeader, i); if (RowPtrIsUsed(rowptr)) { @@ -807,38 +1137,54 @@ static void ParseUHeapPageData(void *page, char *output) } if (RowPtrIsNormal(rowptr)) { + // 濡傛灉琛屾寚閽堟爣蹇椾负姝e父锛坣ormal锛夛紝鍒欒В鏋愮浉搴旂殑 UHeap 鍏冪粍淇℃伅 rc = snprintf_s(output + (int)strlen(output), MAXOUTPUTLEN, MAXOUTPUTLEN, - "\n\t\tTuple #%u is normal: length %u, offset %u\n", i, RowPtrGetLen(rowptr), - RowPtrGetOffset(rowptr)); + "\n\t\tTuple #%u is normal: length %u, offset %u\n", i, RowPtrGetLen(rowptr), + RowPtrGetOffset(rowptr)); securec_check_ss(rc, "\0", "\0"); normalCnt++; + // 鑾峰彇鍏冪粍鏁版嵁椤癸紝骞惰繘琛岃В鏋 item = UPageGetRowData(pageHeader, rowptr); UHeapTupleCopyBaseFromPage(&utuple, pageHeader); ParseUHeapPageItem(item, &utuple, output); } else if (RowPtrIsDead(rowptr)) { + // 濡傛灉琛屾寚閽堟爣蹇椾负宸插垹闄わ紙dead锛夛紝鍒欒緭鍑虹浉搴斾俊鎭 rc = snprintf_s(output + (int)strlen(output), MAXOUTPUTLEN, MAXOUTPUTLEN, - "\n\t\tTuple #%u is dead: length %u, offset %u", i, RowPtrGetLen(rowptr), RowPtrGetOffset(rowptr)); + "\n\t\tTuple #%u is dead: length %u, offset %u", i, RowPtrGetLen(rowptr), + RowPtrGetOffset(rowptr)); securec_check_ss(rc, "\0", "\0"); deadCnt++; } else { + // 鍚﹀垯锛岃鎸囬拡鏍囧織涓洪噸瀹氬悜锛坮edirect锛夛紝杈撳嚭鐩稿簲淇℃伅 rc = snprintf_s(output + (int)strlen(output), MAXOUTPUTLEN, MAXOUTPUTLEN, - "\n\t\tTuple #%u is redirected: length %u, offset %u", i, RowPtrGetLen(rowptr), - RowPtrGetOffset(rowptr)); + "\n\t\tTuple #%u is redirected: length %u, offset %u", i, RowPtrGetLen(rowptr), + RowPtrGetOffset(rowptr)); securec_check_ss(rc, "\0", "\0"); redirectCnt++; } } else { + // 琛屾寚閽堟湭浣跨敤锛岃緭鍑虹浉搴斾俊鎭 unusedCnt++; rc = snprintf_s(output + (int)strlen(output), MAXOUTPUTLEN, MAXOUTPUTLEN, "\n\t\tTuple #%u is unused\n", i); securec_check_ss(rc, "\0", "\0"); } } + // 杈撳嚭 UHeap 椤甸潰鏁版嵁鐨勬眹鎬讳俊鎭紝鍖呮嫭鏈娇鐢ㄣ佹甯搞佸凡鍒犻櫎鍜岄噸瀹氬悜鐨勫厓缁勬暟閲 rc = snprintf_s(output + (int)strlen(output), MAXOUTPUTLEN, MAXOUTPUTLEN, - "\tSummary (%u total): %u unused, %u normal, %u dead, %u redirect\n", rowPtrCnt, unusedCnt, normalCnt, deadCnt, - redirectCnt); + "\tSummary (%u total): %u unused, %u normal, %u dead, %u redirect\n", rowPtrCnt, unusedCnt, + normalCnt, deadCnt, redirectCnt); securec_check_ss(rc, "\0", "\0"); } - +/* + * 鍔熻兘锛氳В鏋 UHeap 椤甸潰涓婄殑鐗规畩淇℃伅 + * + * 鍙傛暟鍒楄〃锛 + * page锛歷oid 鎸囬拡锛岃〃绀 UHeap 椤甸潰鐨勬寚閽 + * output锛歝har 鎸囬拡锛岃〃绀鸿緭鍑鸿В鏋愮粨鏋滅殑瀛楃涓 + * + * 娉ㄦ剰浜嬮」锛 + * - 璇ュ嚱鏁扮敤浜庤В鏋 UHeap 椤甸潰涓婄殑鐗规畩淇℃伅锛屼絾褰撳墠鐗堟湰鏈娇鐢ㄧ壒娈婁俊鎭紝鍥犳杈撳嚭 "Not used currently."銆 + */ static void ParseUHeapPageSpecialInfo(void *page, char *output) { errno_t rc = 0; @@ -847,13 +1193,27 @@ static void ParseUHeapPageSpecialInfo(void *page, char *output) return; } + // 杈撳嚭鐗规畩淇℃伅閮ㄥ垎鐨勬爣棰 rc = snprintf_s(output + (int)strlen(output), MAXOUTPUTLEN, MAXOUTPUTLEN, - "\n\tSpecial area information on this page\n"); + "\n\tSpecial area information on this page\n"); securec_check_ss(rc, "\0", "\0"); + // 杈撳嚭鐗规畩淇℃伅鐨勫叿浣撳唴瀹癸紝褰撳墠鐗堟湰鏈娇鐢ㄧ壒娈婁俊鎭紝鍥犳杈撳嚭鎻愮ず淇℃伅 rc = snprintf_s(output + (int)strlen(output), MAXOUTPUTLEN, MAXOUTPUTLEN, "\n\tNot used currently.\n"); securec_check_ss(rc, "\0", "\0"); } - +/* + * 鍔熻兘锛氳В鏋 UHeap 椤甸潰鐨勫悇涓儴鍒嗕俊鎭 + * + * 鍙傛暟鍒楄〃锛 + * page锛歷oid 鎸囬拡锛岃〃绀 UHeap 椤甸潰鐨勬寚閽 + * blkno锛欱lockNumber锛岃〃绀哄綋鍓嶅鐞嗙殑鍧楀彿 + * endBlk锛欱lockNumber锛岃〃绀虹粨鏉熺殑鍧楀彿 + * output锛歝har 鎸囬拡锛岃〃绀鸿緭鍑鸿В鏋愮粨鏋滅殑瀛楃涓 + * + * 娉ㄦ剰浜嬮」锛 + * - 璇ュ嚱鏁扮敤浜庤В鏋 UHeap 椤甸潰鐨勫悇涓儴鍒嗕俊鎭紝鍖呮嫭椤甸潰澶淬乀D slot 淇℃伅銆佸厓缁勬暟鎹拰鐗规畩鍖哄煙銆 + * - 濡傛灉椤甸潰鏁版嵁涓嶅悎娉曟垨宸茶鏍囪涓烘柊椤甸潰锛屽垯鍙В鏋愰〉闈㈠ご閮ㄥ垎銆 + */ static void ParseUHeapPage(void *page, BlockNumber blkno, BlockNumber endBlk, char *output) { uint16 pageHeaderSize = 0; @@ -873,8 +1233,8 @@ static void ParseUHeapPage(void *page, BlockNumber blkno, BlockNumber endBlk, ch pageHeader->pd_upper > pageHeader->pd_special || pageHeader->pd_special > BLCKSZ || pageHeader->pd_special != MAXALIGN(pageHeader->pd_special)) { rc = snprintf_s(output + (int)strlen(output), MAXOUTPUTLEN, MAXOUTPUTLEN, - "The page data is corrupted, corrupted page pointers: lower = %u, upper = %u, special = %u\n", - pageHeader->pd_lower, pageHeader->pd_upper, pageHeader->pd_special); + "The page data is corrupted, corrupted page pointers: lower = %u, upper = %u, special = %u\n", + pageHeader->pd_lower, pageHeader->pd_upper, pageHeader->pd_special); securec_check_ss(rc, "\0", "\0"); return; } @@ -891,7 +1251,19 @@ static void ParseUHeapPage(void *page, BlockNumber blkno, BlockNumber endBlk, ch /* Parse special area of uheap page. */ ParseUHeapPageSpecialInfo(pageHeader, output); } - +/* + * 鍔熻兘锛氳В鏋愮储寮曢〉鐨勫ご閮ㄤ俊鎭 + * + * 鍙傛暟鍒楄〃锛 + * page锛歷oid 鎸囬拡锛岃〃绀虹储寮曢〉鐨勬寚閽 + * type锛歩nt锛岃〃绀虹储寮曠殑绫诲瀷锛圔TREE_INDEX 鎴 UBtree锛 + * blkno锛欱lockNumber锛岃〃绀哄綋鍓嶅鐞嗙殑鍧楀彿 + * endBlk锛欱lockNumber锛岃〃绀虹粨鏉熺殑鍧楀彿 + * output锛歝har 鎸囬拡锛岃〃绀鸿緭鍑鸿В鏋愮粨鏋滅殑瀛楃涓 + * + * 娉ㄦ剰浜嬮」锛 + * - 璇ュ嚱鏁扮敤浜庤В鏋愮储寮曢〉鐨勫ご閮ㄤ俊鎭紝鍖呮嫭椤甸潰澶淬佹牎楠屽拰銆佹爣蹇椾綅绛夈 + */ static void ParseIndexPageHeader(void *page, int type, BlockNumber blkno, BlockNumber endBlk, char *output) { errno_t rc = 0; @@ -904,10 +1276,11 @@ static void ParseIndexPageHeader(void *page, int type, BlockNumber blkno, BlockN pageHeader = (PageHeader)page; rc = snprintf_s(output + (int)strlen(output), MAXOUTPUTLEN, MAXOUTPUTLEN, - "%s index page information of block %u/%u\n", (type == BTREE_INDEX) ? "Btree" : "UBtree", blkno, endBlk); + "%s index page information of block %u/%u\n", (type == BTREE_INDEX) ? "Btree" : "UBtree", blkno, + endBlk); securec_check_ss(rc, "\0", "\0"); rc = snprintf_s(output + (int)strlen(output), MAXOUTPUTLEN, MAXOUTPUTLEN, "\tpd_lsn: %X/%X\n", - (uint32)(PageGetLSN((Page)pageHeader) >> XIDTHIRTYTWO), (uint32)PageGetLSN((Page)pageHeader)); + (uint32)(PageGetLSN((Page)pageHeader) >> XIDTHIRTYTWO), (uint32)PageGetLSN((Page)pageHeader)); securec_check_ss(rc, "\0", "\0"); if (CheckPageZeroCases(pageHeader)) { @@ -916,7 +1289,7 @@ static void ParseIndexPageHeader(void *page, int type, BlockNumber blkno, BlockN } rc = snprintf_s(output + (int)strlen(output), MAXOUTPUTLEN, MAXOUTPUTLEN, "\tpd_checksum: 0x%X, verify %s\n", - pageHeader->pd_checksum, chksumResult ? "success" : "fail"); + pageHeader->pd_checksum, chksumResult ? "success" : "fail"); securec_check_ss(rc, "\0", "\0"); if (PageHasFreeLinePointers((Page)pageHeader)) { @@ -945,25 +1318,37 @@ static void ParseIndexPageHeader(void *page, int type, BlockNumber blkno, BlockN } rc = snprintf_s(output + (int)strlen(output), MAXOUTPUTLEN, MAXOUTPUTLEN, - "\tpd_lower: %u, %s\n\tpd_upper: %u, %s\n\tpd_special: %u, size %u\n", pageHeader->pd_lower, - PageIsEmpty((Page)pageHeader) ? "empty" : "non-empty", pageHeader->pd_upper, - PageIsNew((Page)pageHeader) ? "new page" : "old page", pageHeader->pd_special, - PageGetSpecialSize((Page)pageHeader)); + "\tpd_lower: %u, %s\n\tpd_upper: %u, %s\n\tpd_special: %u, size %u\n", pageHeader->pd_lower, + PageIsEmpty((Page)pageHeader) ? "empty" : "non-empty", pageHeader->pd_upper, + PageIsNew((Page)pageHeader) ? "new page" : "old page", pageHeader->pd_special, + PageGetSpecialSize((Page)pageHeader)); securec_check_ss(rc, "\0", "\0"); rc = snprintf_s(output + (int)strlen(output), MAXOUTPUTLEN, MAXOUTPUTLEN, "\tPage size & version: %u, %u\n", - (uint16)PageGetPageSize(page), (uint16)PageGetPageLayoutVersion(page)); + (uint16)PageGetPageSize(page), (uint16)PageGetPageLayoutVersion(page)); securec_check_ss(rc, "\0", "\0"); rc = snprintf_s(output + (int)strlen(output), MAXOUTPUTLEN, MAXOUTPUTLEN, "\tpd_prune_xid: %lu\n", - pageHeader->pd_prune_xid + ((HeapPageHeader)(pageHeader))->pd_xid_base); + pageHeader->pd_prune_xid + ((HeapPageHeader)(pageHeader))->pd_xid_base); securec_check_ss(rc, "\0", "\0"); rc = snprintf_s(output + (int)strlen(output), MAXOUTPUTLEN, MAXOUTPUTLEN, "\tpd_xid_base: %lu, pd_multi_base: %lu\n", - ((HeapPageHeader)(pageHeader))->pd_xid_base, ((HeapPageHeader)(pageHeader))->pd_multi_base); + ((HeapPageHeader)(pageHeader))->pd_xid_base, ((HeapPageHeader)(pageHeader))->pd_multi_base); securec_check_ss(rc, "\0", "\0"); return; } - +/* + * 鍔熻兘锛氳В鏋愮储寮曢〉涓殑椤圭洰淇℃伅 + * + * 鍙傛暟鍒楄〃锛 + * item锛欼tem锛岃〃绀虹储寮曢」鐨勬寚閽 + * type锛歩nt锛岃〃绀虹储寮曠殑绫诲瀷锛圔TREE_INDEX 鎴 UBTREE_INDEX锛 + * len锛歶int32锛岃〃绀虹储寮曢」鐨勯暱搴 + * output锛歝har 鎸囬拡锛岃〃绀鸿緭鍑鸿В鏋愮粨鏋滅殑瀛楃涓 + * + * 娉ㄦ剰浜嬮」锛 + * - 璇ュ嚱鏁扮敤浜庤В鏋愮储寮曢〉涓殑绱㈠紩椤逛俊鎭紝鍖呮嫭鏄惁鍖呭惈 NULL 鍊笺佹槸鍚﹀寘鍚彲鍙橀暱搴﹀睘鎬х瓑銆 + * - 濡傛灉绱㈠紩椤归暱搴︿笌缁欏畾鐨 len 涓嶅尮閰嶏紝鍒欒緭鍑洪檮鍔犱俊鎭紙瀵逛簬 UBTREE_INDEX 绫诲瀷锛夈 + */ static void ParseIndexPageItem(Item item, int type, uint32 len, char *output) { if (item == NULL || output == NULL) { @@ -978,14 +1363,14 @@ static void ParseIndexPageItem(Item item, int type, uint32 len, char *output) if (type == UBTREE_INDEX) { UstoreIndexXid uxid = (UstoreIndexXid)UstoreIndexTupleGetXid(itup); rc = snprintf_s(output + (int)strlen(output), MAXOUTPUTLEN, MAXOUTPUTLEN, - "\t\t\txmin:%d xmax:%d Heap Tid: block %u/%u, offset %u\n", uxid->xmin, uxid->xmax, - itup->t_tid.ip_blkid.bi_hi, itup->t_tid.ip_blkid.bi_lo, itup->t_tid.ip_posid); + "\t\t\txmin:%d xmax:%d Heap Tid: block %u/%u, offset %u\n", uxid->xmin, uxid->xmax, + itup->t_tid.ip_blkid.bi_hi, itup->t_tid.ip_blkid.bi_lo, itup->t_tid.ip_posid); securec_check_ss(rc, "\0", "\0"); } } else { rc = snprintf_s(output + (int)strlen(output), MAXOUTPUTLEN, MAXOUTPUTLEN, - "\t\t\tHeap Tid: block %u/%u, offset %u\n", itup->t_tid.ip_blkid.bi_hi, itup->t_tid.ip_blkid.bi_lo, - itup->t_tid.ip_posid); + "\t\t\tHeap Tid: block %u/%u, offset %u\n", itup->t_tid.ip_blkid.bi_hi, + itup->t_tid.ip_blkid.bi_lo, itup->t_tid.ip_posid); securec_check_ss(rc, "\0", "\0"); } @@ -1006,7 +1391,20 @@ static void ParseIndexPageItem(Item item, int type, uint32 len, char *output) securec_check_ss(rc, "\0", "\0"); return; } - +/* + * 鍔熻兘锛氳В鏋愮储寮曢〉鐨勭壒娈婁俊鎭 + * + * 鍙傛暟鍒楄〃锛 + * page锛歷oid 鎸囬拡锛岃〃绀虹储寮曢〉鐨勬暟鎹 + * type锛歩nt锛岃〃绀虹储寮曠殑绫诲瀷锛圔TREE_INDEX 鎴 UBTREE_INDEX锛 + * output锛歝har 鎸囬拡锛岃〃绀鸿緭鍑鸿В鏋愮粨鏋滅殑瀛楃涓 + * + * 娉ㄦ剰浜嬮」锛 + * - 璇ュ嚱鏁扮敤浜庤В鏋愮储寮曢〉鐨勭壒娈婁俊鎭紝鍖呮嫭 BTree 鎴 UBTree 鐨勭壒鏈変俊鎭 + * - 杈撳嚭鍖呮嫭宸﹀厔寮熼〉鍙枫佸彸鍏勫紵椤靛彿銆佹爲鐨勭骇鍒佹爣蹇椾綅銆佸惊鐜 ID 绛夈 + * - 濡傛灉绱㈠紩椤佃鏍囪涓哄凡鍒犻櫎锛圥_ISDELETED锛夛紝鍒欒緭鍑轰笅涓涓簨鍔 ID锛坸act锛夈 + * - 濡傛灉鏄 UBTree 绫诲瀷鐨勭储寮曢〉锛岃繕浼氳緭鍑烘椿璺冨厓缁勬暟锛坅ctiveTupleCount锛夈 + */ static void ParseIndexPageSpecialInfo(void *page, int type, char *output) { errno_t rc = 0; @@ -1025,27 +1423,27 @@ static void ParseIndexPageSpecialInfo(void *page, int type, char *output) } rc = snprintf_s(output + (int)strlen(output), MAXOUTPUTLEN, MAXOUTPUTLEN, "\n%s index special information:\n", - (type == BTREE_INDEX) ? "BTree" : "UBTree"); + (type == BTREE_INDEX) ? "BTree" : "UBTree"); securec_check_ss(rc, "\0", "\0"); rc = snprintf_s(output + (int)strlen(output), MAXOUTPUTLEN, MAXOUTPUTLEN, "\tbtree left sibling: %u\n", - opaque->btpo_prev); + opaque->btpo_prev); securec_check_ss(rc, "\0", "\0"); rc = snprintf_s(output + (int)strlen(output), MAXOUTPUTLEN, MAXOUTPUTLEN, "\tbtree right sibling: %u\n", - opaque->btpo_next); + opaque->btpo_next); securec_check_ss(rc, "\0", "\0"); if (!P_ISDELETED(opaque)) { rc = snprintf_s(output + (int)strlen(output), MAXOUTPUTLEN, MAXOUTPUTLEN, "\tbtree tree level: %u\n", - opaque->btpo.level); + opaque->btpo.level); securec_check_ss(rc, "\0", "\0"); } else { if (uopaque) { rc = snprintf_s(output + (int)strlen(output), MAXOUTPUTLEN, MAXOUTPUTLEN, "\tnext txid (deleted): %lu\n", - ((UBTPageOpaque)uopaque)->xact); + ((UBTPageOpaque)uopaque)->xact); securec_check_ss(rc, "\0", "\0"); } else { rc = snprintf_s(output + (int)strlen(output), MAXOUTPUTLEN, MAXOUTPUTLEN, "\tnext txid (deleted): %lu\n", - ((BTPageOpaque)opaque)->xact); + ((BTPageOpaque)opaque)->xact); securec_check_ss(rc, "\0", "\0"); } } @@ -1080,18 +1478,30 @@ static void ParseIndexPageSpecialInfo(void *page, int type, char *output) securec_check_ss(rc, "\0", "\0"); rc = snprintf_s(output + (int)strlen(output), MAXOUTPUTLEN, MAXOUTPUTLEN, "\tbtree cycle ID: %u\n ", - opaque->btpo_cycleid); + opaque->btpo_cycleid); securec_check_ss(rc, "\0", "\0"); if (uopaque) { rc = snprintf_s(output + (int)strlen(output), MAXOUTPUTLEN, MAXOUTPUTLEN, "\tubtree active tuples: %d\n", - uopaque->activeTupleCount); + uopaque->activeTupleCount); securec_check_ss(rc, "\0", "\0"); } return; } - +/* + * 鍔熻兘锛氳В鏋愮储寮曢〉涓婄殑鏁版嵁淇℃伅 + * + * 鍙傛暟鍒楄〃锛 + * page锛歷oid 鎸囬拡锛岃〃绀虹储寮曢〉鐨勬暟鎹 + * type锛歩nt锛岃〃绀虹储寮曠殑绫诲瀷锛圔TREE_INDEX 鎴 UBTREE_INDEX锛 + * output锛歝har 鎸囬拡锛岃〃绀鸿緭鍑鸿В鏋愮粨鏋滅殑瀛楃涓 + * + * 娉ㄦ剰浜嬮」锛 + * - 璇ュ嚱鏁扮敤浜庤В鏋愮储寮曢〉涓婂瓨鍌ㄧ殑绱㈠紩鍏冪粍淇℃伅锛屽寘鎷瓨鍌ㄥ厓缁勭殑绫诲瀷銆佸亸绉婚噺绛夈 + * - 杈撳嚭鍖呮嫭鍏冪粍鐨勭被鍨嬶紙姝e父銆佸喕缁撱佹浜°侀噸瀹氬悜锛変互鍙婂厓缁勭殑闀垮害鍜屽亸绉婚噺銆 + * - 濡傛灉鏄 UBTree 绫诲瀷鐨勭储寮曪紝杩樹細璋冪敤 ParseIndexPageItem 鍑芥暟杩涗竴姝ヨВ鏋愬厓缁勪俊鎭 + */ static void ParseIndexPageData(void *page, int type, char *output) { errno_t rc; @@ -1113,7 +1523,7 @@ static void ParseIndexPageData(void *page, int type, char *output) rowPtrCnt = PageGetMaxOffsetNumber((Page)pageHeader); rc = snprintf_s(output + (int)strlen(output), MAXOUTPUTLEN, MAXOUTPUTLEN, - "\n\tIndex tuple information on this page\n"); + "\n\tIndex tuple information on this page\n"); securec_check_ss(rc, "\0", "\0"); for (uint32 i = FirstOffsetNumber; i <= rowPtrCnt; i++) { @@ -1124,21 +1534,25 @@ static void ParseIndexPageData(void *page, int type, char *output) } if (ItemIdIsNormal(lp) || (IndexItemIdIsFrozen(lp))) { rc = ItemIdIsNormal(lp) ? (snprintf_s(output + (int)strlen(output), MAXOUTPUTLEN, MAXOUTPUTLEN, - "\n\t\tTuple #%u is normal: length %u, offset %u\n", i, ItemIdGetLength(lp), ItemIdGetOffset(lp))) : - (snprintf_s(output + (int)strlen(output), MAXOUTPUTLEN, MAXOUTPUTLEN, - "\n\t\tTuple #%u is frozen: length %u, offset %u\n", i, ItemIdGetLength(lp), ItemIdGetOffset(lp))); + "\n\t\tTuple #%u is normal: length %u, offset %u\n", i, + ItemIdGetLength(lp), ItemIdGetOffset(lp))) + : (snprintf_s(output + (int)strlen(output), MAXOUTPUTLEN, MAXOUTPUTLEN, + "\n\t\tTuple #%u is frozen: length %u, offset %u\n", i, + ItemIdGetLength(lp), ItemIdGetOffset(lp))); securec_check_ss(rc, "\0", "\0"); normalCnt++; item = PageGetItem((Page)pageHeader, lp); ParseIndexPageItem(item, type, ItemIdGetLength(lp), output); } else if (ItemIdIsDead(lp)) { rc = snprintf_s(output + (int)strlen(output), MAXOUTPUTLEN, MAXOUTPUTLEN, - "\n\t\tTuple #%u is dead: length %u, offset %u", i, ItemIdGetLength(lp), ItemIdGetOffset(lp)); + "\n\t\tTuple #%u is dead: length %u, offset %u", i, ItemIdGetLength(lp), + ItemIdGetOffset(lp)); securec_check_ss(rc, "\0", "\0"); deadCnt++; } else { rc = snprintf_s(output + (int)strlen(output), MAXOUTPUTLEN, MAXOUTPUTLEN, - "\n\t\tTuple #%u is redirected: length %u, offset %u", i, ItemIdGetLength(lp), ItemIdGetOffset(lp)); + "\n\t\tTuple #%u is redirected: length %u, offset %u", i, ItemIdGetLength(lp), + ItemIdGetOffset(lp)); securec_check_ss(rc, "\0", "\0"); redirectCnt++; } @@ -1150,12 +1564,25 @@ static void ParseIndexPageData(void *page, int type, char *output) } rc = snprintf_s(output + (int)strlen(output), MAXOUTPUTLEN, MAXOUTPUTLEN, - "\tSummary (%u total): %u unused, %u normal, %u dead, %u redirect\n", rowPtrCnt, notusedCnt, normalCnt, deadCnt, - redirectCnt); + "\tSummary (%u total): %u unused, %u normal, %u dead, %u redirect\n", rowPtrCnt, notusedCnt, + normalCnt, deadCnt, redirectCnt); securec_check_ss(rc, "\0", "\0"); return; } - +/* + * 鍔熻兘锛氳В鏋愮储寮曢〉鐨勫悇涓儴鍒嗭紙椤靛ご銆佹暟鎹佺壒娈婁俊鎭級 + * + * 鍙傛暟鍒楄〃锛 + * page锛歷oid 鎸囬拡锛岃〃绀虹储寮曢〉鐨勬暟鎹 + * type锛歩nt锛岃〃绀虹储寮曠殑绫诲瀷锛圔TREE_INDEX 鎴 UBTREE_INDEX锛 + * blkno锛欱lockNumber锛岃〃绀哄綋鍓嶇储寮曢〉鐨勫潡鍙 + * endBlk锛欱lockNumber锛岃〃绀虹储寮曢〉鐨勭粨鏉熷潡鍙 + * output锛歝har 鎸囬拡锛岃〃绀鸿緭鍑鸿В鏋愮粨鏋滅殑瀛楃涓 + * + * 娉ㄦ剰浜嬮」锛 + * - 璇ュ嚱鏁伴鍏堟鏌ョ储寮曢〉鐨勯〉澶存槸鍚︽湁鏁堬紝鐒跺悗渚濇瑙f瀽椤靛ご銆佹暟鎹拰鐗规畩淇℃伅銆 + * - 濡傛灉绱㈠紩椤垫槸鏂伴〉锛圥ageIsNew锛夛紝鍒欎笉杩涜杩涗竴姝ヨВ鏋愩 + */ static void ParseIndexPage(void *page, int type, BlockNumber blkno, BlockNumber endBlk, char *output) { PageHeader pageHeader = NULL; @@ -1172,8 +1599,8 @@ static void ParseIndexPage(void *page, int type, BlockNumber blkno, BlockNumber pageHeader->pd_upper > pageHeader->pd_special || pageHeader->pd_special > BLCKSZ || pageHeader->pd_special != MAXALIGN(pageHeader->pd_special)) { rc = snprintf_s(output + (int)strlen(output), MAXOUTPUTLEN, MAXOUTPUTLEN, - "The page data is corrupted, corrupted page pointers: lower = %u, upper = %u, special = %u\n", - pageHeader->pd_lower, pageHeader->pd_upper, pageHeader->pd_special); + "The page data is corrupted, corrupted page pointers: lower = %u, upper = %u, special = %u\n", + pageHeader->pd_lower, pageHeader->pd_upper, pageHeader->pd_special); securec_check_ss(rc, "\0", "\0"); return; } @@ -1187,7 +1614,22 @@ static void ParseIndexPage(void *page, int type, BlockNumber blkno, BlockNumber ParseIndexPageSpecialInfo((void *)page, type, output); return; } - +/* + * gs_parse_page_bypath - Parses a page on disk and returns the parsed information as text. + * + * This function is used to parse a page on disk and return the parsed information as text. + * It performs the following steps: + * 1. Checks the user's rights. + * 2. Reads input parameters. + * 3. Parses the requested page and writes the results to a file. + * 4. Returns the filename of the output file as text. + * + * Parameters: + * - PG_FUNCTION_ARGS: The standard input arguments for a PostgreSQL function. + * + * Returns: + * A text value containing the filename of the output file. + */ Datum gs_parse_page_bypath(PG_FUNCTION_ARGS) { /* check user's right */ diff --git a/src/gausskernel/storage/remote/remote_adapter.cpp b/src/gausskernel/storage/remote/remote_adapter.cpp index 0adcf7d73..7ccd60901 100755 --- a/src/gausskernel/storage/remote/remote_adapter.cpp +++ b/src/gausskernel/storage/remote/remote_adapter.cpp @@ -44,9 +44,9 @@ #include "utils/aiomem.h" const int DEFAULT_WAIT_TIMES = 60; -int ReadFileForRemote(RemoteReadFileKey *key, XLogRecPtr lsn, bytea** fileData, int timeout); +int ReadFileForRemote(RemoteReadFileKey *key, XLogRecPtr lsn, bytea **fileData, int timeout); -int ReadCOrCsnFileForRemote(RelFileNode rnode, bytea** fileData); +int ReadCOrCsnFileForRemote(RelFileNode rnode, bytea **fileData); /* * @Description: wait lsn to replay @@ -66,12 +66,9 @@ int XLogWaitForReplay(uint64 primary_insert_lsn, int timeout = DEFAULT_WAIT_TIME /* if sleep to much times */ if (wait_times >= timeout) { ereport(LOG, - (errmodule(MOD_REMOTE), - errmsg("replay slow. requre lsn %X/%X, replayed lsn %X/%X", - (uint32)(primary_insert_lsn >> 32), - (uint32)primary_insert_lsn, - (uint32)(standby_replay_lsn >> 32), - (uint32)standby_replay_lsn))); + (errmodule(MOD_REMOTE), errmsg("replay slow. requre lsn %X/%X, replayed lsn %X/%X", + (uint32)(primary_insert_lsn >> 32), (uint32)primary_insert_lsn, + (uint32)(standby_replay_lsn >> 32), (uint32)standby_replay_lsn))); return REMOTE_READ_NEED_WAIT; } @@ -100,7 +97,7 @@ Datum gs_read_block_from_remote(PG_FUNCTION_ARGS) uint32 blockSize; uint64 lsn; bool isForCU = false; - bytea* result = NULL; + bytea *result = NULL; int timeout = 0; if (GetUserId() != BOOTSTRAP_SUPERUSERID) { @@ -152,7 +149,7 @@ Datum gs_read_block_from_remote_compress(PG_FUNCTION_ARGS) uint64 lsn; int timeout = 0; bool isForCU = false; - bytea* result = NULL; + bytea *result = NULL; if (GetUserId() != BOOTSTRAP_SUPERUSERID) { ereport(ERROR, (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), (errmsg("must be initial account to read files")))); @@ -176,7 +173,7 @@ Datum gs_read_block_from_remote_compress(PG_FUNCTION_ARGS) } else { (void)StandbyReadPageforPrimary(key, blockSize, lsn, &result, timeout, NULL); } - + if (NULL != result) { PG_RETURN_BYTEA_P(result); } else { @@ -198,8 +195,7 @@ Datum gs_read_block_from_remote_compress(PG_FUNCTION_ARGS) * @Return: remote read error code * @See also: */ -int StandbyReadCUforPrimary(RepairBlockKey key, uint64 offset, int32 size, uint64 lsn, int32 timeout, - bytea** cudata) +int StandbyReadCUforPrimary(RepairBlockKey key, uint64 offset, int32 size, uint64 lsn, int32 timeout, bytea **cudata) { Assert(cudata); @@ -214,14 +210,14 @@ int StandbyReadCUforPrimary(RepairBlockKey key, uint64 offset, int32 size, uint6 } } - RelFileNode relfilenode {key.relfilenode.spcNode, key.relfilenode.dbNode, key.relfilenode.relNode, InvalidBktId}; + RelFileNode relfilenode{key.relfilenode.spcNode, key.relfilenode.dbNode, key.relfilenode.relNode, InvalidBktId}; { /* read from disk */ CFileNode cfilenode(relfilenode, key.forknum, MAIN_FORKNUM); - CUStorage* custorage = New(CurrentMemoryContext) CUStorage(cfilenode); - CU* cu = New(CurrentMemoryContext) CU(); + CUStorage *custorage = New(CurrentMemoryContext) CUStorage(cfilenode); + CU *cu = New(CurrentMemoryContext) CU(); cu->m_inCUCache = false; custorage->LoadCU(cu, offset, size, false, false); @@ -232,7 +228,7 @@ int StandbyReadCUforPrimary(RepairBlockKey key, uint64 offset, int32 size, uint6 ereport(ERROR, (errmodule(MOD_REMOTE), errmsg("check CU crc error."))); ret_code = REMOTE_READ_CRC_ERROR; } else { - bytea* buf = (bytea*)palloc0(VARHDRSZ + size); + bytea *buf = (bytea *)palloc0(VARHDRSZ + size); SET_VARSIZE(buf, size + VARHDRSZ); errno_t rc = memcpy_s(VARDATA(buf), size, cu->m_compressedLoadBuf, size); if (rc != EOK) { @@ -263,8 +259,8 @@ int StandbyReadCUforPrimary(RepairBlockKey key, uint64 offset, int32 size, uint6 * @Return: remote read error code * @See also: */ -int StandbyReadPageforPrimary(RepairBlockKey key, uint32 blocksize, uint64 lsn, bytea** pagedata, - int timeout, const XLogPhyBlock *pblk) +int StandbyReadPageforPrimary(RepairBlockKey key, uint32 blocksize, uint64 lsn, bytea **pagedata, int timeout, + const XLogPhyBlock *pblk) { Assert(pagedata); @@ -287,18 +283,17 @@ int StandbyReadPageforPrimary(RepairBlockKey key, uint32 blocksize, uint64 lsn, if (NULL != pblk) { SegPageLocation loc = seg_get_physical_location(relfilenode, key.forknum, key.blocknum); - uint8 standby_relNode = (uint8) EXTENT_SIZE_TO_TYPE(loc.extent_size); + uint8 standby_relNode = (uint8)EXTENT_SIZE_TO_TYPE(loc.extent_size); BlockNumber standby_block = loc.blocknum; if (standby_relNode != pblk->relNode || standby_block != pblk->block) { - ereport(ERROR, (errmodule(MOD_REMOTE), - errmsg("Standby page file is invalid! Standby relnode is %u, " - "master is %u; Standby block is %u, master is %u.", - standby_relNode, pblk->relNode, standby_block, pblk->block))); + ereport(ERROR, (errmodule(MOD_REMOTE), errmsg("Standby page file is invalid! Standby relnode is %u, " + "master is %u; Standby block is %u, master is %u.", + standby_relNode, pblk->relNode, standby_block, pblk->block))); return REMOTE_READ_BLCKSZ_NOT_SAME; } } - bytea* pageData = (bytea*)palloc(BLCKSZ + VARHDRSZ); + bytea *pageData = (bytea *)palloc(BLCKSZ + VARHDRSZ); SET_VARSIZE(pageData, BLCKSZ + VARHDRSZ); if (IsSegmentPhysicalRelNode(relfilenode)) { Buffer buffer = InvalidBuffer; @@ -351,13 +346,25 @@ int StandbyReadPageforPrimary(RepairBlockKey key, uint32 blocksize, uint64 lsn, if (ret_code == REMOTE_READ_OK) { *pagedata = pageData; - PageSetChecksumInplace((Page) VARDATA(*pagedata), key.blocknum); + PageSetChecksumInplace((Page)VARDATA(*pagedata), key.blocknum); } return ret_code; } const int RES_COL_NUM = 2; +/* + * 鍔熻兘锛氫粠杩滅▼鏈嶅姟鍣ㄨ鍙栨枃浠跺苟杩斿洖鏂囦欢鍐呭鍙婂綋鍓峀SN锛岃鍑芥暟閫傜敤浜庣壒鏉冪敤鎴凤紝闈炵壒鏉冪敤鎴锋棤娉曡皟鐢 + * + * 鍙傛暟鍒楄〃锛 + * PG_FUNCTION_ARGS锛歅ostgreSQL鎵╁睍鍑芥暟鍙傛暟鍒楄〃 + * + * 娉ㄦ剰浜嬮」锛 + * - 璋冪敤鑰呭繀椤绘槸瓒呯骇鐢ㄦ埛锛圔OOTSTRAP_SUPERUSERID锛夋墠鑳戒娇鐢ㄦ鍑芥暟銆 + * - 濡傛灉琛ㄧ┖闂磋妭鐐逛笉鏄1鎴2锛屽嚱鏁板皢灏濊瘯璇诲彇鏁版嵁鏂囦欢锛屽惁鍒欏皢灏濊瘯璇诲彇鍏朵粬绫诲瀷鐨勬枃浠躲 + * - 濡傛灉閫掑綊鏍囧織涓1锛屽皢閫掑綊鍒犻櫎鐩綍鍙婂叾鍐呭銆 + * - 濡傛灉鏂囦欢璇诲彇澶辫触锛屽嚱鏁板皢杩斿洖 NULL銆 + */ Datum gs_read_file_from_remote(PG_FUNCTION_ARGS) { RelFileNode rnode; @@ -365,7 +372,7 @@ Datum gs_read_file_from_remote(PG_FUNCTION_ARGS) int32 forknum; uint32 blockstart; uint64 lsn; - bytea* result = NULL; + bytea *result = NULL; Datum values[RES_COL_NUM]; bool nulls[RES_COL_NUM] = {false}; HeapTuple tuple = NULL; @@ -374,58 +381,77 @@ Datum gs_read_file_from_remote(PG_FUNCTION_ARGS) int32 timeout; int parano = 0; XLogRecPtr current_lsn = InvalidXLogRecPtr; - + // 妫鏌ヨ皟鐢ㄨ呮槸鍚︿负瓒呯骇鐢ㄦ埛 if (GetUserId() != BOOTSTRAP_SUPERUSERID) { ereport(ERROR, (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), (errmsg("must be initial account to read files")))); } - /* handle optional arguments */ + // 浠庡嚱鏁板弬鏁颁腑鑾峰彇琛ㄧ┖闂淬佹暟鎹簱銆佽〃/鍏崇郴銆佸潡浣嶇疆绛変俊鎭 rnode.spcNode = PG_GETARG_UINT32(parano++); rnode.dbNode = PG_GETARG_UINT32(parano++); rnode.relNode = PG_GETARG_UINT32(parano++); rnode.bucketNode = PG_GETARG_INT32(parano++); rnode.opt = 0; + // 鑾峰彇 fork 鍙峰拰鍧楃殑璧峰浣嶇疆 forknum = PG_GETARG_INT32(parano++); blockstart = PG_GETARG_INT32(parano++); + // 鑾峰彇浜嬪姟鐨 LSN锛圠og Sequence Number锛 lsn = (uint64)PG_GETARG_TRANSACTIONID(parano++); + // 鑾峰彇瓒呮椂鏃堕棿 timeout = PG_GETARG_INT32(parano++); - + // 濡傛灉琛ㄧ┖闂磋妭鐐逛笉鏄1鎴2锛岃鏄庤璇诲彇鏁版嵁鏂囦欢 if (rnode.spcNode != 1 && rnode.spcNode != 2) { - /* get tale data file */ + // 璁剧疆 RemoteReadFileKey 缁撴瀯浣 key.relfilenode = rnode; key.forknum = forknum; key.blockstart = blockstart; + + // 濡傛灉 fork 鍙蜂笉鏄富 fork锛屽垯鍙戝嚭璀﹀憡骞惰繑鍥 NULL if (forknum != MAIN_FORKNUM) { ereport(WARNING, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - (errmsg("Forknum should be 0. Now is %d. \n", forknum)))); + (errmsg("Forknum should be 0. Now is %d. \n", forknum)))); PG_RETURN_NULL(); } + + // 璋冪敤 ReadFileForRemote 鍑芥暟灏濊瘯璇诲彇杩滅▼鏂囦欢 ret_code = ReadFileForRemote(&key, lsn, &result, timeout); } else { + // 濡傛灉琛ㄧ┖闂磋妭鐐规槸1鎴2锛岃鏄庤璇诲彇鍏朵粬绫诲瀷鐨勬枃浠 ret_code = ReadCOrCsnFileForRemote(rnode, &result); } - + // 濡傛灉鏂囦欢璇诲彇澶辫触锛岃繑鍥 NULL if (ret_code != REMOTE_READ_OK) { PG_RETURN_NULL(); } - + // 濡傛灉涓嶅浜庢仮澶嶆ā寮忎笅锛岃幏鍙栧綋鍓嶇殑 LSN锛圠og Sequence Number锛 if (!RecoveryInProgress()) { current_lsn = GetXLogInsertRecPtr(); } - + // 鍒涘缓缁撴灉鍏冪粍鐨勬弿杩颁俊鎭 tupdesc = CreateTemplateTupleDesc(RES_COL_NUM, false, TAM_HEAP); parano = 1; + // 鍒濆鍖栫粨鏋滃厓缁勭殑姣忎釜鍒 TupleDescInitEntry(tupdesc, (AttrNumber)parano++, "file", BYTEAOID, -1, 0); TupleDescInitEntry(tupdesc, (AttrNumber)parano++, "lsn", XIDOID, -1, 0); + // 璁剧疆鍏冪粍鐨勫煎拰 nulls 鏍囧織 values[0] = PointerGetDatum(result); nulls[0] = false; values[1] = UInt64GetDatum(current_lsn); nulls[1] = false; - + // 鍒涘缓鍏冪粍 tupdesc = BlessTupleDesc(tupdesc); tuple = heap_form_tuple(tupdesc, values, nulls); + // 杩斿洖缁撴灉鍏冪粍 PG_RETURN_DATUM(HeapTupleGetDatum(tuple)); } - +/* + * 鍔熻兘锛氳幏鍙栬繙绋嬫枃浠剁殑澶у皬 + * + * 鍙傛暟鍒楄〃锛 + * PG_FUNCTION_ARGS锛歅ostgreSQL鎵╁睍鍑芥暟鍙傛暟鍒楄〃 + * + * 娉ㄦ剰浜嬮」锛 + * - 璋冪敤鑰呭繀椤绘槸瓒呯骇鐢ㄦ埛锛圔OOTSTRAP_SUPERUSERID锛夋墠鑳戒娇鐢ㄦ鍑芥暟銆 + */ Datum gs_read_file_size_from_remote(PG_FUNCTION_ARGS) { RelFileNode rnode; @@ -436,29 +462,56 @@ Datum gs_read_file_size_from_remote(PG_FUNCTION_ARGS) int parano = 0; int ret_code = REMOTE_READ_OK; + // 妫鏌ヨ皟鐢ㄨ呮槸鍚︿负瓒呯骇鐢ㄦ埛 if (GetUserId() != BOOTSTRAP_SUPERUSERID) { ereport(ERROR, (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), (errmsg("must be initial account to read files")))); } /* handle optional arguments */ + // 浠庡嚱鏁板弬鏁颁腑鑾峰彇琛ㄧ┖闂淬佹暟鎹簱銆佽〃/鍏崇郴銆佸潡浣嶇疆绛変俊鎭 rnode.spcNode = PG_GETARG_UINT32(parano++); rnode.dbNode = PG_GETARG_UINT32(parano++); rnode.relNode = PG_GETARG_UINT32(parano++); rnode.bucketNode = PG_GETARG_INT32(parano++); rnode.opt = 0; + // 鑾峰彇 fork 鍙 forknum = PG_GETARG_INT32(parano++); + // 鑾峰彇浜嬪姟鐨 LSN锛圠og Sequence Number锛 lsn = (uint64)PG_GETARG_TRANSACTIONID(parano++); + // 鑾峰彇瓒呮椂鏃堕棿 timeout = PG_GETARG_INT32(parano++); /* get file size */ ret_code = ReadFileSizeForRemote(rnode, forknum, lsn, &size, timeout); + // 濡傛灉鎴愬姛鑾峰彇鏂囦欢澶у皬锛岃繑鍥炲ぇ灏忓 if (ret_code == REMOTE_READ_OK) { PG_RETURN_INT64(size); } else { + // 濡傛灉鑾峰彇澶辫触锛岃繑鍥 NULL PG_RETURN_NULL(); } } - -int ReadFileSizeForRemote(RelFileNode rnode, int32 forknum, XLogRecPtr lsn, int64* res, int timeout) +/* + * 鍔熻兘锛氳幏鍙栬繙绋嬫枃浠剁殑澶у皬 + * + * 鍙傛暟鍒楄〃锛 + * rnode锛氬緟鑾峰彇鏂囦欢鐨勬枃浠惰妭鐐逛俊鎭紙鍖呮嫭琛ㄧ┖闂淬佹暟鎹簱銆佽〃/鍏崇郴绛変俊鎭級 + * forknum锛氭枃浠剁殑 fork 鍙 + * lsn锛氱敤浜庣瓑寰呬簨鍔℃棩蹇楀洖鏀剧殑 LSN锛堜粎鍦ㄦ仮澶嶆ā寮忎笅浣跨敤锛 + * res锛氱敤浜庡瓨鍌ㄦ枃浠跺ぇ灏忕殑鎸囬拡 + * timeout锛氱瓑寰呭洖鏀剧殑瓒呮椂鏃堕棿 + * + * 杩斿洖鍊硷細 + * 鎴愬姛鑾峰彇鏂囦欢澶у皬鏃讹紝灏嗘枃浠跺ぇ灏忓瓨鍌ㄥ湪 res 鎸囬拡鎸囧悜鐨勪綅缃紝骞惰繑鍥 REMOTE_READ_OK銆 + * 濡傛灉鍑虹幇閿欒鎴栨枃浠朵笉瀛樺湪锛屽皢杩斿洖閫傚綋鐨勯敊璇唬鐮併 + * + * 娉ㄦ剰浜嬮」锛 + * - 鍦ㄦ仮澶嶆ā寮忎笅锛屽嚱鏁板皢绛夊緟鎸囧畾 LSN 鐨勪簨鍔℃棩蹇楀洖鏀惧畬鎴愩 + * - 鍑芥暟灏嗛鍏堟鏌ユ枃浠舵槸鍚﹀瓨鍦紝濡傛灉鏂囦欢涓嶅瓨鍦紝灏嗚繑鍥炴枃浠跺ぇ灏忎负 -1銆 + * - 瀵逛簬闈炲垎娈垫枃浠惰妭鐐癸紝鍑芥暟灏嗘墦寮鏂囦欢骞惰绠楀潡鏁颁互鑾峰彇鏂囦欢澶у皬銆 + * - 瀵逛簬鍒嗘鏂囦欢鑺傜偣锛屽嚱鏁板皢閫氳繃 spc_open 鍜 spc_size 鑾峰彇鏂囦欢澶у皬銆 + * - 鏂囦欢澶у皬灏嗕互瀛楄妭涓哄崟浣嶅瓨鍌ㄥ湪 res 鎸囬拡鎸囧悜鐨勪綅缃 + */ +int ReadFileSizeForRemote(RelFileNode rnode, int32 forknum, XLogRecPtr lsn, int64 *res, int timeout) { SMgrRelation smgr = NULL; int64 nblock = 0; @@ -477,7 +530,7 @@ int ReadFileSizeForRemote(RelFileNode rnode, int32 forknum, XLogRecPtr lsn, int6 /* check whether the file exists. not exist, return size -1 */ struct stat statBuf; - char* path = relpathperm(rnode, forknum); + char *path = relpathperm(rnode, forknum); if (stat(path, &statBuf) < 0 && errno == ENOENT) { *res = -1; pfree(path); @@ -485,22 +538,42 @@ int ReadFileSizeForRemote(RelFileNode rnode, int32 forknum, XLogRecPtr lsn, int6 } pfree(path); - if (!IsSegmentFileNode(rnode)) { - smgr = smgropen(rnode, InvalidBackendId); - nblock = smgrnblocks(smgr, forknum); - smgrcloseall(); - } else { - SegSpace *spc = spc_open(rnode.spcNode, rnode.dbNode, true, true); - spc_datafile_create(spc, rnode.relNode, forknum); - - nblock = spc_size(spc, rnode.relNode, forknum); + // 濡傛灉涓嶆槸鍒嗘鏂囦欢鑺傜偣锛屾墦寮鏂囦欢骞惰绠楀潡鏁 + if (!IsSegmentFileNode(rnode)) { // 濡傛灉涓嶆槸鍒嗘鏂囦欢鑺傜偣 + smgr = smgropen(rnode, InvalidBackendId); // 鎵撳紑鏂囦欢鐨勫瓨鍌ㄧ鐞嗗櫒 + nblock = smgrnblocks(smgr, forknum); // 鑾峰彇鏂囦欢鐨勫潡鏁 + smgrcloseall(); // 鍏抽棴鎵鏈夌殑瀛樺偍绠$悊鍣 + } else { // 濡傛灉鏄垎娈垫枃浠惰妭鐐 + SegSpace *spc = spc_open(rnode.spcNode, rnode.dbNode, true, true); // 鎵撳紑鍒嗘绌洪棿 + spc_datafile_create(spc, rnode.relNode, forknum); // 鍒涘缓鏁版嵁鏂囦欢 + nblock = spc_size(spc, rnode.relNode, forknum); // 鑾峰彇鏂囦欢澶у皬 } + // 璁$畻鏂囦欢澶у皬骞跺瓨鍌ㄥ湪 res 鎸囬拡鎸囧悜鐨勪綅缃 *res = nblock * BLCKSZ; return ret_code; } - -int ReadFileByReadBufferComom(RemoteReadFileKey *key, bytea* pageData, uint32 nblock) +/* + * 鍔熻兘锛氶氳繃 ReadBuffer 璇诲彇杩滅▼鏂囦欢鐨勫涓暟鎹潡骞跺皢鏁版嵁瀛樺偍鍦 pageData 涓 + * 姣忎釜鏁版嵁鍧楃殑澶у皬涓 BLCKSZ 瀛楄妭銆傚嚱鏁板彲浠ュ鐞嗕竴涓潡鑼冨洿鍐呯殑鏁版嵁鍧楄鍙栬姹傘 + * + * 鍙傛暟鍒楄〃锛 + * key锛氳繙绋嬫枃浠惰鍙栬姹傜殑鍏抽敭淇℃伅锛屽寘鎷枃浠惰妭鐐广乫ork 鍙峰拰鍧楄捣濮嬩綅缃 + * pageData锛氱敤浜庡瓨鍌ㄨ鍙栨暟鎹潡鍐呭鐨勫瓧鑺傛暟缁 + * nblock锛氭枃浠朵腑鐨勬绘暟鎹潡鏁伴噺 + * + * 杩斿洖鍊硷細 + * 濡傛灉鎴愬姛璇诲彇鏁版嵁鍧楋紝灏嗚繑鍥 REMOTE_READ_OK銆 + * 濡傛灉璇诲彇杩囩▼涓彂鐢熼敊璇紝灏嗚繑鍥為傚綋鐨勯敊璇唬鐮併 + * + * 娉ㄦ剰浜嬮」锛 + * - 鍑芥暟浠 blk_start 鍒 blk_end 涔嬮棿鐨勬暟鎹潡鑼冨洿鍐呰鍙栨暟鎹 + * - 姣忎釜鏁版嵁鍧楃殑澶у皬涓 BLCKSZ 瀛楄妭銆 + * - 鍑芥暟鍦ㄨ鍙栨暟鎹潡鏃朵細楠岃瘉鏁版嵁鍧楃殑鏈夋晥鎬с + * - 濡傛灉璇诲彇鏁版嵁鍧楀け璐ワ紝鍑芥暟灏嗚繑鍥為傚綋鐨勯敊璇唬鐮併 + * - 鍑芥暟浣跨敤浜嗙紦鍐茬瓥鐣ワ紙BufferAccessStrategy锛夋潵鎻愰珮璇诲彇鏁堢巼銆 + */ +int ReadFileByReadBufferComom(RemoteReadFileKey *key, bytea *pageData, uint32 nblock) { int ret_code = REMOTE_READ_OK; uint32 i = 0; @@ -508,7 +581,7 @@ int ReadFileByReadBufferComom(RemoteReadFileKey *key, bytea* pageData, uint32 nb uint32 blk_start; uint32 blk_end; bool hit = false; - char* bufBlock = NULL; + char *bufBlock = NULL; errno_t rc; /* get the segno file block start and block end */ @@ -526,8 +599,9 @@ int ReadFileByReadBufferComom(RemoteReadFileKey *key, bytea* pageData, uint32 nb } LockBuffer(buf, BUFFER_LOCK_SHARE); - bufBlock = (char*)BufferGetBlock(buf); + bufBlock = (char *)BufferGetBlock(buf); + // 灏嗚鍙栫殑鏁版嵁鍧楀唴瀹瑰鍒跺埌 pageData 涓 rc = memcpy_s(VARDATA(pageData) + j * BLCKSZ, BLCKSZ, bufBlock, BLCKSZ); if (rc != EOK) { ereport(WARNING, (errmodule(MOD_REMOTE), errmsg("repair file failed, memcpy_s error, retcode=%d", rc))); @@ -539,28 +613,50 @@ int ReadFileByReadBufferComom(RemoteReadFileKey *key, bytea* pageData, uint32 nb LockBuffer(buf, BUFFER_LOCK_UNLOCK); ReleaseBuffer(buf); - PageSetChecksumInplace((Page) (VARDATA(pageData) + j * BLCKSZ), i); + PageSetChecksumInplace((Page)(VARDATA(pageData) + j * BLCKSZ), i); } return ret_code; } const int MAX_RETRY_TIMES = 60; -int ReadFileByReadDisk(SegSpace* spc, RemoteReadFileKey *key, char* bufBlock, BlockNumber blocknum) +/* + * 鍔熻兘锛氶氳繃鐩存帴浠庣鐩樿鍙栨暟鎹潡淇杩滅▼鏂囦欢锛屽畠鍙互澶勭悊鍒嗘鏂囦欢鍜岄潪鍒嗘鏂囦欢 + * + * 鍙傛暟鍒楄〃锛 + * spc锛氬垎娈电┖闂寸殑淇℃伅锛堜粎瀵瑰垎娈垫枃浠舵湁鏁堬級 + * key锛氳繙绋嬫枃浠惰鍙栬姹傜殑鍏抽敭淇℃伅锛屽寘鎷枃浠惰妭鐐广乫ork 鍙峰拰鍧楀彿 + * bufBlock锛氱敤浜庡瓨鍌ㄨ鍙栨暟鎹潡鍐呭鐨勭紦鍐插尯 + * blocknum锛氳璇诲彇鐨勬暟鎹潡鍙 + * + * 杩斿洖鍊硷細 + * 濡傛灉鎴愬姛淇鎹熷潖鍧楋紝灏嗚繑鍥 REMOTE_READ_OK銆 + * 濡傛灉淇杩囩▼涓彂鐢熼敊璇紝灏嗚繑鍥為傚綋鐨勯敊璇唬鐮併 + * + * 娉ㄦ剰浜嬮」锛 + * - 鍑芥暟棣栧厛妫鏌ユ枃浠惰妭鐐规槸鍚﹀睘浜庡垎娈垫枃浠讹紝浠ョ‘瀹氶噰鐢ㄤ綍绉嶈鍙栨柟寮忋 + * - 瀵逛簬鍒嗘鏂囦欢锛屽嚱鏁颁娇鐢 seg_physical_read 浠庣鐩樿鍙栨暟鎹潡锛屽苟杩涜 CRC 楠岃瘉銆 + * - 濡傛灉 CRC 楠岃瘉澶辫触锛屽嚱鏁板皢灏濊瘯鏈澶 MAX_RETRY_TIMES 娆℃潵淇鎹熷潖鍧椼 + * - 瀵逛簬闈炲垎娈垫枃浠讹紝鍑芥暟浣跨敤 smgrread 浠庣鐩樿鍙栨暟鎹潡锛屽苟杩涜 CRC 楠岃瘉銆 + * - 濡傛灉 CRC 楠岃瘉澶辫触锛屽嚱鏁板皢杩斿洖閫傚綋鐨勯敊璇唬鐮併 + * - 鍑芥暟浼氬湪姣忔閲嶈瘯涔嬮棿浼戠湢 10 姣銆 + * - 淇澶辫触鍚庯紝鍑芥暟灏嗛噴鏀 bufBlock 骞惰繑鍥為敊璇唬鐮併 + */ +int ReadFileByReadDisk(SegSpace *spc, RemoteReadFileKey *key, char *bufBlock, BlockNumber blocknum) { int ret_code = REMOTE_READ_OK; int pageStatus; int retryTimes = 0; + // 妫鏌ユ枃浠舵槸鍚︿负鍒嗘鏂囦欢 if (IsSegmentFileNode(key->relfilenode)) { - RelFileNode fakenode = { - .spcNode = key->relfilenode.spcNode, - .dbNode = key->relfilenode.dbNode, - .relNode = key->relfilenode.relNode, - .bucketNode = SegmentBktId, - .opt = 0 - }; -SEG_RETRY: + RelFileNode fakenode = {.spcNode = key->relfilenode.spcNode, + .dbNode = key->relfilenode.dbNode, + .relNode = key->relfilenode.relNode, + .bucketNode = SegmentBktId, + .opt = 0}; + SEG_RETRY: + // 浠庣鐩樿鍙栨暟鎹潡 seg_physical_read(spc, fakenode, key->forknum, blocknum, (char *)bufBlock); retryTimes++; if (PageIsVerified((Page)bufBlock, blocknum)) { @@ -574,9 +670,10 @@ SEG_RETRY: } else { pfree(bufBlock); ereport(WARNING, (errmodule(MOD_REMOTE), - errmsg("repair file failed, read page crc check error, page: %u/%u/%u/%d, " - "forknum is %d, block num is %u", key->relfilenode.spcNode, key->relfilenode.dbNode, - key->relfilenode.relNode, key->relfilenode.bucketNode, key->forknum, blocknum))); + errmsg("repair file failed, read page crc check error, page: %u/%u/%u/%d, " + "forknum is %d, block num is %u", + key->relfilenode.spcNode, key->relfilenode.dbNode, key->relfilenode.relNode, + key->relfilenode.bucketNode, key->forknum, blocknum))); ret_code = REMOTE_READ_CRC_ERROR; return ret_code; } @@ -589,9 +686,10 @@ SEG_RETRY: if (pageStatus != SMGR_RD_OK) { pfree(bufBlock); ereport(WARNING, (errmodule(MOD_REMOTE), - errmsg("repair file failed, read page crc check error, page: %u/%u/%u/%d, " - "forknum is %d, block num is %u", key->relfilenode.spcNode, key->relfilenode.dbNode, - key->relfilenode.relNode, key->relfilenode.bucketNode, key->forknum, blocknum))); + errmsg("repair file failed, read page crc check error, page: %u/%u/%u/%d, " + "forknum is %d, block num is %u", + key->relfilenode.spcNode, key->relfilenode.dbNode, key->relfilenode.relNode, + key->relfilenode.bucketNode, key->forknum, blocknum))); ret_code = REMOTE_READ_CRC_ERROR; smgrclose(smgr); return ret_code; @@ -600,14 +698,52 @@ SEG_RETRY: } return ret_code; } - -int ReadFileForRemote(RemoteReadFileKey *key, XLogRecPtr lsn, bytea** fileData, int timeout) +/* + * 鍔熻兘锛氫粠杩滅▼鏂囦欢涓鍙栨暟鎹潡 + * + * 璇ュ嚱鏁扮敤浜庝粠杩滅▼鏂囦欢涓鍙栨暟鎹潡锛屾敮鎸佸垎娈垫枃浠跺拰闈炲垎娈垫枃浠躲傚鏋滄鍦ㄨ繘琛屾晠闅滄仮澶嶏紝鍒欎細绛夊緟璇锋眰鐨凩SN杩涜閲嶆斁銆 + * 鍑芥暟浼氭鏌ヨ姹傜殑鏁版嵁鍧楄寖鍥达紝骞朵娇鐢ㄥ悎閫傜殑鏂瑰紡鏉ヨ鍙栨暟鎹潡锛岀劧鍚庡皢鏁版嵁瀛樺偍鍦 fileData 涓 + * + * 鍙傛暟鍒楄〃锛 + * key锛氳繙绋嬫枃浠惰鍙栬姹傜殑鍏抽敭淇℃伅锛屽寘鎷枃浠惰妭鐐广乫ork 鍙峰拰鍧楄捣濮嬩綅缃 + * lsn锛氳姹傜殑LSN锛岀敤浜庣瓑寰呴噸鏀 + * fileData锛氱敤浜庡瓨鍌ㄨ鍙栨暟鎹潡鍐呭鐨 bytea 绫诲瀷鏁版嵁 + * timeout锛氱瓑寰呴噸鏀綥SN鐨勮秴鏃舵椂闂 + * + * 杩斿洖鍊硷細 + * 濡傛灉鎴愬姛璇诲彇鏁版嵁鍧楋紝灏嗚繑鍥 REMOTE_READ_OK銆 + * 濡傛灉璇诲彇杩囩▼涓彂鐢熼敊璇紝灏嗚繑鍥為傚綋鐨勯敊璇唬鐮併 + * + * 娉ㄦ剰浜嬮」锛 + * - 鍑芥暟棣栧厛绛夊緟璇锋眰鐨凩SN杩涜閲嶆斁锛屼互纭繚鍦ㄨ鍙栦箣鍓嶆暟鎹凡琚纭啓鍏ャ + * - 瀵逛簬闈炲垎娈垫枃浠讹紝鍑芥暟浼氳幏鍙栨枃浠剁殑鎬绘暟鎹潡鏁伴噺锛坣block锛夊苟妫鏌ヨ姹傜殑鏁版嵁鍧楄寖鍥淬 + * - 鍑芥暟灏嗕細鍒嗘壒娆¤鍙栨暟鎹潡锛屾瘡娆℃渶澶氳鍙 MAX_BATCH_READ_BLOCKNUM 涓暟鎹潡銆 + * - 瀵逛簬涓绘暟鎹簱锛屽嚱鏁颁娇鐢 ReadFileByReadBufferComom 鍑芥暟浠庣紦鍐插尯涓鍙栨暟鎹潡锛屽惁鍒欎娇鐢 ReadFileByReadDisk + * 鍑芥暟浠庣鐩樹腑璇诲彇銆 + * - 鍑芥暟浼氭鏌 CRC 楠岃瘉锛屽苟鍦ㄩ獙璇佸け璐ユ椂杩涜閲嶈瘯锛堟渶澶 MAX_RETRY_TIMES 娆★級銆 + * - 鍦ㄨ鍙栧け璐ユ垨鍑虹幇閿欒鏃讹紝鍑芥暟浼氶噴鏀捐祫婧愬苟杩斿洖閫傚綋鐨勯敊璇唬鐮併 + * + * 璇︾粏姝ラ锛 + * 1. 绛夊緟璇锋眰鐨凩SN杩涜閲嶆斁锛屼互纭繚鏁版嵁鐨勪竴鑷存с + * 2. 鍦ㄦ晠闅滄仮澶嶆垨瀵瑰垎娈垫枃浠剁殑璇锋眰涓婏紝瑙﹀彂寮哄埗妫鏌ョ偣锛屼互纭繚鏈鏂扮殑鏁版嵁宸叉寔涔呭寲鍒扮鐩樸 + * 3. 鑾峰彇鏂囦欢鐨勬绘暟鎹潡鏁伴噺锛坣block锛夊苟妫鏌ヨ姹傜殑鏁版嵁鍧楄寖鍥存槸鍚﹀悎娉曘 + * 4. 鏍规嵁鏁版嵁鍧楄寖鍥磋绠楄捣濮嬪拰缁撴潫鍧楀彿锛坆lk_start 鍜 blk_end锛夈 + * 5. 涓哄瓨鍌ㄦ暟鎹潡鍐呭鐨勭紦鍐插尯鍒嗛厤鍐呭瓨骞跺垵濮嬪寲銆 + * 6. 濡傛灉鏄富鏁版嵁搴擄紝浣跨敤 ReadFileByReadBufferComom 鍑芥暟浠庣紦鍐插尯涓鍙栨暟鎹潡銆 + * - 濡傛灉璇诲彇澶辫触锛岄噴鏀捐祫婧愬苟杩斿洖閿欒銆 + * 7. 濡傛灉鏄垎娈垫枃浠舵垨鏁呴殰鎭㈠锛屼娇鐢 ReadFileByReadDisk 鍑芥暟浠庣鐩樹腑璇诲彇鏁版嵁鍧椼 + * - 濡傛灉璇诲彇澶辫触锛岄噴鏀捐祫婧愬苟杩斿洖閿欒銆 + * 8. 灏嗚鍙栫殑鏁版嵁鍧楀唴瀹瑰鍒跺埌 pageData 涓 + * 9. 閲婃斁涓存椂缂撳啿鍖哄拰璧勬簮銆 + * 10. 杩斿洖璇诲彇缁撴灉鎴栭敊璇唬鐮併 + */ +int ReadFileForRemote(RemoteReadFileKey *key, XLogRecPtr lsn, bytea **fileData, int timeout) { int ret_code = REMOTE_READ_OK; SMgrRelation smgr = NULL; - SegSpace* spc = NULL; - bytea* pageData = NULL; - char* bufBlock = NULL; + SegSpace *spc = NULL; + bytea *pageData = NULL; + char *bufBlock = NULL; uint32 nblock = 0; uint32 blk_start = 0; uint32 blk_end = 0; @@ -635,9 +771,8 @@ int ReadFileForRemote(RemoteReadFileKey *key, XLogRecPtr lsn, bytea** fileData, } else { spc = spc_open(key->relfilenode.spcNode, key->relfilenode.dbNode, false, false); if (!spc) { - ereport(WARNING, (errmodule(MOD_REMOTE), - errmsg("Spc open failed. spcNode is: %u, dbNode is %u", - key->relfilenode.spcNode, key->relfilenode.dbNode))); + ereport(WARNING, (errmodule(MOD_REMOTE), errmsg("Spc open failed. spcNode is: %u, dbNode is %u", + key->relfilenode.spcNode, key->relfilenode.dbNode))); return REMOTE_READ_IO_ERROR; } nblock = spc_size(spc, key->relfilenode.relNode, key->forknum); @@ -652,7 +787,7 @@ int ReadFileForRemote(RemoteReadFileKey *key, XLogRecPtr lsn, bytea** fileData, blk_start = key->blockstart; blk_end = (nblock >= blk_start + MAX_BATCH_READ_BLOCKNUM ? blk_start + MAX_BATCH_READ_BLOCKNUM : nblock); - pageData = (bytea*)palloc((blk_end - blk_start) * BLCKSZ + VARHDRSZ); + pageData = (bytea *)palloc((blk_end - blk_start) * BLCKSZ + VARHDRSZ); SET_VARSIZE(pageData, ((blk_end - blk_start) * BLCKSZ + VARHDRSZ)); /* primary read page, need read page by ReadBuffer_common */ @@ -678,8 +813,8 @@ int ReadFileForRemote(RemoteReadFileKey *key, XLogRecPtr lsn, bytea** fileData, if (ret_code != REMOTE_READ_OK) { pfree(bufBlock); pfree(pageData); - ereport(ERROR, (errmodule(MOD_REMOTE), errmsg("repair file failed, read block %u error, retcode=%d", - i, rc))); + ereport(ERROR, + (errmodule(MOD_REMOTE), errmsg("repair file failed, read block %u error, retcode=%d", i, rc))); return ret_code; } rc = memcpy_s(VARDATA(pageData) + j * BLCKSZ, BLCKSZ, bufBlock, BLCKSZ); @@ -707,60 +842,92 @@ int ReadFileForRemote(RemoteReadFileKey *key, XLogRecPtr lsn, bytea** fileData, const int REGR_MCR_SIZE_1MB = 1048576; const int CLOG_NODE = 1; const int CSN_NODE = 2; -int ReadCOrCsnFileForRemote(RelFileNode rnode, bytea** fileData) +/* + * 鍔熻兘锛氫粠杩滅▼璇诲彇 CLOG 鎴 CSN 鏂囦欢鍐呭 + * + * 璇ュ嚱鏁扮敤浜庝粠杩滅▼鑺傜偣璇诲彇 CLOG 鎴 CSN 鏂囦欢鐨勫唴瀹癸紝骞跺皢鍏跺瓨鍌ㄥ湪 fileData 涓傝繖浜涙枃浠剁敤浜庝簨鍔℃棩蹇楄褰曞拰 CSN 鎺у埗銆 + * 鍑芥暟棣栧厛纭畾瑕佽鍙栫殑鏂囦欢绫诲瀷锛圕LOG 鎴 CSN锛夛紝鐒跺悗鏋勯犳枃浠惰矾寰勫苟鎵撳紑鏂囦欢銆傚鏋滄枃浠朵笉瀛樺湪锛屽垯杩斿洖閿欒銆 + * 鍚﹀垯锛屽嚱鏁板皢鏂囦欢鍐呭璇诲彇鍒板唴瀛樼紦鍐插尯涓紝灏嗗叾澶嶅埗鍒 bytea 绫诲瀷鐨勬暟鎹粨鏋勪腑锛屽苟灏嗗叾杩斿洖銆 + * + * 鍙傛暟鍒楄〃锛 + * rnode锛氳璇诲彇鏂囦欢鐨勫叧鑱旀枃浠惰妭鐐逛俊鎭紝鍖呮嫭绌洪棿ID銆佹暟鎹簱ID鍜屾枃浠禝D + * fileData锛氱敤浜庡瓨鍌ㄨ鍙栨枃浠跺唴瀹圭殑 bytea 绫诲瀷鏁版嵁鐨勬寚閽 + * + * 杩斿洖鍊硷細 + * 濡傛灉鎴愬姛璇诲彇鏂囦欢锛屽皢杩斿洖 0銆 + * 濡傛灉璇诲彇澶辫触鎴栧嚭鐜伴敊璇紝灏嗚繑鍥 -1銆 + * + * 娉ㄦ剰浜嬮」锛 + * - 鍑芥暟鏍规嵁鏂囦欢鑺傜偣鐨勭┖闂碔D鏉ョ‘瀹氭枃浠剁被鍨嬶紝CLOG 鎴 CSN銆 + * - 鍑芥暟鏋勯犳枃浠惰矾寰勫苟灏濊瘯鎵撳紑鏂囦欢銆傚鏋滄枃浠朵笉瀛樺湪锛屽皢杩斿洖 -1銆 + * - 鍑芥暟浣跨敤 pread 浠庢枃浠朵腑璇诲彇鍐呭锛岀劧鍚庡皢鍏跺鍒跺埌 bytea 鏁版嵁缁撴瀯涓 + * - 濡傛灉鏂囦欢璇诲彇澶辫触锛屽嚱鏁板皢杩斿洖 -1锛屽苟璁板綍閿欒娑堟伅銆 + * - 濡傛灉鏂囦欢鍐呭瓒呰繃棰勫畾涔夌殑鏈澶уぇ灏忥紙logSize锛夛紝鍑芥暟灏嗚繑鍥 -1銆 + * - 鍦ㄦ垚鍔熻鍙栨枃浠跺悗锛屽嚱鏁板皢鏂囦欢鍐呭瀛樺偍鍦 fileData 涓苟杩斿洖 0銆 + * - 鍑芥暟璐熻矗閲婃斁鍒嗛厤鐨勫唴瀛樺苟鍏抽棴鏂囦欢鎻忚堪绗︺ + */ +int ReadCOrCsnFileForRemote(RelFileNode rnode, bytea **fileData) { uint32 flags = O_RDWR | PG_BINARY; int fd = -1; - char* logType = NULL; - char* path = (char*)palloc0(MAX_PATH); + char *logType = NULL; + char *path = (char *)palloc0(MAX_PATH); errno_t rc; uint32 logSize = 16 * REGR_MCR_SIZE_1MB; - char *buffer = (char*)palloc(logSize); + char *buffer = (char *)palloc(logSize); int result = -1; + // 纭畾鏂囦欢绫诲瀷锛圕LOG 鎴 CSN锛 if (rnode.spcNode == CLOG_NODE) { logType = "pg_clog"; } else if (rnode.spcNode == CSN_NODE) { logType = "pg_csnlog"; } else { - ereport(LOG, (errmodule(MOD_SEGMENT_PAGE), errmsg("File type\"%u\" does not exist, stop read here.", - rnode.spcNode))); + // 鏈煡鏂囦欢绫诲瀷锛岃褰曟棩蹇楀苟杩斿洖閿欒 + ereport(LOG, (errmodule(MOD_SEGMENT_PAGE), + errmsg("File type\"%u\" does not exist, stop read here.", rnode.spcNode))); } + // 鏋勯犳枃浠惰矾寰 rc = snprintf_s(path, MAX_PATH, MAX_PATH - 1, "%s/%012u", logType, rnode.relNode); securec_check_ss(rc, "\0", "\0"); + // 灏濊瘯鎵撳紑鏂囦欢 fd = BasicOpenFile(path, flags, S_IWUSR | S_IRUSR); if (fd < 0) { pfree(buffer); if (errno != ENOENT) { + // 鎵撳紑鏂囦欢澶辫触锛岃褰曢敊璇秷鎭苟杩斿洖 -1 ereport(ERROR, (errcode_for_file_access(), errmsg("could not open file \"%s\": %m", path))); } - // The file does not exist, break. - ereport(LOG, - (errmodule(MOD_SEGMENT_PAGE), errmsg("File \"%s\" does not exist, stop read here.", path))); + // 鏂囦欢涓嶅瓨鍦紝璁板綍鏃ュ織骞惰繑鍥 -1 + ereport(LOG, (errmodule(MOD_SEGMENT_PAGE), errmsg("File \"%s\" does not exist, stop read here.", path))); pfree(path); return -1; } + + // 璇诲彇鏂囦欢鍐呭鍒板唴瀛樼紦鍐插尯 pgstat_report_waitevent(WAIT_EVENT_DATA_FILE_READ); uint32 nbytes = pread(fd, buffer, logSize, 0); pgstat_report_waitevent(WAIT_EVENT_END); + + // 鍏抽棴鏂囦欢 if (close(fd)) { pfree(path); pfree(buffer); ereport(ERROR, (errcode_for_file_access(), errmsg("could not close file \"%s\": %m", path))); } + // 妫鏌ヨ鍙栫殑鏂囦欢鍐呭鏄惁瓒呰繃棰勫畾涔夌殑鏈澶уぇ灏 if (nbytes > logSize) { pfree(buffer); - ereport(ERROR, - (errcode(MOD_SEGMENT_PAGE), - errcode_for_file_access(), + ereport(ERROR, (errcode(MOD_SEGMENT_PAGE), errcode_for_file_access(), errmsg("could not read file %s. nbytes:%u, logSize:%u", path, nbytes, logSize))); pfree(path); return -1; } else { - bytea* pageData = (bytea*)palloc(nbytes + VARHDRSZ); + // 鍒嗛厤鍐呭瓨骞跺鍒舵枃浠跺唴瀹瑰埌 bytea 鏁版嵁缁撴瀯涓 + bytea *pageData = (bytea *)palloc(nbytes + VARHDRSZ); SET_VARSIZE(pageData, (nbytes + VARHDRSZ)); rc = memcpy_s(VARDATA(pageData), nbytes, buffer, nbytes); if (rc != EOK) { @@ -770,10 +937,13 @@ int ReadCOrCsnFileForRemote(RelFileNode rnode, bytea** fileData) ereport(ERROR, (errmodule(MOD_REMOTE), errmsg("repair file failed, memcpy_s error, retcode=%d", rc))); return -1; } else { + // 灏嗘枃浠跺唴瀹硅繑鍥炵粰璋冪敤鑰 *fileData = pageData; result = 0; } } + + // 閲婃斁鍒嗛厤鐨勫唴瀛樺苟杩斿洖缁撴灉 pfree(path); pfree(buffer); return result; diff --git a/src/gausskernel/storage/remote/remote_read.cpp b/src/gausskernel/storage/remote/remote_read.cpp index 505e159a7..6b547ca26 100755 --- a/src/gausskernel/storage/remote/remote_read.cpp +++ b/src/gausskernel/storage/remote/remote_read.cpp @@ -37,9 +37,23 @@ * @IN error_code: remote read error code * @Return: remote read error message */ -const char* RemoteReadErrMsg(int error_code) +/* + * 鍔熻兘锛氳幏鍙栬繙绋嬫枃浠惰鍙栭敊璇爜瀵瑰簲鐨勯敊璇秷鎭 + * + * 鍙傛暟鍒楄〃锛 + * error_code锛氳繙绋嬫枃浠惰鍙栭敊璇爜锛岄氬父鏄竴涓暣鏁板艰〃绀虹壒瀹氱殑閿欒绫诲瀷 + * + * 杩斿洖鍊硷細 + * 杩斿洖涓涓瓧绗︿覆鎸囬拡锛岃〃绀轰笌閿欒鐮佸搴旂殑閿欒娑堟伅 + * + * 娉ㄦ剰浜嬮」锛 + * - 璇ュ嚱鏁版牴鎹紶鍏ョ殑閿欒鐮佽繑鍥炵浉搴旂殑閿欒娑堟伅锛岀敤浜庤В閲婇敊璇師鍥犮 + * - 閿欒鐮侀氬父鏄竴涓暣鏁板硷紝瀵瑰簲涓嶅悓鐨勯敊璇被鍨嬨 + * - 濡傛灉浼犲叆鐨勯敊璇爜娌℃湁鍖归厤鐨勯敊璇秷鎭紝鍑芥暟灏嗚繑鍥炰竴涓粯璁ょ殑閿欒娑堟伅銆 + */ +const char *RemoteReadErrMsg(int error_code) { - const char* error_msg = ""; + const char *error_msg = ""; switch (error_code) { case REMOTE_READ_OK: error_msg = "normal"; @@ -79,27 +93,40 @@ const char* RemoteReadErrMsg(int error_code) return error_msg; } +/* + * 鍔熻兘锛氳幏鍙栦富鏈嶅姟鐨勫湴鍧 + * + * 鍙傛暟鍒楄〃锛 + * address锛氱敤浜庡瓨鍌ㄤ富鏈嶅姟鍦板潃鐨勫瓧绗︿覆 + * address_len锛氬瓧绗︿覆鍦板潃鐨勬渶澶ч暱搴 + * + * 娉ㄦ剰浜嬮」锛 + * - 濡傛灉浼犲叆鐨勫湴鍧涓虹┖锛屽湴鍧闀垮害涓 0锛屾垨鑰 WalRcv 鏁版嵁缁撴瀯涓虹┖锛屽嚱鏁板皢鐩存帴杩斿洖銆 + * - 鍑芥暟閫氳繃浜掓枼閿佷繚璇佸绾跨▼鐜涓嬬殑鏁版嵁璁块棶瀹夊叏銆 + * - 濡傛灉 WalRcv 鐨勮繘绋 ID 涓 0 鎴栬 WalRcv 涓嶅湪杩愯鐘舵侊紝鍑芥暟灏嗙洿鎺ヨ繑鍥炪 + * - 鍑芥暟灏嗘牸寮忓寲涓绘湇鍔$殑鍦板潃瀛楃涓诧紝骞跺瓨鍌ㄥ湪浼犲叆鐨 address 鍙傛暟涓 + */ void GetPrimaryServiceAddress(char *address, size_t address_len) { if (address == NULL || address_len == 0 || t_thrd.walreceiverfuncs_cxt.WalRcv == NULL) - return; + return; // 濡傛灉浼犲叆鐨勫湴鍧涓虹┖锛屽湴鍧闀垮害涓 0锛屾垨鑰 WalRcv 涓虹┖锛岀洿鎺ヨ繑鍥 - bool is_running = false; - volatile WalRcvData *walrcv = t_thrd.walreceiverfuncs_cxt.WalRcv; - int rc = 0; + bool is_running = false; // 鐢ㄤ簬鏍囪瘑 WalRcv 鏄惁姝e湪杩愯 + volatile WalRcvData *walrcv = t_thrd.walreceiverfuncs_cxt.WalRcv; // 鑾峰彇 WalRcv 鏁版嵁缁撴瀯鐨勬寚閽 + int rc = 0; // 鐢ㄤ簬瀛樺偍 snprintf_s 鍑芥暟鐨勮繑鍥炲 - SpinLockAcquire(&walrcv->mutex); - is_running = walrcv->isRuning; - SpinLockRelease(&walrcv->mutex); + SpinLockAcquire(&walrcv->mutex); // 鑾峰彇浜掓枼閿佷互璁块棶 WalRcv 鏁版嵁缁撴瀯 + is_running = walrcv->isRuning; // 鑾峰彇 WalRcv 鏄惁姝e湪杩愯鐨勭姸鎬 + SpinLockRelease(&walrcv->mutex); // 閲婃斁浜掓枼閿 if (walrcv->pid == 0 || !is_running) - return; + return; // 濡傛灉 WalRcv 鐨勮繘绋 ID 涓 0 鎴栬 WalRcv 涓嶅湪杩愯鐘舵侊紝鐩存帴杩斿洖 - SpinLockAcquire(&walrcv->mutex); + SpinLockAcquire(&walrcv->mutex); // 鍐嶆鑾峰彇浜掓枼閿佷互璁块棶 WalRcv 鏁版嵁缁撴瀯 rc = snprintf_s(address, address_len, (address_len - 1), "%s@%d", walrcv->conn_channel.remotehost, - walrcv->conn_channel.remoteport); - securec_check_ss(rc, "\0", "\0"); - SpinLockRelease(&walrcv->mutex); + walrcv->conn_channel.remoteport); // 浣跨敤 snprintf_s 鏍煎紡鍖栧湴鍧瀛楃涓 + securec_check_ss(rc, "\0", "\0"); // 妫鏌 snprintf_s 鍑芥暟鐨勮繑鍥炲 + SpinLockRelease(&walrcv->mutex); // 閲婃斁浜掓枼閿 } /* @@ -108,7 +135,27 @@ void GetPrimaryServiceAddress(char *address, size_t address_len) * @IN/OUT second_address: second_address * @IN address_len: address len */ -void GetRemoteReadAddress(char* firstAddress, char* secondAddress, size_t addressLen) +/* + * 鍔熻兘锛氳幏鍙栬繙绋嬭鍙栧湴鍧 + * + * 鍙傛暟鍒楄〃锛 + * firstAddress锛氱敤浜庡瓨鍌ㄧ涓涓繙绋嬭鍙栧湴鍧鐨勭紦鍐插尯 + * secondAddress锛氱敤浜庡瓨鍌ㄧ浜屼釜杩滅▼璇诲彇鍦板潃鐨勭紦鍐插尯 + * addressLen锛氱紦鍐插尯鐨勯暱搴 + * + * 娉ㄦ剰浜嬮」锛 + * - 璇ュ嚱鏁扮敤浜庤幏鍙栫敤浜庤繙绋嬭鍙栫殑鍦板潃淇℃伅銆 + * - 鍑芥暟棣栧厛纭繚浼犲叆鐨勭涓涓湴鍧缂撳啿鍖烘湁鏁堜笖闀垮害澶т簬0銆 + * - 鐒跺悗鏍规嵁鏈嶅姟鍣ㄧ殑杩愯妯″紡閫夋嫨鐩稿簲鐨勬搷浣滐細 + * - 濡傛灉鏈嶅姟鍣ㄥ浜嶥N_DUMMY_STANDYS_MODE涓嬶紝妫鏌ユ槸鍚︿负PRIMARY_MODE骞剁‘淇濅富澶囪妭鐐瑰噯澶囧ソ杩涜杩滅▼璇诲彇銆 + * 濡傛灉鏄紝灏嗙涓涓湴鍧缂撳啿鍖鸿缃负涓诲鑺傜偣鐨勮繙绋嬩富鏈哄湴鍧銆 + * - 濡傛灉鏈嶅姟鍣ㄥ浜嶥N_MULTI_STANDYS_MODE涓嬶紝妫鏌ユ湇鍔″櫒妯″紡锛 + * - 濡傛灉鏄疨RIMARY_MODE锛岃皟鐢 GetFastestReplayStandByServiceAddress 鑾峰彇鏈蹇殑澶囩敤鑺傜偣鏈嶅姟鍦板潃锛 + * 骞跺皢绗竴涓拰绗簩涓湴鍧缂撳啿鍖鸿缃负鐩稿簲鐨勪富鏈哄湴鍧銆 + * - 濡傛灉鏄疭TANDBY_MODE锛岃皟鐢 GetPrimaryServiceAddress 鑾峰彇涓昏妭鐐规湇鍔″湴鍧锛屽苟灏嗙涓涓湴鍧缂撳啿鍖鸿缃负涓绘満鍦板潃銆 + * - 濡傛灉鏈嶅姟鍣ㄦā寮忎笉鍖归厤浠ヤ笂浠讳綍涓绉嶆儏鍐碉紝鍑芥暟灏嗚繑鍥炪 + */ +void GetRemoteReadAddress(char *firstAddress, char *secondAddress, size_t addressLen) { char ip[MAX_IPADDR_LEN] = {0}; char port[MAX_IPADDR_LEN] = {0}; @@ -118,7 +165,7 @@ void GetRemoteReadAddress(char* firstAddress, char* secondAddress, size_t addres if (firstAddress == NULL || addressLen == 0) return; - volatile HaShmemData* hashmdata = t_thrd.postmaster_cxt.HaShmData; + volatile HaShmemData *hashmdata = t_thrd.postmaster_cxt.HaShmData; ServerMode serverMode = hashmdata->current_mode; if (IS_DN_DUMMY_STANDYS_MODE()) { @@ -127,8 +174,8 @@ void GetRemoteReadAddress(char* firstAddress, char* secondAddress, size_t addres } if (t_thrd.postmaster_cxt.ReplConnArray[1]) { - rc = snprintf_s(firstAddress, addressLen, (addressLen - 1), - "%s@%d", t_thrd.postmaster_cxt.ReplConnArray[1]->remotehost, + rc = snprintf_s(firstAddress, addressLen, (addressLen - 1), "%s@%d", + t_thrd.postmaster_cxt.ReplConnArray[1]->remotehost, t_thrd.postmaster_cxt.ReplConnArray[1]->remoteport); securec_check_ss(rc, "", ""); } @@ -159,21 +206,35 @@ void GetRemoteReadAddress(char* firstAddress, char* secondAddress, size_t addres } } -void GetIPAndPort(char* address, char* ip, char* port, size_t len) +/* + * 鍔熻兘锛氫粠鍦板潃瀛楃涓蹭腑鎻愬彇 IP 鍦板潃鍜岀鍙e彿 + * + * 鍙傛暟鍒楄〃锛 + * address锛氬寘鍚 IP 鍦板潃鍜岀鍙e彿鐨勫湴鍧瀛楃涓 + * ip锛氱敤浜庡瓨鍌ㄦ彁鍙栫殑 IP 鍦板潃鐨勫瓧绗︿覆 + * port锛氱敤浜庡瓨鍌ㄦ彁鍙栫殑绔彛鍙风殑瀛楃涓 + * len锛氬瓨鍌ㄥ湴鍧鐨勭紦鍐插尯鐨勬渶澶ч暱搴 + * + * 娉ㄦ剰浜嬮」锛 + * - 鍑芥暟浣跨敤 "@" 绗﹀彿灏嗗湴鍧瀛楃涓插垎鍓叉垚 IP 鍦板潃鍜岀鍙e彿涓ら儴鍒嗐 + * - 濡傛灉鍒嗗壊鎴愬姛锛屽苟涓旀彁鍙栫殑 IP 鍦板潃鍜岀鍙e彿涓嶄负绌轰笖鎬婚暱搴﹀皬浜 len锛屽皢瀹冧滑澶嶅埗鍒板搴旂殑缂撳啿鍖轰腑銆 + * - 濡傛灉鍒嗗壊澶辫触鎴栬呭鍒惰繃绋嬩腑鍑虹幇閿欒锛屽皢涓嶈繘琛屼换浣曟搷浣溿 + */ +void GetIPAndPort(char *address, char *ip, char *port, size_t len) { - char* outerPtr = NULL; - errno_t rc = EOK; - char* tmpIp; - char* tempPort; + char *outerPtr = NULL; // 鐢ㄤ簬 strtok_r 鍑芥暟鐨勫閮ㄦ寚閽 + errno_t rc = EOK; // 鐢ㄤ簬瀛樺偍鍑芥暟杩斿洖鍊肩殑閿欒鐮 + char *tmpIp; // 鐢ㄤ簬瀛樺偍鎻愬彇鐨 IP 鍦板潃鐨勪复鏃跺彉閲 + char *tempPort; // 鐢ㄤ簬瀛樺偍鎻愬彇鐨勭鍙e彿鐨勪复鏃跺彉閲 - tmpIp = strtok_r(address, "@", &outerPtr); - tempPort = strtok_r(NULL, "@", &outerPtr); + tmpIp = strtok_r(address, "@", &outerPtr); // 浣跨敤 "@" 绗﹀彿鍒嗗壊鍦板潃瀛楃涓诧紝骞惰幏鍙 IP 鍦板潃閮ㄥ垎 + tempPort = strtok_r(NULL, "@", &outerPtr); // 鑾峰彇鍓╀綑鐨勫瓧绗︿覆锛屽嵆绔彛鍙烽儴鍒 if (tmpIp != NULL && tmpIp[0] != '\0' && tempPort != NULL && tempPort[0] != '\0' && strlen(tmpIp) + strlen(tempPort) + 1 < len) { - rc = strcpy_s(ip, MAX_IPADDR_LEN, tmpIp); - securec_check(rc, "", ""); - rc = strcpy_s(port, MAX_IPADDR_LEN, tempPort); - securec_check(rc, "", ""); + rc = strcpy_s(ip, MAX_IPADDR_LEN, tmpIp); // 灏嗘彁鍙栫殑 IP 鍦板潃澶嶅埗鍒 ip 缂撳啿鍖 + securec_check(rc, "", ""); // 妫鏌ュ鍒惰繃绋嬩腑鐨勯敊璇 + rc = strcpy_s(port, MAX_IPADDR_LEN, tempPort); // 灏嗘彁鍙栫殑绔彛鍙峰鍒跺埌 port 缂撳啿鍖 + securec_check(rc, "", ""); // 妫鏌ュ鍒惰繃绋嬩腑鐨勯敊璇 } return; } @@ -184,7 +245,7 @@ void GetIPAndPort(char* address, char* ip, char* port, size_t len) */ bool CanRemoteRead() { - volatile HaShmemData* hashmdata = t_thrd.postmaster_cxt.HaShmData; + volatile HaShmemData *hashmdata = t_thrd.postmaster_cxt.HaShmData; ServerMode serveMode = hashmdata->current_mode; if (IsRemoteReadModeOn() && !IS_DN_WITHOUT_STANDBYS_MODE() && IS_PGXC_DATANODE && serveMode != NORMAL_MODE && @@ -214,7 +275,17 @@ int SetRemoteReadModeOffAndGetOldMode() g_instance.attr.attr_storage.remote_read_mode = REMOTE_READ_OFF; return oldRemoteRead; } - +/* + * 鍔熻兘锛氳缃繙绋嬭鍙栨ā寮 + * + * 鍙傛暟鍒楄〃锛 + * mode锛氳璁剧疆鐨勮繙绋嬭鍙栨ā寮忥紝閫氬父鏄竴涓暣鏁板艰〃绀烘ā寮 + * + * 娉ㄦ剰浜嬮」锛 + * - 璇ュ嚱鏁扮敤浜庤缃繙绋嬭鍙栨ā寮忥紝浠ュ奖鍝嶅悗缁殑杩滅▼鏂囦欢璇诲彇琛屼负銆 + * - 杩滅▼璇诲彇妯″紡閫氬父鏄竴涓暣鏁板硷紝涓嶅悓鐨勬ā寮忓彲鑳藉璇诲彇鎿嶄綔浜х敓涓嶅悓鐨勫奖鍝嶃 + * - 鍑芥暟绠鍗曞湴灏嗕紶鍏ョ殑 mode 鍙傛暟璧嬪肩粰鍏ㄥ眬鍙橀噺锛屼互瀹炵幇妯″紡鐨勮缃 + */ void SetRemoteReadMode(int mode) { g_instance.attr.attr_storage.remote_read_mode = mode; diff --git a/src/gausskernel/storage/smgr/knl_uundofile.cpp b/src/gausskernel/storage/smgr/knl_uundofile.cpp index 5cc6123e2..1785d0349 100644 --- a/src/gausskernel/storage/smgr/knl_uundofile.cpp +++ b/src/gausskernel/storage/smgr/knl_uundofile.cpp @@ -30,16 +30,15 @@ #define UNDOFORMAT(f) UNDODEBUGSTR f UNDODEBUGINFO /* Populate a file tag describing an undofile.cpp segment file. */ -#define INIT_UNDO_FILE_TAG(tag, rNode, segNo) \ - do \ - { \ - errno_t errorno = EOK; \ - errorno = memset_s(&(tag), sizeof(FileTag), (0), sizeof(FileTag)); \ - securec_check(errorno, "\0", "\0"); \ - (tag).handler = SYNC_HANDLER_UNDO; \ - (tag).forknum = MAIN_FORKNUM; \ - (tag).rnode = (rNode); \ - (tag).segno = (segNo); \ +#define INIT_UNDO_FILE_TAG(tag, rNode, segNo) \ + do { \ + errno_t errorno = EOK; \ + errorno = memset_s(&(tag), sizeof(FileTag), (0), sizeof(FileTag)); \ + securec_check(errorno, "\0", "\0"); \ + (tag).handler = SYNC_HANDLER_UNDO; \ + (tag).forknum = MAIN_FORKNUM; \ + (tag).rnode = (rNode); \ + (tag).segno = (segNo); \ } while (false); /* @@ -77,66 +76,106 @@ static const int UNDO_FILE_EXTEND_PAGES = 8; /* local routines */ static UndoFileState *AllocUndoFileState(void); static void GetUndoFilePath(int zoneId, uint32 dbId, int segno, char *path, int len); -static UndoFileState *OpenUndoFile(SMgrRelation reln, ForkNumber forknum, BlockNumber blockNum, ExtensionBehavior behavior); +static UndoFileState *OpenUndoFile(SMgrRelation reln, ForkNumber forknum, BlockNumber blockNum, + ExtensionBehavior behavior); static void RegisterDirtyUndoSegment(SMgrRelation reln, const UndoFileState *state); static void RegisterForgetUndoRequests(RelFileNodeBackend rnode, uint32 segno); static void RegisterUnlinkUndoRequests(RelFileNodeBackend rnode, uint32 segno); static BlockNumber GetUndoFileBlocks(SMgrRelation reln, ForkNumber forknum, const UndoFileState *state); void CheckUndoFileDirectory(UndoPersistence upersistence); - +/* + * 鍔熻兘锛氭牴鎹暟鎹簱ID纭畾UNDO鏂囦欢鐨勫ぇ灏 + * + * 鍙傛暟鍒楄〃锛 + * dbId锛氭暟鎹簱ID锛岀敤浜庣‘瀹歎NDO鏂囦欢澶у皬鐨勪緷鎹 + */ static inline uint32 UNDO_FILE_SIZE(uint32 dbId) { if (dbId == UNDO_DB_OID) { - return UNDO_FILE_MAXSIZE; + return UNDO_FILE_MAXSIZE; // 濡傛灉鏁版嵁搴揑D绛変簬UNDO_DB_OID锛屽垯杩斿洖UNDO_FILE_MAXSIZE } - return UNDO_META_MAXSIZE; + return UNDO_META_MAXSIZE; // 鍚﹀垯杩斿洖UNDO_META_MAXSIZE } +/* + * 鍔熻兘锛氭牴鎹暟鎹簱ID纭畾UNDO鏂囦欢鐨勫潡鏁 + * + * 鍙傛暟鍒楄〃锛 + * dbId锛氭暟鎹簱ID锛岀敤浜庣‘瀹歎NDO鏂囦欢鍧楁暟鐨勪緷鎹 + */ static inline uint32 UNDO_FILE_BLOCK(uint32 dbId) { if (dbId == UNDO_DB_OID) { - return UNDO_FILE_BLOCKS; + return UNDO_FILE_BLOCKS; // 濡傛灉鏁版嵁搴揑D绛変簬UNDO_DB_OID锛屽垯杩斿洖UNDO_FILE_BLOCKS } - return UNDO_META_BLOCKS; + return UNDO_META_BLOCKS; // 鍚﹀垯杩斿洖UNDO_META_BLOCKS } /* allocate UndoFileState memory. */ +/* + * 鍔熻兘锛氬垎閰峌ndoFileState缁撴瀯浣撶殑鍐呭瓨骞惰繑鍥炴寚閽 + * + * 鍙傛暟鍒楄〃锛氭棤 + */ static UndoFileState *AllocUndoFileState(void) { MemoryContext current; if (EnableLocalSysCache()) { - current = t_thrd.lsc_cxt.lsc->lsc_mydb_memcxt; + current = t_thrd.lsc_cxt.lsc->lsc_mydb_memcxt; // 鑾峰彇鏈湴绯荤粺缂撳瓨鐨勫唴瀛樹笂涓嬫枃 } else { - current = u_sess->storage_cxt.UndoFileCxt; + current = u_sess->storage_cxt.UndoFileCxt; // 鑾峰彇鍏ㄥ眬UndoFile涓婁笅鏂 } - return (UndoFileState *)MemoryContextAlloc(current, sizeof(UndoFileState)); + return (UndoFileState *)MemoryContextAlloc(current, + sizeof(UndoFileState)); // 鍒嗛厤UndoFileState缁撴瀯浣撶殑鍐呭瓨骞惰繑鍥炴寚閽 } - +/* + * 鍔熻兘锛氳缃甎ndoFileState缁撴瀯浣撶殑瀛楁鍊 + * + * 鍙傛暟鍒楄〃锛 + * state锛氭寚鍚慤ndoFileState缁撴瀯浣撶殑鎸囬拡 + * segno锛氭枃浠舵鍙 + * file锛氭枃浠跺彞鏌 + */ static inline void SetUndoFileState(UndoFileState *state, int segno, File file) { - state->segno = segno; - state->file = file; + state->segno = segno; // 璁剧疆UndoFileState缁撴瀯浣撶殑segno瀛楁 + state->file = file; // 璁剧疆UndoFileState缁撴瀯浣撶殑file瀛楁 } - +/* + * 鍔熻兘锛氬垵濮嬪寲Undo鏂囦欢鐩稿叧鐨勫唴瀛樹笂涓嬫枃 + * + * 鍙傛暟鍒楄〃锛氭棤 + */ void InitUndoFile(void) { + // 濡傛灉鍚敤浜嗘湰鍦扮郴缁熺紦瀛橈紝鐩存帴杩斿洖锛屼笉闇瑕佸垵濮嬪寲鍏ㄥ眬Undo鏂囦欢涓婁笅鏂 if (EnableLocalSysCache()) { return; } + // 纭繚鍏ㄥ眬Undo鏂囦欢涓婁笅鏂囧皻鏈垵濮嬪寲 Assert(u_sess->storage_cxt.UndoFileCxt == NULL); - u_sess->storage_cxt.UndoFileCxt = AllocSetContextCreate(u_sess->top_mem_cxt, "UndoFileSmgr", ALLOCSET_DEFAULT_SIZES); + // 鍒涘缓鍏ㄥ眬Undo鏂囦欢涓婁笅鏂囷紝鍩轰簬褰撳墠浼氳瘽鐨勯《绾у唴瀛樹笂涓嬫枃 u_sess->top_mem_cxt + u_sess->storage_cxt.UndoFileCxt = + AllocSetContextCreate(u_sess->top_mem_cxt, "UndoFileSmgr", ALLOCSET_DEFAULT_SIZES); } - +/* + * 鍔熻兘锛氳幏鍙朥ndo鏂囦欢鐨勭洰褰曡矾寰 + * + * 鍙傛暟鍒楄〃锛 + * path锛氱敤浜庡瓨鍌ㄧ洰褰曡矾寰勭殑缂撳啿鍖 + * len锛氱紦鍐插尯闀垮害 + * upersistence锛歎ndo鏂囦欢鐨勬寔涔呮э紝鍙互鏄疷NDO_PERMANENT銆乁NDO_UNLOGGED鎴朥NDO_TEMP + */ void GetUndoFileDirectory(char *path, int len, UndoPersistence upersistence) { Assert(len >= UNDO_FILE_DIR_LEN); errno_t rc = EOK; if (upersistence == UNDO_PERMANENT) { - rc = snprintf_s(path, len, len - 1, UNDO_PERMANENT_DIR); + rc = snprintf_s(path, len, len - 1, UNDO_PERMANENT_DIR); // 璁剧疆鐩綍璺緞涓烘案涔匲ndo鏂囦欢鐩綍 } else if (upersistence == UNDO_UNLOGGED) { - rc = snprintf_s(path, len, len - 1, UNDO_UNLOGGED_DIR); + rc = snprintf_s(path, len, len - 1, UNDO_UNLOGGED_DIR); // 璁剧疆鐩綍璺緞涓洪潪鏃ュ織Undo鏂囦欢鐩綍 } else { - rc = snprintf_s(path, len, len - 1, UNDO_TEMP_DIR); + rc = snprintf_s(path, len, len - 1, UNDO_TEMP_DIR); // 璁剧疆鐩綍璺緞涓轰复鏃禪ndo鏂囦欢鐩綍- } securec_check_ss(rc, "\0", "\0"); return; @@ -144,11 +183,13 @@ void GetUndoFileDirectory(char *path, int len, UndoPersistence upersistence) void CheckUndoDirectory(void) { + // 鐢ㄤ簬娴嬭瘯鐨勬潯浠剁紪璇戯紝妯℃嫙UNDO_CHECK_DIRECTORY_FAILED閿欒鎯呭喌 WHITEBOX_TEST_STUB(UNDO_CHECK_DIRECTORY_FAILED, WhiteboxDefaultErrorEmit); + // 灏濊瘯鍒涘缓Undo鏂囦欢鐨勬牴鐩綍锛屽鏋滃垱寤哄け璐ュ苟涓旈敊璇爜涓嶆槸EEXIST锛堢洰褰曞凡瀛樺湪锛夛紝鍒欐姤鍛婇敊璇 if (mkdir(UNDO_FILE_DIR_PREFIX, S_IRWXU) < 0 && errno != EEXIST) { - ereport(ERROR, (errcode_for_file_access(), - errmsg("could not create directory \"%s\": %m", UNDO_FILE_DIR_PREFIX))); + ereport(ERROR, + (errcode_for_file_access(), errmsg("could not create directory \"%s\": %m", UNDO_FILE_DIR_PREFIX))); } return; } @@ -156,28 +197,39 @@ void CheckUndoDirectory(void) void CheckUndoFileDirectory(UndoPersistence upersistence) { char dir[UNDO_FILE_DIR_LEN]; - GetUndoFileDirectory(dir, UNDO_FILE_DIR_LEN, upersistence); + GetUndoFileDirectory(dir, UNDO_FILE_DIR_LEN, upersistence); // 鑾峰彇Undo鏂囦欢鐩綍璺緞 + // 鐢ㄤ簬娴嬭瘯鐨勬潯浠剁紪璇戯紝妯℃嫙UNDO_CHECK_FILE_DIRECTORY_FAILED閿欒鎯呭喌 WHITEBOX_TEST_STUB(UNDO_CHECK_FILE_DIRECTORY_FAILED, WhiteboxDefaultErrorEmit); + // 灏濊瘯鍒涘缓Undo鏂囦欢鐩綍锛屽鏋滃垱寤哄け璐ュ苟涓旈敊璇爜涓嶆槸EEXIST锛堢洰褰曞凡瀛樺湪锛夛紝鍒欒繘琛岄澶栧鐞 if (mkdir(dir, S_IRWXU) != 0 && errno != EEXIST) { + // 濡傛灉閿欒鐮佷笉鏄疎NOENT锛堢洰褰曚笉瀛樺湪锛夋垨鑰呬笉澶勪簬XLOG鎭㈠鐘舵侊紝鍒欐姤鍛婇敊璇 if (errno != ENOENT || !t_thrd.xlog_cxt.InRecovery) { ereport(ERROR, (errcode_for_file_access(), errmsg("could not create directory \"%s\": %m", dir))); } + // 灏濊瘯鍒涘缓Undo鏂囦欢鐨勬牴鐩綍锛屽鏋滃垱寤哄け璐ュ苟涓旈敊璇爜涓嶆槸EEXIST锛堢洰褰曞凡瀛樺湪锛夛紝鍒欐姤鍛婇敊璇 if (mkdir(UNDO_FILE_DIR_PREFIX, S_IRWXU) < 0 && errno != EEXIST) { - ereport(ERROR, (errcode_for_file_access(), errmsg("could not create directory \"%s\": %m", UNDO_FILE_DIR_PREFIX))); + ereport(ERROR, + (errcode_for_file_access(), errmsg("could not create directory \"%s\": %m", UNDO_FILE_DIR_PREFIX))); } + // 鍐嶆灏濊瘯鍒涘缓Undo鏂囦欢鐩綍锛屽鏋滃垱寤哄け璐ュ苟涓旈敊璇爜涓嶆槸EEXIST锛堢洰褰曞凡瀛樺湪锛夛紝鍒欐姤鍛婇敊璇 if (mkdir(dir, S_IRWXU) != 0 && errno != EEXIST) { ereport(ERROR, (errcode_for_file_access(), errmsg("could not create directory \"%s\": %m", dir))); } } return; } - +/* + * 鍔熻兘锛氭竻鐞哢ndo鏂囦欢鐨勭洰褰曪紝濡傛灉鐩綍瀛樺湪鐨勮瘽 + * + * 鍙傛暟鍒楄〃锛 + * upersistence锛歎ndo鏂囦欢鐨勬寔涔呮э紝鍙互鏄疷NDO_PERMANENT銆乁NDO_UNLOGGED鎴朥NDO_TEMP + */ void CleanUndoFileDirectory(UndoPersistence upersistence) { char dir[UNDO_FILE_DIR_LEN]; - GetUndoFileDirectory(dir, UNDO_FILE_DIR_LEN, upersistence); + GetUndoFileDirectory(dir, UNDO_FILE_DIR_LEN, upersistence); // 鑾峰彇Undo鏂囦欢鐩綍璺緞 if (rmdir(dir) < 0 && errno != ENOENT) { /* try again */ if ((rmdir(dir) < 0) && (errno != ENOENT)) { @@ -186,15 +238,29 @@ void CleanUndoFileDirectory(UndoPersistence upersistence) } return; } - +/* + * 鍔熻兘锛氳幏鍙朥ndo鏂囦欢鐨勫畬鏁磋矾寰 + * + * 鍙傛暟鍒楄〃锛 + * zoneId锛歎ndo鏂囦欢鐨勫尯鍩烮D + * dbId锛氭暟鎹簱ID锛岀敤浜庡尯鍒嗘暟鎹枃浠跺拰鍏冩暟鎹枃浠 + * segno锛氭枃浠舵鍙 + * path锛氱敤浜庡瓨鍌ㄥ畬鏁磋矾寰勭殑缂撳啿鍖 + * len锛氱紦鍐插尯闀垮害 + */ void GetUndoFilePath(int zoneId, uint32 dbId, int segno, char *path, int len) { + // 纭繚缂撳啿鍖洪暱搴﹁冻澶熷ぇ Assert(len >= UNDO_FILE_PATH_LEN); char dir[UNDO_FILE_DIR_LEN]; errno_t rc = EOK; DECLARE_NODE_COUNT(); - GET_UPERSISTENCE_BY_ZONEID(zoneId, nodeCount); + GET_UPERSISTENCE_BY_ZONEID(zoneId, nodeCount); // 鑾峰彇鎸佷箙鎬х被鍨 + + // 鑾峰彇Undo鏂囦欢鐩綍璺緞 GetUndoFileDirectory(dir, UNDO_FILE_DIR_LEN, upersistence); + + // 鏍规嵁鏁版嵁搴揑D鐨勪笉鍚岋紝璁剧疆涓嶅悓鐨勬枃浠跺悕鏍煎紡 if (dbId == UNDO_DB_OID) { rc = snprintf_s(path, len, len - 1, "%s/%05X.%07zX", dir, zoneId, segno); } else { @@ -203,38 +269,66 @@ void GetUndoFilePath(int zoneId, uint32 dbId, int segno, char *path, int len) securec_check_ss(rc, "\0", "\0"); return; } - +/* + * 鍔熻兘锛氳幏鍙朥ndo鏂囦欢鐨勫潡鏁 + * + * 鍙傛暟鍒楄〃锛 + * reln锛歋MgrRelation瀵硅薄锛岀敤浜庤〃绀哄叧鑱旂殑Undo鏂囦欢 + * forknum锛欶orkNumber锛岃〃绀烘枃浠剁殑鍒嗗弶绫诲瀷 + * + * 杩斿洖鍊硷細鏈澶у潡鍙凤紙MaxBlockNumber锛夛紝琛ㄧず鏂囦欢鐨勫潡鏁 + */ BlockNumber GetUndoFileNblocks(SMgrRelation reln, ForkNumber forknum) { - return MaxBlockNumber; + return MaxBlockNumber; // 杩斿洖鏈澶у潡鍙凤紝琛ㄧず鏂囦欢鐨勫潡鏁 } /* Get number of blocks present in a single disk undofile. */ +/* + * 鍔熻兘锛氳幏鍙朥ndo鏂囦欢鐨勫潡鏁 + * + * 鍙傛暟鍒楄〃锛 + * reln锛歋MgrRelation瀵硅薄锛岀敤浜庤〃绀哄叧鑱旂殑Undo鏂囦欢 + * forknum锛欶orkNumber锛岃〃绀烘枃浠剁殑鍒嗗弶绫诲瀷 + * state锛歎ndoFileState瀵硅薄锛岃〃绀篣ndo鏂囦欢鐨勭姸鎬佷俊鎭 + * + * 杩斿洖鍊硷細BlockNumber锛岃〃绀烘枃浠剁殑鍧楁暟 + */ static BlockNumber GetUndoFileBlocks(SMgrRelation reln, ForkNumber forknum, const UndoFileState *state) { + // 纭繚浼犲叆鐨刄ndoFileState瀵硅薄涓嶄负绌 Assert(state != NULL); - + // 鑾峰彇鏂囦欢鐨勫畬鏁磋矾寰 char *fileName = FilePathName(state->file); + // 浣跨敤FileSeek鍑芥暟鑾峰彇鏂囦欢鐨勯暱搴 off_t len = FileSeek(state->file, 0L, SEEK_END); + // 鑾峰彇Undo鏂囦欢鐨勬湡鏈涘ぇ灏 uint32 undoFileSize = UNDO_FILE_SIZE(reln->smgr_rnode.node.dbNode); - + // 鐢ㄤ簬娴嬭瘯鐨勬潯浠剁紪璇戯紝妯℃嫙UNDO_GET_FILE_BLOCKS_FAILED閿欒鎯呭喌 WHITEBOX_TEST_STUB(UNDO_GET_FILE_BLOCKS_FAILED, WhiteboxDefaultErrorEmit); - + // 妫鏌ユ枃浠堕暱搴︽槸鍚﹀皬浜0锛屽鏋滄槸鍒欐姤鍛婇敊璇苟鍏抽棴鏂囦欢 if (len < 0) { CloseUndoFile(reln, forknum, InvalidBlockNumber); ereport(ERROR, (errmsg(UNDOFORMAT("could not seek to end of file \"%s\": %m."), fileName))); } - + // 妫鏌ユ枃浠堕暱搴︽槸鍚︾鍚堟湡鏈涚殑鍧楀ぇ灏忥紝濡傛灉涓嶇鍚堝垯鎶ュ憡閿欒骞跺叧闂枃浠 if (len % BLCKSZ != 0) { CloseUndoFile(reln, forknum, InvalidBlockNumber); ereport(ERROR, (errmsg(UNDOFORMAT("The expected size of file \"%s\" is %d, but the actual size is %ld."), - fileName, undoFileSize, len))); + fileName, undoFileSize, len))); } /* note that this calculation will ignore any partial block at EOF */ - return (BlockNumber)(len / BLCKSZ); + return (BlockNumber)(len / BLCKSZ); // 杩斿洖鏂囦欢鐨勫潡鏁 } - +/* + * 鍔熻兘锛氬垱寤篣ndo鏂囦欢 + * + * 鍙傛暟鍒楄〃锛 + * reln锛歋MgrRelation瀵硅薄锛岀敤浜庤〃绀哄叧鑱旂殑Undo鏂囦欢 + * forknum锛欶orkNumber锛岃〃绀烘枃浠剁殑鍒嗗弶绫诲瀷 + * isRedo锛氫竴涓竷灏斿硷紝鎸囩ず鏄惁鍦ㄩ噸鍋氫腑鍒涘缓Undo鏂囦欢 + */ void CreateUndoFile(SMgrRelation reln, ForkNumber forknum, bool isRedo) { /* Undo file creation is managed by ExtendUndoFile. */ @@ -242,13 +336,26 @@ void CreateUndoFile(SMgrRelation reln, ForkNumber forknum, bool isRedo) } /* Create an undo file, expand the file by 8 pages until the file size reaches 1 MB. */ +/* + * 鍔熻兘锛氭墿灞昒ndo鏂囦欢 + * + * 鍙傛暟鍒楄〃锛 + * reln锛歋MgrRelation瀵硅薄锛岀敤浜庤〃绀哄叧鑱旂殑Undo鏂囦欢 + * forknum锛欶orkNumber锛岃〃绀烘枃浠剁殑鍒嗗弶绫诲瀷 + * blockno锛氳鎵╁睍鍒扮殑鍧楀彿 + * buffer锛氱敤浜庡~鍏呯殑缂撳啿鍖猴紙鏈娇鐢級 + * skipFsync锛氫竴涓竷灏斿硷紝鎸囩ず鏄惁璺宠繃fsync + */ void ExtendUndoFile(SMgrRelation reln, ForkNumber forknum, BlockNumber blockno, char *buffer, bool skipFsync) { + // 纭繚SMgrRelation瀵硅薄涓嶄负绌 Assert(reln != NULL); - + // 鑾峰彇Undo鏂囦欢鐨勭姸鎬佷俊鎭 UndoFileState *state = (UndoFileState *)reln->fileState; + // 鑾峰彇Undo鏂囦欢鐨勫潡澶у皬鍜屾湡鏈涘ぇ灏 uint32 undoFileBlocks = UNDO_FILE_BLOCK(reln->smgr_rnode.node.dbNode); uint32 undoFileSize = UNDO_FILE_SIZE(reln->smgr_rnode.node.dbNode); + // 鍒濆鍖栧彉閲 int segno = -1; char path[UNDO_FILE_PATH_LEN]; File fd; @@ -258,55 +365,64 @@ void ExtendUndoFile(SMgrRelation reln, ForkNumber forknum, BlockNumber blockno, struct stat statBuffer; BlockNumber blockNum; RelFileNodeForkNum filenode; - + // 濡傛灉浼犲叆鐨勫潡鍙锋棤鏁堬紝鍒欐姤鍛婇敊璇 if (blockno == InvalidBlockNumber) { ereport(ERROR, (errmsg(UNDOFORMAT("cannot extend undo file beyond %u blocks."), InvalidBlockNumber))); } - + // 濡傛灉Undo鏂囦欢鐨勭姸鎬佷俊鎭负绌猴紝鍒欏垎閰嶄竴涓柊鐨勭姸鎬佷俊鎭璞 if (state == NULL) { state = AllocUndoFileState(); reln->fileState = state; } else if (state->file > 0) { FileClose(state->file); } + // 璁剧疆鐘舵佷俊鎭 SetUndoFileState(state, -1, -1); WHITEBOX_TEST_STUB(UNDO_EXTEND_FILE_FAILED, WhiteboxDefaultErrorEmit); - - ADIO_RUN() { + // 鏉′欢缂栬瘧锛屾牴鎹槸鍚︽敮鎸丄DIO璁剧疆鏍囧織 + ADIO_RUN() + { flags |= O_DIRECT; } ADIO_END(); - + // 璁$畻鎵╁睍鍧楁墍鍦ㄧ殑娈靛彿 segno = (int)(blockno / undoFileBlocks); - GetUndoFilePath(reln->smgr_rnode.node.relNode, reln->smgr_rnode.node.dbNode, - segno, path, UNDO_FILE_PATH_LEN); + // 鑾峰彇Undo鏂囦欢鐨勫畬鏁磋矾寰 + GetUndoFilePath(reln->smgr_rnode.node.relNode, reln->smgr_rnode.node.dbNode, segno, path, UNDO_FILE_PATH_LEN); + // 鏋勫缓鏂囦欢鑺傜偣瀵硅薄 filenode = RelFileNodeForkNumFill(reln->smgr_rnode, forknum, segno); + // 鎵撳紑鏂囦欢 fd = DataFileIdOpenFile(path, filenode, (int)flags, S_IRUSR | S_IWUSR); + // 濡傛灉鎵撳紑鏂囦欢澶辫触锛屽垯杩涜閿欒澶勭悊 if (fd < 0) { int saveErrno = errno; DECLARE_NODE_COUNT(); GET_UPERSISTENCE_BY_ZONEID((int)reln->smgr_rnode.node.relNode, nodeCount); CheckUndoFileDirectory(upersistence); fd = DataFileIdOpenFile(path, filenode, (int)flags, S_IRUSR | S_IWUSR); + // 濡傛灉鍐嶆鎵撳紑鏂囦欢澶辫触锛屽垯鎶ュ憡閿欒 if (fd < 0) { /* be sure to report the error reported by create, not open */ + // 濡傛灉鍐嶆鎵撳紑鏂囦欢澶辫触锛屽垯鎶ュ憡閿欒 errno = saveErrno; CloseUndoFile(reln, forknum, InvalidBlockNumber); ereport(ERROR, (errmsg(UNDOFORMAT("could not create file \"%s\": %m."), path))); } } - + // 鑾峰彇鏂囦欢鐘舵佷俊鎭 if (fstat(GetVfdCache()[fd].fd, &statBuffer) < 0) { CloseUndoFile(reln, forknum, InvalidBlockNumber); ereport(ERROR, (errmsg(UNDOFORMAT("could not stat file \"%s\": %m."), path))); } - + // 璁剧疆鐘舵佷俊鎭 SetUndoFileState(state, segno, fd); + // 鑾峰彇鏂囦欢鐨勫綋鍓嶄綅缃 seekpos = statBuffer.st_size; char undoBuffer[BLCKSZ] = {'\0'}; /* Extend file to undoFileSize. */ + // 鎵╁睍鏂囦欢鍒版湡鏈涘ぇ灏 while (seekpos < (off_t)undoFileSize) { off_t diffSize = (off_t)undoFileSize - seekpos; if (diffSize < BLCKSZ) { @@ -314,21 +430,25 @@ void ExtendUndoFile(SMgrRelation reln, ForkNumber forknum, BlockNumber blockno, } else { nbytes = FilePWrite(fd, (char *)undoBuffer, BLCKSZ, seekpos, WAIT_EVENT_UNDO_FILE_EXTEND); } + // 鎵╁睍鏂囦欢鍒版湡鏈涘ぇ灏 if (nbytes < 0) { CloseUndoFile(reln, forknum, InvalidBlockNumber); + // 鍒犻櫎鍒涘缓澶辫触鐨刄ndo鏂囦欢 if (unlink(path) != 0) { - ereport(ERROR, (errmsg(UNDOFORMAT("could not delete undo file during initialization \"%s\": %m."), path))); + ereport(ERROR, + (errmsg(UNDOFORMAT("could not delete undo file during initialization \"%s\": %m."), path))); } ereport(ERROR, (errmsg(UNDOFORMAT("could not initialize undo log segment file \"%s\": %m."), path))); } seekpos += (off_t)nbytes; } - + // 濡傛灉涓嶈烦杩噁sync骞朵笖涓嶆槸涓存椂鏂囦欢锛屽垯娉ㄥ唽Dirty Undo Segment if (!skipFsync && !SmgrIsTemp(reln)) { RegisterDirtyUndoSegment(reln, state); } - + // 鑾峰彇鏂囦欢鐨勫潡鏁 blockNum = GetUndoFileBlocks(reln, forknum, state); + // 濡傛灉鏂囦欢鐨勫潡鏁颁笉绛変簬鏈熸湜鐨勫潡鏁帮紝鍒欐姤鍛奝ANIC閿欒 if (blockNum != undoFileBlocks) { ereport(PANIC, (errmsg(UNDOFORMAT("The undo file \"%s\" size is incorrect, blockNum=%u."), path, blockNum))); } @@ -336,26 +456,46 @@ void ExtendUndoFile(SMgrRelation reln, ForkNumber forknum, BlockNumber blockno, } /* Open the undo file and return the UndoFileState. */ -static UndoFileState *OpenUndoFile(SMgrRelation reln, ForkNumber forknum, BlockNumber blockno, ExtensionBehavior behavior) +/* + * 鍔熻兘锛氭墦寮Undo鏂囦欢 + * + * 鍙傛暟鍒楄〃锛 + * reln锛歋MgrRelation瀵硅薄锛岀敤浜庤〃绀哄叧鑱旂殑Undo鏂囦欢 + * forknum锛欶orkNumber锛岃〃绀烘枃浠剁殑鍒嗗弶绫诲瀷 + * blockno锛氳鎵撳紑鐨勫潡鍙 + * behavior锛氭墿灞曡涓猴紙鐢ㄤ簬澶勭悊鏂囦欢涓嶅瓨鍦ㄧ殑鎯呭喌锛 + * + * 杩斿洖鍊硷細鎵撳紑鐨刄ndo鏂囦欢鐨勭姸鎬佷俊鎭紙UndoFileState瀵硅薄锛 + */ +static UndoFileState *OpenUndoFile(SMgrRelation reln, ForkNumber forknum, BlockNumber blockno, + ExtensionBehavior behavior) { + // 纭繚SMgrRelation瀵硅薄涓嶄负绌 Assert(reln != NULL); + // 鑾峰彇Undo鏂囦欢鐨勭姸鎬佷俊鎭 UndoFileState *state = (UndoFileState *)reln->fileState; + + // 鑾峰彇Undo鏂囦欢鐨勫潡澶у皬 uint32 undoFileBlocks = UNDO_FILE_BLOCK(reln->smgr_rnode.node.dbNode); + + // 鏋勫缓Undo鏂囦欢鐨勮矾寰 char path[UNDO_FILE_PATH_LEN]; File fd; uint32 flags = O_RDWR | PG_BINARY; + // 璁$畻鍧楁墍鍦ㄧ殑娈靛彿 int segno = (int)(blockno / undoFileBlocks); BlockNumber blockNum; RelFileNodeForkNum filenode; WHITEBOX_TEST_STUB(UNDO_OPEN_FILE_FAILED, WhiteboxDefaultErrorEmit); - + // 濡傛灉浼犲叆鐨勫潡鍙锋棤鏁堬紝鍒欐姤鍛婇敊璇 if (blockno == InvalidBlockNumber) { ereport(ERROR, (errmsg(UNDOFORMAT("cannot open undo file beyond %u blocks."), InvalidBlockNumber))); } /* No work if already open */ + // 濡傛灉鏂囦欢宸茬粡鎵撳紑锛屽垯鐩存帴杩斿洖鐘舵佷俊鎭 if (state != NULL) { if (state->file > 0) { if (state->segno == segno) { @@ -368,35 +508,43 @@ static UndoFileState *OpenUndoFile(SMgrRelation reln, ForkNumber forknum, BlockN state = AllocUndoFileState(); reln->fileState = state; } + // 璁剧疆鐘舵佷俊鎭 SetUndoFileState(state, -1, -1); - - ADIO_RUN() { + // 鏉′欢缂栬瘧锛屾牴鎹槸鍚︽敮鎸丄DIO璁剧疆鏍囧織 + ADIO_RUN() + { flags |= O_DIRECT; } ADIO_END(); - - GetUndoFilePath(reln->smgr_rnode.node.relNode, reln->smgr_rnode.node.dbNode, - segno, path, UNDO_FILE_PATH_LEN); + // 鑾峰彇Undo鏂囦欢鐨勫畬鏁磋矾寰 + GetUndoFilePath(reln->smgr_rnode.node.relNode, reln->smgr_rnode.node.dbNode, segno, path, UNDO_FILE_PATH_LEN); + // 鏋勫缓鏂囦欢鑺傜偣瀵硅薄 filenode = RelFileNodeForkNumFill(reln->smgr_rnode, forknum, segno); + // 鎵撳紑鏂囦欢 fd = DataFileIdOpenFile(path, filenode, (int)flags, S_IRUSR | S_IWUSR); - + // 濡傛灉鎵撳紑鏂囦欢澶辫触锛屽垯杩涜閿欒澶勭悊 if (fd < 0) { - if ((behavior == EXTENSION_RETURN_NULL) && FILE_POSSIBLY_DELETED(errno)) { + if ((behavior == EXTENSION_RETURN_NULL) && FILE_POSSIBLY_DELETED(errno)) { // 鏂囦欢鍙兘宸茶鍒犻櫎 return NULL; } + // 妫鏌ョ郴缁熸槸鍚﹀浜庡紩瀵煎鐞嗘ā寮忔垨鑰呮鍦ㄨ繘琛屾仮澶嶆搷浣 + // 濡傛灉鏄叾涓箣涓锛岃〃绀虹郴缁熷彲鑳藉浜庡垵濮嬪寲鎴栬呮仮澶嶉樁娈碉紝姝ゆ椂灏濊瘯鍒涘缓鏂囦欢 if (IsBootstrapProcessingMode() || t_thrd.xlog_cxt.InRecovery) { DECLARE_NODE_COUNT(); GET_UPERSISTENCE_BY_ZONEID((int)reln->smgr_rnode.node.relNode, nodeCount); - CheckUndoFileDirectory(upersistence); - ExtendUndoFile(reln, forknum, blockno, NULL, false); - fd = DataFileIdOpenFile(path, filenode, (int)flags, S_IRUSR | S_IWUSR); + CheckUndoFileDirectory(upersistence); // 鐢ㄤ簬妫鏌ndo鏂囦欢鐩綍鏄惁瀛樺湪锛屽鏋滀笉瀛樺湪鍒欏垱寤哄畠 + ExtendUndoFile(reln, forknum, blockno, NULL, false); // 鎵╁睍Undo鏂囦欢锛屼互閫傚簲瑕佽鍙栫殑鍧 + fd = DataFileIdOpenFile(path, filenode, (int)flags, + S_IRUSR | S_IWUSR); // 灏濊瘯鍐嶆鎵撳紑鏂囦欢鐨勬搷浣滐紝浣跨敤鐩稿悓鐨勮矾寰勫拰鏂囦欢鑺傜偣 } if (fd < 0) { - CloseUndoFile(reln, forknum, InvalidBlockNumber); + CloseUndoFile(reln, forknum, InvalidBlockNumber); // 鍏抽棴Undo鏂囦欢 + // 妫鏌 fetchRecord 鏄惁涓 true锛岃〃绀哄綋鍓嶄笂涓嬫枃姝e湪灏濊瘯鑾峰彇Undo璁板綍 if (t_thrd.undo_cxt.fetchRecord == true) { - t_thrd.undo_cxt.fetchRecord = false; + t_thrd.undo_cxt.fetchRecord = false; // 琛ㄧず涓嶅啀灏濊瘯鑾峰彇Undo璁板綍 if (t_thrd.storage_cxt.InProgressBuf != NULL) { Buffer buffer = BufferDescriptorGetBuffer(t_thrd.storage_cxt.InProgressBuf); + // 缁堟缂撳啿鍖篒O鎿嶄綔锛屼絾涓嶆爣璁颁负鏈夋晥 TerminateBufferIO(t_thrd.storage_cxt.InProgressBuf, false, BM_VALID); ReleaseBuffer(buffer); } @@ -406,16 +554,21 @@ static UndoFileState *OpenUndoFile(SMgrRelation reln, ForkNumber forknum, BlockN } } } - + // 璁剧疆鐘舵佷俊鎭 SetUndoFileState(state, segno, fd); + // 鑾峰彇鏂囦欢鐨勫潡鏁 blockNum = GetUndoFileBlocks(reln, forknum, state); + // 濡傛灉鏂囦欢鐨勫潡鏁板皬浜庢湡鏈涚殑鍧楁暟锛屽垯鎶ュ憡璀﹀憡骞舵墿灞曟枃浠 if (blockNum < undoFileBlocks) { ereport(WARNING, (errmsg(UNDOFORMAT("The undo file \"%s\" size is small than undoFileBlocks, " - "file blockNum=%u, we will extend undo file."), path, blockNum))); + "file blockNum=%u, we will extend undo file."), + path, blockNum))); ExtendUndoFile(reln, forknum, blockno, NULL, false); } else if (blockNum > undoFileBlocks) { + // 濡傛灉鏂囦欢鐨勫潡鏁板皬浜庢湡鏈涚殑鍧楁暟锛屽垯鎶ュ憡璀﹀憡骞舵墿灞曟枃浠 ereport(WARNING, (errmsg(UNDOFORMAT("The undo file \"%s\" size is big than undoFileBlocks, " - "file blockNum=%u, we will extend undo file."), path, blockNum))); + "file blockNum=%u, we will extend undo file."), + path, blockNum))); /* close undofile before unlink undo file */ CloseUndoFile(reln, forknum, InvalidBlockNumber); UnlinkUndoFile(reln->smgr_rnode, forknum, true, blockno); @@ -425,43 +578,67 @@ static UndoFileState *OpenUndoFile(SMgrRelation reln, ForkNumber forknum, BlockN } /* Read the specified block from a undo file. */ +/* + * 鍔熻兘锛氫粠Undo鏂囦欢涓鍙栨暟鎹潡 + * + * 鍙傛暟鍒楄〃锛 + * reln锛歋MgrRelation瀵硅薄锛岃〃绀哄叧鑱旂殑Undo鏂囦欢 + * forknum锛欶orkNumber锛岃〃绀烘枃浠剁殑鍒嗗弶绫诲瀷 + * blockno锛氳璇诲彇鐨勫潡鍙 + * buffer锛氱敤浜庡瓨鍌ㄨ鍙栨暟鎹殑缂撳啿鍖 + * + */ SMGR_READ_STATUS ReadUndoFile(SMgrRelation reln, ForkNumber forknum, BlockNumber blockno, char *buffer) { + // 纭繚缂撳啿鍖轰笉涓虹┖ Assert(buffer != NULL); - + // 鐢ㄤ簬瀛樺偍Undo鏂囦欢鐨勭姸鎬佷俊鎭 UndoFileState *state = NULL; char *fileName = NULL; off_t seekpos; int nbytes; + // 鑾峰彇Undo鏂囦欢鐨勫潡澶у皬 uint32 undoFileBlocks = UNDO_FILE_BLOCK(reln->smgr_rnode.node.dbNode); - + // 鎵撳紑Undo鏂囦欢锛屽鏋滄枃浠朵笉瀛樺湪鍒欒繑鍥為敊璇 state = OpenUndoFile(reln, forknum, blockno, EXTENSION_FAIL); + // 璁$畻瑕佽鍙栫殑浣嶇疆 seekpos = (off_t)BLCKSZ * (blockno % undoFileBlocks); fileName = FilePathName(state->file); - + // 鏂█瑕佽鍙栫殑浣嶇疆鍦ㄦ枃浠舵湁鏁堣寖鍥村唴 Assert(seekpos < (off_t)(undoFileBlocks * BLCKSZ)); - + // 鏉′欢缂栬瘧锛屾牴鎹槸鍚︽敮鎸丄DIO璁剧疆鏍囧織 WHITEBOX_TEST_STUB(UNDO_READ_FILE_FAILED, WhiteboxDefaultErrorEmit); - + // 浠嶶ndo鏂囦欢涓鍙栨暟鎹潡 nbytes = FilePRead(state->file, buffer, BLCKSZ, seekpos, WAIT_EVENT_UNDO_FILE_READ); + // 濡傛灉璇诲彇鐨勫瓧鑺傛暟涓嶇瓑浜庢湡鏈涚殑鍧楀ぇ灏忥紝鎶ュ憡閿欒 if (nbytes != BLCKSZ) { CloseUndoFile(reln, forknum, InvalidBlockNumber); if (nbytes < 0) { ereport(ERROR, (errmsg(UNDOFORMAT("could not read block %u in file \"%s\": %m."), blockno, fileName))); } - ereport(ERROR, (errmsg(UNDOFORMAT("could not read block %u in file \"%s\": read only %d of %d bytes."), - blockno, fileName, nbytes, BLCKSZ))); + ereport(ERROR, (errmsg(UNDOFORMAT("could not read block %u in file \"%s\": read only %d of %d bytes."), blockno, + fileName, nbytes, BLCKSZ))); } - + // 妫鏌ヨ鍙栫殑鏁版嵁鍧楁槸鍚﹂氳繃鏍¢獙锛岃繑鍥炵浉搴旂殑鐘舵 if (PageIsVerified((Page)buffer, blockno)) { return SMGR_RD_OK; } else { return SMGR_RD_CRC_ERROR; } } - +/* + * 鍔熻兘锛氬皢鏁版嵁鍐欏叆Undo鏂囦欢鎸囧畾鍧 + * + * 鍙傛暟鍒楄〃锛 + * reln锛歋MgrRelation瀵硅薄锛岃〃绀哄叧鑱旂殑Undo鏂囦欢 + * forknum锛欶orkNumber锛岃〃绀烘枃浠剁殑鍒嗗弶绫诲瀷 + * blockNum锛氳鍐欏叆鐨勫潡鍙 + * buffer锛氬寘鍚緟鍐欏叆鏁版嵁鐨勭紦鍐插尯 + * skipFsync锛氭槸鍚﹁烦杩嘑sync鎿嶄綔鐨勬爣蹇 + */ void WriteUndoFile(SMgrRelation reln, ForkNumber forknum, BlockNumber blockNum, const char *buffer, bool skipFsync) { + // 妫鏌ヨ緭鍏ョ紦鍐插尯鏄惁涓虹┖ Assert(buffer != NULL); UndoFileState *state = NULL; @@ -469,23 +646,31 @@ void WriteUndoFile(SMgrRelation reln, ForkNumber forknum, BlockNumber blockNum, int nbytes; off_t seekpos; uint32 undoFileBlocks = UNDO_FILE_BLOCK(reln->smgr_rnode.node.dbNode); - + // 鎵撳紑鎴栧垱寤篣ndo鏂囦欢锛屽鏋滄枃浠朵笉瀛樺湪鍒欒繑鍥濶ULL state = OpenUndoFile(reln, forknum, blockNum, EXTENSION_FAIL); seekpos = (off_t)BLCKSZ * (blockNum % undoFileBlocks); fileName = FilePathName(state->file); - + // 妫鏌ュ啓鍏ヤ綅缃槸鍚﹀悎娉 Assert(seekpos < (off_t)(undoFileBlocks * BLCKSZ)); - + // 妯℃嫙鐧界洅娴嬭瘯锛氭ā鎷熷啓鍏ユ枃浠跺け璐 + /* + * 鐧界洅娴嬭瘯鏄竴绉嶆祴璇曟墜娈碉紝鐢ㄤ簬妯℃嫙鍦ㄦ祴璇曠幆澧冧腑浜х敓鍐欐枃浠跺け璐ョ殑鎯呭喌锛 + * 浠ョ‘淇濈郴缁熷湪闈㈠寮傚父鎯呭喌鏃舵湁閫傚綋鐨勫鐞嗘満鍒躲 + */ WHITEBOX_TEST_STUB(UNDO_WRITE_FILE_FAILED, WhiteboxDefaultErrorEmit); - + // 浣跨敤FilePWrite鍑芥暟灏嗘暟鎹啓鍏ndo鏂囦欢鐨勬寚瀹氫綅缃 nbytes = FilePWrite(state->file, buffer, BLCKSZ, seekpos, WAIT_EVENT_UNDO_FILE_WRITE); + // 濡傛灉鍐欏叆鐨勫瓧鑺傛暟涓嶇瓑浜庡潡澶у皬锛岃〃绀哄啓鍏ュけ璐 if (nbytes != BLCKSZ) { + // 鍏抽棴Undo鏂囦欢 CloseUndoFile(reln, forknum, InvalidBlockNumber); + // 濡傛灉鍐欏叆鍑洪敊锛屾姤閿欏苟璁板綍閿欒淇℃伅 if (nbytes < 0) { ereport(ERROR, (errmsg(UNDOFORMAT("could not write block %u in file \"%s\": %m."), blockNum, fileName))); } + // 濡傛灉鍐欏叆涓嶅畬鏁达紝鎶ラ敊骞惰褰曢敊璇俊鎭 ereport(ERROR, (errmsg(UNDOFORMAT("could not write block %u in file \"%s\": wrote only %d of %d bytes."), - blockNum, fileName, nbytes, BLCKSZ))); + blockNum, fileName, nbytes, BLCKSZ))); } /* Tell checkpointer this file is dirty. */ @@ -494,83 +679,122 @@ void WriteUndoFile(SMgrRelation reln, ForkNumber forknum, BlockNumber blockNum, } return; } - +/* + * 鍔熻兘锛氬皢 Undo 鏂囦欢鐨勪竴涓垨澶氫釜鏁版嵁鍧楀啓鍥炵鐩 + * + * 鍙傛暟鍒楄〃锛 + * reln锛歋MgrRelation瀵硅薄锛岃〃绀哄叧鑱旂殑Undo鏂囦欢 + * forknum锛欶orkNumber锛岃〃绀烘枃浠剁殑鍒嗗弶绫诲瀷 + * blockno锛氳鍐欏洖鐨勫潡鐨勮捣濮嬪潡鍙 + * nblocks锛氳鍐欏洖鐨勫潡鐨勬暟閲 + */ void WritebackUndoFile(SMgrRelation reln, ForkNumber forknum, BlockNumber blockno, BlockNumber nblocks) { + // 鑾峰彇 Undo 鏂囦欢鍧楃殑澶у皬锛岄氬父鏄 8KB uint32 undoFileBlocks = UNDO_FILE_BLOCK(reln->smgr_rnode.node.dbNode); - + // 鑾峰彇 Undo 鏂囦欢鍧楃殑澶у皬锛岄氬父鏄 8KB while (nblocks > 0) { UndoFileState *state = NULL; int segStart; int segEnd; BlockNumber nflush = nblocks; off_t seekpos; - + // 鎵撳紑鎴栧垱寤 Undo 鏂囦欢锛屽鏋滄枃浠朵笉瀛樺湪锛屽嚱鏁拌繑鍥 NULL state = OpenUndoFile(reln, forknum, blockno, EXTENSION_RETURN_NULL); + // 璁$畻褰撳墠鍐欏洖鍧楃殑璧峰娈靛拰缁撴潫娈 segStart = blockno / undoFileBlocks; segEnd = (blockno + nblocks - 1) / undoFileBlocks; /* * We might be flushing buffers of already removed relations, that's * ok, just ignore that case. */ + // 濡傛灉褰撳墠 Undo 鏂囦欢涓嶅瓨鍦紙鍙兘宸茶鍒犻櫎锛夛紝鐩存帴杩斿洖 if (state == NULL) { return; } - + // 濡傛灉褰撳墠鍐欏洖璺ㄨ秺澶氫釜娈碉紝璁$畻鍑鸿鍐欏洖鐨勫潡鏁伴噺 if (segStart != segEnd) { nflush = undoFileBlocks - (blockno % undoFileBlocks); } - + // 鏂█瑕佸啓鍥炵殑鍧楁暟閲忓湪鍚堢悊鑼冨洿鍐 Assert(nflush >= 1); Assert(nflush <= nblocks); - + // 璁$畻瑕佸啓鍥炵殑鍧楃殑鍋忕Щ閲 seekpos = (off_t)BLCKSZ * (blockno % undoFileBlocks); + // 璋冪敤 FileWriteback 鍑芥暟灏嗗潡鍐欏洖 Undo 鏂囦欢 FileWriteback(state->file, seekpos, (off_t)BLCKSZ * nflush); - + // 鏇存柊鍓╀綑鍧楁暟鍜屽潡鍙 nblocks -= nflush; blockno += nflush; } } - +/* + * 鍔熻兘锛氶鍙栵紙Prefetch锛塙ndo鏂囦欢鐨勪竴涓暟鎹潡鍒板唴瀛樹腑 + * + * 鍙傛暟鍒楄〃锛 + * reln锛歋MgrRelation瀵硅薄锛岃〃绀哄叧鑱旂殑Undo鏂囦欢 + * forknum锛欶orkNumber锛岃〃绀烘枃浠剁殑鍒嗗弶绫诲瀷 + * blockNum锛氳棰勫彇鐨勫潡鍙 + */ void PrefetchUndoFile(SMgrRelation reln, ForkNumber forknum, BlockNumber blockNum) { + /* + *妫鏌ユ槸鍚﹀畾涔変簡 USE_PREFETCH 瀹忋傚鏋滃湪缂栬瘧鏃跺畾涔変簡杩欎釜瀹忥紝閭d箞鏉′欢鎴愮珛锛屽悗闈㈢殑浠g爜鍧椾細琚紪璇戝拰鎵ц銆 + */ #ifdef USE_PREFETCH + // 瀹氫箟涓涓寚鍚慤ndo鏂囦欢鐘舵佺粨鏋勭殑鎸囬拡 UndoFileState *state = NULL; + // 璁$畻瑕侀鍙栫殑鍧楃殑鍋忕Щ閲 off_t seekpos; + // 鑾峰彇Undo鏂囦欢鍧楃殑澶у皬锛岄氬父鏄8KB uint32 undoFileBlocks = UNDO_FILE_BLOCK(reln->smgr_rnode.node.dbNode); - + // 鎵撳紑鎴栧垱寤篣ndo鏂囦欢锛屽鏋滄枃浠朵笉瀛樺湪锛屽嚱鏁拌繑鍥濶ULL state = OpenUndoFile(reln, forknum, blockNum, EXTENSION_FAIL); + // 鎵撳紑鎴栧垱寤篣ndo鏂囦欢锛屽鏋滄枃浠朵笉瀛樺湪锛屽嚱鏁拌繑鍥濶ULL seekpos = (off_t)BLCKSZ * (blockNum % undoFileBlocks); - + // 鏂█鍧楃殑鍋忕Щ閲忓湪鍚堢悊鑼冨洿鍐 Assert(seekpos < (off_t)(undoFileBlocks * BLCKSZ)); - + // 璋冪敤FilePrefetch鍑芥暟灏嗗潡棰勫彇鍒板唴瀛樹腑 (void)FilePrefetch(state->file, seekpos, BLCKSZ, WAIT_EVENT_UNDO_FILE_PREFETCH); + + // 琛ㄧず鏉′欢缂栬瘧鐨勭粨鏉熸爣璁 #endif /* USE_PREFETCH */ } -void UnlinkUndoFile(const RelFileNodeBackend& rnode, ForkNumber forkNum, bool isRedo, BlockNumber blockNum) +void UnlinkUndoFile(const RelFileNodeBackend &rnode, ForkNumber forkNum, bool isRedo, BlockNumber blockNum) { + // 鏂█鍧楀彿涓嶄负InvalidBlockNumber锛屽嵆瑕佹搷浣滅殑鍧楀彿鍚堟硶 Assert(blockNum != InvalidBlockNumber); + // 瀹氫箟涓涓敤浜庡瓨鍌║ndo鏂囦欢璺緞鐨勫瓧绗︽暟缁 char path[UNDO_FILE_PATH_LEN]; + // 鑾峰彇Undo鏂囦欢鍧楃殑澶у皬锛岄氬父鏄8KB uint32 undoFileBlocks = UNDO_FILE_BLOCK(rnode.node.dbNode); + // 鐢ㄤ簬瀛樺偍unlink鍑芥暟鐨勮繑鍥炲 int ret; + // 浠嶳elFileNodeBackend瀵硅薄涓幏鍙栧叧鑱擴ndo鏂囦欢鐨刏one ID int zid = rnode.node.relNode; + // 璁$畻鍧楁墍鍦ㄧ殑Undo鏂囦欢娈靛彿 int segno = blockNum / undoFileBlocks; + // 鑾峰彇Undo鏂囦欢鐨勮矾寰 GetUndoFilePath(zid, rnode.node.dbNode, segno, path, UNDO_FILE_PATH_LEN); - + // 濡傛灉姝e湪鎵цredo鎿嶄綔锛屾垨鑰呮鍦ㄨ繘琛屽師鍦板崌绾э紝鎴栬呮枃浠跺垎鍙夌被鍨嬩笉鏄疢AIN_FORKNUM if (isRedo || u_sess->attr.attr_common.IsInplaceUpgrade || forkNum != MAIN_FORKNUM || RelFileNodeBackendIsTemp(rnode) || rnode.node.bucketNode != InvalidBktId) { + // 濡傛灉鏂囦欢涓嶆槸涓存椂鏂囦欢锛屾敞鍐屼竴涓繕璁癠ndo璇锋眰 if (!RelFileNodeBackendIsTemp(rnode)) { RegisterForgetUndoRequests(rnode, segno); } + // 鎶ュ憡绛夊緟浜嬩欢锛岃〃绀烘鍦ㄦ墽琛孶ndo鏂囦欢鍒犻櫎鎿嶄綔 pgstat_report_waitevent(WAIT_EVENT_UNDO_FILE_UNLINK); + // 灏濊瘯鍒犻櫎Undo鏂囦欢锛屽鏋滃垹闄ゅけ璐ワ紝灏濊瘯鍐嶆鍒犻櫎 if (unlink(path) < 0 && errno != ENOENT) { /* try again */ if ((unlink(path) < 0) && (errno != ENOENT) && !isRedo) { ereport(WARNING, (errmsg(UNDOFORMAT("could not remove file \"%s\": %m."), path))); } } + // 鎶ュ憡绛夊緟浜嬩欢锛岃〃绀篣ndo鏂囦欢鍒犻櫎鎿嶄綔缁撴潫 pgstat_report_waitevent(WAIT_EVENT_END); } else { /* truncate(2) would be easier here, but Windows hasn't got it */ @@ -578,6 +802,7 @@ void UnlinkUndoFile(const RelFileNodeBackend& rnode, ForkNumber forkNum, bool is fd = BasicOpenFile(path, O_RDWR | PG_BINARY, 0); if (fd >= 0) { int save_errno; + // 鎴柇Undo鏂囦欢锛屽皢鍏跺ぇ灏忔埅鏂负0 ret = ftruncate(fd, 0); save_errno = errno; (void)close(fd); @@ -585,16 +810,25 @@ void UnlinkUndoFile(const RelFileNodeBackend& rnode, ForkNumber forkNum, bool is } else { ret = -1; } + // 濡傛灉鎴柇鎿嶄綔澶辫触骞朵笖涓嶆槸鍥犱负鏂囦欢涓嶅瓨鍦紝鍒欐姤閿 if (ret < 0 && errno != ENOENT) { ereport(WARNING, (errcode_for_file_access(), errmsg("could not truncate file \"%s\": %m", path))); } /* Register request to unlink first segment later */ + // 娉ㄥ唽涓涓姹傦紝绋嶅悗鍒犻櫎绗竴涓猆ndo鏂囦欢娈 RegisterUnlinkUndoRequests(rnode, segno); } return; } - +/* + * 鍔熻兘锛氬叧闂璘ndo鏂囦欢 + * + * 鍙傛暟鍒楄〃锛 + * reln锛歋MgrRelation瀵硅薄锛岃〃绀哄叧鑱旂殑Undo鏂囦欢 + * forkNum锛欶orkNumber锛岃〃绀烘枃浠剁殑鍒嗗弶绫诲瀷 + * blockNum锛氳鍏抽棴鐨勫潡鍙凤紙鍙夊弬鏁帮紝鐢ㄤ簬鎸囧畾鍏抽棴鍝釜鍧楋紝濡傛灉涓嶉渶瑕佸叧闂壒瀹氬潡锛屽彲浠ヤ紶鍏nvalidBlockNumber锛 + */ void CloseUndoFile(SMgrRelation reln, ForkNumber forkNum, BlockNumber blockNum) { Assert(reln != NULL); @@ -605,7 +839,7 @@ void CloseUndoFile(SMgrRelation reln, ForkNumber forkNum, BlockNumber blockNum) if (state == NULL) { return; } - reln->fileState = NULL; /* prevent dangling pointer after error */ + reln->fileState = NULL; /* prevent dangling pointer after error */ /* if not closed already */ if (state->file >= 0) { @@ -615,62 +849,122 @@ void CloseUndoFile(SMgrRelation reln, ForkNumber forkNum, BlockNumber blockNum) } /* Sync undo file. */ +/* + * 鍔熻兘锛氬悓姝ワ紙鍒风洏锛塙ndo鏂囦欢 + * + * 鍙傛暟鍒楄〃锛 + * tag锛氭寚鍚慒ileTag缁撴瀯鐨勬寚閽堬紝鐢ㄤ簬鏍囪瘑Undo鏂囦欢鐨勪綅缃拰灞炴 + * path锛氱敤浜庡瓨鍌║ndo鏂囦欢璺緞鐨勫瓧绗︽暟缁 + * + */ int SyncUndoFile(const FileTag *tag, char *path) { + // 浣跨敤smgropen鎵撳紑鎸囧畾Undo鏂囦欢锛宺eln涓篠MgrRelation瀵硅薄 SMgrRelation reln = smgropen(tag->rnode, InvalidBackendId); - uint32 undoFileBlocks = UNDO_FILE_BLOCK(tag->rnode.dbNode); + uint32 undoFileBlocks = UNDO_FILE_BLOCK(tag->rnode.dbNode); // 鑾峰彇Undo鏂囦欢鍧楁暟 - GetUndoFilePath(tag->rnode.relNode, tag->rnode.dbNode, tag->segno, - path, UNDO_FILE_PATH_LEN); - UndoFileState *state = OpenUndoFile(reln, tag->forknum, - tag->segno * undoFileBlocks, EXTENSION_RETURN_NULL); + // 鑾峰彇鎸囧畾Undo鏂囦欢鐨勮矾寰 + GetUndoFilePath(tag->rnode.relNode, tag->rnode.dbNode, tag->segno, path, UNDO_FILE_PATH_LEN); + // 鎵撳紑鎸囧畾Undo鏂囦欢鐨勭姸鎬侊紝濡傛灉鏂囦欢涓嶅瓨鍦ㄥ垯杩斿洖NULL + UndoFileState *state = OpenUndoFile(reln, tag->forknum, tag->segno * undoFileBlocks, EXTENSION_RETURN_NULL); + // 濡傛灉鏂囦欢鐘舵佷负绌猴紝琛ㄧず鏂囦欢涓嶅瓨鍦ㄦ垨鑰呮湭琚墦寮锛岃繑鍥-1琛ㄧず鍚屾澶辫触 if (state == NULL) { return -1; } - + // 璋冪敤FileSync鍑芥暟瀵规枃浠惰繘琛屽悓姝ワ紙鍒风洏锛夋搷浣滐紝绛夊緟鍚屾瀹屾垚 return FileSync(state->file, WAIT_EVENT_UNDO_FILE_SYNC); } - +/* + * 鍔熻兘锛氬皾璇曞垹闄わ紙瑙i摼鎺ワ級Undo鏂囦欢 + * + * 鍙傛暟鍒楄〃锛 + * tag锛氭寚鍚慒ileTag缁撴瀯鐨勬寚閽堬紝鐢ㄤ簬鏍囪瘑Undo鏂囦欢鐨勪綅缃拰灞炴 + * path锛氱敤浜庡瓨鍌║ndo鏂囦欢璺緞鐨勫瓧绗︽暟缁 + */ int SyncUnlinkUndoFile(const FileTag *tag, char *path) { - GetUndoFilePath(tag->rnode.relNode, tag->rnode.dbNode, tag->segno, - path, UNDO_FILE_PATH_LEN); + // 鑾峰彇鎸囧畾Undo鏂囦欢鐨勮矾寰 + GetUndoFilePath(tag->rnode.relNode, tag->rnode.dbNode, tag->segno, path, UNDO_FILE_PATH_LEN); /* Try to unlink the file. */ + // 灏濊瘯鍒犻櫎锛堣В閾炬帴锛夋寚瀹氳矾寰勭殑鏂囦欢锛屾垚鍔熻繑鍥0锛屽け璐ヨ繑鍥-1 return unlink(path); } - +/* + * 鍔熻兘锛氭敞鍐孶ndo鏂囦欢鐨勫垹闄よ姹 + * + * 鍙傛暟鍒楄〃锛 + * rnode锛歊elFileNodeBackend 缁撴瀯锛岃〃绀篣ndo鏂囦欢鐨勭浉鍏充俊鎭 + * segno锛歶int32锛岃〃绀篣ndo鏂囦欢鐨勬鍙 + */ static void RegisterUnlinkUndoRequests(RelFileNodeBackend rnode, uint32 segno) { FileTag tag; + // 鍒濆鍖栦竴涓狥ileTag缁撴瀯锛岀敤浜庢爣璇哢ndo鏂囦欢鐨勪綅缃拰灞炴 INIT_UNDO_FILE_TAG(tag, rnode.node, segno); - (void) RegisterSyncRequest(&tag, SYNC_UNLINK_REQUEST, true /* retryOnError */ ); + // 鍚戝悓姝ヨ姹傞槦鍒椾腑娉ㄥ唽鍒犻櫎璇锋眰锛岃缃畆etryOnError鍙傛暟涓簍rue + (void)RegisterSyncRequest(&tag, SYNC_UNLINK_REQUEST, true /* retryOnError */); } - +/* + * 鍔熻兘锛氭敞鍐屽繕璁癠ndo鏂囦欢鐨勮姹 + * + * 鍙傛暟鍒楄〃锛 + * rnode锛歊elFileNodeBackend 缁撴瀯锛岃〃绀篣ndo鏂囦欢鐨勭浉鍏充俊鎭 + * segno锛歶int32锛岃〃绀篣ndo鏂囦欢鐨勬鍙 + */ static void RegisterForgetUndoRequests(RelFileNodeBackend rnode, uint32 segno) { FileTag tag; + // 鍒濆鍖栦竴涓狥ileTag缁撴瀯锛岀敤浜庢爣璇哢ndo鏂囦欢鐨勪綅缃拰灞炴 INIT_UNDO_FILE_TAG(tag, rnode.node, segno); - (void) RegisterSyncRequest(&tag, SYNC_FORGET_REQUEST, true /* retryOnError */ ); + // 鍒濆鍖栦竴涓狥ileTag缁撴瀯锛岀敤浜庢爣璇哢ndo鏂囦欢鐨勪綅缃拰灞炴 + (void)RegisterSyncRequest(&tag, SYNC_FORGET_REQUEST, true /* retryOnError */); } - +/* + * 鍔熻兘锛氭敞鍐 "鑴" 鐨刄ndo娈电殑鍚屾璇锋眰 + * + * 鍙傛暟鍒楄〃锛 + * reln锛歋MgrRelation 缁撴瀯锛岃〃绀篣ndo鏂囦欢鐨勫叧鑱斿叧绯 + * state锛歎ndoFileState 缁撴瀯锛岃〃绀篣ndo鏂囦欢鐨勭姸鎬佷俊鎭 + * + * 璇存槑锛 + * 璇ュ嚱鏁颁細灏嗕竴涓 "鑴" 鐨刄ndo娈电殑鍚屾璇锋眰娣诲姞鍒板悓姝ヨ姹傞槦鍒椾腑锛屼互纭繚Undo娈典腑鐨勬暟鎹鍐欏叆鎸佷箙瀛樺偍銆 + * 濡傛灉鍚屾璇锋眰闃熷垪宸叉弧锛屽嚱鏁板皢灏濊瘯绔嬪嵆鎵ц鏂囦欢鍚屾鎿嶄綔銆 + */ static void RegisterDirtyUndoSegment(SMgrRelation reln, const UndoFileState *state) { /* Temp relations should never be fsync'd */ Assert(!SmgrIsTemp(reln)); FileTag tag; + // 鍒濆鍖栦竴涓狥ileTag缁撴瀯锛岀敤浜庢爣璇哢ndo鏂囦欢娈电殑浣嶇疆鍜屽睘鎬 INIT_UNDO_FILE_TAG(tag, reln->smgr_rnode.node, state->segno); - - if (!RegisterSyncRequest(&tag, SYNC_REQUEST, false /* retryOnError */ )) { + // 鍚戝悓姝ヨ姹傞槦鍒椾腑娉ㄥ唽 "鑴" Undo娈电殑鍚屾璇锋眰锛岃缃畆etryOnError鍙傛暟涓篺alse + if (!RegisterSyncRequest(&tag, SYNC_REQUEST, false /* retryOnError */)) { ereport(DEBUG5, (errmsg(UNDOFORMAT("could not forward fsync request because request queue is full.")))); + // 濡傛灉鍚屾璇锋眰闃熷垪宸叉弧锛屽皾璇曠珛鍗虫墽琛屾枃浠跺悓姝ユ搷浣 if (FileSync(state->file, WAIT_EVENT_DATA_FILE_SYNC) < 0) { ereport(ERROR, (errmsg(UNDOFORMAT("could not fsync file \"%s\": %m."), FilePathName(state->file)))); } } } - +/* + * 鍔熻兘锛氭鏌ユ寚瀹氱殑Undo鏂囦欢鏄惁瀛樺湪 + * + * 鍙傛暟鍒楄〃锛 + * reln锛歋MgrRelation 缁撴瀯锛岃〃绀篣ndo鏂囦欢鐨勫叧鑱斿叧绯 + * forkNum锛欶orkNumber锛岃〃绀烘枃浠剁殑鍒嗗弶绫诲瀷 + * blockNum锛氳妫鏌ョ殑鍧楀彿 + * + * 杩斿洖鍊硷細 + * 濡傛灉Undo鏂囦欢瀛樺湪锛岃繑鍥瀟rue锛涘惁鍒欙紝杩斿洖false銆 + * + * 璇存槑锛 + * 璇ュ嚱鏁伴鍏堝叧闂寚瀹氱殑Undo鏂囦欢锛屼互纭繚鎴戜滑娉ㄦ剰鍒板鏋滃湪鎵撳紑鏂囦欢鍚庡凡琚垹闄ゃ + * 鐒跺悗锛屽畠灏濊瘯鎵撳紑Undo鏂囦欢銆傚鏋滄垚鍔熸墦寮鏂囦欢锛屽畠灏嗚繑鍥瀟rue锛屽惁鍒欒繑鍥瀎alse銆 + * 鏈鍚庯紝瀹冨啀娆″叧闂璘ndo鏂囦欢锛屼互纭繚鏂囦欢鐘舵佷笉鍙楀奖鍝嶃 + */ bool CheckUndoFileExists(SMgrRelation reln, ForkNumber forkNum, BlockNumber blockNum) { /* @@ -680,9 +974,11 @@ bool CheckUndoFileExists(SMgrRelation reln, ForkNumber forkNum, BlockNumber bloc CloseUndoFile(reln, forkNum, blockNum); bool isExist = false; + // 灏濊瘯鎵撳紑Undo鏂囦欢锛屽鏋滄垚鍔熸墦寮鏂囦欢锛屽垯灏唅sExist璁剧疆涓簍rue if (OpenUndoFile(reln, forkNum, blockNum, EXTENSION_RETURN_NULL) != NULL) { isExist = true; } + // 鍐嶆鍏抽棴鏂囦欢锛屼互纭繚鏂囦欢鐘舵佷笉鍙楀奖鍝 CloseUndoFile(reln, forkNum, blockNum); return isExist; } diff --git a/src/gausskernel/storage/smgr/md.cpp b/src/gausskernel/storage/smgr/md.cpp index 51bd5d1d6..3302a0484 100644 --- a/src/gausskernel/storage/smgr/md.cpp +++ b/src/gausskernel/storage/smgr/md.cpp @@ -44,16 +44,15 @@ #include "pgstat.h" /* Populate a file tag describing an md.cpp segment file. */ -#define INIT_MD_FILETAG(tag, rNode, forkNum, segNo) \ - do \ - { \ - errno_t errorno = EOK; \ - errorno = memset_s(&(tag), sizeof(FileTag), (0), sizeof(FileTag)); \ - securec_check(errorno, "\0", "\0"); \ - (tag).handler = SYNC_HANDLER_MD; \ - (tag).forknum = (forkNum); \ - (tag).rnode = (rNode); \ - (tag).segno = (segNo); \ +#define INIT_MD_FILETAG(tag, rNode, forkNum, segNo) \ + do { \ + errno_t errorno = EOK; \ + errorno = memset_s(&(tag), sizeof(FileTag), (0), sizeof(FileTag)); \ + securec_check(errorno, "\0", "\0"); \ + (tag).handler = SYNC_HANDLER_MD; \ + (tag).forknum = (forkNum); \ + (tag).rnode = (rNode); \ + (tag).segno = (segNo); \ } while (false); constexpr mode_t FILE_RW_PERMISSION = 0600; @@ -105,8 +104,8 @@ inline static uint4 PageCompressChunkSize(SMgrRelation reln) */ typedef struct _MdfdVec { File mdfd_vfd; /* fd number in fd.c's pool */ - File mdfd_vfd_pca; /* page compression address file 's fd number in fd.cpp's pool */ - File mdfd_vfd_pcd; /* page compression data file 's fd number in fd.cpp's pool */ + File mdfd_vfd_pca; /* page compression address file 's fd number in fd.cpp's pool */ + File mdfd_vfd_pcd; /* page compression data file 's fd number in fd.cpp's pool */ BlockNumber mdfd_segno; /* segment number, from 0 */ struct _MdfdVec *mdfd_chain; /* next segment, or NULL */ } MdfdVec; @@ -117,71 +116,156 @@ static MdfdVec *mdopen(SMgrRelation reln, ForkNumber forknum, ExtensionBehavior static MdfdVec *_fdvec_alloc(void); static char *_mdfd_segpath(const SMgrRelation reln, ForkNumber forknum, BlockNumber segno); static MdfdVec *_mdfd_openseg(SMgrRelation reln, ForkNumber forkno, BlockNumber segno, int oflags); -static MdfdVec *_mdfd_getseg(SMgrRelation reln, ForkNumber forkno, BlockNumber blkno, bool skipFsync, ExtensionBehavior behavior); +static MdfdVec *_mdfd_getseg(SMgrRelation reln, ForkNumber forkno, BlockNumber blkno, bool skipFsync, + ExtensionBehavior behavior); static BlockNumber _mdnblocks(SMgrRelation reln, ForkNumber forknum, const MdfdVec *seg); static void register_dirty_segment(SMgrRelation reln, ForkNumber forknum, const MdfdVec *seg); static void register_unlink_segment(RelFileNodeBackend rnode, ForkNumber forknum, BlockNumber segno); /* function of compressed table */ static int sync_pcmap(PageCompressHeader *pcMap, uint32 wait_event_info); - +/* + * 鍔熻兘锛氭鏌ユ寚瀹氱殑Undo鏂囦欢鏄惁瀛樺湪 + * + * 鍙傛暟鍒楄〃锛 + * rnode锛歊elFileNode 缁撴瀯锛岃〃绀篣ndo鏂囦欢鐨勫叧鑱斿叧绯 + * forknum锛欶orkNumber锛岃〃绀烘枃浠剁殑鍒嗗弶绫诲瀷 + */ bool check_unlink_rel_hashtbl(RelFileNode rnode, ForkNumber forknum) { - HTAB* relfilenode_hashtbl = g_instance.bgwriter_cxt.unlink_rel_hashtbl; - HTAB* relfilenode_fork_hashtbl = g_instance.bgwriter_cxt.unlink_rel_fork_hashtbl; + // 鑾峰彇鍚嶄负unlink_rel_hashtbl鐨勫搱甯岃〃鐨勬寚閽 + HTAB *relfilenode_hashtbl = g_instance.bgwriter_cxt.unlink_rel_hashtbl; + // 鑾峰彇鍚嶄负unlink_rel_fork_hashtbl鐨勫搱甯岃〃鐨勬寚閽 + HTAB *relfilenode_fork_hashtbl = g_instance.bgwriter_cxt.unlink_rel_fork_hashtbl; + + // 瀹氫箟涓涓粨鏋勪綋鍙橀噺entry_key锛岀敤浜庡瓨鍌ㄥ叧閿瓧淇℃伅 ForkRelFileNode entry_key; + // 甯冨皵鍙橀噺found鐢ㄤ簬琛ㄧず鏄惁鎵惧埌浜嗗叧閿瓧锛屽垵濮嬪间负false bool found = false; + // 鑾峰彇鍚嶄负rel_hashtbl_lock鐨勮交閲忕骇閿侊紙LWLock锛夛紝浠ョ‘淇濆畨鍏ㄨ闂畊nlink_rel_hashtbl鍝堝笇琛 LWLockAcquire(g_instance.bgwriter_cxt.rel_hashtbl_lock, LW_SHARED); + + // 鍦╱nlink_rel_hashtbl鍝堝笇琛ㄤ腑鎼滅储鍏抽敭瀛梤node锛屽苟灏嗘悳绱㈢粨鏋滃瓨鍌ㄥ湪found鍙橀噺涓 (void)hash_search(relfilenode_hashtbl, &(rnode), HASH_FIND, &found); + + // 閲婃斁rel_hashtbl_lock閿侊紝鍏佽鍏朵粬绾跨▼璁块棶unlink_rel_hashtbl鍝堝笇琛 LWLockRelease(g_instance.bgwriter_cxt.rel_hashtbl_lock); + // 濡傛灉鍦╱nlink_rel_hashtbl鍝堝笇琛ㄤ腑娌℃湁鎵惧埌鍏抽敭瀛梤node if (!found) { + // 璁剧疆entry_key鐨剅node鍜宖orkNum瀛楁 entry_key.rnode = rnode; entry_key.forkNum = forknum; + + // 鑾峰彇鍚嶄负rel_one_fork_hashtbl_lock鐨勮交閲忕骇閿侊紙LWLock锛夛紝浠ョ‘淇濆畨鍏ㄨ闂畊nlink_rel_fork_hashtbl鍝堝笇琛 LWLockAcquire(g_instance.bgwriter_cxt.rel_one_fork_hashtbl_lock, LW_SHARED); + + // 鍦╱nlink_rel_fork_hashtbl鍝堝笇琛ㄤ腑鎼滅储鍏抽敭瀛梕ntry_key锛屽苟灏嗘悳绱㈢粨鏋滃瓨鍌ㄥ湪found鍙橀噺涓 (void)hash_search(relfilenode_fork_hashtbl, &(entry_key), HASH_FIND, &found); + + // 閲婃斁rel_one_fork_hashtbl_lock閿侊紝鍏佽鍏朵粬绾跨▼璁块棶unlink_rel_fork_hashtbl鍝堝笇琛 LWLockRelease(g_instance.bgwriter_cxt.rel_one_fork_hashtbl_lock); } + + // 杩斿洖found鍙橀噺鐨勫硷紝琛ㄧず鏄惁鎵惧埌浜嗗叧閿瓧 return found; } - -static int OpenPcaFile(const char *path, const RelFileNodeBackend &node, const ForkNumber &forkNum, const uint32 &segNo, int oflags = 0) +/* + * 鍔熻兘锛氭墦寮鎸囧畾鐨凱CA鏂囦欢 + * + * 鍙傛暟鍒楄〃锛 + * path锛歅CA鏂囦欢鐨勮矾寰 + * node锛歊elFileNodeBackend 缁撴瀯锛岃〃绀篣ndo鏂囦欢鐨勫叧鑱斿叧绯 + * forkNum锛欶orkNumber锛岃〃绀烘枃浠剁殑鍒嗗弶绫诲瀷 + * segNo锛氳鎵撳紑鐨勬鍙 + * oflags锛氭墦寮鏂囦欢鐨勬爣蹇椾綅锛堥粯璁ゅ间负0锛 + */ +static int OpenPcaFile(const char *path, const RelFileNodeBackend &node, const ForkNumber &forkNum, const uint32 &segNo, + int oflags = 0) { + // 鏂█锛岀‘淇漬ode鐨刼pt瀛楁涓嶄负0涓攆orkNum涓篗AIN_FORKNUM Assert(node.node.opt != 0 && forkNum == MAIN_FORKNUM); + + // 瀹氫箟涓涓瓧绗︽暟缁刣st锛岀敤浜庡瓨鍌ㄧ洰鏍囨枃浠惰矾寰 char dst[MAXPGPATH]; + + // 璋冪敤CopyCompressedPath鍑芥暟锛屽皢path澶嶅埗鍒癲st锛屽苟娣诲姞COMPRESSED_TABLE_PCA_FILE鍚庣紑 CopyCompressedPath(dst, path, COMPRESSED_TABLE_PCA_FILE); + + // 瀹氫箟涓涓暣鏁板彉閲廸lags锛岀敤浜庤〃绀烘枃浠舵墦寮鐨勬爣蹇椾綅 + // O_RDWR琛ㄧず浠ュ彲璇诲啓鏂瑰紡鎵撳紑鏂囦欢 + // PG_BINARY琛ㄧず浠ヤ簩杩涘埗妯″紡鎵撳紑鏂囦欢 + // oflags琛ㄧず鍏朵粬鐢ㄦ埛鑷畾涔夌殑鏍囧織浣 uint32 flags = O_RDWR | PG_BINARY | oflags; + + // 璋冪敤DataFileIdOpenFile鍑芥暟锛屼互鎸囧畾鐨勮矾寰勫拰鍙傛暟鎵撳紑鏂囦欢锛屽苟杩斿洖鏂囦欢鎻忚堪绗 return DataFileIdOpenFile(dst, RelFileNodeForkNumFill(node, PCA_FORKNUM, segNo), (int)flags, S_IRUSR | S_IWUSR); } - -static int OpenPcdFile(const char *path, const RelFileNodeBackend &node, const ForkNumber &forkNum, const uint32 &segNo, int oflags = 0) +/* + * 鍔熻兘锛氭墦寮鎸囧畾鐨凱CD鏂囦欢 + * + * 鍙傛暟鍒楄〃锛 + * path锛歅CD鏂囦欢鐨勮矾寰 + * node锛歊elFileNodeBackend 缁撴瀯锛岃〃绀篣ndo鏂囦欢鐨勫叧鑱斿叧绯 + * forkNum锛欶orkNumber锛岃〃绀烘枃浠剁殑鍒嗗弶绫诲瀷 + * segNo锛氳鎵撳紑鐨勬鍙 + * oflags锛氭墦寮鏂囦欢鐨勬爣蹇椾綅锛堥粯璁ゅ间负0锛 + */ +static int OpenPcdFile(const char *path, const RelFileNodeBackend &node, const ForkNumber &forkNum, const uint32 &segNo, + int oflags = 0) { + // 鏂█锛岀‘淇漬ode鐨刼pt瀛楁涓嶄负0涓攆orkNum涓篗AIN_FORKNUM Assert(node.node.opt != 0 && forkNum == MAIN_FORKNUM); + + // 瀹氫箟涓涓瓧绗︽暟缁刣st锛岀敤浜庡瓨鍌ㄧ洰鏍囨枃浠惰矾寰 char dst[MAXPGPATH]; + + // 璋冪敤CopyCompressedPath鍑芥暟锛屽皢path澶嶅埗鍒癲st锛屽苟娣诲姞COMPRESSED_TABLE_PCD_FILE鍚庣紑 CopyCompressedPath(dst, path, COMPRESSED_TABLE_PCD_FILE); + + // 瀹氫箟涓涓暣鏁板彉閲廸lags锛岀敤浜庤〃绀烘枃浠舵墦寮鐨勬爣蹇椾綅 + // O_RDWR琛ㄧず浠ュ彲璇诲啓鏂瑰紡鎵撳紑鏂囦欢 + // PG_BINARY琛ㄧず浠ヤ簩杩涘埗妯″紡鎵撳紑鏂囦欢 + // oflags琛ㄧず鍏朵粬鐢ㄦ埛鑷畾涔夌殑鏍囧織浣 uint32 flags = O_RDWR | PG_BINARY | oflags; + + // 璋冪敤DataFileIdOpenFile鍑芥暟锛屼互鎸囧畾鐨勮矾寰勫拰鍙傛暟鎵撳紑鏂囦欢锛屽苟杩斿洖鏂囦欢鎻忚堪绗 return DataFileIdOpenFile(dst, RelFileNodeForkNumFill(node, PCD_FORKNUM, segNo), (int)flags, S_IRUSR | S_IWUSR); } - +/* + * 鍔熻兘锛氭敞鍐岃剰娈靛苟鎵ц鍚屾鎿嶄綔 + * + * 鍙傛暟鍒楄〃锛 + * reln锛歋MgrRelation 缁撴瀯锛岃〃绀轰笌鑴忔鍏宠仈鐨勫瓨鍌ㄧ鐞嗗櫒鍏崇郴 + * forknum锛欶orkNumber锛岃〃绀烘枃浠剁殑鍒嗗弶绫诲瀷 + * seg锛歁dfdVec 缁撴瀯锛岃〃绀鸿剰娈电殑鍏冩暟鎹枃浠舵弿杩扮鍚戦噺 + */ static void RegisterCompressDirtySegment(SMgrRelation reln, ForkNumber forknum, const MdfdVec *seg) { + // 鑾峰彇鍘嬬缉椤电殑鍐呭瓨鏄犲皠 PageCompressHeader *pcMap = GetPageCompressMemoryMap(seg->mdfd_vfd_pca, PageCompressChunkSize(reln)); + // 鍚屾鍘嬬缉椤靛唴瀛樻槧灏勫埌纾佺洏锛岀瓑寰匔OMPRESS_ADDRESS_FILE_SYNC浜嬩欢 if (sync_pcmap(pcMap, WAIT_EVENT_COMPRESS_ADDRESS_FILE_SYNC) != 0) { + // 濡傛灉鍚屾澶辫触骞朵笖闇瑕佸彇娑堥摼鎺ユ枃浠讹紝杈撳嚭DEBUG绾у埆鐨勯敊璇秷鎭紝鐒跺悗杩斿洖 if (check_unlink_rel_hashtbl(reln->smgr_rnode.node, forknum)) { ereport(DEBUG1, (errmsg("could not fsync file \"%s\": %m", FilePathName(seg->mdfd_vfd)))); return; } - ereport(data_sync_elevel(ERROR), (errcode_for_file_access(), errmsg("could not msync file \"%s\": %m", - FilePathName(seg->mdfd_vfd_pca)))); + // 鍚﹀垯锛岃緭鍑篍RROR绾у埆鐨勯敊璇秷鎭紝琛ㄧず鍚屾澶辫触 + ereport(data_sync_elevel(ERROR), (errcode_for_file_access(), + errmsg("could not msync file \"%s\": %m", FilePathName(seg->mdfd_vfd_pca)))); } + // 鍚屾鑴忔鐨勬暟鎹枃浠跺埌纾佺洏锛岀瓑寰匘ATA_FILE_SYNC浜嬩欢 if (FileSync(seg->mdfd_vfd_pcd, WAIT_EVENT_DATA_FILE_SYNC) < 0) { + // 濡傛灉鍚屾澶辫触骞朵笖闇瑕佸彇娑堥摼鎺ユ枃浠讹紝杈撳嚭DEBUG绾у埆鐨勯敊璇秷鎭紝鐒跺悗杩斿洖 if (check_unlink_rel_hashtbl(reln->smgr_rnode.node, forknum)) { ereport(DEBUG1, (errmsg("could not fsync file \"%s\": %m", FilePathName(seg->mdfd_vfd)))); return; } - ereport(data_sync_elevel(ERROR), (errcode_for_file_access(), errmsg("could not fsync file \"%s\": %m", - FilePathName(seg->mdfd_vfd_pcd)))); + // 鍚﹀垯锛岃緭鍑篍RROR绾у埆鐨勯敊璇秷鎭紝琛ㄧず鍚屾澶辫触 + ereport(data_sync_elevel(ERROR), (errcode_for_file_access(), + errmsg("could not fsync file \"%s\": %m", FilePathName(seg->mdfd_vfd_pcd)))); } } /* @@ -213,8 +297,8 @@ static void register_dirty_segment(SMgrRelation reln, ForkNumber forknum, const ereport(DEBUG1, (errmsg("could not fsync file \"%s\": %m", FilePathName(seg->mdfd_vfd)))); return; } - ereport(data_sync_elevel(ERROR), (errcode_for_file_access(), - errmsg("could not fsync file \"%s\": %m", FilePathName(seg->mdfd_vfd)))); + ereport(data_sync_elevel(ERROR), (errcode_for_file_access(), errmsg("could not fsync file \"%s\": %m", + FilePathName(seg->mdfd_vfd)))); } } } @@ -223,15 +307,25 @@ static void register_dirty_segment(SMgrRelation reln, ForkNumber forknum, const /* * register_unlink_segment() -- Schedule a file to be deleted after next checkpoint */ +/* + * 鍔熻兘锛氭敞鍐屽彇娑堥摼鎺ユ鐨勫悓姝ヨ姹 + * + * 鍙傛暟鍒楄〃锛 + * rnode锛歊elFileNodeBackend 缁撴瀯锛岃〃绀轰笌鑴忔鍏宠仈鐨勫瓨鍌ㄧ鐞嗗櫒鍏崇郴 + * forknum锛欶orkNumber锛岃〃绀烘枃浠剁殑鍒嗗弶绫诲瀷 + * segno锛氳鍙栨秷閾炬帴鐨勬鍙 + */ static void register_unlink_segment(RelFileNodeBackend rnode, ForkNumber forknum, BlockNumber segno) { FileTag tag; - + // 鍒濆鍖栨枃浠舵爣绛総ag锛岀敤浜庢爣璇嗚鍙栨秷閾炬帴鐨勬枃浠舵 INIT_MD_FILETAG(tag, rnode.node, forknum, segno); /* Should never be used with temp relations */ + // 鍒濆鍖栨枃浠舵爣绛総ag锛岀敤浜庢爣璇嗚鍙栨秷閾炬帴鐨勬枃浠舵 Assert(!RelFileNodeBackendIsTemp(rnode)); - + // 娉ㄥ唽鍚屾璇锋眰锛岃姹傚彇娑堥摼鎺ユ寚瀹氱殑鏂囦欢娈 + // SYNC_UNLINK_REQUEST琛ㄧず鍙栨秷閾炬帴璇锋眰锛宺etryOnError琛ㄧず鍦ㄩ敊璇儏鍐典笅鏄惁閲嶈瘯 RegisterSyncRequest(&tag, SYNC_UNLINK_REQUEST, true /* retryOnError */); } @@ -245,46 +339,70 @@ void md_register_forget_request(RelFileNode rnode, ForkNumber forknum, BlockNumb RegisterSyncRequest(&tag, SYNC_FORGET_REQUEST, true /* retryOnError */); } - +/* + * 鍔熻兘锛氭鏌ュ垎閰嶇殑鍧楁暟鍜屽潡鍙锋槸鍚︽湁鏁 + * + * 鍙傛暟鍒楄〃锛 + * pcAddr锛歅ageCompressAddr 缁撴瀯锛岃〃绀哄帇缂╅〉鐨勫湴鍧淇℃伅 + * chunk_size锛歶int32锛岃〃绀哄潡鐨勫ぇ灏 + * blocknum锛欱lockNumber锛岃〃绀哄潡鐨勭紪鍙 + * v锛歁dfdVec 缁撴瀯锛岃〃绀鸿剰娈电殑鍏冩暟鎹枃浠舵弿杩扮鍚戦噺 + */ static void allocate_chunk_check(PageCompressAddr *pcAddr, uint32 chunk_size, BlockNumber blocknum, MdfdVec *v) { /* check allocated chunk number */ Assert(chunk_size == BLCKSZ / 2 || chunk_size == BLCKSZ / 4 || chunk_size == BLCKSZ / 8 || - chunk_size == BLCKSZ / 16); + chunk_size == BLCKSZ / 16); // 鏂█锛岀‘淇漜hunk_size鏄湁鏁堢殑鍧楀ぇ灏忥紝鍙互鏄疊LCKSZ鐨2銆4銆8鎴16鍒嗕箣涓 if (pcAddr->allocated_chunks > BLCKSZ / chunk_size) { - ereport(ERROR, (errcode(ERRCODE_DATA_CORRUPTED), errmsg("invalid chunks %u of block %u in file \"%s\"", - pcAddr->allocated_chunks, blocknum, - FilePathName(v->mdfd_vfd_pca)))); + // 濡傛灉鍒嗛厤鐨勫潡鏁板ぇ浜庢枃浠跺潡澶у皬涓庡潡澶у皬鐨勬瘮鍊硷紝鎶ラ敊 + ereport(ERROR, (errcode(ERRCODE_DATA_CORRUPTED), + errmsg("invalid chunks %u of block %u in file \"%s\"", pcAddr->allocated_chunks, blocknum, + FilePathName(v->mdfd_vfd_pca)))); } auto maxChunkNumbers = MAX_CHUNK_NUMBER(chunk_size); for (auto i = 0; i < pcAddr->allocated_chunks; i++) { if (pcAddr->chunknos[i] <= 0 || pcAddr->chunknos[i] > maxChunkNumbers) { - ereport(ERROR, - (errcode(ERRCODE_DATA_CORRUPTED), errmsg("invalid chunk number %u of block %u in file \"%s\"", - pcAddr->chunknos[i], blocknum, - FilePathName(v->mdfd_vfd_pca)))); + // 濡傛灉鍒嗛厤鐨勫潡鍙峰皬浜庣瓑浜0鎴栧ぇ浜庢渶澶у厑璁稿潡鍙凤紝鎶ラ敊 + ereport(ERROR, (errcode(ERRCODE_DATA_CORRUPTED), + errmsg("invalid chunk number %u of block %u in file \"%s\"", pcAddr->chunknos[i], blocknum, + FilePathName(v->mdfd_vfd_pca)))); } } } - -int openrepairfile(char* path, RelFileNodeForkNum filenode) +/* + * 鍔熻兘锛氭墦寮鐢ㄤ簬淇鐨勬枃浠 + * + * 鍙傛暟鍒楄〃锛 + * path锛氳鎵撳紑鐨勬枃浠惰矾寰 + * filenode锛歊elFileNodeForkNum 缁撴瀯锛岃〃绀烘枃浠剁殑鍏宠仈鍏崇郴鍜屽垎鍙夌被鍨 + */ +int openrepairfile(char *path, RelFileNodeForkNum filenode) { + // 鍒濆鍖栨枃浠舵弿杩扮涓-1 int fd = -1; const int TEMPLEN = 8; + // 瀹氫箟骞跺垵濮嬪寲鎵撳紑鏂囦欢鐨勬爣蹇椾綅锛屼互鏀寔璇诲啓鍜屼簩杩涘埗妯″紡 volatile uint32 repair_flags = O_RDWR | PG_BINARY; + // 鍒嗛厤鐢ㄤ簬鏋勫缓涓存椂鏂囦欢璺緞鐨勫唴瀛 char *temppath = (char *)palloc(strlen(path) + TEMPLEN); + // 浣跨敤sprintf_s鏋勫缓涓存椂鏂囦欢璺緞锛屽苟妫鏌ユ槸鍚﹀嚭閿 errno_t rc = sprintf_s(temppath, strlen(path) + TEMPLEN, "%s.repair", path); securec_check_ss(rc, "", ""); + // 鏍规嵁缂栬瘧鍣ㄦ敮鎸佺殑鏍囧織浣嶏紝鍐冲畾鏄惁浣跨敤O_DIRECT ADIO_RUN() { repair_flags |= O_DIRECT; } ADIO_END(); + // 璋冪敤DataFileIdOpenFile鍑芥暟锛屼互涓存椂鏂囦欢璺緞鍜宖ilenode鍙傛暟鎵撳紑鏂囦欢 + // 骞惰繑鍥炴枃浠舵弿杩扮 fd = DataFileIdOpenFile(temppath, filenode, (int)repair_flags, 0600); + // 濡傛灉鎵撳紑鏂囦欢澶辫触锛岃緭鍑鸿鍛婃秷鎭 if (fd < 0) { ereport(WARNING, (errmsg("[file repair] could not open repair file %s: %m", temppath))); } + // 閲婃斁鍒嗛厤鐨勫唴瀛 pfree(temppath); return fd; } @@ -317,7 +435,7 @@ bool mdexists(SMgrRelation reln, ForkNumber forkNum, BlockNumber blockNum) return (mdopen(reln, forkNum, EXTENSION_RETURN_NULL) != NULL); } -static int RetryDataFileIdOpenFile(bool isRedo, char* path, const RelFileNodeForkNum &filenode, uint32 flags) +static int RetryDataFileIdOpenFile(bool isRedo, char *path, const RelFileNodeForkNum &filenode, uint32 flags) { int save_errno = errno; int fd = -1; @@ -353,7 +471,6 @@ static int RetryDataFileIdOpenFile(bool isRedo, char* path, const RelFileNodeFor ereport(ERROR, (errcode_for_file_access(), errmsg("could not create file \"%s\": %m", path))); } return fd; - } /* @@ -363,7 +480,7 @@ static int RetryDataFileIdOpenFile(bool isRedo, char* path, const RelFileNodeFor */ void mdcreate(SMgrRelation reln, ForkNumber forkNum, bool isRedo) { - char* path = NULL; + char *path = NULL; File fd; RelFileNodeForkNum filenode; volatile uint32 flags = O_RDWR | O_CREAT | O_EXCL | PG_BINARY; @@ -441,7 +558,7 @@ void mdcreate(SMgrRelation reln, ForkNumber forkNum, bool isRedo) reln->md_fd[forkNum] = _fdvec_alloc(); reln->md_fd[forkNum]->mdfd_vfd_pca = fd_pca; - reln->md_fd[forkNum] ->mdfd_vfd_pcd = fd_pcd; + reln->md_fd[forkNum]->mdfd_vfd_pcd = fd_pcd; reln->md_fd[forkNum]->mdfd_vfd = fd; reln->md_fd[forkNum]->mdfd_segno = 0; reln->md_fd[forkNum]->mdfd_chain = NULL; @@ -494,7 +611,7 @@ void mdcreate(SMgrRelation reln, ForkNumber forkNum, bool isRedo) * Note: any failure should be reported as WARNING not ERROR, because * we are usually not in a transaction anymore when this is called. */ -void mdunlink(const RelFileNodeBackend& rnode, ForkNumber forkNum, bool isRedo, uint32 segno) +void mdunlink(const RelFileNodeBackend &rnode, ForkNumber forkNum, bool isRedo, uint32 segno) { Assert(segno == InvalidBlockNumber); @@ -507,35 +624,59 @@ void mdunlink(const RelFileNodeBackend& rnode, ForkNumber forkNum, bool isRedo, mdunlinkfork(rnode, forkNum, isRedo); } } - +/* + * 鍔熻兘锛氳缃寚瀹氬叧绯诲拰鍒嗗弶鐨勬渶澶ф鍙 + * + * 鍙傛暟鍒楄〃锛 + * max_segno锛氳璁剧疆鐨勬渶澶ф鍙 + * rnode锛歊elFileNode 缁撴瀯锛岃〃绀哄叧绯荤殑鍏宠仈鍏崇郴 + * forknum锛欶orkNumber锛岃〃绀烘枃浠剁殑鍒嗗弶绫诲瀷 + */ void set_max_segno_delrel(int max_segno, RelFileNode rnode, ForkNumber forknum) { + // 鑾峰彇鍚嶄负unlink_rel_hashtbl鐨勫搱甯岃〃鐨勬寚閽 HTAB *relfilenode_hashtbl = g_instance.bgwriter_cxt.unlink_rel_hashtbl; - HTAB* relfilenode_fork_hashtbl = g_instance.bgwriter_cxt.unlink_rel_fork_hashtbl; + // 鑾峰彇鍚嶄负unlink_rel_fork_hashtbl鐨勫搱甯岃〃鐨勬寚閽 + HTAB *relfilenode_fork_hashtbl = g_instance.bgwriter_cxt.unlink_rel_fork_hashtbl; + // 瀹氫箟涓涓狣elFileTag缁撴瀯浣撴寚閽坋ntry锛岀敤浜庡瓨鍌ㄥ搱甯岃〃涓殑鍏抽敭瀛椾俊鎭 DelFileTag *entry = NULL; + // 瀹氫箟涓涓狥orkRelFileNode缁撴瀯浣撳彉閲廵ntry_key锛岀敤浜庡瓨鍌ㄥ叧閿瓧淇℃伅 ForkRelFileNode entry_key; + // 瀹氫箟涓涓狣elForkFileTag缁撴瀯浣撴寚閽坒ork_entry锛岀敤浜庡瓨鍌ㄥ搱甯岃〃涓殑鍏抽敭瀛椾俊鎭 DelForkFileTag *fork_entry = NULL; + // 甯冨皵鍙橀噺found鐢ㄤ簬琛ㄧず鏄惁鎵惧埌浜嗗叧閿瓧锛屽垵濮嬪间负false bool found = false; - + // 鑾峰彇鍚嶄负rel_hashtbl_lock鐨勮交閲忕骇閿侊紙LWLock锛夛紝浠ョ‘淇濆畨鍏ㄨ闂畊nlink_rel_hashtbl鍝堝笇琛 LWLockAcquire(g_instance.bgwriter_cxt.rel_hashtbl_lock, LW_SHARED); - entry = (DelFileTag*)hash_search(relfilenode_hashtbl, &(rnode), HASH_FIND, &found); + // 鍦╱nlink_rel_hashtbl鍝堝笇琛ㄤ腑鎼滅储鍏抽敭瀛梤node锛屽苟灏嗘悳绱㈢粨鏋滃瓨鍌ㄥ湪entry涓 + entry = (DelFileTag *)hash_search(relfilenode_hashtbl, &(rnode), HASH_FIND, &found); + // 濡傛灉鎵惧埌浜嗗叧閿瓧 if (found) { + // 姣旇緝max_segno鍜宔ntry->maxSegNo锛屽鏋渕ax_segno鏇村ぇ锛屾洿鏂癳ntry->maxSegNo if (max_segno > entry->maxSegNo) { entry->maxSegNo = max_segno; } } + // 閲婃斁rel_hashtbl_lock閿侊紝鍏佽鍏朵粬绾跨▼璁块棶unlink_rel_hashtbl鍝堝笇琛 LWLockRelease(g_instance.bgwriter_cxt.rel_hashtbl_lock); + // 濡傛灉鍦╱nlink_rel_hashtbl鍝堝笇琛ㄤ腑娌℃湁鎵惧埌鍏抽敭瀛梤node if (!found) { + // 璁剧疆entry_key鐨剅node鍜宖orkNum瀛楁 entry_key.rnode = rnode; entry_key.forkNum = forknum; + // 鑾峰彇鍚嶄负rel_one_fork_hashtbl_lock鐨勮交閲忕骇閿侊紙LWLock锛夛紝浠ョ‘淇濆畨鍏ㄨ闂畊nlink_rel_fork_hashtbl鍝堝笇琛 LWLockAcquire(g_instance.bgwriter_cxt.rel_one_fork_hashtbl_lock, LW_SHARED); - fork_entry = (DelForkFileTag*)hash_search(relfilenode_fork_hashtbl, &(entry_key), HASH_FIND, &found); + // 鍦╱nlink_rel_fork_hashtbl鍝堝笇琛ㄤ腑鎼滅储鍏抽敭瀛梕ntry_key锛屽苟灏嗘悳绱㈢粨鏋滃瓨鍌ㄥ湪fork_entry涓 + fork_entry = (DelForkFileTag *)hash_search(relfilenode_fork_hashtbl, &(entry_key), HASH_FIND, &found); + // 濡傛灉鎵惧埌浜嗗叧閿瓧 if (found) { + // 姣旇緝max_segno鍜宖ork_entry->maxSegNo锛屽鏋渕ax_segno鏇村ぇ锛屾洿鏂癴ork_entry->maxSegNo if (max_segno > fork_entry->maxSegNo) { fork_entry->maxSegNo = max_segno; } } + // 閲婃斁rel_one_fork_hashtbl_lock閿侊紝鍏佽鍏朵粬绾跨▼璁块棶unlink_rel_fork_hashtbl鍝堝笇琛 LWLockRelease(g_instance.bgwriter_cxt.rel_one_fork_hashtbl_lock); } return; @@ -543,7 +684,7 @@ void set_max_segno_delrel(int max_segno, RelFileNode rnode, ForkNumber forknum) /** * set all zero to pca file - * @param fd pca file fd + * @param fd pca file fd * @param chunkSize chunkSize * @param path for errport * @return 0 for success and other for failed @@ -578,7 +719,7 @@ static int ResetPcaFileInner(int fd, int chunkSize, char *path) } /** - * + * * @param fd pca_file fd * @param chunkSize chunkSize destination * @param path for ereport @@ -597,94 +738,143 @@ static bool ReadChunkSizeFromFile(int fd, uint16 *chunkSize, char *path) } return true; } - +/* + * 鍔熻兘锛氶噸缃寚瀹氳矾寰勭殑鍘嬬缉椤垫槧灏勬枃浠 + * + * 鍙傛暟鍒楄〃锛 + * path锛氳閲嶇疆鐨勬枃浠剁殑璺緞 + * rnode锛歊elFileNodeBackend 缁撴瀯锛岃〃绀烘枃浠剁殑鍏宠仈鍏崇郴 + */ static int ResetPcMap(char *path, const RelFileNodeBackend &rnode) { int ret = 0; char pcfile_path[MAXPGPATH]; + // 浣跨敤snprintf_s鏋勫缓鍘嬬缉椤垫槧灏勬枃浠剁殑璺緞锛屽苟妫鏌ユ槸鍚﹀嚭閿 int rc = snprintf_s(pcfile_path, MAXPGPATH, MAXPGPATH - 1, PCA_SUFFIX, path); securec_check_ss(rc, "\0", "\0"); + // 鎵撳紑鍘嬬缉椤垫槧灏勬枃浠讹紝浠ュ彲璇诲啓鍜屼簩杩涘埗妯″紡鎵撳紑 int fd_pca = BasicOpenFile(pcfile_path, O_RDWR | PG_BINARY, 0); + // 濡傛灉鎵撳紑鏂囦欢澶辫触锛岃繑鍥-1 if (fd_pca < 0) { return -1; } uint16 chunkSize; + // 浠庡帇缂╅〉鏄犲皠鏂囦欢涓鍙栧潡澶у皬 if (ReadChunkSizeFromFile(fd_pca, &chunkSize, pcfile_path)) { + // 浠庡帇缂╅〉鏄犲皠鏂囦欢涓鍙栧潡澶у皬 ret = ResetPcaFileInner(fd_pca, chunkSize, pcfile_path); } else { ret = -1; } + // 淇濆瓨褰撳墠鐨別rrno鍊 int save_errno = errno; + // 鍏抽棴鎵撳紑鐨勬枃浠 (void)close(fd_pca); + // 鎭㈠涔嬪墠淇濆瓨鐨別rrno鍊 errno = save_errno; - + return ret; } - -static void UnlinkCompressedFile(const RelFileNode& node, ForkNumber forkNum, char* path) +/* + * 鍔熻兘锛氬垹闄ゅ帇缂╂枃浠讹紙鍖呮嫭PCA鍜孭CD鏂囦欢锛 + * + * 鍙傛暟鍒楄〃锛 + * node锛歊elFileNode 缁撴瀯锛岃〃绀烘枃浠剁殑鍏宠仈鍏崇郴 + * forkNum锛欶orkNumber锛岃〃绀烘枃浠剁殑鍒嗗弶绫诲瀷 + * path锛氭枃浠剁殑璺緞 + */ +static void UnlinkCompressedFile(const RelFileNode &node, ForkNumber forkNum, char *path) { + // 妫鏌ユ枃浠舵槸鍚︿负鍘嬬缉鏂囦欢锛屽鏋滀笉鏄紝鐩存帴杩斿洖 if (!IS_COMPRESSED_RNODE(node, forkNum)) { return; } /* remove pca */ char pcfile_path[MAXPGPATH]; + // 妫鏌ユ枃浠舵槸鍚︿负鍘嬬缉鏂囦欢锛屽鏋滀笉鏄紝鐩存帴杩斿洖 errno_t rc = snprintf_s(pcfile_path, MAXPGPATH, MAXPGPATH - 1, PCA_SUFFIX, path); securec_check_ss(rc, "\0", "\0"); + // 璋冪敤unlink鍑芥暟锛屽垹闄CA鏂囦欢 int ret = unlink(pcfile_path); + // 濡傛灉鍒犻櫎澶辫触锛屽苟涓旈敊璇爜涓嶆槸ENOENT锛堟枃浠朵笉瀛樺湪锛夛紝杈撳嚭璀﹀憡娑堟伅 if (ret < 0 && errno != ENOENT) { ereport(WARNING, (errcode_for_file_access(), errmsg("could not remove file \"%s\": %m", pcfile_path))); } /* remove pcd */ rc = snprintf_s(pcfile_path, MAXPGPATH, MAXPGPATH - 1, PCD_SUFFIX, path); securec_check_ss(rc, "\0", "\0"); + // 璋冪敤unlink鍑芥暟锛屽垹闄CD鏂囦欢 ret = unlink(pcfile_path); + // 濡傛灉鍒犻櫎澶辫触锛屽苟涓旈敊璇爜涓嶆槸ENOENT锛堟枃浠朵笉瀛樺湪锛夛紝杈撳嚭璀﹀憡娑堟伅 if (ret < 0 && errno != ENOENT) { ereport(WARNING, (errcode_for_file_access(), errmsg("could not remove file \"%s\": %m", pcfile_path))); } } - +/* + * 鍔熻兘锛氬垹闄や笌鎸囧畾娈佃矾寰勭浉鍏崇殑淇鏂囦欢 + * + * 鍙傛暟鍒楄〃锛 + * segpath锛氭璺緞 + */ static void mdcleanrepairfile(char *segpath) { + // 瀹氫箟甯搁噺TEMPELN锛岃〃绀轰复鏃舵枃浠跺悕闀垮害 const int TEMPLEN = 8; struct stat statBuf; - + // 鍒嗛厤鍐呭瓨鐢ㄤ簬鏋勫缓涓存椂鏂囦欢璺緞锛屽叾闀垮害涓烘璺緞鐨勯暱搴﹀姞涓奣EMPELN char *temppath = (char *)palloc(strlen(segpath) + TEMPLEN); + // 浣跨敤sprintf_s鏋勫缓涓存椂鏂囦欢璺緞锛屽苟妫鏌ユ槸鍚﹀嚭閿 errno_t rc = sprintf_s(temppath, strlen(segpath) + TEMPLEN, "%s.repair", segpath); securec_check_ss(rc, "", ""); + // 浣跨敤stat鍑芥暟妫鏌ヤ复鏃舵枃浠舵槸鍚﹀瓨鍦 if (stat(temppath, &statBuf) >= 0) { + // 濡傛灉瀛樺湪锛屼娇鐢╱nlink鍑芥暟鍒犻櫎涓存椂鏂囦欢 (void)unlink(temppath); - ereport(LOG, (errcode_for_file_access(), - errmsg("remove repair file \"%s\"", temppath))); + // 杈撳嚭鏃ュ織娑堟伅锛岃〃绀哄凡鍒犻櫎淇鏂囦欢 + ereport(LOG, (errcode_for_file_access(), errmsg("remove repair file \"%s\"", temppath))); } + // 閲婃斁鍒嗛厤鐨勫唴瀛 pfree(temppath); } - -static void mdunlinkfork(const RelFileNodeBackend& rnode, ForkNumber forkNum, bool isRedo) +/* + * 鍔熻兘锛氬垹闄ゆ寚瀹氬叧鑱斿叧绯诲拰鍒嗗弶绫诲瀷鐨勬枃浠 + * + * 鍙傛暟鍒楄〃锛 + * rnode锛歊elFileNodeBackend 缁撴瀯锛岃〃绀烘枃浠剁殑鍏宠仈鍏崇郴 + * forkNum锛欶orkNumber锛岃〃绀烘枃浠剁殑鍒嗗弶绫诲瀷 + * isRedo锛氭寚绀烘槸鍚﹀湪閲嶅仛杩囩▼涓搷浣滅殑鏍囧織 + */ +static void mdunlinkfork(const RelFileNodeBackend &rnode, ForkNumber forkNum, bool isRedo) { - char* path = NULL; + char *path = NULL; int ret; - + // 鑾峰彇鏂囦欢鐨勮矾寰 path = relpath(rnode, forkNum); - + /* * Delete or truncate the first segment. */ Assert(IsHeapFileNode(rnode.node)); + // 濡傛灉鍦ㄩ噸鍋氳繃绋嬩腑鎿嶄綔锛屾垨鑰呮槸 inplace 鍗囩骇锛屾垨鑰呬笉鏄富鍒嗗弶锛屾垨鑰呮枃浠跺叧鑱斿叧绯绘槸涓存椂鐨 if (isRedo || u_sess->attr.attr_common.IsInplaceUpgrade || forkNum != MAIN_FORKNUM || RelFileNodeBackendIsTemp(rnode)) { /* First, forget any pending sync requests for the first segment */ + // 濡傛灉鏂囦欢涓嶆槸涓存椂鐨勶紝鍙栨秷瀵圭涓涓鐨勫悓姝ヨ姹 if (!RelFileNodeBackendIsTemp(rnode)) { md_register_forget_request(rnode.node, forkNum, 0 /* first segment */); } /* Next unlink the file */ - ret = unlink(path); + ret = unlink(path); // 鍒犻櫎鏂囦欢 + // 濡傛灉鍒犻櫎澶辫触锛屽苟涓旈敊璇爜涓嶆槸ENOENT锛堟枃浠朵笉瀛樺湪锛夛紝杈撳嚭璀﹀憡娑堟伅 if (ret < 0 && errno != ENOENT) { ereport(WARNING, (errcode_for_file_access(), errmsg("could not remove file \"%s\": %m", path))); } + // 濡傛灉鍒犻櫎澶辫触锛屽苟涓旈敊璇爜涓嶆槸ENOENT锛堟枃浠朵笉瀛樺湪锛夛紝杈撳嚭璀﹀憡娑堟伅 if (isRedo) { mdcleanrepairfile(path); } + // 璋冪敤UnlinkCompressedFile鍑芥暟鍒犻櫎鍘嬬缉鏂囦欢 UnlinkCompressedFile(rnode.node, forkNum, path); } else { /* truncate(2) would be easier here, but Windows hasn't got it */ @@ -694,16 +884,18 @@ static void mdunlinkfork(const RelFileNodeBackend& rnode, ForkNumber forkNum, bo if (fd >= 0) { int save_errno; - ret = ftruncate(fd, 0); + ret = ftruncate(fd, 0); // 浣跨敤ftruncate鍑芥暟鎴柇鏂囦欢锛岀敤浜庡垹闄ゆ枃浠跺唴瀹 save_errno = errno; (void)close(fd); errno = save_errno; } else { ret = -1; } + // 濡傛灉鎴柇澶辫触锛屽苟涓旈敊璇爜涓嶆槸ENOENT锛堟枃浠朵笉瀛樺湪锛夛紝杈撳嚭璀﹀憡娑堟伅 if (ret < 0 && errno != ENOENT) { ereport(WARNING, (errcode_for_file_access(), errmsg("could not truncate file \"%s\": %m", path))); } + // 濡傛灉鏂囦欢鏄帇缂╂枃浠讹紝璋冪敤ResetPcMap鍑芥暟閲嶇疆鍘嬬缉椤垫槧灏勬枃浠 if (IS_COMPRESSED_RNODE(rnode.node, forkNum)) { // dont truncate pca! pca may be occupied by other threads by mmap ret = ResetPcMap(path, rnode); @@ -722,6 +914,7 @@ static void mdunlinkfork(const RelFileNodeBackend& rnode, ForkNumber forkNum, bo } else { ret = -1; } + // 濡傛灉鍒犻櫎澶辫触锛屽苟涓旈敊璇爜涓嶆槸ENOENT锛岃緭鍑鸿鍛婃秷鎭 if (ret < 0 && errno != ENOENT) { ereport(WARNING, (errcode_for_file_access(), errmsg("could not truncate file \"%s\": %m", dataPath))); } @@ -757,7 +950,7 @@ static void mdunlinkfork(const RelFileNodeBackend& rnode, ForkNumber forkNum, bo /* ENOENT is expected after the last segment... */ if (errno != ENOENT) { ereport(WARNING, (errcode_for_file_access(), - errmsg("could not stat file \"%s\" before removing: %m", segpath))); + errmsg("could not stat file \"%s\" before removing: %m", segpath))); } break; } @@ -777,8 +970,7 @@ static void mdunlinkfork(const RelFileNodeBackend& rnode, ForkNumber forkNum, bo rc = sprintf_s(segpath, strlen(path) + 12, "%s.%u", path, segno); securec_check_ss(rc, "", ""); if (unlink(segpath) < 0) { - ereport(WARNING, (errcode_for_file_access(), - errmsg("could not remove file \"%s\": %m", segpath))); + ereport(WARNING, (errcode_for_file_access(), errmsg("could not remove file \"%s\": %m", segpath))); } if (IS_COMPRESSED_RNODE(rnode.node, forkNum)) { char pcfile_segpath[MAXPGPATH]; @@ -806,21 +998,35 @@ static void mdunlinkfork(const RelFileNodeBackend& rnode, ForkNumber forkNum, bo pfree(path); } - -static inline void ExtendChunksOfBlock(PageCompressHeader* pcMap, PageCompressAddr* pcAddr, int needChunks, MdfdVec* v) +/* + * 鍔熻兘锛氫负鎸囧畾鐨勫潡鍒嗛厤棰濆鐨勫帇缂╁潡锛屽苟灏嗗帇缂╁潡鐨勭姸鎬佸悓姝ュ埌鏄犲皠鏂囦欢 + * + * 鍙傛暟鍒楄〃锛 + * pcMap锛歅ageCompressHeader 缁撴瀯锛岃〃绀洪〉鍘嬬缉鏄犲皠澶撮儴淇℃伅 + * pcAddr锛歅ageCompressAddr 缁撴瀯锛岃〃绀洪〉鐨勫帇缂╁湴鍧淇℃伅 + * needChunks锛氶渶瑕佸垎閰嶇殑鍘嬬缉鍧楁暟閲 + * v锛歁dfdVec 缁撴瀯锛岃〃绀哄厓鏁版嵁鏂囦欢鎻忚堪绗﹀悜閲 + */ +static inline void ExtendChunksOfBlock(PageCompressHeader *pcMap, PageCompressAddr *pcAddr, int needChunks, MdfdVec *v) { + // 濡傛灉宸插垎閰嶇殑鍘嬬缉鍧楁暟閲忓皬浜庢墍闇鏁伴噺 if (pcAddr->allocated_chunks < needChunks) { auto allocateNumber = needChunks - pcAddr->allocated_chunks; + // 浣跨敤鍘熷瓙鎿嶄綔鍒嗛厤鍘嬬缉鍧楃紪鍙 int chunkno = (pc_chunk_number_t)pg_atomic_fetch_add_u32(&pcMap->allocated_chunks, allocateNumber) + 1; + // 鍒嗛厤鍘嬬缉鍧楃紪鍙风粰鍦板潃缁撴瀯涓湭鍒嗛厤鐨勪綅缃 for (int i = pcAddr->allocated_chunks; i < needChunks; ++i, ++chunkno) { pcAddr->chunknos[i] = chunkno; } pcAddr->allocated_chunks = needChunks; - + // 濡傛灉宸插垎閰嶇殑鍘嬬缉鍧楁暟閲忎笌涓婃鍚屾鏃剁殑鏁伴噺涔嬪樊瓒呰繃鎸囧畾闃堝 if (pg_atomic_read_u32(&pcMap->allocated_chunks) - pg_atomic_read_u32(&pcMap->last_synced_allocated_chunks) > COMPRESS_ADDRESS_FLUSH_CHUNKS) { + // 鏍囪鏄犲皠鏂囦欢闇瑕佸悓姝 pcMap->sync = false; + // 鏍囪鏄犲皠鏂囦欢闇瑕佸悓姝 if (sync_pcmap(pcMap, WAIT_EVENT_COMPRESS_ADDRESS_FILE_FLUSH) != 0) { + // 杈撳嚭閿欒娑堟伅锛岃〃绀哄悓姝ュけ璐 ereport(data_sync_elevel(ERROR), (errcode_for_file_access(), errmsg("could not msync file \"%s\": %m", FilePathName(v->mdfd_vfd_pca)))); } @@ -832,14 +1038,14 @@ static inline void ExtendChunksOfBlock(PageCompressHeader* pcMap, PageCompressAd * mdextend_pc() -- Add a block to the specified page compressed relation. * */ -static void mdextend_pc(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum, const char* buffer, bool skipFsync) +static void mdextend_pc(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum, const char *buffer, bool skipFsync) { #ifdef CHECK_WRITE_VS_EXTEND Assert(blocknum >= mdnblocks(reln, forknum)); #endif Assert(IS_COMPRESSED_MAINFORK(reln, forknum)); - MdfdVec* v = _mdfd_getseg(reln, MAIN_FORKNUM, blocknum, skipFsync, EXTENSION_CREATE); + MdfdVec *v = _mdfd_getseg(reln, MAIN_FORKNUM, blocknum, skipFsync, EXTENSION_CREATE); RelFileCompressOption option; TransCompressOptions(reln->smgr_rnode.node, &option); uint32 chunk_size = CHUNK_SIZE_LIST[option.compressChunkSize]; @@ -849,23 +1055,22 @@ static void mdextend_pc(SMgrRelation reln, ForkNumber forknum, BlockNumber block Assert(blocknum % RELSEG_SIZE >= pg_atomic_read_u32(&pcMap->nblocks)); uint32 maxAllocChunkNum = (uint32)(BLCKSZ / chunk_size - 1); - PageCompressAddr* pcAddr = GET_PAGE_COMPRESS_ADDR(pcMap, chunk_size, blocknum); + PageCompressAddr *pcAddr = GET_PAGE_COMPRESS_ADDR(pcMap, chunk_size, blocknum); prealloc_chunk = (prealloc_chunk > maxAllocChunkNum) ? maxAllocChunkNum : prealloc_chunk; /* check allocated chunk number */ if (pcAddr->allocated_chunks > BLCKSZ / chunk_size) { - ereport(ERROR, (errcode(ERRCODE_DATA_CORRUPTED), errmsg("invalid chunks %u of block %u in file \"%s\"", - pcAddr->allocated_chunks, blocknum, - FilePathName(v->mdfd_vfd_pca)))); + ereport(ERROR, (errcode(ERRCODE_DATA_CORRUPTED), + errmsg("invalid chunks %u of block %u in file \"%s\"", pcAddr->allocated_chunks, blocknum, + FilePathName(v->mdfd_vfd_pca)))); } for (int i = 0; i < pcAddr->allocated_chunks; ++i) { if (pcAddr->chunknos[i] <= 0 || pcAddr->chunknos[i] > (BLCKSZ / chunk_size) * RELSEG_SIZE) { - ereport(ERROR, - (errcode(ERRCODE_DATA_CORRUPTED), errmsg("invalid chunk number %u of block %u in file \"%s\"", - pcAddr->chunknos[i], blocknum, - FilePathName(v->mdfd_vfd_pca)))); + ereport(ERROR, (errcode(ERRCODE_DATA_CORRUPTED), + errmsg("invalid chunk number %u of block %u in file \"%s\"", pcAddr->chunknos[i], blocknum, + FilePathName(v->mdfd_vfd_pca)))); } } @@ -875,21 +1080,19 @@ static void mdextend_pc(SMgrRelation reln, ForkNumber forknum, BlockNumber block if (!PageIsNew(buffer)) { int work_buffer_size = CompressPageBufferBound(buffer, algorithm); if (work_buffer_size < 0) { - ereport(ERROR, - (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - errmsg("mdextend_pc unrecognized compression algorithm %d", algorithm))); + ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("mdextend_pc unrecognized compression algorithm %d", algorithm))); } - work_buffer = (char *) palloc(work_buffer_size); + work_buffer = (char *)palloc(work_buffer_size); int compressed_page_size = CompressPage(buffer, work_buffer, work_buffer_size, option); if (compressed_page_size < 0) { - ereport(ERROR, - (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - errmsg("mdextend_pc unrecognized compression algorithm %d", algorithm))); + ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("mdextend_pc unrecognized compression algorithm %d", algorithm))); } nchunks = (compressed_page_size - 1) / chunk_size + 1; if (nchunks * chunk_size >= BLCKSZ) { pfree(work_buffer); - work_buffer = (char *) buffer; + work_buffer = (char *)buffer; nchunks = BLCKSZ / chunk_size; } else { /* fill zero in the last chunk */ @@ -909,8 +1112,8 @@ static void mdextend_pc(SMgrRelation reln, ForkNumber forknum, BlockNumber block * worker_buffer = NULL -> nchunks = 0 */ for (int i = 0; i < nchunks; i++) { - char* buffer_pos = work_buffer + chunk_size * i; - off_t seekpos = (off_t) OFFSET_OF_PAGE_COMPRESS_CHUNK(chunk_size, pcAddr->chunknos[i]); + char *buffer_pos = work_buffer + chunk_size * i; + off_t seekpos = (off_t)OFFSET_OF_PAGE_COMPRESS_CHUNK(chunk_size, pcAddr->chunknos[i]); // write continuous chunks int range = 1; while (i < nchunks - 1 && pcAddr->chunknos[i + 1] == pcAddr->chunknos[i] + 1) { @@ -921,14 +1124,15 @@ static void mdextend_pc(SMgrRelation reln, ForkNumber forknum, BlockNumber block int nbytes; if ((nbytes = FileWrite(v->mdfd_vfd_pcd, buffer_pos, write_amount, seekpos)) != write_amount) { if (nbytes < 0) { - ereport(ERROR, (errcode_for_file_access(), errmsg("could not extend file \"%s\": %m", - FilePathName(v->mdfd_vfd_pcd)), errhint( - "Check free disk space."))); + ereport(ERROR, (errcode_for_file_access(), + errmsg("could not extend file \"%s\": %m", FilePathName(v->mdfd_vfd_pcd)), + errhint("Check free disk space."))); } /* short write: complain appropriately */ - ereport(ERROR, (errcode(ERRCODE_DISK_FULL), errmsg( - "could not extend file \"%s\": wrote only %d of %d bytes at block %u", FilePathName(v->mdfd_vfd_pcd), - nbytes, write_amount, blocknum), errhint("Check free disk space."))); + ereport(ERROR, (errcode(ERRCODE_DISK_FULL), + errmsg("could not extend file \"%s\": wrote only %d of %d bytes at block %u", + FilePathName(v->mdfd_vfd_pcd), nbytes, write_amount, blocknum), + errhint("Check free disk space."))); } } @@ -940,7 +1144,6 @@ static void mdextend_pc(SMgrRelation reln, ForkNumber forknum, BlockNumber block /* write checksum */ pcAddr->checksum = AddrChecksum32(blocknum, pcAddr, chunk_size); - if (pg_atomic_read_u32(&pcMap->nblocks) < blocknum % RELSEG_SIZE + 1) { pg_atomic_write_u32(&pcMap->nblocks, blocknum % RELSEG_SIZE + 1); } @@ -954,7 +1157,7 @@ static void mdextend_pc(SMgrRelation reln, ForkNumber forknum, BlockNumber block register_dirty_segment(reln, forknum, v); } - Assert(_mdnblocks(reln, forknum, v) <= ((BlockNumber) RELSEG_SIZE)); + Assert(_mdnblocks(reln, forknum, v) <= ((BlockNumber)RELSEG_SIZE)); } /* @@ -966,8 +1169,7 @@ static void mdextend_pc(SMgrRelation reln, ForkNumber forknum, BlockNumber block * EOF). Note that we assume writing a block beyond current EOF * causes intervening file space to become filled with zeroes. */ -void mdextend(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum, - char *buffer, bool skipFsync) +void mdextend(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum, char *buffer, bool skipFsync) { off_t seekpos; int nbytes; @@ -1011,20 +1213,19 @@ void mdextend(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum, */ if ((nbytes = FilePWrite(v->mdfd_vfd, buffer, BLCKSZ, seekpos, WAIT_EVENT_DATA_FILE_EXTEND)) != BLCKSZ) { if (check_unlink_rel_hashtbl(reln->smgr_rnode.node, forknum)) { - ereport(DEBUG1, - (errmsg("could not extend file \"%s\": %m, this relation has been removed", - FilePathName(v->mdfd_vfd)))); + ereport(DEBUG1, (errmsg("could not extend file \"%s\": %m, this relation has been removed", + FilePathName(v->mdfd_vfd)))); } else { if (nbytes < 0) { - ereport(ERROR, - (errcode_for_file_access(), errmsg("could not extend file \"%s\": %m", FilePathName(v->mdfd_vfd)), - errhint("Check free disk space."))); + ereport(ERROR, (errcode_for_file_access(), + errmsg("could not extend file \"%s\": %m", FilePathName(v->mdfd_vfd)), + errhint("Check free disk space."))); } /* short write: complain appropriately */ ereport(ERROR, (errcode(ERRCODE_DISK_FULL), - errmsg("could not extend file \"%s\": wrote only %d of %d bytes at block %u", - FilePathName(v->mdfd_vfd), nbytes, BLCKSZ, blocknum), - errhint("Check free disk space."))); + errmsg("could not extend file \"%s\": wrote only %d of %d bytes at block %u", + FilePathName(v->mdfd_vfd), nbytes, BLCKSZ, blocknum), + errhint("Check free disk space."))); } } @@ -1082,15 +1283,15 @@ static File mdopenagain(SMgrRelation reln, ForkNumber forknum, ExtensionBehavior return fd; } -static int MdOpenRetryOpenFile(char* path, const RelFileNodeForkNum &filenode, ExtensionBehavior behavior, uint32 flags) +static int MdOpenRetryOpenFile(char *path, const RelFileNodeForkNum &filenode, ExtensionBehavior behavior, uint32 flags) { int fd = -1; /* - * During bootstrap, there are cases where a system relation will be - * accessed (by internal backend processes) before the bootstrap - * script nominally creates it. Therefore, accept mdopen() as a - * substitute for mdcreate() in bootstrap mode only. (See mdcreate) - */ + * During bootstrap, there are cases where a system relation will be + * accessed (by internal backend processes) before the bootstrap + * script nominally creates it. Therefore, accept mdopen() as a + * substitute for mdcreate() in bootstrap mode only. (See mdcreate) + */ if (IsBootstrapProcessingMode()) { flags |= (O_CREAT | O_EXCL); fd = DataFileIdOpenFile(path, filenode, (int)flags, FILE_RW_PERMISSION); @@ -1199,9 +1400,17 @@ static MdfdVec *mdopen(SMgrRelation reln, ForkNumber forknum, ExtensionBehavior /* * mdclose() -- Close the specified relation, if it isn't closed already. */ +/* + * 鍔熻兘锛氬叧闂寚瀹氬叧鑱斿叧绯汇佸垎鍙夌被鍨嬪拰鍧楀彿鐨勬枃浠舵弿杩扮 + * + * 鍙傛暟鍒楄〃锛 + * reln锛歋MgrRelation 缁撴瀯锛岃〃绀烘枃浠剁殑瀛樺偍绠$悊鍣ㄥ叧绯 + * forknum锛欶orkNumber锛岃〃绀烘枃浠剁殑鍒嗗弶绫诲瀷 + * blockNum锛欱lockNumber锛岃〃绀哄潡鍙 + */ void mdclose(SMgrRelation reln, ForkNumber forknum, BlockNumber blockNum) { - MdfdVec *v = reln->md_fd[forknum]; + MdfdVec *v = reln->md_fd[forknum]; // 鑾峰彇鏂囦欢鎻忚堪绗﹀悜閲 /* No work if already closed */ if (v == NULL) { @@ -1210,20 +1419,20 @@ void mdclose(SMgrRelation reln, ForkNumber forknum, BlockNumber blockNum) reln->md_fd[forknum] = NULL; /* prevent dangling pointer after error */ - while (v != NULL) { + while (v != NULL) { // 鑾峰彇鏂囦欢鎻忚堪绗﹀悜閲 MdfdVec *ov = v; /* if not closed already */ if (IS_COMPRESSED_MAINFORK(reln, forknum)) { - if (v->mdfd_vfd_pca >= 0) { - FileClose(v->mdfd_vfd_pca); + if (v->mdfd_vfd_pca >= 0) { // 濡傛灉鍘嬬缉鍦板潃鏂囦欢鎻忚堪绗︽湁鏁 + FileClose(v->mdfd_vfd_pca); // 鍏抽棴鍘嬬缉鍦板潃鏂囦欢 } - if (v->mdfd_vfd_pcd >= 0) { - FileClose(v->mdfd_vfd_pcd); + if (v->mdfd_vfd_pcd >= 0) { // 濡傛灉鍘嬬缉鍦板潃鏂囦欢鎻忚堪绗︽湁鏁 + FileClose(v->mdfd_vfd_pca); // 鍏抽棴鍘嬬缉鍦板潃鏂囦欢 } } else { - if (v->mdfd_vfd >= 0) { - FileClose(v->mdfd_vfd); + if (v->mdfd_vfd >= 0) { // 濡傛灉鏂囦欢鎻忚堪绗︽湁鏁 + FileClose(v->mdfd_vfd); // 鍏抽棴鏂囦欢 } } @@ -1236,21 +1445,29 @@ void mdclose(SMgrRelation reln, ForkNumber forknum, BlockNumber blockNum) /* * mdprefetch() -- Initiate asynchronous read of the specified block of a relation */ +/* + * 鍔熻兘锛氶鍙栨寚瀹氬叧鑱斿叧绯汇佸垎鍙夌被鍨嬪拰鍧楀彿鐨勬枃浠跺潡鏁版嵁 + * + * 鍙傛暟鍒楄〃锛 + * reln锛歋MgrRelation 缁撴瀯锛岃〃绀烘枃浠剁殑瀛樺偍绠$悊鍣ㄥ叧绯 + * forknum锛欶orkNumber锛岃〃绀烘枃浠剁殑鍒嗗弶绫诲瀷 + * blocknum锛欱lockNumber锛岃〃绀哄潡鍙 + */ void mdprefetch(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum) { -#ifdef USE_PREFETCH +#ifdef USE_PREFETCH // 濡傛灉鍚敤浜嗛鍙栧姛鑳 off_t seekpos; MdfdVec *v = NULL; - v = _mdfd_getseg(reln, forknum, blocknum, false, EXTENSION_FAIL); + v = _mdfd_getseg(reln, forknum, blocknum, false, EXTENSION_FAIL); // 鑾峰彇鏂囦欢鎻忚堪绗﹀悜閲 if (v == NULL) { return; } - if (IS_COMPRESSED_MAINFORK(reln, forknum)) { - int chunk_size = PageCompressChunkSize(reln); - PageCompressHeader *pcMap = GetPageCompressMemoryMap(v->mdfd_vfd_pca, chunk_size); - PageCompressAddr *pcAddr = GET_PAGE_COMPRESS_ADDR(pcMap, chunk_size, blocknum); + if (IS_COMPRESSED_MAINFORK(reln, forknum)) { // 濡傛灉鏄帇缂╂枃浠 + int chunk_size = PageCompressChunkSize(reln); // 濡傛灉鏄帇缂╂枃浠 + PageCompressHeader *pcMap = GetPageCompressMemoryMap(v->mdfd_vfd_pca, chunk_size); // 鑾峰彇鍘嬬缉鏄犲皠澶撮儴 + PageCompressAddr *pcAddr = GET_PAGE_COMPRESS_ADDR(pcMap, chunk_size, blocknum); // 鑾峰彇鍘嬬缉鍦板潃淇℃伅 /* check chunk number */ if (pcAddr->nchunks < 0 || pcAddr->nchunks > BLCKSZ / chunk_size) { if (u_sess->attr.attr_security.zero_damaged_pages || t_thrd.xlog_cxt.InRecovery) { @@ -1263,6 +1480,7 @@ void mdprefetch(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum) } for (uint8 i = 0; i < pcAddr->nchunks; i++) { + /* 妫鏌ュ帇缂╁潡缂栧彿鏄惁鍚堟硶 */ if (pcAddr->chunknos[i] <= 0 || pcAddr->chunknos[i] > (uint32)(BLCKSZ / chunk_size) * RELSEG_SIZE) { if (u_sess->attr.attr_security.zero_damaged_pages || t_thrd.xlog_cxt.InRecovery) { return; @@ -1278,13 +1496,14 @@ void mdprefetch(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum) range++; i++; } + /* 妫鏌ュ帇缂╁潡缂栧彿鏄惁鍚堟硶 */ (void)FilePrefetch(v->mdfd_vfd_pcd, seekpos, chunk_size * range, WAIT_EVENT_DATA_FILE_PREFETCH); } - } else { + } else { // 濡傛灉涓嶆槸鍘嬬缉鏂囦欢 seekpos = (off_t)BLCKSZ * (blocknum % ((BlockNumber)RELSEG_SIZE)); Assert(seekpos < (off_t)BLCKSZ * RELSEG_SIZE); - + /* 浣跨敤FilePrefetch鍑芥暟棰勫彇鏂囦欢鏁版嵁 */ (void)FilePrefetch(v->mdfd_vfd, seekpos, BLCKSZ, WAIT_EVENT_DATA_FILE_PREFETCH); } #endif /* USE_PREFETCH */ @@ -1361,8 +1580,8 @@ void mdwriteback(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum, Bl FileWriteback(v->mdfd_vfd_pcd, seekpos, (off_t)nchunks * chunk_size); } } else { - seekpos = (off_t) BLCKSZ * (blocknum % ((BlockNumber) RELSEG_SIZE)); - FileWriteback(v->mdfd_vfd, seekpos, (off_t) BLCKSZ * nflush); + seekpos = (off_t)BLCKSZ * (blocknum % ((BlockNumber)RELSEG_SIZE)); + FileWriteback(v->mdfd_vfd, seekpos, (off_t)BLCKSZ * nflush); } nblocks -= nflush; blocknum += nflush; @@ -1614,82 +1833,106 @@ int CompltrWriteReq(void *aioDesc, long res) return 0; } -const int FILE_NAME_LEN = 128; +const int FILE_NAME_LEN = 128; // 瀹氫箟鏂囦欢鍚嶇殑鏈澶ч暱搴︿负128 +/* + * 鍔熻兘锛氭鏌ユ寚瀹氭枃浠剁殑鐘舵佷俊鎭苟灏嗙粨鏋滆褰曞埌鏃ュ織涓 + * + * 鍙傛暟鍒楄〃锛 + * file_name锛歝har 鎸囬拡锛岃〃绀鸿妫鏌ョ殑鏂囦欢鍚 + */ static void check_file_stat(char *file_name) { int rc; - struct stat stat_buf; - char file_path[MAX_PATH_LEN] = {0}; - char strfbuf[FILE_NAME_LEN]; + struct stat stat_buf; // 瀹氫箟鏂囦欢鍚嶇殑鏈澶ч暱搴︿负128 + char file_path[MAX_PATH_LEN] = {0}; // 瀹氫箟鏂囦欢鍚嶇殑鏈澶ч暱搴︿负128 + char strfbuf[FILE_NAME_LEN]; // 瀛樺偍鏃堕棿鎴崇殑瀛楃鏁扮粍 + // 濡傛灉鏁版嵁鐩綍鎴栨枃浠跺悕涓虹┖锛屽垯鐩存帴杩斿洖 if (t_thrd.proc_cxt.DataDir == NULL || file_name == NULL) { return; } + // 鏋勫缓鏂囦欢鐨勫畬鏁磋矾寰 rc = snprintf_s(file_path, MAX_PATH_LEN, MAX_PATH_LEN - 1, "%s/%s", t_thrd.proc_cxt.DataDir, file_name); securec_check_ss(rc, "", ""); + // 浣跨敤stat鍑芥暟鑾峰彇鏂囦欢鐨勭姸鎬佷俊鎭 if (stat(file_path, &stat_buf) == 0) { - pg_time_t stamp_time = (pg_time_t)stat_buf.st_mtime; + pg_time_t stamp_time = (pg_time_t)stat_buf.st_mtime; // 浣跨敤stat鍑芥暟鑾峰彇鏂囦欢鐨勭姸鎬佷俊鎭 if (log_timezone != NULL) { - struct pg_tm *tm = pg_localtime(&stamp_time, log_timezone); + struct pg_tm *tm = pg_localtime(&stamp_time, log_timezone); // 杞崲鏃堕棿鎴充负鏈湴鏃堕棿 if (tm != NULL) { + // 鏍煎紡鍖栨椂闂存埑涓哄瓧绗︿覆锛屽寘鎷棩鏈熴佹椂闂村拰鏃跺尯淇℃伅 (void)pg_strftime(strfbuf, sizeof(strfbuf), "%Y-%m-%d %H:%M:%S %Z", tm); ereport(LOG, (errmsg("file \"%s\" size is %ld bytes, last modify time is %s.", file_name, stat_buf.st_size, strfbuf))); } else { + // 濡傛灉鏃犳硶鑾峰彇鏈湴鏃堕棿锛屽彧璁板綍鏂囦欢鍚嶅拰澶у皬 ereport(LOG, (errmsg("file \"%s\" size is %ld bytes.", file_name, stat_buf.st_size))); } } else { + // 濡傛灉鏃犳硶鑾峰彇鏃跺尯淇℃伅锛屽彧璁板綍鏂囦欢鍚嶅拰澶у皬 ereport(LOG, (errmsg("file \"%s\" size is %ld bytes.", file_name, stat_buf.st_size))); } } else { + // 濡傛灉鏃犳硶鑾峰彇鏂囦欢鐘舵佷俊鎭紝璁板綍閿欒淇℃伅 ereport(LOG, (errmsg("could not stat the file : \"%s\".", file_name))); } } -#define CONTINUOUS_ASSIGN_2(a, b, value) do { \ - (a) = (value); \ - (b) = (value); \ -} while (0) +#define CONTINUOUS_ASSIGN_2(a, b, value) \ + do { \ + (a) = (value); \ + (b) = (value); \ + } while (0) -#define CONTINUOUS_ASSIGN_3(a, b, c, value) do { \ - (a) = (value); \ - (b) = (value); \ - (c) = (value); \ -} while (0) +#define CONTINUOUS_ASSIGN_3(a, b, c, value) \ + do { \ + (a) = (value); \ + (b) = (value); \ + (c) = (value); \ + } while (0) /* * mdread_pc() -- Read the specified block from a page compressed relation. */ +/* + * 鍔熻兘: 浠庡帇缂╁瓨鍌ㄤ腑璇诲彇鍘嬬缉鍧楀苟瑙e帇鍒扮粰瀹氱紦鍐插尯涓 + * + * 鍔熻兘鍒楄〃: + * reln: 瀛樺偍绠$悊鍣ㄥ叧绯诲璞 + * forknum: 鏂囦欢鍙ユ焺缂栧彿锛堜緥濡備富瑕佸彞鏌勬垨鍏朵粬鍙ユ焺锛 + * blocknum: 瑕佽鍙栫殑鍧楀彿 + * buffer: 瀛樺偍璇诲彇骞惰В鍘嬪悗鐨勬暟鎹殑缂撳啿鍖 + */ bool mdread_pc(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum, char *buffer) { - Assert(IS_COMPRESSED_MAINFORK(reln, forknum)); + Assert(IS_COMPRESSED_MAINFORK(reln, forknum)); // 纭繚鏂囦欢鏄帇缂╂枃浠 - MdfdVec *v = _mdfd_getseg(reln, forknum, blocknum, false, EXTENSION_FAIL); + MdfdVec *v = _mdfd_getseg(reln, forknum, blocknum, false, EXTENSION_FAIL); // 鑾峰彇鏂囦欢娈垫弿杩扮 RelFileCompressOption option; - TransCompressOptions(reln->smgr_rnode.node, &option); - uint32 chunk_size = CHUNK_SIZE_LIST[option.compressChunkSize]; - uint8 algorithm = option.compressAlgorithm; - PageCompressHeader *pcMap = GetPageCompressMemoryMap(v->mdfd_vfd_pca, chunk_size); - PageCompressAddr *pcAddr = GET_PAGE_COMPRESS_ADDR(pcMap, chunk_size, blocknum); - uint8 nchunks = pcAddr->nchunks; + TransCompressOptions(reln->smgr_rnode.node, &option); // 杞崲鍘嬬缉閫夐」 + uint32 chunk_size = CHUNK_SIZE_LIST[option.compressChunkSize]; // 鑾峰彇鍘嬬缉鍧楀ぇ灏 + uint8 algorithm = option.compressAlgorithm; // 鑾峰彇鍘嬬缉绠楁硶 + PageCompressHeader *pcMap = GetPageCompressMemoryMap(v->mdfd_vfd_pca, chunk_size); // 鑾峰彇鍘嬬缉椤靛唴瀛樻槧灏 + PageCompressAddr *pcAddr = GET_PAGE_COMPRESS_ADDR(pcMap, chunk_size, blocknum); // 鑾峰彇鍘嬬缉椤靛湴鍧淇℃伅 + uint8 nchunks = pcAddr->nchunks; // 鍘嬬缉椤典腑鍧楃殑鏁伴噺 if (nchunks == 0) { MemSet(buffer, 0, BLCKSZ); - return true; + return true; // 濡傛灉鍧楃殑鏁伴噺涓0锛岀洿鎺ュ~鍏0骞惰繑鍥 } if (nchunks > BLCKSZ / chunk_size) { if (u_sess->attr.attr_security.zero_damaged_pages || t_thrd.xlog_cxt.InRecovery) { MemSet(buffer, 0, BLCKSZ); - return true; + return true; // 濡傛灉鍧楃殑鏁伴噺瓒呭嚭棰勬湡锛屽苟涓斿厑璁搁浂鎹熷潖椤甸潰鎴栬呭浜庢仮澶嶆ā寮忥紝鐩存帴濉厖0骞惰繑鍥 } else { #ifndef ENABLE_MULTIPLE_NODES if (RecoveryInProgress()) { - return false; + return false; // 濡傛灉澶勪簬鎭㈠妯″紡锛岃繑鍥瀎alse } #endif - ereport(ERROR, - (errcode(ERRCODE_DATA_CORRUPTED), errmsg("invalid chunks %u of block %u in file \"%s\"", nchunks, - blocknum, FilePathName(v->mdfd_vfd_pca)))); + // 鍚﹀垯锛屾姤鍛婃暟鎹崯鍧忛敊璇 + ereport(ERROR, (errcode(ERRCODE_DATA_CORRUPTED), errmsg("invalid chunks %u of block %u in file \"%s\"", + nchunks, blocknum, FilePathName(v->mdfd_vfd_pca)))); } } @@ -1697,18 +1940,19 @@ bool mdread_pc(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum, char if (pcAddr->chunknos[i] <= 0 || pcAddr->chunknos[i] > MAX_CHUNK_NUMBER(chunk_size)) { if (u_sess->attr.attr_security.zero_damaged_pages || t_thrd.xlog_cxt.InRecovery) { MemSet(buffer, 0, BLCKSZ); - return true; + return true; // 濡傛灉鍧楃殑缂栧彿鏃犳晥锛屽苟涓斿厑璁搁浂鎹熷潖椤甸潰鎴栬呭浜庢仮澶嶆ā寮忥紝鐩存帴濉厖0骞惰繑鍥 } else { - check_file_stat(FilePathName(v->mdfd_vfd_pcd)); + check_file_stat(FilePathName(v->mdfd_vfd_pcd)); // 妫鏌ユ枃浠剁姸鎬 force_backtrace_messages = true; #ifndef ENABLE_MULTIPLE_NODES if (RecoveryInProgress()) { - return false; + return false; // 妫鏌ユ枃浠剁姸鎬 } #endif - ereport(ERROR, (errcode(ERRCODE_DATA_CORRUPTED), errmsg("invalid chunks %u of block %u in file \"%s\"", - nchunks, blocknum, - FilePathName(v->mdfd_vfd_pca)))); + // 妫鏌ユ枃浠剁姸鎬 + ereport(ERROR, + (errcode(ERRCODE_DATA_CORRUPTED), errmsg("invalid chunks %u of block %u in file \"%s\"", + nchunks, blocknum, FilePathName(v->mdfd_vfd_pca)))); } } } @@ -1717,10 +1961,10 @@ bool mdread_pc(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum, char char *buffer_pos = NULL; uint8 start; int read_amount; - char *compress_buffer = (char*)palloc(chunk_size * nchunks); + char *compress_buffer = (char *)palloc(chunk_size * nchunks); // 妫鏌ユ枃浠剁姸鎬 for (uint8 i = 0; i < nchunks; ++i) { buffer_pos = compress_buffer + chunk_size * i; - off_t seekpos = (off_t) OFFSET_OF_PAGE_COMPRESS_CHUNK(chunk_size, pcAddr->chunknos[i]); + off_t seekpos = (off_t)OFFSET_OF_PAGE_COMPRESS_CHUNK(chunk_size, pcAddr->chunknos[i]); start = i; while (i < nchunks - 1 && pcAddr->chunknos[i + 1] == pcAddr->chunknos[i] + 1) { i++; @@ -1741,9 +1985,8 @@ bool mdread_pc(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum, char return false; } #endif - ereport(ERROR, - (errcode_for_file_access(), errmsg("could not read block %u in file \"%s\": %m", blocknum, - FilePathName(v->mdfd_vfd_pcd)))); + ereport(ERROR, (errcode_for_file_access(), errmsg("could not read block %u in file \"%s\": %m", + blocknum, FilePathName(v->mdfd_vfd_pcd)))); } /* * Short read: we are at or past EOF, or we read a partial block at @@ -1765,9 +2008,9 @@ bool mdread_pc(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum, char return false; } #endif - ereport(ERROR, (errcode(ERRCODE_DATA_CORRUPTED), errmsg( - "could not read block %u in file \"%s\": read only %d of %d bytes", blocknum, - FilePathName(v->mdfd_vfd_pcd), nbytes, read_amount))); + ereport(ERROR, (errcode(ERRCODE_DATA_CORRUPTED), + errmsg("could not read block %u in file \"%s\": read only %d of %d bytes", blocknum, + FilePathName(v->mdfd_vfd_pcd), nbytes, read_amount))); } } } @@ -1781,9 +2024,9 @@ bool mdread_pc(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum, char nbytes = DecompressPage(compress_buffer, buffer, algorithm); if (nbytes != BLCKSZ) { if (nbytes == -2) { - ereport(ERROR, (errcode(ERRCODE_DATA_CORRUPTED), errmsg( - "could not recognized compression algorithm %d for file \"%s\"", algorithm, - FilePathName(v->mdfd_vfd_pcd)))); + ereport(ERROR, (errcode(ERRCODE_DATA_CORRUPTED), + errmsg("could not recognized compression algorithm %d for file \"%s\"", algorithm, + FilePathName(v->mdfd_vfd_pcd)))); } if (u_sess->attr.attr_security.zero_damaged_pages || t_thrd.xlog_cxt.InRecovery) { pfree(compress_buffer); @@ -1798,9 +2041,9 @@ bool mdread_pc(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum, char return false; } #endif - ereport(ERROR, (errcode(ERRCODE_DATA_CORRUPTED), errmsg( - "could not decompress block %u in file \"%s\": decompress %d of %d bytes", blocknum, - FilePathName(v->mdfd_vfd_pcd), nbytes, BLCKSZ))); + ereport(ERROR, (errcode(ERRCODE_DATA_CORRUPTED), + errmsg("could not decompress block %u in file \"%s\": decompress %d of %d bytes", + blocknum, FilePathName(v->mdfd_vfd_pcd), nbytes, BLCKSZ))); } } } @@ -1811,60 +2054,73 @@ bool mdread_pc(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum, char /* * mdread() -- Read the specified block from a relation. */ +/* + * 鍔熻兘锛氫粠瀛樺偍绠$悊鍣ㄤ腑璇诲彇鎸囧畾鍧楃殑鍐呭鍒扮紦鍐插尯锛屽苟杩涜鏍¢獙銆 + * + * 鍙傛暟鍒楄〃锛 + * reln: SMgrRelation 缁撴瀯浣擄紝琛ㄧず瀛樺偍绠$悊鍣ㄥ叧绯汇 + * forknum: ForkNumber 鍊硷紝琛ㄧず瑕佽鍙栫殑鍒嗘敮鍙枫 + * blocknum: BlockNumber 鍊硷紝琛ㄧず瑕佽鍙栫殑鍧楀彿銆 + * buffer: char 鎸囬拡锛岀敤浜庢帴鏀惰鍙栫殑鍧楁暟鎹殑缂撳啿鍖恒 + * + * 杩斿洖鍊硷細 + * SMGR_READ_STATUS 鏋氫妇锛岃〃绀鸿鍙栨搷浣滅殑缁撴灉鐘舵併 + */ SMGR_READ_STATUS mdread(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum, char *buffer) { - off_t seekpos; - int nbytes; - MdfdVec *v = NULL; + off_t seekpos; // 澹版槑鍙橀噺 seekpos锛岀敤浜庢枃浠跺畾浣 + int nbytes; // 澹版槑鍙橀噺 nbytes锛岀敤浜庡瓨鍌ㄨ鍙栫殑瀛楄妭鏁 + MdfdVec *v = NULL; // 澹版槑鏂囦欢鎻忚堪绗﹀悜閲忔寚閽堬紝骞跺垵濮嬪寲涓 NULL - instr_time startTime; - instr_time endTime; - PgStat_Counter timeDiff = 0; - static THR_LOCAL PgStat_Counter msgCount = 0; - static THR_LOCAL PgStat_Counter sumPage = 0; - static THR_LOCAL PgStat_Counter sumTime = 0; - static THR_LOCAL PgStat_Counter lstTime = 0; - static THR_LOCAL PgStat_Counter minTime = 0; - static THR_LOCAL PgStat_Counter maxTime = 0; + instr_time startTime; // 璁℃椂寮濮 + instr_time endTime; // 璁℃椂缁撴潫 + PgStat_Counter timeDiff = 0; // 瀛樺偍鏃堕棿宸 + static THR_LOCAL PgStat_Counter msgCount = 0; // 娑堟伅璁℃暟 + static THR_LOCAL PgStat_Counter sumPage = 0; // 鎬婚〉鏁 + static THR_LOCAL PgStat_Counter sumTime = 0; // 鎬绘椂闂 + static THR_LOCAL PgStat_Counter lstTime = 0; // 涓婃鏃堕棿 + static THR_LOCAL PgStat_Counter minTime = 0; // 鏈灏忔椂闂 + static THR_LOCAL PgStat_Counter maxTime = 0; // 鏈澶ф椂闂 static THR_LOCAL Oid lstFile = InvalidOid; static THR_LOCAL Oid lstDb = InvalidOid; static THR_LOCAL Oid lstSpc = InvalidOid; if (IS_COMPRESSED_MAINFORK(reln, forknum)) { + // 濡傛灉鏄帇缂╃殑涓诲垎鏀紝璋冪敤 mdread_pc 鍑芥暟杩涜璇诲彇鍜屾牎楠 bool success = mdread_pc(reln, forknum, blocknum, buffer); if (success && PageIsVerified((Page)buffer, blocknum)) { - return SMGR_RD_OK; + return SMGR_RD_OK; // 璇诲彇鎴愬姛涓旈氳繃鏍¢獙 } else { - return SMGR_RD_CRC_ERROR; + return SMGR_RD_CRC_ERROR; // 璇诲彇澶辫触鎴栨湭閫氳繃鏍¢獙 } } - (void)INSTR_TIME_SET_CURRENT(startTime); + (void)INSTR_TIME_SET_CURRENT(startTime); // 璁板綍寮濮嬫椂闂 TRACE_POSTGRESQL_SMGR_MD_READ_START(forknum, blocknum, reln->smgr_rnode.node.spcNode, reln->smgr_rnode.node.dbNode, reln->smgr_rnode.node.relNode, reln->smgr_rnode.backend); - v = _mdfd_getseg(reln, forknum, blocknum, false, EXTENSION_FAIL); + v = _mdfd_getseg(reln, forknum, blocknum, false, EXTENSION_FAIL); // 鑾峰彇鏂囦欢鎻忚堪绗﹀悜閲 if (v == NULL) { - return SMGR_RD_NO_BLOCK; + return SMGR_RD_NO_BLOCK; // 鏈壘鍒板潡 } - seekpos = (off_t)BLCKSZ * (blocknum % ((BlockNumber)RELSEG_SIZE)); + seekpos = (off_t)BLCKSZ * (blocknum % ((BlockNumber)RELSEG_SIZE)); // 璁$畻鏂囦欢瀹氫綅浣嶇疆 - nbytes = FilePRead(v->mdfd_vfd, buffer, BLCKSZ, seekpos, WAIT_EVENT_DATA_FILE_READ); + nbytes = FilePRead(v->mdfd_vfd, buffer, BLCKSZ, seekpos, WAIT_EVENT_DATA_FILE_READ); // 浠庢枃浠朵腑璇诲彇鏁版嵁 TRACE_POSTGRESQL_SMGR_MD_READ_DONE(forknum, blocknum, reln->smgr_rnode.node.spcNode, reln->smgr_rnode.node.dbNode, reln->smgr_rnode.node.relNode, reln->smgr_rnode.backend, nbytes, BLCKSZ); - (void)INSTR_TIME_SET_CURRENT(endTime); - INSTR_TIME_SUBTRACT(endTime, startTime); - timeDiff = INSTR_TIME_GET_MICROSEC(endTime); + (void)INSTR_TIME_SET_CURRENT(endTime); // 璁板綍缁撴潫鏃堕棿 + INSTR_TIME_SUBTRACT(endTime, startTime); // 璁$畻鏃堕棿宸 + timeDiff = INSTR_TIME_GET_MICROSEC(endTime); // 鑾峰彇寰绾ф椂闂村樊 if (msgCount == 0) { - lstFile = reln->smgr_rnode.node.relNode; - lstDb = reln->smgr_rnode.node.dbNode; - lstSpc = reln->smgr_rnode.node.spcNode; - CONTINUOUS_ASSIGN_2(msgCount, sumPage, 1); - CONTINUOUS_ASSIGN_3(sumTime, minTime, maxTime, timeDiff); + lstFile = reln->smgr_rnode.node.relNode; // 璁剧疆涓婃鏂囦欢 + lstDb = reln->smgr_rnode.node.dbNode; // 璁剧疆涓婃鏁版嵁搴 + lstSpc = reln->smgr_rnode.node.spcNode; // 璁剧疆涓婃绌洪棿 + CONTINUOUS_ASSIGN_2(msgCount, sumPage, 1); // 鍒嗛厤鍊肩粰璁℃暟鍜屾婚〉鏁 + CONTINUOUS_ASSIGN_3(sumTime, minTime, maxTime, timeDiff); // 鍒嗛厤鍊肩粰鎬绘椂闂淬佹渶灏忔椂闂村拰鏈澶ф椂闂 } else if (msgCount % STAT_MSG_BATCH == 0 || lstFile != reln->smgr_rnode.node.relNode) { PgStat_MsgFile msg; errno_t rc; @@ -1881,28 +2137,28 @@ SMGR_READ_STATUS mdread(SMgrRelation reln, ForkNumber forknum, BlockNumber block msg.maxtim = maxTime; reportFileStat(&msg); - rc = memset_s(&msg, sizeof(PgStat_MsgFile), 0, sizeof(PgStat_MsgFile)); + rc = memset_s(&msg, sizeof(PgStat_MsgFile), 0, sizeof(PgStat_MsgFile)); // 娓呴浂娑堟伅缁撴瀯 securec_check(rc, "", ""); - CONTINUOUS_ASSIGN_2(msgCount, sumPage, 1); - sumTime = timeDiff; + CONTINUOUS_ASSIGN_2(msgCount, sumPage, 1); // 鍒嗛厤鍊肩粰璁℃暟鍜屾婚〉鏁 + sumTime = timeDiff; // 鏇存柊鎬绘椂闂 if (lstFile != reln->smgr_rnode.node.relNode) { - lstFile = reln->smgr_rnode.node.relNode; - lstDb = reln->smgr_rnode.node.dbNode; - lstSpc = reln->smgr_rnode.node.spcNode; + lstFile = reln->smgr_rnode.node.relNode; // 鏇存柊涓婃鏂囦欢 + lstDb = reln->smgr_rnode.node.dbNode; // 鏇存柊涓婃鏁版嵁搴 + lstSpc = reln->smgr_rnode.node.spcNode; // 鏇存柊涓婃绌洪棿 CONTINUOUS_ASSIGN_3(sumTime, minTime, maxTime, timeDiff); } } else { - msgCount++; - sumPage++; - sumTime += timeDiff; + msgCount++; // 澧炲姞娑堟伅璁℃暟 + sumPage++; // 澧炲姞鎬婚〉鏁 + sumTime += timeDiff; // 澧炲姞鎬绘椂闂 } - lstTime = timeDiff; + lstTime = timeDiff; // 鏇存柊涓婃鏃堕棿 if (minTime > timeDiff) { - minTime = timeDiff; + minTime = timeDiff; // 鏇存柊鏈灏忔椂闂 } if (maxTime < timeDiff) { - maxTime = timeDiff; + maxTime = timeDiff; // 鏇存柊鏈澶ф椂闂 } if (nbytes != BLCKSZ) { @@ -1919,7 +2175,7 @@ SMGR_READ_STATUS mdread(SMgrRelation reln, ForkNumber forknum, BlockNumber block * update a block that was later truncated away. */ if (u_sess->attr.attr_security.zero_damaged_pages || t_thrd.xlog_cxt.InRecovery) { - MemSet(buffer, 0, BLCKSZ); + MemSet(buffer, 0, BLCKSZ); // 鍦ㄧ壒瀹氭潯浠朵笅锛屽~鍏呯紦鍐插尯涓洪浂 } else { check_file_stat(FilePathName(v->mdfd_vfd)); force_backtrace_messages = true; @@ -1930,7 +2186,7 @@ SMGR_READ_STATUS mdread(SMgrRelation reln, ForkNumber forknum, BlockNumber block } } - if (PageIsVerified((Page) buffer, blocknum)) { + if (PageIsVerified((Page)buffer, blocknum)) { return SMGR_RD_OK; } else { return SMGR_RD_CRC_ERROR; @@ -1954,10 +2210,9 @@ static void mdwrite_pc(SMgrRelation reln, ForkNumber forknum, BlockNumber blockn bool mmapSync = false; MdfdVec *v = _mdfd_getseg(reln, forknum, blocknum, skipFsync, EXTENSION_FAIL); - if (check_unlink_rel_hashtbl(reln->smgr_rnode.node, forknum)) { - ereport(DEBUG1, (errmsg("could not write block %u in file \"%s\": %m, this relation has been removed", - blocknum, FilePathName(v->mdfd_vfd)))); + ereport(DEBUG1, (errmsg("could not write block %u in file \"%s\": %m, this relation has been removed", blocknum, + FilePathName(v->mdfd_vfd)))); /* this file need skip sync */ return; } @@ -1982,16 +2237,18 @@ static void mdwrite_pc(SMgrRelation reln, ForkNumber forknum, BlockNumber blockn /* compress page */ auto work_buffer_size = CompressPageBufferBound(buffer, algorithm); if (work_buffer_size < 0) { - ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg( - "mdwrite_pc unrecognized compression algorithm %d,chunk_size:%ud,level:%d,prealloc_chunk:%ud", algorithm, - chunk_size, level, prealloc_chunk))); + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("mdwrite_pc unrecognized compression algorithm %d,chunk_size:%ud,level:%d,prealloc_chunk:%ud", + algorithm, chunk_size, level, prealloc_chunk))); } - char *work_buffer = (char *) palloc(work_buffer_size); + char *work_buffer = (char *)palloc(work_buffer_size); auto compress_buffer_size = CompressPage(buffer, work_buffer, work_buffer_size, option); if (compress_buffer_size < 0) { - ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg( - "mdwrite_pc unrecognized compression algorithm %d,chunk_size:%ud,level:%d,prealloc_chunk:%ud", algorithm, - chunk_size, level, prealloc_chunk))); + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("mdwrite_pc unrecognized compression algorithm %d,chunk_size:%ud,level:%d,prealloc_chunk:%ud", + algorithm, chunk_size, level, prealloc_chunk))); } uint8 nchunks = (compress_buffer_size - 1) / chunk_size + 1; @@ -1999,11 +2256,11 @@ static void mdwrite_pc(SMgrRelation reln, ForkNumber forknum, BlockNumber blockn if (bufferSize >= BLCKSZ) { /* store original page if can not save space? */ pfree(work_buffer); - work_buffer = (char *) buffer; + work_buffer = (char *)buffer; nchunks = BLCKSZ / chunk_size; } else { /* fill zero in the last chunk */ - if ((uint32) compress_buffer_size < bufferSize) { + if ((uint32)compress_buffer_size < bufferSize) { auto leftSize = bufferSize - compress_buffer_size; errno_t rc = memset_s(work_buffer + compress_buffer_size, leftSize, 0, leftSize); securec_check(rc, "", ""); @@ -2016,7 +2273,7 @@ static void mdwrite_pc(SMgrRelation reln, ForkNumber forknum, BlockNumber blockn // write chunks of compressed page for (auto i = 0; i < nchunks; ++i) { auto buffer_pos = work_buffer + chunk_size * i; - off_t seekpos = (off_t) OFFSET_OF_PAGE_COMPRESS_CHUNK(chunk_size, pcAddr->chunknos[i]); + off_t seekpos = (off_t)OFFSET_OF_PAGE_COMPRESS_CHUNK(chunk_size, pcAddr->chunknos[i]); auto start = i; while (i < nchunks - 1 && pcAddr->chunknos[i + 1] == pcAddr->chunknos[i] + 1) { i++; @@ -2033,14 +2290,14 @@ static void mdwrite_pc(SMgrRelation reln, ForkNumber forknum, BlockNumber blockn if (nbytes != write_amount) { if (nbytes < 0) { - ereport(ERROR, - (errcode_for_file_access(), errmsg("could not write block %u in file \"%s\": %m", blocknum, - FilePathName(v->mdfd_vfd_pcd)))); + ereport(ERROR, (errcode_for_file_access(), errmsg("could not write block %u in file \"%s\": %m", + blocknum, FilePathName(v->mdfd_vfd_pcd)))); } /* short write: complain appropriately */ - ereport(ERROR, (errcode(ERRCODE_DISK_FULL), errmsg( - "could not write block %u in file \"%s\": wrote only %d of %d bytes", blocknum, - FilePathName(v->mdfd_vfd_pcd), nbytes, BLCKSZ), errhint("Check free disk space."))); + ereport(ERROR, (errcode(ERRCODE_DISK_FULL), + errmsg("could not write block %u in file \"%s\": wrote only %d of %d bytes", blocknum, + FilePathName(v->mdfd_vfd_pcd), nbytes, BLCKSZ), + errhint("Check free disk space."))); } } @@ -2060,13 +2317,11 @@ static void mdwrite_pc(SMgrRelation reln, ForkNumber forknum, BlockNumber blockn pfree(work_buffer); } - if (!skipFsync && !SmgrIsTemp(reln)) { register_dirty_segment(reln, forknum, v); } } - /* * mdwrite() -- Write the supplied block at the appropriate location. * @@ -2176,19 +2431,19 @@ void mdwrite(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum, const if (nbytes != BLCKSZ) { if (check_unlink_rel_hashtbl(reln->smgr_rnode.node, forknum)) { ereport(DEBUG1, (errmsg("could not write block %u in file \"%s\": %m, this relation has been removed", - blocknum, FilePathName(v->mdfd_vfd)))); + blocknum, FilePathName(v->mdfd_vfd)))); /* this file need skip sync */ skipFsync = true; } else { if (nbytes < 0) { - ereport(ERROR, (errcode_for_file_access(), errmsg("could not write block %u in file \"%s\": %m", blocknum, - FilePathName(v->mdfd_vfd)))); + ereport(ERROR, (errcode_for_file_access(), errmsg("could not write block %u in file \"%s\": %m", + blocknum, FilePathName(v->mdfd_vfd)))); } /* short write: complain appropriately */ ereport(ERROR, (errcode(ERRCODE_DISK_FULL), - errmsg("could not write block %u in file \"%s\": wrote only %d of %d bytes", blocknum, - FilePathName(v->mdfd_vfd), nbytes, BLCKSZ), - errhint("Check free disk space."))); + errmsg("could not write block %u in file \"%s\": wrote only %d of %d bytes", blocknum, + FilePathName(v->mdfd_vfd), nbytes, BLCKSZ), + errhint("Check free disk space."))); } } @@ -2258,7 +2513,7 @@ BlockNumber mdnblocks(SMgrRelation reln, ForkNumber forknum) if (v->mdfd_chain == NULL) { if (check_unlink_rel_hashtbl(reln->smgr_rnode.node, forknum)) { ereport(DEBUG1, (errmsg("\"%s\": %m, this relation has been removed", - _mdfd_segpath(reln, forknum, segno)))); + _mdfd_segpath(reln, forknum, segno)))); return 0; } ereport(ERROR, (errcode_for_file_access(), @@ -2288,7 +2543,7 @@ void mdtruncate(SMgrRelation reln, ForkNumber forknum, BlockNumber nblocks) */ curnblk = mdnblocks(reln, forknum); if (curnblk == 0) { - return; + return; } if (nblocks > curnblk) { /* Bogus request ... but no complaint if InRecovery */ @@ -2315,7 +2570,7 @@ void mdtruncate(SMgrRelation reln, ForkNumber forknum, BlockNumber nblocks) * from the mdfd_chain). We truncate the file, but do not delete * it, for reasons explained in the header comments. */ - if (IS_COMPRESSED_MAINFORK(reln, forknum)) { + if (IS_COMPRESSED_MAINFORK(reln, forknum)) { chunk_size = PageCompressChunkSize(reln); pcMap = GetPageCompressMemoryMap(v->mdfd_vfd_pca, chunk_size); pg_atomic_write_u32(&pcMap->nblocks, 0); @@ -2340,18 +2595,18 @@ void mdtruncate(SMgrRelation reln, ForkNumber forknum, BlockNumber nblocks) errmsg("could not truncate file \"%s\": %m", FilePathName(v->mdfd_vfd_pcd)))); } } else { - if (FileTruncate(v->mdfd_vfd, 0, WAIT_EVENT_DATA_FILE_TRUNCATE) < 0) { - if (check_unlink_rel_hashtbl(reln->smgr_rnode.node, forknum)) { - ereport(DEBUG1, (errmsg("could not truncate file \"%s\": %m, this relation has been removed", - FilePathName(v->mdfd_vfd)))); - FileClose(ov->mdfd_vfd); - pfree(ov); - break; - } - ereport(ERROR, (errcode_for_file_access(), - errmsg("could not truncate file \"%s\": %m", FilePathName(v->mdfd_vfd)))); - } - } + if (FileTruncate(v->mdfd_vfd, 0, WAIT_EVENT_DATA_FILE_TRUNCATE) < 0) { + if (check_unlink_rel_hashtbl(reln->smgr_rnode.node, forknum)) { + ereport(DEBUG1, (errmsg("could not truncate file \"%s\": %m, this relation has been removed", + FilePathName(v->mdfd_vfd)))); + FileClose(ov->mdfd_vfd); + pfree(ov); + break; + } + ereport(ERROR, (errcode_for_file_access(), + errmsg("could not truncate file \"%s\": %m", FilePathName(v->mdfd_vfd)))); + } + } if (!SmgrIsTemp(reln)) { register_dirty_segment(reln, forknum, v); @@ -2377,7 +2632,7 @@ void mdtruncate(SMgrRelation reln, ForkNumber forknum, BlockNumber nblocks) */ BlockNumber last_seg_blocks = nblocks - prior_blocks; if (IS_COMPRESSED_MAINFORK(reln, forknum)) { - pc_chunk_number_t max_used_chunkno = (pc_chunk_number_t) 0; + pc_chunk_number_t max_used_chunkno = (pc_chunk_number_t)0; uint32 allocated_chunks; chunk_size = PageCompressChunkSize(reln); pcMap = GetPageCompressMemoryMap(v->mdfd_vfd_pca, chunk_size); @@ -2391,27 +2646,26 @@ void mdtruncate(SMgrRelation reln, ForkNumber forknum, BlockNumber nblocks) pcMap->sync = false; if (sync_pcmap(pcMap, WAIT_EVENT_COMPRESS_ADDRESS_FILE_SYNC) != 0) { ereport(data_sync_elevel(ERROR), - (errcode_for_file_access(), errmsg("could not msync file \"%s\": %m", - FilePathName(v->mdfd_vfd_pca)))); + (errcode_for_file_access(), + errmsg("could not msync file \"%s\": %m", FilePathName(v->mdfd_vfd_pca)))); } allocated_chunks = pg_atomic_read_u32(&pcMap->allocated_chunks); /* find the max used chunkno */ - for (BlockNumber blk = (BlockNumber) 0; blk < (BlockNumber) last_seg_blocks; blk++) { + for (BlockNumber blk = (BlockNumber)0; blk < (BlockNumber)last_seg_blocks; blk++) { pcAddr = GET_PAGE_COMPRESS_ADDR(pcMap, chunk_size, blk); /* check allocated_chunks for one page */ if (pcAddr->allocated_chunks > BLCKSZ / chunk_size) { - ereport(ERROR, - (errcode(ERRCODE_DATA_CORRUPTED), errmsg("invalid chunks %u of block %u in file \"%s\"", - pcAddr->allocated_chunks, blk, - FilePathName(v->mdfd_vfd_pca)))); + ereport(ERROR, (errcode(ERRCODE_DATA_CORRUPTED), + errmsg("invalid chunks %u of block %u in file \"%s\"", pcAddr->allocated_chunks, + blk, FilePathName(v->mdfd_vfd_pca)))); } /* check chunknos for one page */ for (i = 0; i < pcAddr->allocated_chunks; i++) { if (pcAddr->chunknos[i] == 0 || pcAddr->chunknos[i] > allocated_chunks) { - ereport(ERROR, (errcode(ERRCODE_DATA_CORRUPTED), errmsg( - "invalid chunk number %u of block %u in file \"%s\"", pcAddr->chunknos[i], blk, - FilePathName(v->mdfd_vfd_pca)))); + ereport(ERROR, (errcode(ERRCODE_DATA_CORRUPTED), + errmsg("invalid chunk number %u of block %u in file \"%s\"", + pcAddr->chunknos[i], blk, FilePathName(v->mdfd_vfd_pca)))); } if (pcAddr->chunknos[i] > max_used_chunkno) { @@ -2456,10 +2710,20 @@ void mdtruncate(SMgrRelation reln, ForkNumber forknum, BlockNumber nblocks) prior_blocks += RELSEG_SIZE; } } - -static bool CompressMdImmediateSync(SMgrRelation reln, ForkNumber forknum, MdfdVec* v) +/* + * 鍔熻兘锛氭墽琛岀珛鍗冲悓姝ユ搷浣滐紝纭繚瀵瑰帇缂╂枃浠剁殑淇敼琚悓姝ュ埌纾佺洏涓 + * + * 鍙傛暟鍒楄〃锛 + * reln锛歋MgrRelation 缁撴瀯锛岃〃绀烘枃浠舵墍灞炵殑 SMgrRelation + * forknum锛欶orkNumber 鏋氫妇锛岃〃绀烘枃浠剁殑鍒嗘敮鍙 + * v锛歁dfdVec 缁撴瀯鎸囬拡锛岃〃绀烘枃浠剁殑 MdfdVec 缁撴瀯 + * + */ +static bool CompressMdImmediateSync(SMgrRelation reln, ForkNumber forknum, MdfdVec *v) { - PageCompressHeader* pcMap = GetPageCompressMemoryMap(v->mdfd_vfd_pca, PageCompressChunkSize(reln)); + // 鑾峰彇鍘嬬缉鏂囦欢鐨勯〉鍘嬬缉澶撮儴鐨勬寚閽 + PageCompressHeader *pcMap = GetPageCompressMemoryMap(v->mdfd_vfd_pca, PageCompressChunkSize(reln)); + // 鍚屾 PageCompressHeader 缁撴瀯鍒扮鐩 if (sync_pcmap(pcMap, WAIT_EVENT_COMPRESS_ADDRESS_FILE_SYNC) != 0) { if (check_unlink_rel_hashtbl(reln->smgr_rnode.node, forknum)) { ereport(DEBUG1, (errmsg("could not fsync file \"%s\": %m, this relation has been removed", @@ -2469,6 +2733,7 @@ static bool CompressMdImmediateSync(SMgrRelation reln, ForkNumber forknum, MdfdV ereport(data_sync_elevel(ERROR), (errcode_for_file_access(), errmsg("could not msync file \"%s\": %m", FilePathName(v->mdfd_vfd_pca)))); } + // 鍚屾 PageCompressData 鍒扮鐩 if (FileSync(v->mdfd_vfd_pcd, WAIT_EVENT_DATA_FILE_IMMEDIATE_SYNC) < 0) { if (check_unlink_rel_hashtbl(reln->smgr_rnode.node, forknum)) { ereport(DEBUG1, (errmsg("could not fsync file \"%s\": %m, this relation has been removed", @@ -2499,21 +2764,21 @@ void mdimmedsync(SMgrRelation reln, ForkNumber forknum) v = mdopen(reln, forknum, EXTENSION_FAIL); while (v != NULL) { - if (IS_COMPRESSED_MAINFORK(reln, forknum)) { + if (IS_COMPRESSED_MAINFORK(reln, forknum)) { if (!CompressMdImmediateSync(reln, forknum, v)) { break; } } else { - if (FileSync(v->mdfd_vfd, WAIT_EVENT_DATA_FILE_IMMEDIATE_SYNC) < 0) { - if (check_unlink_rel_hashtbl(reln->smgr_rnode.node, forknum)) { - ereport(DEBUG1, (errmsg("could not fsync file \"%s\": %m, this relation has been removed", - FilePathName(v->mdfd_vfd)))); - break; - } - ereport(data_sync_elevel(ERROR), (errcode_for_file_access(), - errmsg("could not fsync file \"%s\": %m", FilePathName(v->mdfd_vfd)))); - } - } + if (FileSync(v->mdfd_vfd, WAIT_EVENT_DATA_FILE_IMMEDIATE_SYNC) < 0) { + if (check_unlink_rel_hashtbl(reln->smgr_rnode.node, forknum)) { + ereport(DEBUG1, (errmsg("could not fsync file \"%s\": %m, this relation has been removed", + FilePathName(v->mdfd_vfd)))); + break; + } + ereport(data_sync_elevel(ERROR), (errcode_for_file_access(), errmsg("could not fsync file \"%s\": %m", + FilePathName(v->mdfd_vfd)))); + } + } v = v->mdfd_chain; } } @@ -2641,7 +2906,7 @@ static MdfdVec *_mdfd_openseg(SMgrRelation reln, ForkNumber forknum, BlockNumber pfree(fullpath); return NULL; } - + int fd_pca = -1; int fd_pcd = -1; if (IS_COMPRESSED_MAINFORK(reln, forknum)) { @@ -2755,7 +3020,7 @@ static MdfdVec *_mdfd_getseg(SMgrRelation reln, ForkNumber forknum, BlockNumber } if (check_unlink_rel_hashtbl(reln->smgr_rnode.node, forknum)) { ereport(DEBUG1, (errmsg("could not open file \"%s\" (target block %u): %m", - _mdfd_segpath(reln, forknum, nextsegno), blkno))); + _mdfd_segpath(reln, forknum, nextsegno), blkno))); return NULL; } @@ -2784,13 +3049,13 @@ static BlockNumber _mdnblocks(SMgrRelation reln, ForkNumber forknum, const MdfdV off_t len; if (IS_COMPRESSED_MAINFORK(reln, forknum)) { PageCompressHeader *pcMap = GetPageCompressMemoryMap(seg->mdfd_vfd_pca, PageCompressChunkSize(reln)); - return (BlockNumber) pg_atomic_read_u32(&pcMap->nblocks); + return (BlockNumber)pg_atomic_read_u32(&pcMap->nblocks); } len = FileSeek(seg->mdfd_vfd, 0L, SEEK_END); if (len < 0) { if (check_unlink_rel_hashtbl(reln->smgr_rnode.node, forknum)) { ereport(DEBUG1, (errmsg("could not seek to end of file \"%s\": %m, this relation has been removed", - FilePathName(seg->mdfd_vfd)))); + FilePathName(seg->mdfd_vfd)))); return 0; } ereport(ERROR, (errcode_for_file_access(), @@ -2810,14 +3075,14 @@ static BlockNumber _mdnblocks(SMgrRelation reln, ForkNumber forknum, const MdfdV int SyncMdFile(const FileTag *ftag, char *path) { SMgrRelation reln = smgropen(ftag->rnode, InvalidBackendId, GetColumnNum(ftag->forknum)); - MdfdVec *v; - char *p; + MdfdVec *v; + char *p; File file = -1; File pcaFd = -1; File pcdFd = -1; int result; int savedErrno; - bool needClose = false; + bool needClose = false; /* Provide the path for informational messages. */ p = _mdfd_segpath(reln, ftag->forknum, ftag->segno); @@ -2825,8 +3090,7 @@ int SyncMdFile(const FileTag *ftag, char *path) pfree(p); /* Try to open the requested segment. */ - v = _mdfd_getseg(reln, ftag->forknum, ftag->segno * (BlockNumber) RELSEG_SIZE, - false, EXTENSION_RETURN_NULL); + v = _mdfd_getseg(reln, ftag->forknum, ftag->segno * (BlockNumber)RELSEG_SIZE, false, EXTENSION_RETURN_NULL); if (IS_COMPRESSED_RNODE(ftag->rnode, ftag->forknum)) { if (v == NULL) { pcaFd = OpenPcaFile(path, reln->smgr_rnode, ftag->forknum, ftag->segno); @@ -2904,7 +3168,7 @@ int SyncMdFile(const FileTag *ftag, char *path) */ int UnlinkMdFile(const FileTag *ftag, char *path) { - char *p; + char *p; /* Compute the path. */ p = relpathperm(ftag->rnode, MAIN_FORKNUM); @@ -2931,19 +3195,29 @@ bool MatchMdFileTag(const FileTag *ftag, const FileTag *candidate) */ return ftag->rnode.dbNode == candidate->rnode.dbNode; } - +/* + * 鍔熻兘锛氬悓姝ラ〉鍘嬬缉鍐呭瓨鏄犲皠鐨勬暟鎹埌纾佺洏 + * + * 鍙傛暟鍒楄〃锛 + * pcMap锛歅ageCompressHeader 缁撴瀯鐨勬寚閽堬紝琛ㄧず椤靛帇缂╁唴瀛樻槧灏勭殑澶撮儴淇℃伅 + * wait_event_info锛氫竴涓〃绀虹瓑寰呬簨浠剁殑鏍囪瘑锛岀敤浜庤褰曠瓑寰呬簨浠剁殑绫诲瀷 + */ static int sync_pcmap(PageCompressHeader *pcMap, uint32 wait_event_info) { + // 濡傛灉宸茬粡鏍囪涓洪渶瑕佸悓姝ワ紝鍒欑洿鎺ヨ繑鍥炴垚鍔 if (pg_atomic_read_u32(&pcMap->sync) == true) { return 0; } int returnCode; uint32 nblocks, allocated_chunks, last_synced_nblocks, last_synced_allocated_chunks; + // 濡傛灉宸茬粡鏍囪涓洪渶瑕佸悓姝ワ紝鍒欑洿鎺ヨ繑鍥炴垚鍔 nblocks = pg_atomic_read_u32(&pcMap->nblocks); allocated_chunks = pg_atomic_read_u32(&pcMap->allocated_chunks); last_synced_nblocks = pg_atomic_read_u32(&pcMap->last_synced_nblocks); last_synced_allocated_chunks = pg_atomic_read_u32(&pcMap->last_synced_allocated_chunks); + // 璋冪敤 pc_msync 鍑芥暟鎵ц鐪熸鐨勫唴瀛樻槧灏勫悓姝ユ搷浣 returnCode = pc_msync(pcMap); + // 濡傛灉鍚屾鎴愬姛锛屾洿鏂板凡鍚屾鐨勫睘鎬у if (returnCode == 0) { if (last_synced_nblocks != nblocks) { pg_atomic_write_u32(&pcMap->last_synced_nblocks, nblocks); @@ -2953,6 +3227,7 @@ static int sync_pcmap(PageCompressHeader *pcMap, uint32 wait_event_info) pg_atomic_write_u32(&pcMap->last_synced_allocated_chunks, allocated_chunks); } } + // 鏍囪涓哄凡鍚屾 pcMap->sync = true; return returnCode; } \ No newline at end of file diff --git a/src/gausskernel/storage/smgr/mmap_shared.cpp b/src/gausskernel/storage/smgr/mmap_shared.cpp index 4d8c85c73..02aee4c38 100644 --- a/src/gausskernel/storage/smgr/mmap_shared.cpp +++ b/src/gausskernel/storage/smgr/mmap_shared.cpp @@ -54,96 +54,148 @@ static inline pthread_mutex_t *MmapPartitionLock(size_t hashCode) { return &mmapLockArray[hashCode % LOCK_ARRAY_SIZE]; } - +/* + * 鍔熻兘锛氬悓姝ラ〉鍘嬬缉鍐呭瓨鏄犲皠鐨勬暟鎹埌纾佺洏 + * + * 鍙傛暟鍒楄〃锛 + * pcMap锛歅ageCompressHeader 缁撴瀯鐨勬寚閽堬紝琛ㄧず椤靛帇缂╁唴瀛樻槧灏勭殑澶撮儴淇℃伅 + * wait_event_info锛氫竴涓〃绀虹瓑寰呬簨浠剁殑鏍囪瘑锛岀敤浜庤褰曠瓑寰呬簨浠剁殑绫诲瀷 + */ static inline PageCompressHeader *MmapSharedMapFile(Vfd *vfdP, uint16 chunkSize, uint2 opt, bool readonly) { + // 璋冪敤 pc_mmap_real_size 鍑芥暟鏄犲皠鍏变韩鍐呭瓨鏂囦欢锛岃繑鍥炰竴涓寚鍚 PageCompressHeader 缁撴瀯浣撶殑鎸囬拡 map銆 auto map = pc_mmap_real_size(vfdP->fd, SIZE_OF_PAGE_COMPRESS_ADDR_FILE(chunkSize), false); + // 妫鏌ユ槧灏勭殑鏂囦欢鍖哄煙鏄惁鏈夋晥锛岃嫢鏃犳晥鍒欒繘琛屽垵濮嬪寲璁剧疆銆 if (map->chunk_size == 0 || map->algorithm == 0) { + // 妫鏌ユ槧灏勭殑鏂囦欢鍖哄煙鏄惁鏈夋晥锛岃嫢鏃犳晥鍒欒繘琛屽垵濮嬪寲璁剧疆銆 map->chunk_size = chunkSize; map->algorithm = GET_COMPRESS_ALGORITHM(opt); + // 浣跨敤 pc_msync 鍑芥暟灏嗘槧灏勫尯鍩熺殑鏁版嵁鍚屾鍒版枃浠朵腑銆 if (pc_msync(map) != 0) { + // 濡傛灉鍚屾澶辫触锛屽垯鐢熸垚閿欒鎶ュ憡銆 ereport(data_sync_elevel(ERROR), (errcode_for_file_access(), errmsg("could not msync file \"%s\": %m", vfdP->fileName))); } } + // 濡傛灉姝e湪杩涜鎭㈠鎿嶄綔涓旀槧灏勫尯鍩熸湭鍚屾锛屽垯璋冪敤 CheckAndRepairCompressAddress 鍑芥暟杩涜妫鏌ュ拰淇銆 if (RecoveryInProgress() && !map->sync) { CheckAndRepairCompressAddress(map, chunkSize, map->algorithm, vfdP->fileName); } + // 杩斿洖鏄犲皠鍖哄煙鐨勬寚閽 map銆 return map; } - +/* + * 鍔熻兘锛氬垵濮嬪寲椤靛帇缂╁唴瀛樻槧灏勭殑閿佹暟缁 + */ void RealInitialMMapLockArray() { + // 閬嶅巻閿佹暟缁勶紝涓烘瘡涓厓绱犲垵濮嬪寲涓涓簰鏂ラ攣 for (size_t i = 0; i < LOCK_ARRAY_SIZE; ++i) { pthread_mutex_init(&mmapLockArray[i], NULL); } - + // 鍒濆鍖栧搱甯岃〃鎺у埗缁撴瀯浣 HASHCTL ctl; /* hash accessed by database file id */ + // 浣跨敤 memset_s 鍑芥暟灏 ctl 缁撴瀯浣撴竻闆 errno_t rc = memset_s(&ctl, sizeof(ctl), 0, sizeof(ctl)); securec_check(rc, "", ""); - + // 璁剧疆鍝堝笇閿殑澶у皬鍜屾瘡涓潯鐩殑澶у皬 ctl.keysize = sizeof(RelFileNodeForkNum); ctl.entrysize = sizeof(MmapEntry); ctl.hash = tag_hash; ctl.num_partitions = LOCK_ARRAY_SIZE; const size_t initLen = 256; + // 鍒濆鍖栧唴瀛樺搱甯岃〃锛岀敤浜庨〉鍘嬬缉鍐呭瓨鏄犲皠鐨勭紦瀛 g_instance.mmapCache = HeapMemInitHash( "mmap hash", initLen, (Max(g_instance.attr.attr_common.max_files_per_process, t_thrd.storage_cxt.max_userdatafiles)) / 2, &ctl, HASH_ELEM | HASH_FUNCTION | HASH_PARTITION); } - +/* + * 鍔熻兘锛氳幏鍙栭〉鍘嬬缉鍐呭瓨鏄犲皠鐨勫ご閮ㄤ俊鎭 + * + * 鍙傛暟鍒楄〃锛 + * vfd锛氭寚鍚戞枃浠舵弿杩扮淇℃伅鐨勬寚閽 + * chunkSize锛歶int16 绫诲瀷锛岃〃绀洪〉闈㈠帇缂╃殑鍧楀ぇ灏 + * relFileNodeForkNum锛歊elFileNodeForkNum 缁撴瀯锛岃〃绀烘枃浠剁殑鏍囪瘑淇℃伅 + */ PageCompressHeader *GetPageCompressHeader(void *vfd, uint16 chunkSize, const RelFileNodeForkNum &relFileNodeForkNum) { + // 灏嗕紶鍏ョ殑 vfd 杞崲涓 Vfd 缁撴瀯浣撴寚閽 Vfd *currentVfd = (Vfd *)vfd; + // 璁$畻鍝堝笇鐮佷互鐢ㄤ簬閿佸垎鍖 uint32 hashCode = MmapTableHashCode(relFileNodeForkNum); + // 浣跨敤 AutoMutexLock 鑷姩鍔犻攣锛岄攣瀹氱浉搴旂殑鍒嗗尯 AutoMutexLock mmapLock(MmapPartitionLock(hashCode)); - + // 鍔犻攣 mmapLock.lock(); + // 鍒濆鍖栨煡鎵剧粨鏋滄爣蹇 bool find = false; + // 鍦ㄥ唴瀛樺搱甯岃〃涓悳绱㈡枃浠舵爣璇嗭紝骞惰繑鍥炵浉搴旂殑 MmapEntry 缁撴瀯鎸囬拡 MmapEntry *mmapEntry = (MmapEntry *)hash_search_with_hash_value(g_instance.mmapCache, (void *)&relFileNodeForkNum, hashCode, HASH_ENTER, &find); + // 濡傛灉鏈壘鍒板搴旀潯鐩紝鍒欒繘琛屽垵濮嬪寲璁剧疆 if (!find) { mmapEntry->pcmap = NULL; mmapEntry->reference = 0; } + // 濡傛灉 pcmap 涓虹┖锛屽垯璋冪敤 MmapSharedMapFile 鍑芥暟鏄犲皠鏂囦欢 if (mmapEntry->pcmap == NULL) { mmapEntry->pcmap = MmapSharedMapFile(currentVfd, chunkSize, relFileNodeForkNum.rnode.node.opt, false); } + // 澧炲姞瀵规槧灏勫尯鍩熺殑寮曠敤璁℃暟 ++mmapEntry->reference; + // 澧炲姞瀵规槧灏勫尯鍩熺殑寮曠敤璁℃暟 mmapLock.unLock(); + // 杩斿洖鏄犲皠鍖哄煙鐨勬寚閽 return mmapEntry->pcmap; } - +/* + * 鍔熻兘锛氳В闄ら〉鍘嬬缉鍐呭瓨鏄犲皠鐨勫紩鐢ㄨ鏁帮紝骞跺湪涓嶅啀浣跨敤鏃堕噴鏀捐祫婧 + * + * 鍙傛暟鍒楄〃锛 + * vfd锛氭寚鍚戞枃浠舵弿杩扮淇℃伅鐨勬寚閽 + */ void UnReferenceAddrFile(void *vfd) { + // 灏嗕紶鍏ョ殑 vfd 杞崲涓 Vfd 缁撴瀯浣撴寚閽 Vfd *currentVfd = (Vfd *)vfd; + // 鑾峰彇鏂囦欢鏍囪瘑淇℃伅 RelFileNodeForkNum relFileNodeForkNum = currentVfd->fileNode; + // 璁$畻鍝堝笇鐮佷互鐢ㄤ簬閿佸垎鍖 uint32 hashCode = MmapTableHashCode(relFileNodeForkNum); + // 浣跨敤 AutoMutexLock 鑷姩鍔犻攣锛岄攣瀹氱浉搴旂殑鍒嗗尯 AutoMutexLock mmapLock(MmapPartitionLock(hashCode)); mmapLock.lock(); + // 鍦ㄥ唴瀛樺搱甯岃〃涓悳绱㈡枃浠舵爣璇嗭紝骞惰繑鍥炵浉搴旂殑 MmapEntry 缁撴瀯鎸囬拡锛圚ASH_FIND 妯″紡锛 MmapEntry *mmapEntry = (MmapEntry *)hash_search_with_hash_value(g_instance.mmapCache, (void *)&relFileNodeForkNum, hashCode, HASH_FIND, NULL); + // 濡傛灉娌℃湁鎵惧埌瀵瑰簲鐨勬潯鐩紝鍒欑敓鎴愰敊璇姤鍛 if (mmapEntry == NULL) { ereport(ERROR, (errcode_for_file_access(), errmsg("UnReferenceAddrFile failed! mmap not found, filePath: %s", currentVfd->fileName))); } + // 鍑忓皯瀵规槧灏勫尯鍩熺殑寮曠敤璁℃暟 --mmapEntry->reference; + // 濡傛灉寮曠敤璁℃暟闄嶄负闆讹紝閲婃斁璧勬簮 if (mmapEntry->reference == 0) { + // 璋冪敤 pc_munmap 鍑芥暟閲婃斁鏄犲皠鍖哄煙鐨勮祫婧 if (pc_munmap(mmapEntry->pcmap) != 0) { ereport(ERROR, (errcode_for_file_access(), errmsg("could not munmap file \"%s\": %m", currentVfd->fileName))); } + // 浠庡唴瀛樺搱甯岃〃涓Щ闄ゅ搴旂殑鍝堝笇閿 if (hash_search_with_hash_value(g_instance.mmapCache, (void *)&relFileNodeForkNum, hashCode, HASH_REMOVE, NULL) == NULL) { ereport(ERROR, (errcode_for_file_access(), errmsg("UnReferenceAddrFile failed! remove hash key failed, filePath: %s", currentVfd->fileName))); } - } else if (mmapEntry->reference < 0) { + } + // 濡傛灉寮曠敤璁℃暟灏忎簬闆讹紝鐢熸垚鑷村懡閿欒鎶ュ憡 + else if (mmapEntry->reference < 0) { ereport(FATAL, (errcode_for_file_access(), errmsg("could not munmap file \"%s\": %m", currentVfd->fileName))); } - mmapLock.unLock(); + mmapLock.unLock(); // 瑙i攣 } \ No newline at end of file diff --git a/src/gausskernel/storage/smgr/page_compression.cpp b/src/gausskernel/storage/smgr/page_compression.cpp index f83fc46fa..513379277 100644 --- a/src/gausskernel/storage/smgr/page_compression.cpp +++ b/src/gausskernel/storage/smgr/page_compression.cpp @@ -35,39 +35,58 @@ #include "storage/checksum.h" #include "storage/page_compression.h" #include "storage/page_compression_impl.h" - -static void CheckHeaderOfCompressAddr(PageCompressHeader* pcMap, uint16 chunk_size, uint8 algorithm, const char* path) +/* + * 鍔熻兘锛氭鏌ラ〉鍘嬬缉鍐呭瓨鏄犲皠鐨勫ご閮ㄤ俊鎭槸鍚﹀悎娉曪紝濡傛灉涓嶅悎娉曞垯鏍规嵁閰嶇疆杩涜澶勭悊 + * + * 鍙傛暟鍒楄〃锛 + * pcMap锛歅ageCompressHeader 缁撴瀯鐨勬寚閽堬紝琛ㄧず椤靛帇缂╁唴瀛樻槧灏勭殑澶撮儴淇℃伅 + * chunk_size锛歶int16 绫诲瀷锛岃〃绀洪〉闈㈠帇缂╃殑鍧楀ぇ灏 + * algorithm锛歶int8 绫诲瀷锛岃〃绀哄帇缂╃畻娉 + * path锛歝onst char* 绫诲瀷锛岃〃绀烘枃浠惰矾寰 + */ +static void CheckHeaderOfCompressAddr(PageCompressHeader *pcMap, uint16 chunk_size, uint8 algorithm, const char *path) { + // 妫鏌ラ〉鍘嬬缉鍐呭瓨鏄犲皠鐨勫潡澶у皬鍜屽帇缂╃畻娉曟槸鍚︿笌棰勬湡鍊肩浉绗 if (pcMap->chunk_size != chunk_size || pcMap->algorithm != algorithm) { + // 濡傛灉鍚敤浜 zero_damaged_pages 閰嶇疆锛岀敓鎴愯鍛婂苟閲嶆柊鍒濆鍖栨槧灏勫ご閮ㄤ俊鎭 if (u_sess->attr.attr_security.zero_damaged_pages) { ereport(WARNING, - (errcode(ERRCODE_DATA_CORRUPTED), - errmsg("invalid chunk_size %u or algorithm %u in head of compress relation address file \"%s\", " - "and reinitialized it.", - pcMap->chunk_size, - pcMap->algorithm, - path))); + (errcode(ERRCODE_DATA_CORRUPTED), + errmsg("invalid chunk_size %u or algorithm %u in head of compress relation address file \"%s\", " + "and reinitialized it.", + pcMap->chunk_size, pcMap->algorithm, path))); + // 閲嶆柊璁剧疆鍘嬬缉绠楁硶銆乶blocks銆乤llocated_chunks 鍜 last_synced_allocated_chunks pcMap->algorithm = algorithm; pg_atomic_write_u32(&pcMap->nblocks, RELSEG_SIZE); pg_atomic_write_u32(&pcMap->allocated_chunks, 0); pg_atomic_write_u32(&pcMap->last_synced_allocated_chunks, 0); pcMap->chunk_size = chunk_size; } else { + // 濡傛灉鏈惎鐢 zero_damaged_pages 閰嶇疆锛岀敓鎴愰敊璇姤鍛 ereport(ERROR, - (errcode(ERRCODE_DATA_CORRUPTED), - errmsg("invalid chunk_size %u or algorithm %u in head of compress relation address file \"%s\"", - pcMap->chunk_size, - pcMap->algorithm, - path))); + (errcode(ERRCODE_DATA_CORRUPTED), + errmsg("invalid chunk_size %u or algorithm %u in head of compress relation address file \"%s\"", + pcMap->chunk_size, pcMap->algorithm, path))); } } } - +/* + * 鍔熻兘锛氭鏌ュ拰淇椤靛帇缂╁唴瀛樻槧灏勭殑鍦板潃淇℃伅锛屼互鍙婃洿鏂扮浉鍏充俊鎭 + * + * 鍙傛暟鍒楄〃锛 + * pcMap锛歅ageCompressHeader 缁撴瀯鐨勬寚閽堬紝琛ㄧず椤靛帇缂╁唴瀛樻槧灏勭殑澶撮儴淇℃伅 + * chunk_size锛歶int16 绫诲瀷锛岃〃绀洪〉闈㈠帇缂╃殑鍧楀ぇ灏 + * algorithm锛歶int8 绫诲瀷锛岃〃绀哄帇缂╃畻娉 + * path锛歝onst char* 绫诲瀷锛岃〃绀烘枃浠惰矾寰 + */ void CheckAndRepairCompressAddress(PageCompressHeader *pcMap, uint16 chunk_size, uint8 algorithm, const char *path) { + // 鑾峰彇涓婃鎭㈠鐨勬椂闂 TimestampTz lastRecoveryTime = pcMap->last_recovery_start_time; + // 鑾峰彇鏁版嵁搴撳惎鍔ㄧ殑鏃堕棿 TimestampTz pgStartTime = t_thrd.time_cxt.pg_start_time; + // 閿欒鐮佸彉閲 error_t rc; /* if the relation had been checked in this startup, skip */ if (lastRecoveryTime == pgStartTime) { @@ -76,21 +95,25 @@ void CheckAndRepairCompressAddress(PageCompressHeader *pcMap, uint16 chunk_size, /* check head of compress address file */ CheckHeaderOfCompressAddr(pcMap, chunk_size, algorithm, path); - + // 璇诲彇澶撮儴淇℃伅涓殑鍧楁暟鍜屽凡鍒嗛厤鍧楁暟 uint32 nblocks = pg_atomic_read_u32(&pcMap->nblocks); uint32 allocated_chunks = pg_atomic_read_u32(&pcMap->allocated_chunks); + // 涓哄叏灞鍧楀彿鏁扮粍鍒嗛厤鍐呭瓨 BlockNumber *global_chunknos = (BlockNumber *)palloc0(MAX_CHUNK_NUMBER(chunk_size) * sizeof(BlockNumber)); - + // 鍒濆鍖栧潡鍙峰彉閲 BlockNumber max_blocknum = (BlockNumber)-1; BlockNumber max_nonzero_blocknum = (BlockNumber)-1; BlockNumber max_allocated_chunkno = (pc_chunk_number_t)0; /* check compress address of every pages */ for (BlockNumber blocknum = 0; blocknum < (BlockNumber)RELSEG_SIZE; ++blocknum) { + // 鑾峰彇褰撳墠椤甸潰鐨勫帇缂╁湴鍧淇℃伅 PageCompressAddr *pcAddr = GET_PAGE_COMPRESS_ADDR(pcMap, chunk_size, blocknum); + // 鑾峰彇褰撳墠椤甸潰鐨勫帇缂╁湴鍧淇℃伅 if (pcAddr->checksum != AddrChecksum32(blocknum, pcAddr, chunk_size)) { ereport(WARNING, (errcode(ERRCODE_DATA_CORRUPTED), errmsg("invalid checkum %u of block %u in file \"%s\"", pcAddr->checksum, blocknum, path))); + // 灏嗚鍧楃殑鍘嬬缉鍦板潃淇℃伅娓呴浂 pcAddr->allocated_chunks = pcAddr->nchunks = 0; for (int i = 0; i < BLCKSZ / chunk_size; ++i) { pcAddr->chunknos[i] = 0; @@ -104,8 +127,10 @@ void CheckAndRepairCompressAddress(PageCompressHeader *pcMap, uint16 chunk_size, */ /* check allocated_chunks for one page */ + // 妫鏌ユ瘡涓〉闈㈢殑宸插垎閰嶅潡鏁 if (pcAddr->allocated_chunks > BLCKSZ / chunk_size) { if (u_sess->attr.attr_security.zero_damaged_pages) { + // 濡傛灉鍚敤浜 zero_damaged_pages 閰嶇疆锛屽皢璇ュ潡鐨勫帇缂╁湴鍧淇℃伅娓呴浂 rc = memset_s((void *)pcAddr, SIZE_OF_PAGE_COMPRESS_ADDR(chunk_size), 0, SIZE_OF_PAGE_COMPRESS_ADDR(chunk_size)); securec_check_c(rc, "\0", "\0"); @@ -114,6 +139,7 @@ void CheckAndRepairCompressAddress(PageCompressHeader *pcMap, uint16 chunk_size, pcAddr->allocated_chunks, blocknum, path))); continue; } else { + // 濡傛灉鏈惎鐢 zero_damaged_pages 閰嶇疆锛岄噴鏀惧唴瀛樺苟鐢熸垚閿欒鎶ュ憡 pfree(global_chunknos); ereport(ERROR, (errcode(ERRCODE_DATA_CORRUPTED), errmsg("invalid allocated_chunks %u of block %u in file \"%s\"", @@ -122,10 +148,12 @@ void CheckAndRepairCompressAddress(PageCompressHeader *pcMap, uint16 chunk_size, } /* check chunknos for one page */ + // 妫鏌ユ瘡涓〉闈㈢殑鍧楀彿鏄惁鏈夋晥 for (int i = 0; i < pcAddr->allocated_chunks; ++i) { /* check for invalid chunkno */ if (pcAddr->chunknos[i] == 0 || pcAddr->chunknos[i] > MAX_CHUNK_NUMBER(chunk_size)) { if (u_sess->attr.attr_security.zero_damaged_pages) { + // 濡傛灉鍚敤浜 zero_damaged_pages 閰嶇疆锛屽皢璇ュ潡鐨勫帇缂╁湴鍧淇℃伅娓呴浂 rc = memset_s((void *)pcAddr, SIZE_OF_PAGE_COMPRESS_ADDR(chunk_size), 0, SIZE_OF_PAGE_COMPRESS_ADDR(chunk_size)); securec_check_c(rc, "\0", "\0"); @@ -134,6 +162,7 @@ void CheckAndRepairCompressAddress(PageCompressHeader *pcMap, uint16 chunk_size, pcAddr->chunknos[i], blocknum, path))); continue; } else { + // 濡傛灉鏈惎鐢 zero_damaged_pages 閰嶇疆锛岄噴鏀惧唴瀛樺苟鐢熸垚閿欒鎶ュ憡 pfree(global_chunknos); ereport(ERROR, (errcode(ERRCODE_DATA_CORRUPTED), errmsg("invalid chunk number %u of block %u in file \"%s\"", pcAddr->chunknos[i], @@ -144,6 +173,7 @@ void CheckAndRepairCompressAddress(PageCompressHeader *pcMap, uint16 chunk_size, /* check for duplicate chunkno */ if (global_chunknos[pcAddr->chunknos[i] - 1] != 0) { if (u_sess->attr.attr_security.zero_damaged_pages) { + // 濡傛灉鍚敤浜 zero_damaged_pages 閰嶇疆锛屽皢璇ュ潡鐨勫帇缂╁湴鍧淇℃伅娓呴浂 rc = memset_s((void *)pcAddr, SIZE_OF_PAGE_COMPRESS_ADDR(chunk_size), 0, SIZE_OF_PAGE_COMPRESS_ADDR(chunk_size)); securec_check_c(rc, "\0", "\0"); @@ -155,6 +185,7 @@ void CheckAndRepairCompressAddress(PageCompressHeader *pcMap, uint16 chunk_size, pcAddr->chunknos[i], blocknum, global_chunknos[pcAddr->chunknos[i] - 1], path))); continue; } else { + // 濡傛灉鏈惎鐢 zero_damaged_pages 閰嶇疆锛岄噴鏀惧唴瀛樺苟鐢熸垚閿欒鎶ュ憡 pfree(global_chunknos); ereport(ERROR, (errcode(ERRCODE_DATA_CORRUPTED), @@ -177,6 +208,7 @@ void CheckAndRepairCompressAddress(PageCompressHeader *pcMap, uint16 chunk_size, /* check nchunks for one page */ if (pcAddr->nchunks > pcAddr->allocated_chunks) { if (u_sess->attr.attr_security.zero_damaged_pages) { + // 濡傛灉鍚敤浜 zero_damaged_pages 閰嶇疆锛屽皢璇ュ潡鐨勫帇缂╁湴鍧淇℃伅娓呴浂 rc = memset_s((void *)pcAddr, SIZE_OF_PAGE_COMPRESS_ADDR(chunk_size), 0, SIZE_OF_PAGE_COMPRESS_ADDR(chunk_size)); securec_check_c(rc, "\0", "\0"); @@ -187,6 +219,7 @@ void CheckAndRepairCompressAddress(PageCompressHeader *pcMap, uint16 chunk_size, pcAddr->nchunks, pcAddr->allocated_chunks, blocknum, path))); continue; } else { + // 濡傛灉鏈惎鐢 zero_damaged_pages 閰嶇疆锛岄噴鏀惧唴瀛樺苟鐢熸垚閿欒鎶ュ憡 pfree(global_chunknos); ereport(ERROR, (errcode(ERRCODE_DATA_CORRUPTED), errmsg("nchunks %u exceeds allocated_chunks %u of block %u in file \"%s\"", @@ -194,11 +227,13 @@ void CheckAndRepairCompressAddress(PageCompressHeader *pcMap, uint16 chunk_size, } } + // 鏇存柊鍧楀彿淇℃伅 max_blocknum = blocknum; if (pcAddr->nchunks > 0) { max_nonzero_blocknum = blocknum; } + // 鏇存柊鍏ㄥ眬鍧楀彿鏁扮粍 for (int i = 0; i < pcAddr->allocated_chunks; ++i) { global_chunknos[pcAddr->chunknos[i] - 1] = blocknum + 1; if (pcAddr->chunknos[i] > max_allocated_chunkno) { @@ -286,16 +321,24 @@ void CheckAndRepairCompressAddress(PageCompressHeader *pcMap, uint16 chunk_size, pcMap->last_recovery_start_time = pgStartTime; } -int64 CalculateMainForkSize(char* pathName, RelFileNode* rnode, ForkNumber forkNumber) +int64 CalculateMainForkSize(char *pathName, RelFileNode *rnode, ForkNumber forkNumber) { Assert(IS_COMPRESSED_RNODE((*rnode), forkNumber)); Assert(rnode->bucketNode == -1); return CalculateCompressMainForkSize(pathName); } - -void CopyCompressedPath(char dst[MAXPGPATH], const char* pathName, CompressedFileType compressFileType) +/* + * 鍔熻兘锛氬鍒跺帇缂╂枃浠剁殑璺緞 + * + * 鍙傛暟鍒楄〃锛 + * dst锛氱洰鏍囪矾寰勭殑瀛楃鏁扮粍锛岀敤浜庡瓨鍌ㄥ鍒跺悗鐨勮矾寰 + * pathName锛氭簮璺緞鐨勫瓧绗︿覆锛岃〃绀哄帇缂╂枃浠剁殑璺緞 + * compressFileType锛氬帇缂╂枃浠剁殑绫诲瀷锛屽彲浠ユ槸 COMPRESSED_TABLE_PCA_FILE 鎴 COMPRESSED_TABLE_PCD_FILE + */ +void CopyCompressedPath(char dst[MAXPGPATH], const char *pathName, CompressedFileType compressFileType) { int rc; + // 鏍规嵁鍘嬬缉鏂囦欢绫诲瀷鏋勯犵洰鏍囪矾寰 if (compressFileType == COMPRESSED_TABLE_PCA_FILE) { rc = snprintf_s(dst, MAXPGPATH, MAXPGPATH - 1, PCA_SUFFIX, pathName); } else { @@ -303,52 +346,91 @@ void CopyCompressedPath(char dst[MAXPGPATH], const char* pathName, CompressedFil } securec_check_ss(rc, "\0", "\0"); } - -int64 CalculateCompressMainForkSize(char* pathName, bool suppressedENOENT) +/* + * 鍔熻兘锛氳绠楀帇缂╀富鍒嗘敮鏂囦欢鐨勫ぇ灏 + * + * 鍙傛暟鍒楄〃锛 + * pathName锛氬帇缂╂枃浠剁殑璺緞瀛楃涓 + * suppressedENOENT锛氫竴涓竷灏斿硷紝琛ㄧず鏄惁蹇界暐 ENOENT 閿欒 + * + */ +int64 CalculateCompressMainForkSize(char *pathName, bool suppressedENOENT) { int64 totalsize = 0; char pcFilePath[MAXPGPATH]; + // 鏋勯犲帇缂╀富鍒嗘敮鏂囦欢鐨勮矾寰勶紝骞惰绠楀叾澶у皬骞剁疮鍔犲埌 totalsize CopyCompressedPath(pcFilePath, pathName, COMPRESSED_TABLE_PCA_FILE); totalsize += CalculateFileSize(pcFilePath, MAXPGPATH, suppressedENOENT); - + // 鏋勯犲帇缂╀富鍒嗘敮鏂囦欢鐨勮矾寰勶紝骞惰绠楀叾澶у皬骞剁疮鍔犲埌 totalsize CopyCompressedPath(pcFilePath, pathName, COMPRESSED_TABLE_PCD_FILE); totalsize += CalculateFileSize(pcFilePath, MAXPGPATH, suppressedENOENT); return totalsize; } - -uint16 ReadChunkSize(FILE* pcaFile, char* pcaFilePath, size_t len) +/* + * 鍔熻兘锛氫粠鍘嬬缉涓诲垎鏀枃浠朵腑璇诲彇鍧楀ぇ灏 + * + * 鍙傛暟鍒楄〃锛 + * pcaFile锛氬凡鎵撳紑鐨勫帇缂╀富鍒嗘敮鏂囦欢鐨勬枃浠舵寚閽 + * pcaFilePath锛氬帇缂╀富鍒嗘敮鏂囦欢鐨勮矾寰勫瓧绗︿覆 + * len锛氭枃浠堕暱搴 + * + * 杩斿洖鍊硷細 + * 璇诲彇鍒扮殑鍧楀ぇ灏忥紙uint16绫诲瀷锛 + */ +uint16 ReadChunkSize(FILE *pcaFile, char *pcaFilePath, size_t len) { uint16 chunkSize; + // 灏嗘枃浠舵寚閽堝畾浣嶅埌 PageCompressHeader 缁撴瀯涓殑 chunk_size 瀛楁 if (fseeko(pcaFile, (off_t)offsetof(PageCompressHeader, chunk_size), SEEK_SET) != 0) { ereport(ERROR, (errcode_for_file_access(), errmsg("could not seek in file \"%s\": \"%lu\": %m", pcaFilePath, len))); } + // 浠庢枃浠朵腑璇诲彇鍧楀ぇ灏 if (fread(&chunkSize, sizeof(chunkSize), 1, pcaFile) <= 0) { ereport(ERROR, (errcode_for_file_access(), errmsg("could not open file \"%s\": \"%lu\": %m", pcaFilePath, len))); } return chunkSize; } - -int64 CalculateFileSize(char* pathName, size_t size, bool suppressedENOENT) +/* + * 鍔熻兘锛氳绠楁枃浠剁殑澶у皬 + * + * 鍙傛暟鍒楄〃锛 + * pathName锛氭枃浠剁殑璺緞瀛楃涓 + * size锛氭枃浠剁殑榛樿澶у皬 + * suppressedENOENT锛氫竴涓竷灏斿硷紝琛ㄧず鏄惁蹇界暐 ENOENT 閿欒 + */ +int64 CalculateFileSize(char *pathName, size_t size, bool suppressedENOENT) { struct stat structstat; + // 鑾峰彇鏂囦欢鐨勭姸鎬佷俊鎭紝骞跺皢鍏跺瓨鍌ㄥ湪 structstat 缁撴瀯涓 if (stat(pathName, &structstat)) { if (errno == ENOENT) { if (suppressedENOENT) { return 0; } + // 濡傛灉鏂囦欢涓嶅瓨鍦ㄤ笖涓嶅拷鐣 ENOENT 閿欒锛屽垯鎶ュ憡鏂囦欢鏈壘鍒伴敊璇 ereport(ERROR, (errcode_for_file_access(), errmsg("could not FIND file \"%s\": %m", pathName))); } else { + // 濡傛灉鍙戠敓鍏朵粬閿欒锛屽垯鎶ュ憡鏃犳硶鑾峰彇鏂囦欢鐘舵佷俊鎭殑閿欒 ereport(ERROR, (errcode_for_file_access(), errmsg("could not stat file \"%s\": %m", pathName))); } } return structstat.st_size; } - +/* + * 鍔熻兘锛氬皢鍘嬬缉鍧楀ぇ灏忚浆鎹负绱㈠紩鍊 + * + * 鍙傛暟鍒楄〃锛 + * compressedChunkSize锛氬帇缂╁潡澶у皬 + * success锛氫竴涓竷灏旀寚閽堬紝鐢ㄤ簬鎸囩ず杞崲鏄惁鎴愬姛 + * + * 杩斿洖鍊硷細 + * 鍘嬬缉鍧楀ぇ灏忓搴旂殑绱㈠紩鍊硷紙uint1绫诲瀷锛 + */ uint1 ConvertChunkSize(uint32 compressedChunkSize, bool *success) { uint1 chunkSize = INDEX_OF_HALF_BLCKSZ; @@ -366,28 +448,38 @@ uint1 ConvertChunkSize(uint32 compressedChunkSize, bool *success) chunkSize = INDEX_OF_SIXTEENTHS_BLCKSZ; break; default: + // 濡傛灉鍘嬬缉鍧楀ぇ灏忎笉鍦ㄩ瀹氫箟鐨勮寖鍥村唴锛屾爣璁拌浆鎹㈠け璐ュ苟杩斿洖榛樿绱㈠紩鍊 *success = false; return chunkSize; } + // 鏍囪杞崲鎴愬姛骞惰繑鍥炵储寮曞 *success = true; return chunkSize; } constexpr int MAX_RETRY_LIMIT = 60; constexpr long RETRY_SLEEP_TIME = 1000000L; - -size_t ReadAllChunkOfBlock(char *dst, size_t destLen, BlockNumber blockNumber, ReadBlockChunksStruct& rbStruct) +/* + * 鍔熻兘锛氫粠鍘嬬缉鏂囦欢涓鍙栨寚瀹氬潡鍙风殑鎵鏈夊潡鏁版嵁 + * + * 鍙傛暟鍒楄〃锛 + * dst锛氱敤浜庡瓨鍌ㄨ鍙栨暟鎹殑鐩爣缂撳啿鍖 + * destLen锛氱洰鏍囩紦鍐插尯鐨勯暱搴 + * blockNumber锛氳璇诲彇鐨勫潡鍙 + * rbStruct锛氬寘鍚鍙栨搷浣滄墍闇淇℃伅鐨勭粨鏋勪綋 + */ +size_t ReadAllChunkOfBlock(char *dst, size_t destLen, BlockNumber blockNumber, ReadBlockChunksStruct &rbStruct) { - PageCompressHeader* header = rbStruct.header; + PageCompressHeader *header = rbStruct.header; + // 妫鏌ュ潡鍙锋槸鍚﹁秴鍑烘渶澶у潡鍙凤紝濡傛灉鏄垯鎶ラ敊 if (blockNumber >= header->nblocks) { ereport(ERROR, - (ERRCODE_INVALID_PARAMETER_VALUE, - errmsg("blocknum \"%u\" exceeds max block number", blockNumber))); + (ERRCODE_INVALID_PARAMETER_VALUE, errmsg("blocknum \"%u\" exceeds max block number", blockNumber))); } - const char* fileName = rbStruct.fileName; + const char *fileName = rbStruct.fileName; decltype(PageCompressHeader::chunk_size) chunkSize = header->chunk_size; decltype(ReadBlockChunksStruct::segmentNo) segmentNo = rbStruct.segmentNo; - PageCompressAddr* currentAddr = GET_PAGE_COMPRESS_ADDR(header, chunkSize, blockNumber); + PageCompressAddr *currentAddr = GET_PAGE_COMPRESS_ADDR(header, chunkSize, blockNumber); size_t tryCount = 0; /* for empty chunks write */ @@ -399,25 +491,30 @@ size_t ReadAllChunkOfBlock(char *dst, size_t destLen, BlockNumber blockNumber, R for (uint8 i = 0; i < nchunks; ++i) { off_t seekPos = (off_t)OFFSET_OF_PAGE_COMPRESS_CHUNK(chunkSize, currentAddr->chunknos[i]); uint8 start = i; + // 瀵绘壘杩炵画鐨勫潡锛屽悎骞惰鍙 while (i < nchunks - 1 && currentAddr->chunknos[i + 1] == currentAddr->chunknos[i] + 1) { i++; } + // 灏嗘枃浠舵寚閽堝畾浣嶅埌鍧楃殑浣嶇疆 if (fseeko(rbStruct.fp, seekPos, SEEK_SET) != 0) { ReleaseMap(header, fileName); ereport(ERROR, (errcode_for_file_access(), errmsg("could not seek in file \"%s\": %m", fileName))); } size_t readAmount = chunkSize * (i - start + 1); + // 浠庢枃浠朵腑璇诲彇鍧楁暟鎹紝骞跺皢鍏跺啓鍏ョ洰鏍囩紦鍐插尯 if (fread(dst + start * chunkSize, 1, readAmount, rbStruct.fp) != readAmount && ferror(rbStruct.fp)) { ReleaseMap(header, fileName); ereport(ERROR, (errcode_for_file_access(), errmsg("could not read file \"%s\": %m", fileName))); } } + // 濡傛灉鍧楁病鏈夋暟鎹紝鍒欒烦鍑哄惊鐜 if (nchunks == 0) { break; } char *data = NULL; size_t dataLen; uint32 crc32; + // 浠庣洰鏍囩紦鍐插尯涓幏鍙栨暟鎹佹暟鎹暱搴﹀拰鏍¢獙鍜 if (PageIs8BXidHeapVersion(dst)) { HeapPageCompressData *heapPageData = (HeapPageCompressData *)dst; data = heapPageData->data; @@ -429,6 +526,7 @@ size_t ReadAllChunkOfBlock(char *dst, size_t destLen, BlockNumber blockNumber, R dataLen = heapPageData->size; crc32 = heapPageData->crc32; } + // 浠庣洰鏍囩紦鍐插尯涓幏鍙栨暟鎹佹暟鎹暱搴﹀拰鏍¢獙鍜 if (DataBlockChecksum(data, dataLen, true) == crc32) { break; } @@ -439,28 +537,31 @@ size_t ReadAllChunkOfBlock(char *dst, size_t destLen, BlockNumber blockNumber, R } else { ReleaseMap(header, fileName); ereport(ERROR, - (errcode_for_file_access(), - errmsg("base backup cheksum or Decompressed blockno %u failed in file \"%s\", aborting backup. " - "nchunks: %u, allocatedChunks: %u, segno: %d.", - blockNumber, - fileName, - nchunks, - allocatedChunks, - segmentNo))); + (errcode_for_file_access(), + errmsg("base backup cheksum or Decompressed blockno %u failed in file \"%s\", aborting backup. " + "nchunks: %u, allocatedChunks: %u, segno: %d.", + blockNumber, fileName, nchunks, allocatedChunks, segmentNo))); } } while (true); + // 濡傛灉宸插垎閰嶇殑鍧楁暟澶т簬瀹為檯鍧楁暟锛屽皢澶氫綑鐨勫潡鏁版嵁娓呴浂 if (allocatedChunks > nchunks) { auto currentWriteSize = nchunks * chunkSize; securec_check( memset_s(dst + currentWriteSize, destLen - currentWriteSize, 0, (allocatedChunks - nchunks) * chunkSize), - "", - ""); + "", ""); } return allocatedChunks * chunkSize; } - -void ReleaseMap(PageCompressHeader* map, const char* fileName) +/* + * 鍔熻兘锛氶噴鏀鹃〉鍘嬬缉鍐呭瓨鏄犲皠 + * + * 鍙傛暟鍒楄〃锛 + * map锛歅ageCompressHeader 缁撴瀯鐨勬寚閽堬紝琛ㄧず椤靛帇缂╁唴瀛樻槧灏勭殑澶撮儴淇℃伅 + * fileName锛氭枃浠跺悕锛岃〃绀鸿閲婃斁鐨勬槧灏勫搴旂殑鏂囦欢 + */ +void ReleaseMap(PageCompressHeader *map, const char *fileName) { + // 妫鏌ユ槧灏勬寚閽堟槸鍚︽湁鏁堬紝骞跺皾璇曡В闄ゆ槧灏 if (map != NULL && pc_munmap(map) != 0) { ereport(WARNING, (errcode_for_file_access(), errmsg("could not munmap file \"%s\": %m", fileName))); } diff --git a/src/gausskernel/storage/smgr/segment/data_file.cpp b/src/gausskernel/storage/smgr/segment/data_file.cpp index d3268e23d..15db84a42 100644 --- a/src/gausskernel/storage/smgr/segment/data_file.cpp +++ b/src/gausskernel/storage/smgr/segment/data_file.cpp @@ -55,11 +55,16 @@ static int dv_open_file(char *filename, uint32 flags, int mode) errno = err; return fd; } - +/* + * 鍔熻兘锛氬叧闂枃浠舵弿杩扮骞剁敓鎴愭棩蹇椾俊鎭 + * + * 鍙傛暟鍒楄〃锛 + * fd锛歩nt锛岃〃绀烘枃浠舵弿杩扮 + */ static void dv_close_file(int fd) { - close(fd); - ereport(LOG, (errmsg("dv_close_file fd is %d", fd))); + close(fd); // 鍏抽棴鏂囦欢鎻忚堪绗 + ereport(LOG, (errmsg("dv_close_file fd is %d", fd))); // 鐢熸垚鏃ュ織淇℃伅锛岃褰曞叧闂殑鏂囦欢鎻忚堪绗︾殑鍊 } /* Return a palloc string, and callers should free it */ @@ -100,17 +105,13 @@ void df_create_file(SegLogicFile *sf, bool redo) // File not exists uint32 flags = O_RDWR | O_CREAT | O_EXCL | PG_BINARY; if (sf->segfiles != NULL) { - ereport(LOG, - (errmodule(MOD_SEGMENT_PAGE), - errmsg("[segpage] sf->segfiles is not null, last invocation of df_create_file must be failed " - "halfway. spc/db/relnode/fork: %u/%u/%d/%d", - sf->relNode.spcNode, - sf->relNode.dbNode, - sf->relNode.relNode, - sf->forknum))); + ereport(LOG, (errmodule(MOD_SEGMENT_PAGE), + errmsg("[segpage] sf->segfiles is not null, last invocation of df_create_file must be failed " + "halfway. spc/db/relnode/fork: %u/%u/%d/%d", + sf->relNode.spcNode, sf->relNode.dbNode, sf->relNode.relNode, sf->forknum))); } else { MemoryContext oldcnxt = MemoryContextSwitchTo(INSTANCE_GET_MEM_CXT_GROUP(MEMORY_CONTEXT_STORAGE)); - sf->segfiles = (SegPhysicalFile*)palloc(sizeof(SegPhysicalFile) * DF_ARRAY_EXTEND_STEP); + sf->segfiles = (SegPhysicalFile *)palloc(sizeof(SegPhysicalFile) * DF_ARRAY_EXTEND_STEP); MemoryContextSwitchTo(oldcnxt); for (int i = 0; i < DF_ARRAY_EXTEND_STEP; i++) { @@ -136,17 +137,28 @@ void df_create_file(SegLogicFile *sf, bool redo) } pfree(filename); } - +/* + * 鍔熻兘锛氳幏鍙栧垎娈甸昏緫鏂囦欢鐨勭墿鐞嗘枃浠 + * + * 鍙傛暟鍒楄〃锛 + * sf锛歋egLogicFile*锛屾寚鍚戝垎娈甸昏緫鏂囦欢鐨勬寚閽 + * sliceno锛歩nt锛屽垎鐗囧彿 + * target_block锛欱lockNumber锛岀洰鏍囧潡鍙 + * + * 杩斿洖鍊硷細SegPhysicalFile锛岃〃绀哄垎娈电墿鐞嗘枃浠剁殑缁撴瀯 + */ static SegPhysicalFile df_get_physical_file(SegLogicFile *sf, int sliceno, BlockNumber target_block) { - AutoMutexLock filelock(&sf->filelock); + AutoMutexLock filelock(&sf->filelock); // 浣跨敤鑷姩浜掓枼閿侊紝纭繚绾跨▼瀹夊叏 filelock.lock(); + // 妫鏌ョ洰鏍囧潡鍙锋槸鍚︿负鏃犳晥鍧楀彿 if (target_block == InvalidBlockNumber) { SegmentCheck(0); - ereport(ERROR, - (errcode(ERRCODE_DATA_EXCEPTION), errmsg("df_get_physical_file target_block is InvalidBlockNumber!\n"))); + ereport(ERROR, (errcode(ERRCODE_DATA_EXCEPTION), + errmsg("df_get_physical_file target_block is InvalidBlockNumber!\n"))); } + // 濡傛灉鐩爣鍧楀彿澶т簬鏂囦欢鐨勬诲潡鏁帮紝灏濊瘯鎵╁睍鏂囦欢 if (sf->total_blocks <= target_block) { ereport(LOG, (errmodule(MOD_SEGMENT_PAGE), errmsg("Try to access file %s block %u, exceeds the file total blocks %u", @@ -157,12 +169,21 @@ static SegPhysicalFile df_get_physical_file(SegLogicFile *sf, int sliceno, Block } } + // 妫鏌ュ垎鐗囧彿鏄惁鏈夋晥 SegmentCheck(sliceno < sf->file_num); + // 鑾峰彇鎸囧畾鍒嗙墖鐨勭墿鐞嗘枃浠 SegPhysicalFile spf = sf->segfiles[sliceno]; return spf; } - +/* + * 鍔熻兘锛氬埛鏂板垎娈甸昏緫鏂囦欢涓殑鏁版嵁鍒扮墿鐞嗘枃浠 + * + * 鍙傛暟鍒楄〃锛 + * sf锛歋egLogicFile*锛屾寚鍚戝垎娈甸昏緫鏂囦欢鐨勬寚閽 + * blocknum锛欱lockNumber锛岃捣濮嬪潡鍙 + * nblocks锛欱lockNumber锛屽潡鐨勬暟閲 + */ void df_flush_data(SegLogicFile *sf, BlockNumber blocknum, BlockNumber nblocks) { int128 remainBlocks = nblocks; @@ -176,12 +197,15 @@ void df_flush_data(SegLogicFile *sf, BlockNumber blocknum, BlockNumber nblocks) nflush = DF_FILE_SLICE_BLOCKS - (blocknum % DF_FILE_SLICE_BLOCKS); } + // 鑾峰彇鍒嗙墖鐨勭墿鐞嗘枃浠 SegPhysicalFile spf = df_get_physical_file(sf, slice_start, blocknum); if (spf.fd < 0) { return; } + // 璁$畻鐗╃悊鏂囦欢涓殑鍋忕Щ浣嶇疆 off_t seekpos = (off_t)BLCKSZ * (blocknum % DF_FILE_SLICE_BLOCKS); + // 璋冪敤搴曞眰鍑芥暟鍒锋柊鏁版嵁鍒扮墿鐞嗘枃浠 pg_flush_data(spf.fd, seekpos, (off_t)nflush * BLCKSZ); remainBlocks -= nflush; @@ -209,7 +233,13 @@ void df_extend_file_vector(SegLogicFile *sf) sf->segfiles = newfiles; sf->vector_capacity = new_capacity; } - +/* + * 鍔熻兘锛氬叧闂墍鏈夊垎娈甸昏緫鏂囦欢涓殑鏂囦欢鎻忚堪绗 + * + * 鍙傛暟鍒楄〃锛 + * key锛歊epairFileKey锛岃〃绀洪渶瑕佷慨澶嶇殑鏂囦欢鐨勫叧閿俊鎭 + * max_sliceno锛歩nt32锛屾渶澶у垎鐗囧彿 + */ void df_close_all_file(RepairFileKey key, int32 max_sliceno) { Oid relNode = key.relfilenode.relNode; @@ -218,10 +248,12 @@ void df_close_all_file(RepairFileKey key, int32 max_sliceno) SegSpace *spc = spc_init_space_node(key.relfilenode.spcNode, key.relfilenode.dbNode); Assert(relNode <= EXTENT_8192 && relNode > 0); + // 鑾峰彇鍒嗘绌洪棿骞跺姞閿 AutoMutexLock spc_lock(&spc->lock); spc_lock.lock(); SegExtentGroup *eg = &spc->extent_group[relNode - 1][forknum]; + // 鑾峰彇鍒嗘缁勫苟鍔犻攣 AutoMutexLock lock(&eg->lock); lock.lock(); @@ -234,11 +266,11 @@ void df_close_all_file(RepairFileKey key, int32 max_sliceno) if (stat(tempfilename, &statBuf) < 0) { /* ENOENT is expected after the last segment... */ if (errno != ENOENT) { - ereport(WARNING, (errcode_for_file_access(), - errmsg("could not stat file \"%s\": %m", tempfilename))); + ereport(WARNING, (errcode_for_file_access(), errmsg("could not stat file \"%s\": %m", tempfilename))); } } else { if (eg->segfile->segfiles[i].fd > 0) { + // 鍏抽棴鏂囦欢鎻忚堪绗 dv_close_file(eg->segfile->segfiles[i].fd); eg->segfile->segfiles[i].fd = -1; } @@ -254,7 +286,13 @@ void df_close_all_file(RepairFileKey key, int32 max_sliceno) spc_lock.unLock(); return; } - +/* + * 鍔熻兘锛氭竻闄ゅ苟鍏抽棴鎵鏈夊垎娈甸昏緫鏂囦欢涓殑鏂囦欢鎻忚堪绗 + * + * 鍙傛暟鍒楄〃锛 + * key锛歊epairFileKey锛岃〃绀洪渶瑕佷慨澶嶇殑鏂囦欢鐨勫叧閿俊鎭 + * max_sliceno锛歩nt32锛屾渶澶у垎鐗囧彿 + */ void df_clear_and_close_all_file(RepairFileKey key, int32 max_sliceno) { Oid relNode = key.relfilenode.relNode; @@ -262,10 +300,12 @@ void df_clear_and_close_all_file(RepairFileKey key, int32 max_sliceno) SegSpace *spc = spc_init_space_node(key.relfilenode.spcNode, key.relfilenode.dbNode); Assert(relNode <= EXTENT_8192 && relNode > 0); + // 鑾峰彇鍒嗘绌洪棿骞跺姞閿 AutoMutexLock spc_lock(&spc->lock); spc_lock.lock(); SegExtentGroup *eg = &spc->extent_group[relNode - 1][forknum]; + // 鑾峰彇鍒嗘缁勫苟鍔犻攣 AutoMutexLock lock(&eg->lock); lock.lock(); @@ -277,13 +317,12 @@ void df_clear_and_close_all_file(RepairFileKey key, int32 max_sliceno) tempfilename = slice_filename(eg->segfile->filename, i); int ret = unlink(tempfilename); if (ret < 0 && errno != ENOENT) { - ereport(WARNING, (errcode_for_file_access(), - errmsg("could not remove file \"%s\": %m", tempfilename))); + ereport(WARNING, (errcode_for_file_access(), errmsg("could not remove file \"%s\": %m", tempfilename))); } if (ret >= 0) { - ereport(LOG, (errcode_for_file_access(), - errmsg("[file repair] clear segment file \"%s\"", tempfilename))); + ereport(LOG, (errcode_for_file_access(), errmsg("[file repair] clear segment file \"%s\"", tempfilename))); if (eg->segfile->segfiles[i].fd > 0) { + // 鍏抽棴鏂囦欢鎻忚堪绗 dv_close_file(eg->segfile->segfiles[i].fd); eg->segfile->segfiles[i].fd = -1; } @@ -299,7 +338,13 @@ void df_clear_and_close_all_file(RepairFileKey key, int32 max_sliceno) spc_lock.unLock(); return; } - +/* + * 鍔熻兘锛氭墦寮鎵鏈夊垎娈甸昏緫鏂囦欢涓殑鏂囦欢鎻忚堪绗 + * + * 鍙傛暟鍒楄〃锛 + * key锛歊epairFileKey锛岃〃绀洪渶瑕佷慨澶嶇殑鏂囦欢鐨勫叧閿俊鎭 + * max_sliceno锛歩nt32锛屾渶澶у垎鐗囧彿 + */ void df_open_all_file(RepairFileKey key, int32 max_sliceno) { int fd = -1; @@ -310,10 +355,12 @@ void df_open_all_file(RepairFileKey key, int32 max_sliceno) SegSpace *spc = spc_init_space_node(key.relfilenode.spcNode, key.relfilenode.dbNode); Assert(relNode <= EXTENT_8192 && relNode > 0); + // 鑾峰彇鍒嗘绌洪棿骞跺姞閿 AutoMutexLock spc_lock(&spc->lock); spc_lock.lock(); SegExtentGroup *eg = &spc->extent_group[relNode - 1][forknum]; + // 鑾峰彇鍒嗘缁勫苟鍔犻攣 AutoMutexLock eg_lock(&eg->lock); eg_lock.lock(); @@ -349,20 +396,32 @@ void df_open_all_file(RepairFileKey key, int32 max_sliceno) /* * sliceno == 0, means opening all files; otherwises open until the target slice. */ +/* + * 鍔熻兘锛氭墦寮鐩爣鏂囦欢骞跺垵濮嬪寲鐩稿簲鐨勬枃浠舵弿杩扮鍜岀浉鍏充俊鎭 + * + * 鍙傛暟鍒楄〃锛 + * sf锛歋egLogicFile*锛屽垎娈甸昏緫鏂囦欢缁撴瀯鎸囬拡 + * targetno锛歩nt锛岀洰鏍囨枃浠跺彿 + */ static void df_open_target_files(SegLogicFile *sf, int targetno) { - int sliceno = sf->file_num; + int sliceno = sf->file_num; // 褰撳墠鏂囦欢鏁板嵆鍒嗙墖鍙 uint32 flags = O_RDWR | PG_BINARY; + // 寰幆鎵撳紑鐩爣鏂囦欢鍜屽悗缁枃浠 for (;;) { + // 濡傛灉鎸囧畾浜嗙洰鏍囨枃浠跺彿骞朵笖宸茬粡杈惧埌浜嗙洰鏍囨枃浠跺彿锛屽垯閫鍑哄惊鐜 if (targetno != 0 && targetno < sliceno) { break; } + // 鏋勫缓鏂囦欢鍚 char *filename = slice_filename(sf->filename, sliceno); + // 濡傛灉鍒嗙墖鍙疯秴鍑轰簡鍚戦噺鐨勫閲忥紝鎵╁睍鍚戦噺 if (sliceno >= sf->vector_capacity) { df_extend_file_vector(sf); } + // 灏濊瘯鎵撳紑鏂囦欢 int fd = dv_open_file(filename, flags, SEGMENT_FILE_MODE); if (fd < 0) { if (errno != ENOENT) { @@ -375,13 +434,16 @@ static void df_open_target_files(SegLogicFile *sf, int targetno) break; } + // 鍒濆鍖栨枃浠舵弿杩扮鍜屾诲潡鏁 sf->segfiles[sliceno].fd = fd; sf->segfiles[sliceno].sliceno = sliceno; off_t size = lseek(fd, 0L, SEEK_END); sf->total_blocks += size / BLCKSZ; + // 閲婃斁涓存椂鏂囦欢鍚嶅唴瀛 pfree(filename); + // 鏇存柊鍒嗙墖鍙峰拰鏂囦欢鏁 sliceno++; sf->file_num++; } @@ -404,33 +466,41 @@ void df_open_files(SegLogicFile *sf) /* * Extend logic file once. Each time we extend at most DF_FILE_SLICE_SIZE. */ +/* + * 鍔熻兘锛氬湪閫昏緫鏂囦欢鐨勬湯灏炬墿灞曟枃浠跺ぇ灏 + * + * 鍙傛暟鍒楄〃锛 + * sf锛歋egLogicFile*锛屽垎娈甸昏緫鏂囦欢缁撴瀯鎸囬拡 + */ void df_extend_internal(SegLogicFile *sf) { - int fd = sf->segfiles[sf->file_num - 1].fd; + int fd = sf->segfiles[sf->file_num - 1].fd; // 鑾峰彇鏈鍚庝竴涓枃浠剁殑鏂囦欢鎻忚堪绗 - off_t last_file_size = lseek(fd, 0L, SEEK_END); - SegmentCheck(last_file_size <= DF_FILE_SLICE_SIZE); + off_t last_file_size = lseek(fd, 0L, SEEK_END); // 鑾峰彇鏈鍚庝竴涓枃浠剁殑褰撳墠澶у皬 + SegmentCheck(last_file_size <= DF_FILE_SLICE_SIZE); // 妫鏌ユ槸鍚﹁秴鍑哄垎鐗囧ぇ灏 - if (last_file_size == DF_FILE_SLICE_SIZE) { - int new_sliceno = sf->file_num; - char *filename = slice_filename(sf->filename, new_sliceno); + if (last_file_size == DF_FILE_SLICE_SIZE) { // 濡傛灉鏈鍚庝竴涓枃浠跺凡婊 + int new_sliceno = sf->file_num; // 鏂板垎鐗囧彿 + char *filename = slice_filename(sf->filename, new_sliceno); // 鏋勫缓鏂版枃浠跺悕 + // 濡傛灉鏂板垎鐗囧彿瓒呭嚭鍚戦噺瀹归噺锛屾墿灞曞悜閲 if (new_sliceno >= sf->vector_capacity) { df_extend_file_vector(sf); } + // 鍒涘缓鏂版枃浠 int new_fd = dv_open_file(filename, O_RDWR | O_CREAT, SEGMENT_FILE_MODE); if (new_fd < 0) { ereport(ERROR, (errcode_for_file_access(), errmsg("[segpage] could not create file \"%s\": %m", filename))); } + // 鎵╁睍鏂版枃浠跺ぇ灏 if (ftruncate(new_fd, DF_FILE_EXTEND_STEP_SIZE) != 0) { dv_close_file(new_fd); - ereport(ERROR, - (errmodule(MOD_SEGMENT_PAGE), - errcode_for_file_access(), - errmsg("ftuncate file %s failed during df_extend due to %s", filename, strerror(errno)), - errdetail("file path: %s", sf->filename))); + ereport(ERROR, (errmodule(MOD_SEGMENT_PAGE), errcode_for_file_access(), + errmsg("ftuncate file %s failed during df_extend due to %s", filename, strerror(errno)), + errdetail("file path: %s", sf->filename))); } + // 鏇存柊鍒嗙墖淇℃伅 sf->segfiles[new_sliceno] = {.fd = new_fd, .sliceno = new_sliceno}; sf->file_num++; sf->total_blocks += DF_FILE_EXTEND_STEP_BLOCKS; @@ -445,11 +515,13 @@ void df_extend_internal(SegLogicFile *sf) SegmentCheck(new_size <= DF_FILE_SLICE_SIZE); + // 鎵╁睍鏈鍚庝竴涓枃浠跺ぇ灏 if (ftruncate(fd, new_size) != 0) { char *filename = slice_filename(sf->filename, sf->file_num - 1); ereport(ERROR, (errmsg("ftuncate file %s failed during df_extend due to %s", filename, strerror(errno)))); } + // 鏇存柊鎬诲潡鏁 sf->total_blocks += (new_size - last_file_size) / BLCKSZ; } } @@ -457,22 +529,29 @@ void df_extend_internal(SegLogicFile *sf) /* * Extend a logic file to target blocks. */ +/* + * 鍔熻兘锛氭牴鎹洰鏍囧潡鏁版墿灞曢昏緫鏂囦欢 + * + * 鍙傛暟鍒楄〃锛 + * sf锛歋egLogicFile*锛屽垎娈甸昏緫鏂囦欢缁撴瀯鎸囬拡 + * target_blocks锛欱lockNumber锛岀洰鏍囧潡鏁 + */ void df_extend(SegLogicFile *sf, BlockNumber target_blocks) { - if (target_blocks == InvalidBlockNumber) { + if (target_blocks == InvalidBlockNumber) { // 妫鏌ョ洰鏍囧潡鏁版槸鍚﹀悎娉 SegmentCheck(0); - ereport(ERROR, - (errcode(ERRCODE_DATA_EXCEPTION), errmsg("df_extend target_blocks is InvalidBlockNumber!\n"))); + ereport(ERROR, (errcode(ERRCODE_DATA_EXCEPTION), errmsg("df_extend target_blocks is InvalidBlockNumber!\n"))); } /* align target blocks to DF_FILE_EXTEND_STEP_BLOCKS */ target_blocks = CM_ALIGN_ANY(target_blocks, DF_FILE_EXTEND_STEP_BLOCKS); - AutoMutexLock lock(&sf->filelock); + AutoMutexLock lock(&sf->filelock); // 鑾峰彇閫昏緫鏂囦欢鐨勯攣 lock.lock(); if (sf->total_blocks < target_blocks) { if (!RecoveryInProgress()) { + // 妫鏌ユ槸鍚﹁秴杩囨渶澶уぇ灏 uint64 requestSize = 1LLU * BLCKSZ * (target_blocks - sf->total_blocks); TableSpaceUsageManager::IsExceedMaxsize(sf->relNode.spcNode, requestSize, true); } @@ -483,20 +562,26 @@ void df_extend(SegLogicFile *sf, BlockNumber target_blocks) SegmentCheck(sf->file_num > 0); while (sf->total_blocks < target_blocks) { - df_extend_internal(sf); + df_extend_internal(sf); // 寰幆鎵╁睍閫昏緫鏂囦欢澶у皬 } ereport(LOG, (errmsg("extend data file %s to %u blocks", sf->filename, target_blocks))); } - +/* + * 鍔熻兘锛氱缉灏忛昏緫鏂囦欢澶у皬鑷崇洰鏍囧潡鏁 + * + * 鍙傛暟鍒楄〃锛 + * sf锛歋egLogicFile*锛屽垎娈甸昏緫鏂囦欢缁撴瀯鎸囬拡 + * target锛欱lockNumber锛岀洰鏍囧潡鏁 + */ void df_shrink(SegLogicFile *sf, BlockNumber target) { - AutoMutexLock lock(&sf->filelock); + AutoMutexLock lock(&sf->filelock); // 鑾峰彇閫昏緫鏂囦欢鐨勯攣 lock.lock(); ssize_t last_file_size; ssize_t last_file_blocks; BlockNumber shrink_blocks; - SegmentCheck(target % DF_FILE_EXTEND_STEP_BLOCKS == 0); + SegmentCheck(target % DF_FILE_EXTEND_STEP_BLOCKS == 0); // 妫鏌ョ洰鏍囧潡鏁版槸鍚︽寜瑙勫垯瀵归綈 if (sf->total_blocks < target) { return; } @@ -527,8 +612,8 @@ void df_shrink(SegLogicFile *sf, BlockNumber target) if (sf->segfiles[i].fd < 0) { ereport(PANIC, (errmsg("Unlink file %s failed and unable to read it again.", filename))); } else { - ereport( - ERROR, (errmsg("unlink file %s failed during df_shrink due to %s", filename, strerror(errno)))); + ereport(ERROR, + (errmsg("unlink file %s failed during df_shrink due to %s", filename, strerror(errno)))); } } sf->file_num--; @@ -565,63 +650,83 @@ void df_pread_block(SegLogicFile *sf, char *buffer, BlockNumber blocknum) int nbytes = pread(spf.fd, buffer, BLCKSZ, roffset); pgstat_report_waitevent(WAIT_EVENT_END); if (nbytes != BLCKSZ) { - ereport(ERROR, - (errcode(MOD_SEGMENT_PAGE), - errcode_for_file_access(), - errmsg("could not read segment block %d in file %s", blocknum, sf->filename), - errdetail("errno: %d", errno))); + ereport(ERROR, (errcode(MOD_SEGMENT_PAGE), errcode_for_file_access(), + errmsg("could not read segment block %d in file %s", blocknum, sf->filename), + errdetail("errno: %d", errno))); } } - +/* + * 鍔熻兘锛氬悜鍒嗘閫昏緫鏂囦欢涓殑鎸囧畾鍧楀啓鍏ユ暟鎹 + * + * 鍙傛暟鍒楄〃锛 + * sf锛歋egLogicFile*锛屽垎娈甸昏緫鏂囦欢缁撴瀯鎸囬拡 + * buffer锛歝onst char*锛岃鍐欏叆鐨勬暟鎹紦鍐插尯鎸囬拡 + * blocknum锛欱lockNumber锛岃鍐欏叆鐨勫潡鍙 + */ void df_pwrite_block(SegLogicFile *sf, const char *buffer, BlockNumber blocknum) { - off_t offset = ((off_t)blocknum) * BLCKSZ; - int sliceno = DF_OFFSET_TO_SLICENO(offset); - off_t roffset = DF_OFFSET_TO_SLICE_OFFSET(offset); + off_t offset = ((off_t)blocknum) * BLCKSZ; // 璁$畻鍧楀彿瀵瑰簲鐨勫亸绉婚噺 + int sliceno = DF_OFFSET_TO_SLICENO(offset); // 璁$畻鍋忕Щ閲忓搴旂殑鍒囩墖鍙 + off_t roffset = DF_OFFSET_TO_SLICE_OFFSET(offset); // 璁$畻鍋忕Щ閲忓搴旂殑鍒囩墖鍐呭亸绉婚噺 - pgstat_report_waitevent(WAIT_EVENT_DATA_FILE_WRITE); + pgstat_report_waitevent(WAIT_EVENT_DATA_FILE_WRITE); // 鎶ュ憡绛夊緟浜嬩欢锛岃〃绀烘鍦ㄨ繘琛屾暟鎹枃浠跺啓鍏ユ搷浣 + + // 鑾峰彇鐗╃悊鏂囦欢鍙ユ焺 SegPhysicalFile spf = df_get_physical_file(sf, sliceno, blocknum); - int nbytes = pwrite(spf.fd, buffer, BLCKSZ, roffset); - pgstat_report_waitevent(WAIT_EVENT_END); + int nbytes = pwrite(spf.fd, buffer, BLCKSZ, roffset); // 鎵ц鍐欏叆鎿嶄綔 + pgstat_report_waitevent(WAIT_EVENT_END); // 缁撴潫绛夊緟浜嬩欢鐨勬姤鍛 + // 妫鏌ュ啓鍏ョ殑瀛楄妭鏁版槸鍚︿笌鏈熸湜鐨勫潡澶у皬鐩哥瓑锛屽鏋滀笉鐩哥瓑锛屽垯鎶涘嚭閿欒 if (nbytes != BLCKSZ) { - ereport(ERROR, - (errcode(MOD_SEGMENT_PAGE), - errcode_for_file_access(), - errmsg("could not write segment block %d in file %s, ", blocknum, sf->filename), - errdetail("errno: %d", errno))); + ereport(ERROR, (errcode(MOD_SEGMENT_PAGE), errcode_for_file_access(), + errmsg("could not write segment block %d in file %s, ", blocknum, sf->filename), + errdetail("errno: %d", errno))); } - seg_register_dirty_file(sf, sliceno); + seg_register_dirty_file(sf, sliceno); // 鏍囪鏂囦欢涓鸿剰鏂囦欢锛岄渶瑕佸埛鏂板埌纾佺洏 } - +/* + * 鍔熻兘锛氬垵濮嬪寲鍒嗘閫昏緫鏂囦欢鎺у埗缁撴瀯 + * + * 鍙傛暟鍒楄〃锛 + * sf锛歋egLogicFile*锛屽垎娈甸昏緫鏂囦欢缁撴瀯鎸囬拡 + * relNode锛歊elFileNode锛屽叧绯绘枃浠惰妭鐐规爣璇 + * forknum锛欶orkNumber锛屽垎鍙夊彿 + */ void df_ctrl_init(SegLogicFile *sf, RelFileNode relNode, ForkNumber forknum) { - sf->file_num = 0; - sf->segfiles = NULL; - sf->vector_capacity = 0; - sf->total_blocks = 0; + sf->file_num = 0; // 鍒濆鍖栨枃浠舵暟閲忎负0 + sf->segfiles = NULL; // 鍒濆鍖栧垎娈垫枃浠剁粨鏋勬暟缁勪负绌 + sf->vector_capacity = 0; // 鍒濆鍖栧閲忎负0 + sf->total_blocks = 0; // 鍒濆鍖栨诲潡鏁颁负0 - sf->relNode = relNode; - sf->forknum = forknum; + sf->relNode = relNode; // 璁剧疆鍏崇郴鏂囦欢鑺傜偣鏍囪瘑 + sf->forknum = forknum; // 璁剧疆鍒嗗弶鍙 - char *filename = relpathperm(relNode, forknum); - errno_t er = strcpy_s(sf->filename, MAXPGPATH, filename); - securec_check(er, "\0", "\0"); - pfree(filename); + char *filename = relpathperm(relNode, forknum); // 鑾峰彇鏂囦欢璺緞 + errno_t er = strcpy_s(sf->filename, MAXPGPATH, filename); // 澶嶅埗鏂囦欢璺緞鍒扮粨鏋勪腑 + securec_check(er, "\0", "\0"); // 妫鏌ュ瓧绗︿覆澶嶅埗鎿嶄綔鐨勯敊璇 + pfree(filename); // 閲婃斁鏂囦欢璺緞鍐呭瓨 - pthread_mutex_init(&sf->filelock, NULL); + pthread_mutex_init(&sf->filelock, NULL); // 鍒濆鍖栨枃浠堕攣 } - +/* + * 鍔熻兘锛氬悓姝ュ垎娈甸昏緫鏂囦欢鍒扮鐩 + * + * 鍙傛暟鍒楄〃锛 + * sf锛歋egLogicFile*锛屽垎娈甸昏緫鏂囦欢缁撴瀯鎸囬拡 + */ void df_fsync(SegLogicFile *sf) { - AutoMutexLock filelock(&sf->filelock); - filelock.lock(); + AutoMutexLock filelock(&sf->filelock); // 鍒涘缓鏂囦欢閿佸璞″苟鑷姩鍔犻攣 + filelock.lock(); // 鍔犻攣浠ヤ繚璇佺嫭鍗犳枃浠舵搷浣 for (int i = 0; i < sf->file_num; i++) { if (pg_fsync(sf->segfiles[i].fd)) { - ereport(data_sync_elevel(ERROR), (errcode_for_file_access(), errmodule(MOD_SEGMENT_PAGE), - errmsg("recover failed could not fsync segment data file"), - errdetail( "filename \"%s\", slot id %d, error message: %m", sf->filename, i))); + ereport(data_sync_elevel(ERROR), // 鎶ュ憡閿欒绾у埆 + (errcode_for_file_access(), // 璁剧疆鏂囦欢璁块棶閿欒鐮 + errmodule(MOD_SEGMENT_PAGE), // 璁剧疆妯″潡鏍囪瘑 + errmsg("recover failed could not fsync segment data file"), // 閿欒娑堟伅 + errdetail("filename \"%s\", slot id %d, error message: %m", sf->filename, i))); // 璇︾粏閿欒淇℃伅 } } } @@ -638,12 +743,12 @@ void df_unlink(SegLogicFile *sf) filelock.lock(); /* - * We first record "drop tablespace" xlog, then do the unlink. When the recovery thread + * We first record "drop tablespace" xlog, then do the unlink. When the recovery thread * replay the drop tablespace xlog, it will reopen the space, i.e., finding all data files - * from 0 to n. Thus, we should unlink files from back to front in case of failure happens + * from 0 to n. Thus, we should unlink files from back to front in case of failure happens * on half, so that the recovery thread can still unlink all files. */ - for (int i = sf->file_num-1; i >= 0; i--) { + for (int i = sf->file_num - 1; i >= 0; i--) { dv_close_file(sf->segfiles[i].fd); sf->segfiles[i].fd = -1; @@ -672,87 +777,109 @@ void forget_space_fsync_request(SegSpace *spc) } } } - +/* + * 鍔熻兘锛氬悜鍚屾绠$悊鍣ㄦ敞鍐屽繕璁拌姹傦紝鐢ㄤ簬澶勭悊鍒嗘閫昏緫鏂囦欢鐨勫洖鏀 + * + * 鍙傛暟鍒楄〃锛 + * sf锛歋egLogicFile*锛屽垎娈甸昏緫鏂囦欢缁撴瀯鎸囬拡 + * segno锛歩nt锛屽垎娈电紪鍙 + */ void seg_register_forget_request(SegLogicFile *sf, int segno) { - FileTag ftag; - errno_t er = memset_s(&ftag, sizeof(FileTag), 0, sizeof(FileTag)); - securec_check(er, "", ""); + FileTag ftag; // 鍒涘缓鏂囦欢鏍囩缁撴瀯 + errno_t er = memset_s(&ftag, sizeof(FileTag), 0, sizeof(FileTag)); // 鍒濆鍖栨枃浠舵爣绛剧粨鏋 + securec_check(er, "", ""); // 妫鏌emset_s鐨勮繑鍥炲硷紝纭繚瀹夊叏 - ftag.rnode = sf->relNode; - ftag.forknum = sf->forknum; - ftag.handler = SYNC_HANDLER_SEGMENT; - ftag.segno = segno; + ftag.rnode = sf->relNode; // 璁剧疆鏂囦欢鏍囩鐨勫叧鑱旀枃浠惰妭鐐 + ftag.forknum = sf->forknum; // 璁剧疆鏂囦欢鏍囩鐨勫垎鏀彿 + ftag.handler = SYNC_HANDLER_SEGMENT; // 璁剧疆鏂囦欢鏍囩鐨勫鐞嗙▼搴忎负鍒嗘澶勭悊绋嬪簭 + ftag.segno = segno; // 璁剧疆鏂囦欢鏍囩鐨勫垎娈电紪鍙 RegisterSyncRequest(&ftag, SYNC_FORGET_REQUEST, true /* retryOnError */); } - +/* + * 鍔熻兘锛氬悜鍚屾绠$悊鍣ㄦ敞鍐岃剰鏂囦欢璇锋眰锛岀敤浜庡鐞嗗垎娈甸昏緫鏂囦欢鐨勮剰鏁版嵁 + * + * 鍙傛暟鍒楄〃锛 + * sf锛歋egLogicFile*锛屽垎娈甸昏緫鏂囦欢缁撴瀯鎸囬拡 + * segno锛歩nt锛屽垎娈电紪鍙 + */ void seg_register_dirty_file(SegLogicFile *sf, int segno) { - FileTag ftag; - errno_t er = memset_s(&ftag, sizeof(FileTag), 0, sizeof(FileTag)); - securec_check(er, "", ""); + FileTag ftag; // 鍒涘缓鏂囦欢鏍囩缁撴瀯 + errno_t er = memset_s(&ftag, sizeof(FileTag), 0, sizeof(FileTag)); // 鍒濆鍖栨枃浠舵爣绛剧粨鏋 + securec_check(er, "", ""); // 妫鏌emset_s鐨勮繑鍥炲硷紝纭繚瀹夊叏 /* Initialize ftag */ - ftag.rnode = sf->relNode; - ftag.forknum = sf->forknum; - ftag.rnode.bucketNode = SegmentBktId; - ftag.handler = SYNC_HANDLER_SEGMENT; - ftag.segno = segno; + ftag.rnode = sf->relNode; // 璁剧疆鏂囦欢鏍囩鐨勫叧鑱旀枃浠惰妭鐐 + ftag.forknum = sf->forknum; // 璁剧疆鏂囦欢鏍囩鐨勫垎鏀彿 + ftag.rnode.bucketNode = SegmentBktId; // 璁剧疆鏂囦欢鏍囩鐨凚ucket鑺傜偣 + ftag.handler = SYNC_HANDLER_SEGMENT; // 璁剧疆鏂囦欢鏍囩鐨勫鐞嗙▼搴忎负鍒嗘澶勭悊绋嬪簭 + ftag.segno = segno; // 璁剧疆鏂囦欢鏍囩鐨勫垎娈电紪鍙 - if (!RegisterSyncRequest(&ftag, SYNC_REQUEST, false)) { - ereport(DEBUG5, - (errmodule(MOD_SEGMENT_PAGE), errmsg("could not forward fsync request because request queue is full"))); + if (!RegisterSyncRequest(&ftag, SYNC_REQUEST, + false)) { // 鍚戝悓姝ョ鐞嗗櫒娉ㄥ唽鑴忔枃浠惰姹傦紝鐢ㄤ簬澶勭悊鍒嗘閫昏緫鏂囦欢鐨勮剰鏁版嵁锛岃缃噸璇曢夐」涓篺alse + ereport(DEBUG5, (errmodule(MOD_SEGMENT_PAGE), errmsg("could not forward fsync request because request queue is " + "full"))); // 濡傛灉娉ㄥ唽璇锋眰澶辫触锛岃緭鍑篋EBUG5绾у埆鐨勬棩蹇椾俊鎭 - if (pg_fsync(sf->segfiles[segno].fd) < 0) { - char *filename = slice_filename(sf->filename, segno); + if (pg_fsync(sf->segfiles[segno].fd) < 0) { // 鍚﹀垯锛岄氳繃pg_fsync鍑芥暟灏濊瘯鍚屾鏂囦欢鏁版嵁 + char *filename = slice_filename(sf->filename, segno); // 鑾峰彇鍒嗘閫昏緫鏂囦欢鐨勬枃浠跺悕 ereport(data_sync_elevel(ERROR), - (errcode_for_file_access(), errmsg("could not fsync file \"%s\": %m", filename))); - pfree(filename); + (errcode_for_file_access(), + errmsg("could not fsync file \"%s\": %m", filename))); // 杈撳嚭鍚屾鏂囦欢鏁版嵁澶辫触鐨勯敊璇棩蹇椾俊鎭 + pfree(filename); // 閲婃斁鍒嗛厤鐨勫唴瀛樼┖闂 } } } - +/* + * 鍔熻兘锛氶氳繃鏂囦欢鏍囩鍚屾鍒嗘鏂囦欢 + * + * 鍙傛暟鍒楄〃锛 + * ftag锛歝onst FileTag*锛屾枃浠舵爣绛炬寚閽堬紝鐢ㄤ簬鏍囪瘑瑕佸悓姝ョ殑鏂囦欢 + * path锛歝har*锛岀敤浜庡瓨鍌ㄦ枃浠惰矾寰勭殑瀛楃鏁扮粍 + * + */ int seg_sync_filetag(const FileTag *ftag, char *path) { /* Open tablespace */ SegSpace *spc = spc_open(ftag->rnode.spcNode, ftag->rnode.dbNode, false); - if (spc == NULL) { + if (spc == NULL) { // 濡傛灉琛ㄧ┖闂翠负绌 ereport(LOG, (errmodule(MOD_SEGMENT_PAGE), errmsg("[segpage] seg_sync_filetag %s, ftag->segno is %u, but space is empty", relpathperm(ftag->rnode, ftag->forknum), ftag->segno))); - errno = ENOENT; - return -1; + errno = ENOENT; // 璁剧疆閿欒鐮佷负ENOENT + return -1; // 杩斿洖-1琛ㄧず鍚屾澶辫触 } - int extent_size = EXTENT_TYPE_TO_SIZE(ftag->rnode.relNode); - int egid = EXTENT_SIZE_TO_GROUPID(extent_size); + int extent_size = EXTENT_TYPE_TO_SIZE(ftag->rnode.relNode); // 鑾峰彇鏂囦欢鐨勫ぇ灏 + int egid = EXTENT_SIZE_TO_GROUPID(extent_size); // 鑾峰彇鏂囦欢鐨勭粍ID - SegLogicFile *lf = spc->extent_group[egid][ftag->forknum].segfile; - strlcpy(path, lf->filename, MAXPGPATH); + SegLogicFile *lf = spc->extent_group[egid][ftag->forknum].segfile; // 鑾峰彇鏂囦欢鐨勫ぇ灏 + int egid = EXTENT_SIZE_TO_GROUPID(extent_size); // 鑾峰彇鏂囦欢鐨勭粍ID - AutoMutexLock lock(&lf->filelock); - lock.lock(); + AutoMutexLock lock(&lf->filelock); // 鍒涘缓鑷姩浜掓枼閿 + lock.lock(); // 閿佸畾浜掓枼閿 - if (ftag->segno >= (uint32)lf->file_num) { + if (ftag->segno >= (uint32)lf->file_num) { // 濡傛灉瑕佸悓姝ョ殑鍒嗘缂栧彿澶т簬绛変簬宸叉湁鐨勬枃浠舵暟 /* File may be deleted by spc_shrink or space delete */ - ereport(LOG, + ereport( + LOG, (errmodule(MOD_SEGMENT_PAGE), - errmsg("[segpage] seg_sync_filetag %s, ftag->segno is %u, but existing file number is %u, the file may " - "be deleted by spc_shrink or drop tablespace", - path, ftag->segno, lf->file_num))); - errno = ENOENT; - return -1; + errmsg("[segpage] seg_sync_filetag %s, ftag->segno is %u, but existing file number is %u, the file may " + "be deleted by spc_shrink or drop tablespace", + path, ftag->segno, lf->file_num))); // 杈撳嚭閿欒鏃ュ織淇℃伅 + errno = ENOENT; // 璁剧疆閿欒鐮佷负ENOENT + return -1; // 杩斿洖-1琛ㄧず鍚屾澶辫触 } /* can not sync the file not exist */ - SegPhysicalFile *sf = &lf->segfiles[ftag->segno]; + SegPhysicalFile *sf = &lf->segfiles[ftag->segno]; // 鑾峰彇鍒嗘鏂囦欢缁撴瀯鎸囬拡 - SegmentCheck((uint32)sf->sliceno == ftag->segno); - int ret = pg_fsync(sf->fd); + SegmentCheck((uint32)sf->sliceno == ftag->segno); // 妫鏌ュ垎娈垫枃浠剁殑鍒嗘缂栧彿鏄惁鍖归厤 + int ret = pg_fsync(sf->fd); // 璋冪敤pg_fsync鍑芥暟杩涜鏂囦欢鍚屾鎿嶄綔 - ereport(DEBUG1, (errmsg("segment fsync %s", path))); + ereport(DEBUG1, (errmsg("segment fsync %s", path))); // 杈撳嚭DEBUG1绾у埆鐨勬棩蹇椾俊鎭 - return ret; + return ret; // 杩斿洖鍚屾鎿嶄綔鐨勭粨鏋 } int seg_unlink_filetag(const FileTag *ftag, char *path) @@ -760,20 +887,30 @@ int seg_unlink_filetag(const FileTag *ftag, char *path) SegmentCheck(0); return 0; } - +/* + * 鍔熻兘锛氬繕璁版寚瀹氭暟鎹簱鐨勬枃浠跺悓姝ヨ姹 + * + * 鍙傛暟鍒楄〃锛 + * dbid锛歄id锛岃蹇樿鍚屾璇锋眰鐨勬暟鎹簱鏍囪瘑 + */ void segForgetDatabaseFsyncRequests(Oid dbid) { - FileTag tag; - RelFileNode rnode = {.spcNode = 0, .dbNode = dbid, .relNode = 0, .bucketNode = InvalidBktId, .opt = 0}; + FileTag tag; // 鍒涘缓鏂囦欢鏍囩缁撴瀯浣 + RelFileNode rnode = { + .spcNode = 0, .dbNode = dbid, .relNode = 0, .bucketNode = InvalidBktId, .opt = 0}; // 鍒涘缓鏂囦欢鑺傜偣缁撴瀯浣 - tag.rnode = rnode; - tag.handler = SYNC_HANDLER_SEGMENT; - tag.forknum = InvalidForkNumber; - tag.segno = InvalidBlockNumber; + tag.rnode = rnode; // 璁剧疆鏂囦欢鏍囩鐨勮妭鐐逛俊鎭负鎸囧畾鏁版嵁搴 + tag.handler = SYNC_HANDLER_SEGMENT; // 璁剧疆鏂囦欢鏍囩鐨勫鐞嗙▼搴忎负SEGMENT + tag.forknum = InvalidForkNumber; // 璁剧疆鏂囦欢鏍囩鐨勫垎鏀彿涓烘棤鏁堝垎鏀彿 + tag.segno = InvalidBlockNumber; // 璁剧疆鏂囦欢鏍囩鐨勫垎娈靛彿涓烘棤鏁堝垎娈靛彿 RegisterSyncRequest(&tag, SYNC_FILTER_REQUEST, true /*retry on error */); } - +/* 鍔熻兘锛氳繘琛屾瘮杈冿紝浠ョ‘瀹氭枃浠舵爣绛炬槸鍚︽弧瓒崇壒瀹氱殑鏉′欢銆 + * 鍙傛暟鍒楄〃锛 + * ftag锛氫竴涓寚鍚 FileTag 缁撴瀯鐨勬寚閽堬紝琛ㄧず瑕佹瘮杈冪殑鐩爣 FileTag銆 + * candidate锛氫竴涓寚鍚 FileTag 缁撴瀯鐨勬寚閽堬紝琛ㄧず瑕佷笌鐩爣 ftag 杩涜姣旇緝鐨 FileTag銆 + */ bool seg_filetag_matches(const FileTag *ftag, const FileTag *candidate) { return ftag->rnode.dbNode == candidate->rnode.dbNode; diff --git a/src/gausskernel/storage/smgr/segment/extent_group.cpp b/src/gausskernel/storage/smgr/segment/extent_group.cpp index d674ff8ff..a7817ab3a 100644 --- a/src/gausskernel/storage/smgr/segment/extent_group.cpp +++ b/src/gausskernel/storage/smgr/segment/extent_group.cpp @@ -92,44 +92,76 @@ void eg_init_df_ctrl(SegExtentGroup *seg) seg->segfile = sf; } - +/* + * 鍔熻兘锛氳幏鍙 SegExtentGroup 涓叧鑱旂殑 SegLogicFile 鐨勬诲潡鏁 + * + * 鍙傛暟鍒楄〃锛 + * seg锛歋egExtentGroup 鎸囬拡锛岃〃绀轰竴涓鎵╁睍缁 + * + */ BlockNumber eg_df_size(SegExtentGroup *seg) { + // 浣跨敤 AutoMutexLock 鏉ュ seg->lock 杩涜鑷姩鍔犻攣锛岀‘淇濈嚎绋嬪畨鍏 AutoMutexLock lock(&seg->lock); lock.lock(); + // 鑾峰彇 seg->segfile锛屽嵆鍏宠仈鐨 SegLogicFile 缁撴瀯 SegLogicFile *sf = seg->segfile; SegmentCheck(sf != NULL); + // 杩斿洖 SegLogicFile 缁撴瀯鐨 total_blocks 鎴愬憳锛岃〃绀烘诲潡鏁 return sf->total_blocks; } - +/* + * 鍔熻兘锛氭鏌 SegExtentGroup 涓槸鍚﹀瓨鍦ㄥ叧鑱旂殑 SegLogicFile + * + * 鍙傛暟鍒楄〃锛 + * seg锛歋egExtentGroup 鎸囬拡锛岃〃绀轰竴涓鎵╁睍缁 + * + * 杩斿洖鍊硷細bool锛屽鏋滃瓨鍦ㄥ叧鑱旂殑 SegLogicFile锛岃繑鍥 true锛涘惁鍒欒繑鍥 false銆 + */ bool eg_df_exists(SegExtentGroup *seg) { + // 浣跨敤 AutoMutexLock 鏉ュ seg->lock 杩涜鑷姩鍔犻攣锛岀‘淇濈嚎绋嬪畨鍏 AutoMutexLock lock(&seg->lock); lock.lock(); SegLogicFile *sf = seg->segfile; SegmentCheck(sf != NULL); + // 杩斿洖鍒ゆ柇鍏宠仈鐨 SegLogicFile 鏄惁瀛樺湪鐨勭粨鏋 return (sf->file_num > 0); } - +/* + * 鍔熻兘锛氬垱寤 SegExtentGroup 鍏宠仈鐨 SegLogicFile锛屽鏋滃皻鏈垱寤 + * + * 鍙傛暟鍒楄〃锛 + * seg锛歋egExtentGroup 鎸囬拡锛岃〃绀轰竴涓鎵╁睍缁 + */ void eg_create_df(SegExtentGroup *seg) { + // 浣跨敤 AutoMutexLock 鏉ュ seg->lock 杩涜鑷姩鍔犻攣锛岀‘淇濈嚎绋嬪畨鍏 AutoMutexLock lock(&seg->lock); lock.lock(); SegLogicFile *sf = seg->segfile; SegmentCheck(sf != NULL); + // 濡傛灉 sf 涓殑鏂囦欢鏁扮洰涓 0锛岃鏄庡皻鏈垱寤 SegLogicFile锛岄渶瑕佸垱寤 if (sf->file_num == 0) { df_create_file(sf, false); } } - +/* + * 鍔熻兘锛氭墿灞 SegExtentGroup 鍏宠仈鐨 SegLogicFile 鍒版寚瀹氱殑鏂囦欢澶у皬 + * + * 鍙傛暟鍒楄〃锛 + * seg锛歋egExtentGroup 鎸囬拡锛岃〃绀轰竴涓鎵╁睍缁 + * target_file_size锛欱lockNumber锛岀洰鏍囨枃浠跺ぇ灏忥紙鍧楁暟锛 + */ void eg_extend_df(SegExtentGroup *seg, BlockNumber target_file_size) { + // 浣跨敤 AutoMutexLock 鏉ュ seg->lock 杩涜鑷姩鍔犻攣锛岀‘淇濈嚎绋嬪畨鍏 AutoMutexLock lock(&seg->lock); lock.lock(); @@ -137,49 +169,86 @@ void eg_extend_df(SegExtentGroup *seg, BlockNumber target_file_size) SegLogicFile *sf = seg->segfile; SegmentCheck(sf != NULL); + // 璋冪敤 df_extend 鍑芥暟鏉ユ墿灞 SegLogicFile 鍒版寚瀹氱殑鏂囦欢澶у皬 df_extend(sf, target_file_size); } - +/* + * 鍔熻兘锛氬皢 SegExtentGroup 鍏宠仈鐨 SegLogicFile 缂╁皬鍒版寚瀹氱殑鐩爣澶у皬 + * + * 鍙傛暟鍒楄〃锛 + * seg锛歋egExtentGroup 鎸囬拡锛岃〃绀轰竴涓鎵╁睍缁 + * target锛欱lockNumber锛岀洰鏍囨枃浠跺ぇ灏忥紙鍧楁暟锛夛紝缂╁皬鍒拌繖涓ぇ灏 + */ void eg_shrink_df(SegExtentGroup *seg, BlockNumber target) { AutoMutexLock lock(&seg->lock); lock.lock(); - + SegLogicFile *sf = seg->segfile; SegmentCheck(sf != NULL); + // 璋冪敤 df_shrink 鍑芥暟鏉ュ皢 SegLogicFile 缂╁皬鍒版寚瀹氱殑鐩爣澶у皬 df_shrink(sf, target); } /* * Check current data file status; this function is usually called when the space is first accessed. */ +/* + * 鍔熻兘锛氳幏鍙 SegExtentGroup 鍏宠仈鐨 SegLogicFile 鐨勭姸鎬 + * + * 鍙傛暟鍒楄〃锛 + * seg锛歋egExtentGroup 鎸囬拡锛岃〃绀轰竴涓鎵╁睍缁 + * + */ SpaceDataFileStatus eg_status(SegExtentGroup *seg) { + // 璋冪敤 eg_df_exists 鍑芥暟妫鏌 SegLogicFile 鏄惁瀛樺湪 if (!eg_df_exists(seg)) { + // 璋冪敤 eg_df_exists 鍑芥暟妫鏌 SegLogicFile 鏄惁瀛樺湪 return SpaceDataFileStatus::EMPTY; } + // 璋冪敤 eg_df_valid 鍑芥暟妫鏌 SegLogicFile 鏄惁鏈夋晥 if (eg_df_valid(seg)) { + // 璋冪敤 eg_df_valid 鍑芥暟妫鏌 SegLogicFile 鏄惁鏈夋晥 return SpaceDataFileStatus::NORMAL; } + // 濡傛灉 SegLogicFile 鏃笉涓虹┖涔熶笉鏈夋晥锛岃繑鍥 CRASHED 鐘舵 return SpaceDataFileStatus::CRASHED; } /* Initialize information in SegExtentGroup structure */ +/* + * 鍔熻兘锛氱敤浜庡垵濮嬪寲 SegExtentGroup 缁撴瀯浣擄紝琛ㄧず涓缁勫叧鑱旂殑鏁版嵁鏂囦欢鐨勪俊鎭 + * + * 鍙傛暟鍒楄〃锛 + * spc锛歋egSpace 缁撴瀯浣擄紝琛ㄧず杩欑粍鏁版嵁鏂囦欢鎵灞炵殑 SegSpace銆 + * seg锛歋egExtentGroup 缁撴瀯浣擄紝瑕佽繘琛屽垵濮嬪寲鐨勭洰鏍囩粨鏋勪綋銆 + * extent_size锛歩nt锛屾瘡涓暟鎹枃浠剁殑澶у皬銆 + * forknum锛欶orkNumber锛屼笌鏁版嵁鏂囦欢鍏宠仈鐨 fork 绫诲瀷銆 + */ void eg_ctrl_init(SegSpace *spc, SegExtentGroup *seg, int extent_size, ForkNumber forknum) { + // 纭繚 seg 姝g‘鍏宠仈鍒 spc 鐨 extent_group 鏁扮粍涓殑浣嶇疆 SegmentCheck(&spc->extent_group[EXTENT_SIZE_TO_GROUPID(extent_size)][forknum] == seg); + // 璁剧疆 seg 鐨 extent_size 瀛楁锛岃〃绀烘瘡涓暟鎹枃浠剁殑澶у皬 seg->extent_size = extent_size; + // 璁剧疆 seg 鐨 space 瀛楁锛岃〃绀鸿繖缁勬暟鎹枃浠舵墍灞炵殑 SegSpace 缁撴瀯浣 seg->space = spc; + // 涓 seg 鐨 rnode 瀛楁鍒嗛厤涓涓 RelFileNode 缁撴瀯浣擄紝鐢ㄤ簬琛ㄧず鏂囦欢鑺傜偣鐨勭浉鍏充俊鎭 seg->rnode = {.spcNode = spc->spcNode, .dbNode = spc->dbNode, .relNode = EXTENT_SIZE_TO_TYPE(extent_size), .bucketNode = SegmentBktId, .opt = 0}; + // 璁剧疆 seg 鐨 forknum 瀛楁锛岃〃绀轰笌鏁版嵁鏂囦欢鍏宠仈鐨 fork 绫诲瀷 seg->forknum = forknum; + // 璁剧疆 seg 鐨 map_head_entry 瀛楁鐨勫垵濮嬪 seg->map_head_entry = DF_MAP_HEAD_PAGE; + // 鍒濆鍖 seg 鐨勪簰鏂ラ攣锛岀‘淇濆 seg 鐨勫苟鍙戣闂殑绾跨▼瀹夊叏鎬 pthread_mutex_init(&seg->lock, NULL); + // 鍙兘鏄竴涓垵濮嬪寲鏁版嵁鏂囦欢鎺у埗缁撴瀯鐨勫嚱鏁帮紝鐢ㄤ簬杩涗竴姝ュ垵濮嬪寲涓庤繖缁勬暟鎹枃浠跺叧鑱旂殑鎺у埗淇℃伅 eg_init_df_ctrl(seg); } @@ -190,36 +259,61 @@ void eg_init_datafile_head(SegExtentGroup *seg) * if necessary in the future. */ } - +/* + * 鍔熻兘锛氱敤浜庡垵濮嬪寲鏄犲皠澶撮〉鐨勫唴瀹癸紝杩欎釜鏄犲皠澶撮〉鍖呭惈浜嗕竴浜涘叧浜庢槧灏勭殑鍏冧俊鎭 + * + * 鍙傛暟鍒楄〃锛 + * map_head_page锛歅age锛屾槧灏勫ご椤电殑鎸囬拡銆 + * extent_size锛歩nt锛屾瘡涓暟鎹枃浠剁殑澶у皬銆 + */ void eg_init_map_head_page_content(Page map_head_page, int extent_size) { + // 浣跨敤 SegPageInit 鍑芥暟鍒濆鍖栨槧灏勫ご椤碉紝璁剧疆椤靛ぇ灏忎负 BLCKSZ SegPageInit(map_head_page, BLCKSZ); + // 鑾峰彇鏄犲皠澶撮〉鐨勫唴瀹规寚閽 char *content = PageGetContents(map_head_page); + // 灏嗗唴瀹硅В閲婁负 df_map_head_t 缁撴瀯浣擄紝杩欐槸鏄犲皠澶撮〉鐨勭粨鏋 df_map_head_t *map_head = (df_map_head_t *)content; - map_head->bit_unit = extent_size; - map_head->group_count = 0; - map_head->free_group = 0; - map_head->allocated_extents = 0; + // 璁剧疆鏄犲皠澶撮〉鐨勫瓧娈靛 + map_head->bit_unit = extent_size; // 姣忎釜浣嶅浘鍗曞厓鐨勫ぇ灏忥紝鍗虫暟鎹枃浠剁殑澶у皬 + map_head->group_count = 0; // 缁勭殑鏁伴噺锛屽垵濮嬩负 0 + map_head->free_group = 0; // 绌洪棽缁勭殑鏁伴噺锛屽垵濮嬩负 0 + map_head->allocated_extents = 0; // 宸插垎閰嶇殑鎵╁睍鏁伴噺锛屽垵濮嬩负 0 + // 鑾峰彇鏄犲皠澶撮〉鐨勯〉澶达紝骞跺皢 pd_lower 瀛楁澧炲姞 df_map_head_t 缁撴瀯浣撶殑澶у皬 PageHeader page_header = (PageHeader)map_head_page; page_header->pd_lower += sizeof(df_map_head_t); } - +/* + * 鍔熻兘锛氱敤浜庡垵濮嬪寲鏄犲皠澶达紝鍖呮嫭鍒涘缓鏄犲皠澶撮〉骞跺啓鍏ョ浉鍏充俊鎭 + * + * 鍙傛暟鍒楄〃锛 + * seg锛歋egExtentGroup*锛屾墿灞曠粍鐨勬寚閽堬紝鍖呭惈浜嗘槧灏勫ご鐨勭浉鍏充俊鎭 + * rec_ptr锛歑LogRecPtr锛岀敤浜庤缃槧灏勫ご椤电殑LSN銆 + */ static void eg_init_map_head(SegExtentGroup *seg, XLogRecPtr rec_ptr) { + // 璁剧疆鏄犲皠澶存墍鍦ㄧ殑椤靛彿 BlockNumber pageno = DF_MAP_HEAD_PAGE; + // 鍒嗛厤涓涓柊鐨勯〉骞跺垵濮嬪寲涓0 Page page = (Page)palloc(BLCKSZ); errno_t er = memset_s((void *)page, BLCKSZ, 0, BLCKSZ); securec_check(er, "", ""); + // 鍒濆鍖栨槧灏勫ご椤电殑鍐呭 eg_init_map_head_page_content(page, seg->extent_size); + // 璁剧疆鏄犲皠澶撮〉鐨凩SN PageSetLSN(page, rec_ptr); + // 璁$畻骞惰缃槧灏勫ご椤电殑鏍¢獙鍜 PageSetChecksumInplace(page, pageno); + // 灏嗘槧灏勫ご椤靛啓鍏ユ墿灞曠粍鐨勬暟鎹枃浠朵腑 df_pwrite_block(seg->segfile, (char *)page, pageno); + // 閲婃斁鍒嗛厤鐨勫唴瀛 pfree(page); + // 鏇存柊鎵╁睍缁勪腑鐨勬槧灏勫ご椤典俊鎭 seg->map_head_entry = pageno; seg->map_head = NULL; } @@ -228,16 +322,26 @@ void eg_clean_data_files(SegExtentGroup *seg) { df_unlink(seg->segfile); } - +/* + * 鍔熻兘锛氬垵濮嬪寲鎵╁睍缁勭殑鏁版嵁鏂囦欢 + * + * 鍙傛暟鍒楄〃锛 + * eg锛歋egExtentGroup*锛屾墿灞曠粍鐨勬寚閽堬紝鍖呭惈浜嗘暟鎹枃浠跺拰鏄犲皠澶寸殑鐩稿叧淇℃伅銆 + * redo锛歜ool锛岃〃绀烘槸鍚﹀浜庨噸鍋氶樁娈点 + * rec_ptr锛歑LogRecPtr锛岀敤浜庤缃槧灏勫ご椤电殑LSN銆 + */ void eg_init_data_files(SegExtentGroup *eg, bool redo, XLogRecPtr rec_ptr) { SEGMENTTEST(EXTENT_GROUP_INIT_DATA, (errmsg("EXTENT_GROUP_INIT_DATA %s: the first time for create segment tb!\n", - g_instance.attr.attr_common.PGXCNodeName))); + g_instance.attr.attr_common.PGXCNodeName))); /* create file will ensure the file has enough space */ df_create_file(eg->segfile, redo); - eg_init_datafile_head(eg); // initialize data file - eg_init_map_head(eg, rec_ptr); // initialize map head + // 鍒濆鍖栨暟鎹枃浠跺ご + eg_init_datafile_head(eg); // initialize data file + // 鍒濆鍖栨槧灏勫ご + eg_init_map_head(eg, rec_ptr); // initialize map head + // 鏂囦欢鍚屾 df_fsync(eg->segfile); } @@ -273,33 +377,56 @@ SpaceMapLocation eg_locate_map_by_pageid(SegExtentGroup *seg, BlockNumber page_i return result; } - +/* + * 鍔熻兘锛氱敤浜庤缃綅鍥鹃〉涓寚瀹氫綅缃殑浣嶏紝骞舵洿鏂颁綅鍥鹃〉鐨勭浉鍏充俊鎭 + * + * 鍙傛暟鍒楄〃锛 + * map_page锛歞f_map_page_t*锛屼綅鍥鹃〉鐨勬寚閽堛 + * bit_id锛歶int16锛岃璁剧疆鐨勪綅鐨勪綅缃 + */ void eg_set_bitmap_page(df_map_page_t *map_page, uint16 bit_id) { + // 妫鏌ヤ綅鍥鹃〉涓寚瀹氫綅缃殑浣嶆槸鍚﹀凡缁忚璁剧疆 SegmentCheck(DF_MAP_FREE(map_page->bitmap, bit_id)); + // 璁剧疆浣嶅浘椤典腑鎸囧畾浣嶇疆鐨勪綅 DF_MAP_SET(map_page->bitmap, bit_id); + // 鏇存柊浣嶅浘椤电殑绌洪棽浣嶆暟 map_page->free_bits--; + // 濡傛灉绌洪棽浣嶇殑璧峰浣嶇疆鏄寚瀹氫綅缃紝鏇存柊绌洪棽浣嶇殑璧峰浣嶇疆 if (map_page->free_begin == bit_id) { map_page->free_begin++; } + // 濡傛灉鑴忎綅鐨勪綅缃皬浜庢寚瀹氫綅缃紝鏇存柊鑴忎綅鐨勪綅缃 if (map_page->dirty_last < bit_id) { map_page->dirty_last = bit_id; } } - +/* + * 鍔熻兘锛氬垵濮嬪寲浣嶅浘椤电殑鍐呭 + * + * 鍙傛暟鍒楄〃锛 + * bitmap_page锛歅age锛屼綅鍥鹃〉鐨勬寚閽堛 + * first_page锛欱lockNumber锛岀涓涓暟鎹〉鐨勫潡鍙枫 + */ void eg_init_bitmap_page_content(Page bitmap_page, BlockNumber first_page) { + // 鍒濆鍖栦綅鍥鹃〉鐨勫唴瀹癸紝灏嗗叾鍏ㄩ儴璁剧疆涓0 SegPageInit(bitmap_page, BLCKSZ); + // 鑾峰彇浣嶅浘椤电殑鍐呭 df_map_page_t *df_map_page = (df_map_page_t *)PageGetContents(bitmap_page); + // 璁剧疆浣嶅浘椤电殑璧峰浣嶇疆銆佽剰浣嶄綅缃佺┖闂蹭綅鏁板拰绗竴涓暟鎹〉鐨勫潡鍙 df_map_page->free_begin = 0; df_map_page->dirty_last = 0; df_map_page->free_bits = DF_MAP_BIT_CNT; df_map_page->first_page = first_page; + // 鑾峰彇浣嶅浘椤电殑椤靛ご淇℃伅 PageHeader bitmap_page_header = (PageHeader)bitmap_page; + // 妫鏌ヤ綅鍥鹃〉鐨勯〉澶翠笂闄愭槸鍚︾瓑浜嶣LCKSZ SegmentCheck(bitmap_page_header->pd_upper = BLCKSZ); + // 璁剧疆浣嶅浘椤电殑椤靛ご涓嬮檺绛変簬椤靛ご涓婇檺锛屾爣璁颁綅鍥鹃〉宸茬粡琚垵濮嬪寲 bitmap_page_header->pd_lower = bitmap_page_header->pd_upper; } @@ -356,15 +483,28 @@ BlockNumber eg_alloc_extent_from_map_internal(SegExtentGroup *seg, Buffer map_bu return pagenum; } - +/* + * 鍔熻兘锛氫粠浣嶅浘涓垎閰嶄竴涓暟鎹墿灞曞潡 + * + * 鍙傛暟鍒楄〃锛 + * seg锛歋egExtentGroup*锛屽垎娈电┖闂寸粍鐨勬寚閽堛 + * map_page_id锛欱lockNumber锛屼綅鍥鹃〉鐨勫潡鍙枫 + * target_file_size锛欱lockNumber*锛岀敤浜庤繑鍥炵洰鏍囨枃浠剁殑澶у皬銆 + * map_group锛歶int32锛屼綅鍥剧粍鐨勬爣璇嗐 + * free_page锛歶int32锛岀┖闂查〉鐨勬爣璇嗐 + * + */ BlockNumber eg_alloc_extent_from_map(SegExtentGroup *seg, BlockNumber map_page_id, BlockNumber *target_file_size, - uint32 map_group, uint32 free_page) + uint32 map_group, uint32 free_page) { + // 璇诲彇浣嶅浘椤靛苟鍔犻攣锛屼互渚胯繘琛屾搷浣 Buffer map_buffer = ReadBufferFast(seg->space, seg->rnode, seg->forknum, map_page_id, RBM_NORMAL); LockBuffer(map_buffer, BUFFER_LOCK_EXCLUSIVE); + // 鑾峰彇浣嶅浘椤电殑鍐呭 df_map_page_t *map_page = (df_map_page_t *)PageGetContents(BufferGetPage(map_buffer)); + // 妫鏌ヤ綅鍥炬槸鍚﹀凡婊★紝濡傛灉宸叉弧鍒欓噴鏀剧紦鍐插尯骞惰繑鍥炴棤鏁堝潡鍙 if (map_page->free_bits == 0) { SegUnlockReleaseBuffer(map_buffer); return InvalidBlockNumber; @@ -379,6 +519,7 @@ BlockNumber eg_alloc_extent_from_map(SegExtentGroup *seg, BlockNumber map_page_i curr++; } + // 濡傛灉娌℃湁鍙敤浣嶏紝鍒欓噴鏀剧紦鍐插尯骞惰繑鍥炴棤鏁堝潡鍙 if (curr >= DF_MAP_BIT_CNT) { /* current map does not contain a free bit */ SegUnlockReleaseBuffer(map_buffer); @@ -388,11 +529,20 @@ BlockNumber eg_alloc_extent_from_map(SegExtentGroup *seg, BlockNumber map_page_i /* internal function will release and unlock the MapPage buffer */ return eg_alloc_extent_from_map_internal(seg, map_buffer, curr, target_file_size, map_group, free_page); } - +/* + * 鍔熻兘锛氫粠棰勫垎閰嶅潡涓垎閰嶄竴涓暟鎹墿灞曞潡 + * + * 鍙傛暟鍒楄〃锛 + * seg锛歋egExtentGroup*锛屽垎娈电┖闂寸粍鐨勬寚閽堛 + * preassigned_block锛欱lockNumber锛岄鍒嗛厤鐨勬暟鎹潡鍙枫 + * target_file_size锛欱lockNumber*锛岀敤浜庤繑鍥炵洰鏍囨枃浠剁殑澶у皬銆 + */ bool eg_alloc_preassigned_block(SegExtentGroup *seg, BlockNumber preassigned_block, BlockNumber *target_file_size) { + // 閫氳繃鏁版嵁鍧楀彿瀹氫綅浣嶅浘浣嶇疆 SpaceMapLocation location = eg_locate_map_by_pageid(seg, preassigned_block, seg->map_head); + // 妫鏌ヤ綅鍥句綅缃槸鍚︽湁鏁堬紝濡傛灉鏃犳晥鍒欒繑鍥瀎alse if (MapLocationIsInvalid(location)) { return false; } @@ -400,13 +550,16 @@ bool eg_alloc_preassigned_block(SegExtentGroup *seg, BlockNumber preassigned_blo BlockNumber map_blocknum = location.map_id + location.group.first_map; + // 璇诲彇浣嶅浘椤靛苟鍔犻攣锛屼互渚胯繘琛屾搷浣 Buffer map_buffer = ReadBufferFast(seg->space, seg->rnode, seg->forknum, map_blocknum, RBM_NORMAL); LockBuffer(map_buffer, BUFFER_LOCK_EXCLUSIVE); df_map_page_t *map_page = (df_map_page_t *)PageGetContents(BufferGetPage(map_buffer)); + // 妫鏌ヤ綅鍥句腑鐨勪綅鏄惁鍙敤锛屽鏋滃彲鐢ㄥ垯缁х画鍒嗛厤锛屽惁鍒欐姤閿 if (DF_MAP_FREE(map_page->bitmap, bit_id)) { BlockNumber pagenum = map_page->first_page + bit_id * seg->map_head->bit_unit; // check whether the allocated block exceeds the file size + // 妫鏌ュ垎閰嶇殑鍧楁槸鍚﹁秴杩囨枃浠跺ぇ灏 if ((pagenum + seg->extent_size) > seg->segfile->total_blocks) { *target_file_size = pagenum + seg->extent_size; SegUnlockReleaseBuffer(map_buffer); @@ -415,52 +568,83 @@ bool eg_alloc_preassigned_block(SegExtentGroup *seg, BlockNumber preassigned_blo } else { ereport(PANIC, (errmsg("The preassigned segment block %u is already in use", preassigned_block))); } + // 鑾峰彇褰撳墠浣嶅浘缁勫拰椤靛彿 uint32 free_group = seg->map_head->free_group; uint32 free_page = seg->map_head->groups[free_group].free_page; SegmentCheck(free_group < seg->map_head->group_count && free_page < seg->map_head->groups[free_group].page_count); + // 璋冪敤鍐呴儴鍑芥暟杩涜鍒嗛厤锛岃鍑芥暟浼氶噴鏀惧拰瑙i攣MapPage缂撳啿鍖 (void)eg_alloc_extent_from_map_internal(seg, map_buffer, bit_id, target_file_size, free_group, free_page); return true; } - +/* + * 鍔熻兘锛氬垵濮嬪寲浣嶅浘椤 + * + * 鍙傛暟鍒楄〃锛 + * seg锛歋egExtentGroup*锛屽垎娈电┖闂寸粍鐨勬寚閽堛 + * pageno锛欱lockNumber锛屼綅鍥鹃〉鍙枫 + * first_page锛欱lockNumber锛屼綅鍥惧搴旂殑鏁版嵁鏂囦欢涓殑璧峰椤靛彿銆 + */ void eg_init_bitmap_page(SegExtentGroup *seg, BlockNumber pageno, BlockNumber first_page) { + // 璇诲彇浣嶅浘椤靛苟鍔犻攣锛屼互渚胯繘琛屾搷浣 Buffer buffer = ReadBufferFast(seg->space, seg->rnode, seg->forknum, pageno, RBM_NORMAL); LockBuffer(buffer, BUFFER_LOCK_EXCLUSIVE); + // 寮濮嬩簨鍔 START_CRIT_SECTION(); + // 鏍囪缂撳啿鍖轰负鑴忛〉锛岃〃绀洪渶瑕佸啓鍥炵鐩 SegMarkBufferDirty(buffer); + // 璋冪敤鍑芥暟鍒濆鍖栦綅鍥鹃〉鐨勫唴瀹 eg_init_bitmap_page_content(BufferGetPage(buffer), first_page); /* XLog Issue */ + // 鎻掑叆XLog璁板綍 XLogBeginInsert(); XLogRegisterData((char *)&first_page, sizeof(BlockNumber)); XLogRegisterBuffer(0, buffer, REGBUF_WILL_INIT); XLogRecPtr rec_ptr = XLogInsert(RM_SEGPAGE_ID, XLOG_SEG_INIT_MAPPAGE, SegmentBktId); + // 璁剧疆椤礚SN PageSetLSN(BufferGetPage(buffer), rec_ptr); + // 璁剧疆椤礚SN END_CRIT_SECTION(); + // 瑙i攣骞堕噴鏀剧紦鍐插尯 SegUnlockReleaseBuffer(buffer); } - +/* + * 鍔熻兘锛氬垵濮嬪寲閫嗗悜鎸囬拡椤 + * + * 鍙傛暟鍒楄〃锛 + * seg锛歋egExtentGroup*锛屽垎娈电┖闂寸粍鐨勬寚閽堛 + * pageno锛欱lockNumber锛岄嗗悜鎸囬拡椤靛彿銆 + */ void eg_init_invrsptr_page(SegExtentGroup *seg, BlockNumber pageno) { + // 璇诲彇閫嗗悜鎸囬拡椤靛苟娓呴浂鍐呭锛屽悓鏃跺姞閿 Buffer buffer = ReadBufferFast(seg->space, seg->rnode, seg->forknum, pageno, RBM_ZERO_AND_LOCK); Page page = BufferGetPage(buffer); + // 寮濮嬩簨鍔 START_CRIT_SECTION(); + // 鏍囪缂撳啿鍖轰负鑴忛〉锛岃〃绀洪渶瑕佸啓鍥炵鐩 SegMarkBufferDirty(buffer); + // 鍒濆鍖栭〉鍐呭锛屽皢鍏舵竻闆 SegPageInit(page, BLCKSZ); + // 鎻掑叆XLog璁板綍 XLogBeginInsert(); XLogRegisterBuffer(0, buffer, REGBUF_WILL_INIT); XLogRecPtr rec_ptr = XLogInsert(RM_SEGPAGE_ID, XLOG_SEG_INIT_INVRSPTR_PAGE, SegmentBktId); + // 璁剧疆椤礚SN PageSetLSN(page, rec_ptr); + // 缁撴潫浜嬪姟 END_CRIT_SECTION(); + // 瑙i攣骞堕噴鏀剧紦鍐插尯 SegUnlockReleaseBuffer(buffer); } @@ -473,24 +657,37 @@ BlockNumber eg_next_group_start(df_map_head_t *map_head) return last_map_group.first_map + last_map_group.page_count + IPBLOCK_GROUP_SIZE + DF_MAP_GROUP_EXTENTS * (uint32)map_head->bit_unit; } - +/* + * 鍔熻兘锛氬悜鍒嗘绌洪棿缁勬坊鍔犳柊鐨勬槧灏勭粍 + * + * 鍙傛暟鍒楄〃锛 + * seg锛歋egExtentGroup*锛屽垎娈电┖闂寸粍鐨勬寚閽堛 + * pageno锛欱lockNumber锛屾柊鏄犲皠缁勭殑璧峰椤靛彿銆 + * group_size锛歶int8锛屾槧灏勭粍鐨勫ぇ灏忋 + * old_group_count锛歩nt锛屼箣鍓嶇殑鏄犲皠缁勬暟閲忋 + */ void eg_add_map_group(SegExtentGroup *seg, BlockNumber pageno, uint8 group_size, int old_group_count) { + // 鎵撳嵃鏃ュ織锛岃褰曟坊鍔犳柊鏄犲皠缁勭殑淇℃伅 ereport(LOG, (errmsg("Extent group (%u, %u, %u) add new group #%d, start pageno: %u ", seg->rnode.spcNode, seg->rnode.dbNode, seg->rnode.relNode, old_group_count, pageno))); + // 鑾峰彇鏄犲皠澶寸紦鍐插尯 Buffer map_head_buffer = seg->map_head_buffer; Page page = BufferGetPage(map_head_buffer); df_map_head_t *map_head = (df_map_head_t *)PageGetContents(page); + // 濡傛灉鏃х殑鏄犲皠缁勬暟閲忓皬浜庡綋鍓嶇殑鏁伴噺锛岃鏄庡叾浠栨搷浣滃凡缁忔墿灞曚簡鏄犲皠缁勶紝鐩存帴杩斿洖 if (old_group_count < map_head->group_count) { /* Some one else extend the extent group for us */ return; } + // 妫鏌ユ槧灏勭粍鏁伴噺鏄惁鍖归厤 SegmentCheck(old_group_count == map_head->group_count); SegmentCheck(group_size == DF_MAP_GROUP_SIZE); BlockNumber start_map_no = pageno; BlockNumber data_start = pageno + group_size + IPBLOCK_GROUP_SIZE; + // 鍒濆鍖栦綅鍥鹃〉鍜岄嗗悜鎸囬拡椤 for (uint32 i = 0; i < group_size; i++) { eg_init_bitmap_page(seg, pageno, data_start); data_start += DF_MAP_BIT_CNT * seg->extent_size; @@ -501,10 +698,12 @@ void eg_add_map_group(SegExtentGroup *seg, BlockNumber pageno, uint8 group_size, eg_init_invrsptr_page(seg, pageno); pageno++; } + // 鎵撳嵃娴嬭瘯淇℃伅 SEGMENTTEST(EXTENT_GROUP_ADD_NEW_GROUP, (errmsg("EXTENT_GROUP_ADD_NEW_GROUP %s: add new group success!\n", - g_instance.attr.attr_common.PGXCNodeName))); + g_instance.attr.attr_common.PGXCNodeName))); /* XLog issue */ { + // 寮濮嬩簨鍔 START_CRIT_SECTION(); /* Update map head */ df_map_group_t *bitmap_group = &map_head->groups[map_head->group_count]; @@ -513,8 +712,10 @@ void eg_add_map_group(SegExtentGroup *seg, BlockNumber pageno, uint8 group_size, bitmap_group->page_count = group_size; bitmap_group->free_page = 0; + // 鏍囪鏄犲皠澶寸紦鍐插尯涓鸿剰椤碉紝琛ㄧず闇瑕佸啓鍥炵鐩 SegMarkBufferDirty(map_head_buffer); + // 鍒涘缓XLog璁板綍 xl_new_map_group_info_t new_map_group_info = {.first_map_pageno = start_map_no, .extent_size = seg->extent_size, .group_count = map_head->group_count, @@ -525,11 +726,15 @@ void eg_add_map_group(SegExtentGroup *seg, BlockNumber pageno, uint8 group_size, XLogRegisterBuffer(0, map_head_buffer, REGBUF_STANDARD); XLogRecPtr recptr = XLogInsert(RM_SEGPAGE_ID, XLOG_SEG_ADD_NEW_GROUP, SegmentBktId); + // 璁剧疆椤礚SN PageSetLSN(page, recptr); + // 缁撴潫浜嬪姟 END_CRIT_SECTION(); } - SEGMENTTEST(EXTENT_GROUP_ADD_NEW_GROUP_XLOG, (errmsg("EXTENT_GROUP_ADD_NEW_GROUP_XLOG %s: add new group xlog success!\n", - g_instance.attr.attr_common.PGXCNodeName))); + // 鎵撳嵃娴嬭瘯淇℃伅 + SEGMENTTEST(EXTENT_GROUP_ADD_NEW_GROUP_XLOG, + (errmsg("EXTENT_GROUP_ADD_NEW_GROUP_XLOG %s: add new group xlog success!\n", + g_instance.attr.attr_common.PGXCNodeName))); } /* @@ -551,8 +756,7 @@ BlockNumber eg_try_alloc_extent(SegExtentGroup *seg, BlockNumber preassigned_blo df_map_head_t *map_head = seg->map_head; seg->map_head = map_head; - SegmentCheck(map_head->group_count > 0 && - map_head->free_group < map_head->group_count); + SegmentCheck(map_head->group_count > 0 && map_head->free_group < map_head->group_count); /* preassigned block */ if (BlockNumberIsValid(preassigned_block)) { @@ -592,31 +796,48 @@ BlockNumber eg_try_alloc_extent(SegExtentGroup *seg, BlockNumber preassigned_blo } return InvalidBlockNumber; } - +/* + * 鍔熻兘锛氭鏌ュ垎娈电┖闂寸粍鏄惁涓虹┖ + * + * 鍙傛暟鍒楄〃锛 + * seg锛歋egExtentGroup*锛屽垎娈电┖闂寸粍鐨勬寚閽堛 + */ bool eg_empty(SegExtentGroup *seg) { + // 濡傛灉鍒嗘鏁版嵁鏂囦欢涓嶅瓨鍦紝璁や负鍒嗘绌洪棿缁勪负绌 if (!eg_df_exists(seg)) { return true; } int result; + // 璇诲彇鏄犲皠澶寸紦鍐插尯骞跺叡浜攣瀹 Buffer buffer = eg_read_maphead_buffer(seg); LockBuffer(buffer, BUFFER_LOCK_SHARE); + // 鑾峰彇鏄犲皠澶翠俊鎭 seg->map_head = (df_map_head_t *)PageGetContents(BufferGetPage(buffer)); result = seg->map_head->allocated_extents; + // 閲婃斁鏄犲皠澶寸紦鍐插尯鐨勯攣瀹 SegUnlockReleaseBuffer(buffer); #ifdef USE_ASSERT_CHECKING + // 浣跨敤鏂█妫鏌ワ紝濡傛灉鏈夊凡鍒嗛厤鐨勫垎娈碉紝鍒欐墦鍗版棩蹇楄褰 if (result != 0) { ereport(LOG, (errmsg("Extent group %d is not empty, there are %d extents used", seg->extent_size, result))); } #endif + // 杩斿洖缁撴灉锛屽鏋滃凡鍒嗛厤鐨勫垎娈垫暟涓0锛屽垯璁や负鍒嗘绌洪棿缁勪负绌 return result == 0; } - +/* + * 鍔熻兘锛氳幏鍙栧垎娈电┖闂寸粍鐨勫瓨鍌ㄧ粺璁′俊鎭 + * + * 鍙傛暟鍒楄〃锛 + * seg锛歋egExtentGroup*锛屽垎娈电┖闂寸粍鐨勬寚閽堛 + */ SegmentSpaceStat eg_storage_stat(SegExtentGroup *seg) { + // 濡傛灉鍒嗘鏁版嵁鏂囦欢涓嶅瓨鍦紝杩斿洖榛樿鐨勫瓨鍌ㄧ粺璁′俊鎭 if (!eg_df_exists(seg)) { return {.extent_size = (uint32)seg->extent_size, .forknum = seg->forknum, @@ -626,9 +847,11 @@ SegmentSpaceStat eg_storage_stat(SegExtentGroup *seg) .utilization = 0, .high_water_mark = 0}; } + // 璇诲彇鏄犲皠澶寸紦鍐插尯骞跺叡浜攣瀹 Buffer buffer = eg_read_maphead_buffer(seg); LockBuffer(buffer, BUFFER_LOCK_SHARE); + // 鑾峰彇鏄犲皠澶翠俊鎭 df_map_head_t *map_head = (df_map_head_t *)PageGetContents(BufferGetPage(buffer)); BlockNumber total_blocks = seg->segfile->total_blocks; @@ -651,9 +874,20 @@ SegmentSpaceStat eg_storage_stat(SegExtentGroup *seg) SegUnlockReleaseBuffer(buffer); return result; } - +/* + * 鍔熻兘锛氳幏鍙栧垎娈电┖闂寸粍涓墍鏈夌殑閫嗘寚閽堝拰鏁版嵁鍧楀彿 + * + * 鍙傛暟鍒楄〃锛 + * seg锛歋egExtentGroup*锛屽垎娈电┖闂寸粍鐨勬寚閽堛 + * cnt锛歶int32*锛岃繑鍥炴壘鍒扮殑閫嗘寚閽堝拰鏁版嵁鍧楀彿鐨勬暟閲忋 + * iptrs锛欵xtentInversePointer**锛岃繑鍥為嗘寚閽堟暟缁勭殑鎸囬拡銆 + * extents锛欱lockNumber**锛岃繑鍥炴暟鎹潡鍙锋暟缁勭殑鎸囬拡銆 + * + * 娉ㄦ剰锛氳皟鐢ㄨ呴渶瑕佸湪涓嶅啀闇瑕侀嗘寚閽堝拰鏁版嵁鍧楀彿鏃堕噴鏀惧畠浠殑鍐呭瓨銆 + */ void GetAllInversePointer(SegExtentGroup *seg, uint32 *cnt, ExtentInversePointer **iptrs, BlockNumber **extents) { + // 濡傛灉鍒嗘鏁版嵁鏂囦欢涓嶅瓨鍦紝杩斿洖绌虹粨鏋 if (!eg_df_exists(seg)) { *cnt = 0; *iptrs = NULL; @@ -665,9 +899,11 @@ void GetAllInversePointer(SegExtentGroup *seg, uint32 *cnt, ExtentInversePointer *extents = (BlockNumber *)palloc(sizeof(BlockNumber) * len); *cnt = 0; + // 鑾峰彇鏄犲皠澶翠俊鎭 Buffer buffer = eg_read_maphead_buffer(seg); LockBuffer(buffer, BUFFER_LOCK_SHARE); + // 鑾峰彇鏄犲皠澶翠俊鎭 df_map_head_t *map_head = (df_map_head_t *)PageGetContents(BufferGetPage(buffer)); /* copy meta-data from map head, to avoid locking it for long time. */ @@ -676,6 +912,7 @@ void GetAllInversePointer(SegExtentGroup *seg, uint32 *cnt, ExtentInversePointer for (int i = 0; i < group_count; i++) { groups[i] = map_head->groups[i]; } + // 閲婃斁鏄犲皠澶寸紦鍐插尯鐨勯攣瀹 SegUnlockReleaseBuffer(buffer); Buffer ipbuf = InvalidBuffer; @@ -715,40 +952,53 @@ void GetAllInversePointer(SegExtentGroup *seg, uint32 *cnt, ExtentInversePointer SegUnlockReleaseBuffer(map_buffer); } } + // 濡傛灉閫嗘寚閽堢紦鍐插尯鏈夋晥锛屽垯閲婃斁瀹 if (BufferIsValid(ipbuf)) { SegReleaseBuffer(ipbuf); } } - +/* + * 鍔熻兘锛氱敤浜庢鏌ュ垎娈电┖闂寸粍鏄惁瀛樺湪锛屽鏋滀笉瀛樺湪鍒欏垱寤轰箣銆傚垱寤哄垎娈电┖闂寸粍鏃讹紝杩樹細杩涜涓浜涢檮鍔犵殑鎿嶄綔 + * + * 鍙傛暟鍒楄〃锛 + * seg锛歋egExtentGroup*锛屽垎娈电┖闂寸粍鐨勬寚閽 + */ void eg_create_if_necessary(SegExtentGroup *seg) { + // 濡傛灉鍒嗘鏁版嵁鏂囦欢涓嶅瓨鍦 if (!eg_df_exists(seg)) { AutoMutexLock lock(&seg->lock); lock.lock(); + // 妫鏌ユ槸鍚﹀凡缁忔湁鍏朵粬杩涚▼鍒涘缓浜嗗垎娈垫暟鎹枃浠 if (seg->segfile->file_num > 0) { /* Someone else has created it */ return; } - TablespaceCreateDbspace(seg->rnode.spcNode, seg->rnode.dbNode, false); + // 鍒涘缓琛ㄧ┖闂村拰妫鏌ヨ〃绌洪棿闄愰 + TablespaceCreateDbspace(seg->rnode.spcNode, seg->rnode.dbNode, false); /* Ensure tablespace limits at first. */ uint64 requestSize = DF_FILE_EXTEND_STEP_SIZE; TableSpaceUsageManager::IsExceedMaxsize(seg->rnode.spcNode, requestSize, true); + // 寮濮嬩复鐣屽尯 START_CRIT_SECTION(); t_thrd.pgxact->delayChkpt = true; + // 鍐欏叆XLog璁板綍锛屾爣璁板垎娈电┖闂寸粍鐨勫垱寤 XLogBeginInsert(); XLogRegisterData((char *)&seg->rnode, sizeof(RelFileNode)); XLogRegisterData((char *)&seg->forknum, sizeof(ForkNumber)); XLogRecPtr xlog = XLogInsert(RM_SEGPAGE_ID, XLOG_SEG_CREATE_EXTENT_GROUP, SegmentBktId); XLogWaitFlush(xlog); + // 鍒濆鍖栨暟鎹枃浠跺拰鏄犲皠澶 eg_init_data_files(seg, false, xlog); SEGMENTTEST(EXTENT_GROUP_CREATE_EXTENT, (errmsg("EXTENT_GROUP_CREATE_EXTENT %s: create segment file success!\n", - g_instance.attr.attr_common.PGXCNodeName))); + g_instance.attr.attr_common.PGXCNodeName))); t_thrd.pgxact->delayChkpt = false; + // 缁撴潫涓寸晫鍖 END_CRIT_SECTION(); } } @@ -756,8 +1006,17 @@ void eg_create_if_necessary(SegExtentGroup *seg) /* * Extent Group Layer APIS: allocate/free extents; auto extend if the space is used up. */ +/* + * 鍔熻兘锛氬垎閰嶄竴涓垎娈电┖闂寸粍鐨勬墿灞 + * + * 鍙傛暟鍒楄〃锛 + * seg锛歋egExtentGroup*锛屽垎娈电┖闂寸粍鐨勬寚閽 + * preassigned_block锛欱lockNumber锛岄鍒嗛厤鐨勫潡鍙 + * iptr锛欵xtentInversePointer锛屾墿灞曞潡鐨勯嗘寚閽 + */ BlockNumber eg_alloc_extent(SegExtentGroup *seg, BlockNumber preassigned_block, ExtentInversePointer iptr) { + // 濡傛灉闇瑕佺殑璇濓紝鍒涘缓鍒嗘绌洪棿缁 eg_create_if_necessary(seg); BlockNumber blocknum = InvalidBlockNumber; @@ -766,6 +1025,7 @@ BlockNumber eg_alloc_extent(SegExtentGroup *seg, BlockNumber preassigned_block, seg->map_head_buffer = eg_read_maphead_buffer(seg); LockBuffer(seg->map_head_buffer, BUFFER_LOCK_EXCLUSIVE); seg->map_head = (df_map_head_t *)PageGetContents(BufferGetBlock(seg->map_head_buffer)); + // 濡傛灉鏄犲皠缁勬暟閲忎负0锛屽垱寤虹涓涓槧灏勭粍 if (seg->map_head->group_count == 0) { // create the first map group eg_add_map_group(seg, DF_MAP_HEAD_PAGE + 1, DF_MAP_GROUP_SIZE, 0); @@ -776,8 +1036,9 @@ BlockNumber eg_alloc_extent(SegExtentGroup *seg, BlockNumber preassigned_block, // Get an extent, we do not have to release the map head buffer. XLogAtomicOpCommit will do it for us. // set inverse point and return SetInversePointer(seg, blocknum, iptr); - SEGMENTTEST(EXTENT_GROUP_CRITICAL_SECTION, (errmsg("EXTENT_GROUP_CRITICAL_SECTION %s: alloc extent end, begin critical section!\n", - g_instance.attr.attr_common.PGXCNodeName))); + SEGMENTTEST(EXTENT_GROUP_CRITICAL_SECTION, + (errmsg("EXTENT_GROUP_CRITICAL_SECTION %s: alloc extent end, begin critical section!\n", + g_instance.attr.attr_common.PGXCNodeName))); return blocknum; } @@ -797,12 +1058,21 @@ BlockNumber eg_alloc_extent(SegExtentGroup *seg, BlockNumber preassigned_block, /* * Free extent should be reentrant */ +/* + * 鍔熻兘锛氱敤浜庡彇娑堜綅鍥鹃〉涓殑鎸囧畾浣嶈缃紝灏嗗叾鏍囪涓烘湭浣跨敤銆 + * + * 鍙傛暟鍒楄〃锛 + * map_page锛歞f_map_page_t*锛屼綅鍥鹃〉鐨勬寚閽 + * bit_id锛歶int16锛岃鍙栨秷璁剧疆鐨勪綅鐨処D + */ void eg_unset_bitmap_page(df_map_page_t *map_page, uint16 bit_id) { SegmentCheck(DF_MAP_NOT_FREE(map_page->bitmap, bit_id)); + // 鍙栨秷璁剧疆浣 DF_MAP_UNSET(map_page->bitmap, bit_id); map_page->free_bits++; + // 鏇存柊绌洪棽浣嶇殑璧峰浣嶇疆 if (map_page->free_begin > bit_id) { map_page->free_begin = bit_id; } @@ -811,12 +1081,21 @@ void eg_unset_bitmap_page(df_map_page_t *map_page, uint16 bit_id) /* * Free an extent in the extent group. 'allocated_extents' will be updated. */ +/* + * 鍔熻兘锛氶噴鏀惧垎閰嶇殑鎵╁睍鍧 + * + * 鍙傛暟鍒楄〃锛 + * seg锛歋egExtentGroup*锛屾墿灞曠粍鐨勬寚閽 + * blocknum锛欱lockNumber锛岃閲婃斁鐨勫潡鐨勭紪鍙 + */ void eg_free_extent(SegExtentGroup *seg, BlockNumber blocknum) { + // 璇诲彇鏄犲皠澶寸紦鍐插尯 seg->map_head_buffer = ReadBufferFast(seg->space, seg->rnode, seg->forknum, seg->map_head_entry, RBM_NORMAL); LockBuffer(seg->map_head_buffer, BUFFER_LOCK_EXCLUSIVE); df_map_head_t *map_head = (df_map_head_t *)PageGetContents(BufferGetPage(seg->map_head_buffer)); + // 瀹氫綅瑕侀噴鏀剧殑鍧楃殑浣嶇疆 SpaceMapLocation location = eg_locate_map_by_pageid(seg, blocknum, map_head); if (MapLocationIsInvalid(location)) { ereport(PANIC, (errmsg("Free an already freed extent"))); @@ -828,6 +1107,7 @@ void eg_free_extent(SegExtentGroup *seg, BlockNumber blocknum) LockBuffer(map_buffer, BUFFER_LOCK_EXCLUSIVE); df_map_page_t *map_page = (df_map_page_t *)PageGetContents(BufferGetPage(map_buffer)); + // 鍙栨秷浣嶅浘椤典腑鐨勪綅璁剧疆锛屽皢鍏舵爣璁颁负鏈娇鐢 eg_unset_bitmap_page(map_page, bit_id); map_head->allocated_extents--; diff --git a/src/gausskernel/storage/smgr/segment/inverse_ptr.cpp b/src/gausskernel/storage/smgr/segment/inverse_ptr.cpp index 4f68b5806..40dd5b089 100644 --- a/src/gausskernel/storage/smgr/segment/inverse_ptr.cpp +++ b/src/gausskernel/storage/smgr/segment/inverse_ptr.cpp @@ -32,7 +32,13 @@ static const char *ExtentUsageName[] = {"Not used", "Non-bucket table segment he /* must be last one */ "Invalid Usage Type"}; - +/* + * 鍔熻兘锛氳幏鍙栨墿灞曞潡鐨処nversePointer鍧椾綅缃 + * + * 鍙傛暟鍒楄〃锛 + * extent锛欱lockNumber锛屾墿灞曞潡鐨勭紪鍙 + * extent_size锛歶int32锛屾墿灞曞潡鐨勫ぇ灏 + */ IpBlockLocation GetIpBlock(BlockNumber extent, uint32 extent_size) { /* Exclude MapHead */ @@ -43,7 +49,7 @@ IpBlockLocation GetIpBlock(BlockNumber extent, uint32 extent_size) uint32 group_id = extent / group_total_blocks; /* - * Group inverse pointer start, plus + * Group inverse pointer start, plus * 1. DF_MAP_HEAD_PAGE * 2. previous groups * 3. Map pages in this group @@ -56,16 +62,20 @@ IpBlockLocation GetIpBlock(BlockNumber extent, uint32 extent_size) SegmentCheck(extent_size > 0); uint32 extent_id = group_offset / extent_size; - IpBlockLocation result = { - .ipblock = group_ip_start + extent_id / EXTENTS_PER_IPBLOCK, - .offset = extent_id % EXTENTS_PER_IPBLOCK - }; + IpBlockLocation result = {.ipblock = group_ip_start + extent_id / EXTENTS_PER_IPBLOCK, + .offset = extent_id % EXTENTS_PER_IPBLOCK}; return result; } - +/* + * 鍔熻兘锛氳幏鍙栨墿灞曞潡浣跨敤鎯呭喌鐨勫悕绉 + * + * 鍙傛暟鍒楄〃锛 + * iptr锛欵xtentInversePointer锛孖nversePointer鍧楃殑鎸囬拡 + */ const char *GetExtentUsageName(ExtentInversePointer iptr) { int usage = SPC_INVRSPTR_GET_USAGE(iptr); + // 濡傛灉浣跨敤鎯呭喌澶т簬鎴栫瓑浜嶪NVALID_EXTNT_USAGE锛屽皢鍏惰缃负INVALID_EXTNT_USAGE if (usage >= INVALID_EXTNT_USAGE) { usage = INVALID_EXTNT_USAGE; } @@ -74,32 +84,58 @@ const char *GetExtentUsageName(ExtentInversePointer iptr) } /* Inverse pointer read buffer */ +/* + * 鍔熻兘锛氱敤浜庤鍙栨墿灞曠粍鐨処nversePointer鍧楃殑缂撳啿鍖猴紝骞跺彲浠ラ夋嫨鏄惁鍦ㄩ渶瑕佹椂杩涜鎵╁睍銆 + * + * 鍙傛暟鍒楄〃锛 + * seg锛歋egExtentGroup鎸囬拡锛岃〃绀烘墿灞曠粍鐨勪俊鎭 + * blocknum锛欱lockNumber锛岃〃绀鸿璇诲彇鐨勫潡鍙 + * extend锛歜ool锛岃〃绀烘槸鍚﹀湪闇瑕佹椂杩涜鎵╁睍 + */ Buffer ip_readbuf(SegExtentGroup *seg, BlockNumber blocknum, bool extend) { #ifdef USE_ASSERT_CHECKING + // 妫鏌ュ潡鍙锋槸鍚﹀皬浜庢暟鎹枃浠剁殑澶у皬 BlockNumber df_size = eg_df_size(seg); SegmentCheck(blocknum < df_size); #endif + // 璇诲彇鍧楃殑缂撳啿鍖 Buffer buf = ReadBufferFast(seg->space, seg->rnode, seg->forknum, blocknum, RBM_NORMAL); + // 濡傛灉椤甸潰鏄柊鐨勶紝鍒欒繘琛屽垵濮嬪寲 if (PageIsNew(BufferGetPage(buf))) { SegPageInit(BufferGetPage(buf), BLCKSZ); } return buf; } - +/* + * 鍔熻兘锛氱敤浜庤缃寚瀹氬潡鍙风殑InversePointer銆傚畠浼氳鍙朓nversePointer鍧楃殑缂撳啿鍖猴紝 + * 灏嗘寚瀹氱殑InversePointer瀛樺偍鍦ㄥ悎閫傜殑浣嶇疆锛屽苟杩涜XLog璁板綍浠ョ‘淇濇寔涔呮с + * + * 鍙傛暟鍒楄〃锛 + * seg锛歋egExtentGroup鎸囬拡锛岃〃绀烘墿灞曠粍鐨勪俊鎭 + * extent锛欱lockNumber锛岃〃绀鸿璁剧疆InversePointer鐨勫潡鍙 + * iptr锛欵xtentInversePointer锛岃〃绀鸿璁剧疆鐨処nversePointer鍊 + * + * 娉ㄦ剰锛氬嚱鏁板唴閮ㄤ細浣跨敤GetIpBlock鍜宨p_readbuf鍑芥暟鏉ュ畾浣嶅拰璇诲彇InversePointer鍧 + */ void SetInversePointer(SegExtentGroup *seg, BlockNumber extent, ExtentInversePointer iptr) { + // 浣跨敤GetIpBlock鍑芥暟鑾峰彇InversePointer鍧楃殑浣嶇疆 IpBlockLocation loc = GetIpBlock(extent, seg->extent_size); + // 浣跨敤ip_readbuf鍑芥暟璇诲彇InversePointer鍧楃殑缂撳啿鍖猴紝骞跺彲浠ラ夋嫨鍦ㄩ渶瑕佹椂杩涜鎵╁睍 Buffer ipBuffer = ip_readbuf(seg, loc.ipblock, true); SegmentCheck(BufferIsValid(ipBuffer)); + // 閿佸畾缂撳啿鍖轰互杩涜鍐欐搷浣 LockBuffer(ipBuffer, BUFFER_LOCK_EXCLUSIVE); + // 鑾峰彇InversePointer鍧楃殑鍐呭骞惰缃寚瀹氫綅缃殑鍊 ExtentInversePointer *eips = (ExtentInversePointer *)PageGetContents(BufferGetBlock(ipBuffer)); eips[loc.offset] = iptr; + // 娉ㄥ唽XLog璁板綍浠ョ‘淇濇寔涔呮 XLogAtomicOpRegisterBuffer(ipBuffer, REGBUF_KEEP_DATA, SPCXLOG_SET_INVERSE_POINTER, XLOG_COMMIT_UNLOCK_RELEASE_BUFFER); XLogAtomicOpRegisterBufData((char *)&loc.offset, sizeof(uint32)); @@ -114,9 +150,26 @@ void SetInversePointer(SegExtentGroup *seg, BlockNumber extent, ExtentInversePoi * is a valid buffer containing the inverse pointer of the given extent. The caller is responsible * to release the buf after it has done scanning. */ +/* + * 鍔熻兘锛氱敤浜庤幏鍙栨寚瀹氬潡鍙风殑InversePointer銆傚畠浼氭牴鎹紶鍏ョ殑缂撳啿鍖烘寚閽堬紙濡傛灉瀛樺湪锛 + * 鎴栬呭垱寤烘柊鐨勭紦鍐插尯鏉ヨ鍙朓nversePointer锛屽苟杩斿洖鎵闇鐨処nversePointer鍊笺 + * + * 鍙傛暟鍒楄〃锛 + * seg锛歋egExtentGroup鎸囬拡锛岃〃绀烘墿灞曠粍鐨勪俊鎭 + * extent锛欱lockNumber锛岃〃绀鸿鑾峰彇InversePointer鐨勫潡鍙 + * buf锛欱uffer鎸囬拡鐨勬寚閽堬紝鐢ㄤ簬浼犻掓垨鎺ユ敹InversePointer鍧楃殑缂撳啿鍖 + * 濡傛灉浼犲叆鐨勭紦鍐插尯鏃犳晥锛屽嚱鏁颁細鍒涘缓涓涓柊鐨勭紦鍐插尯 + * + * 娉ㄦ剰锛 + * - 濡傛灉浼犲叆鐨勭紦鍐插尯涓嶄负绌轰笖缂撳啿鍖轰笌鍧楀彿涓嶅尮閰嶏紝鏃х紦鍐插尯浼氳閲婃斁骞剁疆涓烘棤鏁堛 + * - 鍑芥暟鍐呴儴浼氫娇鐢℅etIpBlock鍜宨p_readbuf鍑芥暟鏉ュ畾浣嶅拰璇诲彇InversePointer鍧椼 + * - 鍑芥暟浼氱‘淇濊繑鍥炵殑InversePointer鍊兼湁鏁堛 + */ ExtentInversePointer GetInversePointer(SegExtentGroup *seg, BlockNumber extent, Buffer *buf) { + // 妫鏌ヤ紶鍏ョ殑缂撳啿鍖烘寚閽堟槸鍚︿负绌 SegmentCheck(buf != NULL); + // 浣跨敤GetIpBlock鍑芥暟鑾峰彇InversePointer鍧楃殑浣嶇疆 IpBlockLocation loc = GetIpBlock(extent, seg->extent_size); if (BufferIsValid(*buf)) { @@ -129,16 +182,21 @@ ExtentInversePointer GetInversePointer(SegExtentGroup *seg, BlockNumber extent, } } + // 濡傛灉浼犲叆鐨勭紦鍐插尯鏃犳晥锛屽垱寤轰竴涓柊鐨勭紦鍐插尯骞惰鍙朓nversePointer鍧 if (BufferIsInvalid(*buf)) { *buf = ip_readbuf(seg, loc.ipblock, false); } + // 妫鏌ョ紦鍐插尯鏄惁鏈夋晥 SegmentCheck(BufferIsValid(*buf)); + // 閿佸畾缂撳啿鍖轰互杩涜璇诲彇鎿嶄綔锛屽苟鑾峰彇InversePointer鍊 LockBuffer(*buf, BUFFER_LOCK_SHARE); ExtentInversePointer *eips = (ExtentInversePointer *)PageGetContents(BufferGetBlock(*buf)); ExtentInversePointer res = eips[loc.offset]; + // 瑙i攣缂撳啿鍖 LockBuffer(*buf, BUFFER_LOCK_UNLOCK); + // 纭繚杩斿洖鐨処nversePointer鍊兼湁鏁 SegmentCheck(InversePointerIsValid(res)); return res; diff --git a/src/gausskernel/storage/smgr/segment/segbuffer.cpp b/src/gausskernel/storage/smgr/segment/segbuffer.cpp index df84a6ba0..027c1a0f4 100644 --- a/src/gausskernel/storage/smgr/segment/segbuffer.cpp +++ b/src/gausskernel/storage/smgr/segment/segbuffer.cpp @@ -34,7 +34,7 @@ #include "tsan_annotation.h" #include "pgstat.h" -/* +/* * Segment buffer, used for segment meta data, e.g., segment head, space map head. We separate segment * meta data buffer and normal data buffer (in bufmgr.cpp) to avoid potential dead locks. */ @@ -54,89 +54,142 @@ static void SegTerminateBufferIO(BufferDesc *buf, bool clear_dirty, uint32 set_f extern PrivateRefCountEntry *GetPrivateRefCountEntry(Buffer buffer, bool create, bool do_move); extern void ForgetPrivateRefCountEntry(PrivateRefCountEntry *ref); - +/* + * 鍔熻兘锛氫腑姝㈠垎娈电紦鍐插尯IO鎿嶄綔 + */ void AbortSegBufferIO(void) { + // 妫鏌ユ槸鍚﹀瓨鍦ㄦ鍦ㄨ繘琛岀殑IO鎿嶄綔 if (InProgressBuf != NULL) { + // 鑾峰彇姝e湪杩涜IO鎿嶄綔鐨勯攣 LWLockAcquire(InProgressBuf->io_in_progress_lock, LW_EXCLUSIVE); + // 璋冪敤SegTerminateBufferIO鍑芥暟缁堟IO鎿嶄綔锛屽皢IO閿欒鏍囧織璁剧疆涓築M_IO_ERROR SegTerminateBufferIO(InProgressBuf, false, BM_IO_ERROR); } } - +/* + * 鍔熻兘锛氱瓑寰呯紦鍐插尯鐨処O鎿嶄綔瀹屾垚 + * + * 鍙傛暟鍒楄〃锛 + * buf锛欱ufferDesc 缁撴瀯锛岃〃绀哄緟绛夊緟IO鎿嶄綔瀹屾垚鐨勭紦鍐插尯 + * + * 娉ㄦ剰锛氳鍑芥暟涓嶄細涓诲姩缁堟缂撳啿鍖虹殑IO鎿嶄綔锛屼粎鐢ㄤ簬绛夊緟IO鎿嶄綔瀹屾垚銆 + */ static void WaitIO(BufferDesc *buf) { while (true) { uint32 buf_state; + // 鑾峰彇缂撳啿鍖虹殑鐘舵 buf_state = LockBufHdr(buf); + // 閲婃斁瀵圭紦鍐插尯鐘舵佺殑閿佸畾 UnlockBufHdr(buf, buf_state); + // 妫鏌ョ紦鍐插尯鏄惁浠嶅湪杩涜IO鎿嶄綔 if (!(buf_state & BM_IO_IN_PROGRESS)) { + // 濡傛灉IO鎿嶄綔宸插畬鎴愶紝鍒欓鍑哄惊鐜 break; } + // 鑾峰彇IO鎿嶄綔鐨勯攣浠ョ瓑寰匢O瀹屾垚 LWLockAcquire(buf->io_in_progress_lock, LW_SHARED); + // 閲婃斁IO鎿嶄綔鐨勯攣 LWLockRelease(buf->io_in_progress_lock); } } - +/* + * 鍔熻兘锛氬紑濮嬬紦鍐插尯鐨処O鎿嶄綔 + * + * 鍙傛暟鍒楄〃锛 + * buf锛欱ufferDesc 缁撴瀯锛岃〃绀哄緟杩涜IO鎿嶄綔鐨勭紦鍐插尯 + * forInput锛歜ool 鍊硷紝琛ㄧず鏄惁鏄緭鍏ユ搷浣滐紙璇诲彇锛 + * + * 娉ㄦ剰锛氬嚱鏁拌皟鐢ㄨ呭簲璇ュ湪閫傚綋鐨勬椂鍊欓噴鏀綢O鎿嶄綔閿佸拰淇敼缂撳啿鍖虹姸鎬併 + */ static bool SegStartBufferIO(BufferDesc *buf, bool forInput) { uint32 buf_state; + // 妫鏌ュ叏灞鍙橀噺锛岀‘淇濇病鏈夊叾浠栫紦鍐插尯鐨処O鎿嶄綔姝e湪杩涜 SegmentCheck(!InProgressBuf); while (true) { + // 鑾峰彇缂撳啿鍖虹殑IO鎿嶄綔閿侊紙鐙崰妯″紡锛 LWLockAcquire(buf->io_in_progress_lock, LW_EXCLUSIVE); + // 鑾峰彇缂撳啿鍖虹殑鐘舵 buf_state = LockBufHdr(buf); if (!(buf_state & BM_IO_IN_PROGRESS)) { + // 濡傛灉缂撳啿鍖虹殑IO鎿嶄綔灏氭湭寮濮嬶紝鍒欓鍑哄惊鐜 break; } + // 閲婃斁瀵圭紦鍐插尯鐘舵佺殑閿佸畾 UnlockBufHdr(buf, buf_state); + // 閲婃斁IO鎿嶄綔閿 LWLockRelease(buf->io_in_progress_lock); + // 绛夊緟鍏朵粬IO鎿嶄綔瀹屾垚 WaitIO(buf); } if (forInput ? (buf_state & BM_VALID) : !(buf_state & BM_DIRTY)) { /* IO finished */ UnlockBufHdr(buf, buf_state); + // 閲婃斁IO鎿嶄綔閿 LWLockRelease(buf->io_in_progress_lock); return false; } + // 璁剧疆缂撳啿鍖虹殑鐘舵佹爣蹇楋紝琛ㄧずIO鎿嶄綔宸插紑濮 buf_state |= BM_IO_IN_PROGRESS; UnlockBufHdr(buf, buf_state); + // 璁剧疆鍏ㄥ眬鍙橀噺锛屾寚鍚戞鍦ㄨ繘琛孖O鎿嶄綔鐨勭紦鍐插尯 InProgressBuf = buf; isForInput = forInput; return true; } - +/* + * 鍔熻兘锛氱粓姝㈢紦鍐插尯鐨処O鎿嶄綔 + * + * 鍙傛暟鍒楄〃锛 + * buf锛欱ufferDesc 缁撴瀯锛岃〃绀哄緟缁堟IO鎿嶄綔鐨勭紦鍐插尯 + * clear_dirty锛歜ool 鍊硷紝琛ㄧず鏄惁娓呴櫎鑴忔爣蹇 + * set_flag_bits锛歶int32 鍊硷紝琛ㄧず瑕佽缃殑鏍囧織浣 + * + * 娉ㄦ剰锛氬嚱鏁拌皟鐢ㄨ呭簲璇ュ湪閫傚綋鐨勬椂鍊欓噴鏀綢O鎿嶄綔閿佸拰淇敼缂撳啿鍖虹姸鎬併 + */ static void SegTerminateBufferIO(BufferDesc *buf, bool clear_dirty, uint32 set_flag_bits) { + // 妫鏌ヤ紶鍏ョ殑缂撳啿鍖烘槸鍚︿笌鍏ㄥ眬鍙橀噺 InProgressBuf 鍖归厤 SegmentCheck(buf == InProgressBuf); + // 鑾峰彇缂撳啿鍖虹殑鐘舵 uint32 buf_state = LockBufHdr(buf); + // 妫鏌ョ紦鍐插尯鐨処O鎿嶄綔鏄惁宸插紑濮 SegmentCheck(buf_state & BM_IO_IN_PROGRESS); + // 娓呴櫎 BM_IO_IN_PROGRESS 鍜 BM_IO_ERROR 鏍囧織浣 buf_state &= ~(BM_IO_IN_PROGRESS | BM_IO_ERROR); if (clear_dirty) { if (ENABLE_INCRE_CKPT) { + // 妫鏌ユ槸鍚﹂渶瑕佷粠鑴忛〉闃熷垪涓Щ闄よ缂撳啿鍖 if (!XLogRecPtrIsInvalid(pg_atomic_read_u64(&buf->rec_lsn))) { remove_dirty_page_from_queue(buf); } else { + // 濡傛灉缂撳啿鍖鸿剰鏍囧織琚缃絾涓嶅湪鑴忛〉闃熷垪涓紝鎶涘嚭 PANIC 閿欒 ereport(PANIC, (errmodule(MOD_INCRE_CKPT), errcode(ERRCODE_INVALID_BUFFER), (errmsg("buffer is dirty but not in dirty page queue in TerminateBufferIO_common")))); } + // 妫鏌 BM_JUST_DIRTIED 鏍囧織浣嶏紝濡傛灉璁剧疆浜嗭紝琛ㄧず涓嶉渶瑕佹鏌ョ偣 if ((buf_state & BM_JUST_DIRTIED)) { buf_state &= ~BM_CHECKPOINT_NEEDED; + // 灏嗙紦鍐插尯娣诲姞鍒板緟鍒锋柊闃熷垪涓 if (!push_pending_flush_queue(BufferDescriptorGetBuffer(buf))) { ereport(PANIC, (errmodule(MOD_INCRE_CKPT), errcode(ERRCODE_INVALID_BUFFER), (errmsg("TerminateBufferIO_common, dirty page queue is full when trying to " @@ -145,51 +198,76 @@ static void SegTerminateBufferIO(BufferDesc *buf, bool clear_dirty, uint32 set_f } } + // 濡傛灉 BM_JUST_DIRTIED 娌℃湁璁剧疆锛屾竻闄 BM_DIRTY 鍜 BM_CHECKPOINT_NEEDED 鏍囧織浣 if (!(buf_state & BM_JUST_DIRTIED)) { buf_state &= ~(BM_DIRTY | BM_CHECKPOINT_NEEDED); } } + // 璁剧疆鎸囧畾鐨勬爣蹇椾綅 buf_state |= set_flag_bits; + // 閲婃斁缂撳啿鍖虹姸鎬侀攣 UnlockBufHdr(buf, buf_state); + // 娓呴櫎鍏ㄥ眬鍙橀噺 InProgressBuf锛岃〃绀篒O鎿嶄綔宸茬粨鏉 InProgressBuf = NULL; + // 閲婃斁IO鎿嶄綔閿 LWLockRelease(buf->io_in_progress_lock); } - +/* + * 鍔熻兘锛氱敤浜庣瓑寰呯紦鍐插尯澶撮儴瑙i攣 + * + * 鍙傛暟鍒楄〃锛 + * buf锛欱ufferDesc 缁撴瀯锛岃〃绀哄緟绛夊緟鐨勭紦鍐插尯澶撮儴 + */ static uint32 SegWaitBufHdrUnlocked(BufferDesc *buf) { #ifndef ENABLE_THREAD_CHECK + // 鍒濆鍖栬嚜鏃嬬瓑寰呯姸鎬侊紝鐢ㄤ簬璁板綍鑷棆绛夊緟鐨勮繘搴 SpinDelayStatus delayStatus = init_spin_delay(buf); #endif uint32 buf_state; + // 璇诲彇缂撳啿鍖哄ご閮ㄧ殑鐘舵 buf_state = pg_atomic_read_u32(&buf->state); + // 寰幆妫鏌ョ紦鍐插尯澶撮儴鐨勭姸鎬侊紝鐩村埌瑙i攣 while (buf_state & BM_LOCKED) { #ifndef ENABLE_THREAD_CHECK + // 鎵ц鑷棆绛夊緟 perform_spin_delay(&delayStatus); #endif + // 閲嶆柊璇诲彇缂撳啿鍖哄ご閮ㄧ殑鐘舵 buf_state = pg_atomic_read_u32(&buf->state); } #ifndef ENABLE_THREAD_CHECK + // 缁撴潫鑷棆绛夊緟 finish_spin_delay(&delayStatus); #endif /* ENABLE_THREAD_CHECK only, acqurie semantic */ + // 浣跨敤 TsAnnotateHappensAfter 娉ㄩ噴纭繚鑾峰彇璇箟 TsAnnotateHappensAfter(&buf->state); + // 杩斿洖鏈缁堢殑缂撳啿鍖哄ご閮ㄧ姸鎬 return buf_state; } - +/* + * 鍔熻兘锛氬鍔犵紦鍐插尯鐨勫紩鐢ㄨ鏁 + * + * 鍙傛暟鍒楄〃锛 + * buf锛欱ufferDesc 缁撴瀯锛岃〃绀哄緟澧炲姞寮曠敤璁℃暟鐨勭紦鍐插尯 + */ bool SegPinBuffer(BufferDesc *buf) { + // 鎵撳嵃璋冭瘯淇℃伅 ereport(DEBUG5, (errmodule(MOD_SEGMENT_PAGE), errmsg("[SegPinBuffer] (%u %u %u %d) %d %u ", buf->tag.rnode.spcNode, buf->tag.rnode.dbNode, buf->tag.rnode.relNode, buf->tag.rnode.bucketNode, buf->tag.forkNum, buf->tag.blockNum))); bool result; - PrivateRefCountEntry * ref = GetPrivateRefCountEntry(BufferDescriptorGetBuffer(buf), true, true); + // 鑾峰彇缂撳啿鍖虹殑绉佹湁寮曠敤璁℃暟椤 + PrivateRefCountEntry *ref = GetPrivateRefCountEntry(BufferDescriptorGetBuffer(buf), true, true); SegmentCheck(ref != NULL); if (ref->refcount == 0) { @@ -198,114 +276,194 @@ bool SegPinBuffer(BufferDesc *buf) for (;;) { if (old_buf_state & BM_LOCKED) { + // 濡傛灉缂撳啿鍖哄凡琚攣瀹氾紝绛夊緟鐩村埌閿佸畾琚噴鏀 old_buf_state = SegWaitBufHdrUnlocked(buf); } buf_state = old_buf_state; + // 澧炲姞寮曠敤璁℃暟 buf_state += BUF_REFCOUNT_ONE; + // 浣跨敤鍘熷瓙鎿嶄綔姣旇緝骞朵氦鎹㈡潵璁剧疆鏂扮殑缂撳啿鍖虹姸鎬 if (pg_atomic_compare_exchange_u32(&buf->state, &old_buf_state, buf_state)) { + // 璁剧疆缁撴灉涓虹紦鍐插尯鏄惁鏈夋晥 result = old_buf_state & BM_VALID; break; } } } else { + // 濡傛灉寮曠敤璁℃暟涓嶄负闆讹紝杩斿洖 true result = true; } + // 澧炲姞绉佹湁寮曠敤璁℃暟椤圭殑寮曠敤璁℃暟 ref->refcount++; + // 鎵╁睍褰撳墠璧勬簮鎵鏈夎呯殑缂撳啿鍖哄垪琛ㄥ苟璁板綍缂撳啿鍖 ResourceOwnerEnlargeBuffers(t_thrd.utils_cxt.CurrentResourceOwner); ResourceOwnerRememberBuffer(t_thrd.utils_cxt.CurrentResourceOwner, BufferDescriptorGetBuffer(buf)); return result; } - +/* + * 鍔熻兘锛氶攣瀹氬苟寮曠敤缂撳啿鍖猴紝杩欐槸涓涓噸瑕佺殑鎿嶄綔锛岀敤浜 + * 淇濊瘉鍦ㄨ闂紦鍐插尯鏃剁殑绾跨▼瀹夊叏鎬с + * + * 鍙傛暟鍒楄〃锛 + * buf锛欱ufferDesc 缁撴瀯锛岃〃绀哄緟閿佸畾鍜屽紩鐢ㄧ殑缂撳啿鍖 + * tag锛欱ufferTag 缁撴瀯锛岃〃绀虹紦鍐插尯鐨勬爣绛句俊鎭 + * + */ static bool SegPinBufferLocked(BufferDesc *buf, const BufferTag *tag) { ereport(DEBUG5, (errmodule(MOD_SEGMENT_PAGE), errmsg("[SegPinBufferLocked] (%u %u %u %d) %d %u ", tag->rnode.spcNode, tag->rnode.dbNode, tag->rnode.relNode, tag->rnode.bucketNode, tag->forkNum, tag->blockNum))); + // 纭繚缂撳啿鍖哄凡缁忚閿佸畾 SegmentCheck(BufHdrLocked(buf)); - PrivateRefCountEntry * ref = GetPrivateRefCountEntry(BufferDescriptorGetBuffer(buf), true, true); + // 鑾峰彇缂撳啿鍖虹殑寮曠敤璁℃暟缁撴瀯 + PrivateRefCountEntry *ref = GetPrivateRefCountEntry(BufferDescriptorGetBuffer(buf), true, true); + // 纭繚寮曠敤璁℃暟缁撴瀯鏈夋晥 SegmentCheck(ref != NULL); + // 璇诲彇缂撳啿鍖虹殑鐘舵 uint32 buf_state = pg_atomic_read_u32(&buf->state); + // 濡傛灉缂撳啿鍖虹殑寮曠敤璁℃暟涓0锛屽鍔犲紩鐢ㄨ鏁 if (ref->refcount == 0) { buf_state += BUF_REFCOUNT_ONE; } + // 瑙i攣缂撳啿鍖猴紝骞惰缃柊鐨勭姸鎬 UnlockBufHdr(buf, buf_state); + // 澧炲姞寮曠敤璁℃暟 ref->refcount++; + // 鎵╁睍褰撳墠璧勬簮鎵鏈夎呯殑缂撳啿鍖哄垪琛 ResourceOwnerEnlargeBuffers(t_thrd.utils_cxt.CurrentResourceOwner); + // 璁板綍缂撳啿鍖哄埌褰撳墠璧勬簮鎵鏈夎 ResourceOwnerRememberBuffer(t_thrd.utils_cxt.CurrentResourceOwner, BufferDescriptorGetBuffer(buf)); + // 杩斿洖缂撳啿鍖虹姸鎬佹槸鍚︽湁鏁 return buf_state & BM_VALID; } - +/* + * 鍔熻兘锛氳В闄ょ紦鍐插尯寮曠敤锛岀敤浜庣‘淇濆湪澶氱嚎绋嬬幆澧冧腑姝g‘澶勭悊缂撳啿鍖虹殑寮曠敤鍜岀姸鎬併 + * + * 鍙傛暟鍒楄〃锛 + * buf锛欱ufferDesc 缁撴瀯锛岃〃绀哄緟瑙i櫎寮曠敤鐨勭紦鍐插尯 + * + * 娉ㄦ剰锛 + * 濡傛灉缂撳啿鍖虹殑寮曠敤璁℃暟褰掗浂锛岃鍑芥暟浼氳В閿佺紦鍐插尯锛屼絾涓嶄細浠庡唴瀛樹腑閲婃斁缂撳啿鍖恒 + */ void SegUnpinBuffer(BufferDesc *buf) { ereport(DEBUG5, (errmodule(MOD_SEGMENT_PAGE), errmsg("[SegUnpinBuffer] (%u %u %u %d) %d %u ", buf->tag.rnode.spcNode, buf->tag.rnode.dbNode, buf->tag.rnode.relNode, buf->tag.rnode.bucketNode, buf->tag.forkNum, buf->tag.blockNum))); - PrivateRefCountEntry * ref = GetPrivateRefCountEntry(BufferDescriptorGetBuffer(buf), true, true); + // 鑾峰彇缂撳啿鍖虹殑寮曠敤璁℃暟缁撴瀯 + PrivateRefCountEntry *ref = GetPrivateRefCountEntry(BufferDescriptorGetBuffer(buf), true, true); + // 纭繚寮曠敤璁℃暟缁撴瀯鏈夋晥 SegmentCheck(ref != NULL); + // 浠庡綋鍓嶈祫婧愭墍鏈夎呯殑缂撳啿鍖哄垪琛ㄤ腑绉婚櫎缂撳啿鍖 ResourceOwnerForgetBuffer(t_thrd.utils_cxt.CurrentResourceOwner, BufferDescriptorGetBuffer(buf)); + // 鍑忓皯寮曠敤璁℃暟 ref->refcount--; + // 濡傛灉寮曠敤璁℃暟褰掗浂 if (ref->refcount == 0) { uint32 buf_state; uint32 old_buf_state; + // 璇诲彇缂撳啿鍖虹殑鐘舵 old_buf_state = pg_atomic_read_u32(&buf->state); for (;;) { + // 濡傛灉缂撳啿鍖鸿閿佸畾锛岀瓑寰呭叾瑙i攣 if (old_buf_state & BM_LOCKED) { old_buf_state = SegWaitBufHdrUnlocked(buf); } buf_state = old_buf_state; + // 纭繚寮曠敤璁℃暟澶т簬0 SegmentCheck(BUF_STATE_GET_REFCOUNT(buf_state) > 0); + // 鍑忓皯寮曠敤璁℃暟 buf_state -= BUF_REFCOUNT_ONE; + // 浣跨敤鍘熷瓙鎿嶄綔鏇存柊缂撳啿鍖虹姸鎬 if (pg_atomic_compare_exchange_u32(&buf->state, &old_buf_state, buf_state)) { break; } } - + + // 纭繚缂撳啿鍖烘病鏈夌瓑寰呯殑寮曠敤璁℃暟 SegmentCheck(!(buf_state & BM_PIN_COUNT_WAITER)); + // 閲嶇疆寮曠敤璁℃暟 ref->refcount = 0; + // 閲婃斁寮曠敤璁℃暟缁撴瀯 ForgetPrivateRefCountEntry(ref); } } - +/* + * 鍔熻兘锛氶噴鏀剧紦鍐插尯 + * + * 鍙傛暟鍒楄〃锛 + * buffer锛欱uffer 鏁版嵁绫诲瀷锛岃〃绀哄緟閲婃斁鐨勭紦鍐插尯 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁扮敤浜庨噴鏀句竴涓紦鍐插尯锛岀‘淇濅笉鍐嶉渶瑕佽闂缂撳啿鍖虹殑鍐呭锛屼互鍏嶅唴瀛樻硠婕忋 + */ void SegReleaseBuffer(Buffer buffer) { + // 妫鏌ョ紦鍐插尯鏄惁鏄湁鏁堢殑娈电紦鍐插尯 SegmentCheck(IsSegmentBufferID(buffer - 1)); + // 璋冪敤 SegUnpinBuffer 鍑芥暟鏉ヨВ闄ゅ缂撳啿鍖虹殑寮曠敤 SegUnpinBuffer(GetBufferDescriptor(buffer - 1)); } - -void SegUnlockReleaseBuffer(Buffer buffer) +/* + * 鍔熻兘锛氳В閿佸苟閲婃斁缂撳啿鍖 + * + * 鍙傛暟鍒楄〃锛 + * buffer锛欱uffer 鏁版嵁绫诲瀷锛岃〃绀哄緟瑙i攣骞堕噴鏀剧殑缂撳啿鍖 + * + * 娉ㄦ剰锛 + * 璇ュ嚱鏁伴傜敤浜庨渶瑕佽В閿佸苟閲婃斁缂撳啿鍖虹殑鎯呭喌锛岀‘淇濅笉鍐嶉渶瑕佽闂缂撳啿鍖虹殑鍐呭锛 + * 浠ュ厤鍐呭瓨娉勬紡銆 + */ +void SegUnlockReleaseBuffer(Buffer buffer) { - LockBuffer(buffer, BUFFER_LOCK_UNLOCK); + // 閫氳繃 LockBuffer 鍑芥暟灏嗙紦鍐插尯瑙i攣 + LockBuffer(buffer, BUFFER_LOCK_UNLOCK); + // 璋冪敤 SegUnpinBuffer 鍑芥暟鏉ヨВ闄ゅ缂撳啿鍖虹殑寮曠敤 SegUnpinBuffer(GetBufferDescriptor(buffer - 1)); } - +/* + * 鍔熻兘锛氬皢缂撳啿鍖烘爣璁颁负鑴忛〉鑴忛〉浼氬湪浠ュ悗鐨勬椂鍒昏鍚屾鍒扮鐩樹笂锛屼互淇濊瘉鏁版嵁鐨勬寔涔呮с + * + * 鍙傛暟鍒楄〃锛 + * buf锛欱uffer 鏁版嵁绫诲瀷锛岃〃绀哄緟鏍囪涓鸿剰椤电殑缂撳啿鍖 + * + * 娉ㄦ剰锛 + * 1. 璇ュ嚱鏁板亣瀹氱紦鍐插尯鐨勫唴瀹归攣锛坈ontent_lock锛夊凡缁忕敱璋冪敤鑰呰幏鍙栵紝鍥犳娌℃湁杩涜閿佺殑鑾峰彇鎿嶄綔銆 + * 2. 鍑芥暟浼氭鏌ヨ剰椤垫槸鍚﹀凡缁忓湪鑴忛〉闃熷垪涓紝濡傛灉涓嶅湪锛屽垯灏嗗叾娣诲姞鍒拌剰椤甸槦鍒椾腑绛夊緟鍚屾銆 + */ void SegMarkBufferDirty(Buffer buf) { uint32 old_buf_state, buf_state; BufferDesc *bufHdr; + // 鑾峰彇缂撳啿鍖烘弿杩扮 bufHdr = GetBufferDescriptor(buf - 1); + // 杩涜涓绯诲垪鏂█妫鏌ワ紝纭繚缂撳啿鍖虹殑鍚堟硶鎬 SegmentCheck(IsSegmentBufferID(bufHdr->buf_id)); /* unfortunately we can't check if the lock is held exclusively */ SegmentCheck(LWLockHeldByMe(bufHdr->content_lock)); + // 鑾峰彇缂撳啿鍖虹殑鏃х姸鎬 old_buf_state = LockBufHdr(bufHdr); + // 璁剧疆缂撳啿鍖虹殑鏂扮姸鎬侊紝鏍囪涓鸿剰椤碉紙BM_DIRTY锛夊拰鍒氬垰鑴忓寲锛圔M_JUST_DIRTIED锛 buf_state = old_buf_state | (BM_DIRTY | BM_JUST_DIRTIED); /* @@ -320,19 +478,33 @@ void SegMarkBufferDirty(Buffer buf) break; } + // 濡傛灉鑴忛〉闃熷垪涓嶆弧锛屽苟涓旀垚鍔熷皢鑴忛〉鎺ㄩ佸埌闃熷垪涓紝灏遍鍑哄惊鐜 if (!is_dirty_page_queue_full(bufHdr) && push_pending_flush_queue(buf)) { break; } + // 瑙i攣缂撳啿鍖烘弿杩扮锛岃鍏朵粬绾跨▼鏈夋満浼氳幏鍙栭攣 UnlockBufHdr(bufHdr, old_buf_state); + // 鐭殏浼戠湢涓娈垫椂闂达紝鐒跺悗鍐嶆灏濊瘯鑾峰彇閿 pg_usleep(TEN_MICROSECOND); old_buf_state = LockBufHdr(bufHdr); } } + // 瑙i攣缂撳啿鍖烘弿杩扮锛屽苟璁剧疆鏂扮姸鎬 UnlockBufHdr(bufHdr, buf_state); } - +/* + * 鍔熻兘锛氬皢缂撳啿鍖虹殑鏁版嵁鍒锋柊鍒扮鐩樹笂锛屼互纭繚鏁版嵁鐨勬寔涔呮с + * + * 鍙傛暟鍒楄〃锛 + * buf锛欱ufferDesc 鏁版嵁绫诲瀷锛岃〃绀哄緟鍒锋柊鍒扮鐩樼殑缂撳啿鍖 + * reln锛歋MgrRelation 鏁版嵁绫诲瀷锛岃〃绀哄叧鑱旂殑瀛樺偍绠$悊鍣ㄥ叧绯伙紝濡傛灉涓篘ULL锛屽垯浠庣紦鍐插尯鐨勬爣绛句腑鑾峰彇 + * + * 娉ㄦ剰锛 + * 1. 濡傛灉鍦ㄥ埛鏂扮紦鍐插尯鏃跺嚭鐜伴敊璇紝鍑芥暟浼氳繘琛岄敊璇笂涓嬫枃鍥炶皟鍜岄敊璇鐞嗐 + * 2. 鍑芥暟浼氭鏌ユ槸鍚︽湁鍏朵粬绾跨▼宸茬粡鍒锋柊浜嗚缂撳啿鍖猴紝濡傛灉鏄紝鍒欎笉鍐嶉噸澶嶅埛鏂般 + */ void SegFlushBuffer(BufferDesc *buf, SMgrRelation reln) { if (!SegStartBufferIO(buf, false)) { @@ -354,7 +526,7 @@ void SegFlushBuffer(BufferDesc *buf, SMgrRelation reln) char *buf_to_write = NULL; RedoBufferInfo buffer_info; - + SegSpace *spc; if (reln == NULL || reln->seg_space == NULL) { spc = spc_open(buf->tag.rnode.spcNode, buf->tag.rnode.dbNode, false); @@ -368,27 +540,33 @@ void SegFlushBuffer(BufferDesc *buf, SMgrRelation reln) UnlockBufHdr(buf, buf_state); + // 鑾峰彇缂撳啿鍖虹殑鍒锋柊淇℃伅 GetFlushBufferInfo(buf, &buffer_info, &buf_state, WITH_NORMAL_CACHE); /* Must be segment-page metadata page */ SegmentCheck(PageIsSegmentVersion(buffer_info.pageinfo.page) || PageIsNew(buffer_info.pageinfo.page)); + // 濡傛灉鍚敤浜咶ORCE_FINISH_ENABLED锛屾洿鏂版渶澶х殑椤甸潰鍒锋柊LSN if (FORCE_FINISH_ENABLED) { update_max_page_flush_lsn(buffer_info.lsn, t_thrd.proc_cxt.MyProcPid, false); } + // 绛夊緟XLog鍒锋柊锛岀‘淇濇暟鎹啓鍏ョ鐩樹箣鍓嶅凡缁忔彁浜ゅ埌WAL鏃ュ織 XLogWaitFlush(buffer_info.lsn); /* page data encrypt */ buf_to_write = PageDataEncryptForBuffer(buffer_info.pageinfo.page, buf, true); + // 濡傛灉鏁版嵁鎸囬拡鍙戠敓鍙樺寲锛岄渶瑕侀噸鏂拌绠楁牎楠屽拰 if (unlikely(buf_to_write != (char *)buffer_info.pageinfo.page)) { PageSetChecksumInplace((Page)buf_to_write, buffer_info.blockinfo.blkno); } else { buf_to_write = PageSetChecksumCopy((Page)buf_to_write, buffer_info.blockinfo.blkno, true); } + // 灏嗘暟鎹啓鍏ョ鐩 seg_physical_write(spc, buf->tag.rnode, buf->tag.forkNum, buf->tag.blockNum, (char *)buf_to_write, false); + // 瀹屾垚缂撳啿鍖虹殑IO鎿嶄綔 SegTerminateBufferIO(buf, true, 0); /* Pop the error context stack, if it was set before */ @@ -396,41 +574,69 @@ void SegFlushBuffer(BufferDesc *buf, SMgrRelation reln) t_thrd.log_cxt.error_context_stack = errcontext.previous; } } - +/* + * 鍔熻兘锛氭姤鍛婃棤鏁堢殑椤甸潰 + * + * 鍙傛暟鍒楄〃锛 + * key锛歊epairBlockKey 鏁版嵁绫诲瀷锛岃〃绀烘棤鏁堥〉闈㈢殑鍏抽敭淇℃伅锛屽寘鎷枃浠惰妭鐐广佸垎鏀彿銆佸潡鍙风瓑銆 + * + * 娉ㄦ剰锛 + * 1. 淇鏃犳晥椤甸潰鐨勮繃绋嬩腑锛屼細璁板綍閿欒淇℃伅锛屽苟鍦ㄤ慨澶嶅畬鎴愬悗杈撳嚭璀﹀憡淇℃伅銆 + * 2. 濡傛灉涓嶆弧瓒抽〉淇鐨勬潯浠讹紝鍑芥暟灏嗚Е鍙戜竴涓敊璇紝鎶ュ憡鏃犳晥椤甸潰銆 + */ void ReportInvalidPage(RepairBlockKey key) { /* record bad page, wait the pagerepair thread repair the page */ - if (CheckVerionSupportRepair() && (AmStartupProcess() || AmPageRedoWorker()) && - IsPrimaryClusterStandbyDN() && g_instance.repair_cxt.support_repair) { + if (CheckVerionSupportRepair() && (AmStartupProcess() || AmPageRedoWorker()) && IsPrimaryClusterStandbyDN() && + g_instance.repair_cxt.support_repair) { + // 濡傛灉鐜鏀寔椤典慨澶嶏紝涓斿綋鍓嶈繘绋嬫槸鍚姩杩涚▼鎴栭〉閲嶅仛宸ヤ綔鑰咃紝骞朵笖鏄富闆嗙兢鐨勫鐢ㄦ暟鎹妭鐐癸紝骞朵笖椤典慨澶嶅姛鑳借鍚敤 XLogPhyBlock pblk_bak = {0}; - RedoPageRepairCallBack(key, pblk_bak); - log_invalid_page(key.relfilenode, key.forknum, key.blocknum, CRC_CHECK_ERROR, NULL); - ereport(WARNING, (errcode(ERRCODE_DATA_CORRUPTED), - errmsg("invalid page in block %u of relation %s", - key.blocknum, relpathperm(key.relfilenode, key.forknum)))); + RedoPageRepairCallBack(key, pblk_bak); // 璋冪敤椤典慨澶嶅洖璋冨嚱鏁帮紝杩涜淇鎿嶄綔 + log_invalid_page(key.relfilenode, key.forknum, key.blocknum, CRC_CHECK_ERROR, NULL); // 璁板綍鏃犳晥椤甸潰鐨勪俊鎭 + ereport(WARNING, + (errcode(ERRCODE_DATA_CORRUPTED), errmsg("invalid page in block %u of relation %s", key.blocknum, + relpathperm(key.relfilenode, key.forknum)))); return; } - ereport(ERROR, (errcode(ERRCODE_DATA_CORRUPTED), errmsg("invalid page in block %u of relation %s", - key.blocknum, relpathperm(key.relfilenode, key.forknum)))); + // 濡傛灉涓嶆弧瓒抽〉淇鏉′欢锛屾姤鍛婃棤鏁堥〉闈㈢殑閿欒 + ereport(ERROR, (errcode(ERRCODE_DATA_CORRUPTED), errmsg("invalid page in block %u of relation %s", key.blocknum, + relpathperm(key.relfilenode, key.forknum)))); return; } - +/* + * 鍔熻兘锛氬揩閫熻鍙栫紦鍐插尯鐨勫唴瀹 + * + * 鍙傛暟鍒楄〃锛 + * spc锛歋egSpace 鏁版嵁绫诲瀷锛岃〃绀烘瀛樺偍绌洪棿銆 + * rnode锛歊elFileNode 鏁版嵁绫诲瀷锛岃〃绀烘枃浠惰妭鐐逛俊鎭 + * forkNum锛欶orkNumber 鏁版嵁绫诲瀷锛岃〃绀哄垎鏀彿銆 + * blockNum锛欱lockNumber 鏁版嵁绫诲瀷锛岃〃绀鸿璇诲彇鐨勫潡鍙枫 + * mode锛歊eadBufferMode 鏁版嵁绫诲瀷锛岃〃绀鸿鍙栫紦鍐插尯鐨勬ā寮忥紝鍖呮嫭闆跺~鍏呭拰閿佸畾绛夈 + * + * 娉ㄦ剰锛 + * 1. 濡傛灉鍧楀彿涓嶅瓨鍦ㄤ簬缂撳啿姹犱腑锛屽嚱鏁颁細鏍规嵁妯″紡杩涜鍒濆鍖栵紝鍖呮嫭闆跺~鍏呮垨璇诲彇瀛樺偍浠嬭川涓殑鏁版嵁銆 + * 2. 濡傛灉璇诲彇鍒扮殑鍧楁棤鏁堬紝鍑芥暟浼氳Е鍙戜竴涓敊璇姤鍛娿 + */ Buffer ReadBufferFast(SegSpace *spc, RelFileNode rnode, ForkNumber forkNum, BlockNumber blockNum, ReadBufferMode mode) { bool found = false; + // 灏濊瘯鍦ㄧ紦鍐叉睜涓垎閰嶆垨鑾峰彇鎸囧畾鍧楀彿鐨勭紦鍐插尯鎻忚堪绗 BufferDesc *bufHdr = SegBufferAlloc(spc, rnode, forkNum, blockNum, &found); - if (!found) { + if (!found) { // 濡傛灉鍧楀彿鍦ㄧ紦鍐叉睜涓笉瀛樺湪 SegmentCheck(!(pg_atomic_read_u32(&bufHdr->state) & BM_VALID)); char *bufBlock = (char *)BufHdrGetBlock(bufHdr); if (mode == RBM_ZERO_AND_LOCK || mode == RBM_ZERO_AND_CLEANUP_LOCK) { + // 闆跺~鍏呮ā寮忔垨闆跺~鍏呭苟閿佸畾妯″紡 errno_t er = memset_s((char *)bufBlock, BLCKSZ, 0, BLCKSZ); securec_check(er, "", ""); } else { + // 浠庡瓨鍌ㄤ粙璐ㄤ腑璇诲彇鍧楃殑鍐呭 seg_physical_read(spc, rnode, forkNum, blockNum, bufBlock); if (!PageIsVerified(bufBlock, blockNum)) { + // 楠岃瘉璇诲彇鐨勫潡鏄惁鏈夋晥锛屽鏋滄棤鏁堝垯鎶ュ憡閿欒 RepairBlockKey key; key.relfilenode = rnode; key.forknum = forkNum; @@ -439,58 +645,107 @@ Buffer ReadBufferFast(SegSpace *spc, RelFileNode rnode, ForkNumber forkNum, Bloc return InvalidBuffer; } if (!PageIsSegmentVersion(bufBlock) && !PageIsNew(bufBlock)) { + // 妫鏌ラ〉闈㈢殑鐗堟湰鏄惁涓庢瀛樺偍鐗堟湰鍏煎锛屽鏋滀笉鍏煎鍒欐姤鍛婇敊璇 ereport(PANIC, (errmsg("Read segment-page metadata buffer, block %u of relation %s, but page version is %d", blockNum, relpathperm(rnode, forkNum), PageGetPageLayoutVersion(bufBlock)))); } } - bufHdr->lsn_on_disk = PageGetLSN(bufBlock); + bufHdr->lsn_on_disk = PageGetLSN(bufBlock); // 璁板綍鍧椾笂鐨凩SN #ifdef USE_ASSERT_CHECKING - bufHdr->lsn_dirty = InvalidXLogRecPtr; + bufHdr->lsn_dirty = InvalidXLogRecPtr; // 鍒濆鍖朙SN涓烘棤鏁堝 #endif - SegTerminateBufferIO(bufHdr, false, BM_VALID); + SegTerminateBufferIO(bufHdr, false, BM_VALID); // 缁堟缂撳啿鍖虹殑IO鎿嶄綔 } if (mode == RBM_ZERO_AND_LOCK || mode == RBM_ZERO_AND_CLEANUP_LOCK) { + // 濡傛灉妯″紡瑕佹眰閿佸畾缂撳啿鍖猴紝鍒欒繘琛岄攣瀹氭搷浣 LWLockAcquire(BufferDescriptorGetContentLock(bufHdr), LW_EXCLUSIVE); } - SegmentCheck(SegBufferIsPinned(bufHdr)); + SegmentCheck(SegBufferIsPinned(bufHdr)); // 纭繚缂撳啿鍖鸿閿佸畾 return BufferDescriptorGetBuffer(bufHdr); } - +/* + * 鍔熻兘锛氳幏鍙栦袱涓交閲忕骇閿佺殑浜掓枼閿 + * + * 鍙傛暟鍒楄〃锛 + * new_partition_lock锛氭柊鐨勮交閲忕骇閿佺殑鎸囬拡 + * old_partition_lock锛氭棫鐨勮交閲忕骇閿佺殑鎸囬拡 + * + * 娉ㄦ剰锛 + * 1. 杩欎釜鍑芥暟鐨勭洰鐨勬槸纭繚鍦ㄨ幏鍙栭攣鏃朵笉浼氬嚭鐜版閿侊紝鎸夌収閿佸湴鍧鐨勫ぇ灏忛『搴忚幏鍙栭攣銆 + * 2. 濡傛灉涓や釜閿佺殑鍦板潃鐩稿悓锛岃鏄庡彧鏈変竴涓垎鍖猴紝鍙渶鑾峰彇涓涓攣銆 + */ void LockTwoLWLock(LWLock *new_partition_lock, LWLock *old_partition_lock) { if (old_partition_lock < new_partition_lock) { + // 鍏堣幏鍙栬緝灏忕殑閿侊紝鍐嶈幏鍙栬緝澶х殑閿 (void)LWLockAcquire(old_partition_lock, LW_EXCLUSIVE); (void)LWLockAcquire(new_partition_lock, LW_EXCLUSIVE); } else if (old_partition_lock > new_partition_lock) { + // 鍏堣幏鍙栬緝灏忕殑閿侊紝鍐嶈幏鍙栬緝澶х殑閿 (void)LWLockAcquire(new_partition_lock, LW_EXCLUSIVE); (void)LWLockAcquire(old_partition_lock, LW_EXCLUSIVE); } else { /* only one partition, only one lock */ + // 濡傛灉涓や釜閿佺殑鍦板潃鐩稿悓锛岃鏄庡彧鏈変竴涓垎鍖猴紝鍙渶鑾峰彇涓涓攣銆 (void)LWLockAcquire(new_partition_lock, LW_EXCLUSIVE); } } +/* + * 鍔熻兘锛氬湪鍝堝笇琛ㄤ腑鏌ユ壘缂撳啿鍖烘弿杩扮 + * + * 鍙傛暟鍒楄〃锛 + * buf_id锛氳鏌ユ壘鐨勭紦鍐插尯鐨勬爣璇嗙銆 + * new_partition_lock锛氭柊鐨勮交閲忕骇閿佺殑鎸囬拡銆 + * foundPtr锛氱敤浜庢寚绀烘槸鍚︽壘鍒扮紦鍐插尯鎻忚堪绗︾殑鎸囬拡銆 -BufferDesc * FoundBufferInHashTable(int buf_id, LWLock *new_partition_lock, bool *foundPtr) + * 娉ㄦ剰锛 + * 1. 杩欎釜鍑芥暟鐢ㄤ簬鏌ユ壘鍜岄攣瀹氱紦鍐插尯鎻忚堪绗︼紝浠ヤ究杩涜鍚庣画鎿嶄綔銆 + * 2. 濡傛灉缂撳啿鍖烘弿杩扮鏈夋晥锛屽垯鍑芥暟灏嗛噴鏀句竴涓交閲忕骇閿侊紝骞跺皢鈥渇oundPtr鈥濊缃负鈥渢rue鈥濄 + * 3. 濡傛灉缂撳啿鍖烘弿杩扮鏃犳晥锛屽垯鍑芥暟浼氬皾璇曞惎鍔ㄧ紦鍐插尯鐨処O鎿嶄綔锛屽苟灏嗏渇oundPtr鈥濊缃负鈥渇alse鈥濄 + */ +BufferDesc *FoundBufferInHashTable(int buf_id, LWLock *new_partition_lock, bool *foundPtr) { + // 鑾峰彇缂撳啿鍖烘弿杩扮 BufferDesc *buf = GetBufferDescriptor(buf_id); + // 灏濊瘯閿佸畾锛圥in锛夌紦鍐插尯骞跺垽鏂叾鏄惁鏈夋晥 bool valid = SegPinBuffer(buf); + // 閲婃斁鏂扮殑杞婚噺绾ч攣 LWLockRelease(new_partition_lock); + // 璁剧疆鈥渇oundPtr鈥濅负true *foundPtr = true; + // 濡傛灉缂撳啿鍖烘棤鏁 if (!valid) { + // 灏濊瘯鍚姩缂撳啿鍖虹殑IO鎿嶄綔 if (SegStartBufferIO(buf, true)) { + // 濡傛灉鎴愬姛鍚姩IO鎿嶄綔锛屽垯璁剧疆鈥渇oundPtr鈥濅负false *foundPtr = false; } } + // 杩斿洖缂撳啿鍖烘弿杩扮 return buf; } +/* + * 鍔熻兘锛氬垎閰嶄竴涓柊鐨勭紦鍐插尯骞惰繑鍥炲叾缂撳啿鍖烘弿杩扮 + * + * 鍙傛暟鍒楄〃锛 + * spc锛氭绌洪棿锛圫egSpace锛夋寚閽堬紝鐢ㄤ簬琛ㄧず缂撳啿鍖烘墍灞炵殑娈电┖闂淬 + * rnode锛氭枃浠惰妭鐐癸紙RelFileNode锛夈 + * forkNum锛氬垎鍙夊彿锛團orkNumber锛夈 + * blockNum锛氬潡鍙凤紙BlockNumber锛夈 + * foundPtr锛氱敤浜庢寚绀烘槸鍚︽壘鍒扮紦鍐插尯鎻忚堪绗︾殑鎸囬拡銆 -BufferDesc *SegBufferAlloc(SegSpace *spc, RelFileNode rnode, ForkNumber forkNum, BlockNumber blockNum, - bool *foundPtr) + * 娉ㄦ剰锛 + * 1. 杩欎釜鍑芥暟棣栧厛灏濊瘯鍦ㄥ搱甯岃〃涓煡鎵剧紦鍐插尯鎻忚堪绗︼紝濡傛灉鎵惧埌锛屽垯杩斿洖璇ユ弿杩扮銆 + * 2. 濡傛灉娌℃湁鎵惧埌缂撳啿鍖烘弿杩扮锛屽嚱鏁板皢鍒嗛厤涓涓柊鐨勭紦鍐插尯鎻忚堪绗︼紝骞舵爣璁颁负鏂扮紦鍐插尯銆 + * 3. 鍦ㄥ皾璇曟煡鎵炬垨鍒嗛厤缂撳啿鍖烘弿杩扮鏃讹紝鍑芥暟浼氭牴鎹渶瑕佸惎鍔ㄧ紦鍐插尯鐨処O鎿嶄綔銆 + * 4. 鍑芥暟鏈缁堣繑鍥炵紦鍐插尯鎻忚堪绗︼紝骞堕氳繃鈥渇oundPtr鈥濇寚绀烘槸鍚︽壘鍒版弿杩扮銆 + */ +BufferDesc *SegBufferAlloc(SegSpace *spc, RelFileNode rnode, ForkNumber forkNum, BlockNumber blockNum, bool *foundPtr) { BufferDesc *buf; BufferTag new_tag, old_tag; @@ -501,29 +756,37 @@ BufferDesc *SegBufferAlloc(SegSpace *spc, RelFileNode rnode, ForkNumber forkNum, LWLock *old_partition_lock; bool old_flag_valid; + // 鍒濆鍖栨柊鐨勭紦鍐插尯鏍囩 INIT_BUFFERTAG(new_tag, rnode, forkNum, blockNum); + // 璁$畻鏂扮紦鍐插尯鏍囩鐨勫搱甯屽煎苟鑾峰彇鐩稿簲鐨勫垎鍖洪攣 new_hash = BufTableHashCode(&new_tag); new_partition_lock = BufMappingPartitionLock(new_hash); + // 灏濊瘯浠ュ叡浜ā寮忚幏鍙栧垎鍖洪攣骞舵煡鎵剧紦鍐插尯鎻忚堪绗 LWLockAcquire(new_partition_lock, LW_SHARED); int buf_id = BufTableLookup(&new_tag, new_hash); + // 濡傛灉鎵惧埌缂撳啿鍖烘弿杩扮锛屽垯杩斿洖瀹 if (buf_id >= 0) { return FoundBufferInHashTable(buf_id, new_partition_lock, foundPtr); } + // 鏍囪鏈壘鍒扮紦鍐插尯鎻忚堪绗︼紝骞堕噴鏀惧垎鍖洪攣 *foundPtr = FALSE; LWLockRelease(new_partition_lock); for (;;) { + // 浠庣瓥鐣ヤ腑鑾峰彇涓涓紦鍐插尯鎻忚堪绗 buf = SegStrategyGetBuffer(&buf_state); SegmentCheck(BUF_STATE_GET_REFCOUNT(buf_state) == 0); old_flags = buf_state & BUF_FLAG_MASK; + // 閿佸畾锛圥in锛夋柊鐨勭紦鍐插尯 SegPinBufferLocked(buf, &new_tag); + // 濡傛灉缂撳啿鍖烘爣璁颁负鑴忥紙BM_DIRTY锛夛紝鍒欐墽琛岀浉搴旀搷浣 if (old_flags & BM_DIRTY) { /* backend should not flush dirty pages if working version less than DW_SUPPORT_NEW_SINGLE_FLUSH */ if (!backend_can_flush_dirty_page()) { @@ -548,6 +811,7 @@ BufferDesc *SegBufferAlloc(SegSpace *spc, RelFileNode rnode, ForkNumber forkNum, old_hash = BufTableHashCode(&old_tag); old_partition_lock = BufMappingPartitionLock(old_hash); + // 鑾峰彇涓や釜鍒嗗尯閿侊紝濡傛灉鏍囩鏈夋晥鍒欒幏鍙栨棫鍒嗗尯閿侊紝鍚﹀垯鍙幏鍙栨柊鍒嗗尯閿 LockTwoLWLock(new_partition_lock, old_partition_lock); } else { /* if it wasn't valid, we need only the new partition */ @@ -557,9 +821,11 @@ BufferDesc *SegBufferAlloc(SegSpace *spc, RelFileNode rnode, ForkNumber forkNum, old_partition_lock = NULL; } + // 鍦ㄥ搱甯岃〃涓彃鍏ユ柊鏍囩锛屽鏋滄垚鍔熷垯杩斿洖缂撳啿鍖烘弿杩扮 buf_id = BufTableInsert(&new_tag, new_hash, buf->buf_id); if (buf_id >= 0) { + // 閲婃斁缂撳啿鍖烘弿杩扮骞惰繑鍥炲凡鎵惧埌鐨勬弿杩扮 SegUnpinBuffer(buf); if (old_flag_valid && old_partition_lock != new_partition_lock) LWLockRelease(old_partition_lock); @@ -567,6 +833,7 @@ BufferDesc *SegBufferAlloc(SegSpace *spc, RelFileNode rnode, ForkNumber forkNum, return FoundBufferInHashTable(buf_id, new_partition_lock, foundPtr); } + // 濡傛灉缂撳啿鍖鸿寮曠敤锛屾垨鑰呮爣璁颁负鑴忥紙BM_DIRTY锛夛紝鍒欑户缁惊鐜 buf_state = LockBufHdr(buf); old_flags = buf_state & BUF_FLAG_MASK; @@ -582,6 +849,7 @@ BufferDesc *SegBufferAlloc(SegSpace *spc, RelFileNode rnode, ForkNumber forkNum, SegUnpinBuffer(buf); } + // 鏇存柊缂撳啿鍖烘弿杩扮鐨勬爣绛惧拰鐘舵 buf->tag = new_tag; buf_state &= ~(BM_VALID | BM_DIRTY | BM_JUST_DIRTIED | BM_CHECKPOINT_NEEDED | BM_IO_ERROR | BM_PERMANENT | BUF_USAGECOUNT_MASK); @@ -589,19 +857,30 @@ BufferDesc *SegBufferAlloc(SegSpace *spc, RelFileNode rnode, ForkNumber forkNum, UnlockBufHdr(buf, buf_state); if (old_flag_valid) { + // 浠庡搱甯岃〃涓垹闄ゆ棫鏍囩 BufTableDelete(&old_tag, old_hash); if (old_partition_lock != new_partition_lock) { LWLockRelease(old_partition_lock); } } + // 閲婃斁鏂板垎鍖洪攣 LWLockRelease(new_partition_lock); + // 璁剧疆鈥渇oundPtr鈥濅负缂撳啿鍖烘槸鍚﹂渶瑕佸惎鍔↖O鎿嶄綔鐨勬爣蹇 *foundPtr = !SegStartBufferIO(buf, true); + // 杩斿洖缂撳啿鍖烘弿杩扮 return buf; } static uint32 next_victim_buffer = 0; - +/* + * 鍔熻兘锛欳lock绠楁硶鐨勪竴涓楠わ紝鐢ㄤ簬閫夋嫨涓嬩竴涓娣樻卑鐨勭紦鍐插尯 + * + * 娉ㄦ剰锛 + * 1. Clock绠楁硶鏄竴绉嶇敤浜庣紦鍐插尯娣樻卑绛栫暐鐨勭畻娉曪紝閫氬父鐢ㄤ簬绠$悊缂撳啿鍖烘睜涓殑缂撳啿鍖恒 + * 2. 璇ュ嚱鏁伴氳繃鍘熷瓙鎿嶄綔浠巒ext_victim_buffer涓幏鍙栦竴涓掑鐨勬暣鏁帮紝琛ㄧず涓嬩竴涓娣樻卑鐨勭紦鍐插尯銆 + * 3. 濡傛灉璁$畻寰楀埌鐨剉ictim瓒呰繃浜哠EGMENT_BUFFER_NUM锛堢紦鍐插尯姹犵殑澶у皬锛夛紝鍒欏皢鍏堕噸鏂版槧灏勫埌0浠ヤ繚鎸佸湪鏈夋晥鑼冨洿鍐呫 + */ static inline uint32 ClockSweepTick(void) { uint32 victim = pg_atomic_fetch_add_u32(&next_victim_buffer, 1); @@ -610,73 +889,102 @@ static inline uint32 ClockSweepTick(void) } return victim; } - -static BufferDesc* get_segbuf_from_candidate_list(uint32* buf_state) +/* + * 鍔熻兘锛氫粠鍊欓夌紦鍐插尯鍒楄〃涓幏鍙栦竴涓紦鍐插尯鎻忚堪绗 + * + * 鍙傛暟鍒楄〃锛 + * buf_state锛氭寚鍚戠敤浜庡瓨鍌ㄧ紦鍐插尯鐘舵佺殑鎸囬拡锛岄氳繃姝ゅ弬鏁拌繑鍥炵紦鍐插尯鐨勭姸鎬 + * + * 娉ㄦ剰锛 + * 1. 璇ュ嚱鏁扮敤浜庝粠鍊欓夌紦鍐插尯鍒楄〃涓幏鍙栦竴涓彲鐢ㄧ殑缂撳啿鍖烘弿杩扮锛岄氬父鐢ㄤ簬楂樻晥鐨勭紦鍐插尯绠$悊銆 + * 2. 濡傛灉ENABLE_INCRE_CKPT寮鍚紝骞朵笖鏈夐〉鍐欏叆杩涚▼鍦ㄨ繍琛岋紝鍑芥暟浼氬皾璇曚粠鍊欓夌紦鍐插尯鍒楄〃涓幏鍙栫紦鍐插尯銆 + * 3. 鍑芥暟浼氶亶鍘嗗欓夌紦鍐插尯鍒楄〃锛屽苟鎵惧埌涓涓弧瓒虫潯浠剁殑鍙敤缂撳啿鍖猴紝杩斿洖鍏舵弿杩扮銆 + * 4. 鍊欓夌紦鍐插尯鐨勬潯浠跺寘鎷細寮曠敤璁℃暟涓0銆佷笉鏄厓鏁版嵁缂撳啿鍖恒佹湭鏍囪涓鸿剰缂撳啿鍖恒 + * 5. 濡傛灉娌℃湁鎵惧埌婊¤冻鏉′欢鐨勭紦鍐插尯锛屽嚱鏁拌繑鍥濶ULL銆 + */ +static BufferDesc *get_segbuf_from_candidate_list(uint32 *buf_state) { - BufferDesc* buf = NULL; - uint32 local_buf_state; - int buf_id = 0; + BufferDesc *buf = NULL; // 缂撳啿鍖烘弿杩扮 + uint32 local_buf_state; // 鏈湴缂撳啿鍖虹姸鎬 + int buf_id = 0; // 缂撳啿鍖烘爣璇嗙 + // 濡傛灉鍚敤澧為噺妫鏌ョ偣骞朵笖鏈夐〉鍐欏叆杩涚▼姝e湪杩愯 if (ENABLE_INCRE_CKPT && pg_atomic_read_u32(&g_instance.ckpt_cxt_ctl->current_page_writer_count) > 0) { int list_num = g_instance.ckpt_cxt_ctl->pgwr_procs.sub_num; - volatile PgBackendStatus* beentry = t_thrd.shemem_ptr_cxt.MyBEEntry; + volatile PgBackendStatus *beentry = t_thrd.shemem_ptr_cxt.MyBEEntry; int list_id = beentry->st_tid > 0 ? (beentry->st_tid % list_num) : (beentry->st_sessionid % list_num); + // 閬嶅巻椤靛啓鍏ヨ繘绋嬬殑瀛愮嚎绋 for (int i = 0; i < list_num; i++) { /* the pagewriter sub thread store normal buffer pool, sub thread starts from 1 */ int thread_id = (list_id + i) % list_num + 1; Assert(thread_id > 0 && thread_id <= list_num); + // 浠庡欓夌紦鍐插尯鍒楄〃涓幏鍙栦竴涓紦鍐插尯鏍囪瘑绗 while (seg_candidate_buf_pop(&buf_id, thread_id)) { - buf = GetBufferDescriptor(buf_id); - local_buf_state = LockBufHdr(buf); + buf = GetBufferDescriptor(buf_id); // 鑾峰彇缂撳啿鍖烘弿杩扮 + local_buf_state = LockBufHdr(buf); // 閿佸畾缂撳啿鍖烘弿杩扮鐨勭姸鎬 SegmentCheck(buf_id >= SegmentBufferStartID); + // 濡傛灉璇ョ紦鍐插尯宸茶鏍囪涓哄欓 if (g_instance.ckpt_cxt_ctl->candidate_free_map[buf_id]) { g_instance.ckpt_cxt_ctl->candidate_free_map[buf_id] = false; - bool available_buffer = BUF_STATE_GET_REFCOUNT(local_buf_state) == 0 - && !(local_buf_state & BM_IS_META) - && !(local_buf_state & BM_DIRTY); + bool available_buffer = BUF_STATE_GET_REFCOUNT(local_buf_state) == 0 && + !(local_buf_state & BM_IS_META) && !(local_buf_state & BM_DIRTY); if (available_buffer) { - *buf_state = local_buf_state; - return buf; + *buf_state = local_buf_state; // 瀛樺偍缂撳啿鍖虹殑鐘舵 + return buf; // 杩斿洖婊¤冻鏉′欢鐨勭紦鍐插尯鎻忚堪绗 } } - UnlockBufHdr(buf, local_buf_state); + UnlockBufHdr(buf, local_buf_state); // 瑙i攣缂撳啿鍖烘弿杩扮 } } - wakeup_pagewriter_thread(); + wakeup_pagewriter_thread(); // 鍞ら啋椤靛啓鍏ヨ繘绋 } - return NULL; + return NULL; // 鏈壘鍒版弧瓒虫潯浠剁殑缂撳啿鍖猴紝杩斿洖NULL } /* lock the buffer descriptor before return */ const int RETRY_COUNT = 3; -static BufferDesc *SegStrategyGetBuffer(uint32 *buf_state) +/* + * 鍔熻兘锛氭牴鎹瓥鐣ヨ幏鍙栦竴涓紦鍐插尯鎻忚堪绗 + * + * 鍙傛暟鍒楄〃锛 + * buf_state锛氭寚鍚戠敤浜庡瓨鍌ㄧ紦鍐插尯鐘舵佺殑鎸囬拡锛岄氳繃姝ゅ弬鏁拌繑鍥炵紦鍐插尯鐨勭姸鎬 + * + * 娉ㄦ剰锛 + * 1. 璇ュ嚱鏁扮敤浜庢牴鎹紦鍐插尯绛栫暐鑾峰彇涓涓彲鐢ㄧ殑缂撳啿鍖烘弿杩扮銆 + * 2. 棣栧厛灏濊瘯浠庡欓夌紦鍐插尯鍒楄〃涓幏鍙栧彲鐢ㄧ殑缂撳啿鍖猴紝濡傛灉鑾峰彇鎴愬姛锛屽垯杩斿洖銆 + * 3. 濡傛灉鍊欓夌紦鍐插尯鍒楄〃涓病鏈夊彲鐢ㄧ殑缂撳啿鍖猴紝鍑芥暟浼氬惊鐜皾璇曢氳繃ClockSweepTick绛栫暐鏉ヨ幏鍙栧彲鐢ㄧ紦鍐插尯銆 + * 4. 鑾峰彇鍒扮殑缂撳啿鍖哄繀椤绘弧瓒冲紩鐢ㄨ鏁颁负0鐨勬潯浠讹紝鍚﹀垯浼氱户缁皾璇曠洿鍒版垚鍔熸垨杈惧埌鏈澶у皾璇曟鏁般 + * 5. 濡傛灉鑾峰彇浜嗕竴涓彲鐢ㄧ紦鍐插尯锛屽垯灏嗗叾鐘舵佸瓨鍌ㄥ湪buf_state鍙傛暟涓紝骞惰繑鍥炶缂撳啿鍖虹殑鎻忚堪绗︺ + * 6. 濡傛灉娌℃湁鍙敤缂撳啿鍖猴紝鍒欐姏鍑洪敊璇彁绀衡渘o unpinned buffers available鈥濄 + */ +static BufferDesc *SegStrategyGetBuffer(uint32 *buf_state) { // todo: add free list - BufferDesc *buf = get_segbuf_from_candidate_list(buf_state); - int try_counter = SEGMENT_BUFFER_NUM * RETRY_COUNT; + BufferDesc *buf = get_segbuf_from_candidate_list(buf_state); // 灏濊瘯浠庡欓夌紦鍐插尯鍒楄〃涓幏鍙栫紦鍐插尯 + int try_counter = SEGMENT_BUFFER_NUM * RETRY_COUNT; // 閲嶈瘯璁℃暟鍣 if (buf != NULL) { (void)pg_atomic_fetch_add_u64(&g_instance.ckpt_cxt_ctl->seg_get_buf_num_candidate_list, 1); - return buf; + return buf; // 濡傛灉鎴愬姛鑾峰彇浜嗗欓夌紦鍐插尯锛屽垯杩斿洖 } for (;;) { - int buf_id = BufferIdOfSegmentBuffer(ClockSweepTick()); - buf = GetBufferDescriptor(buf_id); + int buf_id = BufferIdOfSegmentBuffer(ClockSweepTick()); // 鏍规嵁ClockSweep绛栫暐鑾峰彇缂撳啿鍖篒D + buf = GetBufferDescriptor(buf_id); // 鑾峰彇缂撳啿鍖烘弿杩扮 - uint32 state = LockBufHdr(buf); + uint32 state = LockBufHdr(buf); // 閿佸畾缂撳啿鍖烘弿杩扮鐨勭姸鎬 - if (BUF_STATE_GET_REFCOUNT(state) == 0) { - *buf_state = state; + if (BUF_STATE_GET_REFCOUNT(state) == 0) { // 濡傛灉缂撳啿鍖哄紩鐢ㄨ鏁颁负0 + *buf_state = state; // 瀛樺偍缂撳啿鍖虹姸鎬 (void)pg_atomic_fetch_add_u64(&g_instance.ckpt_cxt_ctl->seg_get_buf_num_clock_sweep, 1); - return buf; + return buf; // 杩斿洖鍙敤缂撳啿鍖烘弿杩扮 } else if (--try_counter == 0) { - UnlockBufHdr(buf, state); + UnlockBufHdr(buf, state); // 瑙i攣缂撳啿鍖烘弿杩扮 ereport(ERROR, (errcode(ERRCODE_INVALID_BUFFER), (errmsg("no unpinned buffers available")))); } - UnlockBufHdr(buf, state); + UnlockBufHdr(buf, state); // 瑙i攣缂撳啿鍖烘弿杩扮 ereport(DEBUG5, (errmodule(MOD_SEGMENT_PAGE), (errmsg("SegStrategyGetBuffer get a pinned buffer, %d, buffer tag <%u, %u, %u, %u>.%d.%u, state %u", @@ -684,7 +992,19 @@ static BufferDesc *SegStrategyGetBuffer(uint32 *buf_state) buf->tag.rnode.bucketNode, buf->tag.forkNum, buf->tag.blockNum, state)))); } } - +/* + * 鍔熻兘锛氶噴鏀炬寚瀹氬瓨鍌ㄧ┖闂寸殑鍏冩暟鎹紦鍐插尯 + * + * 鍙傛暟鍒楄〃锛 + * spcNode锛氳閲婃斁鐨勫瓨鍌ㄧ┖闂寸殑Oid + * dbNode锛氳閲婃斁鐨勬暟鎹簱鐨凮id + * + * 娉ㄦ剰锛 + * 1. 璇ュ嚱鏁扮敤浜庨噴鏀炬寚瀹氬瓨鍌ㄧ┖闂翠腑鐨勫厓鏁版嵁缂撳啿鍖恒 + * 2. 棣栧厛鍏抽棴鎵鏈夋澶存枃浠躲 + * 3. 鐒跺悗閬嶅巻鎵鏈夌紦鍐插尯鎻忚堪绗︼紝鏌ユ壘骞堕噴鏀句笌鎸囧畾瀛樺偍绌洪棿鍜屾暟鎹簱鍖归厤鐨勫厓鏁版嵁缂撳啿鍖恒 + * 4. 瀵逛簬鍖归厤鐨勭紦鍐插尯锛屽鏋滃叾鐘舵佷负鈥淏M_DIRTY鈥濆拰鈥淏M_VALID鈥濓紝鍒欏皢鍏舵爣璁颁负鏃犳晥锛屽惁鍒欒В閿佺紦鍐插尯銆 + */ void SegDropSpaceMetaBuffers(Oid spcNode, Oid dbNode) { int i; @@ -692,7 +1012,7 @@ void SegDropSpaceMetaBuffers(Oid spcNode, Oid dbNode) // Release segment head buffer smgrcloseall(); for (i = SegmentBufferStartID; i < TOTAL_BUFFER_NUM; i++) { - BufferDesc *buf_desc = GetBufferDescriptor(i); + BufferDesc *buf_desc = GetBufferDescriptor(i); // 鑾峰彇缂撳啿鍖烘弿杩扮 uint32 buf_state; /* * As in DropRelFileNodeBuffers, an unlocked precheck should be safe @@ -702,19 +1022,26 @@ void SegDropSpaceMetaBuffers(Oid spcNode, Oid dbNode) continue; } - buf_state = LockBufHdr(buf_desc); - if (buf_desc->tag.rnode.spcNode == spcNode && buf_desc->tag.rnode.dbNode == dbNode && - (buf_state & BM_DIRTY) && (buf_state & BM_VALID)) { + buf_state = LockBufHdr(buf_desc); // 閿佸畾缂撳啿鍖烘弿杩扮鐨勭姸鎬 + if (buf_desc->tag.rnode.spcNode == spcNode && buf_desc->tag.rnode.dbNode == dbNode && (buf_state & BM_DIRTY) && + (buf_state & BM_VALID)) { InvalidateBuffer(buf_desc); /* releases spinlock */ } else { - UnlockBufHdr(buf_desc, buf_state); + UnlockBufHdr(buf_desc, buf_state); // 瑙i攣缂撳啿鍖烘弿杩扮 } } } - +/* + * 鍔熻兘锛氬埛鏂板崟涓缂撳啿鍖 + * + * 鍙傛暟鍒楄〃锛 + * buffer锛氳鍒锋柊鐨勭紦鍐插尯鏍囪瘑绗︺ + * + */ void FlushOneSegmentBuffer(Buffer buffer) { BufferDesc *buf_desc = GetBufferDescriptor(buffer - 1); + // 妫鏌ョ紦鍐插尯涓殑椤甸潰鏄惁涓烘鐗堟湰椤甸潰鎴栨柊椤甸潰锛屽惁鍒欏紩鍙 PANIC 閿欒 if (!PageIsSegmentVersion(BufferGetBlock(buffer)) && !PageIsNew(BufferGetBlock(buffer))) { ereport(PANIC, (errmsg("Flush segment-page metadata buffer, block %u of relation %s, but page version is %d", buf_desc->tag.blockNum, relpathperm(buf_desc->tag.rnode, buf_desc->tag.forkNum), @@ -724,37 +1051,46 @@ void FlushOneSegmentBuffer(Buffer buffer) if (dw_enabled() && pg_atomic_read_u32(&g_instance.ckpt_cxt_ctl->current_page_writer_count) > 0) { uint32 pos = 0; bool flush_old_file = false; + // 鑾峰彇 Double Write 浣嶇疆 pos = seg_dw_single_flush(buf_desc, &flush_old_file); t_thrd.proc->dw_pos = pos; t_thrd.proc->flush_new_dw = !flush_old_file; + // 璋冪敤 SegFlushBuffer 鍑芥暟鍒锋柊缂撳啿鍖 SegFlushBuffer(buf_desc, NULL); if (flush_old_file) { g_instance.dw_single_cxt.recovery_buf.single_flush_state[pos] = true; } else { g_instance.dw_single_cxt.single_flush_state[pos] = true; } - t_thrd.proc->dw_pos = -1; + t_thrd.proc->dw_pos = -1; // 娓呴櫎 Double Write 浣嶇疆 } else { - SegFlushBuffer(buf_desc, NULL); + SegFlushBuffer(buf_desc, NULL); // 鐩存帴璋冪敤 SegFlushBuffer 鍑芥暟鍒锋柊缂撳啿鍖 } } /* Flush a data buffer. If double write is on, it will invoke single-page-dw first. Caller should lock the buffer. */ +/* + * 鍔熻兘锛氬埛鏂板崟涓紦鍐插尯锛屽寘鎷 Double Write 鎿嶄綔 + * + * 鍙傛暟鍒楄〃锛 + * buf_desc锛氳鍒锋柊鐨勭紦鍐插尯鎻忚堪绗︺ + */ void FlushOneBufferIncludeDW(BufferDesc *buf_desc) { if (dw_enabled()) { bool flush_old_file = false; - uint32 pos = seg_dw_single_flush(buf_desc, &flush_old_file); + uint32 pos = seg_dw_single_flush(buf_desc, &flush_old_file); // 鑾峰彇 Double Write 浣嶇疆 t_thrd.proc->dw_pos = pos; t_thrd.proc->flush_new_dw = !flush_old_file; + // 璋冪敤 FlushBuffer 鍑芥暟鍒锋柊缂撳啿鍖 FlushBuffer(buf_desc, NULL); if (flush_old_file) { g_instance.dw_single_cxt.recovery_buf.single_flush_state[pos] = true; } else { g_instance.dw_single_cxt.single_flush_state[pos] = true; } - t_thrd.proc->dw_pos = -1; + t_thrd.proc->dw_pos = -1; // 娓呴櫎 Double Write 浣嶇疆 } else { - FlushBuffer(buf_desc, NULL); + FlushBuffer(buf_desc, NULL); // 鐩存帴璋冪敤 FlushBuffer 鍑芥暟鍒锋柊缂撳啿鍖 } } diff --git a/src/gausskernel/storage/smgr/segment/segxlog.cpp b/src/gausskernel/storage/smgr/segment/segxlog.cpp index 05954cd08..bf85b9e9a 100644 --- a/src/gausskernel/storage/smgr/segment/segxlog.cpp +++ b/src/gausskernel/storage/smgr/segment/segxlog.cpp @@ -35,22 +35,45 @@ /* * Truncate segment size */ +/* + * 鍔熻兘锛氬鐞嗛噸鍋氭搷浣滀腑鐨勬埅鏂褰 + * + * 鍙傛暟鍒楄〃锛 + * record锛歑Log 閲嶅仛璁板綍鐨勭姸鎬佷俊鎭 + * + * 娉ㄦ剰锛 + * 1. 璇ュ嚱鏁扮敤浜庡鐞嗛噸鍋氭搷浣滀腑鐨勬埅鏂褰曘 + * 2. 棣栧厛锛岄氳繃璋冪敤 XLogReadBufferForRedo 鑾峰彇寰呭鐞嗙殑缂撳啿鍖轰俊鎭強閲嶅仛鎿嶄綔绫诲瀷銆 + * 3. 濡傛灉閲嶅仛鎿嶄綔绫诲瀷涓 BLK_NEEDS_REDO锛岃〃绀洪渶瑕佹墽琛岄噸鍋氭搷浣滐細 + * a. 浠 XLog 璁板綍涓幏鍙栨埅鏂悗鐨勫潡鏁 nblocks銆 + * b. 鑾峰彇缂撳啿鍖哄搴旂殑椤甸潰锛屽苟灏嗚椤甸潰鐨勫ご閮ㄤ俊鎭浆鎹负 SegmentHead 缁撴瀯銆 + * c. 鏇存柊 seg_head->nblocks 涓 nblocks锛屽苟璁剧疆椤甸潰鐨 LSN銆 + * d. 鏍囪缂撳啿鍖轰负鑴忋 + * 4. 鏈鍚庯紝濡傛灉缂撳啿鍖烘湁鏁堬紝鍒欒В閿佸苟閲婃斁缂撳啿鍖恒 + */ static void redo_truncate(XLogReaderState *record) { RedoBufferInfo buffer_info; XLogRedoAction redo_action = XLogReadBufferForRedo(record, 0, &buffer_info); if (redo_action == BLK_NEEDS_REDO) { + // 鑾峰彇琚埅鏂殑鍧楁暟 BlockNumber nblocks = *(BlockNumber *)XLogRecGetBlockData(record, 0, NULL); + // 鑾峰彇涓庣紦鍐插尯鐩稿叧鑱旂殑椤甸潰 Page page = buffer_info.pageinfo.page; + // 灏嗛〉闈㈠ご淇℃伅瑙嗕负SegmentHead缁撴瀯 SegmentHead *seg_head = (SegmentHead *)PageGetContents(page); + // 浣跨敤鎴柇鍧楁暟鏇存柊seg_head->nblocks seg_head->nblocks = nblocks; + // 璁剧疆椤甸潰鐨凩SN锛屼互璁板綍閲嶅仛鎿嶄綔鐨勫畬鎴 PageSetLSN(page, buffer_info.lsn); + // 鏍囪缂撳啿鍖轰负鑴忛〉锛岃〃绀洪〉闈㈠唴瀹瑰凡琚慨鏀 SegMarkBufferDirty(buffer_info.buf); } if (BufferIsValid(buffer_info.buf)) { + // 濡傛灉缂撳啿鍖烘湁鏁堬紝鍒欒В閿佸苟閲婃斁瀹冿紝纭繚鍐呭瓨绠$悊鐨勪竴鑷存 SegUnlockReleaseBuffer(buffer_info.buf); } } @@ -58,17 +81,36 @@ static void redo_truncate(XLogReaderState *record) /* * Move a list of buckets. */ +/* + * 鍔熻兘璇ュ嚱鏁拌礋璐e鐞嗛噸鍋氭湡闂寸殑绉诲姩妗惰褰曘 + * + * 鍙傛暟鍒楄〃锛 + * buffer锛氳澶勭悊鐨勭紦鍐插尯銆 + * data锛歑Log閲嶅仛璁板綍涓殑鏁版嵁銆 + * + * 娉ㄦ剰锛 + * 1. 璇ュ嚱鏁扮敤浜庡湪閲嶅仛鎿嶄綔鏈熼棿澶勭悊绉诲姩妗惰褰曘 + * 2. 鍑芥暟浠嶺Log璁板綍涓幏鍙栦竴缁勬《椤圭殑淇℃伅锛岀劧鍚庢洿鏂扮浉鍏崇紦鍐插尯鐨勬槧灏勫潡銆 + * 3. 鏄犲皠鍧楃敤浜庤窡韪《鐨勪綅缃拰澶翠俊鎭 + * 4. 鍑芥暟閬嶅巻姣忎釜妗堕」锛屽皢鍏舵爣璇嗭紙bktentry_id锛夋槧灏勫埌鏂扮殑妗跺ご淇℃伅锛坆ktentry_header锛夈 + */ static void redo_move_buckets(Buffer buffer, const char *data) { + // 鑾峰彇妗堕」鏁版嵁鐨勬寚閽 xl_seg_bktentry_tag_t *bktentry; + // 浠嶺Log璁板綍涓幏鍙栨《椤规暟閲 uint32 nentry; nentry = *(uint32 *)data; bktentry = (xl_seg_bktentry_tag_t *)(data + sizeof(uint32)); + // 鑾峰彇涓庣紦鍐插尯鍏宠仈鐨勬槧灏勫潡 BktHeadMapBlock *mapblock = (BktHeadMapBlock *)PageGetContents(BufferGetPage(buffer)); + // 閬嶅巻姣忎釜妗堕」 for (uint32 i = 0; i < nentry; i++) { + // 鑾峰彇妗堕」鐨勬爣璇 uint32 mapentry_id = bktentry[i].bktentry_id; + // 鏇存柊鏄犲皠鍧椾腑鐨勫ご淇℃伅锛屽皢妗堕」鏍囪瘑鏄犲皠鍒版柊鐨勬《澶翠俊鎭 mapblock->head_block[mapentry_id] = bktentry[i].bktentry_header; } } @@ -76,60 +118,123 @@ static void redo_move_buckets(Buffer buffer, const char *data) /* * Record redis info for bucket relation. */ +/* + * 鍔熻兘锛氳鍑芥暟璐熻矗澶勭悊閲嶅仛鏈熼棿鐨勬坊鍔燫edis淇℃伅璁板綍銆 + * + * 鍙傛暟鍒楄〃锛 + * buffer锛氳澶勭悊鐨勭紦鍐插尯 + * data锛歑Log閲嶅仛璁板綍涓殑鏁版嵁锛屽寘鍚玆edis淇℃伅 + * + * 娉ㄦ剰锛 + * 1. 璇ュ嚱鏁扮敤浜庡湪閲嶅仛鎿嶄綔鏈熼棿澶勭悊娣诲姞Redis淇℃伅璁板綍銆 + * 2. 鍑芥暟浠嶺Log璁板綍涓幏鍙朢edis淇℃伅骞跺皢鍏舵坊鍔犲埌鐩稿叧缂撳啿鍖轰腑銆 + * 3. 濡傛灉Redis淇℃伅涓殑鍗曡瘝鏁伴噺涓0锛屽嚱鏁板皢鍒锋柊涓庣紦鍐插尯鍏宠仈鐨勮〃锛坮elation锛夌殑鎵鏈夌紦鍐插尯銆 + * 4. 鏈鍚庯紝鍑芥暟灏哛edis淇℃伅娣诲姞鍒扮紦鍐插尯鐨勫ご閮ㄣ + */ static void redo_bucket_add_redisinfo(Buffer buffer, const char *data) { - SegRedisInfo *redis_info = (SegRedisInfo *)data; + // 浠嶺Log璁板綍涓幏鍙朢edis淇℃伅 + SegRedisInfo *redis_info = (SegRedisInfo *)data; - if (redis_info->nwords == 0) { + // 濡傛灉Redis淇℃伅涓殑鍗曡瘝鏁伴噺涓0 + if (redis_info->nwords == 0) { + // 鑾峰彇缂撳啿鍖烘弿杩扮 BufferDesc *buf_desc = GetBufferDescriptor(buffer - 1); + // 鍒涘缓铏氭嫙鐨勫叧绯荤紦瀛樻潯鐩 Relation reln = CreateFakeRelcacheEntry(buf_desc->tag.rnode); + // 鎵撳紑鍏崇郴鐨勫瓨鍌ㄧ鐞嗗櫒 RelationOpenSmgr(reln); + // 鍒锋柊涓庡叧绯诲叧鑱旂殑鎵鏈夌紦鍐插尯 flush_all_buffers(reln, InvalidOid); + // 閲婃斁铏氭嫙鐨勫叧绯荤紦瀛樻潯鐩 FreeFakeRelcacheEntry(reln); } + // 鑾峰彇缂撳啿鍖虹殑涓诲ご閮 BktMainHead *head = (BktMainHead *)PageGetContents(BufferGetPage(buffer)); - head->redis_info = *redis_info; + // 灏哛edis淇℃伅娣诲姞鍒扮紦鍐插尯鐨勫ご閮 + head->redis_info = *redis_info; } - +/* + * 鍔熻兘锛氳鍑芥暟璐熻矗澶勭悊閲嶅仛鏈熼棿鐨勫彇娑堣缃綅鍥捐褰曘 + * + * 鍙傛暟鍒楄〃锛 + * buffer锛氳澶勭悊鐨勭紦鍐插尯 + * data锛歑Log閲嶅仛璁板綍涓殑鏁版嵁锛屽寘鍚彇娑堣缃綅鍥句俊鎭 + * + * 娉ㄦ剰锛 + * 1. 璇ュ嚱鏁扮敤浜庡湪閲嶅仛鎿嶄綔鏈熼棿澶勭悊鍙栨秷璁剧疆浣嶅浘璁板綍銆 + * 2. 鍑芥暟浠嶺Log璁板綍涓幏鍙栧彇娑堣缃綅鍥剧殑浣嶆爣璇嗭紙bitid锛変互鍙婄浉鍏充綅鍥句俊鎭 + * 3. 鍑芥暟妫鏌apPage鐨勭涓涓〉鏄惁涓鑷达紝濡傛灉涓嶄竴鑷达紝灏嗗紩鍙慞ANIC閿欒銆 + * 4. 濡傛灉灏濊瘯鍙栨秷璁剧疆涓涓凡缁忕┖闂茬殑浣嶅浘锛屽垯鍑芥暟灏嗗紩鍙慞ANIC閿欒銆 + * 5. 鏈鍚庯紝鍑芥暟鏇存柊MapPage鐨勭浉鍏充俊鎭紝骞跺彇娑堣缃寚瀹氱殑浣嶅浘銆 + */ static void redo_unset_bitmap(Buffer buffer, const char *data) { + // 浠嶺Log璁板綍涓幏鍙栦綅鍥炬爣璇嗭紙bitid锛 uint16 bitid = *(uint16 *)data; data += sizeof(uint16); + // 鑾峰彇XLog璁板綍涓殑MapPage淇℃伅 df_map_page_t *log_map_page = (df_map_page_t *)data; + // 鑾峰彇缂撳啿鍖轰腑鐨凪apPage df_map_page_t *map_page = (df_map_page_t *)PageGetContents(BufferGetPage(buffer)); + // 妫鏌apPage鐨勭涓涓〉鏄惁涓鑷达紝濡傛灉涓嶄竴鑷达紝寮曞彂PANIC閿欒 if (map_page->first_page != log_map_page->first_page) { ereport(PANIC, (errmsg("MapPage's first_page is not consistent, it's %u on disk but should be %u according to xlog", map_page->first_page, log_map_page->first_page))); } - + + // 濡傛灉灏濊瘯鍙栨秷璁剧疆涓涓凡缁忕┖闂茬殑浣嶅浘锛屽紩鍙慞ANIC閿欒 if (DF_MAP_FREE(map_page->bitmap, bitid)) { ereport(PANIC, (errmsg("Try to unset bitmap which is free: %u", bitid))); } + // 鏇存柊MapPage鐨勭浉鍏充俊鎭 map_page->dirty_last = log_map_page->dirty_last; map_page->free_begin = log_map_page->free_begin; map_page->free_bits = log_map_page->free_bits; + // 鍙栨秷璁剧疆鎸囧畾鐨勪綅鍥 DF_MAP_UNSET(map_page->bitmap, bitid); } - +/* + * 鍔熻兘锛氬鐞嗛噸鍋氭搷浣滀腑鐨勮缃綅鍥捐褰 + * + * 鍙傛暟鍒楄〃锛 + * buftag锛氱紦鍐插尯鏍囪锛岀敤浜庣‘瀹氭搷浣滅殑缂撳啿鍖轰綅缃 + * buffer锛氬緟澶勭悊鐨勭紦鍐插尯銆 + * data锛氫粠 XLog 璁板綍涓彁鍙栫殑鏁版嵁銆 + * + * 娉ㄦ剰锛 + * 1. 璇ュ嚱鏁扮敤浜庡鐞嗛噸鍋氭搷浣滀腑鐨勮缃綅鍥捐褰曘 + * 2. 棣栧厛锛屼粠鏁版嵁涓幏鍙栦綅鍥剧殑浣嶅彿 bitid銆 + * 3. 鑾峰彇缂撳啿鍖哄搴旂殑椤甸潰锛屽皢鍏惰浆鎹负 df_map_page_t 缁撴瀯銆 + * 4. 妫鏌ラ〉闈㈢殑 first_page 鏄惁涓 XLog 璁板綍涓殑 log_map_page->first_page 涓鑷达紝濡傛灉涓嶄竴鑷达紝鎶ュ憡 PANIC 閿欒銆 + * 5. 妫鏌ユ寚瀹氫綅鏄惁宸茶璁剧疆锛屽鏋滃凡琚缃紝鎶ュ憡 PANIC 閿欒銆 + * 6. 灏嗛〉闈㈢殑 dirty_last銆乫ree_begin銆乫ree_bits 鏇存柊涓 log_map_page 涓殑瀵瑰簲鍊硷紝骞惰缃寚瀹氫綅銆 + * 7. 鏍规嵁浣嶅浘鐨 bitid 璁$畻鍑哄搴旀暟鎹枃浠剁殑鍧楀彿 blkno銆 + * 8. 鏍规嵁鍧楀彿璁$畻鍑虹洰鏍囧潡鍙 target锛屽苟浣跨敤 spc_extend_file 鎵╁睍鏁版嵁鏂囦欢鍒扮洰鏍囧潡鍙枫 + */ static void redo_set_bitmap(RedoBufferTag buftag, Buffer buffer, const char *data) { + // 浠 XLog 璁板綍鐨勬暟鎹腑鑾峰彇浣嶅浘鐨勪綅鍙 bitid uint16 bitid = *(uint16 *)data; data += sizeof(uint16); + // 鑾峰彇 log_map_page 鍜屽綋鍓嶇紦鍐插尯鐨 map_page df_map_page_t *log_map_page = (df_map_page_t *)data; df_map_page_t *map_page = (df_map_page_t *)PageGetContents(BufferGetPage(buffer)); + // 妫鏌ラ〉闈㈢殑 first_page 鏄惁涓鑷达紝涓嶄竴鑷存姤鍛 PANIC 閿欒 if (map_page->first_page != log_map_page->first_page) { ereport(PANIC, (errmsg("MapPage's first_page is not consistent, it's %u on disk but should be %u according to xlog", map_page->first_page, log_map_page->first_page), errhint("segment-page may have bug"))); } + // 妫鏌ユ寚瀹氫綅鏄惁宸茶璁剧疆锛屽鏋滃凡琚缃紝鎶ュ憡 PANIC 閿欒 if (DF_MAP_NOT_FREE(map_page->bitmap, bitid)) { ereport(PANIC, (errmsg("Try to set bitmap which is not free: %u", bitid), errhint("segment-page may have bug"))); @@ -140,39 +245,92 @@ static void redo_set_bitmap(RedoBufferTag buftag, Buffer buffer, const char *dat DF_MAP_SET(map_page->bitmap, bitid); /* Extend data file if necessary. First get the extent start */ + // 璁$畻鏁版嵁鏂囦欢鐨勫潡鍙 blkno锛屼互鍙婄洰鏍囧潡鍙 target BlockNumber blkno = map_page->first_page + EXTENT_TYPE_TO_SIZE(buftag.rnode.relNode) * bitid; /* Then plus one extent length */ BlockNumber target = blkno + EXTENT_TYPE_TO_SIZE(buftag.rnode.relNode); + // 鎵撳紑 SegSpace 骞惰皟鐢 spc_extend_file 鎵╁睍鏁版嵁鏂囦欢鍒扮洰鏍囧潡鍙 SegSpace *spc = spc_open(buftag.rnode.spcNode, buftag.rnode.dbNode, false); SegmentCheck(spc != NULL); spc_extend_file(spc, buftag.rnode.relNode, buftag.forknum, target); } - +/* + * 鍔熻兘锛氬鐞嗛噸鍋氭搷浣滀腑鐨勬槧灏勫ご鍒嗛厤鎵╁睍璁板綍 + * + * 鍙傛暟鍒楄〃锛 + * buffer锛氬緟澶勭悊鐨勭紦鍐插尯銆 + * data锛氫粠 XLog 璁板綍涓彁鍙栫殑鏁版嵁銆 + * + * 娉ㄦ剰锛 + * 1. 璇ュ嚱鏁扮敤浜庡鐞嗛噸鍋氭搷浣滀腑鐨勬槧灏勫ご鍒嗛厤鎵╁睍璁板綍銆 + * 2. 浠 XLog 璁板綍鏁版嵁涓幏鍙 XLogDataSpaceAllocateExtent 缁撴瀯锛屽寘鍚垎閰嶆墿灞曟墍闇鐨勪俊鎭 + * 3. 鑾峰彇缂撳啿鍖哄搴旂殑椤甸潰锛屽苟灏嗗叾杞崲涓 df_map_head_t 缁撴瀯銆 + * 4. 鏇存柊鏄犲皠澶寸殑 allocated_extents銆乫ree_group銆乬roups[free_group].free_page 鍜 high_water_mark 瀛楁 + * 浠ュ弽鏄 XLog 璁板綍涓殑鏁版嵁銆 + */ static void redo_maphead_allocated_extents(Buffer buffer, const char *data) { + // 浠 XLog 璁板綍鏁版嵁涓幏鍙 XLogDataSpaceAllocateExtent 缁撴瀯 XLogDataSpaceAllocateExtent *xlog_data = (XLogDataSpaceAllocateExtent *)data; + // 鑾峰彇缂撳啿鍖哄搴旂殑椤甸潰锛屽苟灏嗗叾杞崲涓 df_map_head_t 缁撴瀯 df_map_head_t *map_head = (df_map_head_t *)PageGetContents(BufferGetPage(buffer)); + // 鏇存柊鏄犲皠澶寸殑 allocated_extents銆乫ree_group銆乬roups[free_group].free_page 鍜 high_water_mark 瀛楁 map_head->allocated_extents = xlog_data->allocated_extents; map_head->free_group = xlog_data->free_group; - map_head->groups[xlog_data->free_group].free_page = xlog_data->free_page; + map_head->groups[xlog_data->free_group].free_page = xlog_data->free_page; map_head->high_water_mark = xlog_data->hwm; } - +/* + * 鍔熻兘锛氬鐞嗛噸鍋氭搷浣滀腑鐨勫垵濮嬪寲娈靛ご璁板綍 + * + * 鍙傛暟鍒楄〃锛 + * buffer锛氬緟澶勭悊鐨勭紦鍐插尯銆 + * data锛氫粠 XLog 璁板綍涓彁鍙栫殑鏁版嵁銆 + * + * 娉ㄦ剰锛 + * 1. 璇ュ嚱鏁扮敤浜庡鐞嗛噸鍋氭搷浣滀腑鐨勫垵濮嬪寲娈靛ご璁板綍銆 + * 2. 鑾峰彇缂撳啿鍖烘弿杩扮锛屽搴斾簬鍙傛暟 buffer 鐨勭紪鍙峰噺涓銆 + * 3. 浣跨敤 SegmentCheck 纭繚缂撳啿鍖虹殑鍏宠仈鍏崇郴锛屽嵆 rnode.relNode 蹇呴』绛変簬 SEGMENT_HEAD_EXTENT_SIZE銆 + * 4. 浠 XLog 璁板綍涓幏鍙 LSN锛屽苟浣跨敤 eg_init_segment_head_buffer_content 鍒濆鍖栫紦鍐插尯鐨勫唴瀹广 + */ static void redo_init_seghead(Buffer buffer, const char *data) { + // 鑾峰彇缂撳啿鍖烘弿杩扮锛屽搴斾簬鍙傛暟 buffer 鐨勭紪鍙峰噺涓 BufferDesc *buf_desc = GetBufferDescriptor(buffer - 1); + // 浣跨敤 SegmentCheck 纭繚缂撳啿鍖虹殑鍏宠仈鍏崇郴 SegmentCheck(buf_desc->tag.rnode.relNode == EXTENT_SIZE_TO_TYPE(SEGMENT_HEAD_EXTENT_SIZE)); + // 浠 XLog 璁板綍涓幏鍙 LSN XLogRecPtr lsn = *(XLogRecPtr *)(data); + // 浣跨敤 eg_init_segment_head_buffer_content 鍒濆鍖栫紦鍐插尯鐨勫唴瀹 eg_init_segment_head_buffer_content(buffer, buf_desc->tag.blockNum, lsn); } - +/* + * 鍔熻兘锛氬鐞嗛噸鍋氭搷浣滀腑鐨勬洿鏂版澶磋褰 + * + * 鍙傛暟鍒楄〃锛 + * buffer锛氬緟澶勭悊鐨勭紦鍐插尯 + * data锛氫粠 XLog 璁板綍涓彁鍙栫殑鏁版嵁 + * + * 娉ㄦ剰锛 + * 1. 璇ュ嚱鏁扮敤浜庡鐞嗛噸鍋氭搷浣滀腑鐨勬洿鏂版澶磋褰曘 + * 2. 浠 XLog 璁板綍涓幏鍙栭噸鍋氭暟鎹 XLogDataUpdateSegmentHead銆 + * 3. 鑾峰彇缂撳啿鍖哄搴旂殑娈靛ご淇℃伅銆 + * 4. 妫鏌 xlog_data 涓殑 nblocks 鏄惁涓庢澶翠腑鐨 nblocks 涓鑷达紝濡傛灉涓嶄竴鑷达紝鎶ラ敊銆 + * 5. 濡傛灉 xlog_data 涓殑 level0_slot 涓嶅皬浜0锛屽皢 level0_slot 浣嶇疆鐨勫兼洿鏂颁负 xlog_data 涓殑 level0_value銆 + * 6. 濡傛灉 xlog_data 涓殑 level1_slot 涓嶅皬浜0锛屽皢 level1_slot 浣嶇疆鐨勫兼洿鏂颁负 xlog_data 涓殑 level1_value銆 + * 7. 鏇存柊娈靛ご鐨 nextents銆乼otal_blocks 灞炴с + * 8. 濡傛灉 total_blocks 涓 0锛岃〃绀烘墍鏈 extents 閮藉凡閲婃斁锛屽皢娈靛ご鍒锋柊鍒扮鐩樹笂銆 + */ static void redo_update_seghead(Buffer buffer, const char *data) { + // 浠 XLog 璁板綍涓幏鍙栭噸鍋氭暟鎹 XLogDataUpdateSegmentHead XLogDataUpdateSegmentHead *xlog_data = (XLogDataUpdateSegmentHead *)data; + // 鑾峰彇缂撳啿鍖哄搴旂殑娈靛ご淇℃伅 SegmentHead *head = (SegmentHead *)PageGetContents(BufferGetPage(buffer)); + // 妫鏌 xlog_data 涓殑 nblocks 鏄惁涓庢澶翠腑鐨 nblocks 涓鑷达紝濡傛灉涓嶄竴鑷达紝鎶ラ敊 if (xlog_data->nblocks != head->nblocks) { ereport(PANIC, (errmsg("redo update seghead, but target head's nblocks is %u, but should be %u according to xlog", @@ -180,174 +338,297 @@ static void redo_update_seghead(Buffer buffer, const char *data) errhint("segment-page may have bug"))); } + // 濡傛灉 xlog_data 涓殑 level0_slot 涓嶅皬浜0锛屽皢 level0_slot 浣嶇疆鐨勫兼洿鏂颁负 xlog_data 涓殑 level0_value if (xlog_data->level0_slot >= 0) { head->level0_slots[xlog_data->level0_slot] = xlog_data->level0_value; } + // 濡傛灉 xlog_data 涓殑 level1_slot 涓嶅皬浜0锛屽皢 level1_slot 浣嶇疆鐨勫兼洿鏂颁负 xlog_data 涓殑 level1_value if (xlog_data->level1_slot >= 0) { head->level1_slots[xlog_data->level1_slot] = xlog_data->level1_value; } + // 鏇存柊娈靛ご鐨 nextents銆乼otal_blocks 灞炴 head->nextents = xlog_data->nextents; head->total_blocks = xlog_data->total_blocks; /* If all extents is freed, flush segment header to disk */ + // 濡傛灉 total_blocks 涓 0锛岃〃绀烘墍鏈 extents 閮藉凡閲婃斁锛屽皢娈靛ご鍒锋柊鍒扮鐩樹笂 if (head->total_blocks == 0) { SegmentCheck(head->nextents == 0); FlushOneSegmentBuffer(buffer); } } - +/* + * 鍔熻兘锛氬鐞嗛噸鍋氭搷浣滀腑鐨勬柊寤 level0 椤佃褰 + * + * 鍙傛暟鍒楄〃锛 + * buffer锛氬緟澶勭悊鐨勭紦鍐插尯 + * data锛氫粠 XLog 璁板綍涓彁鍙栫殑鏁版嵁 + * + */ static void redo_new_level0_page(Buffer buffer, const char *data) { + // 浠 XLog 璁板綍涓幏鍙栭噸鍋氭暟鎹紝鍗崇涓涓潡鐨勫潡鍙 first_extent BlockNumber first_extent = *(BlockNumber *)data; + // 鑾峰彇寰呭鐞嗙紦鍐插尯瀵瑰簲鐨 level0 椤 Page level0_page = BufferGetPage(buffer); + // 鍒濆鍖 level0 椤电殑鍐呭锛岃缃〉闈㈠ぇ灏忎负 BLCKSZ SegPageInit(level0_page, BLCKSZ); + // 鏇存柊椤甸潰澶撮儴淇℃伅 PageHeader header = (PageHeader)level0_page; header->pd_lower += sizeof(BMTLevel0Page); + // 鑾峰彇 level0 椤电殑鍐呭锛屽皢绗竴涓Ы slots[0] 璁剧疆涓 first_extent BMTLevel0Page *bmt_level0_page = (BMTLevel0Page *)PageGetContents(level0_page); bmt_level0_page->slots[0] = first_extent; + // 璁剧疆 bmt_level0_page 鐨 magic 灞炴т负 BMTLEVEL0_MAGIC bmt_level0_page->magic = BMTLEVEL0_MAGIC; } - +/* + * 鍔熻兘锛氬鐞嗛噸鍋氭搷浣滀腑鐨勫悜 level0 椤垫坊鍔 extent 璁板綍 + * + * 鍙傛暟鍒楄〃锛 + * buffer锛氬緟澶勭悊鐨勭紦鍐插尯 + * data锛氫粠 XLog 璁板綍涓彁鍙栫殑鏁版嵁 + */ static void redo_level0_page_add_extent(Buffer buffer, const char *data) { + // 浠 XLog 璁板綍涓幏鍙栭噸鍋氭暟鎹紝鍗宠娣诲姞鐨 extent 鐨勬Ы浣嶅彿鍜屽潡鍙 XLogDataSetLevel0Page *xlog_data = (XLogDataSetLevel0Page *)data; + // 鑾峰彇寰呭鐞嗙紦鍐插尯瀵瑰簲鐨 level0 椤 BMTLevel0Page *bmt_level0_page = (BMTLevel0Page *)PageGetContents(BufferGetPage(buffer)); + // 灏 level0 椤典腑鎸囧畾妲戒綅 slots[slot] 璁剧疆涓烘柊鐨 extent bmt_level0_page->slots[xlog_data->slot] = xlog_data->extent; } - +/* + * 鍔熻兘锛氬鐞嗛噸鍋氭搷浣滀腑娣诲姞鍒嗘敮娈电殑璁板綍 + * + * 鍙傛暟鍒楄〃锛 + * buffer锛氬緟澶勭悊鐨勭紦鍐插尯 + * data锛歑Log 閲嶅仛璁板綍涓殑鏁版嵁 + */ static void redo_seghead_add_fork_segment(Buffer buffer, const char *data) { - int forknum = *(int *)data; + int forknum = *(int *)data; // 浠庤褰曟暟鎹腑鑾峰彇鍒嗘敮鍙 data += sizeof(int); - BlockNumber forkhead = *(BlockNumber *)data; + BlockNumber forkhead = *(BlockNumber *)data; // 浠庤褰曟暟鎹腑鑾峰彇鍒嗘敮澶村潡鍙 - SegmentHead *seghead = (SegmentHead *)PageGetContents(BufferGetPage(buffer)); - seghead->fork_head[forknum] = forkhead; + SegmentHead *seghead = (SegmentHead *)PageGetContents(BufferGetPage(buffer)); // 鑾峰彇缂撳啿鍖哄搴旂殑娈靛ご淇℃伅 + seghead->fork_head[forknum] = forkhead; // 灏嗗垎鏀ご鍧楀彿 forkhead 瀛樺偍鍒扮浉搴斿垎鏀彿 forknum 鐨勪綅缃 } - +/* + * 鍔熻兘锛氬鐞嗛噸鍋氭搷浣滀腑鍙栨秷閾炬帴娈靛ご鎸囬拡鐨勮褰 + * + * 鍙傛暟鍒楄〃锛 + * buffer锛氬緟澶勭悊鐨勭紦鍐插尯 + * data锛歑Log 閲嶅仛璁板綍涓殑鏁版嵁 + */ static void redo_unlink_seghead_ptr(Buffer buffer, const char *data) { - off_t offset = *(off_t *)data; - + off_t offset = *(off_t *)data; // 浠庤褰曟暟鎹腑鑾峰彇鍋忕Щ閲 + // 鑾峰彇缂撳啿鍖哄搴旂殑鏁版嵁锛屽苟璁$畻鎸囧悜鍋忕Щ閲忕殑鎸囬拡 BlockNumber *owner_pointer = (BlockNumber *)((char *)PageGetContents(BufferGetPage(buffer)) + offset); + // 灏嗗亸绉婚噺 offset 澶勭殑 BlockNumber 璁剧疆涓 InvalidBlockNumber锛屽彇娑堥摼鎺ユ澶存寚閽 *owner_pointer = InvalidBlockNumber; } +/* + * 鍔熻兘锛氬鐞嗛噸鍋氭搷浣滀腑鍒濆鍖栨《鐨勪富澶撮儴璁板綍 + * + * 鍙傛暟鍒楄〃锛 + * buffer锛氬緟澶勭悊鐨勭紦鍐插尯 + * data锛歑Log 閲嶅仛璁板綍涓殑鏁版嵁 + * + * 娉ㄦ剰锛 + * 1. 璇ュ嚱鏁扮敤浜庡鐞嗛噸鍋氭搷浣滀腑鍒濆鍖栨《鐨勪富澶撮儴璁板綍銆 + * 2. 鍦ㄤ娇鐢ㄦ鍑芥暟鏃讹紝璇风‘淇濅紶鍏ョ殑缂撳啿鍖烘槸鍚堥傜殑锛屽苟涓旀暟鎹牸寮忔纭 + */ static void redo_init_bucket_main_head(Buffer buffer, const char *data) { Page main_head_page = BufferGetPage(buffer); - SegPageInit(main_head_page, BLCKSZ); - ((PageHeader)main_head_page)->pd_lower += sizeof(BktMainHead); + SegPageInit(main_head_page, BLCKSZ); // 鍒濆鍖栭〉闈 + ((PageHeader)main_head_page)->pd_lower += sizeof(BktMainHead); // 璋冩暣椤甸潰澶撮儴淇℃伅 - BktMainHead *main_head = (BktMainHead *)PageGetContents(main_head_page); - main_head->magic = BUCKET_SEGMENT_MAGIC; - main_head->lsn = *(XLogRecPtr *)data; - main_head->redis_info.redis_xid = InvalidTransactionId; - main_head->redis_info.nwords = 0; + BktMainHead *main_head = (BktMainHead *)PageGetContents(main_head_page); // 鑾峰彇涓诲ご閮ㄧ粨鏋勬寚閽 + main_head->magic = BUCKET_SEGMENT_MAGIC; // 璁剧疆榄旀湳鍊 + main_head->lsn = *(XLogRecPtr *)data; // 浠庨噸鍋氳褰曚腑鑾峰彇LSN + main_head->redis_info.redis_xid = InvalidTransactionId; // 璁剧疆浜嬪姟ID涓烘棤鏁 + main_head->redis_info.nwords = 0; // 鍒濆鍖栧崟璇嶆暟涓0 } +/* + * 鍔熻兘锛氬鐞嗛噸鍋氭搷浣滀腑閲婃斁妗剁殑浣嶅浘鍧楄褰 + * + * 鍙傛暟鍒楄〃锛 + * buffer锛氬緟澶勭悊鐨勭紦鍐插尯 + * data锛歑Log 閲嶅仛璁板綍涓殑鏁版嵁 + * + * 娉ㄦ剰锛 + * 1. 璇ュ嚱鏁扮敤浜庡鐞嗛噸鍋氭搷浣滀腑閲婃斁妗剁殑浣嶅浘鍧楄褰曘 + * 2. 鍦ㄤ娇鐢ㄦ鍑芥暟鏃讹紝璇风‘淇濅紶鍏ョ殑缂撳啿鍖哄拰鏁版嵁鏍煎紡姝g‘銆 + */ static void redo_bucket_free_mapblock(Buffer buffer, const char *data) { - uint32 map_id = *(uint32 *)data; - BktMainHead *main_head = (BktMainHead *)PageGetContents(BufferGetPage(buffer)); - main_head->bkt_map[map_id] = InvalidBlockNumber; + uint32 map_id = *(uint32 *)data; // 浠庨噸鍋氳褰曚腑鑾峰彇浣嶅浘鍧楃殑ID + BktMainHead *main_head = (BktMainHead *)PageGetContents(BufferGetPage(buffer)); // 鑾峰彇涓诲ご閮ㄦ寚閽 + main_head->bkt_map[map_id] = InvalidBlockNumber; // 灏嗕綅鍥惧潡鐨処D鏍囪涓烘棤鏁 } - +/* + * 鍔熻兘锛氬鐞嗛噸鍋氭搷浣滀腑娣诲姞妗剁殑浣嶅浘鍧楄褰 + * + * 鍙傛暟鍒楄〃锛 + * buffer锛氬緟澶勭悊鐨勭紦鍐插尯 + * data锛歑Log 閲嶅仛璁板綍涓殑鏁版嵁 + * + * 娉ㄦ剰锛 + * 1. 璇ュ嚱鏁扮敤浜庡鐞嗛噸鍋氭搷浣滀腑娣诲姞妗剁殑浣嶅浘鍧楄褰曘 + * 2. 鍦ㄤ娇鐢ㄦ鍑芥暟鏃讹紝璇风‘淇濅紶鍏ョ殑缂撳啿鍖哄拰鏁版嵁鏍煎紡姝g‘銆 + */ static void redo_bucket_add_mapblock(Buffer buffer, const char *data) { - uint32 blockid = *(uint32 *)data; + uint32 blockid = *(uint32 *)data; // 浠庨噸鍋氳褰曚腑鑾峰彇妗剁殑ID data += sizeof(uint32); - BlockNumber mapblock = *(BlockNumber *)data; + BlockNumber mapblock = *(BlockNumber *)data; // 浠庨噸鍋氳褰曚腑鑾峰彇浣嶅浘鍧楃殑鍧楀彿 - BktMainHead *main_head = (BktMainHead *)PageGetContents(BufferGetPage(buffer)); - main_head->bkt_map[blockid] = mapblock; + BktMainHead *main_head = (BktMainHead *)PageGetContents(BufferGetPage(buffer)); // 鑾峰彇涓诲ご閮ㄦ寚閽 + main_head->bkt_map[blockid] = mapblock; // 灏嗘《鐨勪綅鍥惧潡鍏宠仈璧锋潵 } +/* + * 鍔熻兘锛氬鐞嗛噸鍋氭搷浣滀腑鍒濆鍖栨《鐨勪綅鍥惧潡璁板綍 + * + * 鍙傛暟鍒楄〃锛 + * buffer锛氬緟澶勭悊鐨勭紦鍐插尯 + * data锛歑Log 閲嶅仛璁板綍涓殑鏁版嵁 + */ static void redo_bucket_init_mapblock(Buffer buffer, const char *data) { - XLogRecPtr lsn = *(XLogRecPtr *)data; - bucket_init_map_page(buffer, lsn); + XLogRecPtr lsn = *(XLogRecPtr *)data; // 浠庨噸鍋氳褰曚腑鑾峰彇LSN + bucket_init_map_page(buffer, lsn); // 璋冪敤 bucket_init_map_page 鍑芥暟杩涜浣嶅浘鍧楀垵濮嬪寲 } +/* + * 鍔熻兘锛氬鐞嗛噸鍋氭搷浣滀腑娣诲姞妗跺ご鏄犲皠鍧楃殑璁板綍 + * + * 鍙傛暟鍒楄〃锛 + * buffer锛氬緟澶勭悊鐨勭紦鍐插尯 + * data锛歑Log 閲嶅仛璁板綍涓殑鏁版嵁 + */ static void redo_bucket_add_bkthead(Buffer buffer, const char *data) { - int map_entry_id = *(int *)data; + int map_entry_id = *(int *)data; // 浠庤褰曟暟鎹腑鑾峰彇鏄犲皠鏉$洰ID data += sizeof(int); - BlockNumber head_block = *(BlockNumber *)data; + BlockNumber head_block = *(BlockNumber *)data; // 浠庤褰曟暟鎹腑鑾峰彇澶村潡鍙 BktHeadMapBlock *map_block = (BktHeadMapBlock *)PageGetContents(BufferGetPage(buffer)); - map_block->head_block[map_entry_id] = head_block; + map_block->head_block[map_entry_id] = head_block; // 灏嗘槧灏勬潯鐩甀D瀵瑰簲鐨勫ご鍧楀彿璁剧疆鍒版槧灏勫潡涓 } - +/* + * 鍔熻兘锛氬鐞嗛噸鍋氭搷浣滀腑鏇存柊绌洪棿楂樻按浣嶆爣璁扮殑璁板綍 + * + * 鍙傛暟鍒楄〃锛 + * buffer锛氬緟澶勭悊鐨勭紦鍐插尯 + * data锛歑Log 閲嶅仛璁板綍涓殑鏁版嵁 + */ static void redo_space_update_hwm(Buffer buffer, const char *data) { XLogDataUpdateSpaceHWM *xlog_data = (XLogDataUpdateSpaceHWM *)data; df_map_head_t *map_head = (df_map_head_t *)PageGetContents(BufferGetPage(buffer)); + // 妫鏌ユ棫楂樻按浣嶆爣璁版槸鍚︿笌璁板綍涓殑鍊间竴鑷 if (map_head->high_water_mark != xlog_data->old_hwm) { ereport(PANIC, (errmsg("update space high water mark, old hwm is %u, but should be %u according to xlog", map_head->high_water_mark, xlog_data->old_hwm), errhint("segment-page may have bug"))); } + // 妫鏌ユ棫鏄犲皠缁勬暟鏄惁涓庤褰曚腑鐨勫间竴鑷 if (map_head->group_count != xlog_data->old_groupcnt) { ereport(PANIC, (errmsg("update map group count, old count is %u, but should be %u according to xlog", - map_head->group_count, xlog_data->old_groupcnt))); + map_head->group_count, xlog_data->old_groupcnt))); } + // 鏇存柊楂樻按浣嶆爣璁板拰鏄犲皠缁勬暟涓鸿褰曚腑鐨勬柊鍊 map_head->high_water_mark = xlog_data->new_hwm; map_head->group_count = xlog_data->new_groupcnt; } - +/* + * 鍔熻兘锛氬鐞嗛噸鍋氭搷浣滀腑璁剧疆鍙嶅悜鎸囬拡鐨勮褰 + * + * 鍙傛暟鍒楄〃锛 + * buffer锛氬緟澶勭悊鐨勭紦鍐插尯 + * data锛歑Log 閲嶅仛璁板綍涓殑鏁版嵁 + */ static void redo_set_inverse_pointer(Buffer buffer, const char *data) { - uint32 offset = *(uint32 *)data; + uint32 offset = *(uint32 *)data; // 浠庤褰曟暟鎹腑鑾峰彇鍋忕Щ閲 data += sizeof(uint32); - ExtentInversePointer iptr = *(ExtentInversePointer *)data; + ExtentInversePointer iptr = *(ExtentInversePointer *)data; // 浠庤褰曟暟鎹腑鑾峰彇鍙嶅悜鎸囬拡 ExtentInversePointer *eips = (ExtentInversePointer *)PageGetContents(BufferGetBlock(buffer)); - eips[offset] = iptr; + eips[offset] = iptr; // 灏嗗弽鍚戞寚閽堣缃埌鎸囧畾鍋忕Щ閲忕殑浣嶇疆 } - +/* + * 鍔熻兘锛氬鐞嗛噸鍋氭搷浣滀腑缂╁噺娈靛ご鏇存柊璁板綍 + * + * 鍙傛暟鍒楄〃锛 + * buffer锛氬緟澶勭悊鐨勭紦鍐插尯 + * data锛歑Log 閲嶅仛璁板綍涓殑鏁版嵁 + */ static void redo_shrink_seghead_update(Buffer buffer, const char *data) { - XLogMoveExtent *xlog_data = (XLogMoveExtent *)data; - SegmentHead *seghead = (SegmentHead *)PageGetContents(BufferGetBlock(buffer)); - int extent_id = xlog_data->extent_id; + XLogMoveExtent *xlog_data = (XLogMoveExtent *)data; // 鑾峰彇XLog璁板綍涓殑鏁版嵁 + SegmentHead *seghead = (SegmentHead *)PageGetContents(BufferGetBlock(buffer)); // 鑾峰彇缂撳啿鍖哄搴旂殑娈靛ご + int extent_id = xlog_data->extent_id; // 鑾峰彇瑕佹洿鏂扮殑Extent鐨処D if (extent_id < BMT_HEADER_LEVEL0_SLOTS) { /* Level0 extent, needs updating segment head */ - SegmentCheck(seghead->level0_slots[extent_id] == xlog_data->old_extent); - seghead->level0_slots[extent_id] = xlog_data->new_extent; + SegmentCheck(seghead->level0_slots[extent_id] == xlog_data->old_extent); // 妫鏌ユ棫鐨凟xtent鏄惁鍖归厤 + seghead->level0_slots[extent_id] = xlog_data->new_extent; // 鏇存柊娈靛ご涓璍evel0 extent鐨勪俊鎭 } + // 鍦⊿EGMENT_REDO_UPDATE_SEGHEAD娴嬭瘯妯″紡涓嬭褰曢敊璇俊鎭 SEGMENTTEST(SEGMENT_REDO_UPDATE_SEGHEAD, (errmsg("error happens when replaying segment head update in shrink"))); } #define REL_NODE_FORMAT(rnode) rnode.spcNode, rnode.dbNode, rnode.relNode, rnode.bucketNode /* create hash table using shared memory when first needed */ -struct HTAB* redo_create_remain_segs_htbl() +struct HTAB *redo_create_remain_segs_htbl() { HASHCTL ctl; - + + // 鍒濆鍖栧搱甯岃〃鎺у埗缁撴瀯 errno_t errorno = memset_s(&ctl, sizeof(ctl), 0, sizeof(ctl)); securec_check(errorno, "", ""); - - ctl.keysize = sizeof(RemainExtentHashTag); - ctl.entrysize = sizeof(ExtentTag); - ctl.hash = tag_hash; - int flag = HASH_ELEM | HASH_FUNCTION; - + + ctl.keysize = sizeof(RemainExtentHashTag); // 璁剧疆閿殑澶у皬 + ctl.entrysize = sizeof(ExtentTag); // 璁剧疆鏉$洰鐨勫ぇ灏 + ctl.hash = tag_hash; // 璁剧疆鍝堝笇鍑芥暟 + int flag = HASH_ELEM | HASH_FUNCTION; // 鏍囪涓哄搱甯屽厓绱犲拰鍝堝笇鍑芥暟 + + // 浣跨敤HeapMemInitHash鍑芥暟鍒涘缓骞跺垵濮嬪寲鍝堝笇琛 return HeapMemInitHash("remain_segs", 1000, DF_MAP_GROUP_EXTENTS, &ctl, flag); } - +/* + * 鍔熻兘锛氬鐞嗛噸鍋氭搷浣滀腑鐨勫垎閰嶆鏃ュ織璁板綍 + * + * 鍙傛暟鍒楄〃锛 + * buffer锛氬緟澶勭悊鐨勭紦鍐插尯 + * xid锛氬垎閰嶆鐨勪簨鍔 ID + * + * 娉ㄦ剰锛 + * 1. 杩欎釜鍑芥暟鐢ㄤ簬澶勭悊閲嶅仛鎿嶄綔涓殑鍒嗛厤娈垫棩蹇楄褰曘 + * 2. 鍑芥暟棣栧厛鑾峰彇閲嶅仛鎿嶄綔瀵瑰簲鐨勭紦鍐插尯鎻忚堪绗︺ + * 3. 鐒跺悗鏋勫缓涓涓 RemainExtentHashTag 缁撴瀯锛岀敤浜庢爣璇嗗墿浣欐鐨勫搱甯岃〃鏉$洰銆 + * 4. 鎺ヤ笅鏉ワ紝鍑芥暟灏濊瘯鍦ㄥ搱甯岃〃涓煡鎵捐鏉$洰锛屽鏋滄壘鍒拌〃绀鸿娈靛凡瀛樺湪锛岃緭鍑鸿鍛婁俊鎭 + * 5. 濡傛灉鏈壘鍒帮紝灏嗚娈典俊鎭坊鍔犲埌鍝堝笇琛ㄤ腑锛屽寘鎷簨鍔 ID銆佸墿浣欐绫诲瀷銆乫ork 鍙峰拰 LSN銆 + * 6. 鏈鍚庯紝閲婃斁閿併 + */ static void redo_xlog_log_alloc_seg(Buffer buffer, TransactionId xid) { AutoMutexLock remainSegsLock(&g_instance.xlog_cxt.remain_segs_lock); remainSegsLock.lock(); Assert(TransactionIdIsValid(xid)); - + if (t_thrd.xlog_cxt.remain_segs == NULL) { t_thrd.xlog_cxt.remain_segs = redo_create_remain_segs_htbl(); } @@ -358,28 +639,44 @@ static void redo_xlog_log_alloc_seg(Buffer buffer, TransactionId xid) remainExtentHashTag.rnode = bufDesc->tag.rnode; remainExtentHashTag.rnode.relNode = bufDesc->tag.blockNum; remainExtentHashTag.extentType = bufDesc->tag.rnode.relNode; - + bool found = false; - ExtentTag* extentTag = (ExtentTag *)hash_search(t_thrd.xlog_cxt.remain_segs, (void *)&remainExtentHashTag, - HASH_ENTER, &found); + ExtentTag *extentTag = + (ExtentTag *)hash_search(t_thrd.xlog_cxt.remain_segs, (void *)&remainExtentHashTag, HASH_ENTER, &found); if (found) { - ereport(WARNING, (errmsg("Segment [%u, %u, %u, %d] already existed in remain segs, Xid %lu," - "remainExtentType %u.", REL_NODE_FORMAT(remainExtentHashTag.rnode), extentTag->xid, - extentTag->remainExtentType))); + ereport(WARNING, + (errmsg("Segment [%u, %u, %u, %d] already existed in remain segs, Xid %lu," + "remainExtentType %u.", + REL_NODE_FORMAT(remainExtentHashTag.rnode), extentTag->xid, extentTag->remainExtentType))); } else { extentTag->remainExtentType = ALLOC_SEGMENT; extentTag->xid = xid; extentTag->forkNum = InvalidForkNumber; extentTag->lsn = InvalidXLogRecPtr; - + ereport(DEBUG5, (errmodule(MOD_SEGMENT_PAGE), errmsg("Segment [%u, %u, %u, %d] is alloced, cur xid %lu.", - REL_NODE_FORMAT(remainExtentHashTag.rnode), xid))); + REL_NODE_FORMAT(remainExtentHashTag.rnode), xid))); } remainSegsLock.unLock(); } - -static void redo_xlog_forget_alloc_seg(Buffer buffer, const char* data, int data_len) +/* + * 鍔熻兘锛氬鐞嗛噸鍋氭搷浣滀腑蹇樿鍒嗛厤娈电殑璁板綍 + * + * 鍙傛暟鍒楄〃锛 + * buffer锛氬緟澶勭悊鐨勭紦鍐插尯 + * data锛歑Log 閲嶅仛璁板綍涓殑鏁版嵁 + * data_len锛氭暟鎹暱搴 + * + * 娉ㄦ剰锛 + * 1. 鍑芥暟棣栧厛妫鏌ユ暟鎹暱搴︽槸鍚︾鍚堥鏈燂紝濡傛灉涓嶇鍚堝垯杩斿洖銆 + * 2. 鐒跺悗浠庢暟鎹腑鑾峰彇鍧楀彿锛屾牴鎹潡鍙锋瀯寤轰竴涓 RemainExtentHashTag 缁撴瀯锛岀敤浜庢爣璇嗗墿浣欐鐨勫搱甯岃〃鏉$洰銆 + * 3. 鑾峰彇鍓╀綑娈电殑鍝堝笇琛ㄩ攣锛屽苟灏濊瘯鍦ㄥ搱甯岃〃涓煡鎵捐鏉$洰锛屽鏋滄壘鍒拌〃绀鸿娈靛凡閲婃斁锛岃緭鍑鸿皟璇曚俊鎭 + * 4. 濡傛灉鏈壘鍒帮紝杈撳嚭璋冭瘯淇℃伅琛ㄧず鏈壘鍒拌娈点 + * 5. 鏈鍚庯紝閲婃斁閿併 + */ +static void redo_xlog_forget_alloc_seg(Buffer buffer, const char *data, int data_len) { + // 棣栧厛妫鏌ユ暟鎹暱搴︽槸鍚︾鍚堥鏈燂紝濡傛灉涓嶇鍚堝垯杩斿洖銆 int first_part_data_len = sizeof(uint16) + sizeof(df_map_page_t); if (data_len <= first_part_data_len) { Assert(data_len == first_part_data_len); @@ -387,14 +684,14 @@ static void redo_xlog_forget_alloc_seg(Buffer buffer, const char* data, int data } Assert(data_len == (sizeof(uint16) + sizeof(df_map_page_t) + sizeof(BlockNumber))); - BlockNumber* blk_num = (BlockNumber *)(data + sizeof(uint16) + sizeof(df_map_page_t)); + BlockNumber *blk_num = (BlockNumber *)(data + sizeof(uint16) + sizeof(df_map_page_t)); BufferDesc *bufDesc = GetBufferDescriptor(buffer - 1); RemainExtentHashTag remainExtentHashTag; remainExtentHashTag.rnode = bufDesc->tag.rnode; remainExtentHashTag.rnode.relNode = *blk_num; remainExtentHashTag.extentType = bufDesc->tag.rnode.relNode; - + AutoMutexLock remain_segs_lock(&g_instance.xlog_cxt.remain_segs_lock); remain_segs_lock.lock(); if (t_thrd.xlog_cxt.remain_segs == NULL) { @@ -402,26 +699,40 @@ static void redo_xlog_forget_alloc_seg(Buffer buffer, const char* data, int data } bool found = false; - ExtentTag* extentTag = (ExtentTag *)hash_search(t_thrd.xlog_cxt.remain_segs, (void *)&(remainExtentHashTag), - HASH_REMOVE, &found); + // 鍦ㄥ搱甯岃〃涓煡鎵捐鏉$洰 + ExtentTag *extentTag = + (ExtentTag *)hash_search(t_thrd.xlog_cxt.remain_segs, (void *)&(remainExtentHashTag), HASH_REMOVE, &found); + // 濡傛灉鎵惧埌锛岃〃绀鸿娈靛凡閲婃斁锛岃緭鍑鸿皟璇曚俊鎭 if (found) { ereport(DEBUG5, (errmodule(MOD_SEGMENT_PAGE), errmsg("Segment [%u, %u, %u, %d] is really freed after" - "drop trxn committed, xid %lu, remainExtentType %u.", REL_NODE_FORMAT(remainExtentHashTag.rnode), - extentTag->xid, extentTag->remainExtentType))); + "drop trxn committed, xid %lu, remainExtentType %u.", + REL_NODE_FORMAT(remainExtentHashTag.rnode), extentTag->xid, + extentTag->remainExtentType))); } else { + // 濡傛灉鏈壘鍒帮紝杈撳嚭璋冭瘯淇℃伅琛ㄧず鏈壘鍒拌娈 ereport(DEBUG5, (errmodule(MOD_SEGMENT_PAGE), errmsg("Segment [%u, %u, %u, %d] is not found" - "in remain segs htbl.", REL_NODE_FORMAT(remainExtentHashTag.rnode)))); + "in remain segs htbl.", + REL_NODE_FORMAT(remainExtentHashTag.rnode)))); } + // 閲婃斁鍝堝笇琛ㄩ攣 remain_segs_lock.unLock(); } - -static void redo_xlog_log_shrink_extent(Buffer buffer, const char* data) +/* + * 鍔熻兘锛氬鐞嗛噸鍋氭搷浣滀腑鏀剁缉娈电殑璁板綍 + * + * 鍙傛暟鍒楄〃锛 + * buffer锛氬緟澶勭悊鐨勭紦鍐插尯 + * data锛歑Log 閲嶅仛璁板綍涓殑鏁版嵁 + */ +static void redo_xlog_log_shrink_extent(Buffer buffer, const char *data) { XLogMoveExtent *xlog_data = (XLogMoveExtent *)data; SegmentCheck(xlog_data->old_extent != InvalidBlockNumber); + // 鑾峰彇鍓╀綑娈靛搱甯岃〃閿侊紝纭繚绾跨▼瀹夊叏 AutoMutexLock remain_segs_lock(&g_instance.xlog_cxt.remain_segs_lock); remain_segs_lock.lock(); + // 濡傛灉鍓╀綑娈靛搱甯岃〃涓嶅瓨鍦紝鍒欏垱寤轰竴涓柊鐨勫搱甯岃〃 if (t_thrd.xlog_cxt.remain_segs == NULL) { t_thrd.xlog_cxt.remain_segs = redo_create_remain_segs_htbl(); } @@ -436,120 +747,186 @@ static void redo_xlog_log_shrink_extent(Buffer buffer, const char* data) remainExtentHashTag.rnode.bucketNode = SegmentBktId; /* extentType is calculated by extent id */ remainExtentHashTag.extentType = EXTENT_SIZE_TO_TYPE(ExtentSizeByCount(xlog_data->extent_id)); - - ExtentTag* extentTag = (ExtentTag *)hash_search(t_thrd.xlog_cxt.remain_segs, (void *)&remainExtentHashTag, - HASH_ENTER, &found); + + // 鍦ㄥ搱甯岃〃涓煡鎵捐鏉$洰锛屽鏋滄壘鍒帮紝杈撳嚭璀﹀憡淇℃伅琛ㄧず宸叉壘鍒拌娈 + ExtentTag *extentTag = + (ExtentTag *)hash_search(t_thrd.xlog_cxt.remain_segs, (void *)&remainExtentHashTag, HASH_ENTER, &found); if (found) { - ereport(WARNING, (errmsg("Segment [%u, %u, %u, %d] Extent %u should not be repeatedly founded, xid %lu," - "remainExtentType %u", REL_NODE_FORMAT(remainExtentHashTag.rnode), xlog_data->old_extent, extentTag->xid, - extentTag->remainExtentType))); + ereport(WARNING, (errmsg("Segment [%u, %u, %u, %d] Extent %u should not be repeatedly founded, xid %lu," + "remainExtentType %u", + REL_NODE_FORMAT(remainExtentHashTag.rnode), xlog_data->old_extent, extentTag->xid, + extentTag->remainExtentType))); } else { + // 濡傛灉鏈壘鍒帮紝灏嗚娈电殑淇℃伅娣诲姞鍒板搱甯岃〃锛屽苟鏍囪涓 SHRINK_EXTENT 绫诲瀷 extentTag->remainExtentType = SHRINK_EXTENT; extentTag->forkNum = xlog_data->forknum; - + extentTag->xid = InvalidTransactionId; extentTag->lsn = InvalidXLogRecPtr; - ereport(DEBUG5, (errmodule(MOD_SEGMENT_PAGE), errmsg("Segment [%u, %u, %u, %d] Extent %u is replaced " - "during shrinking in shrink extents.", REL_NODE_FORMAT(remainExtentHashTag.rnode), xlog_data->old_extent))); + ereport(DEBUG5, (errmodule(MOD_SEGMENT_PAGE), + errmsg("Segment [%u, %u, %u, %d] Extent %u is replaced " + "during shrinking in shrink extents.", + REL_NODE_FORMAT(remainExtentHashTag.rnode), xlog_data->old_extent))); } + // 閲婃斁鍝堝笇琛ㄩ攣 remain_segs_lock.unLock(); } - -void redo_xlog_deal_alloc_seg(uint8 opCode, Buffer buffer, const char* data, int data_len, TransactionId xid) +/* + * 澶勭悊閲嶅仛鎿嶄綔涓殑鍒嗛厤娈靛拰閲婃斁娈电殑璁板綍 + * + * 鍙傛暟鍒楄〃锛 + * opCode锛氭搷浣滅爜锛屾寚绀洪噸鍋氳褰曠殑绫诲瀷 + * buffer锛氬緟澶勭悊鐨勭紦鍐插尯 + * data锛歑Log 閲嶅仛璁板綍涓殑鏁版嵁 + * data_len锛歑Log 閲嶅仛璁板綍鏁版嵁鐨勯暱搴 + * xid锛氫簨鍔 ID + */ +void redo_xlog_deal_alloc_seg(uint8 opCode, Buffer buffer, const char *data, int data_len, TransactionId xid) { if (opCode == SPCXLOG_INIT_SEGHEAD) { + // 妫鏌ユ槸鍚︽槸鍒濆鍖栨澶磋褰 unsigned char is_seg_head = *(unsigned char *)(data + sizeof(XLogRecPtr)); if (is_seg_head == 0) { return; } + // 璋冪敤 redo_xlog_log_alloc_seg 澶勭悊鍒濆鍖栨澶寸殑璁板綍 redo_xlog_log_alloc_seg(buffer, xid); } else if (opCode == SPCXLOG_INIT_BUCKET_HEAD) { + // 澶勭悊鍒濆鍖栨《澶磋褰曪紝璋冪敤 redo_xlog_log_alloc_seg 澶勭悊 redo_xlog_log_alloc_seg(buffer, xid); } else if (opCode == SPCXLOG_FREE_BITMAP) { + // 澶勭悊閲婃斁娈电殑璁板綍锛岃皟鐢 redo_xlog_forget_alloc_seg 澶勭悊 redo_xlog_forget_alloc_seg(buffer, data, data_len); } else if (opCode == SPCXLOG_SHRINK_SEGHEAD_UPDATE) { + // 澶勭悊鍒嗛厤娈电殑璁板綍锛岃皟鐢 redo_xlog_log_shrink_extent 澶勭悊 redo_xlog_log_shrink_extent(buffer, data); } } - +/* + * 鍔熻兘锛氬鐞嗗師瀛愰噸鍋氭棩蹇楀垎鍙 + * + * 鍙傛暟鍒楄〃锛 + * opCode锛氶噸鍋氭搷浣滅殑浠g爜 + * redo_buf锛氶噸鍋氱紦鍐插尯淇℃伅 + * data锛歑Log 閲嶅仛璁板綍涓殑鏁版嵁 + * + * 娉ㄦ剰锛 + * 1. 璇ュ嚱鏁扮敤浜庢牴鎹噸鍋氭搷浣滅殑浠g爜鍒嗗彂涓嶅悓鐨勫鐞嗗嚱鏁般 + * 2. 鏍规嵁 opCode 鐨勪笉鍚岋紝璋冪敤鐩稿簲鐨勫鐞嗗嚱鏁版潵澶勭悊閲嶅仛鎿嶄綔銆 + */ void redo_atomic_xlog_dispatch(uint8 opCode, RedoBufferInfo *redo_buf, const char *data) { Buffer buffer = redo_buf->buf; + /* 杈撳嚭璋冭瘯淇℃伅锛屾樉绀 opCode */ ereport(DEBUG5, (errmodule(MOD_SEGMENT_PAGE), errmsg("redo_atomic_xlog_dispatch opCode: %u", opCode))); if (opCode == SPCXLOG_SET_BITMAP) { + /* 澶勭悊璁剧疆浣嶅浘鐨勯噸鍋氭搷浣 */ redo_set_bitmap(redo_buf->blockinfo, buffer, data); } else if (opCode == SPCXLOG_FREE_BITMAP) { + /* 澶勭悊璁剧疆浣嶅浘鐨勯噸鍋氭搷浣 */ redo_unset_bitmap(buffer, data); } else if (opCode == SPCXLOG_MAPHEAD_ALLOCATED_EXTENTS) { + /* 澶勭悊鏄犲皠澶村垎閰嶆墿灞曠殑閲嶅仛鎿嶄綔 */ redo_maphead_allocated_extents(buffer, data); } else if (opCode == SPCXLOG_INIT_SEGHEAD) { + /* 澶勭悊鍒濆鍖栨澶寸殑閲嶅仛鎿嶄綔 */ redo_init_seghead(buffer, data); } else if (opCode == SPCXLOG_UPDATE_SEGHEAD) { + /* 澶勭悊鏇存柊娈靛ご鐨勯噸鍋氭搷浣 */ redo_update_seghead(buffer, data); } else if (opCode == SPCXLOG_NEW_LEVEL0_PAGE) { + /* 澶勭悊鍒涘缓鏂扮殑 Level0 椤电殑閲嶅仛鎿嶄綔 */ redo_new_level0_page(buffer, data); } else if (opCode == SPCXLOG_LEVEL0_PAGE_ADD_EXTENT) { + /* 澶勭悊 Level0 椤垫坊鍔犳墿灞曠殑閲嶅仛鎿嶄綔 */ redo_level0_page_add_extent(buffer, data); } else if (opCode == SPCXLOG_SEGHEAD_ADD_FORK_SEGMENT) { + /* 澶勭悊娈靛ご娣诲姞鍒嗘鐨勯噸鍋氭搷浣 */ redo_seghead_add_fork_segment(buffer, data); } else if (opCode == SPCXLOG_UNLINK_SEGHEAD_PTR) { + /* 澶勭悊鍙栨秷閾炬帴娈靛ご鎸囬拡鐨勯噸鍋氭搷浣 */ redo_unlink_seghead_ptr(buffer, data); } else if (opCode == SPCXLOG_INIT_BUCKET_HEAD) { + /* 澶勭悊鍒濆鍖栨《涓诲ご鐨勯噸鍋氭搷浣 */ redo_init_bucket_main_head(buffer, data); } else if (opCode == SPCXLOG_BUCKET_FREE_MAPBLOCK) { + /* 澶勭悊閲婃斁妗跺湴鍥惧潡鐨勯噸鍋氭搷浣 */ redo_bucket_free_mapblock(buffer, data); } else if (opCode == SPCXLOG_BUCKET_ADD_MAPBLOCK) { + /* 澶勭悊娣诲姞妗跺湴鍥惧潡鐨勯噸鍋氭搷浣 */ redo_bucket_add_mapblock(buffer, data); } else if (opCode == SPCXLOG_BUCKET_INIT_MAPBLOCK) { + /* 澶勭悊鍒濆鍖栨《鍦板浘鍧楃殑閲嶅仛鎿嶄綔 */ redo_bucket_init_mapblock(buffer, data); } else if (opCode == SPCXLOG_BUCKET_ADD_BKTHEAD) { + /* 澶勭悊娣诲姞妗朵富澶寸殑閲嶅仛鎿嶄綔 */ redo_bucket_add_bkthead(buffer, data); } else if (opCode == SPCXLOG_SPACE_UPDATE_HWM) { + /* 澶勭悊鏇存柊绌洪棿楂樻按浣嶆爣璁扮殑閲嶅仛鎿嶄綔 */ redo_space_update_hwm(buffer, data); } else if (opCode == SPCXLOG_SET_INVERSE_POINTER) { + /* 澶勭悊璁剧疆閫嗗悜鎸囬拡鐨勯噸鍋氭搷浣 */ redo_set_inverse_pointer(buffer, data); } else if (opCode == SPCXLOG_SEG_MOVE_BUCKETS) { + /* 澶勭悊娈电Щ鍔ㄦ《鐨勯噸鍋氭搷浣 */ redo_move_buckets(buffer, data); } else if (opCode == SPCXLOG_BUCKET_ADD_REDISINFO) { + /* 澶勭悊娣诲姞妗 Redis 淇℃伅鐨勯噸鍋氭搷浣 */ redo_bucket_add_redisinfo(buffer, data); } else { + /* 榛樿澶勭悊鏀剁缉娈靛ご鏇存柊鐨勯噸鍋氭搷浣 */ SegmentCheck(opCode == SPCXLOG_SHRINK_SEGHEAD_UPDATE); redo_shrink_seghead_update(buffer, data); } } - +/* + * 鍒锋柊绉诲姩鐨勬鍒扮鐩 + * + * 鍙傛暟鍒楄〃锛 + * xlog_data锛氶噸鍋氳褰曚腑鐨勭Щ鍔ㄦ鏁版嵁 + */ void move_extent_flush_buffer(XLogMoveExtent *xlog_data) { BlockNumber logic_start = ExtentIdToLogicBlockNum(xlog_data->extent_id); - for (int i=0; iextent_id); i++) { + for (int i = 0; i < ExtentSizeByCount(xlog_data->extent_id); i++) { BlockNumber blk = logic_start + i; + // 濡傛灉鍧楀彿瓒呰繃浜嗘鐨勫潡鏁帮紝璺冲嚭寰幆 if (blk >= xlog_data->nblocks) { break; } + // 灏濊瘯鑾峰彇绉诲姩鍚庣殑椤甸潰缂撳啿鍖 Buffer buffer = try_get_moved_pagebuf(&xlog_data->logic_rnode, xlog_data->forknum, blk); if (BufferIsValid(buffer)) { BlockNumber old_seg_blockno = xlog_data->old_extent + i; BlockNumber new_seg_blockno = xlog_data->new_extent + i; BufferDesc *buf_desc = BufferGetBufferDescriptor(buffer); + // 濡傛灉缂撳啿鍖虹殑娈靛潡鍙风瓑浜庢棫娈靛潡鍙 if (buf_desc->seg_blockno == old_seg_blockno) { uint32 buf_state = LockBufHdr(buf_desc); + // 濡傛灉缂撳啿鍖烘爣璁颁负鑴 if (buf_state & BM_DIRTY) { /* spin-lock should be released before IO */ + // 閲婃斁鑷棆閿佷互鍏佽 IO 鎿嶄綔 UnlockBufHdr(buf_desc, buf_state); + // 閿佸畾缂撳啿鍖轰互杩涜鐙崰鍒锋柊 LockBuffer(buffer, BUFFER_LOCK_EXCLUSIVE); /* Flush data to the old block */ + // 鍒锋柊鏁版嵁鍒版棫鍧 FlushOneBufferIncludeDW(buf_desc); + // 瑙i攣缂撳啿鍖 LockBuffer(buffer, BUFFER_LOCK_UNLOCK); } else { UnlockBufHdr(buf_desc, buf_state); } /* It's dirty, but we must unpin buffer before InvalidateBuffer */ + // 鍦ㄦ棤鏁堝寲缂撳啿鍖轰箣鍓嶏紝蹇呴』瑙i櫎缂撳啿鍖虹殑寮曠敤 UnpinBuffer(buf_desc, true); buf_state = LockBufHdr(buf_desc); + // 濡傛灉缂撳啿鍖虹殑鑺傜偣淇℃伅鍖归厤 if (RelFileNodeEquals(buf_desc->tag.rnode, xlog_data->logic_rnode) && buf_desc->tag.forkNum == xlog_data->forknum && buf_desc->tag.blockNum == blk) { InvalidateBuffer(buf_desc); @@ -558,6 +935,7 @@ void move_extent_flush_buffer(XLogMoveExtent *xlog_data) } } else { /* Get here only because standby read after we modifiy the segment head */ + // 鍙湁鍦ㄤ富澶囨ā寮忎笅璇诲彇鍒版垜浠慨鏀规澶村悗鎵嶄細鎵ц鍒拌繖閲 SegmentCheck(buf_desc->seg_blockno == new_seg_blockno); UnpinBuffer(buf_desc, true); } @@ -607,7 +985,7 @@ static void redo_atomic_xlog(XLogReaderState *record) PageSetLSN(redo_buf.pageinfo.page, redo_buf.lsn); SegMarkBufferDirty(redo_buf.buf); } - + for (int j = 0; j < decoded_op.operations; j++) { if (decoded_op.op[j] == SPCXLOG_SHRINK_SEGHEAD_UPDATE) { need_flush_buffer_for_shrink = true; @@ -615,8 +993,7 @@ static void redo_atomic_xlog(XLogReaderState *record) } if (is_need_log_remain_segs) { - redo_xlog_deal_alloc_seg(decoded_op.op[j], redo_buf.buf, - decoded_op.data[j], decoded_op.data_len[j], + redo_xlog_deal_alloc_seg(decoded_op.op[j], redo_buf.buf, decoded_op.data[j], decoded_op.data_len[j], XLogRecGetXid(record)); } } @@ -795,7 +1172,6 @@ void seg_redo_new_page_copy_and_flush(BufferTag *tag, char *data, XLogRecPtr lsn t_thrd.proc->dw_pos = -1; } - /* * This xlog only copy data to the new block, without modifying data in buffer. If the logic block being in the * buffer pool, its pblk points to the old block. The buffer descriptor can not have the logic blocknumber and the new diff --git a/src/gausskernel/storage/smgr/segstore.cpp b/src/gausskernel/storage/smgr/segstore.cpp index f2ddbfc34..5c6ec005a 100755 --- a/src/gausskernel/storage/smgr/segstore.cpp +++ b/src/gausskernel/storage/smgr/segstore.cpp @@ -94,14 +94,25 @@ * 1. drop table. * 2. delete a list of buckets during redistributing. */ +/* + * 鍔熻兘锛氭洿鏂板叡浜唴瀛樻鐨勬椂闂磋酱淇℃伅銆 + */ static void seg_update_timeline() { - pg_atomic_add_fetch_u32(&g_instance.segment_cxt.segment_drop_timeline, 1); + // 浣跨敤 pg_atomic_add_fetch_u32 鍑芥暟鏉ュ師瀛愬湴澧炲姞涓涓32浣嶆棤绗﹀彿鏁存暟鐨勫 + pg_atomic_add_fetch_u32(&g_instance.segment_cxt.segment_drop_timeline, 1); // 鍘熷瓙鎿嶄綔鍑芥暟 } - +/* + * 鍔熻兘锛氳幏鍙栧叡浜唴瀛樻鐨勬椂闂磋酱淇℃伅 + */ static uint32 seg_get_drop_timeline() { + // 鍒涘缓涓涓悕涓 expected 鐨勬湰鍦板彉閲忥紝鍒濆鍖栦负 0 uint32 expected = 0; + // 鍒涘缓涓涓悕涓 expected 鐨勬湰鍦板彉閲忥紝鍒濆鍖栦负 0 + // 杩欎釜鍑芥暟鐨勭洰鐨勬槸灏 g_instance.segment_cxt.segment_drop_timeline 鐨勫间笌 expected 杩涜姣旇緝 + // 濡傛灉鐩哥瓑锛屽垯灏 g_instance.segment_cxt.segment_drop_timeline 鐨勫艰缃负 0 + // 杩欎釜鎿嶄綔鏄師瀛愮殑锛岀‘淇濆湪澶氱嚎绋嬫垨澶氳繘绋嬬幆澧冧腑鐨勪竴鑷存 pg_atomic_compare_exchange_u32(&g_instance.segment_cxt.segment_drop_timeline, &expected, 0); return expected; } @@ -111,29 +122,55 @@ struct SegmentHeadLockPartitionTag { Oid dbNode; BlockNumber head; }; - +/* + * 鍔熻兘锛氶攣瀹氬垎娈靛ご閮ㄧ殑鐗瑰畾鍒嗗尯锛屼互杩涜鍚屾璁块棶 + * + * 鍙傛暟鍒楄〃锛 + * spcNode锛氳〃绀鸿〃绌洪棿鑺傜偣鐨勫敮涓鏍囪瘑绗 + * dbNode锛氳〃绀烘暟鎹簱鑺傜偣鐨勫敮涓鏍囪瘑绗 + * head锛氳〃绀哄垎娈靛ご閮ㄧ殑鍧楀彿 + * mode锛氳〃绀洪攣鐨勬ā寮忥紝渚嬪鍏变韩閿佹垨鎺掍粬閿 + */ void LockSegmentHeadPartition(Oid spcNode, Oid dbNode, BlockNumber head, LWLockMode mode) { + // 鍒涘缓涓涓 SegmentHeadLockPartitionTag 缁撴瀯浣 tag锛屽苟鍒濆鍖栧叾鎴愬憳鍙橀噺銆 SegmentHeadLockPartitionTag tag = {.spcNode = spcNode, .dbNode = dbNode, head = head}; + + // 浣跨敤鍝堝笇鍑芥暟 hashquickany 璁$畻涓涓搱甯岀爜锛屼互渚跨敤浜庨攣鐨勯夋嫨銆 uint32 hashcode = hashquickany(0xFFFFFFFF, (unsigned char *)&tag, sizeof(tag)); + + // 鏍规嵁鍝堝笇鐮侀夋嫨涓涓壒瀹氱殑 LWLock銆 LWLock *lock = SegmentHeadPartitionLock(hashcode); + + // 鑾峰彇鎸囧畾鐨 LWLock锛屼娇鐢ㄧ粰瀹氱殑閿佹ā寮 mode銆 LWLockAcquire(lock, mode); } - +/* + * 鍔熻兘锛氳В閿佸垎娈靛ご閮ㄧ殑鐗瑰畾鍒嗗尯锛屼互鍏佽鍏朵粬杩涚▼鎴栫嚎绋嬭闂 + * + * 鍙傛暟鍒楄〃锛 + * spcNode锛氳〃绀鸿〃绌洪棿鑺傜偣鐨勫敮涓鏍囪瘑绗 + * dbNode锛氳〃绀烘暟鎹簱鑺傜偣鐨勫敮涓鏍囪瘑绗 + * head锛氳〃绀哄垎娈靛ご閮ㄧ殑鍧楀彿 + */ void UnlockSegmentHeadPartition(Oid spcNode, Oid dbNode, BlockNumber head) { + // 鍒涘缓涓涓 SegmentHeadLockPartitionTag 缁撴瀯浣 tag锛屽苟鍒濆鍖栧叾鎴愬憳鍙橀噺銆 SegmentHeadLockPartitionTag tag = {.spcNode = spcNode, .dbNode = dbNode, head = head}; + // 浣跨敤鍝堝笇鍑芥暟 hashquickany 璁$畻涓涓搱甯岀爜锛屼互渚跨敤浜庨攣鐨勯夋嫨銆 uint32 hashcode = hashquickany(0xFFFFFFFF, (unsigned char *)&tag, sizeof(tag)); + // 鏍规嵁鍝堝笇鐮侀夋嫨涓涓壒瀹氱殑 LWLock銆 LWLock *lock = SegmentHeadPartitionLock(hashcode); + // 閲婃斁鎸囧畾鐨 LWLock锛屽厑璁稿叾浠栬繘绋嬫垨绾跨▼璁块棶銆 LWLockRelease(lock); } #define IsBucketSMgrRelation(reln) IsBucketFileNode((reln)->smgr_rnode.node) -#define ReadSegmentBuffer(spc, blockno) \ +#define ReadSegmentBuffer(spc, blockno) \ ReadBufferFast((spc), EXTENT_GROUP_RNODE((spc), SEGMENT_HEAD_EXTENT_SIZE), MAIN_FORKNUM, (blockno), RBM_NORMAL) -#define ReadLevel0Buffer(spc, blockno) \ +#define ReadLevel0Buffer(spc, blockno) \ ReadBufferFast((spc), EXTENT_GROUP_RNODE((spc), LEVEL0_PAGE_EXTENT_SIZE), MAIN_FORKNUM, (blockno), RBM_NORMAL) /* @@ -165,20 +202,51 @@ inline static void SegLogicPageIdToExtentId(BlockNumber logic_id, uint32 *extent *offset = logic_id % EXT_SIZE_8192; } } - +/* + * 鍔熻兘锛氳褰曞垎娈典腑鐨勬《绉诲姩鎿嶄綔鍒癤LOG + * + * 鍙傛暟鍒楄〃锛 + * mapentry锛氭寚鍚 xl_seg_bktentry_tag_t 缁撴瀯鐨勬寚閽堟暟缁勶紝琛ㄧず妗剁Щ鍔ㄧ殑淇℃伅 + * nentry锛氳〃绀 mapentry 鏁扮粍涓殑鏉$洰鏁伴噺 + * buffer锛氳〃绀鸿璁板綍鐨勭紦鍐插尯 + */ void log_move_segment_buckets(xl_seg_bktentry_tag_t *mapentry, uint32 nentry, Buffer buffer) { + // 浣跨敤 XLogAtomicOpRegisterBuffer 鍑芥暟鏉ユ敞鍐屼竴涓紦鍐插尯浠ヨ褰 XLOG 淇℃伅銆 + // 鍙傛暟鍖呮嫭瑕佹敞鍐岀殑缂撳啿鍖猴紝鎸囧畾涓嶈褰曠紦鍐插尯鍥惧儚锛屾寚瀹氳褰曠殑鎿嶄綔绫诲瀷锛屼互鍙婃寚瀹氬湪鎻愪氦鏃惰В閿佸苟閲婃斁缂撳啿鍖恒 XLogAtomicOpRegisterBuffer(buffer, REGBUF_NO_IMAGE, SPCXLOG_SEG_MOVE_BUCKETS, XLOG_COMMIT_UNLOCK_RELEASE_BUFFER); + + // 浣跨敤 XLogAtomicOpRegisterBufData 鍑芥暟鏉ユ敞鍐屼竴涓垨澶氫釜鏁版嵁鍧椾互璁板綍鍦 XLOG 涓 + // 鍦ㄨ繖閲岋紝棣栧厛娉ㄥ唽 nentry 鐨勫硷紝琛ㄧず鍚庣画璁板綍鐨 mapentry 鏁扮粍鐨勬潯鐩暟閲忋 XLogAtomicOpRegisterBufData((char *)&nentry, sizeof(uint32)); + + // 鎺ヤ笅鏉ワ紝娉ㄥ唽 mapentry 鏁扮粍鐨勬暟鎹紝鏁版嵁鐨勯暱搴︿负 sizeof(xl_seg_bktentry_tag_t) * nentry銆 XLogAtomicOpRegisterBufData((char *)mapentry, sizeof(xl_seg_bktentry_tag_t) * nentry); } - +/* + * 鍔熻兘锛氳褰曞垎娈电殑Redis淇℃伅鍒癤LOG + * + * 鍙傛暟鍒楄〃锛 + * dredis锛氭寚鍚 SegRedisInfo 缁撴瀯鐨勬寚閽堬紝琛ㄧず鐩爣鍒嗘鐨凴edis淇℃伅 + * sredis锛氭寚鍚 SegRedisInfo 缁撴瀯鐨勬寚閽堬紝琛ㄧず婧愬垎娈电殑Redis淇℃伅 + * dbuffer锛氳〃绀虹洰鏍囧垎娈电殑缂撳啿鍖 + * sbuffer锛氳〃绀烘簮鍒嗘鐨勭紦鍐插尯 + */ void log_move_segment_redisinfo(SegRedisInfo *dredis, SegRedisInfo *sredis, Buffer dbuffer, Buffer sbuffer) { - XLogAtomicOpRegisterBuffer(dbuffer, REGBUF_NO_IMAGE, SPCXLOG_BUCKET_ADD_REDISINFO, XLOG_COMMIT_UNLOCK_RELEASE_BUFFER); + // 浣跨敤 XLogAtomicOpRegisterBuffer 鍑芥暟鏉ユ敞鍐岀洰鏍囧垎娈电殑缂撳啿鍖轰互璁板綍 XLOG 淇℃伅銆 + // 鍙傛暟鍖呮嫭瑕佹敞鍐岀殑缂撳啿鍖猴紝鎸囧畾涓嶈褰曠紦鍐插尯鍥惧儚锛屾寚瀹氳褰曠殑鎿嶄綔绫诲瀷锛屼互鍙婃寚瀹氬湪鎻愪氦鏃惰В閿佸苟閲婃斁缂撳啿鍖恒 + XLogAtomicOpRegisterBuffer(dbuffer, REGBUF_NO_IMAGE, SPCXLOG_BUCKET_ADD_REDISINFO, + XLOG_COMMIT_UNLOCK_RELEASE_BUFFER); + + // 浣跨敤 XLogAtomicOpRegisterBufData 鍑芥暟鏉ユ敞鍐岀洰鏍囧垎娈电殑 Redis 淇℃伅鐨勬暟鎹潡銆 XLogAtomicOpRegisterBufData((char *)dredis, sizeof(SegRedisInfo)); - XLogAtomicOpRegisterBuffer(sbuffer, REGBUF_NO_IMAGE, SPCXLOG_BUCKET_ADD_REDISINFO, XLOG_COMMIT_UNLOCK_RELEASE_BUFFER); + // 浣跨敤 XLogAtomicOpRegisterBuffer 鍑芥暟鏉ユ敞鍐屾簮鍒嗘鐨勭紦鍐插尯浠ヨ褰 XLOG 淇℃伅銆 + XLogAtomicOpRegisterBuffer(sbuffer, REGBUF_NO_IMAGE, SPCXLOG_BUCKET_ADD_REDISINFO, + XLOG_COMMIT_UNLOCK_RELEASE_BUFFER); + + // 浣跨敤 XLogAtomicOpRegisterBufData 鍑芥暟鏉ユ敞鍐屾簮鍒嗘鐨 Redis 淇℃伅鐨勬暟鎹潡銆 XLogAtomicOpRegisterBufData((char *)sredis, sizeof(SegRedisInfo)); } @@ -190,22 +258,33 @@ RelFileNode EXTENT_GROUP_RNODE(SegSpace *spc, ExtentSize extentSize) .bucketNode = SegmentBktId, .opt = 0}; } - -void seg_head_update_xlog(Buffer head_buffer, SegmentHead *seg_head, int level0_slot, - int level1_slot) +/* + * 鍔熻兘锛氳褰曟洿鏂板垎娈靛ご閮ㄤ俊鎭殑XLOG + * + * 鍙傛暟鍒楄〃锛 + * head_buffer锛氳〃绀哄垎娈靛ご閮ㄧ殑缂撳啿鍖 + * seg_head锛氭寚鍚 SegmentHead 缁撴瀯鐨勬寚閽堬紝琛ㄧず鍒嗘澶撮儴淇℃伅 + * level0_slot锛氳〃绀鸿鏇存柊鐨 level 0 鎻掓Ы鐨勭储寮曪紝濡傛灉涓嶉渶瑕佹洿鏂帮紝鍒欎负璐熸暟 + * level1_slot锛氳〃绀鸿鏇存柊鐨 level 1 鎻掓Ы鐨勭储寮曪紝濡傛灉涓嶉渶瑕佹洿鏂帮紝鍒欎负璐熸暟 + */ +void seg_head_update_xlog(Buffer head_buffer, SegmentHead *seg_head, int level0_slot, int level1_slot) { + // 鍒涘缓 XLogDataUpdateSegmentHead 缁撴瀯浣 xlog_data锛屽苟灏嗗叾鍒濆鍖栦负闆 XLogDataUpdateSegmentHead xlog_data; errno_t rc = memset_s(&xlog_data, sizeof(xlog_data), 0, sizeof(xlog_data)); securec_check(rc, "\0", "\0"); + // 璁剧疆瑕佽褰曞埌 XLOG 鐨勬暟鎹 xlog_data.level0_slot = level0_slot; xlog_data.level1_slot = level1_slot; + // 濡傛灉 level0_slot 澶т簬绛変簬0锛屽垯璁板綍 seg_head 涓搴旂储寮曠殑 level 0 鎻掓Ы鐨勫硷紝鍚﹀垯璁剧疆涓 InvalidBlockNumber if (level0_slot >= 0) { xlog_data.level0_value = seg_head->level0_slots[level0_slot]; } else { xlog_data.level0_value = InvalidBlockNumber; } + // 濡傛灉 level1_slot 澶т簬绛変簬0锛屽垯璁板綍 seg_head 涓搴旂储寮曠殑 level 1 鎻掓Ы鐨勫硷紝鍚﹀垯璁剧疆涓 InvalidBlockNumber if (level1_slot >= 0) { xlog_data.level1_value = seg_head->level1_slots[level1_slot]; } else { @@ -221,28 +300,43 @@ void seg_head_update_xlog(Buffer head_buffer, SegmentHead *seg_head, int level0_ XLogAtomicOpRegisterBuffer(head_buffer, REGBUF_KEEP_DATA, SPCXLOG_UPDATE_SEGHEAD, XLOG_COMMIT_KEEP_BUFFER_STATE); XLogAtomicOpRegisterBufData((char *)&xlog_data, sizeof(xlog_data)); } - +/* + * 鍔熻兘锛氬垵濮嬪寲鏂扮殑 Level 0 椤靛苟璁板綍鍒癤LOG + * + * 鍙傛暟鍒楄〃锛 + * spc锛氭寚鍚 SegSpace 缁撴瀯鐨勬寚閽堬紝琛ㄧず鍒嗘绌洪棿淇℃伅 + * new_extent_id锛氭柊鐨勮寖鍥撮〉鎵╁睍鏍囪瘑绗 + * seg_head_buffer锛氳〃绀哄垎娈靛ご閮ㄧ殑缂撳啿鍖 + * new_level0_page锛氭柊鐨 Level 0 椤靛彿 + * first_extent锛氱涓涓寖鍥撮〉鍙 + */ void seg_init_new_level0_page(SegSpace *spc, uint32_t new_extent_id, Buffer seg_head_buffer, BlockNumber new_level0_page, BlockNumber first_extent) { + // 浠 seg_head_buffer 涓幏鍙栧垎娈靛ご閮ㄤ俊鎭 SegmentHead *seg_head = (SegmentHead *)PageGetContents(BufferGetPage(seg_head_buffer)); + // 璇诲彇鏂扮殑 Level 0 缂撳啿鍖哄苟浠ユ帓浠栭攣鏂瑰紡閿佸畾瀹 Buffer new_level0_buffer = ReadLevel0Buffer(spc, new_level0_page); LockBuffer(new_level0_buffer, BUFFER_LOCK_EXCLUSIVE); Page level0_page = BufferGetPage(new_level0_buffer); + // 鍒濆鍖 Level 0 椤 SegPageInit(level0_page, BLCKSZ); PageHeader header = (PageHeader)level0_page; header->pd_lower += sizeof(BMTLevel0Page); + // 鑾峰彇 Level 0 椤电殑鍐呭 BMTLevel0Page *bmt_level0_page = (BMTLevel0Page *)PageGetContents(level0_page); bmt_level0_page->slots[0] = first_extent; bmt_level0_page->magic = BMTLEVEL0_MAGIC; + // 璁$畻鏂拌寖鍥撮〉鐨 Level 1 鎻掓Ы uint32 level1_slot = ExtentIdToLevel1Slot(new_extent_id); seg_head->level1_slots[level1_slot] = new_level0_page; // XLog issue + // 澶勭悊 XLog 闂 { // new level0 page, we do not use level0 page buffer anymore, release it. XLogAtomicOpRegisterBuffer(new_level0_buffer, REGBUF_WILL_INIT | REGBUF_KEEP_DATA, SPCXLOG_NEW_LEVEL0_PAGE, @@ -253,20 +347,33 @@ void seg_init_new_level0_page(SegSpace *spc, uint32_t new_extent_id, Buffer seg_ seg_head_update_xlog(seg_head_buffer, seg_head, -1, level1_slot); } } - +/* + * 鍔熻兘锛氳褰曟柊鑼冨洿椤靛湪 Level 0 椤典笂鐨勪俊鎭埌XLOG + * + * 鍙傛暟鍒楄〃锛 + * spc锛氭寚鍚 SegSpace 缁撴瀯鐨勬寚閽堬紝琛ㄧず鍒嗘绌洪棿淇℃伅 + * seg_head_buffer锛氳〃绀哄垎娈靛ご閮ㄧ殑缂撳啿鍖 + * new_extent_id锛氭柊鐨勮寖鍥撮〉鎵╁睍鏍囪瘑绗 + * new_extent_first_pageno锛氭柊鑼冨洿椤电殑绗竴涓〉鍙 + */ void seg_record_new_extent_on_level0_page(SegSpace *spc, Buffer seg_head_buffer, uint32 new_extent_id, BlockNumber new_extent_first_pageno) { + // 浠 seg_head_buffer 涓幏鍙栧垎娈靛ご閮ㄤ俊鎭 SegmentHead *seg_head = (SegmentHead *)PageGetContents(BufferGetPage(seg_head_buffer)); + // 璁$畻鏂拌寖鍥撮〉鐨 Level 1 鎻掓Ы uint32 level1_slot = ExtentIdToLevel1Slot(new_extent_id); + // 鑾峰彇瀵瑰簲鐨 Level 0 椤靛彿鍜屽湪 Level 0 椤典腑鐨勫亸绉婚噺 BlockNumber level0_pageno = seg_head->level1_slots[level1_slot]; uint32 level0_offset = ExtentIdToLevel0PageOffset(new_extent_id); + // 璇诲彇骞堕攣瀹 Level 0 缂撳啿鍖猴紝骞惰幏鍙栧叾鍐呭 Buffer level0_buffer = ReadLevel0Buffer(spc, level0_pageno); BMTLevel0Page *bmt_level0_page = (BMTLevel0Page *)PageGetContents(BufferGetPage(level0_buffer)); LockBuffer(level0_buffer, BUFFER_LOCK_EXCLUSIVE); + // 鏇存柊 Level 0 椤典笂瀵瑰簲鍋忕Щ閲忕殑 slot 涓烘柊鑼冨洿椤电殑绗竴涓〉鍙 bmt_level0_page->slots[level0_offset] = new_extent_first_pageno; // XLogIssue @@ -325,31 +432,52 @@ void seg_extend_segment(SegSpace *spc, ForkNumber forknum, Buffer seg_head_buffe } } SEGMENTTEST(SEG_STORE_EXTEND_EXTENT, (errmsg("SEG_STORE_EXTEND_EXTENT %s: segment extend an extent!\n", - g_instance.attr.attr_common.PGXCNodeName))); + g_instance.attr.attr_common.PGXCNodeName))); XLogAtomicOpCommit(); END_CRIT_SECTION(); } - +/* + * 鍔熻兘锛氳幏鍙栬寖鍥撮〉鐨勪綅缃俊鎭 + * + * 鍙傛暟鍒楄〃锛 + * spc锛氭寚鍚 SegSpace 缁撴瀯鐨勬寚閽堬紝琛ㄧず鍒嗘绌洪棿淇℃伅 + * seg_head锛氭寚鍚 SegmentHead 缁撴瀯鐨勬寚閽堬紝琛ㄧず鍒嗘澶撮儴淇℃伅 + * extent_id锛氳寖鍥撮〉鎵╁睍鏍囪瘑绗 + */ BlockNumber seg_extent_location(SegSpace *spc, SegmentHead *seg_head, int extent_id) { + // 濡傛灉 extent_id 灏忎簬 BMT_HEADER_LEVEL0_SLOTS锛屽垯鐩存帴杩斿洖 seg_head 涓搴旂储寮曠殑 level 0 鎻掓Ы鐨勫 if (extent_id < BMT_HEADER_LEVEL0_SLOTS) { return seg_head->level0_slots[extent_id]; } else { + // 濡傛灉 extent_id 灏忎簬 BMT_HEADER_LEVEL0_SLOTS锛屽垯鐩存帴杩斿洖 seg_head 涓搴旂储寮曠殑 level 0 鎻掓Ы鐨勫 BlockNumber level0_page_id = ExtentIdToLevel0PageNumber(seg_head, extent_id); + // 璇诲彇 Level 0 缂撳啿鍖哄苟浠ュ叡浜攣鏂瑰紡閿佸畾瀹 Buffer buffer = ReadLevel0Buffer(spc, level0_page_id); LockBuffer(buffer, BUFFER_LOCK_SHARE); + // 鑾峰彇 Level 0 椤电殑鍐呭 BMTLevel0Page *level0_page = (BMTLevel0Page *)PageGetContents(BufferGetPage(buffer)); + // 璁$畻鍦 Level 0 椤典腑鐨勫亸绉婚噺 extent_id -= BMT_HEADER_LEVEL0_SLOTS; + // 鑾峰彇鑼冨洿椤电殑璧峰椤靛彿锛屽苟閲婃斁 Level 0 缂撳啿鍖 BlockNumber start = level0_page->slots[extent_id % BMT_LEVEL0_SLOTS]; SegUnlockReleaseBuffer(buffer); + // 杩斿洖鑼冨洿椤电殑璧峰椤靛彿 return start; } } - +/* + * 鍔熻兘锛氬皢閫昏緫椤靛彿鏄犲皠鍒扮墿鐞嗛〉鍙峰苟杩斿洖鐩稿叧淇℃伅 + * + * 鍙傛暟鍒楄〃锛 + * reln锛歋MgrRelation 缁撴瀯锛岃〃绀哄瓨鍌ㄧ鐞嗗櫒鍏崇郴淇℃伅 + * seg_head锛氭寚鍚 SegmentHead 缁撴瀯鐨勬寚閽堬紝琛ㄧず鍒嗘澶撮儴淇℃伅 + * logic_id锛氶昏緫椤靛彿 + */ SegPageLocation seg_logic_to_physic_mapping(SMgrRelation reln, SegmentHead *seg_head, BlockNumber logic_id) { uint32 extent_id; @@ -363,11 +491,15 @@ SegPageLocation seg_logic_to_physic_mapping(SMgrRelation reln, SegmentHead *seg_ errhint("cannot do segment address translation during recovery"))); } + // 灏嗛昏緫椤靛彿杞崲涓鸿寖鍥撮〉鎵╁睍鏍囪瘑绗︺佸亸绉婚噺鍜岃寖鍥撮〉澶у皬 SegLogicPageIdToExtentId(logic_id, &extent_id, &offset, &extent_size); + // 鑾峰彇鑼冨洿椤电殑璧峰椤靛彿 BlockNumber extent_start = seg_extent_location(reln->seg_space, seg_head, extent_id); + // 璁$畻鐗╃悊椤靛彿 blocknum = extent_start + offset; + // 杩斿洖 SegPageLocation 缁撴瀯锛屽寘鍚墿鐞嗛〉鍙峰拰鐩稿叧淇℃伅 return { .extent_size = extent_size, .extent_id = extent_id, @@ -397,7 +529,7 @@ static bool open_segment(SMgrRelation reln, ForkNumber forknum, bool create, XLo /* Normal Table Segment Head API */ static bool normal_open_segment(SMgrRelation reln, int forknum, bool create); static BlockNumber normal_alloc_segment(Oid tablespace_id, Oid database_id, BlockNumber preassigned_block, - ExtentInversePointer iptr, bool is_heap_seg_head=false); + ExtentInversePointer iptr, bool is_heap_seg_head = false); void eg_init_segment_head_buffer_content(Buffer seg_head_buffer, BlockNumber seg_head_blocknum, XLogRecPtr lsn) { @@ -479,11 +611,12 @@ static bool normal_open_segment(SMgrRelation reln, int forknum, bool create) main_buffer = ReadSegmentBuffer(reln->seg_space, reln->seg_desc[MAIN_FORKNUM]->head_blocknum); main_head = (SegmentHead *)PageGetContents(BufferGetBlock(main_buffer)); if (unlikely(!IsNormalSegmentHead(main_head))) { - ereport(PANIC, (errmodule(MOD_SEGMENT_PAGE), errmsg("Segment head magic value 0x%lx is invalid," - "head lsn 0x%lx(maybe wrong). Rnode [%u, %u, %u, %d], head blocknum %u.", - main_head->magic, main_head->lsn, reln->smgr_rnode.node.spcNode, reln->smgr_rnode.node.dbNode, - reln->smgr_rnode.node.relNode, reln->smgr_rnode.node.bucketNode, - reln->seg_desc[MAIN_FORKNUM]->head_blocknum))); + ereport(PANIC, (errmodule(MOD_SEGMENT_PAGE), + errmsg("Segment head magic value 0x%lx is invalid," + "head lsn 0x%lx(maybe wrong). Rnode [%u, %u, %u, %d], head blocknum %u.", + main_head->magic, main_head->lsn, reln->smgr_rnode.node.spcNode, + reln->smgr_rnode.node.dbNode, reln->smgr_rnode.node.relNode, + reln->smgr_rnode.node.bucketNode, reln->seg_desc[MAIN_FORKNUM]->head_blocknum))); } /* @@ -520,8 +653,9 @@ static bool normal_open_segment(SMgrRelation reln, int forknum, bool create) fork_head_blocknum = new_head_blocknum; XLogAtomicOpCommit(); - SEGMENTTEST(FREE_EXTENT_ADD_FSM_FORK, (errmsg("FREE_EXTENT_ADD_FSM_FORK %s: add fsm fork, free extent success!\n", - g_instance.attr.attr_common.PGXCNodeName))); + SEGMENTTEST(FREE_EXTENT_ADD_FSM_FORK, + (errmsg("FREE_EXTENT_ADD_FSM_FORK %s: add fsm fork, free extent success!\n", + g_instance.attr.attr_common.PGXCNodeName))); ereport(DEBUG5, (errmodule(MOD_SEGMENT_PAGE), errmsg("Add fork %d for segment %u, fork head is %u", forknum, @@ -540,8 +674,7 @@ CREATE_DESC: /* * Initialize the segment descriptor in SMgrRelationData. */ - SegmentDesc *fork_desc = - (SegmentDesc *)MemoryContextAlloc(LocalSmgrStorageMemoryCxt(), sizeof(SegmentDesc)); + SegmentDesc *fork_desc = (SegmentDesc *)MemoryContextAlloc(LocalSmgrStorageMemoryCxt(), sizeof(SegmentDesc)); fork_desc->head_blocknum = fork_head_blocknum; fork_desc->timeline = seg_get_drop_timeline(); SegmentCheck(fork_head_blocknum >= DF_MAP_GROUP_SIZE); @@ -594,10 +727,11 @@ static void free_last_extent(SegSpace *spc, ForkNumber forknum, Buffer head_buff END_CRIT_SECTION(); SEGMENTTEST(FREE_EXTENT_DROP_EXTENTS, (errmsg("FREE_EXTENT_DROP_EXTENTS %s: " - "drop some extents,remain extents can drop !\n", g_instance.attr.attr_common.PGXCNodeName))); + "drop some extents,remain extents can drop !\n", + g_instance.attr.attr_common.PGXCNodeName))); XLogAtomicOpCommit(); - /* If all extents is freed, flush segment header to disk */ + /* If all extents is freed, flush segment header to disk */ if (head->total_blocks == 0) { SegmentCheck(head->nextents == 0); FlushOneSegmentBuffer(head_buffer); @@ -746,103 +880,165 @@ static void bucket_get_mapentry(BktMainHead *main_head, int4 bucketid, int forkn *map_blocknum = main_head->bkt_map[blockid]; SegmentCheck(*map_blocknum != 0); } - +/* + * 鍔熻兘锛氬垵濮嬪寲妗朵綅鍥鹃〉骞惰缃浉搴旂殑淇℃伅 + * + * 鍙傛暟鍒楄〃锛 + * map_buffer锛氳〃绀烘《浣嶅浘椤电殑缂撳啿鍖 + * lsn锛歑Log璁板綍浣嶇疆 + */ void bucket_init_map_page(Buffer map_buffer, XLogRecPtr lsn) { + // 鑾峰彇妗朵綅鍥鹃〉 Page map_page = BufferGetPage(map_buffer); + // 鍒濆鍖栨《浣嶅浘椤碉紝璁剧疆澶у皬涓 BLCKSZ锛堝潡澶у皬锛 SegPageInit(map_page, BLCKSZ); + // 鍒濆鍖栨《浣嶅浘椤碉紝璁剧疆澶у皬涓 BLCKSZ锛堝潡澶у皬锛 BktHeadMapBlock *map_block = (BktHeadMapBlock *)PageGetContents(map_page); + // 璁剧疆妗朵綅鍥鹃〉鐨勯瓟鏈暟瀛楀拰璁板綍浣嶇疆锛坙sn锛 map_block->magic = BUCKETMAP_MAGIC; map_block->lsn = lsn; + // 鍒濆鍖栨《浣嶅浘椤典腑鐨勬《浣嶅浘椤逛负鏃犳晥鍧楀彿 for (uint32 j = 0; j < BktMapEntryNumberPerBlock; j++) { map_block->head_block[j] = InvalidBlockNumber; } + // 澧炲姞妗朵綅鍥鹃〉鐨 pd_lower锛屼互琛ㄧず鏁版嵁鐨勭粨鏉熶綅缃 ((PageHeader)map_page)->pd_lower += sizeof(BktHeadMapBlock); } - +/* + * 鍔熻兘锛氬垎閰嶄竴涓柊鐨勬《娈 + * + * 鍙傛暟鍒楄〃锛 + * tablespace_id锛氳〃绌洪棿鐨勬爣璇嗙 + * database_id锛氭暟鎹簱鐨勬爣璇嗙 + * preassigned_block锛氶鍒嗛厤鐨勫潡鍙 + */ static BlockNumber bucket_alloc_segment(Oid tablespace_id, Oid database_id, BlockNumber preassigned_block) { + // 鎵撳紑鎸囧畾琛ㄧ┖闂村拰鏁版嵁搴撶殑鍒嗘绌洪棿 SegSpace *spc = spc_open(tablespace_id, database_id, true); + // 鍒涘缓涓涓嗗悜鎸囬拡锛屾爣璇嗕负妗舵锛圔UCKET_SEGMENT锛夛紝骞惰缃墍鏈夎呬负鏃犳晥鍧楀彿 ExtentInversePointer iptr = {.flag = SPC_INVRSPTR_ASSEMBLE_FLAG(BUCKET_SEGMENT, 0), .owner = InvalidBlockNumber}; /* Allocate BktMainHead first */ + // 寮濮嬩竴涓師瀛愭搷浣 XLogAtomicOpStart(); + // 鍒嗛厤 BktMainHead 鎵闇鐨勫潡鍙凤紝澶у皬涓 SEGMENT_HEAD_EXTENT_SIZE BlockNumber main_head_blocknum = spc_alloc_extent(spc, SEGMENT_HEAD_EXTENT_SIZE, MAIN_FORKNUM, InvalidBlockNumber, iptr); + // 璇诲彇鍒嗛厤鐨勫潡鍙峰搴旂殑缂撳啿鍖 Buffer main_head_buffer = ReadSegmentBuffer(spc, main_head_blocknum); + // 閿佸畾鍒嗛厤鐨勫潡鍙峰搴旂殑缂撳啿鍖猴紝浠ユ帓浠栭攣鏂瑰紡 LockBuffer(main_head_buffer, BUFFER_LOCK_EXCLUSIVE); + // 鑾峰彇 BktMainHead 鐨勯〉闈 Page main_head_page = BufferGetPage(main_head_buffer); + // 鑾峰彇 BktMainHead 鐨勯〉闈 SegPageInit(main_head_page, BLCKSZ); + // 澧炲姞 BktMainHead 椤甸潰鐨 pd_lower锛屼互琛ㄧず鏁版嵁鐨勭粨鏉熶綅缃 ((PageHeader)main_head_page)->pd_lower += sizeof(BktMainHead); + // 鑾峰彇 BktMainHead 缁撴瀯鐨勬寚閽 BktMainHead *main_head = (BktMainHead *)PageGetContents(main_head_page); + // 鑾峰彇褰撳墠 XLog 璁板綍浣嶇疆锛坙sn锛 XLogRecPtr lsn = GetXLogInsertRecPtr(); + // 璁剧疆 BktMainHead 鐨勯瓟鏈暟瀛椼乴sn銆乺edis_info 淇℃伅 main_head->magic = BUCKET_SEGMENT_MAGIC; main_head->lsn = lsn; main_head->redis_info.redis_xid = InvalidTransactionId; main_head->redis_info.nwords = 0; + // 娉ㄥ唽瑕佽褰曠殑缂撳啿鍖猴紝骞舵寚瀹氬皢鍒濆鍖栵紙WILL_INIT锛夌紦鍐插尯锛屼互鍙婅褰曞垵濮嬪寲鐨 XLOG 淇℃伅 XLogAtomicOpRegisterBuffer(main_head_buffer, REGBUF_WILL_INIT, SPCXLOG_INIT_BUCKET_HEAD, XLOG_COMMIT_KEEP_BUFFER_STATE); + // 娉ㄥ唽瑕佽褰曠殑鏁版嵁锛屽嵆璁板綍褰撳墠 XLog 璁板綍浣嶇疆锛坙sn锛 XLogAtomicOpRegisterBufData((char *)&lsn, sizeof(XLogRecPtr)); + // 鎻愪氦鍘熷瓙鎿嶄綔 XLogAtomicOpCommit(); + // 涓 BktMainHead 鍒嗛厤妗朵綅鍥惧潡锛圔ktMapBlock锛夛紝骞惰缃浉鍏 XLOG 璁板綍 for (uint32 i = 0; i < BktMapBlockNumber; i++) { bucket_ensure_mapblock(spc, main_head_buffer, i, lsn); } - + // 澧炲姞妗朵綅鍥鹃〉鐨 pd_lower锛屼互琛ㄧず鏁版嵁鐨勭粨鏉熶綅缃 SegUnlockReleaseBuffer(main_head_buffer); return main_head_blocknum; } - +/* + * 鍔熻兘锛氬姞杞芥《鐨勪富澶撮儴淇℃伅 + * + * 鍙傛暟鍒楄〃锛 + * spc锛氭寚鍚 SegSpace 缁撴瀯鐨勬寚閽堬紝琛ㄧず鍒嗘绌洪棿淇℃伅 + * blocknum锛氭《鐨勫潡鍙 + * buffer锛氱敤浜庤繑鍥炲姞杞界殑缂撳啿鍖 + * head锛氱敤浜庤繑鍥炲姞杞界殑 BktMainHead 缁撴瀯鎸囬拡 + */ static inline void bucket_load_main_head(SegSpace *spc, BlockNumber blocknum, Buffer *buffer, BktMainHead **head) { *buffer = ReadSegmentBuffer(spc, blocknum); *head = (BktMainHead *)PageGetContents(BufferGetPage(*buffer)); } - +/* + * 鍔熻兘锛氭墦寮鎴栧垱寤轰竴涓《娈碉紙bucket segment锛 + * + * 鍙傛暟鍒楄〃锛 + * reln锛歋MgrRelation 缁撴瀯锛岃〃绀哄瓨鍌ㄧ鐞嗗櫒鍏崇郴淇℃伅 + * forknum锛氬垎鍙夊彿 + * create锛氭槸鍚﹀垱寤 + * lsn锛歑Log 璁板綍浣嶇疆 + */ static bool bucket_open_segment(SMgrRelation reln, int forknum, bool create, XLogRecPtr lsn) { + // 濡傛灉宸茬粡瀛樺湪瀵瑰簲 forknum 鐨勫垎娈垫弿杩扮锛屽垯鐩存帴杩斿洖 true if (reln->seg_desc[forknum] != NULL) { return true; } + // 鐢ㄤ簬瀛樺偍妗剁殑涓诲ご閮ㄤ俊鎭殑缂撳啿鍖哄拰鎸囬拡 Buffer main_buffer; BktMainHead *main_head; + // 閫氳繃鍧楀彿鍔犺浇妗剁殑涓诲ご閮ㄤ俊鎭 bucket_load_main_head(reln->seg_space, reln->smgr_rnode.node.relNode, &main_buffer, &main_head); + // 妫鏌ュ姞杞界殑涓诲ご閮ㄤ俊鎭槸鍚︾鍚堥鏈 SegmentCheck(IsBucketMainHead(main_head)); + // 鑾峰彇妗剁殑缂栧彿 int4 bucketid = reln->smgr_rnode.node.bucketNode; /* find the map block */ + // 鏌ユ壘妗朵綅鍥句腑瀵瑰簲鐨勬《浣嶅浘鍧楀彿鍜屾《浣嶅浘椤 ID BlockNumber map_blocknum; int map_entry_id; bucket_get_mapentry(main_head, bucketid, forknum, &map_blocknum, &map_entry_id); - if (map_blocknum == InvalidBlockNumber) - { + // 濡傛灉妗朵綅鍥惧潡鍙蜂负鏃犳晥鍧楀彿锛屼笖鎻愪緵鐨 XLog 璁板綍浣嶇疆鏈夋晥锛屽垯杩斿洖 false + if (map_blocknum == InvalidBlockNumber) { SegmentCheck(XLogRecPtrIsValid(lsn)); SegReleaseBuffer(main_buffer); return false; } /* get the entry */ + // 鑾峰彇妗朵綅鍥惧潡鐨勭紦鍐插尯骞朵互鍏变韩閿佹柟寮忛攣瀹 Buffer map_buffer = ReadSegmentBuffer(reln->seg_space, map_blocknum); LockBuffer(map_buffer, BUFFER_LOCK_SHARE); BktHeadMapBlock *map_block = (BktHeadMapBlock *)PageGetContents(BufferGetPage(map_buffer)); + // 濡傛灉鎻愪緵鐨 XLog 璁板綍浣嶇疆鏈夋晥锛屽苟涓斾笉婊¤冻鏉′欢锛岃繑鍥 false if (XLogRecPtrIsValid(lsn) && (XLByteLE(lsn, map_block->lsn) || map_block->magic != BUCKETMAP_MAGIC)) { SegUnlockReleaseBuffer(map_buffer); SegReleaseBuffer(main_buffer); return false; } + // 鑾峰彇妗剁殑涓诲潡鍙 BlockNumber head_blocknum = map_block->head_block[map_entry_id]; + // 濡傛灉涓诲潡鍙蜂负鏃犳晥鍧楀彿 if (head_blocknum == InvalidBlockNumber) { /* the entry is not initialized */ + // 濡傛灉涓嶅厑璁稿垱寤猴紝鍒欒繑鍥 false if (create == false) { SegUnlockReleaseBuffer(map_buffer); SegReleaseBuffer(main_buffer); @@ -859,69 +1055,103 @@ static bool bucket_open_segment(SMgrRelation reln, int forknum, bool create, XLo * require/acquire above */ if (head_blocknum == InvalidBlockNumber) { + // 寮濮嬩竴涓師瀛愭搷浣 XLogAtomicOpStart(); + // 鍒涘缓閫嗗悜鎸囬拡锛屾爣璇嗕负妗跺ご閮紙BUCKET_HEAD锛 ExtentInversePointer iptr = { .flag = SPC_INVRSPTR_ASSEMBLE_FLAG(BUCKET_HEAD, forknum * MAX_BUCKETMAPLEN + reln->smgr_rnode.node.bucketNode), .owner = reln->smgr_rnode.node.relNode}; + // 鍒嗛厤涓诲潡鍙 head_blocknum = normal_alloc_segment(reln->smgr_rnode.node.spcNode, reln->smgr_rnode.node.dbNode, InvalidBlockNumber, iptr); + // 璁剧疆妗朵綅鍥惧潡涓搴旀《浣嶅浘椤圭殑涓诲潡鍙 map_block->head_block[map_entry_id] = head_blocknum; + // 娉ㄥ唽瑕佽褰曠殑妗朵綅鍥惧潡鐨勭紦鍐插尯锛屽苟鎸囧畾淇濇寔鏁版嵁锛圞EEP_DATA锛夛紝浠ュ強璁板綍鍒濆鍖栫殑 XLOG 淇℃伅 XLogAtomicOpRegisterBuffer(map_buffer, REGBUF_KEEP_DATA, SPCXLOG_BUCKET_ADD_BKTHEAD, XLOG_COMMIT_KEEP_BUFFER_STATE); + // 娉ㄥ唽瑕佽褰曠殑鏁版嵁锛屽寘鎷《浣嶅浘椤 ID 鍜屼富鍧楀彿 XLogAtomicOpRegisterBufData((char *)&map_entry_id, sizeof(int)); XLogAtomicOpRegisterBufData((char *)&head_blocknum, sizeof(BlockNumber)); XLogAtomicOpCommit(); + // 鐢ㄤ簬娴嬭瘯鐨勫畯锛岀敤浜庤褰曟彃鍏ヤ竴涓《涓殑鎵鏈夊 SEGMENTTEST(FREE_EXTENT_INSERT_ONE_BUCKET, (errmsg("FREE_EXTENT_INSERT_ONE_BUCKET %s: " - "all values insert into one bucket!\n", g_instance.attr.attr_common.PGXCNodeName))); + "all values insert into one bucket!\n", + g_instance.attr.attr_common.PGXCNodeName))); } } - SegmentDesc *seg_desc = - (SegmentDesc *)MemoryContextAlloc(LocalSmgrStorageMemoryCxt(), sizeof(SegmentDesc)); + // 鍒嗛厤骞跺垵濮嬪寲鍒嗘鎻忚堪绗 + SegmentDesc *seg_desc = (SegmentDesc *)MemoryContextAlloc(LocalSmgrStorageMemoryCxt(), sizeof(SegmentDesc)); seg_desc->head_blocknum = head_blocknum; seg_desc->timeline = seg_get_drop_timeline(); + // 妫鏌ヤ富鍧楀彿鏄惁澶т簬绛変簬 DF_MAP_GROUP_SIZE锛屽鏋滄槸锛岃〃绀烘湁鏁 SegmentCheck(head_blocknum >= DF_MAP_GROUP_SIZE); + // 灏嗗垎娈垫弿杩扮淇濆瓨鍒 SMgrRelation 缁撴瀯涓 reln->seg_desc[forknum] = seg_desc; + // 瑙i攣骞堕噴鏀炬《浣嶅浘鍧楃殑缂撳啿鍖 SegUnlockReleaseBuffer(map_buffer); + // 閲婃斁妗剁殑涓诲潡鍙风殑缂撳啿鍖 SegReleaseBuffer(main_buffer); return true; } - +/* + * 鍔熻兘锛氭柇寮涓涓《锛坆ucket锛変笌鐩稿叧娈碉紙segment锛夌殑杩炴帴 + * + * 鍙傛暟鍒楄〃锛 + * spc锛氭寚鍚 SegSpace 缁撴瀯鐨勬寚閽堬紝琛ㄧず鍒嗘绌洪棿淇℃伅 + * rnode锛歊elFileNode 缁撴瀯锛岃〃绀哄叧绯绘枃浠惰妭鐐逛俊鎭 + */ static void bucket_unlink_one_bucket(SegSpace *spc, const RelFileNode &rnode) { + // 鐢ㄤ簬瀛樺偍妗剁殑涓诲ご閮ㄤ俊鎭殑缂撳啿鍖哄拰鎸囬拡 Buffer main_buffer; BktMainHead *main_head; + // 閫氳繃鍧楀彿鍔犺浇妗剁殑涓诲ご閮ㄤ俊鎭 bucket_load_main_head(spc, rnode.relNode, &main_buffer, &main_head); + // 妫鏌ュ姞杞界殑涓诲ご閮ㄤ俊鎭槸鍚︾鍚堥鏈 SegmentCheck(IsBucketMainHead(main_head)); + // 浠ュ叡浜攣鏂瑰紡閿佸畾涓诲ご閮ㄤ俊鎭殑缂撳啿鍖 LockBuffer(main_buffer, BUFFER_LOCK_SHARE); + // 閬嶅巻鎵鏈夊彲鑳界殑鍒嗗弶鍙 for (int i = 0; i <= SEGMENT_MAX_FORKNUM; i++) { /* Locate the segment head for this fork */ BlockNumber map_blocknum; int map_entry_id; + // 鏌ユ壘妗朵綅鍥惧潡涓搴旂殑妗朵綅鍥惧潡鍧楀彿鍜屾《浣嶅浘椤 ID bucket_get_mapentry(main_head, rnode.bucketNode, i, &map_blocknum, &map_entry_id); + // 濡傛灉妗朵綅鍥惧潡鍧楀彿涓嶄负 0 if (map_blocknum != 0) { + // 鑾峰彇妗朵綅鍥惧潡鐨勭紦鍐插尯骞朵互鐙崰閿佹柟寮忛攣瀹 Buffer map_buffer = ReadSegmentBuffer(spc, map_blocknum); LockBuffer(map_buffer, BUFFER_LOCK_EXCLUSIVE); BktHeadMapBlock *map_block = (BktHeadMapBlock *)PageGetContents(BufferGetPage(map_buffer)); + // 妫鏌ュ姞杞界殑妗朵綅鍥惧潡鏄惁绗﹀悎棰勬湡 SegmentCheck(IsBucketMapBlock(map_block)); BlockNumber head_blocknum = map_block->head_block[map_entry_id]; + // 濡傛灉涓诲潡鍙蜂笉涓烘棤鏁堝潡鍙 if (head_blocknum != InvalidBlockNumber) { + // 鑾峰彇涓诲潡鐨勭紦鍐插尯骞朵互鐙崰閿佹柟寮忛攣瀹 Buffer head_buffer = ReadSegmentBuffer(spc, head_blocknum); LockBuffer(head_buffer, BUFFER_LOCK_EXCLUSIVE); + // 璁$畻妗朵綅鍥惧潡涓 head_block 鏁扮粍鐨勫亸绉婚噺 off_t offset = offsetof(BktHeadMapBlock, head_block) + sizeof(BlockNumber) * map_entry_id; + // 閲婃斁涓涓 free_one_segment(spc, i, head_buffer, head_blocknum, map_buffer, offset); + // 瑙i攣骞堕噴鏀句富鍧楃殑缂撳啿鍖 SegUnlockReleaseBuffer(head_buffer); } + // 瑙i攣骞堕噴鏀炬《浣嶅浘鍧楃殑缂撳啿鍖 SegUnlockReleaseBuffer(map_buffer); } } + // 瑙i攣骞堕噴鏀句富澶撮儴淇℃伅鐨勭紦鍐插尯 SegUnlockReleaseBuffer(main_buffer); } @@ -985,13 +1215,10 @@ static void bucket_unlink_segment(SegSpace *spc, RelFileNode rnode, Buffer main_ } } ereport(LOG, - (errmsg("rnode <%u %u %u %u>, xid [%lu, %lu, %lu], redis nwords %u, redis is [%s]", - rnode.spcNode, rnode.dbNode, rnode.relNode, rnode.bucketNode, - t_thrd.xact_cxt.ShmemVariableCache->oldestXid, - main_head->redis_info.redis_xid, - GetCurrentTransactionIdIfAny(), - main_head->redis_info.nwords, - redis_committed ? "committed" : "abort"))); + (errmsg("rnode <%u %u %u %u>, xid [%lu, %lu, %lu], redis nwords %u, redis is [%s]", rnode.spcNode, + rnode.dbNode, rnode.relNode, rnode.bucketNode, t_thrd.xact_cxt.ShmemVariableCache->oldestXid, + main_head->redis_info.redis_xid, GetCurrentTransactionIdIfAny(), main_head->redis_info.nwords, + redis_committed ? "committed" : "abort"))); } LockBuffer(main_buffer, BUFFER_LOCK_EXCLUSIVE); @@ -1016,7 +1243,8 @@ static void bucket_unlink_segment(SegSpace *spc, RelFileNode rnode, Buffer main_ ForkNumber forknum = (i * BktMapEntryNumberPerBlock + k) / MAX_BUCKETMAPLEN; free_one_segment(spc, forknum, head_buffer, head_blocknum, map_buffer, offset); SEGMENTTEST(FREE_EXTENT_DROP_BUCKETS, (errmsg("FREE_EXTENT_DROP_BUCKETS %s: " - "drop some buckets,remain buckets can drop !\n", g_instance.attr.attr_common.PGXCNodeName))); + "drop some buckets,remain buckets can drop !\n", + g_instance.attr.attr_common.PGXCNodeName))); SegUnlockReleaseBuffer(head_buffer); } } @@ -1031,70 +1259,115 @@ static void bucket_unlink_segment(SegSpace *spc, RelFileNode rnode, Buffer main_ LockBuffer(main_buffer, BUFFER_LOCK_UNLOCK); } - +/* + * 鍔熻兘锛氳绠楁寚瀹氬垎鏀殑鎵鏈夋《娈电殑鎬诲潡鏁 + * + * 鍙傛暟鍒楄〃锛 + * reln锛歋MgrRelation 缁撴瀯锛岃〃绀哄瓨鍌ㄧ鐞嗗櫒鍏崇郴淇℃伅 + * forknum锛欶orkNumber锛岃〃绀哄垎鏀彿 + * main_buffer锛欱uffer锛岃〃绀烘《鐨勪富澶撮儴淇℃伅鐨勭紦鍐插尯 + */ BlockNumber bucket_totalblocks(SMgrRelation reln, ForkNumber forknum, Buffer main_buffer) { + // 鎵撳紑鍒嗘绌洪棿 SMgrOpenSpace(reln); + // 鑾峰彇妗剁殑涓诲ご閮ㄤ俊鎭 BktMainHead *main_head = (BktMainHead *)PageGetContents(BufferGetPage(main_buffer)); + // 鑾峰彇鍒嗘绌洪棿淇℃伅 SegSpace *spc = reln->seg_space; + // 浠ュ叡浜攣鏂瑰紡閿佸畾涓诲ご閮ㄤ俊鎭殑缂撳啿鍖 LockBuffer(main_buffer, BUFFER_LOCK_SHARE); + // 鍒濆鍖栫粨鏋滃彉閲 BlockNumber result = 0; + // 鐢ㄤ簬瀛樺偍褰撳墠妗朵綅鍥惧潡鐨勫潡鍙峰拰涓婁竴涓《浣嶅浘鍧楃殑鍧楀彿 BlockNumber map_blocknum, last_map_blocknum = InvalidBlockNumber; + // 鐢ㄤ簬瀛樺偍妗朵綅鍥鹃」 ID int map_entry_id; + // 鍒濆鍖栨《浣嶅浘鍧楃紦鍐插尯涓烘棤鏁堢紦鍐插尯 Buffer map_buffer = InvalidBuffer; + // 閬嶅巻鎵鏈夊彲鑳界殑妗朵綅鍥鹃」 for (int i = 0; i < MAX_BUCKETMAPLEN; i++) { + // 鑾峰彇妗朵綅鍥惧潡涓殑妗朵綅鍥鹃」淇℃伅 bucket_get_mapentry(main_head, i, forknum, &map_blocknum, &map_entry_id); + // 濡傛灉褰撳墠妗朵綅鍥惧潡鍧楀彿涓庝笂涓涓笉鍚 if (map_blocknum != last_map_blocknum) { + // 濡傛灉涓婁竴涓《浣嶅浘鍧楃紦鍐插尯涓嶆槸鏃犳晥缂撳啿鍖猴紝鍒欒В閿佸苟閲婃斁瀹 if (map_buffer != InvalidBuffer) { SegUnlockReleaseBuffer(map_buffer); } + // 鑾峰彇褰撳墠妗朵綅鍥惧潡鐨勭紦鍐插尯骞朵互鍏变韩閿佹柟寮忛攣瀹 map_buffer = ReadSegmentBuffer(spc, map_blocknum); LockBuffer(map_buffer, BUFFER_LOCK_SHARE); + // 鏇存柊涓婁竴涓《浣嶅浘鍧楀潡鍙 last_map_blocknum = map_blocknum; } + // 鑾峰彇妗朵綅鍥惧潡鐨勫唴瀹 BktHeadMapBlock *map_block = (BktHeadMapBlock *)PageGetContents(BufferGetPage(map_buffer)); + // 妫鏌ュ姞杞界殑妗朵綅鍥惧潡鏄惁绗﹀悎棰勬湡 SegmentCheck(IsBucketMapBlock(map_block)); + // 鑾峰彇妗舵鐨勪富鍧楀彿 BlockNumber head_blocknum = map_block->head_block[map_entry_id]; + // 濡傛灉涓诲潡鍙蜂笉涓烘棤鏁堝潡鍙 if (head_blocknum != InvalidBlockNumber) { + // 鑾峰彇涓诲潡鐨勭紦鍐插尯 Buffer head_buffer = ReadSegmentBuffer(spc, head_blocknum); + // 鑾峰彇涓诲潡鐨勫唴瀹 SegmentHead *seg_head = (SegmentHead *)PageGetContents(BufferGetPage(head_buffer)); + // 浠ュ叡浜攣鏂瑰紡閿佸畾涓诲潡鐨勭紦鍐插尯锛屽苟绱姞妗舵鐨勫潡鏁板埌缁撴灉鍙橀噺 LockBuffer(head_buffer, BUFFER_LOCK_SHARE); result += seg_head->nblocks; + // 瑙i攣骞堕噴鏀句富鍧楃殑缂撳啿鍖 SegUnlockReleaseBuffer(head_buffer); } } + // 濡傛灉鏈鍚庝竴涓《浣嶅浘鍧楃殑缂撳啿鍖轰笉鏄棤鏁堢紦鍐插尯锛屽垯瑙i攣骞堕噴鏀惧畠 if (map_buffer != InvalidBuffer) { SegUnlockReleaseBuffer(map_buffer); } + // 瑙i攣涓诲ご閮ㄤ俊鎭殑缂撳啿鍖 LockBuffer(main_buffer, BUFFER_LOCK_UNLOCK); return result; } - +/* + * 鍔熻兘锛氭牴鎹昏緫鍧楀彿鑾峰彇鍒嗘鐨勭墿鐞嗕綅缃俊鎭 + * + * 鍙傛暟鍒楄〃锛 + * rnode锛歊elFileNode 缁撴瀯锛岃〃绀烘枃浠惰妭鐐逛俊鎭 + * forknum锛欶orkNumber锛岃〃绀哄垎鏀彿 + * blocknum锛欱lockNumber锛岃〃绀洪昏緫鍧楀彿 + */ SegPageLocation seg_get_physical_location(RelFileNode rnode, ForkNumber forknum, BlockNumber blocknum) { SMgrRelation reln; + // 濡傛灉姝e湪杩涜鎭㈠杩囩▼锛屾姤閿欙紝涓嶅厑璁稿湪鎭㈠杩囩▼涓幏鍙栧垎娈电殑鍦板潃鏄犲皠 if (RecoveryInProgress()) { ereport(ERROR, (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE), errmsg("recovery is in progress"), errhint("cannot get segment address translation during recovery"))); } + // 鎵撳紑瀛樺偍绠$悊鍣ㄥ叧绯 reln = smgropen(rnode, InvalidBackendId); + // 璇诲彇鍒嗘鐨勪富澶撮儴淇℃伅缂撳啿鍖猴紝涓嶈繘琛屽垱寤 Buffer buffer = read_head_buffer(reln, forknum, false); + // 妫鏌ヨ幏鍙栫殑缂撳啿鍖烘槸鍚︽湁鏁 SegmentCheck(BufferIsValid(buffer)); + // 鑾峰彇鍒嗘鐨勪富澶撮儴淇℃伅 SegmentHead *head = (SegmentHead *)PageGetContents(BufferGetBlock(buffer)); + // 璋冪敤 seg_logic_to_physic_mapping 鍑芥暟鑾峰彇閫昏緫鍧楀彿瀵瑰簲鐨勭墿鐞嗕綅缃俊鎭 SegPageLocation loc = seg_logic_to_physic_mapping(reln, head, blocknum); + // 閲婃斁鑾峰彇鐨勪富澶撮儴淇℃伅缂撳啿鍖 SegReleaseBuffer(buffer); return loc; } @@ -1117,8 +1390,10 @@ BlockNumber seg_alloc_segment(Oid tablespace_id, Oid database_id, bool isbucket, ExtentInversePointer iptr = {.flag = SPC_INVRSPTR_ASSEMBLE_FLAG(SEGMENT_HEAD, 0), .owner = InvalidBlockNumber}; XLogAtomicOpStart(); result = normal_alloc_segment(tablespace_id, database_id, preassigned_block, iptr, true); - SEGMENTTEST(FREE_EXTENT_CREATE_SEGMENT_UNCOMMIT, (errmsg("FREE_EXTENT_CREATE_SEGMENT_UNCOMMIT %s: alloc segment success, " - "transation uncommit can drop segment!\n", g_instance.attr.attr_common.PGXCNodeName))); + SEGMENTTEST(FREE_EXTENT_CREATE_SEGMENT_UNCOMMIT, + (errmsg("FREE_EXTENT_CREATE_SEGMENT_UNCOMMIT %s: alloc segment success, " + "transation uncommit can drop segment!\n", + g_instance.attr.attr_common.PGXCNodeName))); XLogAtomicOpCommit(); } return result; @@ -1187,7 +1462,14 @@ static Buffer read_head_buffer(SMgrRelation reln, ForkNumber forknum, bool creat return buffer; } - +/* + * 鍔熻兘锛氬湪閲嶅仛鏈熼棿璇诲彇鍒嗘鐨勪富澶撮儴淇℃伅缂撳啿鍖 + * + * 鍙傛暟鍒楄〃锛 + * reln锛歋MgrRelation 缁撴瀯锛岃〃绀哄瓨鍌ㄧ鐞嗗櫒鍏崇郴淇℃伅 + * forknum锛欶orkNumber锛岃〃绀哄垎鏀彿 + * lsn锛歑LogRecPtr锛岃〃绀洪昏緫澶嶅埗鐐圭殑浣嶇疆淇℃伅 + */ static Buffer read_head_buffer_redo(SMgrRelation reln, ForkNumber forknum, XLogRecPtr lsn) { ASSERT_NORMAL_FORK(forknum); @@ -1201,23 +1483,34 @@ static Buffer read_head_buffer_redo(SMgrRelation reln, ForkNumber forknum, XLogR return buffer; } - - +/* + * 鍔熻兘锛氬垹闄ゅ垎娈 + * + * 鍙傛暟鍒楄〃锛 + * rnode锛歊elFileNode 缁撴瀯锛岃〃绀烘枃浠惰妭鐐逛俊鎭 + */ static void seg_unlink_segment(const RelFileNode &rnode) { + // 鏇存柊鍒嗘鍒犻櫎鏃堕棿绾 seg_update_timeline(); + // 鎵撳紑鍒嗘绌洪棿 SegSpace *spc = spc_open(rnode.spcNode, rnode.dbNode, false); + // 妫鏌ュ垎娈电┖闂存槸鍚︽湁鏁 SegmentCheck(spc != NULL); + // 鍑芥暟鍒ゆ柇鍒嗘绫诲瀷鏄櫘閫氳〃杩樻槸妗惰〃锛屽苟鍒嗗埆璋冪敤鐩稿簲鐨勫嚱鏁版潵鍒犻櫎鍒嗘 if (!IsBucketFileNode(rnode)) { + // 璇诲彇鍒嗘鐨勭紦鍐插尯锛屽苟鑾峰彇鍒嗘澶撮儴淇℃伅 Buffer buffer = ReadSegmentBuffer(spc, rnode.relNode); SegmentHead *head = (SegmentHead *)PageGetContents(BufferGetBlock(buffer)); + // 鏍规嵁鍒嗘澶撮儴淇℃伅鐨勯瓟鏈暟鍒ゆ柇鍒嗘绫诲瀷 if (head->magic == SEGMENT_HEAD_MAGIC) { // normal table SEGMENTTEST(FREE_SEGMENT_DROP_SEGMENT, (errmsg("FREE_SEGMENT_DROP_SEGMENT %s: " - "drop segment tb success!\n", g_instance.attr.attr_common.PGXCNodeName))); + "drop segment tb success!\n", + g_instance.attr.attr_common.PGXCNodeName))); normal_unlink_segment(spc, rnode, buffer); } else if (head->magic == BUCKET_SEGMENT_MAGIC) { // Delete all buckets in the table @@ -1232,11 +1525,22 @@ static void seg_unlink_segment(const RelFileNode &rnode) bucket_unlink_one_bucket(spc, rnode); } } - +/* + * 鍔熻兘锛氳褰曞瓨鍌ㄧ鐞嗗櫒 API 璋冪敤鐨勬棩蹇椾俊鎭 + * + * 鍙傛暟鍒楄〃锛 + * smgr_rnode锛歊elFileNodeBackend 缁撴瀯锛岃〃绀哄甫鏈夊悗绔俊鎭殑鏂囦欢鑺傜偣淇℃伅 + * forknum锛欶orkNumber锛岃〃绀哄垎鏀彿 + * blocknum锛欱lockNumber锛岃〃绀哄潡鍙 + * func_name锛歝onst char*锛岃〃绀鸿皟鐢ㄧ殑 API 鍑芥暟鍚嶇О + * elevel锛歩nt锛岃〃绀烘棩蹇楃骇鍒紝榛樿涓 DEBUG2 + */ static inline void LOG_SMGR_API(RelFileNodeBackend smgr_rnode, ForkNumber forknum, BlockNumber blocknum, const char *func_name, int elevel = DEBUG2) { + // 鑾峰彇鏂囦欢鑺傜偣淇℃伅 RelFileNode rnode = smgr_rnode.node; + // 璁板綍鏃ュ織淇℃伅 ereport(DEBUG2, (errmodule(MOD_SEGMENT_PAGE), errmsg("Segment-page smgr api: %s is invoked, SMgrRelation: <%u, %u, %u, %u> %d %u", func_name, rnode.spcNode, rnode.dbNode, rnode.relNode, rnode.bucketNode, forknum, blocknum))); @@ -1254,84 +1558,129 @@ void seg_shutdown() { // do nothing } - +/* + * 鍔熻兘锛氬叧闂垎娈 + * + * 鍙傛暟鍒楄〃锛 + * reln锛歋MgrRelation 缁撴瀯锛岃〃绀哄瓨鍌ㄧ鐞嗗櫒鍏崇郴淇℃伅 + * forknum锛欶orkNumber锛岃〃绀哄垎鏀彿 + * blockNum锛欱lockNumber锛岃〃绀哄潡鍙 + */ void seg_close(SMgrRelation reln, ForkNumber forknum, BlockNumber blockNum) { + // 鏂█鍧楀彿涓烘棤鏁堝潡鍙 SegmentCheck(blockNum == InvalidBlockNumber); + // 璁板綍瀛樺偍绠$悊鍣 API 璋冪敤鐨勬棩蹇椾俊鎭 LOG_SMGR_API(reln->smgr_rnode, forknum, InvalidBlockNumber, "seg_close"); + // 濡傛灉瀛樺偍绠$悊鍣ㄥ叧绯讳腑瀛樺湪鍒嗘鎻忚堪淇℃伅涓斿垎娈垫弿杩颁俊鎭笉涓虹┖ if (reln->seg_desc && reln->seg_desc[forknum] != NULL) { /* release memory */ pfree(reln->seg_desc[forknum]); reln->seg_desc[forknum] = NULL; } } - +/* + * 鍔熻兘锛氬垱寤哄垎娈 + * + * 鍙傛暟鍒楄〃锛 + * reln锛歋MgrRelation 缁撴瀯锛岃〃绀哄瓨鍌ㄧ鐞嗗櫒鍏崇郴淇℃伅 + * forknum锛欶orkNumber锛岃〃绀哄垎鏀彿 + * isRedo锛歜ool锛岃〃绀烘槸鍚﹀湪閲嶅仛涓垱寤 + */ void seg_create(SMgrRelation reln, ForkNumber forknum, bool isRedo) { + // 璁板綍瀛樺偍绠$悊鍣 API 璋冪敤鐨勬棩蹇椾俊鎭 LOG_SMGR_API(reln->smgr_rnode, forknum, InvalidBlockNumber, "seg_create"); + // 鎵撳紑鍒嗘锛屽鏋滃垎娈靛凡瀛樺湪鍒欒繑鍥 true bool res = open_segment(reln, forknum, true); - SegmentCheck(res == true); - (void)res; // keep compiler silent + SegmentCheck(res == true); // 纭繚鎴愬姛鎵撳紑鎴栧垱寤轰簡鍒嗘 + // 闃叉缂栬瘧鍣ㄨ鍛婏紝淇濇寔缂栬瘧鍣ㄩ潤榛 + (void)res; // keep compiler silent } - +/* + * 鍔熻兘锛氭鏌ュ垎娈垫槸鍚﹀瓨鍦 + * + * 鍙傛暟鍒楄〃锛 + * reln锛歋MgrRelation 缁撴瀯锛岃〃绀哄瓨鍌ㄧ鐞嗗櫒鍏崇郴淇℃伅 + * forknum锛欶orkNumber锛岃〃绀哄垎鏀彿 + * blockNum锛欱lockNumber锛岃〃绀哄潡鍙 + */ bool seg_exists(SMgrRelation reln, ForkNumber forknum, BlockNumber blockNum) { + // 璁板綍瀛樺偍绠$悊鍣 API 璋冪敤鐨勬棩蹇椾俊鎭 LOG_SMGR_API(reln->smgr_rnode, forknum, InvalidBlockNumber, "seg_exists"); + // 璋冪敤 open_segment 鍑芥暟妫鏌ュ垎娈垫槸鍚﹀瓨鍦紝骞惰繑鍥炵粨鏋 return open_segment(reln, forknum, false); } - +/* + * 鍔熻兘锛氬垹闄ゅ垎娈 + * + * 鍙傛暟鍒楄〃锛 + * rnode锛歊elFileNodeBackend 缁撴瀯锛岃〃绀哄叧绯绘枃浠惰妭鐐圭殑鍚庣淇℃伅 + * forknum锛欶orkNumber锛岃〃绀哄垎鏀彿 + * isRedo锛歜ool锛岃〃绀烘槸鍚﹀湪閲嶅仛涓垹闄 + * blockNum锛欱lockNumber锛岃〃绀哄潡鍙 + */ void seg_unlink(const RelFileNodeBackend &rnode, ForkNumber forknum, bool isRedo, BlockNumber blockNum) { if (isRedo) { return; } + // 璁板綍瀛樺偍绠$悊鍣 API 璋冪敤鐨勬棩蹇椾俊鎭紝浣跨敤 LOG 绾у埆 LOG_SMGR_API(rnode, forknum, InvalidBlockNumber, "seg_unlink", LOG); + // 鏂█鍒嗘敮鍙蜂负鏃犳晥鍒嗘敮鍙凤紝纭繚鍙兘鍒犻櫎鏁翠釜鍒嗘鑰屼笉鏄崟涓潡 SegmentCheck(forknum == InvalidForkNumber); + // 璋冪敤 seg_unlink_segment 鍑芥暟鍒犻櫎鏁翠釜鍒嗘 seg_unlink_segment(rnode.node); } - +// 缁撴瀯浣 ExtendStat struct ExtendStat { - private: - instr_time start_time; - instr_time end_time; - Oid _spc; - Oid _db; - Oid _file; +private: + instr_time start_time; // 璁板綍璧峰鏃堕棿鐨勬暟鎹粨鏋 + instr_time end_time; // 璁板綍缁撴潫鏃堕棿鐨勬暟鎹粨鏋 + Oid _spc; // 瀛樺偍绌洪棿鐨勬爣璇嗙 + Oid _db; // 鏁版嵁搴撶殑鏍囪瘑绗 + Oid _file; // 鏂囦欢鐨勬爣璇嗙 - public: +public: + // 璁剧疆鏂囦欢鏍囪瘑绗︾殑鏂规硶 void set_file(Oid spc, Oid db, Oid file) { _spc = spc; _db = db; _file = file; } - + // 璁板綍璧峰鏃堕棿鐨勬柟娉 void start() { (void)INSTR_TIME_SET_CURRENT(start_time); } - + // 璁板綍缁撴潫鏃堕棿鐨勬柟娉 void end() { (void)INSTR_TIME_SET_CURRENT(end_time); INSTR_TIME_SUBTRACT(end_time, start_time); PgStat_Counter time_diff = (PgStat_Counter)INSTR_TIME_GET_MICROSEC(end_time); + // 鍒涘缓 PgStat_MsgFile 缁撴瀯浣撳苟鍒濆鍖栦负0 PgStat_MsgFile msg; errno_t rc = memset_s(&msg, sizeof(msg), 0, sizeof(msg)); securec_check(rc, "", ""); - msg.dbid = _db; - msg.spcid = _spc; - msg.fn = _file; - msg.rw = 'w'; - msg.cnt = 1; - msg.blks = 1; - msg.tim = time_diff; - msg.lsttim = time_diff; - msg.mintim = time_diff; - msg.maxtim = time_diff; + // 璁剧疆 PgStat_MsgFile 缁撴瀯浣撶殑鎴愬憳鍙橀噺 + msg.dbid = _db; // 鏁版嵁搴撴爣璇嗙 + msg.spcid = _spc; // 瀛樺偍绌洪棿鏍囪瘑绗 + msg.fn = _file; // 鏂囦欢鏍囪瘑绗 + msg.rw = 'w'; // 璇诲啓鎿嶄綔绫诲瀷锛岃繖閲岃〃绀哄啓 + msg.cnt = 1; // 璁℃暟鍣紝琛ㄧず鎿嶄綔娆℃暟 + msg.blks = 1; // 鎿嶄綔鐨勫潡鏁 + msg.tim = time_diff; // 鎿嶄綔鐨勬椂闂村樊锛堜互寰涓哄崟浣嶏級 + msg.lsttim = time_diff; // 鏈鍚庝竴娆℃搷浣滅殑鏃堕棿宸 + msg.mintim = time_diff; // 鏈灏忔搷浣滄椂闂村樊 + msg.maxtim = time_diff; // 鏈澶ф搷浣滄椂闂村樊 + + // 璋冪敤 reportFileStat 鍑芥暟鎶ュ憡鏂囦欢缁熻淇℃伅 reportFileStat(&msg); } }; @@ -1454,16 +1803,34 @@ void seg_prefetch(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum) LOG_SMGR_API(reln->smgr_rnode, forknum, blocknum, "seg_prefetch"); /* Not support prefetch yet, just return */ } - +/* + * 鍔熻兘: 浠巗egment file涓鍙栨寚瀹氬潡锛堟暟鎹潡锛夌殑鍑芥暟銆 + * + * 鍙傛暟锛 + * reln: SMgrRelation锛岃〃绀轰笌娈垫枃浠剁浉鍏崇殑SMgrRelation瀵硅薄銆 + * forknum: ForkNumber锛岃〃绀烘暟鎹枃浠剁殑鍒嗗弶鍙枫 + * blocknum: BlockNumber锛岃璇诲彇鐨勫潡鍙枫 + * buffer: char*锛岀敤浜庡瓨鍌ㄨ鍙栧埌鐨勫潡鏁版嵁鐨勭紦鍐插尯銆 + * + * 杩斿洖鍊硷細 + * SMGR_READ_STATUS锛岃〃绀鸿鍙栨搷浣滅殑鐘舵侊紝鍙兘鐨勫彇鍊煎寘鎷細 + * - SMGR_RD_OK: 璇诲彇鎴愬姛銆 + * - SMGR_RD_CRC_ERROR: 鍧楃殑鏍¢獙鍜屾牎楠屽け璐ワ紝璇诲彇澶辫触銆 + * + * 娉ㄦ剰锛氬嚱鏁颁細鑷姩澶勭悊骞跺彂璁块棶鍐茬獊锛岀‘淇濇暟鎹殑涓鑷存с + */ SMGR_READ_STATUS seg_read(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum, char *buffer) { + // 璁板綍鍑芥暟璋冪敤淇℃伅 LOG_SMGR_API(reln->smgr_rnode, forknum, blocknum, "seg_read"); + // 璇诲彇娈靛ご閮ㄧ殑缂撳啿鍖 Buffer seg_buffer = read_head_buffer(reln, forknum, false); SegmentCheck(BufferIsValid(seg_buffer)); SegmentHead *seg_head = (SegmentHead *)PageGetContents(BufferGetBlock(seg_buffer)); SegmentCheck(IsNormalSegmentHead(seg_head)); + // 妫鏌ヨ璇诲彇鐨勫潡鍙锋槸鍚﹁秴鍑烘鐨勫ぇ灏 if (seg_head->nblocks <= blocknum) { SegReleaseBuffer(seg_buffer); ereport(ERROR, (errmodule(MOD_SEGMENT_PAGE), errcode(ERRCODE_DATA_CORRUPTED), @@ -1473,15 +1840,19 @@ SMGR_READ_STATUS seg_read(SMgrRelation reln, ForkNumber forknum, BlockNumber blo blocknum, seg_head->nblocks))); } + // 鑾峰彇娈靛ご閮ㄧ殑閿 LockSegmentHeadPartition(reln->seg_space->spcNode, reln->seg_space->dbNode, reln->seg_desc[forknum]->head_blocknum, LW_SHARED); + // 灏嗛昏緫鍧楀彿鏄犲皠鍒扮墿鐞嗗潡鍙 SegPageLocation loc = seg_logic_to_physic_mapping(reln, seg_head, blocknum); SegmentCheck(loc.blocknum != InvalidBlockNumber); + // 璇诲彇鍧楁暟鎹 SegSpace *spc = reln->seg_space; spc_read_block(spc, EXTENT_GROUP_RNODE(spc, loc.extent_size), forknum, buffer, loc.blocknum); + // 閲婃斁娈靛ご閮ㄧ殑閿 UnlockSegmentHeadPartition(reln->seg_space->spcNode, reln->seg_space->dbNode, reln->seg_desc[forknum]->head_blocknum); @@ -1489,6 +1860,7 @@ SMGR_READ_STATUS seg_read(SMgrRelation reln, ForkNumber forknum, BlockNumber blo SegmentCheck(loc.extent_size != 1); /* Set physical location in buffer descriptor, which is used for XLog */ + // 璁剧疆缂撳啿鍖烘弿杩扮涓殑鐗╃悊浣嶇疆锛岀敤浜 XLog 璁板綍 Buffer buf = BlockGetBuffer(buffer); if (BufferIsValid(buf)) { BufferDesc *buf_desc = BufferGetBufferDescriptor(buf); @@ -1496,24 +1868,40 @@ SMGR_READ_STATUS seg_read(SMgrRelation reln, ForkNumber forknum, BlockNumber blo buf_desc->seg_blockno = loc.blocknum; } + // 閲婃斁娈靛ご閮ㄧ殑缂撳啿鍖 SegReleaseBuffer(seg_buffer); + // 濡傛灉閫氳繃鏍¢獙鍒欒繑鍥 SMGR_RD_OK锛屽惁鍒欒繑鍥 SMGR_RD_CRC_ERROR if (PageIsVerified((Page)buffer, loc.blocknum)) { return SMGR_RD_OK; } else { return SMGR_RD_CRC_ERROR; } } - +/* + * 鍔熻兘锛氬皢鏁版嵁鍐欏叆鍒嗘鏂囦欢 + * + * 鍙傛暟鍒楄〃锛 + * reln锛歋MgrRelation 缁撴瀯锛岃〃绀哄垎娈垫枃浠剁殑SMgrRelation瀵硅薄 + * forknum锛欶orkNumber锛岃〃绀哄垎鏀彿 + * blocknum锛欱lockNumber锛岃〃绀鸿鍐欏叆鐨勫潡鍙 + * buffer锛歝onst char*锛屽寘鍚鍐欏叆鐨勬暟鎹殑缂撳啿鍖 + * skipFsync锛歜ool锛屽鏋滀负true锛岃〃绀哄彲浠ヨ烦杩噁sync鍚屾浠ユ彁楂樻ц兘 + * + * 娉ㄦ剰锛氳鍑芥暟璐熻矗灏嗘寚瀹氬潡鐨勬暟鎹啓鍏ュ垎娈垫枃浠讹紝绠$悊骞跺彂璁块棶鍐茬獊浠ョ‘淇濇暟鎹竴鑷存с + */ void seg_write(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum, const char *buffer, bool skipFsync) { + // 璁板綍SMGR API璋冪敤鏃ュ織 LOG_SMGR_API(reln->smgr_rnode, forknum, blocknum, "seg_write"); + // 璇诲彇鍒嗘澶撮儴缂撳啿鍖 Buffer seg_buffer = read_head_buffer(reln, forknum, true); SegmentCheck(BufferIsValid(seg_buffer)); SegmentHead *seg_head = (SegmentHead *)PageGetContents(BufferGetBlock(seg_buffer)); SegmentCheck(IsNormalSegmentHead(seg_head)); + // 妫鏌ュ潡鍙锋槸鍚﹁秴杩囧垎娈靛ぇ灏 if (seg_head->nblocks <= blocknum) { SegReleaseBuffer(seg_buffer); ereport(ERROR, (errmodule(MOD_SEGMENT_PAGE), errcode(ERRCODE_DATA_CORRUPTED), @@ -1523,42 +1911,62 @@ void seg_write(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum, cons blocknum, seg_head->nblocks))); } + // 閿佸畾鍒嗘澶撮儴鎵鍦ㄧ殑鍒嗗尯 LockSegmentHeadPartition(reln->seg_space->spcNode, reln->seg_space->dbNode, reln->seg_desc[forknum]->head_blocknum, LW_SHARED); + // 閫昏緫鍒扮墿鐞嗗湴鍧鏄犲皠 SegPageLocation loc = seg_logic_to_physic_mapping(reln, seg_head, blocknum); SegmentCheck(loc.blocknum != InvalidBlockNumber); + // 瑙i攣鍒嗘澶撮儴鎵鍦ㄧ殑鍒嗗尯 UnlockSegmentHeadPartition(reln->seg_space->spcNode, reln->seg_space->dbNode, reln->seg_desc[forknum]->head_blocknum); // TODO: remove PageSetChecksumInplace invocation outside SMGR. PageSetChecksumInplace((Page)buffer, loc.blocknum); SegSpace *spc = reln->seg_space; + // 鍐欏叆鏁版嵁鍧 spc_write_block(spc, EXTENT_GROUP_RNODE(spc, loc.extent_size), forknum, buffer, loc.blocknum); + // 閲婃斁鍒嗘澶撮儴缂撳啿鍖 SegReleaseBuffer(seg_buffer); } - +/* + * 鍔熻兘锛氬皢鎸囧畾鍒嗘鐨勬暟鎹啓鍥炵鐩 + * + * 鍙傛暟鍒楄〃锛 + * reln锛歋MgrRelation 缁撴瀯锛岃〃绀哄垎娈垫枃浠剁殑SMgrRelation瀵硅薄 + * forknum锛欶orkNumber锛岃〃绀哄垎鏀彿 + * blocknum锛欱lockNumber锛岃〃绀鸿鍐欏洖鐨勮捣濮嬪潡鍙 + * nblocks锛欱lockNumber锛岃〃绀鸿鍐欏洖鐨勫潡鏁伴噺 + * + * 娉ㄦ剰锛氳鍑芥暟鐢ㄤ簬灏嗘寚瀹氬垎娈电殑鏁版嵁鍐欏洖纾佺洏锛屽彲鐢ㄤ簬缂撳啿鍖哄埛鏂版搷浣溿傚鏋滀紶閫掔殑 rNode 琛ㄧず鐗╃悊鍒嗘鏂囦欢锛屽垯浣跨敤 + * spc_writeback 鍑芥暟锛屽鏋滆〃绀洪昏緫鍒嗘鏂囦欢锛屽垯閫愪釜閫昏緫鍖哄潡鍐欏洖纾佺洏銆 + */ void seg_writeback(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum, BlockNumber nblocks) { + // 璁板綍SMGR API璋冪敤鏃ュ織 LOG_SMGR_API(reln->smgr_rnode, forknum, InvalidBlockNumber, "seg_writeback"); RelFileNode rNode = reln->smgr_rnode.node; if (IsSegmentPhysicalRelNode(rNode)) { SMgrOpenSpace(reln); + // 璁板綍SMGR API璋冪敤鏃ュ織 if (reln->seg_space == NULL) { ereport(ERROR, (errmodule(MOD_SEGMENT_PAGE), errcode(ERRCODE_DATA_CORRUPTED), - errmsg("when write back, segment space [%u, %u] doesn't exist.", reln->smgr_rnode.node.spcNode, - reln->smgr_rnode.node.dbNode))); + errmsg("when write back, segment space [%u, %u] doesn't exist.", + reln->smgr_rnode.node.spcNode, reln->smgr_rnode.node.dbNode))); return; } + // 浣跨敤 spc_writeback 鍑芥暟灏嗘暟鎹啓鍥炵鐩 spc_writeback(reln->seg_space, EXTENT_TYPE_TO_SIZE(rNode.relNode), forknum, blocknum, nblocks); } else { /* * Logical writes are continues in each extent. * XXX: Continues extents can be merged to reduece system call. */ + // 璇诲彇鍒嗘澶撮儴缂撳啿鍖 Buffer seg_buffer = read_head_buffer(reln, forknum, true); SegmentCheck(BufferIsValid(seg_buffer)); SegmentHead *seg_head = (SegmentHead *)PageGetContents(BufferGetBlock(seg_buffer)); @@ -1566,6 +1974,7 @@ void seg_writeback(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum, SegmentCheck(blocknum + nblocks < seg_head->nblocks); /* Get the start extent id */ + // 鑾峰彇璧峰閫昏緫鍖哄潡鐨勬槧灏勪俊鎭 SegPageLocation loc1 = seg_logic_to_physic_mapping(reln, seg_head, blocknum); SegmentCheck(loc1.blocknum != InvalidBlockNumber); uint32 curr_ext_id = loc1.extent_id; @@ -1590,23 +1999,35 @@ void seg_writeback(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum, SegReleaseBuffer(seg_buffer); } } - +/* + * 鍔熻兘锛氳幏鍙栧垎娈典腑鐨勫潡鏁伴噺 + * + * 鍙傛暟鍒楄〃锛 + * reln锛歋MgrRelation 缁撴瀯锛岃〃绀哄垎娈垫枃浠剁殑SMgrRelation瀵硅薄 + * forknum锛欶orkNumber锛岃〃绀哄垎鏀彿 + * + * 娉ㄦ剰锛氳鍑芥暟鐢ㄤ簬鑾峰彇鍒嗘鏂囦欢涓殑鍧楁暟閲忥紝鏍规嵁 forknum 鍙傛暟鍖哄垎涓嶅悓鍒嗘敮銆傚鏋滃垎娈垫枃浠朵笉瀛樺湪鎴栦笉鍖呭惈鏈夋晥鏁版嵁锛岃繑鍥0銆 + */ BlockNumber seg_nblocks(SMgrRelation reln, ForkNumber forknum) { + // 璁板綍SMGR API璋冪敤鏃ュ織 LOG_SMGR_API(reln->smgr_rnode, forknum, InvalidBlockNumber, "seg_nblocks"); ASSERT_NORMAL_FORK(forknum); + // 妫鏌ュ垎娈垫枃浠舵槸鍚﹀瓨鍦 bool seg_exist = open_segment(reln, forknum, false); if (!seg_exist) { return 0; } + // 妫鏌ュ垎娈垫枃浠舵槸鍚﹀瓨鍦 Buffer seg_buffer = read_head_buffer(reln, forknum, false); SegmentCheck(BufferIsValid(seg_buffer)); SegmentHead *seg_head = (SegmentHead *)PageGetContents(BufferGetBlock(seg_buffer)); SegmentCheck(IsNormalSegmentHead(seg_head)); + // 閿佸畾鍒嗘澶撮儴缂撳啿鍖哄苟鑾峰彇鍧楁暟閲 LockBuffer(seg_buffer, BUFFER_LOCK_SHARE); BlockNumber nblocks = seg_head->nblocks; SegUnlockReleaseBuffer(seg_buffer); @@ -1618,11 +2039,21 @@ void seg_truncate(SMgrRelation reln, ForkNumber forknum, BlockNumber nblocks) { SegmentCheck(0); } - +/* + * 鍔熻兘锛氱Щ鍔ㄥ垎娈典腑鐨勫瓨鍌ㄦ《 + * + * 鍙傛暟鍒楄〃锛 + * dest锛歊elFileNodeBackend 缁撴瀯锛岃〃绀虹洰鏍囧垎娈垫枃浠惰妭鐐圭殑鍚庣淇℃伅 + * src锛歊elFileNodeBackend 缁撴瀯锛岃〃绀烘簮鍒嗘鏂囦欢鑺傜偣鐨勫悗绔俊鎭 + * bucketList锛歀ist 缁撴瀯锛屽寘鍚绉诲姩鐨勫瓨鍌ㄦ《鐨勫垪琛 + * + * 娉ㄦ剰锛氳鍑芥暟鐢ㄤ簬鍦ㄤ袱涓垎娈典箣闂寸Щ鍔ㄥ瓨鍌ㄦ《鐨勬暟鎹傛簮鍒嗘涓殑瀛樺偍妗舵暟鎹皢琚鍒跺埌鐩爣鍒嗘涓 + */ void seg_move_buckets(const RelFileNodeBackend &dest, const RelFileNodeBackend &src, List *bucketList) { + // 璁板綍瀛樺偍妗禦edis淇℃伅鐨刋LOG LOG_SMGR_API(dest, InvalidForkNumber, InvalidBlockNumber, "seg_move_buckets"); - uint32 i,j; + uint32 i, j; uint32 nentry; ListCell *cell = NULL; BktMainHead *shead, *dhead; @@ -1634,16 +2065,18 @@ void seg_move_buckets(const RelFileNodeBackend &dest, const RelFileNodeBackend & SegmentCheck(dest.node.spcNode == src.node.spcNode && dest.node.dbNode == src.node.dbNode); SegSpace *spc = spc_open(dest.node.spcNode, dest.node.dbNode, false); + // 璇诲彇鐩爣鍜屾簮鍒嗘鐨勪富澶撮儴 bucket_load_main_head(spc, dest.node.relNode, &dbuffer, &dhead); bucket_load_main_head(spc, src.node.relNode, &sbuffer, &shead); + // 閿佸畾鐩爣鍜屾簮鍒嗘鐨勪富澶撮儴 LockBuffer(dbuffer, BUFFER_LOCK_EXCLUSIVE); LockBuffer(sbuffer, BUFFER_LOCK_EXCLUSIVE); XLogAtomicOpStart(); /* Add redis info for both source and dest bucket segment header */ - dhead->redis_info.redis_xid = redis_xid; - shead->redis_info.redis_xid = redis_xid; + dhead->redis_info.redis_xid = redis_xid; + shead->redis_info.redis_xid = redis_xid; dhead->redis_info.nwords = BktBitMaxMapCnt; shead->redis_info.nwords = 0; for (i = 0; i < BktBitMaxMapCnt; i++) { @@ -1695,18 +2128,30 @@ void seg_move_buckets(const RelFileNodeBackend &dest, const RelFileNodeBackend & SegUnlockReleaseBuffer(smapbuffer); } + // 璁板綍瀛樺偍妗禦edis淇℃伅鐨刋LOG log_move_segment_redisinfo(&dhead->redis_info, &shead->redis_info, dbuffer, sbuffer); XLogAtomicOpCommit(); } - +/* + * 鍔熻兘锛氳幏鍙栧垎娈靛ご閮ㄧ殑LSN + * + * 鍙傛暟鍒楄〃锛 + * spc锛歋egSpace 缁撴瀯锛岃〃绀烘绌洪棿 + * blockNum锛欱lockNumber锛岃〃绀哄潡鍙 + * isbucket锛歜ool锛岃〃绀烘槸鍚︿负瀛樺偍妗跺垎娈 + * + * 娉ㄦ剰锛氳鍑芥暟鐢ㄤ簬鑾峰彇鍒嗘澶撮儴鐨凩SN锛岀敤浜庢鏌ュ垎娈垫槸鍚﹀凡缁忚鍐欏叆鏃ュ織銆 + */ XLogRecPtr seg_get_headlsn(SegSpace *spc, BlockNumber blockNum, bool isbucket) { + // 璇诲彇鍒嗘澶撮儴鐨勭紦鍐插尯 Buffer buffer = ReadSegmentBuffer(spc, blockNum); LockBuffer(buffer, BUFFER_LOCK_SHARE); SegmentHead *head = (SegmentHead *)PageGetContents(BufferGetPage(buffer)); uint64 magic = isbucket ? BUCKET_SEGMENT_MAGIC : SEGMENT_HEAD_MAGIC; XLogRecPtr lsn = InvalidXLogRecPtr; + // 妫鏌ュ垎娈靛ご閮ㄧ殑榄旀暟鍜屾棩蹇楀簭鍒楀彿鏄惁鏈夋晥 if (PageIsSegmentVersion(BufferGetPage(buffer)) && head->magic == magic) { lsn = head->lsn; SegmentCheck(XLogRecPtrIsValid(lsn)); @@ -1717,48 +2162,61 @@ XLogRecPtr seg_get_headlsn(SegSpace *spc, BlockNumber blockNum, bool isbucket) } void seg_immedsync(SMgrRelation reln, ForkNumber forknum) -{ -} +{} void seg_pre_ckpt(void) -{ -} +{} void seg_sync(void) -{ -} +{} void seg_post_ckpt(void) -{ -} +{} void seg_async_read(SMgrRelation reln, ForkNumber forknum, AioDispatchDesc_t **dList, int32 dn) -{ -} +{} void seg_async_write(SMgrRelation reln, ForkNumber forknum, AioDispatchDesc_t **dList, int32 dn) -{ -} - +{} +/* + * 鍔熻兘锛氳幏鍙栨寚瀹氬垎鏀殑鍒嗘鎬诲潡鏁 + * + * 鍙傛暟鍒楄〃锛 + * reln锛歋MgrRelation 缁撴瀯锛岃〃绀篠MgrRelation瀵硅薄 + * forknum锛欶orkNumber锛岃〃绀哄垎鏀彿 + * + * 娉ㄦ剰锛氳鍑芥暟鐢ㄤ簬鑾峰彇鎸囧畾鍒嗘敮鐨勫垎娈垫诲潡鏁帮紝濡傛灉鍒嗘涓嶅瓨鍦紝鍒欒繑鍥0銆 + */ BlockNumber seg_fork_totalblocks(SMgrRelation reln, ForkNumber forknum) { + // 妫鏌ユ寚瀹氬垎鏀殑鏈夋晥鎬 bool seg_exist = open_segment(reln, forknum, false); if (!seg_exist) { return 0; } + // 璇诲彇鎸囧畾鍒嗘敮鐨勫垎娈靛ご閮ㄧ紦鍐插尯 Buffer seg_buffer = read_head_buffer(reln, forknum, false); SegmentCheck(BufferIsValid(seg_buffer)); SegmentHead *seg_head = (SegmentHead *)PageGetContents(BufferGetBlock(seg_buffer)); + // 鑾峰彇鍒嗘鎬诲潡鏁板苟閲婃斁缂撳啿鍖 LockBuffer(seg_buffer, BUFFER_LOCK_SHARE); BlockNumber nblocks = seg_head->nblocks; SegUnlockReleaseBuffer(seg_buffer); return nblocks; } - +/* + * 鍔熻兘锛氳幏鍙栨寚瀹氬垎鏀殑鍒嗘鎬诲潡鏁 + * + * 鍙傛暟鍒楄〃锛 + * reln锛歋MgrRelation 缁撴瀯锛岃〃绀篠MgrRelation瀵硅薄 + * forknum锛欶orkNumber锛岃〃绀哄垎鏀彿 + * + * 娉ㄦ剰锛氳鍑芥暟鐢ㄤ簬鑾峰彇鎸囧畾鍒嗘敮鐨勫垎娈垫诲潡鏁帮紝濡傛灉鍒嗘涓嶅瓨鍦紝鍒欒繑鍥0銆 + */ BlockNumber seg_totalblocks(SMgrRelation reln, ForkNumber forknum) { LOG_SMGR_API(reln->smgr_rnode, forknum, InvalidBlockNumber, "seg_totalblocks"); @@ -1768,21 +2226,34 @@ BlockNumber seg_totalblocks(SMgrRelation reln, ForkNumber forknum) } ASSERT_NORMAL_FORK(forknum); + // 璇诲彇涓诲垎鏀殑鍒嗘澶撮儴缂撳啿鍖 Buffer seg_buffer = read_head_buffer(reln, MAIN_FORKNUM, false); SegmentCheck(BufferIsValid(seg_buffer)); SegmentHead *seg_head = (SegmentHead *)PageGetContents(BufferGetBlock(seg_buffer)); BlockNumber res = 0; + // 鏍规嵁鍒嗘绫诲瀷璋冪敤涓嶅悓鐨勮幏鍙栨诲潡鏁板嚱鏁 if (seg_head->magic == BUCKET_SEGMENT_MAGIC) { res = bucket_totalblocks(reln, forknum, seg_buffer); } else { res = seg_fork_totalblocks(reln, forknum); } + // 閲婃斁鍒嗘澶撮儴缂撳啿鍖 SegReleaseBuffer(seg_buffer); return res; } - +/* + * 鍔熻兘锛氭鏌ユ寚瀹氬垎鏀殑鍒嗘鏄惁瀛樺湪 + * + * 鍙傛暟鍒楄〃锛 + * spc锛歋egSpace 缁撴瀯锛岃〃绀篠egSpace瀵硅薄 + * reln锛歋MgrRelation 缁撴瀯锛岃〃绀篠MgrRelation瀵硅薄 + * forknum锛欶orkNumber锛岃〃绀哄垎鏀彿 + * pblk锛歑LogPhyBlock 缁撴瀯锛岃〃绀虹墿鐞嗗潡鍙峰拰鏃ュ織搴忓垪鍙 + * + * 娉ㄦ剰锛氳鍑芥暟鐢ㄤ簬妫鏌ユ寚瀹氬垎鏀殑鍒嗘鏄惁瀛樺湪锛屽瓨鍦ㄥ垯杩斿洖true锛屽惁鍒欒繑鍥瀎alse銆 + */ bool seg_fork_exists(SegSpace *spc, SMgrRelation reln, ForkNumber forknum, const XLogPhyBlock *pblk) { ASSERT_NORMAL_FORK(forknum); @@ -1790,6 +2261,7 @@ bool seg_fork_exists(SegSpace *spc, SMgrRelation reln, ForkNumber forknum, const RelFileNode rnode = reln->smgr_rnode.node; BlockNumber lastblock = spc_size(spc, pblk->relNode, forknum); + // 濡傛灉鍧楀彿澶т簬绛変簬鏈鍚庝竴涓潡鍙凤紝杩斿洖false if (pblk->block >= lastblock) { return false; } @@ -1801,7 +2273,7 @@ bool seg_fork_exists(SegSpace *spc, SMgrRelation reln, ForkNumber forknum, const /* check if main relation is still here */ XLogRecPtr seglsn = seg_get_headlsn(spc, rnode.relNode, IsBucketFileNode(rnode)); - + // 濡傛灉LSN鏃犳晥鎴栬卲blk鐨凩SN灏忎簬绛変簬鍒嗘澶撮儴鐨凩SN锛岃繑鍥瀎alse if (XLogRecPtrIsInvalid(seglsn) || XLByteLE(pblk->lsn, seglsn)) { /* segment header is reused */ return false; @@ -1809,6 +2281,7 @@ bool seg_fork_exists(SegSpace *spc, SMgrRelation reln, ForkNumber forknum, const /* check if relation or bucket's fork is still here */ Buffer seg_buffer = read_head_buffer_redo(reln, forknum, pblk->lsn); + // 濡傛灉鍒嗘敮缂撳啿鍖烘棤鏁堬紝杩斿洖false if (!BufferIsValid(seg_buffer)) { /* bucket or fork is dropped */ return false; @@ -1816,6 +2289,7 @@ bool seg_fork_exists(SegSpace *spc, SMgrRelation reln, ForkNumber forknum, const SegmentHead *seg_head = (SegmentHead *)PageGetContents(BufferGetBlock(seg_buffer)); LockBuffer(seg_buffer, BUFFER_LOCK_SHARE); + // 濡傛灉鍒嗘敮缂撳啿鍖轰笉鏄垎娈电増鏈垨鑰呭垎娈靛ご閮ㄧ殑榄旀暟涓嶆槸SEGMENT_HEAD_MAGIC锛岃繑鍥瀎alse if (!PageIsSegmentVersion(BufferGetBlock(seg_buffer)) || seg_head->magic != SEGMENT_HEAD_MAGIC) { /* segment header reused */ SegUnlockReleaseBuffer(seg_buffer); @@ -1834,25 +2308,64 @@ bool seg_fork_exists(SegSpace *spc, SMgrRelation reln, ForkNumber forknum, const } /* APIs for others */ - +/* + * 鍔熻兘锛氫负鎸囧畾鐨勫垎鏀鍒嗛厤鎵╁睍绌洪棿 + * + * 鍙傛暟鍒楄〃锛 + * rNode锛歊elFileNode 缁撴瀯锛岃〃绀哄叧绯绘枃浠惰妭鐐 + * forkNum锛欶orkNumber锛岃〃绀哄垎鏀彿 + * blkno锛欱lockNumber锛岃〃绀哄潡鍙 + * + * 娉ㄦ剰锛氳鍑芥暟鐢ㄤ簬涓烘寚瀹氱殑鍒嗘敮棰勫垎閰嶆墿灞曠┖闂淬 + */ void seg_preextend(RelFileNode &rNode, ForkNumber forkNum, BlockNumber blkno) { + // 鎵撳紑鍏崇郴鏂囦欢骞惰繘琛岄鍒嗛厤鎵╁睍 SMgrRelation reln = smgropen(rNode, InvalidBackendId); seg_extend_internal(reln, forkNum, blkno); } - +/* + * 鍔熻兘锛氱墿鐞嗚鍙栨寚瀹氬垎鏀殑鎸囧畾鍧楁暟鎹 + * + * 鍙傛暟鍒楄〃锛 + * spc锛歋egSpace 缁撴瀯鎸囬拡锛岃〃绀哄垎娈电┖闂 + * rNode锛歊elFileNode 缁撴瀯锛岃〃绀哄叧绯绘枃浠惰妭鐐 + * forknum锛欶orkNumber锛岃〃绀哄垎鏀彿 + * blocknum锛欱lockNumber锛岃〃绀哄潡鍙 + * buffer锛歝har 鎸囬拡锛岀敤浜庡瓨鍌ㄨ鍙栫殑鏁版嵁 + * + * 娉ㄦ剰锛氳鍑芥暟鐢ㄤ簬鐗╃悊璇诲彇鎸囧畾鍒嗘敮鐨勬寚瀹氬潡鏁版嵁銆 + */ void seg_physical_read(SegSpace *spc, RelFileNode &rNode, ForkNumber forknum, BlockNumber blocknum, char *buffer) { + // 妫鏌ュ叧绯绘枃浠惰妭鐐规槸鍚︿负鐗╃悊鏂囦欢绫诲瀷 SegmentCheck(IsSegmentPhysicalRelNode(rNode)); + // 妫鏌ュ垎娈电┖闂存槸鍚︽湁鏁 SegmentCheck(spc != NULL); + // 璋冪敤 spc_read_block 鍑芥暟杩涜鐗╃悊璇诲彇 spc_read_block(spc, rNode, forknum, buffer, blocknum); } - +/* + * 鍔熻兘锛氱墿鐞嗗啓鍏ユ寚瀹氬垎鏀殑鎸囧畾鍧楁暟鎹 + * + * 鍙傛暟鍒楄〃锛 + * spc锛歋egSpace 缁撴瀯鎸囬拡锛岃〃绀哄垎娈电┖闂 + * rNode锛歊elFileNode 缁撴瀯锛岃〃绀哄叧绯绘枃浠惰妭鐐 + * forknum锛欶orkNumber锛岃〃绀哄垎鏀彿 + * blocknum锛欱lockNumber锛岃〃绀哄潡鍙 + * buffer锛歝onst char 鎸囬拡锛岀敤浜庡瓨鍌ㄨ鍐欏叆鐨勬暟鎹 + * skipFsync锛歜ool锛岃〃绀烘槸鍚﹁烦杩囨枃浠跺悓姝ユ搷浣 + * + * 娉ㄦ剰锛氳鍑芥暟鐢ㄤ簬鐗╃悊鍐欏叆鎸囧畾鍒嗘敮鐨勬寚瀹氬潡鏁版嵁銆 + */ void seg_physical_write(SegSpace *spc, RelFileNode &rNode, ForkNumber forknum, BlockNumber blocknum, const char *buffer, bool skipFsync) { + // 妫鏌ュ叧绯绘枃浠惰妭鐐规槸鍚︿负鐗╃悊鏂囦欢绫诲瀷 SegmentCheck(IsSegmentPhysicalRelNode(rNode)); + // 妫鏌ュ垎娈电┖闂存槸鍚︽湁鏁 SegmentCheck(spc != NULL); + // 璋冪敤 spc_write_block 鍑芥暟杩涜鐗╃悊鍐欏叆 spc_write_block(spc, rNode, forknum, buffer, blocknum); } diff --git a/src/gausskernel/storage/smgr/smgr.cpp b/src/gausskernel/storage/smgr/smgr.cpp index b76bbfe3b..5ad1e44e3 100644 --- a/src/gausskernel/storage/smgr/smgr.cpp +++ b/src/gausskernel/storage/smgr/smgr.cpp @@ -63,63 +63,17 @@ typedef struct f_smgr { static const f_smgr smgrsw[] = { /* magnetic disk */ - { mdinit, - NULL, - mdclose, - mdcreate, - mdexists, - mdunlink, - mdextend, - mdprefetch, - mdread, - mdwrite, - mdwriteback, - mdnblocks, - mdtruncate, - mdimmedsync, - mdasyncread, - mdasyncwrite, - NULL - }, + {mdinit, NULL, mdclose, mdcreate, mdexists, mdunlink, mdextend, mdprefetch, mdread, mdwrite, mdwriteback, mdnblocks, + mdtruncate, mdimmedsync, mdasyncread, mdasyncwrite, NULL}, /* undo file */ - { - InitUndoFile, - NULL, - CloseUndoFile, - CreateUndoFile, - CheckUndoFileExists, - UnlinkUndoFile, - ExtendUndoFile, - PrefetchUndoFile, - ReadUndoFile, - WriteUndoFile, - WritebackUndoFile, - GetUndoFileNblocks, - NULL, - NULL - }, + {InitUndoFile, NULL, CloseUndoFile, CreateUndoFile, CheckUndoFileExists, UnlinkUndoFile, ExtendUndoFile, + PrefetchUndoFile, ReadUndoFile, WriteUndoFile, WritebackUndoFile, GetUndoFileNblocks, NULL, NULL}, /* segment-page */ - { - seg_init, - seg_shutdown, - seg_close, - seg_create, - seg_exists, - seg_unlink, - seg_extend, - seg_prefetch, - seg_read, - seg_write, - seg_writeback, - seg_nblocks, - seg_truncate, - seg_immedsync, - seg_async_read, - seg_async_write, - seg_move_buckets - }, + {seg_init, seg_shutdown, seg_close, seg_create, seg_exists, seg_unlink, seg_extend, seg_prefetch, seg_read, + seg_write, seg_writeback, seg_nblocks, seg_truncate, seg_immedsync, seg_async_read, seg_async_write, + seg_move_buckets}, }; static const int NSmgr = lengthof(smgrsw); @@ -137,7 +91,6 @@ static inline int ChooseSmgrManager(RelFileNode rnode) return MD_MANAGER; } - /* * smgrinit(), smgrshutdown() -- Initialize or shut down storage * managers. @@ -183,7 +136,7 @@ void smgrshutdown(int code, Datum arg) * * This does not attempt to actually open the underlying file. */ -SMgrRelation smgropen(const RelFileNode& rnode, BackendId backend, int col /* = 0 */) +SMgrRelation smgropen(const RelFileNode &rnode, BackendId backend, int col /* = 0 */) { RelFileNodeBackend brnode; SMgrRelation reln; @@ -207,16 +160,15 @@ SMgrRelation smgropen(const RelFileNode& rnode, BackendId backend, int col /* = hashCtrl.hash = tag_hash; if (EnableLocalSysCache()) { hashCtrl.hcxt = t_thrd.lsc_cxt.lsc->lsc_mydb_memcxt; - t_thrd.lsc_cxt.lsc->SMgrRelationHash = hash_create("smgr relation table", 400, - &hashCtrl, HASH_ELEM | HASH_FUNCTION | HASH_CONTEXT); + t_thrd.lsc_cxt.lsc->SMgrRelationHash = + hash_create("smgr relation table", 400, &hashCtrl, HASH_ELEM | HASH_FUNCTION | HASH_CONTEXT); dlist_init(&t_thrd.lsc_cxt.lsc->unowned_reln); } else { hashCtrl.hcxt = u_sess->cache_mem_cxt; - u_sess->storage_cxt.SMgrRelationHash = hash_create("smgr relation table", 400, - &hashCtrl, HASH_ELEM | HASH_FUNCTION | HASH_CONTEXT); + u_sess->storage_cxt.SMgrRelationHash = + hash_create("smgr relation table", 400, &hashCtrl, HASH_ELEM | HASH_FUNCTION | HASH_CONTEXT); dlist_init(&u_sess->storage_cxt.unowned_reln); } - } START_CRIT_SECTION(); @@ -224,7 +176,7 @@ SMgrRelation smgropen(const RelFileNode& rnode, BackendId backend, int col /* = /* Look up or create an entry */ brnode.node = rnode; brnode.backend = backend; - reln = (SMgrRelation)hash_search(GetSMgrRelationHash(), (void*)&brnode, HASH_ENTER, &found); + reln = (SMgrRelation)hash_search(GetSMgrRelationHash(), (void *)&brnode, HASH_ENTER, &found); /* Initialize it if not present before */ if (!found) { @@ -238,8 +190,8 @@ SMgrRelation smgropen(const RelFileNode& rnode, BackendId backend, int col /* = reln->smgr_vm_nblocks = InvalidBlockNumber; reln->encrypt = false; temp = col + 1; - reln->smgr_bcm_nblocks = (BlockNumber*)MemoryContextAllocZero( - LocalSmgrStorageMemoryCxt(), temp * sizeof(BlockNumber)); + reln->smgr_bcm_nblocks = + (BlockNumber *)MemoryContextAllocZero(LocalSmgrStorageMemoryCxt(), temp * sizeof(BlockNumber)); reln->smgr_bcmarry_size = temp; for (colnum = 0; colnum < reln->smgr_bcmarry_size; colnum++) { reln->smgr_bcm_nblocks[colnum] = InvalidBlockNumber; @@ -253,13 +205,13 @@ SMgrRelation smgropen(const RelFileNode& rnode, BackendId backend, int col /* = reln->seg_space = NULL; if (reln->smgr_which == SEGMENT_MANAGER) { reln->md_fdarray_size = fdNeeded; - reln->seg_desc = (struct SegmentDesc **)MemoryContextAllocZero( - LocalSmgrStorageMemoryCxt(), fdNeeded * sizeof(struct SegmentDesc *)); + reln->seg_desc = (struct SegmentDesc **)MemoryContextAllocZero(LocalSmgrStorageMemoryCxt(), + fdNeeded * sizeof(struct SegmentDesc *)); reln->md_fd = NULL; } else if (reln->smgr_which == MD_MANAGER) { reln->md_fdarray_size = fdNeeded; - reln->md_fd = (struct _MdfdVec**)MemoryContextAllocZero( - LocalSmgrStorageMemoryCxt(), fdNeeded * sizeof(struct _MdfdVec*)); + reln->md_fd = (struct _MdfdVec **)MemoryContextAllocZero(LocalSmgrStorageMemoryCxt(), + fdNeeded * sizeof(struct _MdfdVec *)); reln->seg_desc = NULL; } else { reln->md_fdarray_size = 1; @@ -284,7 +236,8 @@ SMgrRelation smgropen(const RelFileNode& rnode, BackendId backend, int col /* = int old_bcmarry_size = reln->smgr_bcmarry_size; temp = reln->smgr_bcmarry_size * 2; temp = Max(temp, (col + 1)); - reln->smgr_bcm_nblocks = (BlockNumber *)repalloc((void *)reln->smgr_bcm_nblocks, temp * sizeof(BlockNumber)); + reln->smgr_bcm_nblocks = + (BlockNumber *)repalloc((void *)reln->smgr_bcm_nblocks, temp * sizeof(BlockNumber)); reln->smgr_bcmarry_size = temp; for (int colnum = old_bcmarry_size; colnum < reln->smgr_bcmarry_size; colnum++) @@ -300,7 +253,7 @@ SMgrRelation smgropen(const RelFileNode& rnode, BackendId backend, int col /* = int old_fdarray_size = reln->md_fdarray_size; temp = reln->md_fdarray_size * 2; temp = Max(temp, fdNeeded); - reln->md_fd = (struct _MdfdVec**)repalloc((void*)reln->md_fd, temp * sizeof(struct _MdfdVec*)); + reln->md_fd = (struct _MdfdVec **)repalloc((void *)reln->md_fd, temp * sizeof(struct _MdfdVec *)); reln->md_fdarray_size = temp; for (int forknum = old_fdarray_size; forknum < reln->md_fdarray_size; forknum++) @@ -387,7 +340,7 @@ static bool smgrhaschildern(SMgrRelation reln) void smgrclose(SMgrRelation reln, BlockNumber blockNum) { ereport(DEBUG5, (errmsg("smgr close %p", reln))); - SMgrRelation* owner = NULL; + SMgrRelation *owner = NULL; int forknum; for (forknum = 0; forknum < (int)(reln->md_fdarray_size); forknum++) { @@ -435,7 +388,7 @@ void smgrclose(SMgrRelation reln, BlockNumber blockNum) * smgrcloseall() -- Close all existing SMgrRelation objects. */ void smgrcloseall(void) -{ +{ HASH_SEQ_STATUS status; SMgrRelation reln; @@ -449,7 +402,7 @@ void smgrcloseall(void) while ((reln = (SMgrRelation)hash_seq_search(&status)) != NULL) { if (smgrhaschildern(reln)) { - /* + /* * if the smgr node has children, it may incur close of all its children. * we can not close it in the first loop, otherwise the hashtable iterator is broken. */ @@ -541,9 +494,7 @@ void smgrcreate(SMgrRelation reln, ForkNumber forknum, bool isRedo) * should be here and not in commands/tablespace.c? But that would imply * importing a lot of stuff that smgr.c oughtn't know, either. */ - TablespaceCreateDbspace(reln->smgr_rnode.node.spcNode, - reln->smgr_rnode.node.dbNode, - isRedo); + TablespaceCreateDbspace(reln->smgr_rnode.node.spcNode, reln->smgr_rnode.node.dbNode, isRedo); (*(smgrsw[reln->smgr_which].smgr_create))(reln, forknum, isRedo); } @@ -668,8 +619,7 @@ void smgrdounlinkfork(SMgrRelation reln, ForkNumber forknum, bool isRedo) * EOF). Note that we assume writing a block beyond current EOF * causes intervening file space to become filled with zeroes. */ -void smgrextend(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum, - char *buffer, bool skipFsync) +void smgrextend(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum, char *buffer, bool skipFsync) { (*(smgrsw[reln->smgr_which].smgr_extend))(reln, forknum, blocknum, buffer, skipFsync); } @@ -764,15 +714,13 @@ BlockNumber smgrnblocks(SMgrRelation reln, ForkNumber forknum) * Returns an InvalidBlockNumber when not in recovery and when the relation * fork size is not cached. Now, we only support cache main fork. */ -BlockNumber -smgrnblocks_cached(SMgrRelation reln, ForkNumber forknum) +BlockNumber smgrnblocks_cached(SMgrRelation reln, ForkNumber forknum) { /* * For now, we only use cached values in recovery due to lack of a shared * invalidation mechanism for changes in file size. */ - if (RecoveryInProgress() && forknum == MAIN_FORKNUM && - reln->smgr_cached_nblocks != InvalidBlockNumber) { + if (RecoveryInProgress() && forknum == MAIN_FORKNUM && reln->smgr_cached_nblocks != InvalidBlockNumber) { return reln->smgr_cached_nblocks; } @@ -860,7 +808,6 @@ void smgrimmedsync(SMgrRelation reln, ForkNumber forknum) (*(smgrsw[reln->smgr_which].smgr_immedsync))(reln, forknum); } - /* * smgrmovebuckets() -- Move buckets between two relation. */ @@ -943,7 +890,13 @@ ScalarToDatum GetTransferFuncByTypeOid(Oid attTypeOid) } } } - +/* + * 鍔熻兘锛氬皢瑕佸垹闄ょ殑鍏崇郴鐨勬煇涓垎鏀俊鎭坊鍔犲埌鍝堝笇琛ㄤ腑 + * + * 鍙傛暟鍒楄〃锛 + * node锛歊elFileNode锛岃〃绀哄叧绯绘枃浠惰妭鐐逛俊鎭 + * forkNum锛欶orkNumber锛岃〃绀哄垎鏀彿 + */ static void push_unlink_rel_one_fork_to_hashtbl(RelFileNode node, ForkNumber forkNum) { HTAB *relfilenode_hashtbl = g_instance.bgwriter_cxt.unlink_rel_fork_hashtbl; @@ -956,7 +909,7 @@ static void push_unlink_rel_one_fork_to_hashtbl(RelFileNode node, ForkNumber for key.forkNum = forkNum; LWLockAcquire(g_instance.bgwriter_cxt.rel_one_fork_hashtbl_lock, LW_EXCLUSIVE); - entry = (DelForkFileTag*)hash_search(relfilenode_hashtbl, &(key), HASH_ENTER, &found); + entry = (DelForkFileTag *)hash_search(relfilenode_hashtbl, &(key), HASH_ENTER, &found); if (!found) { entry->forkrnode.rnode.spcNode = key.rnode.spcNode; entry->forkrnode.rnode.dbNode = key.rnode.dbNode; @@ -974,4 +927,3 @@ static void push_unlink_rel_one_fork_to_hashtbl(RelFileNode node, ForkNumber for } return; } - diff --git a/src/gausskernel/storage/sync/knl_usync.cpp b/src/gausskernel/storage/sync/knl_usync.cpp index 17f78738e..f2c73f059 100644 --- a/src/gausskernel/storage/sync/knl_usync.cpp +++ b/src/gausskernel/storage/sync/knl_usync.cpp @@ -54,7 +54,7 @@ * (Regular backends do not track pending operations locally, but forward * them to the checkpointer.) */ -typedef uint16 CycleCtr; /* can be any convenient integer size */ +typedef uint16 CycleCtr; /* can be any convenient integer size */ typedef struct { FileTag tag; /* identifies handler and file */ @@ -109,11 +109,16 @@ static const SyncOps SYNCSW[] = { }; static const int NSync = lengthof(SYNCSW); - +/* + * 鍔熻兘锛氬垵濮嬪寲寰呭鐞嗘搷浣滅殑鍝堝笇琛紝鐢ㄤ簬璺熻釜闇瑕佹墽琛岀殑鏂囦欢绯荤粺鍚屾鎿嶄綔 + * + * 鍙傛暟鍒楄〃锛氭棤 + */ void InitPendingOps(void) { + // 濡傛灉涓嶅浜嶱ostmaster杩涚▼涓嬶紝鎴栬呮槸鍚姩杩涚▼銆佹鏌ョ偣杩涚▼銆侀〉鍐欒繘绋嬶紝鍒欐墽琛屼互涓嬫搷浣 if (!IsUnderPostmaster || AmStartupProcess() || AmCheckpointerProcess() || AmPageWriterMainProcess()) { - HASHCTL hashCtl; + HASHCTL hashCtl; errno_t rc; /* @@ -125,17 +130,18 @@ void InitPendingOps(void) * Fortunately the hash table is small so that's unlikely to happen in * practice. */ - u_sess->storage_cxt.pendingOpsCxt = AllocSetContextCreate(u_sess->top_mem_cxt, - "Pending ops context", ALLOCSET_DEFAULT_SIZES); - MemoryContextAllowInCriticalSection(u_sess->storage_cxt.pendingOpsCxt, true); - rc = memset_s(&hashCtl, sizeof(hashCtl), 0, sizeof(hashCtl)); - securec_check(rc, "", ""); - hashCtl.keysize = sizeof(FileTag); - hashCtl.entrysize = sizeof(PendingFsyncEntry); - hashCtl.hcxt = u_sess->storage_cxt.pendingOpsCxt; - hashCtl.hash = tag_hash; - u_sess->storage_cxt.pendingOps = hash_create("Pending Ops Table", - 100L, &hashCtl, HASH_ELEM | HASH_BLOBS | HASH_CONTEXT); + u_sess->storage_cxt.pendingOpsCxt = + AllocSetContextCreate(u_sess->top_mem_cxt, "Pending ops context", + ALLOCSET_DEFAULT_SIZES); // 鍒涘缓鍐呭瓨涓婁笅鏂囨潵绠$悊寰呭鐞嗘搷浣滅殑鍐呭瓨 + MemoryContextAllowInCriticalSection(u_sess->storage_cxt.pendingOpsCxt, true); // 鍏佽鍦ㄤ复鐣屽尯鍐呭垎閰嶅唴瀛 + rc = memset_s(&hashCtl, sizeof(hashCtl), 0, sizeof(hashCtl)); // 鍒濆鍖杊ashCtl缁撴瀯浣 + securec_check(rc, "", ""); // 妫鏌emset_s鏄惁澶辫触 + hashCtl.keysize = sizeof(FileTag); // 鍝堝笇閿殑澶у皬涓篎ileTag鐨勫ぇ灏 + hashCtl.entrysize = sizeof(PendingFsyncEntry); // 鍝堝笇琛ㄩ」鐨勫ぇ灏忎负PendingFsyncEntry鐨勫ぇ灏 + hashCtl.hcxt = u_sess->storage_cxt.pendingOpsCxt; // 鍝堝笇琛ㄤ娇鐢ㄤ笂闈㈠垱寤虹殑鍐呭瓨涓婁笅鏂 + hashCtl.hash = tag_hash; // 鍝堝笇鍑芥暟浣跨敤tag_hash鏉ヨ绠楀搱甯屽 + u_sess->storage_cxt.pendingOps = hash_create( + "Pending Ops Table", 100L, &hashCtl, HASH_ELEM | HASH_BLOBS | HASH_CONTEXT); // 鍒涘缓鍝堝笇琛ㄦ潵瀛樺偍寰呭鐞嗘搷浣 } } @@ -189,7 +195,7 @@ void SyncPostCheckpoint(void) absorbCounter = UNLINKS_PER_ABSORB; while (u_sess->storage_cxt.pendingUnlinks != NIL) { - PendingUnlinkEntry *entry = (PendingUnlinkEntry *) linitial(u_sess->storage_cxt.pendingUnlinks); + PendingUnlinkEntry *entry = (PendingUnlinkEntry *)linitial(u_sess->storage_cxt.pendingUnlinks); char path[MAXPGPATH]; /* @@ -215,8 +221,7 @@ void SyncPostCheckpoint(void) * the possibility that we delete the file first. */ if (errno != ENOENT) { - ereport(WARNING, (errcode_for_file_access(), - errmsg("could not remove file \"%s\": %m", path))); + ereport(WARNING, (errcode_for_file_access(), errmsg("could not remove file \"%s\": %m", path))); } } @@ -287,7 +292,7 @@ static void HandleAbnormalSyncExit(bool syncInProgress) if (syncInProgress) { /* prior try failed, so update any stale cycle_ctr values */ hash_seq_init(&hstat, u_sess->storage_cxt.pendingOps); - while ((entry = (PendingFsyncEntry *) hash_seq_search(&hstat)) != NULL) { + while ((entry = (PendingFsyncEntry *)hash_seq_search(&hstat)) != NULL) { entry->cycle_ctr = u_sess->storage_cxt.sync_cycle_ctr; } } @@ -305,13 +310,13 @@ void ProcessSyncRequests(void) int absorbCounter; /* Statistics on sync times */ - int processed = 0; - instr_time syncStart; - instr_time syncEnd; - instr_time syncDiff; - uint64 elapsed; - uint64 longest = 0; - uint64 totalElapsed = 0; + int processed = 0; + instr_time syncStart; + instr_time syncEnd; + instr_time syncDiff; + uint64 elapsed; + uint64 longest = 0; + uint64 totalElapsed = 0; /* * This is only called during checkpoints, and checkpoints should only @@ -342,7 +347,7 @@ void ProcessSyncRequests(void) /* Now scan the hashtable for fsync requests to process */ absorbCounter = FSYNCS_PER_ABSORB; hash_seq_init(&hstat, u_sess->storage_cxt.pendingOps); - while ((entry = (PendingFsyncEntry *) hash_seq_search(&hstat)) != NULL) { + while ((entry = (PendingFsyncEntry *)hash_seq_search(&hstat)) != NULL) { int failures; /* @@ -364,7 +369,7 @@ void ProcessSyncRequests(void) } /* Else assert we haven't missed it */ - Assert((CycleCtr) (entry->cycle_ctr + 1) == u_sess->storage_cxt.sync_cycle_ctr); + Assert((CycleCtr)(entry->cycle_ctr + 1) == u_sess->storage_cxt.sync_cycle_ctr); /* * If in checkpointer, we want to absorb pending requests every so @@ -405,10 +410,10 @@ void ProcessSyncRequests(void) processed++; if (u_sess->attr.attr_common.log_checkpoints) { - ereport(DEBUG1, (errmsg("checkpoint sync: number=%d file=%s time=%.3f msec", - processed, path, (double) elapsed / MSEC_PER_MICROSEC))); + ereport(DEBUG1, (errmsg("checkpoint sync: number=%d file=%s time=%.3f msec", processed, path, + (double)elapsed / MSEC_PER_MICROSEC))); } - break; /* out of retry loop */ + break; /* out of retry loop */ } /* @@ -418,8 +423,7 @@ void ProcessSyncRequests(void) */ if (!FILE_POSSIBLY_DELETED(errno) || failures > 0) { if (check_unlink_rel_hashtbl(entry->tag.rnode, entry->tag.forknum)) { - ereport(DEBUG1, - (errmsg("could not fsync file \"%s\": %m, this relation has been remove", path))); + ereport(DEBUG1, (errmsg("could not fsync file \"%s\": %m, this relation has been remove", path))); break; } @@ -432,13 +436,12 @@ void ProcessSyncRequests(void) break; } /* treat it as truncate */ - ereport(data_sync_elevel(ERROR), (errcode_for_file_access(), - errmsg("could not fsync file \"%s\": %m", path))); + ereport(data_sync_elevel(ERROR), + (errcode_for_file_access(), errmsg("could not fsync file \"%s\": %m", path))); break; } else { ereport(DEBUG1, - (errcode_for_file_access(), - errmsg("could not fsync file \"%s\" but retrying: %m", path))); + (errcode_for_file_access(), errmsg("could not fsync file \"%s\" but retrying: %m", path))); } /* @@ -475,11 +478,10 @@ void ProcessUnlinkList(const FileTag *ftag) if (!AmPageWriterMainProcess()) { prev = NULL; for (cell = list_head(u_sess->storage_cxt.pendingUnlinks); cell; cell = next) { - PendingUnlinkEntry *entry = (PendingUnlinkEntry *) lfirst(cell); + PendingUnlinkEntry *entry = (PendingUnlinkEntry *)lfirst(cell); next = lnext(cell); if (entry->tag.handler == ftag->handler && SYNCSW[ftag->handler].matchfiletag(ftag, &entry->tag)) { - u_sess->storage_cxt.pendingUnlinks = - list_delete_cell(u_sess->storage_cxt.pendingUnlinks, cell, prev); + u_sess->storage_cxt.pendingUnlinks = list_delete_cell(u_sess->storage_cxt.pendingUnlinks, cell, prev); pfree(entry); } else { prev = cell; @@ -505,7 +507,7 @@ void RememberSyncRequest(const FileTag *ftag, SyncRequestType type) PendingFsyncEntry *entry; /* Cancel previously entered request */ - entry = (PendingFsyncEntry *) hash_search(u_sess->storage_cxt.pendingOps, (void *) ftag, HASH_FIND, NULL); + entry = (PendingFsyncEntry *)hash_search(u_sess->storage_cxt.pendingOps, (void *)ftag, HASH_FIND, NULL); if (entry != NULL) { entry->canceled = true; } @@ -515,9 +517,8 @@ void RememberSyncRequest(const FileTag *ftag, SyncRequestType type) /* Cancel matching fsync requests */ hash_seq_init(&hstat, u_sess->storage_cxt.pendingOps); - while ((entry = (PendingFsyncEntry *) hash_seq_search(&hstat)) != NULL) { - if (entry->tag.handler == ftag->handler && - SYNCSW[ftag->handler].matchfiletag(ftag, &entry->tag)) { + while ((entry = (PendingFsyncEntry *)hash_seq_search(&hstat)) != NULL) { + if (entry->tag.handler == ftag->handler && SYNCSW[ftag->handler].matchfiletag(ftag, &entry->tag)) { entry->canceled = true; } } @@ -528,7 +529,7 @@ void RememberSyncRequest(const FileTag *ftag, SyncRequestType type) Assert(!AmPageWriterMainProcess()); /* Unlink request: put it in the linked list */ MemoryContext oldcxt = MemoryContextSwitchTo(u_sess->storage_cxt.pendingOpsCxt); - PendingUnlinkEntry *entry = (PendingUnlinkEntry*)palloc(sizeof(PendingUnlinkEntry)); + PendingUnlinkEntry *entry = (PendingUnlinkEntry *)palloc(sizeof(PendingUnlinkEntry)); entry->tag = *ftag; entry->cycle_ctr = u_sess->storage_cxt.checkpoint_cycle_ctr; u_sess->storage_cxt.pendingUnlinks = lappend(u_sess->storage_cxt.pendingUnlinks, entry); @@ -541,12 +542,12 @@ void RememberSyncRequest(const FileTag *ftag, SyncRequestType type) Assert(type == SYNC_REQUEST); - entry = (PendingFsyncEntry *) hash_search(u_sess->storage_cxt.pendingOps, (void *) ftag, HASH_ENTER, &found); + entry = (PendingFsyncEntry *)hash_search(u_sess->storage_cxt.pendingOps, (void *)ftag, HASH_ENTER, &found); /* if new entry, initialize it */ if (!found) { entry->cycle_ctr = u_sess->storage_cxt.sync_cycle_ctr; entry->canceled = false; - entry->tag = *ftag; // ZheapTodo initialize tag first + entry->tag = *ftag; // ZheapTodo initialize tag first } /* @@ -594,8 +595,7 @@ static bool ForwardSyncRequest(const FileTag *ftag, SyncRequestType type) ret = CkptForwardSyncRequest(ftag, type); break; default: - ereport(ERROR, - (errmsg("Incremental ckpt, Error SyncRequestType, the type is %d", type))); + ereport(ERROR, (errmsg("Incremental ckpt, Error SyncRequestType, the type is %d", type))); break; } } @@ -672,7 +672,7 @@ void ForgetDatabaseSyncRequests(Oid dbid) /* * We need two tags to forget two kinds of fsync requests generated by segment store and heap store respectively */ - for (int i=0; iincre_ckpt_sync_shmem; /* Initialize skip_slot array */ - skip_slot = (bool*)palloc0(sizeof(bool) * incre_ckpt_sync_shmem->num_requests); + skip_slot = (bool *)palloc0(sizeof(bool) * incre_ckpt_sync_shmem->num_requests); /* must hold the request queue in exclusive mode */ Assert(LWLockHeldByMe(incre_ckpt_sync_shmem->sync_queue_lwlock)); @@ -710,29 +710,27 @@ static bool CompactPageWriterRequestQueue(void) incre_ckpt_sync_shmem->requests[preserve_count++] = incre_ckpt_sync_shmem->requests[n]; } - ereport(DEBUG1, - (errmsg("pagewriter compacted fsync request queue from %d entries to %d entries", - incre_ckpt_sync_shmem->num_requests, preserve_count))); + ereport(DEBUG1, (errmsg("pagewriter compacted fsync request queue from %d entries to %d entries", + incre_ckpt_sync_shmem->num_requests, preserve_count))); incre_ckpt_sync_shmem->num_requests = preserve_count; pfree(skip_slot); return true; } - /* PgwrForwardSyncRequest +/* PgwrForwardSyncRequest * Forward a file-fsync request from a backend to the pagewriter. */ bool PgwrForwardSyncRequest(const FileTag *ftag, SyncRequestType type) { - CheckpointerRequest* request = NULL; + CheckpointerRequest *request = NULL; bool too_full = false; IncreCkptSyncShmemStruct *incre_ckpt_sync_shmem = g_instance.ckpt_cxt_ctl->incre_ckpt_sync_shmem; LWLock *sync_queue_lwlock = incre_ckpt_sync_shmem->sync_queue_lwlock; if (AmPageWriterMainProcess()) { - ereport(ERROR, - (errcode(ERRCODE_WITH_CHECK_OPTION_VIOLATION), - errmsg("PgwrForwardSyncRequest must not be called in pagewriter main thread"))); + ereport(ERROR, (errcode(ERRCODE_WITH_CHECK_OPTION_VIOLATION), + errmsg("PgwrForwardSyncRequest must not be called in pagewriter main thread"))); } LWLockAcquire(sync_queue_lwlock, LW_EXCLUSIVE); @@ -742,8 +740,9 @@ bool PgwrForwardSyncRequest(const FileTag *ftag, SyncRequestType type) * backend will have to perform its own fsync request. But before forcing * that to happen, we can try to compact the request queue. */ - if (incre_ckpt_sync_shmem->pagewritermain_pid == 0 || (incre_ckpt_sync_shmem->num_requests >= - incre_ckpt_sync_shmem->max_requests && !CompactPageWriterRequestQueue())) { + if (incre_ckpt_sync_shmem->pagewritermain_pid == 0 || + (incre_ckpt_sync_shmem->num_requests >= incre_ckpt_sync_shmem->max_requests && + !CompactPageWriterRequestQueue())) { LWLockRelease(sync_queue_lwlock); return false; } @@ -771,8 +770,8 @@ bool PgwrForwardSyncRequest(const FileTag *ftag, SyncRequestType type) */ void PgwrAbsorbFsyncRequests(void) { - CheckpointerRequest* requests = NULL; - CheckpointerRequest* request = NULL; + CheckpointerRequest *requests = NULL; + CheckpointerRequest *request = NULL; IncreCkptSyncShmemStruct *incre_ckpt_sync_shmem = g_instance.ckpt_cxt_ctl->incre_ckpt_sync_shmem; LWLock *sync_queue_lwlock = incre_ckpt_sync_shmem->sync_queue_lwlock; int n; @@ -795,9 +794,9 @@ void PgwrAbsorbFsyncRequests(void) if (n > 0) { errno_t rc; - requests = (CheckpointerRequest*)palloc(n * sizeof(CheckpointerRequest)); + requests = (CheckpointerRequest *)palloc(n * sizeof(CheckpointerRequest)); rc = memcpy_s(requests, n * sizeof(CheckpointerRequest), incre_ckpt_sync_shmem->requests, - n * sizeof(CheckpointerRequest)); + n * sizeof(CheckpointerRequest)); securec_check(rc, "\0", "\0"); } @@ -820,7 +819,7 @@ void PgwrAbsorbFsyncRequests(void) */ void PageWriterSyncWithAbsorption(void) { - volatile IncreCkptSyncShmemStruct* cps = g_instance.ckpt_cxt_ctl->incre_ckpt_sync_shmem; + volatile IncreCkptSyncShmemStruct *cps = g_instance.ckpt_cxt_ctl->incre_ckpt_sync_shmem; SpinLockAcquire(&cps->sync_lock); cps->fsync_start++; @@ -833,10 +832,10 @@ void PageWriterSyncWithAbsorption(void) SpinLockRelease(&cps->sync_lock); } -const int WAIT_THREAD_START = 600; /* every time sleep 0.1 sec, the 1min = 600 * 0.1 sec */ +const int WAIT_THREAD_START = 600; /* every time sleep 0.1 sec, the 1min = 600 * 0.1 sec */ void RequestPgwrSync(void) { - volatile IncreCkptSyncShmemStruct* cps = g_instance.ckpt_cxt_ctl->incre_ckpt_sync_shmem; + volatile IncreCkptSyncShmemStruct *cps = g_instance.ckpt_cxt_ctl->incre_ckpt_sync_shmem; /* * Send signal to request sync. It's possible that the pagewriter main thread @@ -855,9 +854,8 @@ void RequestPgwrSync(void) } else if (gs_signal_send(cps->pagewritermain_pid, SIGINT) != 0) { /* max wait 1min */ if (ntries >= WAIT_THREAD_START) { - ereport(LOG, - (errmsg("could not signal for pagewriter main thread: %m, thread pid is %lu", - cps->pagewritermain_pid))); + ereport(LOG, (errmsg("could not signal for pagewriter main thread: %m, thread pid is %lu", + cps->pagewritermain_pid))); break; } } else { @@ -887,7 +885,7 @@ void PageWriterSync(void) int64 old_fsync_start = 0; int64 new_fsync_start = 0; int64 new_fsync_done = 0; - volatile IncreCkptSyncShmemStruct* cps = g_instance.ckpt_cxt_ctl->incre_ckpt_sync_shmem; + volatile IncreCkptSyncShmemStruct *cps = g_instance.ckpt_cxt_ctl->incre_ckpt_sync_shmem; SpinLockAcquire(&cps->sync_lock); old_fsync_start = cps->fsync_start; SpinLockRelease(&cps->sync_lock); diff --git a/src/gausskernel/storage/tcap/tcap_drop.cpp b/src/gausskernel/storage/tcap/tcap_drop.cpp index a6cb8515c..ad050e497 100644 --- a/src/gausskernel/storage/tcap/tcap_drop.cpp +++ b/src/gausskernel/storage/tcap/tcap_drop.cpp @@ -1,3 +1,4 @@ +<<<<<<< HEAD /* * Copyright (c) Huawei Technologies Co., Ltd. 2020-2020. All rights reserved. * @@ -92,142 +93,170 @@ #include "storage/tcap.h" #include "storage/tcap_impl.h" - +/* + * 鍔熻兘璇ュ嚱鏁扮敤浜庨噸鍛藉悕鏁版嵁搴撲腑鐨勮〃銆 + * + * 鍙傛暟鍒楄〃锛 + * baseDesc锛歍rObjDesc缁撴瀯锛岃〃绀哄璞℃弿杩颁俊鎭殑鍩烘湰缁撴瀯銆 + * object锛歄bjectAddress缁撴瀯锛岃〃绀鸿閲嶅懡鍚嶇殑瀵硅薄鐨勫湴鍧淇℃伅銆 + * newName锛歝onst char鎸囬拡锛岃〃绀烘柊鐨勫璞″悕绉般 + */ static void TrRenameClass(TrObjDesc *baseDesc, ObjectAddress *object, const char *newName) { - Relation rel; - HeapTuple tup; - HeapTuple newtup; - char rbname[NAMEDATALEN]; - Datum values[Natts_pg_class] = { 0 }; - bool nulls[Natts_pg_class] = { false }; - bool replaces[Natts_pg_class] = { false }; - Oid relid = object->objectId; - errno_t rc = EOK; + Relation rel; // 鐢ㄤ簬琛ㄧず鍏崇郴锛堣〃锛夌殑鍏崇郴瀵硅薄 + HeapTuple tup; // 鐢ㄤ簬瀛樺偍浠庣郴缁熺紦瀛樹腑妫绱㈢殑鍫嗗厓缁 + HeapTuple newtup; // 鐢ㄤ簬瀛樺偍淇敼鍚庣殑鍫嗗厓缁 + char rbname[NAMEDATALEN]; // 瀛樺偍鏂扮殑瀵硅薄鍚嶇О鐨勫瓧绗︽暟缁 + Datum values[Natts_pg_class] = { 0 }; // 瀛樺偍寰呮洿鏂扮殑鍒楀 + bool nulls[Natts_pg_class] = { false }; // 鏍囧織浣嶆暟缁勶紝鎸囩ず姣忓垪鏄惁涓篘ULL + bool replaces[Natts_pg_class] = { false }; // 鏍囧織浣嶆暟缁勶紝鎸囩ず鍝簺鍒楀皢琚浛鎹 + Oid relid = object->objectId; // 瑕侀噸鍛藉悕鐨勮〃鐨凮ID锛堝璞℃爣璇嗙锛 + errno_t rc = EOK; // 鐢ㄤ簬澶勭悊瀛楃涓插鍒剁殑閿欒鐮 if (newName) { - rc = strncpy_s(rbname, NAMEDATALEN, newName, strlen(newName)); - securec_check(rc, "\0", "\0"); + rc = strncpy_s(rbname, NAMEDATALEN, newName, strlen(newName)); // 灏嗘柊鍚嶇О澶嶅埗鍒皉bname涓 + securec_check(rc, "\0", "\0"); // 妫鏌ュ瓧绗︿覆澶嶅埗鏄惁鍑洪敊 } else { - TrGenObjName(rbname, object->classId, relid); + TrGenObjName(rbname, object->classId, relid); // 鏍规嵁瀵硅薄鐨勭被鍜孫ID鐢熸垚鏂板悕绉 } - replaces[Anum_pg_class_relname - 1] = true; - values[Anum_pg_class_relname - 1] = CStringGetDatum(rbname); + replaces[Anum_pg_class_relname - 1] = true; // 鏍囪琛ㄧ殑鍚嶇О鍒楀皢琚浛鎹 + values[Anum_pg_class_relname - 1] = CStringGetDatum(rbname); // 璁剧疆鏂扮殑琛ㄥ悕鍊 - rel = heap_open(RelationRelationId, RowExclusiveLock); + rel = heap_open(RelationRelationId, RowExclusiveLock); // 鎵撳紑pg_class鍏崇郴锛岃幏鍙栫敤浜庤〃鐨勬搷浣滃彞鏌 - tup = SearchSysCache1(RELOID, ObjectIdGetDatum(relid)); + tup = SearchSysCache1(RELOID, ObjectIdGetDatum(relid)); // 浠庣郴缁熺紦瀛樹腑鑾峰彇琛ㄧ殑鍏冪粍 if (!HeapTupleIsValid(tup)) { - ereport(ERROR, (errcode(ERRCODE_CACHE_LOOKUP_FAILED), errmsg("cache lookup failed for relation %u", relid))); + ereport(ERROR, (errcode(ERRCODE_CACHE_LOOKUP_FAILED), errmsg("cache lookup failed for relation %u", relid))); // 濡傛灉鎵句笉鍒拌〃鐨勫厓缁勶紝鎶ラ敊 } - newtup = heap_modify_tuple(tup, RelationGetDescr(rel), values, nulls, replaces); + newtup = heap_modify_tuple(tup, RelationGetDescr(rel), values, nulls, replaces); // 淇敼鍏冪粍鐨勫 - simple_heap_update(rel, &newtup->t_self, newtup); + simple_heap_update(rel, &newtup->t_self, newtup); // 鍦ㄥ爢涓洿鏂颁慨鏀瑰悗鐨勫厓缁 - CatalogUpdateIndexes(rel, newtup); + CatalogUpdateIndexes(rel, newtup); // 鏇存柊绱㈠紩 - ReleaseSysCache(tup); + ReleaseSysCache(tup); // 閲婃斁绯荤粺缂撳瓨涓殑鍏冪粍 - heap_freetuple_ext(newtup); + heap_freetuple_ext(newtup); // 閲婃斁淇敼鍚庣殑鍏冪粍鐨勫唴瀛 - heap_close(rel, RowExclusiveLock); + heap_close(rel, RowExclusiveLock); // 鍏抽棴pg_class鍏崇郴 } +/** + * 鍔熻兘锛氶氱敤閲嶅懡鍚嶅嚱鏁帮紝鐢ㄤ簬閲嶅懡鍚嶆暟鎹簱涓殑鏌愪簺瀵硅薄銆 + * + * 鍙傛暟鍒楄〃锛 + * baseDesc锛歍rObjDesc缁撴瀯锛岃〃绀哄璞℃弿杩颁俊鎭殑鍩烘湰缁撴瀯銆 + * object锛歄bjectAddress缁撴瀯锛岃〃绀鸿閲嶅懡鍚嶇殑瀵硅薄鐨勫湴鍧淇℃伅銆 + * relid锛氳鎿嶄綔鐨勫叧绯伙紙琛級鐨凮ID銆 + * natts锛氬緟鎿嶄綔鐨勫睘鎬ф暟閲忋 + * oidAttrNum锛歄ID灞炴х殑搴忓彿銆 + * oidIndexId锛歄ID灞炴у搴旂殑绱㈠紩鐨凮ID銆 + * objTag锛氬璞$殑鏍囩锛岀敤浜庢姤閿欎俊鎭 + */ static void TrRenameCommon(TrObjDesc *baseDesc, ObjectAddress *object, Oid relid, int natts, int oidAttrNum, Oid oidIndexId, char *objTag) { - Relation rel; - HeapTuple tup; - HeapTuple newtup; - char rbname[NAMEDATALEN]; - Datum *values = (Datum *)palloc0(sizeof(Datum) * natts); - bool *nulls = (bool *)palloc0(sizeof(bool) * natts); - bool *replaces = (bool *)palloc0(sizeof(bool) * natts); - ScanKeyData skey[1]; - SysScanDesc sd; + Relation rel; // 鐢ㄤ簬琛ㄧず鍏崇郴锛堣〃锛夌殑鍏崇郴瀵硅薄 + HeapTuple tup; // 鐢ㄤ簬瀛樺偍浠庣郴缁熺紦瀛樹腑妫绱㈢殑鍫嗗厓缁 + HeapTuple newtup; // 鐢ㄤ簬瀛樺偍淇敼鍚庣殑鍫嗗厓缁 + char rbname[NAMEDATALEN]; // 瀛樺偍鏂扮殑瀵硅薄鍚嶇О鐨勫瓧绗︽暟缁 + Datum *values = (Datum *)palloc0(sizeof(Datum) * natts); // 瀛樺偍寰呮洿鏂扮殑鍒楀硷紝鍒濆鍖栦负0 + bool *nulls = (bool *)palloc0(sizeof(bool) * natts); // 鏍囧織浣嶆暟缁勶紝鎸囩ず姣忓垪鏄惁涓篘ULL锛屽垵濮嬪寲涓篺alse + bool *replaces = (bool *)palloc0(sizeof(bool) * natts); // 鏍囧織浣嶆暟缁勶紝鎸囩ず鍝簺鍒楀皢琚浛鎹紝鍒濆鍖栦负false + ScanKeyData skey[1]; // 鎵弿閿暟鎹暟缁 + SysScanDesc sd; // 绯荤粺鎵弿鎻忚堪绗 - TrGenObjName(rbname, object->classId, object->objectId); + TrGenObjName(rbname, object->classId, object->objectId); // 鏍规嵁瀵硅薄鐨勭被鍜孫ID鐢熸垚鏂板悕绉 - replaces[oidAttrNum - 1] = true; - values[oidAttrNum - 1] = CStringGetDatum(rbname); + replaces[oidAttrNum - 1] = true; // 鏍囪瑕佽鏇挎崲鐨勫睘鎬 + values[oidAttrNum - 1] = CStringGetDatum(rbname); // 璁剧疆鏂扮殑灞炴у - rel = heap_open(relid, RowExclusiveLock); + rel = heap_open(relid, RowExclusiveLock); // 鎵撳紑瑕佹搷浣滅殑鍏崇郴锛堣〃锛 - ScanKeyInit(&skey[0], ObjectIdAttributeNumber, BTEqualStrategyNumber, F_OIDEQ, ObjectIdGetDatum(object->objectId)); - sd = systable_beginscan(rel, oidIndexId, true, NULL, 1, skey); + ScanKeyInit(&skey[0], ObjectIdAttributeNumber, BTEqualStrategyNumber, F_OIDEQ, ObjectIdGetDatum(object->objectId)); // 鍒濆鍖栨壂鎻忛敭 + sd = systable_beginscan(rel, oidIndexId, true, NULL, 1, skey); // 寮濮嬬郴缁熻〃鎵弿 - tup = systable_getnext(sd); + tup = systable_getnext(sd); // 鑾峰彇鎵弿缁撴灉 if (!HeapTupleIsValid(tup)) { pfree(values); pfree(nulls); pfree(replaces); ereport(ERROR, - (errcode(ERRCODE_NO_DATA_FOUND), errmsg("could not find tuple for %s %u", objTag, object->objectId))); + (errcode(ERRCODE_NO_DATA_FOUND), errmsg("could not find tuple for %s %u", objTag, object->objectId))); // 濡傛灉鎵句笉鍒板搴斿厓缁勶紝鎶ラ敊 } - newtup = heap_modify_tuple(tup, RelationGetDescr(rel), values, nulls, replaces); + newtup = heap_modify_tuple(tup, RelationGetDescr(rel), values, nulls, replaces); // 淇敼鍏冪粍鐨勫 - simple_heap_update(rel, &newtup->t_self, newtup); + simple_heap_update(rel, &newtup->t_self, newtup); // 鍦ㄥ爢涓洿鏂颁慨鏀瑰悗鐨勫厓缁 - CatalogUpdateIndexes(rel, newtup); + CatalogUpdateIndexes(rel, newtup); // 鏇存柊绱㈠紩 - heap_freetuple_ext(newtup); + heap_freetuple_ext(newtup); // 閲婃斁淇敼鍚庣殑鍏冪粍鐨勫唴瀛 - systable_endscan(sd); + systable_endscan(sd); // 缁撴潫绯荤粺琛ㄦ壂鎻 - heap_close(rel, RowExclusiveLock); + heap_close(rel, RowExclusiveLock); // 鍏抽棴鍏崇郴锛堣〃锛 pfree(values); pfree(nulls); pfree(replaces); } + +/* + * 鍔熻兘锛氱敤浜庡垹闄ゆ寚瀹 baseid 瀵瑰簲鐨勮褰曘 + * + * 鍙傛暟鍒楄〃锛 + * baseid锛氳鍒犻櫎鐨勮褰曠殑 baseid銆 + */ static void TrDeleteBaseid(Oid baseid) { - Relation rbRel; - SysScanDesc sd; - ScanKeyData skey[1]; - HeapTuple tup; + Relation rbRel; // 鐢ㄤ簬琛ㄧず鍥炴敹绔欏叧绯伙紙琛級鐨勫叧绯诲璞 + SysScanDesc sd; // 绯荤粺鎵弿鎻忚堪绗 + ScanKeyData skey[1]; // 鎵弿閿暟鎹暟缁 + HeapTuple tup; // 鐢ㄤ簬瀛樺偍浠庣郴缁熻〃涓绱㈢殑鍫嗗厓缁 - rbRel = heap_open(RecyclebinRelationId, RowExclusiveLock); + rbRel = heap_open(RecyclebinRelationId, RowExclusiveLock); // 鎵撳紑鍥炴敹绔 - ScanKeyInit(&skey[0], Anum_pg_recyclebin_rcybaseid, BTEqualStrategyNumber, F_INT8EQ, ObjectIdGetDatum(baseid)); + ScanKeyInit(&skey[0], Anum_pg_recyclebin_rcybaseid, BTEqualStrategyNumber, F_INT8EQ, ObjectIdGetDatum(baseid)); // 鍒濆鍖栨壂鎻忛敭 - sd = systable_beginscan(rbRel, RecyclebinBaseidIndexId, true, NULL, 1, skey); + sd = systable_beginscan(rbRel, RecyclebinBaseidIndexId, true, NULL, 1, skey); // 寮濮嬬郴缁熻〃鎵弿 while (HeapTupleIsValid(tup = systable_getnext(sd))) { - simple_heap_delete(rbRel, &tup->t_self); + simple_heap_delete(rbRel, &tup->t_self); // 鍒犻櫎鎵弿鍒扮殑鍏冪粍 } - systable_endscan(sd); - heap_close(rbRel, RowExclusiveLock); - - /* - * CommandCounterIncrement here to ensure that preceding changes are all - * visible to the next deletion step. - */ + systable_endscan(sd); // 缁撴潫绯荤粺琛ㄦ壂鎻 + heap_close(rbRel, RowExclusiveLock); // 鍏抽棴鍥炴敹绔 CommandCounterIncrement(); } + +/* + * 鍔熻兘锛氱敤浜庡垹闄ゆ寚瀹 id 瀵瑰簲鐨勮褰曘 + * + * 鍙傛暟鍒楄〃锛 + * id锛氳鍒犻櫎鐨勮褰曠殑 id銆 + */ static void TrDeleteId(Oid id) { - Relation rbRel; - SysScanDesc sd; - ScanKeyData skey[1]; - HeapTuple tup; + Relation rbRel; // 鐢ㄤ簬琛ㄧず鍥炴敹绔欏叧绯伙紙琛級鐨勫叧绯诲璞 + SysScanDesc sd; // 绯荤粺鎵弿鎻忚堪绗 + ScanKeyData skey[1]; // 鎵弿閿暟鎹暟缁 + HeapTuple tup; // 鐢ㄤ簬瀛樺偍浠庣郴缁熻〃涓绱㈢殑鍫嗗厓缁 - rbRel = heap_open(RecyclebinRelationId, RowExclusiveLock); + rbRel = heap_open(RecyclebinRelationId, RowExclusiveLock); // 鎵撳紑鍥炴敹绔欏叧绯伙紙琛級 - ScanKeyInit(&skey[0], ObjectIdAttributeNumber, BTEqualStrategyNumber, F_OIDEQ, ObjectIdGetDatum(id)); + ScanKeyInit(&skey[0], ObjectIdAttributeNumber, BTEqualStrategyNumber, F_OIDEQ, ObjectIdGetDatum(id)); // 鍒濆鍖栨壂鎻忛敭 - sd = systable_beginscan(rbRel, RecyclebinIdIndexId, true, NULL, 1, skey); + sd = systable_beginscan(rbRel, RecyclebinIdIndexId, true, NULL, 1, skey); // 寮濮嬬郴缁熻〃鎵弿 if (HeapTupleIsValid(tup = systable_getnext(sd))) { - simple_heap_delete(rbRel, &tup->t_self); + simple_heap_delete(rbRel, &tup->t_self); // 鍒犻櫎鎵弿鍒扮殑鍏冪粍 } - systable_endscan(sd); - heap_close(rbRel, RowExclusiveLock); + systable_endscan(sd); // 缁撴潫绯荤粺琛ㄦ壂鎻 + heap_close(rbRel, RowExclusiveLock); // 鍏抽棴鍥炴敹绔欏叧绯伙紙琛級 /* * CommandCounterIncrement here to ensure that preceding changes are all @@ -235,28 +264,42 @@ static void TrDeleteId(Oid id) */ CommandCounterIncrement(); } - +/* + * 鍔熻兘锛氬垽鏂槸鍚﹂渶瑕佽繘琛岄昏緫鍒犻櫎銆 + * + * 鍙傛暟鍒楄〃锛 + * object锛歄bjectAddress缁撴瀯锛岃〃绀哄璞$殑鍦板潃淇℃伅銆 + * + */ static inline bool TrNeedLogicDrop(const ObjectAddress *object) { return object->rbDropMode == RB_DROP_MODE_LOGIC; } +/** + * 鍔熻兘锛氬垽鏂槸鍚﹀彲浠ヨ繘琛屾竻闄ゆ搷浣溿 + * + * 鍙傛暟鍒楄〃锛 + * baseDesc锛歍rObjDesc缁撴瀯锛岃〃绀哄璞℃弿杩颁俊鎭殑鍩烘湰缁撴瀯銆 + * object锛歄bjectAddress缁撴瀯锛岃〃绀哄璞$殑鍦板潃淇℃伅銆 + * relKind锛氳〃绀哄璞$殑鍏崇郴绫诲瀷銆 + */ static bool TrCanPurge(const TrObjDesc *baseDesc, const ObjectAddress *object, char relKind) { - Relation depRel; - SysScanDesc sd; - HeapTuple tuple; - ScanKeyData key[3]; - int nkeys; - bool found = false; + Relation depRel; // 鐢ㄤ簬琛ㄧず渚濊禆鍏崇郴锛堣〃锛夌殑鍏崇郴瀵硅薄 + SysScanDesc sd; // 绯荤粺鎵弿鎻忚堪绗 + HeapTuple tuple; // 鐢ㄤ簬瀛樺偍浠庣郴缁熻〃涓绱㈢殑鍫嗗厓缁 + ScanKeyData key[3]; // 鎵弿閿暟鎹暟缁 + int nkeys; // 鎵弿閿殑鏁伴噺 + bool found = false; // 琛ㄧず鏄惁鎵惧埌鍖归厤渚濊禆鍏崇郴 if (relKind != RELKIND_INDEX && relKind != RELKIND_GLOBAL_INDEX && relKind != RELKIND_RELATION) { - return false; + return false; // 濡傛灉鍏崇郴绫诲瀷涓嶆槸鍚堟硶绫诲瀷锛岀洿鎺ヨ繑鍥瀎alse } - depRel = heap_open(DependRelationId, AccessShareLock); + depRel = heap_open(DependRelationId, AccessShareLock); // 鎵撳紑渚濊禆鍏崇郴锛堣〃锛 - ScanKeyInit(&key[0], Anum_pg_depend_classid, BTEqualStrategyNumber, F_OIDEQ, ObjectIdGetDatum(object->classId)); + ScanKeyInit(&key[0], Anum_pg_depend_classid, BTEqualStrategyNumber, F_OIDEQ, ObjectIdGetDatum(object->classId)); // 鍒濆鍖栨壂鎻忛敭 ScanKeyInit(&key[1], Anum_pg_depend_objid, BTEqualStrategyNumber, F_OIDEQ, ObjectIdGetDatum(object->objectId)); nkeys = 2; if (object->objectSubId != 0) { @@ -265,85 +308,100 @@ static bool TrCanPurge(const TrObjDesc *baseDesc, const ObjectAddress *object, c nkeys = 3; } - sd = systable_beginscan(depRel, DependDependerIndexId, true, NULL, nkeys, key); + sd = systable_beginscan(depRel, DependDependerIndexId, true, NULL, nkeys, key); // 寮濮嬬郴缁熻〃鎵弿 while (HeapTupleIsValid(tuple = systable_getnext(sd))) { Form_pg_depend depForm = (Form_pg_depend)GETSTRUCT(tuple); - if (depForm->refclassid == RelationRelationId && depForm->refobjid == baseDesc->relid) { - if (depForm->deptype != DEPENDENCY_AUTO) { + if (depForm->refclassid == RelationRelationId && depForm->refobjid == baseDesc->relid) { // 鍒ゆ柇鏄惁涓轰緷璧栦簬褰撳墠琛ㄧ殑渚濊禆鍏崇郴 + if (depForm->deptype != DEPENDENCY_AUTO) { // 濡傛灉渚濊禆绫诲瀷涓嶆槸鑷姩渚濊禆锛屼笉鍙竻闄 found = false; break; } - found = true; + found = true; // 鎵惧埌鍖归厤鐨勪緷璧栧叧绯 } } - systable_endscan(sd); - heap_close(depRel, AccessShareLock); + systable_endscan(sd); // 缁撴潫绯荤粺琛ㄦ壂鎻 + heap_close(depRel, AccessShareLock); // 鍏抽棴渚濊禆鍏崇郴锛堣〃锛 return found; } + +/* + * 鍔熻兘锛氭墽琛屽垹闄ょ储寮曠殑鎿嶄綔銆 + * + * 鍙傛暟鍒楄〃锛 + * baseDesc锛歍rObjDesc缁撴瀯锛岃〃绀哄璞℃弿杩颁俊鎭殑鍩烘湰缁撴瀯銆 + * object锛歄bjectAddress缁撴瀯锛岃〃绀哄璞$殑鍦板潃淇℃伅銆 + */ static void TrDoDropIndex(TrObjDesc *baseDesc, ObjectAddress *object) { - Assert(object->objectSubId == 0); + Assert(object->objectSubId == 0); // 鏂█锛岀‘淇濆璞$殑瀛愭爣璇嗙涓0锛堢储寮曟病鏈夊瓙鏍囪瘑绗︼級 - if (TrNeedLogicDrop(object)) { - TrObjDesc desc = *baseDesc; + if (TrNeedLogicDrop(object)) { // 濡傛灉闇瑕侀昏緫鍒犻櫎 + TrObjDesc desc = *baseDesc; // 澶嶅埗鍩烘湰鎻忚堪淇℃伅 if (!TR_IS_BASE_OBJ(baseDesc, object)) { - /* Deletion lock already accquired before single object drop. */ - Relation rel = relation_open(object->objectId, NoLock); + /* 鍗曚釜瀵硅薄鍒犻櫎涔嬪墠宸茶幏鍙栧垹闄ら攣銆*/ + Relation rel = relation_open(object->objectId, NoLock); // 鎵撳紑瑕佸垹闄ょ殑鍏崇郴锛堣〃锛 - TrDescInit(rel, &desc, RB_OPER_DROP, TrGetObjType(RelationGetNamespace(rel), RELKIND_INDEX), + TrDescInit(rel, &desc, RB_OPER_DROP, TrGetObjType(RelationGetNamespace(rel), RELKIND_INDEX), // 鍒濆鍖栨弿杩颁俊鎭 TrCanPurge(baseDesc, object, RelationGetRelkind(rel))); - relation_close(rel, NoLock); + relation_close(rel, NoLock); // 鍏抽棴鍏崇郴锛堣〃锛 - TrDescWrite(&desc); + TrDescWrite(&desc); // 鍐欏叆鎻忚堪淇℃伅 } - TrRenameClass(baseDesc, object, desc.name); + TrRenameClass(baseDesc, object, desc.name); // 閲嶅懡鍚嶅璞 } else { - index_drop(object->objectId, false); + index_drop(object->objectId, false); // 鐩存帴鍒犻櫎绱㈠紩 } return; } +/* + * 鍔熻兘锛氭墽琛屽垹闄よ〃鐨勬搷浣溿 + * + * 鍙傛暟鍒楄〃锛 + * baseDesc锛歍rObjDesc缁撴瀯锛岃〃绀哄璞℃弿杩颁俊鎭殑鍩烘湰缁撴瀯銆 + * object锛歄bjectAddress缁撴瀯锛岃〃绀哄璞$殑鍦板潃淇℃伅銆 + * relKind锛氳〃绀哄璞$殑鍏崇郴绫诲瀷锛屽彲浠ユ槸RELKIND_RELATION銆丷ELKIND_VIEW銆丷ELKIND_COMPOSITE_TYPE鎴朢ELKIND_FOREIGN_TABLE銆 + */ static void TrDoDropTable(TrObjDesc *baseDesc, ObjectAddress *object, char relKind) { - if (TrNeedLogicDrop(object)) { + if (TrNeedLogicDrop(object)) { // 濡傛灉闇瑕侀昏緫鍒犻櫎 TrObjDesc desc; if (object->objectSubId != 0 || relKind == RELKIND_VIEW || relKind == RELKIND_COMPOSITE_TYPE || - relKind == RELKIND_FOREIGN_TABLE) { + relKind == RELKIND_FOREIGN_TABLE) { // 瀵逛簬瀛愬璞℃垨鐗瑰畾绫诲瀷鐨勫璞★紝鐩存帴閲嶅懡鍚嶅苟杩斿洖 TrRenameClass(baseDesc, object, NULL); return; } - desc = *baseDesc; + desc = *baseDesc; // 澶嶅埗鍩烘湰鎻忚堪淇℃伅 if (!TR_IS_BASE_OBJ(baseDesc, object)) { - /* Deletion lock already accquired before single object drop. */ - Relation rel = relation_open(object->objectId, NoLock); + /* 鍗曚釜瀵硅薄鍒犻櫎涔嬪墠宸茶幏鍙栧垹闄ら攣銆*/ + Relation rel = relation_open(object->objectId, NoLock); // 鎵撳紑瑕佸垹闄ょ殑鍏崇郴锛堣〃锛 - TrDescInit(rel, &desc, RB_OPER_DROP, TrGetObjType(InvalidOid, relKind), + TrDescInit(rel, &desc, RB_OPER_DROP, TrGetObjType(InvalidOid, relKind), // 鍒濆鍖栨弿杩颁俊鎭 TrCanPurge(baseDesc, object, relKind)); - relation_close(rel, NoLock); + relation_close(rel, NoLock); // 鍏抽棴鍏崇郴锛堣〃锛 - TrDescWrite(&desc); + TrDescWrite(&desc); // 鍐欏叆鎻忚堪淇℃伅 } - TrRenameClass(baseDesc, object, desc.name); + TrRenameClass(baseDesc, object, desc.name); // 閲嶅懡鍚嶅璞 return; } - /* * relation_open() must be before the heap_drop_with_catalog(). If you reload * relation after drop, it may cause other exceptions during the drop process. */ if (object->objectSubId != 0) - RemoveAttributeById(object->objectId, object->objectSubId); + RemoveAttributeById(object->objectId, object->objectSubId); // 鍒犻櫎瀛愬睘鎬 else - heap_drop_with_catalog(object->objectId); + heap_drop_with_catalog(object->objectId); // 鍒犻櫎琛 /* * IMPORANT: The relation must not be reloaded after heap_drop_with_catalog() @@ -354,394 +412,636 @@ static void TrDoDropTable(TrObjDesc *baseDesc, ObjectAddress *object, char relKi return; } +/* + * 鍔熻兘锛氭墽琛屽垹闄ょ被鍨嬬殑鎿嶄綔銆 + * + * 鍙傛暟鍒楄〃锛 + * baseDesc锛歍rObjDesc缁撴瀯锛岃〃绀哄璞℃弿杩颁俊鎭殑鍩烘湰缁撴瀯銆 + * object锛歄bjectAddress缁撴瀯锛岃〃绀哄璞$殑鍦板潃淇℃伅銆 + */ static void TrDoDropType(TrObjDesc *baseDesc, ObjectAddress *object) { - if (TrNeedLogicDrop(object)) { - TrRenameCommon(baseDesc, object, TypeRelationId, Natts_pg_type, Anum_pg_type_typname, TypeOidIndexId, "type"); + if (TrNeedLogicDrop(object)) { // 濡傛灉闇瑕侀昏緫鍒犻櫎 + TrRenameCommon(baseDesc, object, TypeRelationId, Natts_pg_type, Anum_pg_type_typname, TypeOidIndexId, "type"); // 璋冪敤閫氱敤閲嶅懡鍚嶅嚱鏁 } else { - RemoveTypeById(object->objectId); - } - - return; -} - -static void TrDoDropConstraint(TrObjDesc *baseDesc, ObjectAddress *object) -{ - if (TrNeedLogicDrop(object)) { - TrRenameCommon(baseDesc, object, ConstraintRelationId, Natts_pg_constraint, Anum_pg_constraint_conname, - ConstraintOidIndexId, "constraint"); - } else { - RemoveConstraintById(object->objectId); - } - - return; -} - -static void TrDoDropTrigger(TrObjDesc *baseDesc, ObjectAddress *object) -{ - if (TrNeedLogicDrop(object)) { - TrRenameCommon(baseDesc, object, TriggerRelationId, Natts_pg_trigger, Anum_pg_trigger_tgname, TriggerOidIndexId, - "trigger"); - } else { - RemoveTriggerById(object->objectId); - } - - return; -} - -static void TrDoDropRewrite(TrObjDesc *baseDesc, ObjectAddress *object) -{ - if (TrNeedLogicDrop(object)) { - /* nothing to do as rule-based view requires that origin rule name preserved. */ - } else { - RemoveRewriteRuleById(object->objectId); - } - - return; -} - -static void TrDoDropAttrdef(TrObjDesc *baseDesc, ObjectAddress *object) -{ - if (TrNeedLogicDrop(object)) { - /* nothing to do as no name attribute in system catalog */ - } else { - RemoveAttrDefaultById(object->objectId); - } - - return; -} - -static void TrDoDropProc(TrObjDesc *baseDesc, ObjectAddress *object) -{ - if (TrNeedLogicDrop(object)) { - TrRenameCommon(baseDesc, object, ProcedureRelationId, Natts_pg_proc, Anum_pg_proc_proname, ProcedureOidIndexId, - "procedure"); - } else { - RemoveFunctionById(object->objectId); - } - - return; -} - -static void TrDoDropCast(TrObjDesc *baseDesc, ObjectAddress *object) -{ - if (TrNeedLogicDrop(object)) { - /* nothing to do as no name attribute in system catalog */ - } else { - DropCastById(object->objectId); - } - - return; -} - -static void TrDoDropCollation(TrObjDesc *baseDesc, ObjectAddress *object) -{ - if (TrNeedLogicDrop(object)) { - TrRenameCommon(baseDesc, object, CollationRelationId, Natts_pg_collation, Anum_pg_collation_collname, - CollationOidIndexId, "collation"); - } else { - RemoveCollationById(object->objectId); - } - - return; -} - -static void TrDoDropConversion(TrObjDesc *baseDesc, ObjectAddress *object) -{ - if (TrNeedLogicDrop(object)) { - TrRenameCommon(baseDesc, object, ConversionRelationId, Natts_pg_conversion, Anum_pg_conversion_conname, - ConversionOidIndexId, "conversion"); - } else { - RemoveConversionById(object->objectId); - } - - return; -} - - -static void TrDoDropProceduralLanguage(TrObjDesc *baseDesc, ObjectAddress *object) -{ - if (TrNeedLogicDrop(object)) { - TrRenameCommon(baseDesc, object, LanguageRelationId, Natts_pg_language, Anum_pg_language_lanname, - LanguageOidIndexId, "language"); - } else { - DropProceduralLanguageById(object->objectId); - } - - return; -} - -static void TrDoDropLargeObject(TrObjDesc *baseDesc, ObjectAddress *object) -{ - if (TrNeedLogicDrop(object)) { - /* nothing to do as no name attribute in system catalog */ - } else { - LargeObjectDrop(object->objectId); - } - - return; -} - -static void TrDoDropOperator(TrObjDesc *baseDesc, ObjectAddress *object) -{ - if (TrNeedLogicDrop(object)) { - TrRenameCommon(baseDesc, object, OperatorRelationId, Natts_pg_operator, Anum_pg_operator_oprname, - OperatorOidIndexId, "operator"); - } else { - RemoveOperatorById(object->objectId); - } - - return; -} - -static void TrDoDropOpClass(TrObjDesc *baseDesc, ObjectAddress *object) -{ - if (TrNeedLogicDrop(object)) { - TrRenameCommon(baseDesc, object, OperatorClassRelationId, Natts_pg_opclass, Anum_pg_opclass_opcname, - OpclassOidIndexId, "opclass"); - } else { - RemoveOpClassById(object->objectId); - } - - return; -} - -static void TrDoDropOpFamily(TrObjDesc *baseDesc, ObjectAddress *object) -{ - if (TrNeedLogicDrop(object)) { - TrRenameCommon(baseDesc, object, OperatorFamilyRelationId, Natts_pg_opfamily, Anum_pg_opfamily_opfname, - OpfamilyOidIndexId, "opfamily"); - } else { - RemoveOpFamilyById(object->objectId); - } - - return; -} - - -static void TrDoDropAmOp(TrObjDesc *baseDesc, ObjectAddress *object) -{ - if (TrNeedLogicDrop(object)) { - /* nothing to do as no name attribute in system catalog */ - } else { - RemoveAmOpEntryById(object->objectId); - } - - return; -} - -static void TrDoDropAmProc(TrObjDesc *baseDesc, ObjectAddress *object) -{ - if (TrNeedLogicDrop(object)) { - /* nothing to do as no name attribute in system catalog */ - } else { - RemoveAmProcEntryById(object->objectId); - } - - return; -} - -static void TrDoDropSchema(TrObjDesc *baseDesc, ObjectAddress *object) -{ - if (TrNeedLogicDrop(object)) { - TrRenameCommon(baseDesc, object, NamespaceRelationId, Natts_pg_namespace, Anum_pg_namespace_nspname, - NamespaceOidIndexId, "namespace"); - } else { - RemoveSchemaById(object->objectId); - } - - return; -} - -static void TrDoDropTSParser(TrObjDesc *baseDesc, ObjectAddress *object) -{ - if (TrNeedLogicDrop(object)) { - TrRenameCommon(baseDesc, object, TSParserRelationId, Natts_pg_ts_parser, Anum_pg_ts_parser_prsname, - TSParserOidIndexId, "ts parser"); - } else { - RemoveTSParserById(object->objectId); - } - - return; -} - -static void TrDoDropTSDictionary(TrObjDesc *baseDesc, ObjectAddress *object) -{ - if (TrNeedLogicDrop(object)) { - TrRenameCommon(baseDesc, object, TSDictionaryRelationId, Natts_pg_ts_dict, Anum_pg_ts_dict_dictname, - TSDictionaryOidIndexId, "ts dictionary"); - } else { - RemoveTSDictionaryById(object->objectId); - } - - return; -} - -static void TrDoDropTSTemplate(TrObjDesc *baseDesc, ObjectAddress *object) -{ - if (TrNeedLogicDrop(object)) { - TrRenameCommon(baseDesc, object, TSTemplateRelationId, Natts_pg_ts_template, Anum_pg_ts_template_tmplname, - TSTemplateOidIndexId, "ts template"); - } else { - RemoveTSTemplateById(object->objectId); - } - - return; -} - -static void TrDoDropTSConfiguration(TrObjDesc *baseDesc, ObjectAddress *object) -{ - if (TrNeedLogicDrop(object)) { - TrRenameCommon(baseDesc, object, TSConfigRelationId, Natts_pg_ts_config, Anum_pg_ts_config_cfgname, - TSConfigOidIndexId, "ts configuration"); - } else { - RemoveTSConfigurationById(object->objectId); - } - - return; -} - -static void TrDoDropForeignDataWrapper(TrObjDesc *baseDesc, ObjectAddress *object) -{ - if (TrNeedLogicDrop(object)) { - TrRenameCommon(baseDesc, object, ForeignDataWrapperRelationId, Natts_pg_foreign_data_wrapper, - Anum_pg_foreign_data_wrapper_fdwname, ForeignDataWrapperOidIndexId, "foreign data wrapper"); - } else { - RemoveForeignDataWrapperById(object->objectId); - } - - return; -} - -static void TrDoDropForeignServer(TrObjDesc *baseDesc, ObjectAddress *object) -{ - if (TrNeedLogicDrop(object)) { - TrRenameCommon(baseDesc, object, ForeignServerRelationId, Natts_pg_foreign_server, - Anum_pg_foreign_server_srvname, ForeignServerOidIndexId, "foreign server"); - } else { - RemoveForeignServerById(object->objectId); - } - - return; -} - -static void TrDoDropUserMapping(TrObjDesc *baseDesc, ObjectAddress *object) -{ - if (TrNeedLogicDrop(object)) { - /* nothing to do as no name attribute in system catalog */ - } else { - RemoveUserMappingById(object->objectId); - } - - return; -} - - -static void TrDoDropDefaultACL(TrObjDesc *baseDesc, ObjectAddress *object) -{ - if (TrNeedLogicDrop(object)) { - /* nothing to do as no name attribute in system catalog */ - } else { - RemoveDefaultACLById(object->objectId); - } - - return; -} - -static void TrDoDropPgxcClass(TrObjDesc *baseDesc, ObjectAddress *object) -{ - if (TrNeedLogicDrop(object)) { - /* nothing to do as no name attribute in system catalog */ - } else { - RemovePgxcClass(object->objectId); - } - - return; -} - -static void TrDoDropExtension(TrObjDesc *baseDesc, ObjectAddress *object) -{ - if (TrNeedLogicDrop(object)) { - TrRenameCommon(baseDesc, object, ExtensionRelationId, Natts_pg_extension, Anum_pg_extension_extname, - ExtensionOidIndexId, "extension"); - } else { - RemoveExtensionById(object->objectId); - } - - return; -} - -static void TrDoDropDataSource(TrObjDesc *baseDesc, ObjectAddress *object) -{ - if (TrNeedLogicDrop(object)) { - TrRenameCommon(baseDesc, object, DataSourceRelationId, Natts_pg_extension_data_source, - Anum_pg_extension_data_source_srcname, DataSourceOidIndexId, "extension data source"); - } else { - RemoveDataSourceById(object->objectId); - } - - return; -} - -static void TrDoDropDirectory(TrObjDesc *baseDesc, ObjectAddress *object) -{ - if (TrNeedLogicDrop(object)) { - TrRenameCommon(baseDesc, object, PgDirectoryRelationId, Natts_pg_directory, Anum_pg_directory_directory_name, - PgDirectoryOidIndexId, "directory"); - } else { - RemoveDirectoryById(object->objectId); - } - - return; -} - -static void TrDoDropRlsPolicy(TrObjDesc *baseDesc, ObjectAddress *object) -{ - if (TrNeedLogicDrop(object)) { - TrRenameCommon(baseDesc, object, RlsPolicyRelationId, Natts_pg_rlspolicy, Anum_pg_rlspolicy_polname, - PgRlspolicyOidIndex, "rlspolicy"); - } else { - RemoveRlsPolicyById(object->objectId); - } - - return; -} - -static void TrDoDropJob(TrObjDesc *baseDesc, ObjectAddress *object) -{ - if (TrNeedLogicDrop(object)) { - /* nothing to do as no name attribute in system catalog */ - } else { - RemoveJobById(object->objectId); - } - - return; -} - -static void TrDoDropSynonym(TrObjDesc *baseDesc, ObjectAddress *object) -{ - if (TrNeedLogicDrop(object)) { - TrRenameCommon(baseDesc, object, PgSynonymRelationId, Natts_pg_synonym, Anum_pg_synonym_synname, - SynonymOidIndexId, "synonym"); - } else { - RemoveSynonymById(object->objectId); + RemoveTypeById(object->objectId); // 鐩存帴鍒犻櫎绫诲瀷 } return; } +/* + * T鍔熻兘鎵ц鍒犻櫎绾︽潫鐨勬搷浣溿 + * + * 鍙傛暟鍒楄〃锛 + * baseDesc锛歍rObjDesc缁撴瀯锛岃〃绀哄璞℃弿杩颁俊鎭殑鍩烘湰缁撴瀯銆 + * object锛歄bjectAddress缁撴瀯锛岃〃绀哄璞$殑鍦板潃淇℃伅銆 + */ +static void TrDoDropConstraint(TrObjDesc *baseDesc, ObjectAddress *object) +{ + if (TrNeedLogicDrop(object)) { // 濡傛灉闇瑕侀昏緫鍒犻櫎 + TrRenameCommon(baseDesc, object, ConstraintRelationId, Natts_pg_constraint, Anum_pg_constraint_conname, + ConstraintOidIndexId, "constraint"); // 璋冪敤閫氱敤閲嶅懡鍚嶅嚱鏁 + } else { + RemoveConstraintById(object->objectId); // 鐩存帴鍒犻櫎绾︽潫 + } + + return; +} + + +/* + * 鍔熻兘锛氭墽琛屽垹闄よЕ鍙戝櫒鐨勬搷浣溿 + * + * 鍙傛暟鍒楄〃锛 + * baseDesc锛歍rObjDesc缁撴瀯锛岃〃绀哄璞℃弿杩颁俊鎭殑鍩烘湰缁撴瀯銆 + * object锛歄bjectAddress缁撴瀯锛岃〃绀哄璞$殑鍦板潃淇℃伅銆 + */ +static void TrDoDropTrigger(TrObjDesc *baseDesc, ObjectAddress *object) +{ + if (TrNeedLogicDrop(object)) { // 濡傛灉闇瑕侀昏緫鍒犻櫎 + TrRenameCommon(baseDesc, object, TriggerRelationId, Natts_pg_trigger, Anum_pg_trigger_tgname, TriggerOidIndexId, + "trigger"); // 璋冪敤閫氱敤閲嶅懡鍚嶅嚱鏁 + } else { + RemoveTriggerById(object->objectId); // 鐩存帴鍒犻櫎瑙﹀彂鍣 + } + + return; +} + +/* + * 鍔熻兘锛氭墽琛屽垹闄ら噸鍐欒鍒欑殑鎿嶄綔銆 + * + * 鍙傛暟鍒楄〃锛 + * baseDesc锛歍rObjDesc缁撴瀯锛岃〃绀哄璞℃弿杩颁俊鎭殑鍩烘湰缁撴瀯銆 + * object锛歄bjectAddress缁撴瀯锛岃〃绀哄璞$殑鍦板潃淇℃伅銆 + */ +static void TrDoDropRewrite(TrObjDesc *baseDesc, ObjectAddress *object) +{ + if (TrNeedLogicDrop(object)) { + /* 鏃犻渶鎿嶄綔锛屽洜涓哄熀浜庤鍒欑殑瑙嗗浘瑕佹眰淇濈暀鍘熷瑙勫垯鍚嶇О銆*/ + } else { + RemoveRewriteRuleById(object->objectId); // 鐩存帴鍒犻櫎閲嶅啓瑙勫垯 + } + + return; +} + + +/* + * 鍔熻兘锛氭墽琛屽垹闄ゅ睘鎬ч粯璁ゅ肩殑鎿嶄綔銆 + * + * 鍙傛暟鍒楄〃锛 + * baseDesc锛歍rObjDesc缁撴瀯锛岃〃绀哄璞℃弿杩颁俊鎭殑鍩烘湰缁撴瀯銆 + * object锛歄bjectAddress缁撴瀯锛岃〃绀哄璞$殑鍦板潃淇℃伅銆 + */ +static void TrDoDropAttrdef(TrObjDesc *baseDesc, ObjectAddress *object) +{ + if (TrNeedLogicDrop(object)) { + /* 鏃犻渶鎿嶄綔锛屽洜涓虹郴缁熺洰褰曚腑娌℃湁鍚嶇О灞炴с*/ + } else { + RemoveAttrDefaultById(object->objectId); // 鐩存帴鍒犻櫎灞炴ч粯璁ゅ + } + + return; +} + +/* + * 鍔熻兘锛氭墽琛屽垹闄よ繃绋嬬殑鎿嶄綔銆 + * + * 鍙傛暟鍒楄〃锛 + * baseDesc锛歍rObjDesc缁撴瀯锛岃〃绀哄璞℃弿杩颁俊鎭殑鍩烘湰缁撴瀯銆 + * object锛歄bjectAddress缁撴瀯锛岃〃绀哄璞$殑鍦板潃淇℃伅銆 + */ +static void TrDoDropProc(TrObjDesc *baseDesc, ObjectAddress *object) +{ + if (TrNeedLogicDrop(object)) { // 濡傛灉闇瑕侀昏緫鍒犻櫎 + TrRenameCommon(baseDesc, object, ProcedureRelationId, Natts_pg_proc, Anum_pg_proc_proname, ProcedureOidIndexId, + "procedure"); // 閲嶅懡鍚 + } else { + RemoveFunctionById(object->objectId); // 鐩存帴鍒犻櫎杩囩▼ + } + + return; +} + + +/* + * 鍔熻兘锛氭墽琛屽垹闄ょ被鍨嬭浆鎹㈢殑鎿嶄綔銆 + * + * 鍙傛暟鍒楄〃锛 + * baseDesc锛歍rObjDesc缁撴瀯锛岃〃绀哄璞℃弿杩颁俊鎭殑鍩烘湰缁撴瀯銆 + * object锛歄bjectAddress缁撴瀯锛岃〃绀哄璞$殑鍦板潃淇℃伅銆 + */ +static void TrDoDropCast(TrObjDesc *baseDesc, ObjectAddress *object) +{ + if (TrNeedLogicDrop(object)) { + /* 鏃犻渶鎿嶄綔锛屽洜涓虹郴缁熺洰褰曚腑娌℃湁鍚嶇О灞炴с*/ + } else { + DropCastById(object->objectId); // 鐩存帴鍒犻櫎绫诲瀷杞崲 + } + + return; +} + +/* + * 鍔熻兘锛氭墽琛屽垹闄ゆ帓搴忚鍒欑殑鎿嶄綔銆 + * + * 鍙傛暟鍒楄〃锛 + * baseDesc锛歍rObjDesc缁撴瀯锛岃〃绀哄璞℃弿杩颁俊鎭殑鍩烘湰缁撴瀯銆 + * object锛歄bjectAddress缁撴瀯锛岃〃绀哄璞$殑鍦板潃淇℃伅銆 + */ +static void TrDoDropCollation(TrObjDesc *baseDesc, ObjectAddress *object) +{ + if (TrNeedLogicDrop(object)) { // 濡傛灉闇瑕侀昏緫鍒犻櫎 + TrRenameCommon(baseDesc, object, CollationRelationId, Natts_pg_collation, Anum_pg_collation_collname, + CollationOidIndexId, "collation"); // 閲嶅懡鍚 + } else { + RemoveCollationById(object->objectId); // 鐩存帴鍒犻櫎鎺掑簭瑙勫垯 + } + + return; +} + + +/* + * 鍔熻兘锛氭墽琛屽垹闄ょ被鍨嬭浆鎹㈢殑鎿嶄綔銆 + * + * 鍙傛暟鍒楄〃锛 + * baseDesc锛歍rObjDesc缁撴瀯锛岃〃绀哄璞℃弿杩颁俊鎭殑鍩烘湰缁撴瀯銆 + * object锛歄bjectAddress缁撴瀯锛岃〃绀哄璞$殑鍦板潃淇℃伅銆 + */ +static void TrDoDropConversion(TrObjDesc *baseDesc, ObjectAddress *object) +{ + if (TrNeedLogicDrop(object)) { // 濡傛灉闇瑕侀昏緫鍒犻櫎 + TrRenameCommon(baseDesc, object, ConversionRelationId, Natts_pg_conversion, Anum_pg_conversion_conname, + ConversionOidIndexId, "conversion"); // 閲嶅懡鍚 + } else { + RemoveConversionById(object->objectId); // 鐩存帴鍒犻櫎绫诲瀷杞崲 + } + + return; +} + +/* + * 鍔熻兘锛氭墽琛屽垹闄よ繃绋嬭瑷鐨勬搷浣溿 + * + * 鍙傛暟鍒楄〃锛 + * baseDesc锛歍rObjDesc缁撴瀯锛岃〃绀哄璞℃弿杩颁俊鎭殑鍩烘湰缁撴瀯銆 + * object锛歄bjectAddress缁撴瀯锛岃〃绀哄璞$殑鍦板潃淇℃伅銆 + */ +static void TrDoDropProceduralLanguage(TrObjDesc *baseDesc, ObjectAddress *object) +{ + if (TrNeedLogicDrop(object)) { // 濡傛灉闇瑕侀昏緫鍒犻櫎 + TrRenameCommon(baseDesc, object, LanguageRelationId, Natts_pg_language, Anum_pg_language_lanname, + LanguageOidIndexId, "language"); // 閲嶅懡鍚 + } else { + DropProceduralLanguageById(object->objectId); // 鐩存帴鍒犻櫎杩囩▼璇█ + } + + return; +} + + +/* + * 鍔熻兘锛氭墽琛屽垹闄ゅぇ瀵硅薄鐨勬搷浣溿 + * + * 鍙傛暟鍒楄〃锛 + * baseDesc锛歍rObjDesc缁撴瀯锛岃〃绀哄璞℃弿杩颁俊鎭殑鍩烘湰缁撴瀯銆 + * object锛歄bjectAddress缁撴瀯锛岃〃绀哄璞$殑鍦板潃淇℃伅銆 + */ +static void TrDoDropLargeObject(TrObjDesc *baseDesc, ObjectAddress *object) +{ + if (TrNeedLogicDrop(object)) { + /* 鏃犻渶鎿嶄綔锛屽洜涓虹郴缁熺洰褰曚腑娌℃湁鍚嶇О灞炴с*/ + } else { + LargeObjectDrop(object->objectId); // 鐩存帴鍒犻櫎瀵硅薄 + } + + return; +} + +/* + * 鍔熻兘锛氭墽琛屽垹闄ゆ搷浣滅鐨勬搷浣溿 + * + * 鍙傛暟鍒楄〃锛 + * baseDesc锛歍rObjDesc缁撴瀯锛岃〃绀哄璞℃弿杩颁俊鎭殑鍩烘湰缁撴瀯銆 + * object锛歄bjectAddress缁撴瀯锛岃〃绀哄璞$殑鍦板潃淇℃伅銆 + */ +static void TrDoDropOperator(TrObjDesc *baseDesc, ObjectAddress *object) +{ + if (TrNeedLogicDrop(object)) { // 濡傛灉闇瑕侀昏緫鍒犻櫎 + TrRenameCommon(baseDesc, object, OperatorRelationId, Natts_pg_operator, Anum_pg_operator_oprname, + OperatorOidIndexId, "operator"); // 閲嶅懡鍚 + } else { + RemoveOperatorById(object->objectId); // 鐩存帴鍒犻櫎鎿嶄綔绗 + } + + return; +} + + +/* + * 鍔熻兘锛氭墽琛屽垹闄ゆ搷浣滅绫荤殑鎿嶄綔銆 + * + * 鍙傛暟鍒楄〃锛 + * baseDesc锛歍rObjDesc缁撴瀯锛岃〃绀哄璞℃弿杩颁俊鎭殑鍩烘湰缁撴瀯銆 + * object锛歄bjectAddress缁撴瀯锛岃〃绀哄璞$殑鍦板潃淇℃伅銆 + */ +static void TrDoDropOpClass(TrObjDesc *baseDesc, ObjectAddress *object) +{ + if (TrNeedLogicDrop(object)) { // 濡傛灉闇瑕侀昏緫鍒犻櫎 + TrRenameCommon(baseDesc, object, OperatorClassRelationId, Natts_pg_opclass, Anum_pg_opclass_opcname, + OpclassOidIndexId, "opclass"); // 閲嶅懡鍚 + } else { + RemoveOpClassById(object->objectId); // 鐩存帴鍒犻櫎鎿嶄綔绗︾被 + } + + return; +} + +/* + * 鍔熻兘锛氭墽琛屽垹闄ゆ搷浣滅鏃忕殑鎿嶄綔銆 + * + * 鍙傛暟鍒楄〃锛 + * baseDesc锛歍rObjDesc缁撴瀯锛岃〃绀哄璞℃弿杩颁俊鎭殑鍩烘湰缁撴瀯銆 + * object锛歄bjectAddress缁撴瀯锛岃〃绀哄璞$殑鍦板潃淇℃伅銆 + */ +static void TrDoDropOpFamily(TrObjDesc *baseDesc, ObjectAddress *object) +{ + if (TrNeedLogicDrop(object)) { // 濡傛灉闇瑕侀昏緫鍒犻櫎 + TrRenameCommon(baseDesc, object, OperatorFamilyRelationId, Natts_pg_opfamily, Anum_pg_opfamily_opfname, + OpfamilyOidIndexId, "opfamily"); // 閲嶅懡鍚 + } else { + RemoveOpFamilyById(object->objectId); // 鐩存帴鍒犻櫎鎿嶄綔绗︽棌 + } + + return; +} + + + +/* + * 鍔熻兘锛氭墽琛屽垹闄ゆ搷浣滅璁块棶鏂规硶椤圭殑鎿嶄綔銆 + * + * 鍙傛暟鍒楄〃锛 + * baseDesc锛歍rObjDesc缁撴瀯锛岃〃绀哄璞℃弿杩颁俊鎭殑鍩烘湰缁撴瀯銆 + * object锛歄bjectAddress缁撴瀯锛岃〃绀哄璞$殑鍦板潃淇℃伅銆 + */ +static void TrDoDropAmOp(TrObjDesc *baseDesc, ObjectAddress *object) +{ + if (TrNeedLogicDrop(object)) { + /* 鏃犻渶鎿嶄綔锛屽洜涓虹郴缁熺洰褰曚腑娌℃湁鍚嶇О灞炴с*/ + } else { + RemoveAmOpEntryById(object->objectId); // 鐩存帴鍒犻櫎鎿嶄綔绗﹁闂柟娉曢」 + } + + return; +} + +/* + * 鍔熻兘锛氭墽琛屽垹闄よ繃绋嬭闂柟娉曢」鐨勬搷浣溿 + * + * 鍙傛暟鍒楄〃锛 + * baseDesc锛歍rObjDesc缁撴瀯锛岃〃绀哄璞℃弿杩颁俊鎭殑鍩烘湰缁撴瀯銆 + * object锛歄bjectAddress缁撴瀯锛岃〃绀哄璞$殑鍦板潃淇℃伅銆 + */ +static void TrDoDropAmProc(TrObjDesc *baseDesc, ObjectAddress *object) +{ + if (TrNeedLogicDrop(object)) { + /* 鏃犻渶鎿嶄綔锛屽洜涓虹郴缁熺洰褰曚腑娌℃湁鍚嶇О灞炴с*/ + } else { + RemoveAmProcEntryById(object->objectId); // 鐩存帴鍒犻櫎杩囩▼璁块棶鏂规硶椤 + } + + return; +} + + +/* + * 鍔熻兘锛氭墽琛屽垹闄ゆā寮忕殑鎿嶄綔銆 + * + * 鍙傛暟鍒楄〃锛 + * baseDesc锛歍rObjDesc缁撴瀯锛岃〃绀哄璞℃弿杩颁俊鎭殑鍩烘湰缁撴瀯銆 + * object锛歄bjectAddress缁撴瀯锛岃〃绀哄璞$殑鍦板潃淇℃伅銆 + */ +static void TrDoDropSchema(TrObjDesc *baseDesc, ObjectAddress *object) +{ + if (TrNeedLogicDrop(object)) { // 濡傛灉闇瑕侀昏緫鍒犻櫎 + TrRenameCommon(baseDesc, object, NamespaceRelationId, Natts_pg_namespace, Anum_pg_namespace_nspname, + NamespaceOidIndexId, "namespace"); // 閲嶅懡鍚 + } else { + RemoveSchemaById(object->objectId); // 鐩存帴鍒犻櫎妯″紡 + } + + return; +} + +/* + * 鍔熻兘锛氭墽琛屽垹闄ゆ枃鏈悳绱㈣В鏋愬櫒鐨勬搷浣溿 + * + * 鍙傛暟鍒楄〃锛 + * baseDesc锛歍rObjDesc缁撴瀯锛岃〃绀哄璞℃弿杩颁俊鎭殑鍩烘湰缁撴瀯銆 + * object锛歄bjectAddress缁撴瀯锛岃〃绀哄璞$殑鍦板潃淇℃伅銆 + */ +static void TrDoDropTSParser(TrObjDesc *baseDesc, ObjectAddress *object) +{ + if (TrNeedLogicDrop(object)) { // 濡傛灉闇瑕侀昏緫鍒犻櫎 + TrRenameCommon(baseDesc, object, TSParserRelationId, Natts_pg_ts_parser, Anum_pg_ts_parser_prsname, + TSParserOidIndexId, "ts parser"); // 閲嶅懡鍚 + } else { + RemoveTSParserById(object->objectId); // 鐩存帴鍒犻櫎鏂囨湰鎼滅储瑙f瀽鍣 + } + + return; +} + +/* + * 鍔熻兘锛氭墽琛屽垹闄ゆ枃鏈悳绱㈠瓧鍏哥殑鎿嶄綔銆 + * + * 鍙傛暟鍒楄〃锛 + * baseDesc锛歍rObjDesc缁撴瀯锛岃〃绀哄璞℃弿杩颁俊鎭殑鍩烘湰缁撴瀯銆 + * object锛歄bjectAddress缁撴瀯锛岃〃绀哄璞$殑鍦板潃淇℃伅銆 + */ +static void TrDoDropTSDictionary(TrObjDesc *baseDesc, ObjectAddress *object) +{ + if (TrNeedLogicDrop(object)) { // 濡傛灉闇瑕侀昏緫鍒犻櫎 + TrRenameCommon(baseDesc, object, TSDictionaryRelationId, Natts_pg_ts_dict, Anum_pg_ts_dict_dictname, + TSDictionaryOidIndexId, "ts dictionary"); // 閲嶅懡鍚 + } else { + RemoveTSDictionaryById(object->objectId); // 鐩存帴鍒犻櫎鏂囨湰鎼滅储瀛楀吀 + } + + return; +} + +/* + * 鍔熻兘锛氭墽琛屽垹闄ゆ枃鏈悳绱㈡ā鏉跨殑鎿嶄綔銆 + * + * 鍙傛暟鍒楄〃锛 + * baseDesc锛歍rObjDesc缁撴瀯锛岃〃绀哄璞℃弿杩颁俊鎭殑鍩烘湰缁撴瀯銆 + * object锛歄bjectAddress缁撴瀯锛岃〃绀哄璞$殑鍦板潃淇℃伅銆 + */ +static void TrDoDropTSTemplate(TrObjDesc *baseDesc, ObjectAddress *object) +{ + if (TrNeedLogicDrop(object)) { // 濡傛灉闇瑕侀昏緫鍒犻櫎 + TrRenameCommon(baseDesc, object, TSTemplateRelationId, Natts_pg_ts_template, Anum_pg_ts_template_tmplname, + TSTemplateOidIndexId, "ts template"); // 閲嶅懡鍚 + } else { + RemoveTSTemplateById(object->objectId); // 鐩存帴鍒犻櫎鏂囨湰鎼滅储妯℃澘 + } + + return; +} + + +/* + * 鍔熻兘锛氭墽琛屽垹闄ゆ枃鏈悳绱㈤厤缃殑鎿嶄綔銆 + * + * 鍙傛暟鍒楄〃锛 + * baseDesc锛歍rObjDesc缁撴瀯锛岃〃绀哄璞℃弿杩颁俊鎭殑鍩烘湰缁撴瀯銆 + * object锛歄bjectAddress缁撴瀯锛岃〃绀哄璞$殑鍦板潃淇℃伅銆 + */ +static void TrDoDropTSConfiguration(TrObjDesc *baseDesc, ObjectAddress *object) +{ + if (TrNeedLogicDrop(object)) { // 濡傛灉闇瑕侀昏緫鍒犻櫎 + TrRenameCommon(baseDesc, object, TSConfigRelationId, Natts_pg_ts_config, Anum_pg_ts_config_cfgname, + TSConfigOidIndexId, "ts configuration"); // 閲嶅懡鍚 + } else { + RemoveTSConfigurationById(object->objectId); // 鐩存帴鍒犻櫎鏂囨湰鎼滅储閰嶇疆 + } + + return; +} + +/* + * 鍔熻兘锛氭墽琛屽垹闄ゅ閮ㄦ暟鎹皝瑁呭櫒鐨勬搷浣溿 + * + * 鍙傛暟鍒楄〃锛 + * baseDesc锛歍rObjDesc缁撴瀯锛岃〃绀哄璞℃弿杩颁俊鎭殑鍩烘湰缁撴瀯銆 + * object锛歄bjectAddress缁撴瀯锛岃〃绀哄璞$殑鍦板潃淇℃伅銆 + */ +static void TrDoDropForeignDataWrapper(TrObjDesc *baseDesc, ObjectAddress *object) +{ + if (TrNeedLogicDrop(object)) { // 濡傛灉闇瑕侀昏緫鍒犻櫎 + TrRenameCommon(baseDesc, object, ForeignDataWrapperRelationId, Natts_pg_foreign_data_wrapper, + Anum_pg_foreign_data_wrapper_fdwname, ForeignDataWrapperOidIndexId, "foreign data wrapper"); // 閲嶅懡鍚 + } else { + RemoveForeignDataWrapperById(object->objectId); // 鐩存帴鍒犻櫎澶栭儴鏁版嵁灏佽鍣 + } + + return; +} + +/* + * 鍔熻兘锛氭墽琛屽垹闄ゅ閮ㄦ湇鍔″櫒鐨勬搷浣溿 + * + * 鍙傛暟鍒楄〃锛 + * baseDesc锛歍rObjDesc缁撴瀯锛岃〃绀哄璞℃弿杩颁俊鎭殑鍩烘湰缁撴瀯銆 + * object锛歄bjectAddress缁撴瀯锛岃〃绀哄璞$殑鍦板潃淇℃伅銆 + */ +static void TrDoDropForeignServer(TrObjDesc *baseDesc, ObjectAddress *object) +{ + if (TrNeedLogicDrop(object)) { // 濡傛灉闇瑕侀昏緫鍒犻櫎 + TrRenameCommon(baseDesc, object, ForeignServerRelationId, Natts_pg_foreign_server, + Anum_pg_foreign_server_srvname, ForeignServerOidIndexId, "foreign server"); // 閲嶅懡鍚 + } else { + RemoveForeignServerById(object->objectId); // 鐩存帴鍒犻櫎澶栭儴鏈嶅姟鍣 + } + + return; +} + +/* + * 鍔熻兘锛氭墽琛屽垹闄ょ敤鎴锋槧灏勭殑鎿嶄綔銆 + * + * 鍙傛暟鍒楄〃锛 + * baseDesc锛歍rObjDesc缁撴瀯锛岃〃绀哄璞℃弿杩颁俊鎭殑鍩烘湰缁撴瀯銆 + * object锛歄bjectAddress缁撴瀯锛岃〃绀哄璞$殑鍦板潃淇℃伅銆 + */ +static void TrDoDropUserMapping(TrObjDesc *baseDesc, ObjectAddress *object) +{ + if (TrNeedLogicDrop(object)) { + /* 鏃犻渶鎿嶄綔锛屽洜涓虹郴缁熺洰褰曚腑娌℃湁鍚嶇О灞炴с*/ + } else { + RemoveUserMappingById(object->objectId); // 鐩存帴鍒犻櫎鐢ㄦ埛鏄犲皠 + } + + return; +} + + + +/* + * 鍔熻兘锛氭墽琛屽垹闄ら粯璁よ闂帶鍒跺垪琛ㄧ殑鎿嶄綔銆 + * + * 鍙傛暟鍒楄〃锛 + * baseDesc锛歍rObjDesc缁撴瀯锛岃〃绀哄璞℃弿杩颁俊鎭殑鍩烘湰缁撴瀯銆 + * object锛歄bjectAddress缁撴瀯锛岃〃绀哄璞$殑鍦板潃淇℃伅銆 + */ +static void TrDoDropDefaultACL(TrObjDesc *baseDesc, ObjectAddress *object) +{ + if (TrNeedLogicDrop(object)) { + /* 鏃犻渶鎿嶄綔锛屽洜涓虹郴缁熺洰褰曚腑娌℃湁鍚嶇О灞炴с*/ + } else { + RemoveDefaultACLById(object->objectId); // 鐩存帴鍒犻櫎榛樿璁块棶鎺у埗鍒楄〃 + } + + return; +} + +/* + * 鍔熻兘锛氭墽琛屽垹闄ゅ垎甯冨紡琛ㄤ俊鎭殑鎿嶄綔銆 + * + * 鍙傛暟鍒楄〃锛 + * baseDesc锛歍rObjDesc缁撴瀯锛岃〃绀哄璞℃弿杩颁俊鎭殑鍩烘湰缁撴瀯銆 + * object锛歄bjectAddress缁撴瀯锛岃〃绀哄璞$殑鍦板潃淇℃伅銆 + */ +static void TrDoDropPgxcClass(TrObjDesc *baseDesc, ObjectAddress *object) +{ + if (TrNeedLogicDrop(object)) { + /* 鏃犻渶鎿嶄綔锛屽洜涓虹郴缁熺洰褰曚腑娌℃湁鍚嶇О灞炴с*/ + } else { + RemovePgxcClass(object->objectId); // 鐩存帴鍒犻櫎鍒嗗竷寮忚〃淇℃伅 + } + + return; +} + +/* + * 鍔熻兘锛氭墽琛屽垹闄ゆ墿灞曠殑鎿嶄綔銆 + * + * 鍙傛暟鍒楄〃锛 + * baseDesc锛歍rObjDesc缁撴瀯锛岃〃绀哄璞℃弿杩颁俊鎭殑鍩烘湰缁撴瀯銆 + * object锛歄bjectAddress缁撴瀯锛岃〃绀哄璞$殑鍦板潃淇℃伅銆 + */ +static void TrDoDropExtension(TrObjDesc *baseDesc, ObjectAddress *object) +{ + if (TrNeedLogicDrop(object)) { // 濡傛灉闇瑕侀昏緫鍒犻櫎 + TrRenameCommon(baseDesc, object, ExtensionRelationId, Natts_pg_extension, Anum_pg_extension_extname, + ExtensionOidIndexId, "extension"); // 閲嶅懡鍚 + } else { + RemoveExtensionById(object->objectId); // 鐩存帴鍒犻櫎鎵╁睍 + } + + return; +} + +/* + * 鍔熻兘锛氭墽琛屽垹闄ゆ墿灞曟暟鎹簮鐨勬搷浣溿 + * + * 鍙傛暟鍒楄〃锛 + * baseDesc锛歍rObjDesc缁撴瀯锛岃〃绀哄璞℃弿杩颁俊鎭殑鍩烘湰缁撴瀯銆 + * object锛歄bjectAddress缁撴瀯锛岃〃绀哄璞$殑鍦板潃淇℃伅銆 + */ +static void TrDoDropDataSource(TrObjDesc *baseDesc, ObjectAddress *object) +{ + if (TrNeedLogicDrop(object)) { // 濡傛灉闇瑕侀昏緫鍒犻櫎 + TrRenameCommon(baseDesc, object, DataSourceRelationId, Natts_pg_extension_data_source, + Anum_pg_extension_data_source_srcname, DataSourceOidIndexId, "extension data source"); // 閲嶅懡鍚 + } else { + RemoveDataSourceById(object->objectId); // 鐩存帴鍒犻櫎鎵╁睍鏁版嵁婧 + } + + return; +} + + +/* + * 鍔熻兘锛氭墽琛屽垹闄ょ洰褰曠殑鎿嶄綔銆 + * + * 鍙傛暟鍒楄〃锛 + * baseDesc锛歍rObjDesc缁撴瀯锛岃〃绀哄璞℃弿杩颁俊鎭殑鍩烘湰缁撴瀯銆 + * object锛歄bjectAddress缁撴瀯锛岃〃绀哄璞$殑鍦板潃淇℃伅銆 + */ +static void TrDoDropDirectory(TrObjDesc *baseDesc, ObjectAddress *object) +{ + if (TrNeedLogicDrop(object)) { // 濡傛灉闇瑕侀昏緫鍒犻櫎 + TrRenameCommon(baseDesc, object, PgDirectoryRelationId, Natts_pg_directory, Anum_pg_directory_directory_name, + PgDirectoryOidIndexId, "directory"); // 閲嶅懡鍚 + } else { + RemoveDirectoryById(object->objectId); // 鐩存帴鍒犻櫎鐩綍 + } + + return; +} + +/* + * 鍔熻兘锛氭墽琛屽垹闄よ绾у畨鍏ㄧ瓥鐣ョ殑鎿嶄綔銆 + * + * 鍙傛暟鍒楄〃锛 + * baseDesc锛歍rObjDesc缁撴瀯锛岃〃绀哄璞℃弿杩颁俊鎭殑鍩烘湰缁撴瀯銆 + * object锛歄bjectAddress缁撴瀯锛岃〃绀哄璞$殑鍦板潃淇℃伅銆 + */ +static void TrDoDropRlsPolicy(TrObjDesc *baseDesc, ObjectAddress *object) +{ + if (TrNeedLogicDrop(object)) { // 濡傛灉闇瑕侀昏緫鍒犻櫎 + TrRenameCommon(baseDesc, object, RlsPolicyRelationId, Natts_pg_rlspolicy, Anum_pg_rlspolicy_polname, + PgRlspolicyOidIndex, "rlspolicy"); // 閲嶅懡鍚 + } else { + RemoveRlsPolicyById(object->objectId); // 鐩存帴鍒犻櫎琛岀骇瀹夊叏绛栫暐 + } + + return; +} + +/* + * 鍔熻兘锛氭墽琛屽垹闄や綔涓氱殑鎿嶄綔銆 + * + * 鍙傛暟鍒楄〃锛 + * baseDesc锛歍rObjDesc缁撴瀯锛岃〃绀哄璞℃弿杩颁俊鎭殑鍩烘湰缁撴瀯銆 + * object锛歄bjectAddress缁撴瀯锛岃〃绀哄璞$殑鍦板潃淇℃伅銆 + */ +static void TrDoDropJob(TrObjDesc *baseDesc, ObjectAddress *object) +{ + if (TrNeedLogicDrop(object)) { + /* 鏃犻渶鎿嶄綔锛屽洜涓虹郴缁熺洰褰曚腑娌℃湁鍚嶇О灞炴с*/ + } else { + RemoveJobById(object->objectId); // 鐩存帴鍒犻櫎浣滀笟 + } + + return; +} + +/* + * 鍔熻兘锛氭墽琛屽垹闄ゅ悓涔夎瘝鐨勬搷浣溿 + * + * 鍙傛暟鍒楄〃锛 + * baseDesc锛歍rObjDesc缁撴瀯锛岃〃绀哄璞℃弿杩颁俊鎭殑鍩烘湰缁撴瀯銆 + * object锛歄bjectAddress缁撴瀯锛岃〃绀哄璞$殑鍦板潃淇℃伅銆 + */ +static void TrDoDropSynonym(TrObjDesc *baseDesc, ObjectAddress *object) +{ + if (TrNeedLogicDrop(object)) { // 濡傛灉闇瑕侀昏緫鍒犻櫎 + TrRenameCommon(baseDesc, object, PgSynonymRelationId, Natts_pg_synonym, Anum_pg_synonym_synname, + SynonymOidIndexId, "synonym"); // 閲嶅懡鍚 + } else { + RemoveSynonymById(object->objectId); // 鐩存帴鍒犻櫎鍚屼箟璇 + } + + return; +} + + /* * doDeletion: delete a single object * return false if logic deleted, * return true if physical deleted, */ +/* + * 鍔熻兘锛氭墽琛屽垹闄ゅ璞$殑鎿嶄綔锛屾牴鎹璞$殑绫诲埆閫夋嫨鐩稿簲鐨勫垹闄ゅ嚱鏁般 + * + * 鍙傛暟鍒楄〃锛 + * baseDesc锛歍rObjDesc缁撴瀯锛岃〃绀哄璞℃弿杩颁俊鎭殑鍩烘湰缁撴瀯銆 + * object锛歄bjectAddress缁撴瀯锛岃〃绀哄璞$殑鍦板潃淇℃伅銆 + */ static void TrDoDrop(TrObjDesc *baseDesc, ObjectAddress *object) { switch (getObjectClass(object)) { case OCLASS_CLASS: { char relKind = get_rel_relkind(object->objectId); if (relKind == RELKIND_INDEX) { - TrDoDropIndex(baseDesc, object); + TrDoDropIndex(baseDesc, object);// 鍒犻櫎绱㈠紩 } else { /* * We use a unified entry for others: @@ -749,93 +1049,93 @@ static void TrDoDrop(TrObjDesc *baseDesc, ObjectAddress *object) * RELKIND_TOASTVALUE, RELKIND_VIEW, * RELKIND_COMPOSITE_TYPE, RELKIND_FOREIGN_TABLE */ - TrDoDropTable(baseDesc, object, relKind); + TrDoDropTable(baseDesc, object, relKind);// 鍒犻櫎琛 } break; } case OCLASS_TYPE: - TrDoDropType(baseDesc, object); + TrDoDropType(baseDesc, object); // 鍒犻櫎绫诲瀷 break; case OCLASS_CONSTRAINT: - TrDoDropConstraint(baseDesc, object); + TrDoDropConstraint(baseDesc, object); // 鍒犻櫎绾︽潫 break; case OCLASS_TRIGGER: - TrDoDropTrigger(baseDesc, object); + TrDoDropTrigger(baseDesc, object); // 鍒犻櫎瑙﹀彂鍣 break; case OCLASS_REWRITE: - TrDoDropRewrite(baseDesc, object); + TrDoDropRewrite(baseDesc, object); // 鍒犻櫎瑙勫垯 break; case OCLASS_DEFAULT: - TrDoDropAttrdef(baseDesc, object); + TrDoDropAttrdef(baseDesc, object); // 鍒犻櫎榛樿鍊 break; case OCLASS_PROC: - TrDoDropProc(baseDesc, object); + TrDoDropProc(baseDesc, object); // 鍒犻櫎鍑芥暟 break; case OCLASS_CAST: - TrDoDropCast(baseDesc, object); + TrDoDropCast(baseDesc, object); // 鍒犻櫎杞崲 break; case OCLASS_COLLATION: - TrDoDropCollation(baseDesc, object); + TrDoDropCollation(baseDesc, object); // 鍒犻櫎鎺掑簭瑙勫垯 break; case OCLASS_CONVERSION: - TrDoDropConversion(baseDesc, object); + TrDoDropConversion(baseDesc, object); // 鍒犻櫎杞崲瑙勫垯 break; case OCLASS_LANGUAGE: - TrDoDropProceduralLanguage(baseDesc, object); + TrDoDropProceduralLanguage(baseDesc, object); // 鍒犻櫎杩囩▼鍖栬瑷 break; case OCLASS_LARGEOBJECT: - TrDoDropLargeObject(baseDesc, object); + TrDoDropLargeObject(baseDesc, object); // 鍒犻櫎澶у璞 break; case OCLASS_OPERATOR: - TrDoDropOperator(baseDesc, object); + TrDoDropOperator(baseDesc, object); // 鍒犻櫎鎿嶄綔绗 break; case OCLASS_OPCLASS: - TrDoDropOpClass(baseDesc, object); + TrDoDropOpClass(baseDesc, object); // 鍒犻櫎鎿嶄綔绗︾被 break; case OCLASS_OPFAMILY: - TrDoDropOpFamily(baseDesc, object); + TrDoDropOpFamily(baseDesc, object); // 鍒犻櫎鎿嶄綔绗︽棌 break; case OCLASS_AMOP: - TrDoDropAmOp(baseDesc, object); + TrDoDropAmOp(baseDesc, object); // 鍒犻櫎鎿嶄綔绗︽槧灏 break; case OCLASS_AMPROC: - TrDoDropAmProc(baseDesc, object); + TrDoDropAmProc(baseDesc, object); // 鍒犻櫎鎿嶄綔绗﹀鐞嗗嚱鏁 break; case OCLASS_SCHEMA: - TrDoDropSchema(baseDesc, object); + TrDoDropSchema(baseDesc, object); // 鍒犻櫎妯″紡 break; case OCLASS_TSPARSER: - TrDoDropTSParser(baseDesc, object); + TrDoDropTSParser(baseDesc, object); // 鍒犻櫎鏂囨湰鎼滅储瑙f瀽鍣 break; case OCLASS_TSDICT: - TrDoDropTSDictionary(baseDesc, object); + TrDoDropTSDictionary(baseDesc, object); // 鍒犻櫎鏂囨湰鎼滅储瀛楀吀 break; case OCLASS_TSTEMPLATE: - TrDoDropTSTemplate(baseDesc, object); + TrDoDropTSTemplate(baseDesc, object); // 鍒犻櫎鏂囨湰鎼滅储妯℃澘 break; case OCLASS_TSCONFIG: - TrDoDropTSConfiguration(baseDesc, object); + TrDoDropTSConfiguration(baseDesc, object); // 鍒犻櫎鏂囨湰鎼滅储閰嶇疆 break; /* @@ -844,48 +1144,48 @@ static void TrDoDrop(TrObjDesc *baseDesc, ObjectAddress *object) */ case OCLASS_FDW: - TrDoDropForeignDataWrapper(baseDesc, object); + TrDoDropForeignDataWrapper(baseDesc, object); // 鍒犻櫎澶栭儴鏁版嵁灏佽鍣 break; case OCLASS_FOREIGN_SERVER: - TrDoDropForeignServer(baseDesc, object); + TrDoDropForeignServer(baseDesc, object); // 鍒犻櫎澶栭儴鏈嶅姟鍣 break; case OCLASS_USER_MAPPING: - TrDoDropUserMapping(baseDesc, object); + TrDoDropUserMapping(baseDesc, object); // 鍒犻櫎鐢ㄦ埛鏄犲皠 break; case OCLASS_DEFACL: - TrDoDropDefaultACL(baseDesc, object); + TrDoDropDefaultACL(baseDesc, object); // 鍒犻櫎榛樿璁块棶鎺у埗 break; case OCLASS_PGXC_CLASS: - TrDoDropPgxcClass(baseDesc, object); + TrDoDropPgxcClass(baseDesc, object); // 鍒犻櫎鍒嗗竷寮忕被 break; case OCLASS_EXTENSION: - TrDoDropExtension(baseDesc, object); + TrDoDropExtension(baseDesc, object); // 鍒犻櫎鎵╁睍 break; case OCLASS_DATA_SOURCE: - TrDoDropDataSource(baseDesc, object); + TrDoDropDataSource(baseDesc, object); // 鍒犻櫎鏁版嵁婧 break; case OCLASS_DIRECTORY: - TrDoDropDirectory(baseDesc, object); + TrDoDropDirectory(baseDesc, object); // 鍒犻櫎鐩綍 break; case OCLASS_RLSPOLICY: - TrDoDropRlsPolicy(baseDesc, object); + TrDoDropRlsPolicy(baseDesc, object); // 鍒犻櫎琛岀骇瀹夊叏绛栫暐 break; case OCLASS_PG_JOB: if ((IS_PGXC_COORDINATOR && !IsConnFromCoord()) || (g_instance.role == VSINGLENODE)) - TrDoDropJob(baseDesc, object); + TrDoDropJob(baseDesc, object); // 鍒犻櫎浣滀笟 break; case OCLASS_SYNONYM: - TrDoDropSynonym(baseDesc, object); + TrDoDropSynonym(baseDesc, object); // 鍒犻櫎鍚屼箟璇 break; default: @@ -902,6 +1202,14 @@ static void TrDoDrop(TrObjDesc *baseDesc, ObjectAddress *object) * * *depRel is the already-open pg_depend relation. */ +/* + * 鍔熻兘锛氬垹闄や竴涓璞★紝鍖呮嫭鍏朵緷璧栧叧绯荤瓑鎿嶄綔銆 + * + * 鍙傛暟鍒楄〃锛 + * baseDesc锛歍rObjDesc缁撴瀯锛岃〃绀哄璞℃弿杩颁俊鎭殑鍩烘湰缁撴瀯銆 + * object锛歄bjectAddress缁撴瀯锛岃〃绀哄璞$殑鍦板潃淇℃伅銆 + * depRel锛歊elation鎸囬拡锛岃〃绀轰緷璧栧叧绯荤殑绯荤粺琛ㄣ + */ static void TrDropOneObject(TrObjDesc *baseDesc, ObjectAddress *object, Relation *depRel) { ScanKeyData key[3]; @@ -998,6 +1306,13 @@ static void TrDropOneObject(TrObjDesc *baseDesc, ObjectAddress *object, Relation */ } +/* + * 鍔熻兘锛氬垽鏂粰瀹氱殑瀵硅薄鍦板潃鏄惁鍦ㄥ璞″湴鍧鍒楄〃涓 + * + * 鍙傛暟鍒楄〃锛 + * targetObjects锛歄bjectAddresses缁撴瀯鎸囬拡锛岃〃绀虹洰鏍囧璞″湴鍧鍒楄〃銆 + * thisobj锛歄bjectAddress缁撴瀯锛岃〃绀哄綋鍓嶅璞$殑鍦板潃銆 + */ static bool TrObjIsInList(const ObjectAddresses *targetObjects, const ObjectAddress *thisobj) { ObjectAddress *item = NULL; @@ -1011,6 +1326,13 @@ static bool TrObjIsInList(const ObjectAddresses *targetObjects, const ObjectAddr return false; } +/* + * 鍔熻兘锛氬湪鐩爣瀵硅薄鍦板潃鍒楄〃涓煡鎵剧粰瀹氬璞$殑绱㈠紩銆 + * + * 鍙傛暟鍒楄〃锛 + * targetObjects锛歄bjectAddresses缁撴瀯鎸囬拡锛岃〃绀虹洰鏍囧璞″湴鍧鍒楄〃銆 + * item锛歄bjectAddress缁撴瀯锛岃〃绀哄緟鏌ユ壘鐨勫璞″湴鍧銆 + */ static ObjectAddress *TrFindIdxInTarget(ObjectAddresses *targetObjects, ObjectAddress *item) { ObjectAddress *thisobj = NULL; @@ -1025,41 +1347,61 @@ static ObjectAddress *TrFindIdxInTarget(ObjectAddresses *targetObjects, ObjectAd return NULL; } + /* * output: refthisobjs */ +/* + * 鍔熻兘锛氭煡鎵炬墍鏈夊紩鐢ㄧ粰瀹氬璞$殑渚濊禆瀵硅薄 + * + * 鍙傛暟鍒楄〃锛 + * depRel锛氫緷璧栧叧绯荤殑绯荤粺鐩綍琛ㄧ殑鍏崇郴鎻忚堪绗 + * refobj锛氱粰瀹氬璞$殑鍦板潃 + * refthisobjs锛氬瓨鍌ㄤ緷璧栧璞″湴鍧鐨勫璞″垪琛 + */ static void TrFindAllSubObjs(Relation depRel, const ObjectAddress *refobj, ObjectAddresses *refthisobjs) { SysScanDesc sd; HeapTuple tuple; ScanKeyData key[3]; int nkeys; - + // 鍒濆鍖栨壂鎻忛敭鏁扮粍锛岃缃潯浠剁敤浜庡尮閰嶅紩鐢ㄥ璞$殑绫诲拰ID ScanKeyInit(&key[0], Anum_pg_depend_refclassid, BTEqualStrategyNumber, F_OIDEQ, ObjectIdGetDatum(refobj->classId)); ScanKeyInit(&key[1], Anum_pg_depend_refobjid, BTEqualStrategyNumber, F_OIDEQ, ObjectIdGetDatum(refobj->objectId)); nkeys = 2; + // 濡傛灉寮曠敤瀵硅薄鏈夊瓙ID锛屽垯璁剧疆绗笁涓潯浠 if (refobj->objectSubId != 0) { ScanKeyInit(&key[2], Anum_pg_depend_refobjsubid, BTEqualStrategyNumber, F_INT4EQ, Int32GetDatum(refobj->objectSubId)); nkeys = 3; } + // 浣跨敤鏉′欢鍒濆鍖栨壂鎻忓櫒 sd = systable_beginscan(depRel, DependReferenceIndexId, true, NULL, nkeys, key); + // 寰幆閬嶅巻婊¤冻鏉′欢鐨勫厓缁 while (HeapTupleIsValid(tuple = systable_getnext(sd))) { + // 鑾峰彇鍏冪粍涓殑Form_pg_depend鏁版嵁 Form_pg_depend depForm = (Form_pg_depend)GETSTRUCT(tuple); /* add the refs to list */ add_object_address_ext(depForm->classid, depForm->objid, depForm->objsubid, depForm->deptype, refthisobjs); } - systable_endscan(sd); + systable_endscan(sd);// 缁撴潫鎵弿 return; } - +/* + * 鍔熻兘锛氭爣璁扮墿鐞嗗垹闄ゆā寮忎笅鐨勬墍鏈夊瓙瀵硅薄锛屽皢鍏舵坊鍔犲埌寰呭垹闄ゅ垪琛ㄤ腑 + * + * 鍙傛暟鍒楄〃锛 + * depRel锛氫緷璧栧叧绯荤殑绯荤粺鐩綍琛ㄧ殑鍏崇郴鎻忚堪绗 + * targetObjects锛氬緟鍒犻櫎瀵硅薄鍒楄〃 + * thisobj锛氬綋鍓嶅璞$殑鍦板潃 + */ static void TrTagPhyDeleteSubObjs(Relation depRel, ObjectAddresses *targetObjects, ObjectAddress *thisobj) { ObjectAddress *item = NULL; - + // 鍒涘缓涓涓敤浜庡瓨鍌ㄤ緷璧栧璞″湴鍧鐨勫璞″垪琛 ObjectAddresses *refthisobjs = new_object_addresses(); /* Tag this obj RB_DROP_MODE_PHYSICAL */ @@ -1067,7 +1409,7 @@ static void TrTagPhyDeleteSubObjs(Relation depRel, ObjectAddresses *targetObject /* Find all sub objs refered to this obj */ TrFindAllSubObjs(depRel, thisobj, refthisobjs); - + // 閬嶅巻寮曠敤瀵硅薄鍒楄〃锛屽皢婊¤冻鏉′欢鐨勫璞℃爣璁颁负鐗╃悊鍒犻櫎妯″紡 for (int i = 0; i < refthisobjs->numrefs; i++) { item = refthisobjs->refs + i; @@ -1076,16 +1418,25 @@ static void TrTagPhyDeleteSubObjs(Relation depRel, ObjectAddresses *targetObject if (item == NULL || item->rbDropMode == RB_DROP_MODE_PHYSICAL) { continue; } + // 閫掑綊鏍囪婊¤冻鏉′欢鐨勫瓙瀵硅薄 TrTagPhyDeleteSubObjs(depRel, targetObjects, item); } - + // 閲婃斁鐢ㄤ簬瀛樺偍渚濊禆瀵硅薄鍦板潃鐨勫璞″垪琛 free_object_addresses(refthisobjs); return; } - +/* + * 鍔熻兘锛氭鏌ユ槸鍚﹂渶瑕佽繘琛岀墿鐞嗗垹闄ゆ搷浣 + * + * 鍙傛暟鍒楄〃锛 + * depRel锛氫緷璧栧叧绯荤殑绯荤粺鐩綍琛ㄧ殑鍏崇郴鎻忚堪绗 + * targetObjects锛氬緟鍒犻櫎瀵硅薄鍒楄〃 + * thisobj锛氬綋鍓嶅璞$殑鍦板潃 + */ static bool TrNeedPhyDelete(Relation depRel, ObjectAddresses *targetObjects, ObjectAddress *thisobj) { ObjectAddress *item = NULL; + // 鍒涘缓涓涓敤浜庡瓨鍌ㄥ紩鐢ㄥ璞″湴鍧鐨勫璞″垪琛 ObjectAddresses *refobjs = new_object_addresses(); bool result = false; @@ -1114,14 +1465,21 @@ static bool TrNeedPhyDelete(Relation depRel, ObjectAddresses *targetObjects, Obj if (item->rbDropMode == RB_DROP_MODE_PHYSICAL) { continue; } + // 鏍囪琚紩鐢ㄥ璞″強鍏跺瓙瀵硅薄涓虹墿鐞嗗垹闄ゆā寮 TrTagPhyDeleteSubObjs(depRel, targetObjects, item); } } - + // 閲婃斁鐢ㄤ簬瀛樺偍寮曠敤瀵硅薄鍦板潃鐨勫璞″垪琛 free_object_addresses(refobjs); return result; } - +/* + * 鍔熻兘閲嶇疆寰呭垹闄ゅ璞$殑鍒犻櫎妯″紡 + * + * 鍙傛暟鍒楄〃锛 + * targetObjects锛氬緟鍒犻櫎瀵硅薄鍒楄〃 + * baseObj锛氬熀纭瀵硅薄鐨勫湴鍧 + */ static void TrResetDropMode(const ObjectAddresses *targetObjects, const ObjectAddress *baseObj) { ObjectAddress *thisobj = NULL; @@ -1129,28 +1487,46 @@ static void TrResetDropMode(const ObjectAddresses *targetObjects, const ObjectAd for (int i = 0; i < targetObjects->numrefs; i++) { thisobj = targetObjects->refs + i; if (TrObjIsEqual(thisobj, baseObj)) { + // 灏嗗熀纭瀵硅薄鐨勫垹闄ゆā寮忛噸缃负閫昏緫鍒犻櫎 thisobj->rbDropMode = RB_DROP_MODE_LOGIC; continue; } + // 灏嗗叾浠栧璞$殑鍒犻櫎妯″紡閲嶇疆涓烘棤鏁 thisobj->rbDropMode = RB_DROP_MODE_INVALID; } return; } + +/* + * 鍔熻兘锛氭爣璁颁緷璧栧璞$殑鍒犻櫎妯″紡 + * + * 鍙傛暟鍒楄〃锛 + * depRel锛氫緷璧栧叧绯诲叧绯 + * targetObjects锛氬緟鍒犻櫎瀵硅薄鍒楄〃 + * baseObj锛氬熀纭瀵硅薄鐨勫湴鍧 + */ static void TrTagDependentObjects(Relation depRel, ObjectAddresses *targetObjects, const ObjectAddress *baseObj) { ObjectAddress *thisobj = NULL; + // 閲嶇疆寰呭垹闄ゅ璞$殑鍒犻櫎妯″紡 TrResetDropMode(targetObjects, baseObj); + for (int i = 0; i < targetObjects->numrefs; i++) { thisobj = targetObjects->refs + i; + + // 濡傛灉瀵硅薄鐨勫垹闄ゆā寮忓凡缁忚缃紝鍒欒烦杩 if (TrDropModeIsAlreadySet(thisobj)) { continue; } + // 濡傛灉闇瑕佽繘琛岀墿鐞嗗垹闄 if (TrNeedPhyDelete(depRel, targetObjects, thisobj)) { + // 鏍囪鎵鏈変緷璧栦簬姝ゅ璞$殑瀛愬璞′负鐗╃悊鍒犻櫎 TrTagPhyDeleteSubObjs(depRel, targetObjects, thisobj); } else { + // 鍚﹀垯灏嗗璞$殑鍒犻櫎妯″紡璁剧疆涓洪昏緫鍒犻櫎 thisobj->rbDropMode = RB_DROP_MODE_LOGIC; } } @@ -1158,39 +1534,57 @@ static void TrTagDependentObjects(Relation depRel, ObjectAddresses *targetObject return; } + +/* + * 鍔熻兘锛氭鏌ユ槸鍚﹀彲浠ヨ繘琛孯ecyclebin-based-Drop鎿嶄綔 + * + * 鍙傛暟鍒楄〃锛 + * stmt锛氬垹闄よ鍙 + * objects锛氬緟鍒犻櫎瀵硅薄鍒楄〃 + */ bool TrCheckRecyclebinDrop(const DropStmt *stmt, ObjectAddresses *objects) { Relation depRel; bool rbDrop = false; - /* No work if no objects... */ + /* 濡傛灉娌℃湁寰呭垹闄ゅ璞★紝鍒欎笉闇瑕佹搷浣 */ if (objects->numrefs <= 0) return false; + /* 妫鏌ユ槸鍚︽弧瓒砇ecyclebin-based-Drop鏉′欢 */ if (/* - * Disable Recyclebin-based-Drop when target object is not OBJECT_TABLE, or + * 褰撶洰鏍囧璞′笉鏄疧BJECT_TABLE鏃讹紝鎴栬 */ stmt->removeType != OBJECT_TABLE || - /* in concurrent drop mode, or */ + /* 鍦ㄥ苟鍙戝垹闄ゆā寮忎笅锛屾垨鑰 */ stmt->concurrent || - /* with purge option, or */ + /* 浣跨敤浜唒urge閫夐」锛屾垨鑰 */ stmt->purge || - /* multi objects drop. */ + /* 鍒犻櫎澶氫釜瀵硅薄鏃讹紝涓嶆敮鎸丷ecyclebin-based-Drop銆 */ list_length(stmt->objects) != 1) { return false; } + /* 濡傛灉涓嶉渶瑕丷ecyclebin鍔熻兘锛屽垯涓嶆敮鎸丷ecyclebin-based-Drop */ if (!NeedTrComm(objects->refs->objectId)) { return false; } + /* 鎵撳紑渚濊禆鍏崇郴鍏崇郴琛紝杩涜妫鏌 */ depRel = heap_open(DependRelationId, AccessShareLock); rbDrop = !TrNeedPhyDelete(depRel, objects, &objects->refs[0]); heap_close(depRel, AccessShareLock); return rbDrop; } - +/* + * 鍔熻兘锛氭墽琛屽垹闄ゆ搷浣滐紝鏀寔閫昏緫鍒犻櫎鍜岀墿鐞嗗垹闄 + * + * 鍙傛暟鍒楄〃锛 + * drop锛氬垹闄よ鍙 + * objects锛氬緟鍒犻櫎瀵硅薄鍒楄〃 + * behavior锛氬垹闄よ涓 + */ void TrDrop(const DropStmt* drop, const ObjectAddresses *objects, DropBehavior behavior) { Relation depRel; @@ -1267,61 +1661,1805 @@ void TrDrop(const DropStmt* drop, const ObjectAddresses *objects, DropBehavior b free_object_addresses(targetObjects); heap_close(depRel, RowExclusiveLock); } - +/* + * 鍔熻兘锛氭墽琛屽洖鏀剁珯涓殑瀵硅薄娓呴櫎鎿嶄綔 + * + * 鍙傛暟鍒楄〃锛 + * desc锛氬璞℃弿杩颁俊鎭 + */ void TrDoPurgeObjectDrop(TrObjDesc *desc) { - ObjectAddresses *objects; - ObjectAddress obj; + ObjectAddresses *objects; // 瀛樺偍瀵硅薄鍦板潃鐨勭粨鏋勪綋锛岀敤浜庢壒閲忓垹闄 + ObjectAddress obj; // 瀵硅薄鍦板潃缁撴瀯浣擄紝鐢ㄤ簬琛ㄧず瀵硅薄鐨勫湴鍧 - objects = new_object_addresses(); + objects = new_object_addresses(); // 鍒涘缓瀵硅薄鍦板潃缁撴瀯浣撶殑瀹炰緥 - obj.classId = RelationRelationId; - obj.objectId = desc->relid; - obj.objectSubId = 0; - add_exact_object_address(&obj, objects); + obj.classId = RelationRelationId; // 璁剧疆瀵硅薄鍦板潃鐨勭被鍒獻D涓篟elationRelationId锛岃〃绀哄叧绯诲璞 + obj.objectId = desc->relid; // 璁剧疆瀵硅薄鍦板潃鐨勫璞D涓鸿鍒犻櫎瀵硅薄鐨勫叧绯籌D + obj.objectSubId = 0; // 璁剧疆瀵硅薄鍦板潃鐨勫瓙瀵硅薄ID涓0锛岃〃绀轰富瀵硅薄 + add_exact_object_address(&obj, objects); // 鍚戝璞″湴鍧缁撴瀯浣撴坊鍔犲璞″湴鍧 - performMultipleDeletions(objects, DROP_CASCADE, PERFORM_DELETION_INVALID); + performMultipleDeletions(objects, DROP_CASCADE, PERFORM_DELETION_INVALID); // 鎵ц澶氫釜瀵硅薄鐨勭骇鑱斿垹闄ゆ搷浣 - if (desc->type == RB_OBJ_TABLE) { - TrDeleteBaseid(desc->baseid); + if (desc->type == RB_OBJ_TABLE) { // 濡傛灉琚垹闄ゅ璞℃槸琛ㄥ璞 + TrDeleteBaseid(desc->baseid); // 鍒犻櫎鍩虹ID } else { /* RB_OBJ_INDEX */ - TrDeleteId(desc->id); + TrDeleteId(desc->id); // 鍒犻櫎ID } - free_object_addresses(objects); + free_object_addresses(objects); // 閲婃斁瀵硅薄鍦板潃缁撴瀯浣撶殑鍐呭瓨 return; } /* TIMECAPSULE TABLE { table_name } TO BEFORE DROP [RENAME TO new_tablename] */ +/* + * 鍔熻兘锛氳繕鍘熷洖鏀剁珯涓鍒犻櫎鐨勫璞 + * + * 鍙傛暟鍒楄〃锛 + * stmt锛氭椂闂磋兌鍥婅鍙 + */ void TrRestoreDrop(const TimeCapsuleStmt *stmt) { - TrObjDesc desc; - ObjectAddress obj; - Relation rel; + TrObjDesc desc; // 瀵硅薄鎻忚堪缁撴瀯浣擄紝鐢ㄤ簬淇濆瓨琚繕鍘熷璞$殑淇℃伅 + ObjectAddress obj; // 瀵硅薄鍦板潃缁撴瀯浣擄紝鐢ㄤ簬琛ㄧず瀵硅薄鐨勫湴鍧 + Relation rel; // 鏁版嵁搴撳叧绯诲璞★紝鐢ㄤ簬鎿嶄綔鏁版嵁搴撳叧绯 - desc.relid = 0; - TrOperFetch(stmt->relation, RB_OBJ_TABLE, &desc, RB_OPER_RESTORE_DROP); + desc.relid = 0; // 鍒濆鍖栬杩樺師瀵硅薄鐨勫叧绯籌D涓0 + TrOperFetch(stmt->relation, RB_OBJ_TABLE, &desc, RB_OPER_RESTORE_DROP); // 鑾峰彇琚繕鍘熷璞$殑鎻忚堪淇℃伅 if (desc.relid != 0 && (desc.type == RB_OBJ_TABLE)) { - stmt->relation->relname = desc.name; - rel = heap_openrv(stmt->relation, AccessExclusiveLock); + stmt->relation->relname = desc.name; // 灏嗚杩樺師瀵硅薄鐨勫悕绉拌祴鍊肩粰鏃堕棿鑳跺泭璇彞鐨勫叧绯诲悕绉 + rel = heap_openrv(stmt->relation, AccessExclusiveLock); // 鎵撳紑鍏崇郴瀵硅薄浠ヨ繘琛屾搷浣 if (rel->rd_tam_type == TAM_HEAP) { - heap_close(rel, NoLock); - elog(ERROR, "timecapsule does not support astore yet"); + heap_close(rel, NoLock); // 鍏抽棴鍏崇郴瀵硅薄 + elog(ERROR, "timecapsule does not support astore yet"); // 鎶ラ敊锛屾殏涓嶆敮鎸佽繕鍘熷瓨鍌ㄥ尯瀵硅薄 return; } - heap_close(rel, NoLock); + heap_close(rel, NoLock); // 鍏抽棴鍏崇郴瀵硅薄 } - desc.authid = GetUserId(); - TrOperPrep(&desc, RB_OPER_RESTORE_DROP); + desc.authid = GetUserId(); // 鑾峰彇褰撳墠鐢ㄦ埛鐨勬潈闄怚D + TrOperPrep(&desc, RB_OPER_RESTORE_DROP); // 鍑嗗杩樺師鎿嶄綔锛屾洿鏂版弿杩颁俊鎭 - obj.classId = RelationRelationId; - obj.objectId = desc.relid; - obj.objectSubId = 0; + obj.classId = RelationRelationId; // 璁剧疆瀵硅薄鍦板潃鐨勭被鍒獻D涓篟elationRelationId锛岃〃绀哄叧绯诲璞 + obj.objectId = desc.relid; // 璁剧疆瀵硅薄鍦板潃鐨勫璞D涓鸿杩樺師瀵硅薄鐨勫叧绯籌D + obj.objectSubId = 0; // 璁剧疆瀵硅薄鍦板潃鐨勫瓙瀵硅薄ID涓0锛岃〃绀轰富瀵硅薄 - TrRenameClass(&desc, &obj, stmt->new_relname ? stmt->new_relname : desc.originname); + TrRenameClass(&desc, &obj, stmt->new_relname ? stmt->new_relname : desc.originname); // 閲嶅懡鍚嶅璞 - TrDeleteBaseid(desc.baseid); + TrDeleteBaseid(desc.baseid); // 鍒犻櫎鍩虹ID锛屽嵆灏嗗璞′粠鍥炴敹绔欑Щ鍑 return; } +======= +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2020-2020. All rights reserved. + * + * openGauss is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * + * http://license.coscl.org.cn/MulanPSL2 + * + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + * --------------------------------------------------------------------------------------- + * + * tcap_drop.cpp + * Routines to support Timecapsule `Recyclebin-based query, restore`. + * We use Tr prefix to indicate it in following coding. + * + * IDENTIFICATION + * src/gausskernel/storage/tcap/tcap_drop.cpp + * + * --------------------------------------------------------------------------------------- + */ + +#include "postgres.h" + +#include "pgstat.h" +#include "access/reloptions.h" +#include "access/sysattr.h" +#include "access/xlog.h" +#include "catalog/dependency.h" +#include "catalog/heap.h" +#include "catalog/index.h" +#include "catalog/indexing.h" +#include "catalog/objectaccess.h" +#include "catalog/pg_collation_fn.h" +#include "catalog/pg_collation.h" +#include "catalog/pg_constraint.h" +#include "catalog/pg_conversion_fn.h" +#include "catalog/pg_conversion.h" +#include "catalog/pg_depend.h" +#include "catalog/pg_extension_data_source.h" +#include "catalog/pg_extension.h" +#include "catalog/pg_foreign_data_wrapper.h" +#include "catalog/pg_foreign_server.h" +#include "catalog/pg_job.h" +#include "catalog/pg_language.h" +#include "catalog/pg_largeobject.h" +#include "catalog/pg_object.h" +#include "catalog/pg_opclass.h" +#include "catalog/pg_operator.h" +#include "catalog/pg_opfamily.h" +#include "catalog/pg_proc.h" +#include "catalog/pg_recyclebin.h" +#include "catalog/pg_rewrite.h" +#include "catalog/pg_rlspolicy.h" +#include "catalog/pg_synonym.h" +#include "catalog/pg_tablespace.h" +#include "catalog/pg_trigger.h" +#include "catalog/pg_ts_config.h" +#include "catalog/pg_ts_dict.h" +#include "catalog/pg_ts_parser.h" +#include "catalog/pg_ts_template.h" +#include "catalog/pgxc_class.h" +#include "catalog/storage.h" +#include "commands/comment.h" +#include "commands/dbcommands.h" +#include "commands/directory.h" +#include "commands/extension.h" +#include "commands/proclang.h" +#include "commands/schemacmds.h" +#include "commands/seclabel.h" +#include "commands/sec_rls_cmds.h" +#include "commands/tablecmds.h" +#include "commands/tablespace.h" +#include "commands/trigger.h" +#include "commands/typecmds.h" +#include "executor/node/nodeModifyTable.h" +#include "rewrite/rewriteRemove.h" +#include "storage/lmgr.h" +#include "storage/predicate.h" +#include "storage/smgr/relfilenode.h" +#include "utils/acl.h" +#include "utils/builtins.h" +#include "utils/fmgroids.h" +#include "utils/inval.h" +#include "utils/lsyscache.h" +#include "utils/relcache.h" +#include "utils/snapmgr.h" +#include "utils/syscache.h" + +#include "storage/tcap.h" +#include "storage/tcap_impl.h" +/* + * 鍔熻兘璇ュ嚱鏁扮敤浜庨噸鍛藉悕鏁版嵁搴撲腑鐨勮〃銆 + * + * 鍙傛暟鍒楄〃锛 + * baseDesc锛歍rObjDesc缁撴瀯锛岃〃绀哄璞℃弿杩颁俊鎭殑鍩烘湰缁撴瀯銆 + * object锛歄bjectAddress缁撴瀯锛岃〃绀鸿閲嶅懡鍚嶇殑瀵硅薄鐨勫湴鍧淇℃伅銆 + * newName锛歝onst char鎸囬拡锛岃〃绀烘柊鐨勫璞″悕绉般 + */ +static void TrRenameClass(TrObjDesc *baseDesc, ObjectAddress *object, const char *newName) +{ + Relation rel; // 鐢ㄤ簬琛ㄧず鍏崇郴锛堣〃锛夌殑鍏崇郴瀵硅薄 + HeapTuple tup; // 鐢ㄤ簬瀛樺偍浠庣郴缁熺紦瀛樹腑妫绱㈢殑鍫嗗厓缁 + HeapTuple newtup; // 鐢ㄤ簬瀛樺偍淇敼鍚庣殑鍫嗗厓缁 + char rbname[NAMEDATALEN]; // 瀛樺偍鏂扮殑瀵硅薄鍚嶇О鐨勫瓧绗︽暟缁 + Datum values[Natts_pg_class] = { 0 }; // 瀛樺偍寰呮洿鏂扮殑鍒楀 + bool nulls[Natts_pg_class] = { false }; // 鏍囧織浣嶆暟缁勶紝鎸囩ず姣忓垪鏄惁涓篘ULL + bool replaces[Natts_pg_class] = { false }; // 鏍囧織浣嶆暟缁勶紝鎸囩ず鍝簺鍒楀皢琚浛鎹 + Oid relid = object->objectId; // 瑕侀噸鍛藉悕鐨勮〃鐨凮ID锛堝璞℃爣璇嗙锛 + errno_t rc = EOK; // 鐢ㄤ簬澶勭悊瀛楃涓插鍒剁殑閿欒鐮 + + if (newName) { + rc = strncpy_s(rbname, NAMEDATALEN, newName, strlen(newName)); // 灏嗘柊鍚嶇О澶嶅埗鍒皉bname涓 + securec_check(rc, "\0", "\0"); // 妫鏌ュ瓧绗︿覆澶嶅埗鏄惁鍑洪敊 + } else { + TrGenObjName(rbname, object->classId, relid); // 鏍规嵁瀵硅薄鐨勭被鍜孫ID鐢熸垚鏂板悕绉 + } + + replaces[Anum_pg_class_relname - 1] = true; // 鏍囪琛ㄧ殑鍚嶇О鍒楀皢琚浛鎹 + values[Anum_pg_class_relname - 1] = CStringGetDatum(rbname); // 璁剧疆鏂扮殑琛ㄥ悕鍊 + + rel = heap_open(RelationRelationId, RowExclusiveLock); // 鎵撳紑pg_class鍏崇郴锛岃幏鍙栫敤浜庤〃鐨勬搷浣滃彞鏌 + + tup = SearchSysCache1(RELOID, ObjectIdGetDatum(relid)); // 浠庣郴缁熺紦瀛樹腑鑾峰彇琛ㄧ殑鍏冪粍 + if (!HeapTupleIsValid(tup)) { + ereport(ERROR, (errcode(ERRCODE_CACHE_LOOKUP_FAILED), errmsg("cache lookup failed for relation %u", relid))); // 濡傛灉鎵句笉鍒拌〃鐨勫厓缁勶紝鎶ラ敊 + } + + newtup = heap_modify_tuple(tup, RelationGetDescr(rel), values, nulls, replaces); // 淇敼鍏冪粍鐨勫 + + simple_heap_update(rel, &newtup->t_self, newtup); // 鍦ㄥ爢涓洿鏂颁慨鏀瑰悗鐨勫厓缁 + + CatalogUpdateIndexes(rel, newtup); // 鏇存柊绱㈠紩 + + ReleaseSysCache(tup); // 閲婃斁绯荤粺缂撳瓨涓殑鍏冪粍 + + heap_freetuple_ext(newtup); // 閲婃斁淇敼鍚庣殑鍏冪粍鐨勫唴瀛 + + heap_close(rel, RowExclusiveLock); // 鍏抽棴pg_class鍏崇郴 +} + +/** + * 鍔熻兘锛氶氱敤閲嶅懡鍚嶅嚱鏁帮紝鐢ㄤ簬閲嶅懡鍚嶆暟鎹簱涓殑鏌愪簺瀵硅薄銆 + * + * 鍙傛暟鍒楄〃锛 + * baseDesc锛歍rObjDesc缁撴瀯锛岃〃绀哄璞℃弿杩颁俊鎭殑鍩烘湰缁撴瀯銆 + * object锛歄bjectAddress缁撴瀯锛岃〃绀鸿閲嶅懡鍚嶇殑瀵硅薄鐨勫湴鍧淇℃伅銆 + * relid锛氳鎿嶄綔鐨勫叧绯伙紙琛級鐨凮ID銆 + * natts锛氬緟鎿嶄綔鐨勫睘鎬ф暟閲忋 + * oidAttrNum锛歄ID灞炴х殑搴忓彿銆 + * oidIndexId锛歄ID灞炴у搴旂殑绱㈠紩鐨凮ID銆 + * objTag锛氬璞$殑鏍囩锛岀敤浜庢姤閿欎俊鎭 + */ +static void TrRenameCommon(TrObjDesc *baseDesc, ObjectAddress *object, Oid relid, int natts, int oidAttrNum, + Oid oidIndexId, char *objTag) +{ + Relation rel; // 鐢ㄤ簬琛ㄧず鍏崇郴锛堣〃锛夌殑鍏崇郴瀵硅薄 + HeapTuple tup; // 鐢ㄤ簬瀛樺偍浠庣郴缁熺紦瀛樹腑妫绱㈢殑鍫嗗厓缁 + HeapTuple newtup; // 鐢ㄤ簬瀛樺偍淇敼鍚庣殑鍫嗗厓缁 + char rbname[NAMEDATALEN]; // 瀛樺偍鏂扮殑瀵硅薄鍚嶇О鐨勫瓧绗︽暟缁 + Datum *values = (Datum *)palloc0(sizeof(Datum) * natts); // 瀛樺偍寰呮洿鏂扮殑鍒楀硷紝鍒濆鍖栦负0 + bool *nulls = (bool *)palloc0(sizeof(bool) * natts); // 鏍囧織浣嶆暟缁勶紝鎸囩ず姣忓垪鏄惁涓篘ULL锛屽垵濮嬪寲涓篺alse + bool *replaces = (bool *)palloc0(sizeof(bool) * natts); // 鏍囧織浣嶆暟缁勶紝鎸囩ず鍝簺鍒楀皢琚浛鎹紝鍒濆鍖栦负false + ScanKeyData skey[1]; // 鎵弿閿暟鎹暟缁 + SysScanDesc sd; // 绯荤粺鎵弿鎻忚堪绗 + + TrGenObjName(rbname, object->classId, object->objectId); // 鏍规嵁瀵硅薄鐨勭被鍜孫ID鐢熸垚鏂板悕绉 + + replaces[oidAttrNum - 1] = true; // 鏍囪瑕佽鏇挎崲鐨勫睘鎬 + values[oidAttrNum - 1] = CStringGetDatum(rbname); // 璁剧疆鏂扮殑灞炴у + + rel = heap_open(relid, RowExclusiveLock); // 鎵撳紑瑕佹搷浣滅殑鍏崇郴锛堣〃锛 + + ScanKeyInit(&skey[0], ObjectIdAttributeNumber, BTEqualStrategyNumber, F_OIDEQ, ObjectIdGetDatum(object->objectId)); // 鍒濆鍖栨壂鎻忛敭 + sd = systable_beginscan(rel, oidIndexId, true, NULL, 1, skey); // 寮濮嬬郴缁熻〃鎵弿 + + tup = systable_getnext(sd); // 鑾峰彇鎵弿缁撴灉 + if (!HeapTupleIsValid(tup)) { + pfree(values); + pfree(nulls); + pfree(replaces); + ereport(ERROR, + (errcode(ERRCODE_NO_DATA_FOUND), errmsg("could not find tuple for %s %u", objTag, object->objectId))); // 濡傛灉鎵句笉鍒板搴斿厓缁勶紝鎶ラ敊 + } + + newtup = heap_modify_tuple(tup, RelationGetDescr(rel), values, nulls, replaces); // 淇敼鍏冪粍鐨勫 + + simple_heap_update(rel, &newtup->t_self, newtup); // 鍦ㄥ爢涓洿鏂颁慨鏀瑰悗鐨勫厓缁 + + CatalogUpdateIndexes(rel, newtup); // 鏇存柊绱㈠紩 + + heap_freetuple_ext(newtup); // 閲婃斁淇敼鍚庣殑鍏冪粍鐨勫唴瀛 + + systable_endscan(sd); // 缁撴潫绯荤粺琛ㄦ壂鎻 + + heap_close(rel, RowExclusiveLock); // 鍏抽棴鍏崇郴锛堣〃锛 + + pfree(values); + pfree(nulls); + pfree(replaces); +} + + +/* + * 鍔熻兘锛氱敤浜庡垹闄ゆ寚瀹 baseid 瀵瑰簲鐨勮褰曘 + * + * 鍙傛暟鍒楄〃锛 + * baseid锛氳鍒犻櫎鐨勮褰曠殑 baseid銆 + */ +static void TrDeleteBaseid(Oid baseid) +{ + Relation rbRel; // 鐢ㄤ簬琛ㄧず鍥炴敹绔欏叧绯伙紙琛級鐨勫叧绯诲璞 + SysScanDesc sd; // 绯荤粺鎵弿鎻忚堪绗 + ScanKeyData skey[1]; // 鎵弿閿暟鎹暟缁 + HeapTuple tup; // 鐢ㄤ簬瀛樺偍浠庣郴缁熻〃涓绱㈢殑鍫嗗厓缁 + + rbRel = heap_open(RecyclebinRelationId, RowExclusiveLock); // 鎵撳紑鍥炴敹绔 + + ScanKeyInit(&skey[0], Anum_pg_recyclebin_rcybaseid, BTEqualStrategyNumber, F_INT8EQ, ObjectIdGetDatum(baseid)); // 鍒濆鍖栨壂鎻忛敭 + + sd = systable_beginscan(rbRel, RecyclebinBaseidIndexId, true, NULL, 1, skey); // 寮濮嬬郴缁熻〃鎵弿 + while (HeapTupleIsValid(tup = systable_getnext(sd))) { + simple_heap_delete(rbRel, &tup->t_self); // 鍒犻櫎鎵弿鍒扮殑鍏冪粍 + } + + systable_endscan(sd); // 缁撴潫绯荤粺琛ㄦ壂鎻 + heap_close(rbRel, RowExclusiveLock); // 鍏抽棴鍥炴敹绔 + CommandCounterIncrement(); +} + + +/* + * 鍔熻兘锛氱敤浜庡垹闄ゆ寚瀹 id 瀵瑰簲鐨勮褰曘 + * + * 鍙傛暟鍒楄〃锛 + * id锛氳鍒犻櫎鐨勮褰曠殑 id銆 + */ +static void TrDeleteId(Oid id) +{ + Relation rbRel; // 鐢ㄤ簬琛ㄧず鍥炴敹绔欏叧绯伙紙琛級鐨勫叧绯诲璞 + SysScanDesc sd; // 绯荤粺鎵弿鎻忚堪绗 + ScanKeyData skey[1]; // 鎵弿閿暟鎹暟缁 + HeapTuple tup; // 鐢ㄤ簬瀛樺偍浠庣郴缁熻〃涓绱㈢殑鍫嗗厓缁 + + rbRel = heap_open(RecyclebinRelationId, RowExclusiveLock); // 鎵撳紑鍥炴敹绔欏叧绯伙紙琛級 + + ScanKeyInit(&skey[0], ObjectIdAttributeNumber, BTEqualStrategyNumber, F_OIDEQ, ObjectIdGetDatum(id)); // 鍒濆鍖栨壂鎻忛敭 + + sd = systable_beginscan(rbRel, RecyclebinIdIndexId, true, NULL, 1, skey); // 寮濮嬬郴缁熻〃鎵弿 + if (HeapTupleIsValid(tup = systable_getnext(sd))) { + simple_heap_delete(rbRel, &tup->t_self); // 鍒犻櫎鎵弿鍒扮殑鍏冪粍 + } + + systable_endscan(sd); // 缁撴潫绯荤粺琛ㄦ壂鎻 + heap_close(rbRel, RowExclusiveLock); // 鍏抽棴鍥炴敹绔欏叧绯伙紙琛級 + + /* + * CommandCounterIncrement here to ensure that preceding changes are all + * visible to the next deletion step. + */ + CommandCounterIncrement(); +} +/* + * 鍔熻兘锛氬垽鏂槸鍚﹂渶瑕佽繘琛岄昏緫鍒犻櫎銆 + * + * 鍙傛暟鍒楄〃锛 + * object锛歄bjectAddress缁撴瀯锛岃〃绀哄璞$殑鍦板潃淇℃伅銆 + * + */ +static inline bool TrNeedLogicDrop(const ObjectAddress *object) +{ + return object->rbDropMode == RB_DROP_MODE_LOGIC; +} + +/** + * 鍔熻兘锛氬垽鏂槸鍚﹀彲浠ヨ繘琛屾竻闄ゆ搷浣溿 + * + * 鍙傛暟鍒楄〃锛 + * baseDesc锛歍rObjDesc缁撴瀯锛岃〃绀哄璞℃弿杩颁俊鎭殑鍩烘湰缁撴瀯銆 + * object锛歄bjectAddress缁撴瀯锛岃〃绀哄璞$殑鍦板潃淇℃伅銆 + * relKind锛氳〃绀哄璞$殑鍏崇郴绫诲瀷銆 + */ +static bool TrCanPurge(const TrObjDesc *baseDesc, const ObjectAddress *object, char relKind) +{ + Relation depRel; // 鐢ㄤ簬琛ㄧず渚濊禆鍏崇郴锛堣〃锛夌殑鍏崇郴瀵硅薄 + SysScanDesc sd; // 绯荤粺鎵弿鎻忚堪绗 + HeapTuple tuple; // 鐢ㄤ簬瀛樺偍浠庣郴缁熻〃涓绱㈢殑鍫嗗厓缁 + ScanKeyData key[3]; // 鎵弿閿暟鎹暟缁 + int nkeys; // 鎵弿閿殑鏁伴噺 + bool found = false; // 琛ㄧず鏄惁鎵惧埌鍖归厤渚濊禆鍏崇郴 + + if (relKind != RELKIND_INDEX && relKind != RELKIND_GLOBAL_INDEX && relKind != RELKIND_RELATION) { + return false; // 濡傛灉鍏崇郴绫诲瀷涓嶆槸鍚堟硶绫诲瀷锛岀洿鎺ヨ繑鍥瀎alse + } + + depRel = heap_open(DependRelationId, AccessShareLock); // 鎵撳紑渚濊禆鍏崇郴锛堣〃锛 + + ScanKeyInit(&key[0], Anum_pg_depend_classid, BTEqualStrategyNumber, F_OIDEQ, ObjectIdGetDatum(object->classId)); // 鍒濆鍖栨壂鎻忛敭 + ScanKeyInit(&key[1], Anum_pg_depend_objid, BTEqualStrategyNumber, F_OIDEQ, ObjectIdGetDatum(object->objectId)); + nkeys = 2; + if (object->objectSubId != 0) { + ScanKeyInit(&key[2], Anum_pg_depend_objsubid, BTEqualStrategyNumber, F_INT4EQ, + Int32GetDatum(object->objectSubId)); + nkeys = 3; + } + + sd = systable_beginscan(depRel, DependDependerIndexId, true, NULL, nkeys, key); // 寮濮嬬郴缁熻〃鎵弿 + while (HeapTupleIsValid(tuple = systable_getnext(sd))) { + Form_pg_depend depForm = (Form_pg_depend)GETSTRUCT(tuple); + if (depForm->refclassid == RelationRelationId && depForm->refobjid == baseDesc->relid) { // 鍒ゆ柇鏄惁涓轰緷璧栦簬褰撳墠琛ㄧ殑渚濊禆鍏崇郴 + if (depForm->deptype != DEPENDENCY_AUTO) { // 濡傛灉渚濊禆绫诲瀷涓嶆槸鑷姩渚濊禆锛屼笉鍙竻闄 + found = false; + break; + } + found = true; // 鎵惧埌鍖归厤鐨勪緷璧栧叧绯 + } + } + + systable_endscan(sd); // 缁撴潫绯荤粺琛ㄦ壂鎻 + heap_close(depRel, AccessShareLock); // 鍏抽棴渚濊禆鍏崇郴锛堣〃锛 + return found; +} + + +/* + * 鍔熻兘锛氭墽琛屽垹闄ょ储寮曠殑鎿嶄綔銆 + * + * 鍙傛暟鍒楄〃锛 + * baseDesc锛歍rObjDesc缁撴瀯锛岃〃绀哄璞℃弿杩颁俊鎭殑鍩烘湰缁撴瀯銆 + * object锛歄bjectAddress缁撴瀯锛岃〃绀哄璞$殑鍦板潃淇℃伅銆 + */ +static void TrDoDropIndex(TrObjDesc *baseDesc, ObjectAddress *object) +{ + Assert(object->objectSubId == 0); // 鏂█锛岀‘淇濆璞$殑瀛愭爣璇嗙涓0锛堢储寮曟病鏈夊瓙鏍囪瘑绗︼級 + + if (TrNeedLogicDrop(object)) { // 濡傛灉闇瑕侀昏緫鍒犻櫎 + TrObjDesc desc = *baseDesc; // 澶嶅埗鍩烘湰鎻忚堪淇℃伅 + + if (!TR_IS_BASE_OBJ(baseDesc, object)) { + /* 鍗曚釜瀵硅薄鍒犻櫎涔嬪墠宸茶幏鍙栧垹闄ら攣銆*/ + Relation rel = relation_open(object->objectId, NoLock); // 鎵撳紑瑕佸垹闄ょ殑鍏崇郴锛堣〃锛 + + TrDescInit(rel, &desc, RB_OPER_DROP, TrGetObjType(RelationGetNamespace(rel), RELKIND_INDEX), // 鍒濆鍖栨弿杩颁俊鎭 + TrCanPurge(baseDesc, object, RelationGetRelkind(rel))); + relation_close(rel, NoLock); // 鍏抽棴鍏崇郴锛堣〃锛 + + TrDescWrite(&desc); // 鍐欏叆鎻忚堪淇℃伅 + } + + TrRenameClass(baseDesc, object, desc.name); // 閲嶅懡鍚嶅璞 + } else { + index_drop(object->objectId, false); // 鐩存帴鍒犻櫎绱㈠紩 + } + + return; +} + +/* + * 鍔熻兘锛氭墽琛屽垹闄よ〃鐨勬搷浣溿 + * + * 鍙傛暟鍒楄〃锛 + * baseDesc锛歍rObjDesc缁撴瀯锛岃〃绀哄璞℃弿杩颁俊鎭殑鍩烘湰缁撴瀯銆 + * object锛歄bjectAddress缁撴瀯锛岃〃绀哄璞$殑鍦板潃淇℃伅銆 + * relKind锛氳〃绀哄璞$殑鍏崇郴绫诲瀷锛屽彲浠ユ槸RELKIND_RELATION銆丷ELKIND_VIEW銆丷ELKIND_COMPOSITE_TYPE鎴朢ELKIND_FOREIGN_TABLE銆 + */ +static void TrDoDropTable(TrObjDesc *baseDesc, ObjectAddress *object, char relKind) +{ + if (TrNeedLogicDrop(object)) { // 濡傛灉闇瑕侀昏緫鍒犻櫎 + TrObjDesc desc; + + if (object->objectSubId != 0 || relKind == RELKIND_VIEW || relKind == RELKIND_COMPOSITE_TYPE || + relKind == RELKIND_FOREIGN_TABLE) { // 瀵逛簬瀛愬璞℃垨鐗瑰畾绫诲瀷鐨勫璞★紝鐩存帴閲嶅懡鍚嶅苟杩斿洖 + TrRenameClass(baseDesc, object, NULL); + return; + } + + desc = *baseDesc; // 澶嶅埗鍩烘湰鎻忚堪淇℃伅 + if (!TR_IS_BASE_OBJ(baseDesc, object)) { + /* 鍗曚釜瀵硅薄鍒犻櫎涔嬪墠宸茶幏鍙栧垹闄ら攣銆*/ + Relation rel = relation_open(object->objectId, NoLock); // 鎵撳紑瑕佸垹闄ょ殑鍏崇郴锛堣〃锛 + + TrDescInit(rel, &desc, RB_OPER_DROP, TrGetObjType(InvalidOid, relKind), // 鍒濆鍖栨弿杩颁俊鎭 + TrCanPurge(baseDesc, object, relKind)); + relation_close(rel, NoLock); // 鍏抽棴鍏崇郴锛堣〃锛 + + TrDescWrite(&desc); // 鍐欏叆鎻忚堪淇℃伅 + } + + TrRenameClass(baseDesc, object, desc.name); // 閲嶅懡鍚嶅璞 + + return; + } + /* + * relation_open() must be before the heap_drop_with_catalog(). If you reload + * relation after drop, it may cause other exceptions during the drop process. + */ + if (object->objectSubId != 0) + RemoveAttributeById(object->objectId, object->objectSubId); // 鍒犻櫎瀛愬睘鎬 + else + heap_drop_with_catalog(object->objectId); // 鍒犻櫎琛 + + /* + * IMPORANT: The relation must not be reloaded after heap_drop_with_catalog() + * is executed to drop this relation.If you reload relation after drop, it may + * cause other exceptions during the drop process + */ + + return; +} + +/* + * 鍔熻兘锛氭墽琛屽垹闄ょ被鍨嬬殑鎿嶄綔銆 + * + * 鍙傛暟鍒楄〃锛 + * baseDesc锛歍rObjDesc缁撴瀯锛岃〃绀哄璞℃弿杩颁俊鎭殑鍩烘湰缁撴瀯銆 + * object锛歄bjectAddress缁撴瀯锛岃〃绀哄璞$殑鍦板潃淇℃伅銆 + */ +static void TrDoDropType(TrObjDesc *baseDesc, ObjectAddress *object) +{ + if (TrNeedLogicDrop(object)) { // 濡傛灉闇瑕侀昏緫鍒犻櫎 + TrRenameCommon(baseDesc, object, TypeRelationId, Natts_pg_type, Anum_pg_type_typname, TypeOidIndexId, "type"); // 璋冪敤閫氱敤閲嶅懡鍚嶅嚱鏁 + } else { + RemoveTypeById(object->objectId); // 鐩存帴鍒犻櫎绫诲瀷 + } + + return; +} + +/* + * T鍔熻兘鎵ц鍒犻櫎绾︽潫鐨勬搷浣溿 + * + * 鍙傛暟鍒楄〃锛 + * baseDesc锛歍rObjDesc缁撴瀯锛岃〃绀哄璞℃弿杩颁俊鎭殑鍩烘湰缁撴瀯銆 + * object锛歄bjectAddress缁撴瀯锛岃〃绀哄璞$殑鍦板潃淇℃伅銆 + */ +static void TrDoDropConstraint(TrObjDesc *baseDesc, ObjectAddress *object) +{ + if (TrNeedLogicDrop(object)) { // 濡傛灉闇瑕侀昏緫鍒犻櫎 + TrRenameCommon(baseDesc, object, ConstraintRelationId, Natts_pg_constraint, Anum_pg_constraint_conname, + ConstraintOidIndexId, "constraint"); // 璋冪敤閫氱敤閲嶅懡鍚嶅嚱鏁 + } else { + RemoveConstraintById(object->objectId); // 鐩存帴鍒犻櫎绾︽潫 + } + + return; +} + + +/* + * 鍔熻兘锛氭墽琛屽垹闄よЕ鍙戝櫒鐨勬搷浣溿 + * + * 鍙傛暟鍒楄〃锛 + * baseDesc锛歍rObjDesc缁撴瀯锛岃〃绀哄璞℃弿杩颁俊鎭殑鍩烘湰缁撴瀯銆 + * object锛歄bjectAddress缁撴瀯锛岃〃绀哄璞$殑鍦板潃淇℃伅銆 + */ +static void TrDoDropTrigger(TrObjDesc *baseDesc, ObjectAddress *object) +{ + if (TrNeedLogicDrop(object)) { // 濡傛灉闇瑕侀昏緫鍒犻櫎 + TrRenameCommon(baseDesc, object, TriggerRelationId, Natts_pg_trigger, Anum_pg_trigger_tgname, TriggerOidIndexId, + "trigger"); // 璋冪敤閫氱敤閲嶅懡鍚嶅嚱鏁 + } else { + RemoveTriggerById(object->objectId); // 鐩存帴鍒犻櫎瑙﹀彂鍣 + } + + return; +} + +/* + * 鍔熻兘锛氭墽琛屽垹闄ら噸鍐欒鍒欑殑鎿嶄綔銆 + * + * 鍙傛暟鍒楄〃锛 + * baseDesc锛歍rObjDesc缁撴瀯锛岃〃绀哄璞℃弿杩颁俊鎭殑鍩烘湰缁撴瀯銆 + * object锛歄bjectAddress缁撴瀯锛岃〃绀哄璞$殑鍦板潃淇℃伅銆 + */ +static void TrDoDropRewrite(TrObjDesc *baseDesc, ObjectAddress *object) +{ + if (TrNeedLogicDrop(object)) { + /* 鏃犻渶鎿嶄綔锛屽洜涓哄熀浜庤鍒欑殑瑙嗗浘瑕佹眰淇濈暀鍘熷瑙勫垯鍚嶇О銆*/ + } else { + RemoveRewriteRuleById(object->objectId); // 鐩存帴鍒犻櫎閲嶅啓瑙勫垯 + } + + return; +} + + +/* + * 鍔熻兘锛氭墽琛屽垹闄ゅ睘鎬ч粯璁ゅ肩殑鎿嶄綔銆 + * + * 鍙傛暟鍒楄〃锛 + * baseDesc锛歍rObjDesc缁撴瀯锛岃〃绀哄璞℃弿杩颁俊鎭殑鍩烘湰缁撴瀯銆 + * object锛歄bjectAddress缁撴瀯锛岃〃绀哄璞$殑鍦板潃淇℃伅銆 + */ +static void TrDoDropAttrdef(TrObjDesc *baseDesc, ObjectAddress *object) +{ + if (TrNeedLogicDrop(object)) { + /* 鏃犻渶鎿嶄綔锛屽洜涓虹郴缁熺洰褰曚腑娌℃湁鍚嶇О灞炴с*/ + } else { + RemoveAttrDefaultById(object->objectId); // 鐩存帴鍒犻櫎灞炴ч粯璁ゅ + } + + return; +} + +/* + * 鍔熻兘锛氭墽琛屽垹闄よ繃绋嬬殑鎿嶄綔銆 + * + * 鍙傛暟鍒楄〃锛 + * baseDesc锛歍rObjDesc缁撴瀯锛岃〃绀哄璞℃弿杩颁俊鎭殑鍩烘湰缁撴瀯銆 + * object锛歄bjectAddress缁撴瀯锛岃〃绀哄璞$殑鍦板潃淇℃伅銆 + */ +static void TrDoDropProc(TrObjDesc *baseDesc, ObjectAddress *object) +{ + if (TrNeedLogicDrop(object)) { // 濡傛灉闇瑕侀昏緫鍒犻櫎 + TrRenameCommon(baseDesc, object, ProcedureRelationId, Natts_pg_proc, Anum_pg_proc_proname, ProcedureOidIndexId, + "procedure"); // 閲嶅懡鍚 + } else { + RemoveFunctionById(object->objectId); // 鐩存帴鍒犻櫎杩囩▼ + } + + return; +} + + +/* + * 鍔熻兘锛氭墽琛屽垹闄ょ被鍨嬭浆鎹㈢殑鎿嶄綔銆 + * + * 鍙傛暟鍒楄〃锛 + * baseDesc锛歍rObjDesc缁撴瀯锛岃〃绀哄璞℃弿杩颁俊鎭殑鍩烘湰缁撴瀯銆 + * object锛歄bjectAddress缁撴瀯锛岃〃绀哄璞$殑鍦板潃淇℃伅銆 + */ +static void TrDoDropCast(TrObjDesc *baseDesc, ObjectAddress *object) +{ + if (TrNeedLogicDrop(object)) { + /* 鏃犻渶鎿嶄綔锛屽洜涓虹郴缁熺洰褰曚腑娌℃湁鍚嶇О灞炴с*/ + } else { + DropCastById(object->objectId); // 鐩存帴鍒犻櫎绫诲瀷杞崲 + } + + return; +} + +/* + * 鍔熻兘锛氭墽琛屽垹闄ゆ帓搴忚鍒欑殑鎿嶄綔銆 + * + * 鍙傛暟鍒楄〃锛 + * baseDesc锛歍rObjDesc缁撴瀯锛岃〃绀哄璞℃弿杩颁俊鎭殑鍩烘湰缁撴瀯銆 + * object锛歄bjectAddress缁撴瀯锛岃〃绀哄璞$殑鍦板潃淇℃伅銆 + */ +static void TrDoDropCollation(TrObjDesc *baseDesc, ObjectAddress *object) +{ + if (TrNeedLogicDrop(object)) { // 濡傛灉闇瑕侀昏緫鍒犻櫎 + TrRenameCommon(baseDesc, object, CollationRelationId, Natts_pg_collation, Anum_pg_collation_collname, + CollationOidIndexId, "collation"); // 閲嶅懡鍚 + } else { + RemoveCollationById(object->objectId); // 鐩存帴鍒犻櫎鎺掑簭瑙勫垯 + } + + return; +} + + +/* + * 鍔熻兘锛氭墽琛屽垹闄ょ被鍨嬭浆鎹㈢殑鎿嶄綔銆 + * + * 鍙傛暟鍒楄〃锛 + * baseDesc锛歍rObjDesc缁撴瀯锛岃〃绀哄璞℃弿杩颁俊鎭殑鍩烘湰缁撴瀯銆 + * object锛歄bjectAddress缁撴瀯锛岃〃绀哄璞$殑鍦板潃淇℃伅銆 + */ +static void TrDoDropConversion(TrObjDesc *baseDesc, ObjectAddress *object) +{ + if (TrNeedLogicDrop(object)) { // 濡傛灉闇瑕侀昏緫鍒犻櫎 + TrRenameCommon(baseDesc, object, ConversionRelationId, Natts_pg_conversion, Anum_pg_conversion_conname, + ConversionOidIndexId, "conversion"); // 閲嶅懡鍚 + } else { + RemoveConversionById(object->objectId); // 鐩存帴鍒犻櫎绫诲瀷杞崲 + } + + return; +} + +/* + * 鍔熻兘锛氭墽琛屽垹闄よ繃绋嬭瑷鐨勬搷浣溿 + * + * 鍙傛暟鍒楄〃锛 + * baseDesc锛歍rObjDesc缁撴瀯锛岃〃绀哄璞℃弿杩颁俊鎭殑鍩烘湰缁撴瀯銆 + * object锛歄bjectAddress缁撴瀯锛岃〃绀哄璞$殑鍦板潃淇℃伅銆 + */ +static void TrDoDropProceduralLanguage(TrObjDesc *baseDesc, ObjectAddress *object) +{ + if (TrNeedLogicDrop(object)) { // 濡傛灉闇瑕侀昏緫鍒犻櫎 + TrRenameCommon(baseDesc, object, LanguageRelationId, Natts_pg_language, Anum_pg_language_lanname, + LanguageOidIndexId, "language"); // 閲嶅懡鍚 + } else { + DropProceduralLanguageById(object->objectId); // 鐩存帴鍒犻櫎杩囩▼璇█ + } + + return; +} + + +/* + * 鍔熻兘锛氭墽琛屽垹闄ゅぇ瀵硅薄鐨勬搷浣溿 + * + * 鍙傛暟鍒楄〃锛 + * baseDesc锛歍rObjDesc缁撴瀯锛岃〃绀哄璞℃弿杩颁俊鎭殑鍩烘湰缁撴瀯銆 + * object锛歄bjectAddress缁撴瀯锛岃〃绀哄璞$殑鍦板潃淇℃伅銆 + */ +static void TrDoDropLargeObject(TrObjDesc *baseDesc, ObjectAddress *object) +{ + if (TrNeedLogicDrop(object)) { + /* 鏃犻渶鎿嶄綔锛屽洜涓虹郴缁熺洰褰曚腑娌℃湁鍚嶇О灞炴с*/ + } else { + LargeObjectDrop(object->objectId); // 鐩存帴鍒犻櫎瀵硅薄 + } + + return; +} + +/* + * 鍔熻兘锛氭墽琛屽垹闄ゆ搷浣滅鐨勬搷浣溿 + * + * 鍙傛暟鍒楄〃锛 + * baseDesc锛歍rObjDesc缁撴瀯锛岃〃绀哄璞℃弿杩颁俊鎭殑鍩烘湰缁撴瀯銆 + * object锛歄bjectAddress缁撴瀯锛岃〃绀哄璞$殑鍦板潃淇℃伅銆 + */ +static void TrDoDropOperator(TrObjDesc *baseDesc, ObjectAddress *object) +{ + if (TrNeedLogicDrop(object)) { // 濡傛灉闇瑕侀昏緫鍒犻櫎 + TrRenameCommon(baseDesc, object, OperatorRelationId, Natts_pg_operator, Anum_pg_operator_oprname, + OperatorOidIndexId, "operator"); // 閲嶅懡鍚 + } else { + RemoveOperatorById(object->objectId); // 鐩存帴鍒犻櫎鎿嶄綔绗 + } + + return; +} + + +/* + * 鍔熻兘锛氭墽琛屽垹闄ゆ搷浣滅绫荤殑鎿嶄綔銆 + * + * 鍙傛暟鍒楄〃锛 + * baseDesc锛歍rObjDesc缁撴瀯锛岃〃绀哄璞℃弿杩颁俊鎭殑鍩烘湰缁撴瀯銆 + * object锛歄bjectAddress缁撴瀯锛岃〃绀哄璞$殑鍦板潃淇℃伅銆 + */ +static void TrDoDropOpClass(TrObjDesc *baseDesc, ObjectAddress *object) +{ + if (TrNeedLogicDrop(object)) { // 濡傛灉闇瑕侀昏緫鍒犻櫎 + TrRenameCommon(baseDesc, object, OperatorClassRelationId, Natts_pg_opclass, Anum_pg_opclass_opcname, + OpclassOidIndexId, "opclass"); // 閲嶅懡鍚 + } else { + RemoveOpClassById(object->objectId); // 鐩存帴鍒犻櫎鎿嶄綔绗︾被 + } + + return; +} + +/* + * 鍔熻兘锛氭墽琛屽垹闄ゆ搷浣滅鏃忕殑鎿嶄綔銆 + * + * 鍙傛暟鍒楄〃锛 + * baseDesc锛歍rObjDesc缁撴瀯锛岃〃绀哄璞℃弿杩颁俊鎭殑鍩烘湰缁撴瀯銆 + * object锛歄bjectAddress缁撴瀯锛岃〃绀哄璞$殑鍦板潃淇℃伅銆 + */ +static void TrDoDropOpFamily(TrObjDesc *baseDesc, ObjectAddress *object) +{ + if (TrNeedLogicDrop(object)) { // 濡傛灉闇瑕侀昏緫鍒犻櫎 + TrRenameCommon(baseDesc, object, OperatorFamilyRelationId, Natts_pg_opfamily, Anum_pg_opfamily_opfname, + OpfamilyOidIndexId, "opfamily"); // 閲嶅懡鍚 + } else { + RemoveOpFamilyById(object->objectId); // 鐩存帴鍒犻櫎鎿嶄綔绗︽棌 + } + + return; +} + + + +/* + * 鍔熻兘锛氭墽琛屽垹闄ゆ搷浣滅璁块棶鏂规硶椤圭殑鎿嶄綔銆 + * + * 鍙傛暟鍒楄〃锛 + * baseDesc锛歍rObjDesc缁撴瀯锛岃〃绀哄璞℃弿杩颁俊鎭殑鍩烘湰缁撴瀯銆 + * object锛歄bjectAddress缁撴瀯锛岃〃绀哄璞$殑鍦板潃淇℃伅銆 + */ +static void TrDoDropAmOp(TrObjDesc *baseDesc, ObjectAddress *object) +{ + if (TrNeedLogicDrop(object)) { + /* 鏃犻渶鎿嶄綔锛屽洜涓虹郴缁熺洰褰曚腑娌℃湁鍚嶇О灞炴с*/ + } else { + RemoveAmOpEntryById(object->objectId); // 鐩存帴鍒犻櫎鎿嶄綔绗﹁闂柟娉曢」 + } + + return; +} + +/* + * 鍔熻兘锛氭墽琛屽垹闄よ繃绋嬭闂柟娉曢」鐨勬搷浣溿 + * + * 鍙傛暟鍒楄〃锛 + * baseDesc锛歍rObjDesc缁撴瀯锛岃〃绀哄璞℃弿杩颁俊鎭殑鍩烘湰缁撴瀯銆 + * object锛歄bjectAddress缁撴瀯锛岃〃绀哄璞$殑鍦板潃淇℃伅銆 + */ +static void TrDoDropAmProc(TrObjDesc *baseDesc, ObjectAddress *object) +{ + if (TrNeedLogicDrop(object)) { + /* 鏃犻渶鎿嶄綔锛屽洜涓虹郴缁熺洰褰曚腑娌℃湁鍚嶇О灞炴с*/ + } else { + RemoveAmProcEntryById(object->objectId); // 鐩存帴鍒犻櫎杩囩▼璁块棶鏂规硶椤 + } + + return; +} + + +/* + * 鍔熻兘锛氭墽琛屽垹闄ゆā寮忕殑鎿嶄綔銆 + * + * 鍙傛暟鍒楄〃锛 + * baseDesc锛歍rObjDesc缁撴瀯锛岃〃绀哄璞℃弿杩颁俊鎭殑鍩烘湰缁撴瀯銆 + * object锛歄bjectAddress缁撴瀯锛岃〃绀哄璞$殑鍦板潃淇℃伅銆 + */ +static void TrDoDropSchema(TrObjDesc *baseDesc, ObjectAddress *object) +{ + if (TrNeedLogicDrop(object)) { // 濡傛灉闇瑕侀昏緫鍒犻櫎 + TrRenameCommon(baseDesc, object, NamespaceRelationId, Natts_pg_namespace, Anum_pg_namespace_nspname, + NamespaceOidIndexId, "namespace"); // 閲嶅懡鍚 + } else { + RemoveSchemaById(object->objectId); // 鐩存帴鍒犻櫎妯″紡 + } + + return; +} + +/* + * 鍔熻兘锛氭墽琛屽垹闄ゆ枃鏈悳绱㈣В鏋愬櫒鐨勬搷浣溿 + * + * 鍙傛暟鍒楄〃锛 + * baseDesc锛歍rObjDesc缁撴瀯锛岃〃绀哄璞℃弿杩颁俊鎭殑鍩烘湰缁撴瀯銆 + * object锛歄bjectAddress缁撴瀯锛岃〃绀哄璞$殑鍦板潃淇℃伅銆 + */ +static void TrDoDropTSParser(TrObjDesc *baseDesc, ObjectAddress *object) +{ + if (TrNeedLogicDrop(object)) { // 濡傛灉闇瑕侀昏緫鍒犻櫎 + TrRenameCommon(baseDesc, object, TSParserRelationId, Natts_pg_ts_parser, Anum_pg_ts_parser_prsname, + TSParserOidIndexId, "ts parser"); // 閲嶅懡鍚 + } else { + RemoveTSParserById(object->objectId); // 鐩存帴鍒犻櫎鏂囨湰鎼滅储瑙f瀽鍣 + } + + return; +} + +/* + * 鍔熻兘锛氭墽琛屽垹闄ゆ枃鏈悳绱㈠瓧鍏哥殑鎿嶄綔銆 + * + * 鍙傛暟鍒楄〃锛 + * baseDesc锛歍rObjDesc缁撴瀯锛岃〃绀哄璞℃弿杩颁俊鎭殑鍩烘湰缁撴瀯銆 + * object锛歄bjectAddress缁撴瀯锛岃〃绀哄璞$殑鍦板潃淇℃伅銆 + */ +static void TrDoDropTSDictionary(TrObjDesc *baseDesc, ObjectAddress *object) +{ + if (TrNeedLogicDrop(object)) { // 濡傛灉闇瑕侀昏緫鍒犻櫎 + TrRenameCommon(baseDesc, object, TSDictionaryRelationId, Natts_pg_ts_dict, Anum_pg_ts_dict_dictname, + TSDictionaryOidIndexId, "ts dictionary"); // 閲嶅懡鍚 + } else { + RemoveTSDictionaryById(object->objectId); // 鐩存帴鍒犻櫎鏂囨湰鎼滅储瀛楀吀 + } + + return; +} + +/* + * 鍔熻兘锛氭墽琛屽垹闄ゆ枃鏈悳绱㈡ā鏉跨殑鎿嶄綔銆 + * + * 鍙傛暟鍒楄〃锛 + * baseDesc锛歍rObjDesc缁撴瀯锛岃〃绀哄璞℃弿杩颁俊鎭殑鍩烘湰缁撴瀯銆 + * object锛歄bjectAddress缁撴瀯锛岃〃绀哄璞$殑鍦板潃淇℃伅銆 + */ +static void TrDoDropTSTemplate(TrObjDesc *baseDesc, ObjectAddress *object) +{ + if (TrNeedLogicDrop(object)) { // 濡傛灉闇瑕侀昏緫鍒犻櫎 + TrRenameCommon(baseDesc, object, TSTemplateRelationId, Natts_pg_ts_template, Anum_pg_ts_template_tmplname, + TSTemplateOidIndexId, "ts template"); // 閲嶅懡鍚 + } else { + RemoveTSTemplateById(object->objectId); // 鐩存帴鍒犻櫎鏂囨湰鎼滅储妯℃澘 + } + + return; +} + + +/* + * 鍔熻兘锛氭墽琛屽垹闄ゆ枃鏈悳绱㈤厤缃殑鎿嶄綔銆 + * + * 鍙傛暟鍒楄〃锛 + * baseDesc锛歍rObjDesc缁撴瀯锛岃〃绀哄璞℃弿杩颁俊鎭殑鍩烘湰缁撴瀯銆 + * object锛歄bjectAddress缁撴瀯锛岃〃绀哄璞$殑鍦板潃淇℃伅銆 + */ +static void TrDoDropTSConfiguration(TrObjDesc *baseDesc, ObjectAddress *object) +{ + if (TrNeedLogicDrop(object)) { // 濡傛灉闇瑕侀昏緫鍒犻櫎 + TrRenameCommon(baseDesc, object, TSConfigRelationId, Natts_pg_ts_config, Anum_pg_ts_config_cfgname, + TSConfigOidIndexId, "ts configuration"); // 閲嶅懡鍚 + } else { + RemoveTSConfigurationById(object->objectId); // 鐩存帴鍒犻櫎鏂囨湰鎼滅储閰嶇疆 + } + + return; +} + +/* + * 鍔熻兘锛氭墽琛屽垹闄ゅ閮ㄦ暟鎹皝瑁呭櫒鐨勬搷浣溿 + * + * 鍙傛暟鍒楄〃锛 + * baseDesc锛歍rObjDesc缁撴瀯锛岃〃绀哄璞℃弿杩颁俊鎭殑鍩烘湰缁撴瀯銆 + * object锛歄bjectAddress缁撴瀯锛岃〃绀哄璞$殑鍦板潃淇℃伅銆 + */ +static void TrDoDropForeignDataWrapper(TrObjDesc *baseDesc, ObjectAddress *object) +{ + if (TrNeedLogicDrop(object)) { // 濡傛灉闇瑕侀昏緫鍒犻櫎 + TrRenameCommon(baseDesc, object, ForeignDataWrapperRelationId, Natts_pg_foreign_data_wrapper, + Anum_pg_foreign_data_wrapper_fdwname, ForeignDataWrapperOidIndexId, "foreign data wrapper"); // 閲嶅懡鍚 + } else { + RemoveForeignDataWrapperById(object->objectId); // 鐩存帴鍒犻櫎澶栭儴鏁版嵁灏佽鍣 + } + + return; +} + +/* + * 鍔熻兘锛氭墽琛屽垹闄ゅ閮ㄦ湇鍔″櫒鐨勬搷浣溿 + * + * 鍙傛暟鍒楄〃锛 + * baseDesc锛歍rObjDesc缁撴瀯锛岃〃绀哄璞℃弿杩颁俊鎭殑鍩烘湰缁撴瀯銆 + * object锛歄bjectAddress缁撴瀯锛岃〃绀哄璞$殑鍦板潃淇℃伅銆 + */ +static void TrDoDropForeignServer(TrObjDesc *baseDesc, ObjectAddress *object) +{ + if (TrNeedLogicDrop(object)) { // 濡傛灉闇瑕侀昏緫鍒犻櫎 + TrRenameCommon(baseDesc, object, ForeignServerRelationId, Natts_pg_foreign_server, + Anum_pg_foreign_server_srvname, ForeignServerOidIndexId, "foreign server"); // 閲嶅懡鍚 + } else { + RemoveForeignServerById(object->objectId); // 鐩存帴鍒犻櫎澶栭儴鏈嶅姟鍣 + } + + return; +} + +/* + * 鍔熻兘锛氭墽琛屽垹闄ょ敤鎴锋槧灏勭殑鎿嶄綔銆 + * + * 鍙傛暟鍒楄〃锛 + * baseDesc锛歍rObjDesc缁撴瀯锛岃〃绀哄璞℃弿杩颁俊鎭殑鍩烘湰缁撴瀯銆 + * object锛歄bjectAddress缁撴瀯锛岃〃绀哄璞$殑鍦板潃淇℃伅銆 + */ +static void TrDoDropUserMapping(TrObjDesc *baseDesc, ObjectAddress *object) +{ + if (TrNeedLogicDrop(object)) { + /* 鏃犻渶鎿嶄綔锛屽洜涓虹郴缁熺洰褰曚腑娌℃湁鍚嶇О灞炴с*/ + } else { + RemoveUserMappingById(object->objectId); // 鐩存帴鍒犻櫎鐢ㄦ埛鏄犲皠 + } + + return; +} + + + +/* + * 鍔熻兘锛氭墽琛屽垹闄ら粯璁よ闂帶鍒跺垪琛ㄧ殑鎿嶄綔銆 + * + * 鍙傛暟鍒楄〃锛 + * baseDesc锛歍rObjDesc缁撴瀯锛岃〃绀哄璞℃弿杩颁俊鎭殑鍩烘湰缁撴瀯銆 + * object锛歄bjectAddress缁撴瀯锛岃〃绀哄璞$殑鍦板潃淇℃伅銆 + */ +static void TrDoDropDefaultACL(TrObjDesc *baseDesc, ObjectAddress *object) +{ + if (TrNeedLogicDrop(object)) { + /* 鏃犻渶鎿嶄綔锛屽洜涓虹郴缁熺洰褰曚腑娌℃湁鍚嶇О灞炴с*/ + } else { + RemoveDefaultACLById(object->objectId); // 鐩存帴鍒犻櫎榛樿璁块棶鎺у埗鍒楄〃 + } + + return; +} + +/* + * 鍔熻兘锛氭墽琛屽垹闄ゅ垎甯冨紡琛ㄤ俊鎭殑鎿嶄綔銆 + * + * 鍙傛暟鍒楄〃锛 + * baseDesc锛歍rObjDesc缁撴瀯锛岃〃绀哄璞℃弿杩颁俊鎭殑鍩烘湰缁撴瀯銆 + * object锛歄bjectAddress缁撴瀯锛岃〃绀哄璞$殑鍦板潃淇℃伅銆 + */ +static void TrDoDropPgxcClass(TrObjDesc *baseDesc, ObjectAddress *object) +{ + if (TrNeedLogicDrop(object)) { + /* 鏃犻渶鎿嶄綔锛屽洜涓虹郴缁熺洰褰曚腑娌℃湁鍚嶇О灞炴с*/ + } else { + RemovePgxcClass(object->objectId); // 鐩存帴鍒犻櫎鍒嗗竷寮忚〃淇℃伅 + } + + return; +} + +/* + * 鍔熻兘锛氭墽琛屽垹闄ゆ墿灞曠殑鎿嶄綔銆 + * + * 鍙傛暟鍒楄〃锛 + * baseDesc锛歍rObjDesc缁撴瀯锛岃〃绀哄璞℃弿杩颁俊鎭殑鍩烘湰缁撴瀯銆 + * object锛歄bjectAddress缁撴瀯锛岃〃绀哄璞$殑鍦板潃淇℃伅銆 + */ +static void TrDoDropExtension(TrObjDesc *baseDesc, ObjectAddress *object) +{ + if (TrNeedLogicDrop(object)) { // 濡傛灉闇瑕侀昏緫鍒犻櫎 + TrRenameCommon(baseDesc, object, ExtensionRelationId, Natts_pg_extension, Anum_pg_extension_extname, + ExtensionOidIndexId, "extension"); // 閲嶅懡鍚 + } else { + RemoveExtensionById(object->objectId); // 鐩存帴鍒犻櫎鎵╁睍 + } + + return; +} + +/* + * 鍔熻兘锛氭墽琛屽垹闄ゆ墿灞曟暟鎹簮鐨勬搷浣溿 + * + * 鍙傛暟鍒楄〃锛 + * baseDesc锛歍rObjDesc缁撴瀯锛岃〃绀哄璞℃弿杩颁俊鎭殑鍩烘湰缁撴瀯銆 + * object锛歄bjectAddress缁撴瀯锛岃〃绀哄璞$殑鍦板潃淇℃伅銆 + */ +static void TrDoDropDataSource(TrObjDesc *baseDesc, ObjectAddress *object) +{ + if (TrNeedLogicDrop(object)) { // 濡傛灉闇瑕侀昏緫鍒犻櫎 + TrRenameCommon(baseDesc, object, DataSourceRelationId, Natts_pg_extension_data_source, + Anum_pg_extension_data_source_srcname, DataSourceOidIndexId, "extension data source"); // 閲嶅懡鍚 + } else { + RemoveDataSourceById(object->objectId); // 鐩存帴鍒犻櫎鎵╁睍鏁版嵁婧 + } + + return; +} + + +/* + * 鍔熻兘锛氭墽琛屽垹闄ょ洰褰曠殑鎿嶄綔銆 + * + * 鍙傛暟鍒楄〃锛 + * baseDesc锛歍rObjDesc缁撴瀯锛岃〃绀哄璞℃弿杩颁俊鎭殑鍩烘湰缁撴瀯銆 + * object锛歄bjectAddress缁撴瀯锛岃〃绀哄璞$殑鍦板潃淇℃伅銆 + */ +static void TrDoDropDirectory(TrObjDesc *baseDesc, ObjectAddress *object) +{ + if (TrNeedLogicDrop(object)) { // 濡傛灉闇瑕侀昏緫鍒犻櫎 + TrRenameCommon(baseDesc, object, PgDirectoryRelationId, Natts_pg_directory, Anum_pg_directory_directory_name, + PgDirectoryOidIndexId, "directory"); // 閲嶅懡鍚 + } else { + RemoveDirectoryById(object->objectId); // 鐩存帴鍒犻櫎鐩綍 + } + + return; +} + +/* + * 鍔熻兘锛氭墽琛屽垹闄よ绾у畨鍏ㄧ瓥鐣ョ殑鎿嶄綔銆 + * + * 鍙傛暟鍒楄〃锛 + * baseDesc锛歍rObjDesc缁撴瀯锛岃〃绀哄璞℃弿杩颁俊鎭殑鍩烘湰缁撴瀯銆 + * object锛歄bjectAddress缁撴瀯锛岃〃绀哄璞$殑鍦板潃淇℃伅銆 + */ +static void TrDoDropRlsPolicy(TrObjDesc *baseDesc, ObjectAddress *object) +{ + if (TrNeedLogicDrop(object)) { // 濡傛灉闇瑕侀昏緫鍒犻櫎 + TrRenameCommon(baseDesc, object, RlsPolicyRelationId, Natts_pg_rlspolicy, Anum_pg_rlspolicy_polname, + PgRlspolicyOidIndex, "rlspolicy"); // 閲嶅懡鍚 + } else { + RemoveRlsPolicyById(object->objectId); // 鐩存帴鍒犻櫎琛岀骇瀹夊叏绛栫暐 + } + + return; +} + +/* + * 鍔熻兘锛氭墽琛屽垹闄や綔涓氱殑鎿嶄綔銆 + * + * 鍙傛暟鍒楄〃锛 + * baseDesc锛歍rObjDesc缁撴瀯锛岃〃绀哄璞℃弿杩颁俊鎭殑鍩烘湰缁撴瀯銆 + * object锛歄bjectAddress缁撴瀯锛岃〃绀哄璞$殑鍦板潃淇℃伅銆 + */ +static void TrDoDropJob(TrObjDesc *baseDesc, ObjectAddress *object) +{ + if (TrNeedLogicDrop(object)) { + /* 鏃犻渶鎿嶄綔锛屽洜涓虹郴缁熺洰褰曚腑娌℃湁鍚嶇О灞炴с*/ + } else { + RemoveJobById(object->objectId); // 鐩存帴鍒犻櫎浣滀笟 + } + + return; +} + +/* + * 鍔熻兘锛氭墽琛屽垹闄ゅ悓涔夎瘝鐨勬搷浣溿 + * + * 鍙傛暟鍒楄〃锛 + * baseDesc锛歍rObjDesc缁撴瀯锛岃〃绀哄璞℃弿杩颁俊鎭殑鍩烘湰缁撴瀯銆 + * object锛歄bjectAddress缁撴瀯锛岃〃绀哄璞$殑鍦板潃淇℃伅銆 + */ +static void TrDoDropSynonym(TrObjDesc *baseDesc, ObjectAddress *object) +{ + if (TrNeedLogicDrop(object)) { // 濡傛灉闇瑕侀昏緫鍒犻櫎 + TrRenameCommon(baseDesc, object, PgSynonymRelationId, Natts_pg_synonym, Anum_pg_synonym_synname, + SynonymOidIndexId, "synonym"); // 閲嶅懡鍚 + } else { + RemoveSynonymById(object->objectId); // 鐩存帴鍒犻櫎鍚屼箟璇 + } + + return; +} + + +/* + * doDeletion: delete a single object + * return false if logic deleted, + * return true if physical deleted, + */ +/* + * 鍔熻兘锛氭墽琛屽垹闄ゅ璞$殑鎿嶄綔锛屾牴鎹璞$殑绫诲埆閫夋嫨鐩稿簲鐨勫垹闄ゅ嚱鏁般 + * + * 鍙傛暟鍒楄〃锛 + * baseDesc锛歍rObjDesc缁撴瀯锛岃〃绀哄璞℃弿杩颁俊鎭殑鍩烘湰缁撴瀯銆 + * object锛歄bjectAddress缁撴瀯锛岃〃绀哄璞$殑鍦板潃淇℃伅銆 + */ +static void TrDoDrop(TrObjDesc *baseDesc, ObjectAddress *object) +{ + switch (getObjectClass(object)) { + case OCLASS_CLASS: { + char relKind = get_rel_relkind(object->objectId); + if (relKind == RELKIND_INDEX) { + TrDoDropIndex(baseDesc, object);// 鍒犻櫎绱㈠紩 + } else { + /* + * We use a unified entry for others: + * RELKIND_RELATION, RELKIND_SEQUENCE, + * RELKIND_TOASTVALUE, RELKIND_VIEW, + * RELKIND_COMPOSITE_TYPE, RELKIND_FOREIGN_TABLE + */ + TrDoDropTable(baseDesc, object, relKind);// 鍒犻櫎琛 + } + break; + } + + case OCLASS_TYPE: + TrDoDropType(baseDesc, object); // 鍒犻櫎绫诲瀷 + break; + + case OCLASS_CONSTRAINT: + TrDoDropConstraint(baseDesc, object); // 鍒犻櫎绾︽潫 + break; + + case OCLASS_TRIGGER: + TrDoDropTrigger(baseDesc, object); // 鍒犻櫎瑙﹀彂鍣 + break; + + case OCLASS_REWRITE: + TrDoDropRewrite(baseDesc, object); // 鍒犻櫎瑙勫垯 + break; + + case OCLASS_DEFAULT: + TrDoDropAttrdef(baseDesc, object); // 鍒犻櫎榛樿鍊 + break; + + case OCLASS_PROC: + TrDoDropProc(baseDesc, object); // 鍒犻櫎鍑芥暟 + break; + + case OCLASS_CAST: + TrDoDropCast(baseDesc, object); // 鍒犻櫎杞崲 + break; + + case OCLASS_COLLATION: + TrDoDropCollation(baseDesc, object); // 鍒犻櫎鎺掑簭瑙勫垯 + break; + + case OCLASS_CONVERSION: + TrDoDropConversion(baseDesc, object); // 鍒犻櫎杞崲瑙勫垯 + break; + + case OCLASS_LANGUAGE: + TrDoDropProceduralLanguage(baseDesc, object); // 鍒犻櫎杩囩▼鍖栬瑷 + break; + + case OCLASS_LARGEOBJECT: + TrDoDropLargeObject(baseDesc, object); // 鍒犻櫎澶у璞 + break; + + case OCLASS_OPERATOR: + TrDoDropOperator(baseDesc, object); // 鍒犻櫎鎿嶄綔绗 + break; + + case OCLASS_OPCLASS: + TrDoDropOpClass(baseDesc, object); // 鍒犻櫎鎿嶄綔绗︾被 + break; + + case OCLASS_OPFAMILY: + TrDoDropOpFamily(baseDesc, object); // 鍒犻櫎鎿嶄綔绗︽棌 + break; + + case OCLASS_AMOP: + TrDoDropAmOp(baseDesc, object); // 鍒犻櫎鎿嶄綔绗︽槧灏 + break; + + case OCLASS_AMPROC: + TrDoDropAmProc(baseDesc, object); // 鍒犻櫎鎿嶄綔绗﹀鐞嗗嚱鏁 + break; + + case OCLASS_SCHEMA: + TrDoDropSchema(baseDesc, object); // 鍒犻櫎妯″紡 + break; + + case OCLASS_TSPARSER: + TrDoDropTSParser(baseDesc, object); // 鍒犻櫎鏂囨湰鎼滅储瑙f瀽鍣 + break; + + case OCLASS_TSDICT: + TrDoDropTSDictionary(baseDesc, object); // 鍒犻櫎鏂囨湰鎼滅储瀛楀吀 + break; + + case OCLASS_TSTEMPLATE: + TrDoDropTSTemplate(baseDesc, object); // 鍒犻櫎鏂囨湰鎼滅储妯℃澘 + break; + + case OCLASS_TSCONFIG: + TrDoDropTSConfiguration(baseDesc, object); // 鍒犻櫎鏂囨湰鎼滅储閰嶇疆 + break; + + /* + * OCLASS_ROLE, OCLASS_DATABASE, OCLASS_TBLSPACE intentionally not + * handled here + */ + + case OCLASS_FDW: + TrDoDropForeignDataWrapper(baseDesc, object); // 鍒犻櫎澶栭儴鏁版嵁灏佽鍣 + break; + + case OCLASS_FOREIGN_SERVER: + TrDoDropForeignServer(baseDesc, object); // 鍒犻櫎澶栭儴鏈嶅姟鍣 + break; + + case OCLASS_USER_MAPPING: + TrDoDropUserMapping(baseDesc, object); // 鍒犻櫎鐢ㄦ埛鏄犲皠 + break; + + case OCLASS_DEFACL: + TrDoDropDefaultACL(baseDesc, object); // 鍒犻櫎榛樿璁块棶鎺у埗 + break; + + case OCLASS_PGXC_CLASS: + TrDoDropPgxcClass(baseDesc, object); // 鍒犻櫎鍒嗗竷寮忕被 + break; + + case OCLASS_EXTENSION: + TrDoDropExtension(baseDesc, object); // 鍒犻櫎鎵╁睍 + break; + + case OCLASS_DATA_SOURCE: + TrDoDropDataSource(baseDesc, object); // 鍒犻櫎鏁版嵁婧 + break; + + case OCLASS_DIRECTORY: + TrDoDropDirectory(baseDesc, object); // 鍒犻櫎鐩綍 + break; + + case OCLASS_RLSPOLICY: + TrDoDropRlsPolicy(baseDesc, object); // 鍒犻櫎琛岀骇瀹夊叏绛栫暐 + break; + + case OCLASS_PG_JOB: + if ((IS_PGXC_COORDINATOR && !IsConnFromCoord()) || (g_instance.role == VSINGLENODE)) + TrDoDropJob(baseDesc, object); // 鍒犻櫎浣滀笟 + break; + + case OCLASS_SYNONYM: + TrDoDropSynonym(baseDesc, object); // 鍒犻櫎鍚屼箟璇 + break; + + default: + ereport(ERROR, + (errcode(ERRCODE_UNRECOGNIZED_NODE_TYPE), errmsg("unrecognized object class: %u", object->classId))); + break; + } + + return; +} + +/* + * deleteOneObject: delete a single object for TrDrop. + * + * *depRel is the already-open pg_depend relation. + */ +/* + * 鍔熻兘锛氬垹闄や竴涓璞★紝鍖呮嫭鍏朵緷璧栧叧绯荤瓑鎿嶄綔銆 + * + * 鍙傛暟鍒楄〃锛 + * baseDesc锛歍rObjDesc缁撴瀯锛岃〃绀哄璞℃弿杩颁俊鎭殑鍩烘湰缁撴瀯銆 + * object锛歄bjectAddress缁撴瀯锛岃〃绀哄璞$殑鍦板潃淇℃伅銆 + * depRel锛歊elation鎸囬拡锛岃〃绀轰緷璧栧叧绯荤殑绯荤粺琛ㄣ + */ +static void TrDropOneObject(TrObjDesc *baseDesc, ObjectAddress *object, Relation *depRel) +{ + ScanKeyData key[3]; + int nkeys; + SysScanDesc scan; + HeapTuple tup; + + /* DROP hook of the objects being removed */ + if (object_access_hook) { + ObjectAccessDrop dropArg; + + dropArg.dropflags = PERFORM_DELETION_INVALID; + InvokeObjectAccessHook(OAT_DROP, object->classId, object->objectId, object->objectSubId, &dropArg); + } + + /* + * Delete the object itself, in an object-type-dependent way. + * + * We used to do this after removing the outgoing dependency links, but it + * seems just as reasonable to do it beforehand. In the concurrent case + * we *must *do it in this order, because we can't make any transactional + * updates before calling doDeletion() --- they'd get committed right + * away, which is not cool if the deletion then fails. + */ + TrDoDrop(baseDesc, object); + + /* + * In logical drop mode, we will keep all related system entries, including + * linked entries such as pg_depend records. It is done! + */ + if (TrNeedLogicDrop(object)) { + /* + * CommandCounterIncrement here to ensure that preceding changes are all + * visible to the next deletion step. + */ + CommandCounterIncrement(); + + /* + * Logic Drop done! + */ + return; + } + + /* + * In physical drop mode, we continue to remove all related system entries. + */ + + /* + * Now remove any pg_depend records that link from this object to others. + * (Any records linking to this object should be gone already.) + * + * When dropping a whole object (subId = 0), remove all pg_depend records + * for its sub-objects too. + */ + ScanKeyInit(&key[0], Anum_pg_depend_classid, BTEqualStrategyNumber, F_OIDEQ, ObjectIdGetDatum(object->classId)); + ScanKeyInit(&key[1], Anum_pg_depend_objid, BTEqualStrategyNumber, F_OIDEQ, ObjectIdGetDatum(object->objectId)); + if (object->objectSubId != 0) { + ScanKeyInit(&key[2], Anum_pg_depend_objsubid, BTEqualStrategyNumber, F_INT4EQ, + Int32GetDatum(object->objectSubId)); + nkeys = 3; + } else + nkeys = 2; + + scan = systable_beginscan(*depRel, DependDependerIndexId, true, NULL, nkeys, key); + + while (HeapTupleIsValid(tup = systable_getnext(scan))) { + simple_heap_delete(*depRel, &tup->t_self); + } + + systable_endscan(scan); + + /* + * Delete shared dependency references related to this object. Again, if + * subId = 0, remove records for sub-objects too. + */ + deleteSharedDependencyRecordsFor(object->classId, object->objectId, object->objectSubId); + + /* + * Delete any comments or security labels associated with this object. + * (This is a convenient place to do these things, rather than having + * every object type know to do it.) + */ + DeleteComments(object->objectId, object->classId, object->objectSubId); + DeleteSecurityLabel(object); + + /* + * CommandCounterIncrement here to ensure that preceding changes are all + * visible to the next deletion step. + */ + CommandCounterIncrement(); + + /* + * Physical Drop done! + */ +} + +/* + * 鍔熻兘锛氬垽鏂粰瀹氱殑瀵硅薄鍦板潃鏄惁鍦ㄥ璞″湴鍧鍒楄〃涓 + * + * 鍙傛暟鍒楄〃锛 + * targetObjects锛歄bjectAddresses缁撴瀯鎸囬拡锛岃〃绀虹洰鏍囧璞″湴鍧鍒楄〃銆 + * thisobj锛歄bjectAddress缁撴瀯锛岃〃绀哄綋鍓嶅璞$殑鍦板潃銆 + */ +static bool TrObjIsInList(const ObjectAddresses *targetObjects, const ObjectAddress *thisobj) +{ + ObjectAddress *item = NULL; + + for (int i = 0; i < targetObjects->numrefs; i++) { + item = targetObjects->refs + i; + if (TrObjIsEqual(thisobj, item)) { + return true; + } + } + return false; +} + +/* + * 鍔熻兘锛氬湪鐩爣瀵硅薄鍦板潃鍒楄〃涓煡鎵剧粰瀹氬璞$殑绱㈠紩銆 + * + * 鍙傛暟鍒楄〃锛 + * targetObjects锛歄bjectAddresses缁撴瀯鎸囬拡锛岃〃绀虹洰鏍囧璞″湴鍧鍒楄〃銆 + * item锛歄bjectAddress缁撴瀯锛岃〃绀哄緟鏌ユ壘鐨勫璞″湴鍧銆 + */ +static ObjectAddress *TrFindIdxInTarget(ObjectAddresses *targetObjects, ObjectAddress *item) +{ + ObjectAddress *thisobj = NULL; + + for (int i = 0; i < targetObjects->numrefs; i++) { + thisobj = targetObjects->refs + i; + if (TrObjIsEqual(item, thisobj)) { + return thisobj; + } + } + + return NULL; +} + + +/* + * output: refthisobjs + */ +/* + * 鍔熻兘锛氭煡鎵炬墍鏈夊紩鐢ㄧ粰瀹氬璞$殑渚濊禆瀵硅薄 + * + * 鍙傛暟鍒楄〃锛 + * depRel锛氫緷璧栧叧绯荤殑绯荤粺鐩綍琛ㄧ殑鍏崇郴鎻忚堪绗 + * refobj锛氱粰瀹氬璞$殑鍦板潃 + * refthisobjs锛氬瓨鍌ㄤ緷璧栧璞″湴鍧鐨勫璞″垪琛 + */ +static void TrFindAllSubObjs(Relation depRel, const ObjectAddress *refobj, ObjectAddresses *refthisobjs) +{ + SysScanDesc sd; + HeapTuple tuple; + ScanKeyData key[3]; + int nkeys; + // 鍒濆鍖栨壂鎻忛敭鏁扮粍锛岃缃潯浠剁敤浜庡尮閰嶅紩鐢ㄥ璞$殑绫诲拰ID + ScanKeyInit(&key[0], Anum_pg_depend_refclassid, BTEqualStrategyNumber, F_OIDEQ, ObjectIdGetDatum(refobj->classId)); + ScanKeyInit(&key[1], Anum_pg_depend_refobjid, BTEqualStrategyNumber, F_OIDEQ, ObjectIdGetDatum(refobj->objectId)); + nkeys = 2; + // 濡傛灉寮曠敤瀵硅薄鏈夊瓙ID锛屽垯璁剧疆绗笁涓潯浠 + if (refobj->objectSubId != 0) { + ScanKeyInit(&key[2], Anum_pg_depend_refobjsubid, BTEqualStrategyNumber, F_INT4EQ, + Int32GetDatum(refobj->objectSubId)); + nkeys = 3; + } + + // 浣跨敤鏉′欢鍒濆鍖栨壂鎻忓櫒 + sd = systable_beginscan(depRel, DependReferenceIndexId, true, NULL, nkeys, key); + // 寰幆閬嶅巻婊¤冻鏉′欢鐨勫厓缁 + while (HeapTupleIsValid(tuple = systable_getnext(sd))) { + // 鑾峰彇鍏冪粍涓殑Form_pg_depend鏁版嵁 + Form_pg_depend depForm = (Form_pg_depend)GETSTRUCT(tuple); + + /* add the refs to list */ + add_object_address_ext(depForm->classid, depForm->objid, depForm->objsubid, depForm->deptype, refthisobjs); + } + + systable_endscan(sd);// 缁撴潫鎵弿 + return; +} +/* + * 鍔熻兘锛氭爣璁扮墿鐞嗗垹闄ゆā寮忎笅鐨勬墍鏈夊瓙瀵硅薄锛屽皢鍏舵坊鍔犲埌寰呭垹闄ゅ垪琛ㄤ腑 + * + * 鍙傛暟鍒楄〃锛 + * depRel锛氫緷璧栧叧绯荤殑绯荤粺鐩綍琛ㄧ殑鍏崇郴鎻忚堪绗 + * targetObjects锛氬緟鍒犻櫎瀵硅薄鍒楄〃 + * thisobj锛氬綋鍓嶅璞$殑鍦板潃 + */ +static void TrTagPhyDeleteSubObjs(Relation depRel, ObjectAddresses *targetObjects, ObjectAddress *thisobj) +{ + ObjectAddress *item = NULL; + // 鍒涘缓涓涓敤浜庡瓨鍌ㄤ緷璧栧璞″湴鍧鐨勫璞″垪琛 + ObjectAddresses *refthisobjs = new_object_addresses(); + + /* Tag this obj RB_DROP_MODE_PHYSICAL */ + thisobj->rbDropMode = RB_DROP_MODE_PHYSICAL; + + /* Find all sub objs refered to this obj */ + TrFindAllSubObjs(depRel, thisobj, refthisobjs); + // 閬嶅巻寮曠敤瀵硅薄鍒楄〃锛屽皢婊¤冻鏉′欢鐨勫璞℃爣璁颁负鐗╃悊鍒犻櫎妯″紡 + for (int i = 0; i < refthisobjs->numrefs; i++) { + item = refthisobjs->refs + i; + + /* the item must exists in targetObjects. */ + item = TrFindIdxInTarget(targetObjects, item); + if (item == NULL || item->rbDropMode == RB_DROP_MODE_PHYSICAL) { + continue; + } + // 閫掑綊鏍囪婊¤冻鏉′欢鐨勫瓙瀵硅薄 + TrTagPhyDeleteSubObjs(depRel, targetObjects, item); + } + // 閲婃斁鐢ㄤ簬瀛樺偍渚濊禆瀵硅薄鍦板潃鐨勫璞″垪琛 + free_object_addresses(refthisobjs); + return; +} +/* + * 鍔熻兘锛氭鏌ユ槸鍚﹂渶瑕佽繘琛岀墿鐞嗗垹闄ゆ搷浣 + * + * 鍙傛暟鍒楄〃锛 + * depRel锛氫緷璧栧叧绯荤殑绯荤粺鐩綍琛ㄧ殑鍏崇郴鎻忚堪绗 + * targetObjects锛氬緟鍒犻櫎瀵硅薄鍒楄〃 + * thisobj锛氬綋鍓嶅璞$殑鍦板潃 + */ +static bool TrNeedPhyDelete(Relation depRel, ObjectAddresses *targetObjects, ObjectAddress *thisobj) +{ + ObjectAddress *item = NULL; + // 鍒涘缓涓涓敤浜庡瓨鍌ㄥ紩鐢ㄥ璞″湴鍧鐨勫璞″垪琛 + ObjectAddresses *refobjs = new_object_addresses(); + bool result = false; + + /* Find all objs this obj refered */ + TrFindAllRefObjs(depRel, thisobj, refobjs); + + /* Step 1: tag refobjs of thisobj, return directly if ALL refobjs not need physical drop. */ + for (int i = 0; i < refobjs->numrefs; i++) { + item = refobjs->refs + i; + if (!TrObjIsInList(targetObjects, item)) { + result = true; + break; + } + } + if (!result) { + free_object_addresses(refobjs); + return result; + } + + /* Step 2: tag refobjs with 'i' deptype to physical drop. */ + for (int i = 0; i < refobjs->numrefs; i++) { + item = refobjs->refs + i; + if (item->deptype == 'i') { + item = TrFindIdxInTarget(targetObjects, item); + Assert(item != NULL); + if (item->rbDropMode == RB_DROP_MODE_PHYSICAL) { + continue; + } + // 鏍囪琚紩鐢ㄥ璞″強鍏跺瓙瀵硅薄涓虹墿鐞嗗垹闄ゆā寮 + TrTagPhyDeleteSubObjs(depRel, targetObjects, item); + } + } + // 閲婃斁鐢ㄤ簬瀛樺偍寮曠敤瀵硅薄鍦板潃鐨勫璞″垪琛 + free_object_addresses(refobjs); + return result; +} +/* + * 鍔熻兘閲嶇疆寰呭垹闄ゅ璞$殑鍒犻櫎妯″紡 + * + * 鍙傛暟鍒楄〃锛 + * targetObjects锛氬緟鍒犻櫎瀵硅薄鍒楄〃 + * baseObj锛氬熀纭瀵硅薄鐨勫湴鍧 + */ +static void TrResetDropMode(const ObjectAddresses *targetObjects, const ObjectAddress *baseObj) +{ + ObjectAddress *thisobj = NULL; + + for (int i = 0; i < targetObjects->numrefs; i++) { + thisobj = targetObjects->refs + i; + if (TrObjIsEqual(thisobj, baseObj)) { + // 灏嗗熀纭瀵硅薄鐨勫垹闄ゆā寮忛噸缃负閫昏緫鍒犻櫎 + thisobj->rbDropMode = RB_DROP_MODE_LOGIC; + continue; + } + // 灏嗗叾浠栧璞$殑鍒犻櫎妯″紡閲嶇疆涓烘棤鏁 + thisobj->rbDropMode = RB_DROP_MODE_INVALID; + } + return; +} + + +/* + * 鍔熻兘锛氭爣璁颁緷璧栧璞$殑鍒犻櫎妯″紡 + * + * 鍙傛暟鍒楄〃锛 + * depRel锛氫緷璧栧叧绯诲叧绯 + * targetObjects锛氬緟鍒犻櫎瀵硅薄鍒楄〃 + * baseObj锛氬熀纭瀵硅薄鐨勫湴鍧 + */ +static void TrTagDependentObjects(Relation depRel, ObjectAddresses *targetObjects, const ObjectAddress *baseObj) +{ + ObjectAddress *thisobj = NULL; + + // 閲嶇疆寰呭垹闄ゅ璞$殑鍒犻櫎妯″紡 + TrResetDropMode(targetObjects, baseObj); + + for (int i = 0; i < targetObjects->numrefs; i++) { + thisobj = targetObjects->refs + i; + + // 濡傛灉瀵硅薄鐨勫垹闄ゆā寮忓凡缁忚缃紝鍒欒烦杩 + if (TrDropModeIsAlreadySet(thisobj)) { + continue; + } + + // 濡傛灉闇瑕佽繘琛岀墿鐞嗗垹闄 + if (TrNeedPhyDelete(depRel, targetObjects, thisobj)) { + // 鏍囪鎵鏈変緷璧栦簬姝ゅ璞$殑瀛愬璞′负鐗╃悊鍒犻櫎 + TrTagPhyDeleteSubObjs(depRel, targetObjects, thisobj); + } else { + // 鍚﹀垯灏嗗璞$殑鍒犻櫎妯″紡璁剧疆涓洪昏緫鍒犻櫎 + thisobj->rbDropMode = RB_DROP_MODE_LOGIC; + } + } + + return; +} + + +/* + * 鍔熻兘锛氭鏌ユ槸鍚﹀彲浠ヨ繘琛孯ecyclebin-based-Drop鎿嶄綔 + * + * 鍙傛暟鍒楄〃锛 + * stmt锛氬垹闄よ鍙 + * objects锛氬緟鍒犻櫎瀵硅薄鍒楄〃 + */ +bool TrCheckRecyclebinDrop(const DropStmt *stmt, ObjectAddresses *objects) +{ + Relation depRel; + bool rbDrop = false; + + /* 濡傛灉娌℃湁寰呭垹闄ゅ璞★紝鍒欎笉闇瑕佹搷浣 */ + if (objects->numrefs <= 0) + return false; + + /* 妫鏌ユ槸鍚︽弧瓒砇ecyclebin-based-Drop鏉′欢 */ + if (/* + * 褰撶洰鏍囧璞′笉鏄疧BJECT_TABLE鏃讹紝鎴栬 + */ + stmt->removeType != OBJECT_TABLE || + /* 鍦ㄥ苟鍙戝垹闄ゆā寮忎笅锛屾垨鑰 */ + stmt->concurrent || + /* 浣跨敤浜唒urge閫夐」锛屾垨鑰 */ + stmt->purge || + /* 鍒犻櫎澶氫釜瀵硅薄鏃讹紝涓嶆敮鎸丷ecyclebin-based-Drop銆 */ + list_length(stmt->objects) != 1) { + return false; + } + + /* 濡傛灉涓嶉渶瑕丷ecyclebin鍔熻兘锛屽垯涓嶆敮鎸丷ecyclebin-based-Drop */ + if (!NeedTrComm(objects->refs->objectId)) { + return false; + } + + /* 鎵撳紑渚濊禆鍏崇郴鍏崇郴琛紝杩涜妫鏌 */ + depRel = heap_open(DependRelationId, AccessShareLock); + rbDrop = !TrNeedPhyDelete(depRel, objects, &objects->refs[0]); + heap_close(depRel, AccessShareLock); + + return rbDrop; +} +/* + * 鍔熻兘锛氭墽琛屽垹闄ゆ搷浣滐紝鏀寔閫昏緫鍒犻櫎鍜岀墿鐞嗗垹闄 + * + * 鍙傛暟鍒楄〃锛 + * drop锛氬垹闄よ鍙 + * objects锛氬緟鍒犻櫎瀵硅薄鍒楄〃 + * behavior锛氬垹闄よ涓 + */ +void TrDrop(const DropStmt* drop, const ObjectAddresses *objects, DropBehavior behavior) +{ + Relation depRel; + Relation baseRel; + TrObjDesc baseDesc; + ObjectAddresses *targetObjects = NULL; + ObjectAddress *baseObj = objects->refs; + + /* + * We save some cycles by opening pg_depend just once and passing the + * Relation pointer down to all the recursive deletion steps. + */ + depRel = heap_open(DependRelationId, RowExclusiveLock); + + /* + * Construct a list of objects to delete (ie, the given objects plus + * everything directly or indirectly dependent on them). Note that + * because we pass the whole objects list as pendingObjects context, we + * won't get a failure from trying to delete an object that is internally + * dependent on another one in the list; we'll just skip that object and + * delete it when we reach its owner. + */ + targetObjects = new_object_addresses(); + + /* + * Acquire deletion lock on each target object. (Ideally the caller + * has done this already, but many places are sloppy about it.) + */ + AcquireDeletionLock(baseObj, PERFORM_DELETION_INVALID); + + /* + * Finds all subobjects that reference the base table recursively. + */ + findDependentObjects(baseObj, DEPFLAG_ORIGINAL, NULL, /* empty stack */ + targetObjects, objects, &depRel); + ereport(LOG, (errmsg("Delete object %u/%u/%d", baseObj->classId, baseObj->objectId, baseObj->objectSubId))); + + /* + * Check if deletion is allowed, and report about cascaded deletes. + * + * If there's exactly one object being deleted, report it the same way as + * in performDeletion(), else we have to be vaguer. + */ + reportDependentObjects(targetObjects, behavior, NOTICE, baseObj); + + /* + * Tag all subobjects' drop mode: LOGIC_DROP, PYHSICAL_DROP. + */ + TrTagDependentObjects(depRel, targetObjects, baseObj); + + /* + * Initialize the baseDesc structure so that the logic dropped subobjects + * can be correctly processed when renamed or placed in recycle bin. Notice + * that base object already locked. + */ + baseRel = relation_open(baseObj->objectId, NoLock); + TrDescInit(baseRel, &baseDesc, RB_OPER_DROP, RB_OBJ_TABLE, true, true); + baseDesc.id = baseDesc.baseid = TrDescWrite(&baseDesc); + TrUpdateBaseid(&baseDesc); + relation_close(baseRel, NoLock); + + Oid relid = RelationGetRelid(baseRel); + UpdatePgObjectChangecsn(relid, baseRel->rd_rel->relkind); + + /* + * Drop all the objects in the proper order. + */ + for (int i = 0; i < targetObjects->numrefs; i++) { + ObjectAddress *thisobj = targetObjects->refs + i; + TrDropOneObject(&baseDesc, thisobj, &depRel); + } + + /* And clean up */ + free_object_addresses(targetObjects); + heap_close(depRel, RowExclusiveLock); +} +/* + * 鍔熻兘锛氭墽琛屽洖鏀剁珯涓殑瀵硅薄娓呴櫎鎿嶄綔 + * + * 鍙傛暟鍒楄〃锛 + * desc锛氬璞℃弿杩颁俊鎭 + */ +void TrDoPurgeObjectDrop(TrObjDesc *desc) +{ + ObjectAddresses *objects; // 瀛樺偍瀵硅薄鍦板潃鐨勭粨鏋勪綋锛岀敤浜庢壒閲忓垹闄 + ObjectAddress obj; // 瀵硅薄鍦板潃缁撴瀯浣擄紝鐢ㄤ簬琛ㄧず瀵硅薄鐨勫湴鍧 + + objects = new_object_addresses(); // 鍒涘缓瀵硅薄鍦板潃缁撴瀯浣撶殑瀹炰緥 + + obj.classId = RelationRelationId; // 璁剧疆瀵硅薄鍦板潃鐨勭被鍒獻D涓篟elationRelationId锛岃〃绀哄叧绯诲璞 + obj.objectId = desc->relid; // 璁剧疆瀵硅薄鍦板潃鐨勫璞D涓鸿鍒犻櫎瀵硅薄鐨勫叧绯籌D + obj.objectSubId = 0; // 璁剧疆瀵硅薄鍦板潃鐨勫瓙瀵硅薄ID涓0锛岃〃绀轰富瀵硅薄 + add_exact_object_address(&obj, objects); // 鍚戝璞″湴鍧缁撴瀯浣撴坊鍔犲璞″湴鍧 + + performMultipleDeletions(objects, DROP_CASCADE, PERFORM_DELETION_INVALID); // 鎵ц澶氫釜瀵硅薄鐨勭骇鑱斿垹闄ゆ搷浣 + + if (desc->type == RB_OBJ_TABLE) { // 濡傛灉琚垹闄ゅ璞℃槸琛ㄥ璞 + TrDeleteBaseid(desc->baseid); // 鍒犻櫎鍩虹ID + } else { /* RB_OBJ_INDEX */ + TrDeleteId(desc->id); // 鍒犻櫎ID + } + + free_object_addresses(objects); // 閲婃斁瀵硅薄鍦板潃缁撴瀯浣撶殑鍐呭瓨 + return; +} + +/* TIMECAPSULE TABLE { table_name } TO BEFORE DROP [RENAME TO new_tablename] */ +/* + * 鍔熻兘锛氳繕鍘熷洖鏀剁珯涓鍒犻櫎鐨勫璞 + * + * 鍙傛暟鍒楄〃锛 + * stmt锛氭椂闂磋兌鍥婅鍙 + */ +void TrRestoreDrop(const TimeCapsuleStmt *stmt) +{ + TrObjDesc desc; // 瀵硅薄鎻忚堪缁撴瀯浣擄紝鐢ㄤ簬淇濆瓨琚繕鍘熷璞$殑淇℃伅 + ObjectAddress obj; // 瀵硅薄鍦板潃缁撴瀯浣擄紝鐢ㄤ簬琛ㄧず瀵硅薄鐨勫湴鍧 + Relation rel; // 鏁版嵁搴撳叧绯诲璞★紝鐢ㄤ簬鎿嶄綔鏁版嵁搴撳叧绯 + + desc.relid = 0; // 鍒濆鍖栬杩樺師瀵硅薄鐨勫叧绯籌D涓0 + TrOperFetch(stmt->relation, RB_OBJ_TABLE, &desc, RB_OPER_RESTORE_DROP); // 鑾峰彇琚繕鍘熷璞$殑鎻忚堪淇℃伅 + if (desc.relid != 0 && (desc.type == RB_OBJ_TABLE)) { + stmt->relation->relname = desc.name; // 灏嗚杩樺師瀵硅薄鐨勫悕绉拌祴鍊肩粰鏃堕棿鑳跺泭璇彞鐨勫叧绯诲悕绉 + rel = heap_openrv(stmt->relation, AccessExclusiveLock); // 鎵撳紑鍏崇郴瀵硅薄浠ヨ繘琛屾搷浣 + if (rel->rd_tam_type == TAM_HEAP) { + heap_close(rel, NoLock); // 鍏抽棴鍏崇郴瀵硅薄 + elog(ERROR, "timecapsule does not support astore yet"); // 鎶ラ敊锛屾殏涓嶆敮鎸佽繕鍘熷瓨鍌ㄥ尯瀵硅薄 + return; + } + heap_close(rel, NoLock); // 鍏抽棴鍏崇郴瀵硅薄 + } + + desc.authid = GetUserId(); // 鑾峰彇褰撳墠鐢ㄦ埛鐨勬潈闄怚D + TrOperPrep(&desc, RB_OPER_RESTORE_DROP); // 鍑嗗杩樺師鎿嶄綔锛屾洿鏂版弿杩颁俊鎭 + + obj.classId = RelationRelationId; // 璁剧疆瀵硅薄鍦板潃鐨勭被鍒獻D涓篟elationRelationId锛岃〃绀哄叧绯诲璞 + obj.objectId = desc.relid; // 璁剧疆瀵硅薄鍦板潃鐨勫璞D涓鸿杩樺師瀵硅薄鐨勫叧绯籌D + obj.objectSubId = 0; // 璁剧疆瀵硅薄鍦板潃鐨勫瓙瀵硅薄ID涓0锛岃〃绀轰富瀵硅薄 + + TrRenameClass(&desc, &obj, stmt->new_relname ? stmt->new_relname : desc.originname); // 閲嶅懡鍚嶅璞 + + TrDeleteBaseid(desc.baseid); // 鍒犻櫎鍩虹ID锛屽嵆灏嗗璞′粠鍥炴敹绔欑Щ鍑 + + return; +} +>>>>>>> cb3246a73302b04edef5793406589f699676c34d diff --git a/src/gausskernel/storage/tcap/tcap_manager.cpp b/src/gausskernel/storage/tcap/tcap_manager.cpp index da0bee6fb..95f11b70d 100644 --- a/src/gausskernel/storage/tcap/tcap_manager.cpp +++ b/src/gausskernel/storage/tcap/tcap_manager.cpp @@ -1,3 +1,4 @@ +<<<<<<< HEAD /* * Copyright (c) Huawei Technologies Co., Ltd. 2020-2020. All rights reserved. * @@ -98,56 +99,74 @@ static bool TrIsRefRbObject(const ObjectAddress *obj, Relation depRel = NULL); void TrDoPurgeObjectDrop(TrObjDesc *desc); - +/* + * 鍔熻兘锛氱敓鎴愬懡鍚嶅璞$殑鍚嶇О锛屽苟灏嗙粨鏋滃瓨鍌ㄥ湪rbname鎸囧悜鐨勭紦鍐插尯涓 + * 鍙傛暟鍒楄〃锛 + * rbname锛氭寚鍚戝瓧绗︾紦鍐插尯鐨勬寚閽堬紝鐢ㄤ簬瀛樺偍鐢熸垚鐨勫璞″悕绉 + * classId锛氬璞$殑绫诲埆ID + * objid锛氬璞$殑ID + */ char *TrGenObjName(char *rbname, Oid classId, Oid objid) { - int rc = EOK; + int rc = EOK; // 澹版槑骞跺垵濮嬪寲涓涓暣鏁板彉閲弐c锛岀敤浜庡偍瀛樻墽琛岀殑缁撴灉 + // 浣跨敤snprintf_s鍑芥暟灏嗘牸寮忓寲鐨勫瓧绗︿覆鍐欏叆rbname缂撳啿鍖 + rc = snprintf_s(rbname, NAMEDATALEN, NAMEDATALEN - 1, "BIN$%X%X%X$%llX==$0", u_sess->proc_cxt.MyDatabaseId, classId, + objid, (uint64)GetXLogInsertRecPtr()); + securec_check_ss_c(rc, "\0", "\0"); // 妫鏌nprintf_s鍑芥暟鐨勬墽琛岀粨鏋滐紝纭繚娌℃湁閿欒鍙戠敓 - rc = snprintf_s(rbname, NAMEDATALEN, NAMEDATALEN - 1, "BIN$%X%X%X$%llX==$0", - u_sess->proc_cxt.MyDatabaseId, classId, objid, (uint64)GetXLogInsertRecPtr()); - securec_check_ss_c(rc, "\0", "\0"); - - return rbname; + return rbname; // 杩斿洖瀛樺偍瀵硅薄鍚嶇О鐨勭紦鍐插尯鐨勫湴鍧浣滀负鍑芥暟缁撴灉 } - +/* + * 鍔熻兘锛氫粠HeapTuple涓幏鍙栧洖鏀剁珯涓殑鍐荤粨浜嬪姟ID锛64浣嶏級锛屽苟杩斿洖璇D + * 鍙傛暟鍒楄〃锛 + * - rbtup锛氭寚鍚戝緟澶勭悊鐨凥eapTuple鐨勬寚閽 + * - rbRel锛歊ecycle Bin鍏崇郴鐨凴elation锛堝彲閫夊弬鏁帮級 + */ static TransactionId TrRbGetRcyfrozenxid64(HeapTuple rbtup, Relation rbRel = NULL) { - Datum datum; - bool isNull = false; - TransactionId rcyfrozenxid64; - bool relArgNull = rbRel == NULL; - + Datum datum; // 瀛樺偍灞炴у肩殑鏁版嵁绫诲瀷 + bool isNull = false; // 鏍囪瘑灞炴у兼槸鍚︿负NULL + TransactionId rcyfrozenxid64; // 瀛樺偍鍥炴敹绔欎腑鐨勫喕缁撲簨鍔D锛64浣嶏級 + bool relArgNull = rbRel == NULL; // 妫鏌bRel鏄惁涓篘ULL鐨勬爣蹇 + // 濡傛灉rbRel涓篘ULL锛屽垯鎵撳紑Recycle Bin鍏崇郴锛圧ecycle Bin琛級 if (relArgNull) { rbRel = heap_open(RecyclebinRelationId, AccessShareLock); } - + // 浠嶩eapTuple涓幏鍙杙g_recyclebin琛ㄤ腑rcyfrozenxid64灞炴х殑鍊 datum = heap_getattr(rbtup, Anum_pg_recyclebin_rcyfrozenxid64, RelationGetDescr(rbRel), &isNull); - Assert(!isNull); - + Assert(!isNull); // 鏂█灞炴у间笉搴斾负NULL + // 灏哾atum杞崲涓篢ransactionId绫诲瀷锛屽苟璧嬪肩粰rcyfrozenxid64 rcyfrozenxid64 = DatumGetTransactionId(datum); - + // 濡傛灉rbRel涓篘ULL锛屽垯鍏抽棴Recycle Bin鍏崇郴 if (relArgNull) { heap_close(rbRel, AccessShareLock); } - return rcyfrozenxid64; + return rcyfrozenxid64; // 杩斿洖鑾峰彇鐨勫喕缁撲簨鍔D锛64浣嶏級 } - -void TrDescInit(Relation rel, TrObjDesc *desc, TrObjOperType operType, - TrObjType objType, bool canpurge, bool isBaseObj) +/* + * 鍔熻兘锛氬垵濮嬪寲TrObjDesc缁撴瀯浣擄紝瀛樺偍鍏充簬瀵硅薄鐨勬弿杩颁俊鎭 + * 鍙傛暟鍒楄〃锛 + * rel锛氭寚鍚戠洰鏍囧叧绯荤殑Relation + * desc锛氭寚鍚慣rObjDesc缁撴瀯浣撶殑鎸囬拡锛岀敤浜庡瓨鍌ㄥ璞℃弿杩颁俊鎭 + * operType锛氭搷浣滅被鍨嬶紝琛ㄧず瀵硅薄鐨勬搷浣滐紙鍒涘缓銆佸垹闄ょ瓑锛 + * objType锛氬璞$被鍨嬶紝琛ㄧず瀵硅薄鐨勭被鍨嬶紙琛ㄣ佺储寮曠瓑锛 + * canpurge锛氭槸鍚﹀厑璁告竻闄ゅ璞℃爣蹇 + * isBaseObj锛氭槸鍚﹀熀鏈璞℃爣蹇 + */ +void TrDescInit(Relation rel, TrObjDesc *desc, TrObjOperType operType, TrObjType objType, bool canpurge, bool isBaseObj) { - errno_t rc = EOK; + errno_t rc = EOK; // 澹版槑骞跺垵濮嬪寲涓涓敊璇彿鍙橀噺rc锛岀敤浜庡瓨鍌ㄥ嚱鏁版墽琛岀殑缁撴灉 /* Notice: desc->id, desc->baseid will be assigned by invoker later. */ - desc->dbid = u_sess->proc_cxt.MyDatabaseId; - desc->relid = RelationGetRelid(rel); - + desc->dbid = u_sess->proc_cxt.MyDatabaseId; // 灏嗗綋鍓嶄細璇濇墍鍦ㄧ殑鏁版嵁搴揑D璧嬪肩粰desc->dbid + desc->relid = RelationGetRelid(rel); // 灏嗙洰鏍囧叧绯荤殑Relid璧嬪肩粰desc->relid + // 鐢熸垚瀵硅薄鐨勫悕绉帮紝瀛樺偍鍦╠esc->name涓 (void)TrGenObjName(desc->name, RelationRelationId, desc->relid); - - rc = strncpy_s(desc->originname, NAMEDATALEN, RelationGetRelationName(rel), - strlen(RelationGetRelationName(rel))); + // 灏嗙洰鏍囧叧绯荤殑鍚嶇О鎷疯礉鍒癲esc->originname涓 + rc = strncpy_s(desc->originname, NAMEDATALEN, RelationGetRelationName(rel), strlen(RelationGetRelationName(rel))); securec_check(rc, "\0", "\0"); - + // 鍒濆鍖栧璞℃弿杩扮殑鍚勪釜瀛楁 desc->operation = operType; desc->type = objType; desc->recyclecsn = t_thrd.xact_cxt.ShmemVariableCache->nextCommitSeqNo; @@ -163,26 +182,35 @@ void TrDescInit(Relation rel, TrObjDesc *desc, TrObjOperType operType, desc->canrestore = objType == RB_OBJ_TABLE; desc->canpurge = canpurge; } - -void TrPartDescInit(Relation rel, Partition part, TrObjDesc *desc, TrObjOperType operType, - TrObjType objType, bool canpurge, bool isBaseObj) +/* + * 鍔熻兘锛氬垵濮嬪寲TrObjDesc缁撴瀯浣擄紝瀛樺偍鍏充簬鍒嗗尯瀵硅薄鐨勬弿杩颁俊鎭 + * 鍙傛暟鍒楄〃锛 + * rel锛氭寚鍚戠埗鍏崇郴鐨凴elation + * part锛氭寚鍚戝垎鍖虹殑Partition + * desc锛氭寚鍚慣rObjDesc缁撴瀯浣撶殑鎸囬拡锛岀敤浜庡瓨鍌ㄥ璞℃弿杩颁俊鎭 + * operType锛氭搷浣滅被鍨嬶紝琛ㄧず瀵硅薄鐨勬搷浣滐紙鍒涘缓銆佸垹闄ょ瓑锛 + * objType锛氬璞$被鍨嬶紝琛ㄧず瀵硅薄鐨勭被鍨嬶紙琛ㄣ佺储寮曠瓑锛 + * canpurge锛氭槸鍚﹀厑璁告竻闄ゅ璞℃爣蹇 + * isBaseObj锛氭槸鍚﹀熀鏈璞℃爣蹇 + */ +void TrPartDescInit(Relation rel, Partition part, TrObjDesc *desc, TrObjOperType operType, TrObjType objType, + bool canpurge, bool isBaseObj) { - errno_t rc = EOK; + errno_t rc = EOK; // 澹版槑骞跺垵濮嬪寲涓涓敊璇彿鍙橀噺rc锛岀敤浜庡瓨鍌ㄥ嚱鏁版墽琛岀殑缁撴灉 /* Notice: desc->id, desc->baseid will be assigned by invoker later. */ - desc->dbid = u_sess->proc_cxt.MyDatabaseId; - desc->relid = part->pd_id; - + desc->dbid = u_sess->proc_cxt.MyDatabaseId; // 灏嗗綋鍓嶄細璇濇墍鍦ㄧ殑鏁版嵁搴揑D璧嬪肩粰desc->dbid + desc->relid = part->pd_id; // 灏嗗垎鍖虹殑pd_id璧嬪肩粰desc->relid + // 鐢熸垚瀵硅薄鐨勫悕绉帮紝瀛樺偍鍦╠esc->name涓 (void)TrGenObjName(desc->name, PartitionRelationId, desc->relid); - - rc = strncpy_s(desc->originname, NAMEDATALEN, RelationGetRelationName(rel), - strlen(RelationGetRelationName(rel))); + // 灏嗙埗鍏崇郴鐨勫悕绉板拰鍒嗗尯鐨勫悕绉拌繛鎺ヨ捣鏉ワ紝瀛樺偍鍦╠esc->originname涓 + rc = strncpy_s(desc->originname, NAMEDATALEN, RelationGetRelationName(rel), strlen(RelationGetRelationName(rel))); securec_check(rc, "\0", "\0"); - + int len = strlen(PartitionGetPartitionName(part)) + strlen(RelationGetRelationName(rel)) + 1; rc = strcat_s(desc->originname, len, PartitionGetPartitionName(part)); securec_check(rc, "\0", "\0"); - + // 鍒濆鍖栧璞℃弿杩扮殑鍚勪釜瀛楁 desc->operation = operType; desc->type = objType; desc->recyclecsn = t_thrd.xact_cxt.ShmemVariableCache->nextCommitSeqNo; @@ -198,34 +226,63 @@ void TrPartDescInit(Relation rel, Partition part, TrObjDesc *desc, TrObjOperType desc->canrestore = false; desc->canpurge = canpurge; } - +/* + * 鍔熻兘锛氫粠HeapTuple涓鍙栧苟濉厖瀵硅薄鎻忚堪淇℃伅鍒癟rObjDesc缁撴瀯浣 + * 鍙傛暟鍒楄〃锛 + * desc锛氭寚鍚慣rObjDesc缁撴瀯浣撶殑鎸囬拡锛岀敤浜庡瓨鍌ㄥ璞℃弿杩颁俊鎭 + * rbtup锛氭寚鍚慔eapTuple鐨勬寚閽堬紝琛ㄧず浠庡洖鏀剁珯鍏崇郴璇诲彇鐨勫厓缁 + */ static void TrDescRead(TrObjDesc *desc, HeapTuple rbtup) { Form_pg_recyclebin rbForm = (Form_pg_recyclebin)GETSTRUCT(rbtup); + // 浠嶩eapTuple涓幏鍙栧璞$殑Oid锛岃祴鍊肩粰desc->id desc->id = HeapTupleGetOid(rbtup); + // 浠嶩eapTuple涓幏鍙栧璞$殑鍩虹ID锛岃祴鍊肩粰desc->baseid desc->baseid = rbForm->rcybaseid; + // 浠嶩eapTuple涓幏鍙栧璞$殑鏁版嵁搴揑D锛岃祴鍊肩粰desc->dbid desc->dbid = rbForm->rcydbid; + // 浠嶩eapTuple涓幏鍙栧璞$殑鍏崇郴ID锛岃祴鍊肩粰desc->relid desc->relid = rbForm->rcyrelid; + // 浠嶩eapTuple涓幏鍙栧璞$殑鍚嶇О锛屾嫹璐濆埌desc->name (void)namestrcpy((Name)desc->name, NameStr(rbForm->rcyname)); + // 浠嶩eapTuple涓幏鍙栧璞$殑鍘熷鍚嶇О锛屾嫹璐濆埌desc->originname (void)namestrcpy((Name)desc->originname, NameStr(rbForm->rcyoriginname)); + // 鏍规嵁HeapTuple涓殑鎿嶄綔绫诲瀷鏍囧織锛岃缃甦esc->operation desc->operation = (rbForm->rcyoperation == 'd') ? RB_OPER_DROP : RB_OPER_TRUNCATE; + // 灏咹eapTuple涓殑瀵硅薄绫诲瀷杞崲涓篢rObjType锛岃祴鍊肩粰desc->type desc->type = (TrObjType)rbForm->rcytype; + // 浠嶩eapTuple涓幏鍙栧璞$殑鍥炴敹CSN锛岃祴鍊肩粰desc->recyclecsn desc->recyclecsn = rbForm->rcyrecyclecsn; + // 浠嶩eapTuple涓幏鍙栧璞$殑鍥炴敹鏃堕棿锛岃祴鍊肩粰desc->recycletime desc->recycletime = rbForm->rcyrecycletime; + // 浠嶩eapTuple涓幏鍙栧璞$殑鍒涘缓CSN锛岃祴鍊肩粰desc->createcsn desc->createcsn = rbForm->rcycreatecsn; + // 浠嶩eapTuple涓幏鍙栧璞$殑鍙樻洿CSN锛岃祴鍊肩粰desc->changecsn desc->changecsn = rbForm->rcychangecsn; + // 浠嶩eapTuple涓幏鍙栧璞$殑鍛藉悕绌洪棿锛岃祴鍊肩粰desc->nspace desc->nspace = rbForm->rcynamespace; + // 浠嶩eapTuple涓幏鍙栧璞$殑鍛藉悕绌洪棿锛岃祴鍊肩粰desc->nspace desc->owner = rbForm->rcyowner; + // 浠嶩eapTuple涓幏鍙栧璞$殑琛ㄧ┖闂达紝璧嬪肩粰desc->tablespace desc->tablespace = rbForm->rcytablespace; + // 浠嶩eapTuple涓幏鍙栧璞$殑鍏崇郴鏂囦欢鑺傜偣锛岃祴鍊肩粰desc->relfilenode desc->relfilenode = rbForm->rcyrelfilenode; + // 浠嶩eapTuple涓幏鍙栧璞$殑鍙仮澶嶆爣蹇楋紝璧嬪肩粰desc->canrestore desc->canrestore = rbForm->rcycanrestore; + // 浠嶩eapTuple涓幏鍙栧璞$殑鍙竻闄ゆ爣蹇楋紝璧嬪肩粰desc->canpurge desc->canpurge = rbForm->rcycanpurge; + // 浠嶩eapTuple涓幏鍙栧璞$殑鍐荤粨浜嬪姟ID锛岃祴鍊肩粰desc->frozenxid desc->frozenxid = rbForm->rcyfrozenxid; + // 璋冪敤TrRbGetRcyfrozenxid64鍑芥暟锛岃幏鍙64浣嶅喕缁撲簨鍔D锛岃祴鍊肩粰desc->frozenxid64 desc->frozenxid64 = TrRbGetRcyfrozenxid64(rbtup); } - +/* + * 鍔熻兘锛氬皢TrObjDesc缁撴瀯浣撲腑鐨勫璞℃弿杩颁俊鎭啓鍏ュ洖鏀剁珯鍏崇郴 + * 鍙傛暟鍒楄〃锛 + * desc锛氭寚鍚慣rObjDesc缁撴瀯浣撶殑鎸囬拡锛屽寘鍚鍐欏叆鍥炴敹绔欏叧绯荤殑瀵硅薄鎻忚堪淇℃伅 + */ Oid TrDescWrite(TrObjDesc *desc) { Relation rel; @@ -236,6 +293,7 @@ Oid TrDescWrite(TrObjDesc *desc) NameData originname; Oid rbid; + // 濉厖灞炴ф暟缁剉alues锛屽皢瀵硅薄鎻忚堪淇℃伅涓殑鍚勫睘鎬у艰祴鍊肩粰瀵瑰簲浣嶇疆 values[Anum_pg_recyclebin_rcydbid - 1] = ObjectIdGetDatum(desc->dbid); values[Anum_pg_recyclebin_rcybaseid - 1] = ObjectIdGetDatum(desc->baseid); values[Anum_pg_recyclebin_rcyrelid - 1] = ObjectIdGetDatum(desc->relid); @@ -258,66 +316,79 @@ Oid TrDescWrite(TrObjDesc *desc) values[Anum_pg_recyclebin_rcyfrozenxid - 1] = ShortTransactionIdGetDatum(desc->frozenxid); values[Anum_pg_recyclebin_rcyfrozenxid64 - 1] = TransactionIdGetDatum(desc->frozenxid64); - rel = heap_open(RecyclebinRelationId, RowExclusiveLock); - + rel = heap_open(RecyclebinRelationId, RowExclusiveLock); // 鎵撳紑鍥炴敹绔欏叧绯 + // 鍒涘缓涓涓柊鐨凥eapTuple锛屽~鍏呭睘鎬у煎拰null鏍囧織 tup = heap_form_tuple(RelationGetDescr(rel), values, nulls); - + // 鍦ㄥ叧绯讳腑鎻掑叆鏂扮殑鍏冪粍锛岃幏鍙栨柊鍏冪粍鐨勫璞D锛坮bid锛 rbid = simple_heap_insert(rel, tup); - + // 鏇存柊鍏崇郴鐨勭储寮 CatalogUpdateIndexes(rel, tup); - + // 閲婃斁HeapTuple heap_freetuple_ext(tup); - + // 鍏抽棴鍥炴敹绔欏叧绯 heap_close(rel, RowExclusiveLock); - + // 澧炲姞鍛戒护璁℃暟鍣紝浠ヤ繚璇佸厓鏁版嵁鐨勪竴鑷存 CommandCounterIncrement(); return rbid; } - -static bool TrFetchOrinameImpl(Oid nspId, const char *oriname, TrObjType type, - TrObjDesc *desc, TrOperMode operMode) +/* + * 鍔熻兘锛氬湪鍥炴敹绔欏叧绯讳腑鏍规嵁鍛藉悕绌洪棿銆佸師濮嬪悕绉般佺被鍨嬪拰鎿嶄綔妯″紡鎼滅储骞惰幏鍙栧璞℃弿杩颁俊鎭 + * 鍙傛暟鍒楄〃锛 + * nspId锛氬懡鍚嶇┖闂碔D锛屾寚瀹氳鎼滅储鐨勫懡鍚嶇┖闂 + * oriname锛氬璞$殑鍘熷鍚嶇О锛岃鎼滅储鐨勫璞″悕绉 + * type锛歍rObjType锛屾寚瀹氬璞$殑绫诲瀷 + * desc锛氭寚鍚慣rObjDesc缁撴瀯浣撶殑鎸囬拡锛岀敤浜庡瓨鍌ㄦ壘鍒扮殑瀵硅薄鎻忚堪淇℃伅 + * operMode锛歍rOperMode锛屾寚瀹氭搷浣滄ā寮忥紙杩樺師妯″紡锛 + */ +static bool TrFetchOrinameImpl(Oid nspId, const char *oriname, TrObjType type, TrObjDesc *desc, TrOperMode operMode) { Relation rbRel; SysScanDesc sd; ScanKeyData skey[3]; HeapTuple tup; bool found = false; - + // 濡傛灉鍛藉悕绌洪棿ID鏃犳晥锛岀洿鎺ヨ繑鍥瀎alse if (!OidIsValid(nspId)) { return false; } - + // 鎵撳紑鍥炴敹绔欏叧绯伙紝鑾峰彇鍏变韩閿 rbRel = heap_open(RecyclebinRelationId, AccessShareLock); - - ScanKeyInit(&skey[0], Anum_pg_recyclebin_rcynamespace, BTEqualStrategyNumber, - F_OIDEQ, ObjectIdGetDatum(nspId)); - ScanKeyInit(&skey[1], Anum_pg_recyclebin_rcydbid, BTEqualStrategyNumber, - F_OIDEQ, ObjectIdGetDatum(u_sess->proc_cxt.MyDatabaseId)); - ScanKeyInit(&skey[2], Anum_pg_recyclebin_rcyoriginname, BTEqualStrategyNumber, - F_NAMEEQ, CStringGetDatum(oriname)); - + // 鍒濆鍖栨壂鎻忛敭锛屾寜鐓у懡鍚嶇┖闂淬佹暟鎹簱ID鍜屽師濮嬪悕绉拌繘琛屾悳绱 + ScanKeyInit(&skey[0], Anum_pg_recyclebin_rcynamespace, BTEqualStrategyNumber, F_OIDEQ, ObjectIdGetDatum(nspId)); + ScanKeyInit(&skey[1], Anum_pg_recyclebin_rcydbid, BTEqualStrategyNumber, F_OIDEQ, + ObjectIdGetDatum(u_sess->proc_cxt.MyDatabaseId)); + ScanKeyInit(&skey[2], Anum_pg_recyclebin_rcyoriginname, BTEqualStrategyNumber, F_NAMEEQ, CStringGetDatum(oriname)); + // 寮濮嬫壂鎻忓洖鏀剁珯鍏崇郴锛屼娇鐢ㄩ瀹氫箟绱㈠紩鍜屾壂鎻忛敭 sd = systable_beginscan(rbRel, RecyclebinDbidNspOrinameIndexId, true, NULL, 3, skey); while ((tup = systable_getnext(sd)) != NULL) { Form_pg_recyclebin rbForm = (Form_pg_recyclebin)GETSTRUCT(tup); + // 妫鏌ュ璞$被鍨嬪拰鎿嶄綔妯″紡鏄惁鍖归厤 if ((rbForm->rcytype != type && rbForm->rcytype == RB_OBJ_TABLE) || (rbForm->rcytype != type && rbForm->rcytype == RB_OBJ_INDEX) || (operMode == RB_OPER_RESTORE_DROP && rbForm->rcyoperation != 'd') || (operMode == RB_OPER_RESTORE_TRUNCATE && rbForm->rcyoperation != 't')) { continue; } - + // 鎵惧埌鍖归厤鐨勫璞★紝璇诲彇瀵硅薄鎻忚堪淇℃伅骞舵爣璁颁负鎵惧埌 found = true; TrDescRead(desc, tup); break; } - + // 缁撴潫鎵弿骞跺叧闂洖鏀剁珯鍏崇郴 systable_endscan(sd); heap_close(rbRel, AccessShareLock); return found; } - +/* + * 鍔熻兘锛氬湪鍥炴敹绔欏叧绯讳腑鏍规嵁瀵硅薄鍚嶇О銆佺被鍨嬪拰鎿嶄綔妯″紡鎼滅储骞惰幏鍙栧璞℃弿杩颁俊鎭 + * 鍙傛暟鍒楄〃锛 + * rcyname锛氳鎼滅储鐨勫洖鏀剁珯瀵硅薄鐨勫悕绉 + * type锛歍rObjType锛屾寚瀹氬璞$殑绫诲瀷 + * desc锛氭寚鍚慣rObjDesc缁撴瀯浣撶殑鎸囬拡锛岀敤浜庡瓨鍌ㄦ壘鍒扮殑瀵硅薄鎻忚堪淇℃伅 + * operMode锛歍rOperMode锛屾寚瀹氭搷浣滄ā寮忥紙杩樺師妯″紡锛 + */ bool TrFetchName(const char *rcyname, TrObjType type, TrObjDesc *desc, TrOperMode operMode) { Relation rbRel; @@ -325,59 +396,74 @@ bool TrFetchName(const char *rcyname, TrObjType type, TrObjDesc *desc, TrOperMod ScanKeyData skey[1]; HeapTuple tup; bool found = false; - + // 鎵撳紑鍥炴敹绔欏叧绯伙紝鑾峰彇鍏变韩閿 rbRel = heap_open(RecyclebinRelationId, AccessShareLock); - - ScanKeyInit(&skey[0], Anum_pg_recyclebin_rcyname, BTEqualStrategyNumber, - F_NAMEEQ, CStringGetDatum(rcyname)); - + // 鍒濆鍖栨壂鎻忛敭锛屾寜鐓у璞″悕绉拌繘琛屾悳绱 + ScanKeyInit(&skey[0], Anum_pg_recyclebin_rcyname, BTEqualStrategyNumber, F_NAMEEQ, CStringGetDatum(rcyname)); + // 寮濮嬫壂鎻忓洖鏀剁珯鍏崇郴锛屼娇鐢ㄩ瀹氫箟绱㈠紩鍜屾壂鎻忛敭 sd = systable_beginscan(rbRel, RecyclebinNameIndexId, true, NULL, 1, skey); if ((tup = systable_getnext(sd)) != NULL) { Form_pg_recyclebin rbForm = (Form_pg_recyclebin)GETSTRUCT(tup); + // 妫鏌ュ璞$被鍨嬫槸鍚﹀尮閰 if ((rbForm->rcytype != type && rbForm->rcytype == RB_OBJ_TABLE) || (rbForm->rcytype != type && rbForm->rcytype == RB_OBJ_INDEX)) { - ereport(ERROR, - (errmsg("The recycle object \"%s\" type mismatched.", rcyname))); + ereport(ERROR, (errmsg("The recycle object \"%s\" type mismatched.", rcyname))); } + // 妫鏌ユ搷浣滄ā寮忔槸鍚﹀尮閰 if ((operMode == RB_OPER_RESTORE_DROP && rbForm->rcyoperation != 'd') || (operMode == RB_OPER_RESTORE_TRUNCATE && rbForm->rcyoperation != 't')) { - ereport(ERROR, - (errmsg("recycle object \"%s\" desired does not exist", rcyname))); + ereport(ERROR, (errmsg("recycle object \"%s\" desired does not exist", rcyname))); } - + // 鎵惧埌鍖归厤鐨勫璞★紝璇诲彇瀵硅薄鎻忚堪淇℃伅骞舵爣璁颁负鎵惧埌 found = true; TrDescRead(desc, tup); } - + // 缁撴潫鎵弿骞跺叧闂洖鏀剁珯鍏崇郴 systable_endscan(sd); heap_close(rbRel, AccessShareLock); return found; } - -static bool TrFetchOriname(const char *schemaname, const char *relname, TrObjType type, - TrObjDesc *desc, TrOperMode operMode) +/* + * 鍔熻兘锛氬湪鍥炴敹绔欏叧绯讳腑鏍规嵁妯″紡鍚嶇О銆佸璞″悕绉般佺被鍨嬪拰鎿嶄綔妯″紡鎼滅储骞惰幏鍙栧璞℃弿杩颁俊鎭 + * 鍙傛暟鍒楄〃锛 + * schemaname锛氭ā寮忓悕绉帮紝鍙夌殑鍛藉悕绌洪棿鍚嶇О + * relname锛氳鎼滅储鐨勫洖鏀剁珯瀵硅薄鐨勫悕绉 + * type锛歍rObjType锛屾寚瀹氬璞$殑绫诲瀷 + * desc锛氭寚鍚慣rObjDesc缁撴瀯浣撶殑鎸囬拡锛岀敤浜庡瓨鍌ㄦ壘鍒扮殑瀵硅薄鎻忚堪淇℃伅 + * operMode锛歍rOperMode锛屾寚瀹氭搷浣滄ā寮忥紙杩樺師妯″紡锛 + */ +static bool TrFetchOriname(const char *schemaname, const char *relname, TrObjType type, TrObjDesc *desc, + TrOperMode operMode) { bool found = false; Oid nspId; - + // 濡傛灉缁欏畾浜嗘ā寮忓悕绉 if (schemaname) { + // 鑾峰彇妯″紡鐨勫懡鍚嶇┖闂碔D nspId = get_namespace_oid(schemaname, true); + // 璋冪敤TrFetchOrinameImpl鍑芥暟杩涜鎼滅储 found = TrFetchOrinameImpl(nspId, relname, type, desc, operMode); } else { List *activeSearchPath = NIL; ListCell *l = NULL; + // 閲嶆柊璁$畻鍛藉悕绌洪棿鎼滅储璺緞 recomputeNamespacePath(); + // 澶嶅埗褰撳墠鐨勫懡鍚嶇┖闂存悳绱㈣矾寰 activeSearchPath = list_copy(u_sess->catalog_cxt.activeSearchPath); + // 閬嶅巻鍛藉悕绌洪棿鎼滅储璺緞 foreach (l, activeSearchPath) { nspId = lfirst_oid(l); + // 璋冪敤TrFetchOrinameImpl鍑芥暟杩涜鎼滅储锛屽鏋滄壘鍒板垯鏍囪涓烘壘鍒板苟閫鍑哄惊鐜 if (TrFetchOrinameImpl(nspId, relname, type, desc, operMode)) { found = true; break; } } + // 閲婃斁鍛藉悕绌洪棿鎼滅储璺緞鍒楄〃 list_free_ext(activeSearchPath); + // 濡傛灉鍦ㄥ綋鍓嶆悳绱㈣矾寰勪腑鏈壘鍒帮紝鍒欏湪PG_TOAST鍛藉悕绌洪棿涓悳绱 if (!found) { nspId = PG_TOAST_NAMESPACE; found = TrFetchOrinameImpl(nspId, relname, type, desc, operMode); @@ -386,45 +472,62 @@ static bool TrFetchOriname(const char *schemaname, const char *relname, TrObjTyp return found; } - +/* + * 鍔熻兘锛氭洿鏂板洖鏀剁珯鍏崇郴涓寚瀹氬璞$殑baseid瀛楁 + * 鍙傛暟鍒楄〃锛 + * desc锛氭寚鍚慣rObjDesc缁撴瀯浣撶殑鎸囬拡锛屽寘鍚緟鏇存柊瀵硅薄鐨勬弿杩颁俊鎭 + */ void TrUpdateBaseid(const TrObjDesc *desc) { + // 澹版槑鍥炴敹绔欏叧绯 Relation rbRel; + // 澹版槑绯荤粺鎵弿鎻忚堪绗 SysScanDesc sd; + // 澹版槑鎵弿閿暟缁勶紝鐢ㄤ簬鏋勫缓鎵弿鏉′欢 ScanKeyData skey[1]; + // 澹版槑鍘熷鐨勫爢鍏冪粍 HeapTuple tup; + // 澹版槑鐢ㄤ簬鏇存柊鐨勬柊鍫嗗厓缁 HeapTuple newtup; - Datum values[Natts_pg_recyclebin] = { 0 }; - bool nulls[Natts_pg_recyclebin] = { false }; - bool replaces[Natts_pg_recyclebin] = { false }; - + // 澹版槑鍊兼暟缁勶紝鐢ㄤ簬瀛樺偍寰呮洿鏂扮殑瀛楁鍊 + Datum values[Natts_pg_recyclebin] = {0}; + // 澹版槑绌哄兼暟缁勶紝鏍囪瘑瀛楁鏄惁涓虹┖ + bool nulls[Natts_pg_recyclebin] = {false}; + // 澹版槑鏇挎崲鏍囧織鏁扮粍锛屾爣璇嗘槸鍚﹁鏇挎崲瀵瑰簲瀛楁 + bool replaces[Natts_pg_recyclebin] = {false}; + // 鎵撳紑鍥炴敹绔欏叧绯伙紝鑾峰彇琛岀嫭鍗犻攣 rbRel = heap_open(RecyclebinRelationId, RowExclusiveLock); - - ScanKeyInit(&skey[0], ObjectIdAttributeNumber, BTEqualStrategyNumber, - F_OIDEQ, ObjectIdGetDatum(desc->id)); - + // 鍒濆鍖栨壂鎻忛敭锛屾寜鐓у璞$殑id杩涜鎼滅储 + ScanKeyInit(&skey[0], ObjectIdAttributeNumber, BTEqualStrategyNumber, F_OIDEQ, ObjectIdGetDatum(desc->id)); + // 寮濮嬫壂鎻忓洖鏀剁珯鍏崇郴锛屼娇鐢ㄩ瀹氫箟绱㈠紩鍜屾壂鎻忛敭 sd = systable_beginscan(rbRel, RecyclebinIdIndexId, true, NULL, 1, skey); if ((tup = systable_getnext(sd)) == NULL) { + // 濡傛灉鏈壘鍒板尮閰嶇殑瀵硅薄锛屾姤鍛婇敊璇 ereport(ERROR, (errmsg("recycle object %u does not exist", desc->id))); } - + // 鍑嗗鏇存柊瀛楁鐨勫煎拰鏍囧織 replaces[Anum_pg_recyclebin_rcybaseid - 1] = true; values[Anum_pg_recyclebin_rcybaseid - 1] = ObjectIdGetDatum(desc->baseid); - + // 鏍规嵁鏂板煎垱寤烘柊鐨勫厓缁 newtup = heap_modify_tuple(tup, RelationGetDescr(rbRel), values, nulls, replaces); - + // 鎵ц鍏冪粍鏇存柊 simple_heap_update(rbRel, &newtup->t_self, newtup); - + // 鏇存柊绱㈠紩 CatalogUpdateIndexes(rbRel, newtup); - + // 閲婃斁鍐呭瓨 heap_freetuple_ext(newtup); - + // 缁撴潫鎵弿骞跺叧闂洖鏀剁珯鍏崇郴 systable_endscan(sd); heap_close(rbRel, RowExclusiveLock); return; } - +/* + * 鍔熻兘锛氬湪鍥炴敹绔欏璞′腑鍔犻攣鎸囧畾鐨勫叧绯伙紝骞舵鏌ュ叧绯绘槸鍚﹀瓨鍦 + * 鍙傛暟鍒楄〃锛 + * relid锛氳鍔犻攣鐨勫叧绯荤殑瀵硅薄ID + * type锛氬璞$殑绫诲瀷锛堣〃銆佺储寮曘佸垎鍖虹瓑锛 + */ static void TrLockRelationImpl(Oid relid, TrObjType type) { /* @@ -433,8 +536,7 @@ static void TrLockRelationImpl(Oid relid, TrObjType type) */ if (!ConditionalLockRelationOid(relid, AccessExclusiveLock)) { ereport(ERROR, - (errcode(ERRCODE_RBIN_LOCK_NOT_AVAILABLE), - errmsg("could not obtain lock on relation \"%u\"", relid))); + (errcode(ERRCODE_RBIN_LOCK_NOT_AVAILABLE), errmsg("could not obtain lock on relation \"%u\"", relid))); } /* @@ -445,18 +547,18 @@ static void TrLockRelationImpl(Oid relid, TrObjType type) if (!SearchSysCacheExists1(RELOID, ObjectIdGetDatum(relid)) && type != RB_OBJ_PARTITION) { /* Clean already held locks if error return. */ UnlockRelationOid(relid, AccessExclusiveLock); - ereport(ERROR, - (errcode(ERRCODE_RBIN_UNDEFINED_OBJECT), - errmsg("relation \"%u\" does not exist", relid))); + ereport(ERROR, (errcode(ERRCODE_RBIN_UNDEFINED_OBJECT), errmsg("relation \"%u\" does not exist", relid))); } else if (!SearchSysCacheExists1(PARTRELID, ObjectIdGetDatum(relid)) && type == RB_OBJ_PARTITION) { /* Clean already held locks if error return. */ UnlockRelationOid(relid, AccessExclusiveLock); - ereport(ERROR, - (errcode(ERRCODE_RBIN_UNDEFINED_OBJECT), - errmsg("partition \"%u\" does not exist", relid))); + ereport(ERROR, (errcode(ERRCODE_RBIN_UNDEFINED_OBJECT), errmsg("partition \"%u\" does not exist", relid))); } } - +/* + * 鍔熻兘锛氬鍥炴敹绔欏璞′腑鐨勫叧绯昏繘琛屽姞閿侊紝棣栧厛閿佸畾绱㈠紩鍏崇郴锛堝鏋滄湁锛夛紝鐒跺悗閿佸畾鍏崇郴鑷韩 + * 鍙傛暟鍒楄〃锛 + * desc锛氬洖鏀剁珯瀵硅薄鎻忚堪 + */ static void TrLockRelation(TrObjDesc *desc) { Oid heapOid = InvalidOid; @@ -466,8 +568,7 @@ static void TrLockRelation(TrObjDesc *desc) heapOid = IndexGetRelation(desc->relid, true); if (!OidIsValid(heapOid)) { ereport(ERROR, - (errcode(ERRCODE_RBIN_UNDEFINED_OBJECT), - errmsg("relation \"%u\" does not exist", desc->relid))); + (errcode(ERRCODE_RBIN_UNDEFINED_OBJECT), errmsg("relation \"%u\" does not exist", desc->relid))); } TrLockRelationImpl(heapOid, desc->type); } @@ -487,11 +588,15 @@ static void TrLockRelation(TrObjDesc *desc) } PG_END_TRY(); } - +/* + * 鍔熻兘锛氬鍥炴敹绔欎腑鐨勬寚瀹氬璞¤繘琛岃В閿 + * 鍙傛暟鍒楄〃锛 + * desc锛氬洖鏀剁珯瀵硅薄鎻忚堪 + */ static void TrUnlockTrItem(TrObjDesc *desc) { - UnlockDatabaseObject(RecyclebinRelationId, desc->id, 0, - AccessExclusiveLock); + // 瀵规寚瀹氱殑鍥炴敹绔欏璞¤繘琛岃В閿 + UnlockDatabaseObject(RecyclebinRelationId, desc->id, 0, AccessExclusiveLock); } static void TrLockTrItem(TrObjDesc *desc) @@ -503,9 +608,8 @@ static void TrLockTrItem(TrObjDesc *desc) /* 1. Try to lock rb item in AccessExclusiveLock */ if (!ConditionalLockDatabaseObject(RecyclebinRelationId, desc->id, 0, AccessExclusiveLock)) { - ereport(ERROR, - (errcode(ERRCODE_RBIN_LOCK_NOT_AVAILABLE), - errmsg("could not obtain lock on recycle object '%s'", desc->name))); + ereport(ERROR, (errcode(ERRCODE_RBIN_LOCK_NOT_AVAILABLE), + errmsg("could not obtain lock on recycle object '%s'", desc->name))); } /* @@ -516,8 +620,7 @@ static void TrLockTrItem(TrObjDesc *desc) rbRel = heap_open(RecyclebinRelationId, AccessShareLock); - ScanKeyInit(&skey[0], ObjectIdAttributeNumber, BTEqualStrategyNumber, - F_OIDEQ, ObjectIdGetDatum(desc->id)); + ScanKeyInit(&skey[0], ObjectIdAttributeNumber, BTEqualStrategyNumber, F_OIDEQ, ObjectIdGetDatum(desc->id)); sd = systable_beginscan(rbRel, RecyclebinIdIndexId, true, NULL, 1, skey); if ((tup = systable_getnext(sd)) == NULL) { @@ -525,8 +628,7 @@ static void TrLockTrItem(TrObjDesc *desc) systable_endscan(sd); heap_close(rbRel, AccessShareLock); ereport(ERROR, - (errcode(ERRCODE_RBIN_UNDEFINED_OBJECT), - errmsg("recycle object \"%s\" does not exist", desc->name))); + (errcode(ERRCODE_RBIN_UNDEFINED_OBJECT), errmsg("recycle object \"%s\" does not exist", desc->name))); } systable_endscan(sd); @@ -534,38 +636,44 @@ static void TrLockTrItem(TrObjDesc *desc) return; } - +/* + * 鍔熻兘锛氶獙璇佸洖鏀剁珯鎿嶄綔鏄惁鍖归厤瀵硅薄鐨勫睘鎬 + * + * 鍙傛暟鍒楄〃: + * desc锛氬洖鏀剁珯瀵硅薄鎻忚堪淇℃伅 + * operMode锛氭搷浣滄ā寮 + */ static void TrOperMatch(const TrObjDesc *desc, TrOperMode operMode) { switch (operMode) { case RB_OPER_PURGE: + /* 瀵硅薄涓嶅厑璁歌娓呴櫎涓斾笉鏄垎鍖哄璞★紝鎶ュ憡鏃犳硶娓呴櫎鐨勯敊璇 */ if (!desc->canpurge && desc->type != RB_OBJ_PARTITION) { - ereport(ERROR, - (errcode(ERRCODE_INVALID_OPERATION), - errmsg("recycle object \"%s\" cannot be purged", desc->name))); + ereport(ERROR, (errcode(ERRCODE_INVALID_OPERATION), + errmsg("recycle object \"%s\" cannot be purged", desc->name))); } break; case RB_OPER_RESTORE_DROP: + /* 瀵硅薄涓嶅厑璁歌鎭㈠涓斾笉鏄垎鍖哄璞★紝鎴栬呮搷浣滅被鍨嬩笉鏄疍ROP锛屾姤鍛婃棤娉曟仮澶嶇殑閿欒 */ if ((!desc->canrestore && desc->type != RB_OBJ_PARTITION) || desc->operation != RB_OPER_DROP) { - ereport(ERROR, - (errcode(ERRCODE_INVALID_OPERATION), - errmsg("recycle object \"%s\" cannot be restored", desc->name))); + ereport(ERROR, (errcode(ERRCODE_INVALID_OPERATION), + errmsg("recycle object \"%s\" cannot be restored", desc->name))); } break; case RB_OPER_RESTORE_TRUNCATE: + /* 瀵硅薄涓嶅厑璁歌鎭㈠涓斾笉鏄垎鍖哄璞★紝鎴栬呮搷浣滅被鍨嬩笉鏄疶RUNCATE锛屾姤鍛婃棤娉曟仮澶嶇殑閿欒 */ if ((!desc->canrestore && desc->type != RB_OBJ_PARTITION) || desc->operation != RB_OPER_TRUNCATE) { - ereport(ERROR, - (errcode(ERRCODE_INVALID_OPERATION), - errmsg("recycle object \"%s\" cannot be restored", desc->name))); + ereport(ERROR, (errcode(ERRCODE_INVALID_OPERATION), + errmsg("recycle object \"%s\" cannot be restored", desc->name))); } break; default: - ereport(ERROR, - (errcode(ERRCODE_UNRECOGNIZED_NODE_TYPE), - errmsg("unrecognized recyclebin operation: %u", operMode))); + /* 鏈煡鐨勫洖鏀剁珯鎿嶄綔绫诲瀷锛屾姤鍛婃棤娉曡瘑鍒殑閿欒 */ + ereport(ERROR, (errcode(ERRCODE_UNRECOGNIZED_NODE_TYPE), + errmsg("unrecognized recyclebin operation: %u", operMode))); break; } } @@ -574,6 +682,14 @@ static void TrOperMatch(const TrObjDesc *desc, TrOperMode operMode) * Fetch object from recycle bin for rb operations - purge, restore : * Prefer to fetch as original name, then recycle name. */ +/* + * 鍔熻兘锛 杩欎釜鍑芥暟鐢ㄤ簬浠庡洖鏀剁珯涓幏鍙栧璞$殑淇℃伅锛屽苟鍖归厤鎸囧畾鐨勬搷浣滄ā寮忋 + * 鍙傛暟鍒楄〃锛 + * purobj锛歊angeVar 绫诲瀷鐨勫璞★紝鍖呭惈瀵硅薄鐨勬ā寮忓悕鍜屽悕绉颁俊鎭 + * objtype锛歍rObjType 绫诲瀷锛岃〃绀哄璞$殑绫诲瀷銆 + * desc锛歍rObjDesc 绫诲瀷鐨勬寚閽堬紝鐢ㄤ簬瀛樺偍鑾峰彇鍒扮殑瀵硅薄鎻忚堪淇℃伅銆 + * operMode锛歍rOperMode 绫诲瀷锛岃〃绀烘搷浣滄ā寮忋 + */ void TrOperFetch(const RangeVar *purobj, TrObjType objtype, TrObjDesc *desc, TrOperMode operMode) { bool found = false; @@ -589,16 +705,21 @@ void TrOperFetch(const RangeVar *purobj, TrObjType objtype, TrObjDesc *desc, TrO /* not found, throw error */ if (!found) { - ereport(ERROR, - (errcode(ERRCODE_UNDEFINED_TABLE), - errmsg("recycle object \"%s\" desired does not exist", purobj->relname))); + ereport(ERROR, (errcode(ERRCODE_UNDEFINED_TABLE), + errmsg("recycle object \"%s\" desired does not exist", purobj->relname))); } TrOperMatch(desc, operMode); return; } - +/* + * 鍔熻兘锛氭仮澶嶅洖鏀剁珯瀵硅薄鏃剁殑鏉冮檺妫鏌 + * + * 鍙傛暟鍒楄〃: + * desc锛氬洖鏀剁珯瀵硅薄鎻忚堪淇℃伅 + * operMode锛氭搷浣滄ā寮 + */ static void TrPermRestore(TrObjDesc *desc, TrOperMode operMode) { AclResult aclCreateResult; @@ -609,7 +730,7 @@ static void TrPermRestore(TrObjDesc *desc, TrOperMode operMode) aclcheck_error(aclCreateResult, ACL_KIND_NAMESPACE, get_namespace_name(desc->nspace)); } - AclResult aclUsageResult = pg_namespace_aclcheck(desc->nspace, desc->authid, ACL_USAGE); + AclResult aclUsageResult = pg_namespace_aclcheck(desc->nspace, desc->authid, ACL_USAGE); if (aclUsageResult != ACLCHECK_OK) { aclcheck_error(aclUsageResult, ACL_KIND_NAMESPACE, get_namespace_name(desc->nspace)); } @@ -619,7 +740,7 @@ static void TrPermRestore(TrObjDesc *desc, TrOperMode operMode) aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_CLASS, desc->name); return; } - + /* 濡傛灉鎿嶄綔妯″紡鏄仮澶嶄负鎴柇锛屽垯妫鏌ヨ〃鎴柇鏉冮檺 */ if (operMode == RB_OPER_RESTORE_TRUNCATE) { AclResult aclTruncateResult = pg_class_aclcheck(desc->relid, desc->authid, ACL_TRUNCATE); if (aclTruncateResult != ACLCHECK_OK) { @@ -627,15 +748,21 @@ static void TrPermRestore(TrObjDesc *desc, TrOperMode operMode) } } } - +/* + * 鍔熻兘锛氶獙璇佸洖鏀剁珯娓呴櫎鎿嶄綔鐨勬潈闄 + * 鍙傛暟鍒楄〃: + * desc锛氬洖鏀剁珯瀵硅薄鎻忚堪淇℃伅 + * operMode锛氭搷浣滄ā寮 + */ static void TrPermPurge(TrObjDesc *desc, TrOperMode operMode) { AclResult result; - + /* 妫鏌ュ懡鍚嶇┖闂寸殑浣跨敤鏉冮檺 */ result = pg_namespace_aclcheck(desc->nspace, desc->authid, ACL_USAGE); if (result != ACLCHECK_OK) { aclcheck_error(result, ACL_KIND_NAMESPACE, get_namespace_name(desc->nspace)); } + /* 鍏佽娓呴櫎鐨勬潯浠讹細鏄〃鐨勬墍鏈夎呮垨鑰呮槸鍛藉悕绌洪棿鐨勬墍鏈夎 */ if (!pg_class_ownercheck(desc->relid, desc->authid) && !pg_namespace_ownercheck(desc->nspace, desc->authid)) { aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_CLASS, desc->name); } @@ -644,18 +771,23 @@ static void TrPermPurge(TrObjDesc *desc, TrOperMode operMode) /* * Check permission for rb operations - purge, restore */ +/* + * 鍔熻兘锛氶獙璇佸洖鏀剁珯鎿嶄綔鐨勬潈闄 + * 鍙傛暟鍒楄〃: + * desc锛氬洖鏀剁珯瀵硅薄鎻忚堪淇℃伅 + * operMode锛氭搷浣滄ā寮忥紙鎿嶄綔绫诲瀷锛 + */ static void TrPerm(TrObjDesc *desc, TrOperMode operMode) { switch (operMode) { case RB_OPER_RESTORE_DROP: case RB_OPER_RESTORE_TRUNCATE: - TrPermRestore(desc, operMode); + TrPermRestore(desc, operMode); // 璋冪敤 TrPermRestore 楠岃瘉鎭㈠鎿嶄綔鏉冮檺 break; case RB_OPER_PURGE: - TrPermPurge(desc, operMode); + TrPermPurge(desc, operMode); // 璋冪敤 TrPermPurge 楠岃瘉娓呴櫎鎿嶄綔鏉冮檺 break; default: - /* Never reached here. */ Assert(0); break; } @@ -665,6 +797,19 @@ static void TrPerm(TrObjDesc *desc, TrOperMode operMode) * Prepare for rb operations - purge, restore : * check permission, lock objects */ +/* + * TrOperPrep - 鍑嗗杩涜鍥炴敹鎿嶄綔 + * + * 姝ゅ嚱鏁扮敤浜庡噯澶囪繘琛屽洖鏀舵搷浣溿傚畠鎵ц浠ヤ笅姝ラ锛 + * 1. 妫鏌ユ潈闄愩 + * 2. 鑾峰彇鍥炴敹绔欐潯鐩殑閿侊紝浠ラ伩鍏嶅苟鍙戠殑娓呴櫎鍜屾仮澶嶆搷浣溿 + * 3. 鑾峰彇鍏崇郴鐨勯攣锛屼互閬垮厤骞跺彂鐨勬暟鎹煡璇㈡搷浣溿傛敞鎰忥細褰撹繘琛屾竻闄ゆ埅鏂叧绯绘搷浣滄椂锛屽拷鐣ユ姝ラ锛 + * 鍥犱负鍩虹鍏崇郴鍙兘涓嶅瓨鍦ㄣ + * + * 鍙傛暟鍒楄〃: + * desc: 鍥炴敹绔欏璞℃弿杩扮锛岀敤浜庤〃绀鸿杩涜鎿嶄綔鐨勫洖鏀剁珯瀵硅薄 + * operMode: 鍥炴敹鎿嶄綔鐨勬ā寮忥紝琛ㄧず鎵ц鐨勫叿浣撴搷浣滅被鍨 + */ void TrOperPrep(TrObjDesc *desc, TrOperMode operMode) { bool needLockRelation = false; @@ -699,7 +844,13 @@ void TrOperPrep(TrObjDesc *desc, TrOperMode operMode) PG_END_TRY(); } } - +/* + * 鍔熻兘锛氭牴鎹紶鍏ョ殑鍏崇郴ID锛坮elid锛夊垽鏂槸鍚﹀彲浠ュ璇ュ叧绯昏繘琛屽洖鏀舵搷浣溿 + * + * 鍙傛暟鍒楄〃: + * relid: 鍏崇郴ID + * + */ bool NeedTrComm(Oid relid) { Relation rel; @@ -750,87 +901,117 @@ bool NeedTrComm(Oid relid) RelationInClusterResizing(rel) || /* is in system namespace. */ (IsSystemNamespace(classForm->relnamespace) || IsToastNamespace(classForm->relnamespace) || - IsCStoreNamespace(classForm->relnamespace))) { - relation_close(rel, NoLock); + IsCStoreNamespace(classForm->relnamespace))) { + relation_close(rel, NoLock); // 鍏抽棴鍏崇郴 return false; } - relation_close(rel, NoLock); + relation_close(rel, NoLock); // 鍏抽棴鍏崇郴 return true; } - +/* + * 鍔熻兘锛氭鍑芥暟鏍规嵁浼犲叆鐨勫懡鍚嶇┖闂碔D鍜屽叧绯荤被鍨嬫爣璇嗭紝纭畾骞惰繑鍥炲搴旂殑鍥炴敹瀵硅薄绫诲瀷銆 + * + * 鍙傛暟鍒楄〃: + * nspId: 鍛藉悕绌洪棿ID锛岀敤浜庡垽鏂璞℃槸鍚﹀湪TOAST鍛藉悕绌洪棿 + * relKind: 鍏崇郴绫诲瀷鏍囪瘑锛岃〃绀哄璞$殑绫诲瀷 + */ TrObjType TrGetObjType(Oid nspId, char relKind) { + // 榛樿鍥炴敹瀵硅薄绫诲瀷涓鸿〃 RB_OBJ_TABLE TrObjType type = RB_OBJ_TABLE; - + // 鏍规嵁鍏崇郴绫诲瀷鏍囪瘑杩涜鍒ゆ柇骞惰缃搴旂殑鍥炴敹瀵硅薄绫诲瀷 switch (relKind) { case RELKIND_INDEX: + // 濡傛灉鏄储寮曞璞★紝鏍规嵁鏄惁鍦═OAST鍛藉悕绌洪棿鍒ゆ柇鏄疶OAST绱㈠紩杩樻槸鏅氱储寮 type = IsToastNamespace(nspId) ? RB_OBJ_TOAST_INDEX : RB_OBJ_INDEX; break; case RELKIND_RELATION: + // 濡傛灉鏄〃瀵硅薄锛岃缃负琛ㄧ被鍨 type = RB_OBJ_TABLE; break; case RELKIND_SEQUENCE: case RELKIND_LARGE_SEQUENCE: + // 濡傛灉鏄簭鍒楀璞★紝璁剧疆涓哄簭鍒楃被鍨 type = RB_OBJ_SEQUENCE; break; case RELKIND_TOASTVALUE: + // 濡傛灉鏄疶OAST鍊煎璞★紝璁剧疆涓篢OAST绫诲瀷 type = RB_OBJ_TOAST; break; case PARTTYPE_PARTITIONED_RELATION: + // 濡傛灉鏄垎鍖鸿〃瀵硅薄锛岃缃负鍒嗗尯琛ㄧ被鍨 type = RB_OBJ_PARTITION; break; case RELKIND_GLOBAL_INDEX: + // 濡傛灉鏄叏灞绱㈠紩瀵硅薄锛岃缃负鍏ㄥ眬绱㈠紩绫诲瀷 type = RB_OBJ_GLOBAL_INDEX; break; case RELKIND_MATVIEW: + // 濡傛灉鏄墿鍖栬鍥惧璞★紝璁剧疆涓虹墿鍖栬鍥剧被鍨 type = RB_OBJ_MATVIEW; break; default: /* Never reached here. */ + // 瀵逛簬鍏朵粬鏈煡鐨勫叧绯荤被鍨嬶紝鏂█鎶ラ敊锛屽洜涓轰笉搴旇鍒拌揪杩欎釜鍒嗘敮 Assert(0); break; } - + // 杩斿洖纭畾鐨勫洖鏀跺璞$被鍨 return type; } - +/* + * 鍔熻兘锛氱敤浜庢鏌ョ粰瀹氱殑瀵硅薄鍦板潃鏄惁瀛樺湪浜庣粰瀹氱殑瀵硅薄鍦板潃闆嗗悎涓 + * + * 鍙傛暟鍒楄〃: + * classid: 瀵硅薄鐨勭被鍒爣璇 + * objid: 瀵硅薄鐨勫敮涓鏍囪瘑 + * objSet: 瀵硅薄鍦板潃闆嗗悎锛屽寘鍚涓璞$殑鍦板潃淇℃伅 + */ static bool TrObjAddrExists(Oid classid, Oid objid, ObjectAddresses *objSet) { int i; - + // 閬嶅巻瀵硅薄鍦板潃闆嗗悎涓殑姣忎釜瀵硅薄鍦板潃 for (i = 0; i < objSet->numrefs; i++) { + // 濡傛灉缁欏畾鐨勫璞″湴鍧鍜岄泦鍚堜腑鐨勫璞″湴鍧鍖归厤锛岃繑鍥 true if (TrObjIsEqualEx(classid, objid, &objSet->refs[i])) { return true; } } - + // 鑻ラ亶鍘嗗畬鎵鏈夊璞″湴鍧浠嶆湭鎵惧埌鍖归厤椤癸紝杩斿洖 false return false; } /* * output: refobjs */ -void TrFindAllRefObjs(Relation depRel, const ObjectAddress *subobj, - ObjectAddresses *refobjs, bool ignoreObjSubId) +/* + * 鍔熻兘鐢ㄤ簬鏌ユ壘寮曠敤缁欏畾瀵硅薄鐨勬墍鏈夊叾浠栧璞★紝骞跺皢杩欎簺寮曠敤瀵硅薄鐨勫湴鍧娣诲姞鍒版寚瀹氱殑瀵硅薄鍦板潃闆嗗悎涓 + * + * 鍙傛暟鍒楄〃: + * depRel: 鐢ㄤ簬鎵弿渚濊禆鍏崇郴鐨勫叧绯诲璞 + * subobj: 琚紩鐢ㄥ璞$殑鍦板潃淇℃伅 + * refobjs: 瀛樺偍寮曠敤瀵硅薄鍦板潃鐨勫璞″湴鍧闆嗗悎 + * ignoreObjSubId: 鏄惁蹇界暐琚紩鐢ㄥ璞$殑瀛愭爣璇嗭紝榛樿涓 false + */ +void TrFindAllRefObjs(Relation depRel, const ObjectAddress *subobj, ObjectAddresses *refobjs, bool ignoreObjSubId) { SysScanDesc sd; HeapTuple tuple; ScanKeyData key[3]; int nkeys; - - ScanKeyInit(&key[0], Anum_pg_depend_classid, BTEqualStrategyNumber, F_OIDEQ, - ObjectIdGetDatum(subobj->classId)); - ScanKeyInit(&key[1], Anum_pg_depend_objid, BTEqualStrategyNumber, F_OIDEQ, - ObjectIdGetDatum(subobj->objectId)); + // 鍒濆鍖栫敤浜庢壂鎻忕殑閿 + ScanKeyInit(&key[0], Anum_pg_depend_classid, BTEqualStrategyNumber, F_OIDEQ, ObjectIdGetDatum(subobj->classId)); + ScanKeyInit(&key[1], Anum_pg_depend_objid, BTEqualStrategyNumber, F_OIDEQ, ObjectIdGetDatum(subobj->objectId)); nkeys = 2; + // 濡傛灉涓嶅拷鐣ュ璞$殑瀛愭爣璇嗕笖瀛愭爣璇嗕笉涓0锛屾坊鍔犵涓変釜閿 if (!ignoreObjSubId && subobj->objectSubId != 0) { ScanKeyInit(&key[2], Anum_pg_depend_objsubid, BTEqualStrategyNumber, F_INT4EQ, - Int32GetDatum(subobj->objectSubId)); + Int32GetDatum(subobj->objectSubId)); nkeys = 3; } - + // 寮濮嬫壂鎻忎緷璧栧叧绯 sd = systable_beginscan(depRel, DependDependerIndexId, true, NULL, nkeys, key); while (HeapTupleIsValid(tuple = systable_getnext(sd))) { Form_pg_depend depForm = (Form_pg_depend)GETSTRUCT(tuple); @@ -841,134 +1022,223 @@ void TrFindAllRefObjs(Relation depRel, const ObjectAddress *subobj, /* We keep `objSet` unique when `ignoreObjSubId = true` to avoid circle recursive. */ if (!ignoreObjSubId || !TrObjAddrExists(depForm->refclassid, depForm->refobjid, refobjs)) { - add_object_address_ext(depForm->refclassid, depForm->refobjid, - depForm->refobjsubid, depForm->deptype, refobjs); + add_object_address_ext(depForm->refclassid, depForm->refobjid, depForm->refobjsubid, depForm->deptype, + refobjs); } } - systable_endscan(sd); + systable_endscan(sd); // 缁撴潫鎵弿 return; } - -static void TrFindAllInternalObjs(Relation depRel, const ObjectAddress *refobj, - ObjectAddresses *objSet, bool ignoreObjSubId = false) +/* + * 鍔熻兘锛氱敤浜庢煡鎵惧紩鐢ㄧ粰瀹氬璞$殑鎵鏈夊唴閮ㄥ璞★紝骞跺皢杩欎簺鍐呴儴瀵硅薄鐨勫湴鍧娣诲姞鍒版寚瀹氱殑瀵硅薄鍦板潃闆嗗悎涓 + * + * 鍙傛暟鍒楄〃: + * depRel: 鐢ㄤ簬鎵弿渚濊禆鍏崇郴鐨勫叧绯诲璞 + * refobj: 琚紩鐢ㄥ璞$殑鍦板潃淇℃伅 + * objSet: 瀛樺偍鍐呴儴瀵硅薄鍦板潃鐨勫璞″湴鍧闆嗗悎 + * ignoreObjSubId: 鏄惁蹇界暐琚紩鐢ㄥ璞$殑瀛愭爣璇嗭紝榛樿涓 false + */ +static void TrFindAllInternalObjs(Relation depRel, const ObjectAddress *refobj, ObjectAddresses *objSet, + bool ignoreObjSubId = false) { SysScanDesc sd; HeapTuple tuple; ScanKeyData key[3]; int nkeys; - - ScanKeyInit(&key[0], Anum_pg_depend_refclassid, BTEqualStrategyNumber, F_OIDEQ, - ObjectIdGetDatum(refobj->classId)); - ScanKeyInit(&key[1], Anum_pg_depend_refobjid, BTEqualStrategyNumber, F_OIDEQ, - ObjectIdGetDatum(refobj->objectId)); + // 鍒濆鍖栫敤浜庢壂鎻忕殑閿 + ScanKeyInit(&key[0], Anum_pg_depend_refclassid, BTEqualStrategyNumber, F_OIDEQ, ObjectIdGetDatum(refobj->classId)); + ScanKeyInit(&key[1], Anum_pg_depend_refobjid, BTEqualStrategyNumber, F_OIDEQ, ObjectIdGetDatum(refobj->objectId)); nkeys = 2; + // 濡傛灉涓嶅拷鐣ュ璞$殑瀛愭爣璇嗕笖瀛愭爣璇嗕笉涓0锛屾坊鍔犵涓変釜閿 if (!ignoreObjSubId && refobj->objectSubId != 0) { ScanKeyInit(&key[2], Anum_pg_depend_refobjsubid, BTEqualStrategyNumber, F_INT4EQ, - Int32GetDatum(refobj->objectSubId)); + Int32GetDatum(refobj->objectSubId)); nkeys = 3; } - + // 寮濮嬫壂鎻忎緷璧栧叧绯 sd = systable_beginscan(depRel, DependReferenceIndexId, true, NULL, nkeys, key); while (HeapTupleIsValid(tuple = systable_getnext(sd))) { Form_pg_depend depForm = (Form_pg_depend)GETSTRUCT(tuple); + // 浠呭鐞 deptype 涓 'i' 鐨勫璞 if (depForm->deptype != 'i') { continue; } /* We keep `objSet` unique when `ignoreObjSubId = true` to avoid circle recursive. */ if (!ignoreObjSubId || !TrObjAddrExists(depForm->classid, depForm->objid, objSet)) { - add_object_address_ext(depForm->classid, depForm->objid, - depForm->objsubid, depForm->deptype, objSet); + // 灏嗗唴閮ㄥ璞$殑鍦板潃娣诲姞鍒板璞″湴鍧闆嗗悎涓 + add_object_address_ext(depForm->classid, depForm->objid, depForm->objsubid, depForm->deptype, objSet); } } - systable_endscan(sd); + systable_endscan(sd); // 缁撴潫鎵弿 return; } - +/* + * 鍔熻兘锛氭牴鎹洖鏀剁珯瀵硅薄鐨勬搷浣滅被鍨嬶紙鎿嶄綔鐮侊級鏉ユ墽琛岀浉搴旂殑娓呴櫎鎿嶄綔銆 + * + * 鍙傛暟鍒楄〃: + * desc: 寰呮竻闄ょ殑鍥炴敹绔欏璞℃弿杩 + */ static void TrDoPurgeObject(TrObjDesc *desc) { - if (desc->operation == RB_OPER_DROP) { + if (desc->operation == RB_OPER_DROP) { // 鎿嶄綔绫诲瀷涓哄垹闄 TrDoPurgeObjectDrop(desc); - } else { + } else { // 鎿嶄綔绫诲瀷涓烘埅鏂 TrDoPurgeObjectTruncate(desc); } } - +/* + * 鍔熻兘锛氭墽琛屽洖鏀剁珯瀵硅薄鐨勬案涔呭垹闄ゆ搷浣 + * 鍙傛暟鍒楄〃锛 + * purobj锛氳姘镐箙鍒犻櫎鐨勫璞$殑鑼冨洿鍙橀噺 + * type锛氬璞$殑绫诲瀷锛堜緥濡傝〃銆佺储寮曠瓑锛 + */ void TrPurgeObject(RangeVar *purobj, TrObjType type) { TrObjDesc desc; + // 鑾峰彇鍥炴敹绔欏璞$殑鎻忚堪淇℃伅 TrOperFetch(purobj, type, &desc, RB_OPER_PURGE); + // 璁剧疆鎿嶄綔鐨勬巿鏉冪敤鎴 ID desc.authid = GetUserId(); + + // 鍑嗗鎵ц鍒犻櫎鎿嶄綔锛屽寘鎷潈闄愭鏌ョ瓑 TrOperPrep(&desc, RB_OPER_PURGE); + // 鎵ц瀹為檯鐨勬案涔呭垹闄ゆ搷浣 TrDoPurgeObject(&desc); return; } - +// 涓娆℃案涔呭垹闄ゆ搷浣滀腑瑕佸鐞嗙殑瀵硅薄鏁伴噺锛堟壒閲忓鐞嗙殑澶у皬锛 const int PURGE_BATCH = 64; +// 鍗曚釜姘镐箙鍒犻櫎鎿嶄綔涓澶勭悊鐨勫璞℃暟閲 const int PURGE_SINGL = 64; +// TrFetchBeginHook 鏄嚱鏁版寚閽堢被鍨嬶紝鐢ㄤ簬鎸囧悜鍦ㄨ幏鍙栧洖鏀剁珯瀵硅薄鍓嶆墽琛岀殑閽╁瓙鍑芥暟銆 +// 璇ラ挬瀛愬嚱鏁版帴鍙 SysScanDesc 鎸囬拡鍜屽璞$殑 ID 浣滀负鍙傛暟锛岀敤浜庡垵濮嬪寲鎵弿浠ヨ幏鍙栧洖鏀剁珯瀵硅薄銆 typedef void (*TrFetchBeginHook)(SysScanDesc *sd, Oid objId); +// TrFetchMatchHook 鏄嚱鏁版寚閽堢被鍨嬶紝鐢ㄤ簬鎸囧悜鍦ㄨ幏鍙栧洖鏀剁珯瀵硅薄鍚庢墽琛岀殑閽╁瓙鍑芥暟銆 +// 璇ラ挬瀛愬嚱鏁版帴鍙楀洖鏀剁珯鍏崇郴銆佸爢鍏冪粍鍜屽璞 ID 浣滀负鍙傛暟锛岀敤浜庢鏌ュ洖鏀剁珯瀵硅薄鏄惁鍖归厤銆 typedef bool (*TrFetchMatchHook)(Relation rbRel, HeapTuple rbTup, Oid objId); - +/* + * 鍔熻兘锛氬紑濮嬫墽琛屽洖鏀剁珯瀵硅薄鎻愬彇鎿嶄綔鐨勯挬瀛愬嚱鏁 + * 鍙傛暟鍒楄〃锛 + * fetchHook锛氭彁鍙栨搷浣滅殑閽╁瓙鍑芥暟鎸囬拡 + * sd锛氱郴缁熸壂鎻忔弿杩扮鎸囬拡 + * objId锛氬璞$殑鏍囪瘑绗 + */ static void TrFetchBegin(TrFetchBeginHook fetchHook, SysScanDesc *sd, Oid objId) { + // 璋冪敤鎻愬彇鎿嶄綔鐨勯挬瀛愬嚱鏁帮紝浼犲叆绯荤粺鎵弿鎻忚堪绗﹀拰瀵硅薄鏍囪瘑绗 fetchHook(sd, objId); } // @return: true for eof +/* + * 鍔熻兘锛氭墽琛屽洖鏀剁珯瀵硅薄鎻愬彇鎿嶄綔鐨勬墽琛屽嚱鏁 + * 鍙傛暟鍒楄〃锛 + * matchHook锛氬尮閰嶆搷浣滅殑閽╁瓙鍑芥暟鎸囬拡 + * objId锛氬璞$殑鏍囪瘑绗 + * sd锛氱郴缁熸壂鎻忔弿杩扮 + * desc锛氬洖鏀剁珯瀵硅薄鎻忚堪缁撴瀯鐨勬寚閽 + */ static bool TrFetchExec(TrFetchMatchHook matchHook, Oid objId, SysScanDesc sd, TrObjDesc *desc) { HeapTuple tup; while ((tup = systable_getnext(sd)) != NULL) { + // 鑾峰彇鍫嗗厓缁勭殑缁撴瀯浣撳舰寮 Form_pg_recyclebin rbForm = (Form_pg_recyclebin)GETSTRUCT(tup); + + // 鏍规嵁鍥炴敹绔欏璞$被鍨嬪拰鍖归厤鎿嶄綔鐨勭粨鏋滆繘琛屽鐞 if ((rbForm->rcytype == RB_OBJ_TABLE) && matchHook(sd->heap_rel, tup, objId)) { - Assert (rbForm->rcycanpurge); + // 鏂█鍥炴敹绔欏璞″彲浠ユ案涔呭垹闄 + Assert(rbForm->rcycanpurge); + + // 璇诲彇鍥炴敹绔欏璞℃弿杩颁俊鎭 TrDescRead(desc, tup); + + // 杩斿洖 false锛岃〃绀烘垚鍔熷尮閰嶅苟鎻愬彇瀵硅薄 return false; } else if ((rbForm->rcytype == RB_OBJ_PARTITION) && matchHook(sd->heap_rel, tup, objId)) { - Assert (!rbForm->rcycanpurge); + // 鏂█鍥炴敹绔欏璞′笉鍙案涔呭垹闄 + Assert(!rbForm->rcycanpurge); + + // 璇诲彇鍥炴敹绔欏璞℃弿杩颁俊鎭 TrDescRead(desc, tup); + + // 杩斿洖 false锛岃〃绀烘垚鍔熷尮閰嶅苟鎻愬彇瀵硅薄 return false; } } + + // 濡傛灉娌℃湁鍖归厤鐨勫璞★紝杩斿洖 true return true; } +/* + * 鍔熻兘锛氱粨鏉熷洖鏀剁珯瀵硅薄鎻愬彇鎿嶄綔鐨勬壂鎻忓苟閲婃斁鐩稿叧璧勬簮 + * 鍙傛暟鍒楄〃锛 + * sd锛氱郴缁熸壂鎻忔弿杩扮 + */ static void TrFetchEnd(SysScanDesc sd) { + // 鑾峰彇鍥炴敹绔欏叧绯荤殑寮曠敤 Relation rbRel = sd->heap_rel; + // 缁撴潫绯荤粺鎵弿 systable_endscan(sd); + + // 鍏抽棴鍥炴敹绔欏叧绯伙紝閲婃斁鍏变韩閿 heap_close(rbRel, AccessShareLock); } -static bool TrPurgeBatch(TrFetchBeginHook beginHook, TrFetchMatchHook matchHook, - Oid objId, Oid roleid, uint32 maxBatch, PurgeMsgRes *localRes) +/* + * 鍔熻兘锛氭壒閲忔案涔呭垹闄ゅ洖鏀剁珯瀵硅薄 + * 鍙傛暟鍒楄〃锛 + * beginHook锛氬紑濮嬫彁鍙栫殑閽╁瓙鍑芥暟 + * matchHook锛氬尮閰嶇殑閽╁瓙鍑芥暟 + * objId锛氬璞$殑ID + * roleid锛氳鑹茬殑ID + * maxBatch锛氭渶澶ф壒娆℃暟閲 + * localRes锛氱敤浜庡瓨鍌ㄥ垹闄ょ粨鏋滅殑缁撴瀯浣撴寚閽 + */ +static bool TrPurgeBatch(TrFetchBeginHook beginHook, TrFetchMatchHook matchHook, Oid objId, Oid roleid, uint32 maxBatch, + PurgeMsgRes *localRes) { SysScanDesc sd = NULL; TrObjDesc desc; uint32 count = 0; bool eof = false; + // 閲嶇疆鏈湴鍒犻櫎缁撴灉淇℃伅 RbMsgResetRes(localRes); + // 寮鍚簨鍔 StartTransactionCommand(); + // 寮濮嬫彁鍙栧洖鏀剁珯瀵硅薄 TrFetchBegin(beginHook, &sd, objId); + + // 寰幆鎵ц鎵归噺鍒犻櫎鎿嶄綔锛岀洿鍒版壒娆$粨鏉 while (!(eof = TrFetchExec(matchHook, objId, sd, &desc))) { CHECK_FOR_INTERRUPTS(); + // 浣跨敤 TRY-CATCH 鍧楁潵澶勭悊鍒犻櫎杩囩▼涓殑寮傚父鎯呭喌 PG_TRY(); { + // 璁剧疆瑕佹墽琛屽垹闄ょ殑瑙掕壊 desc.authid = roleid; + + // 鍑嗗鍒犻櫎鎿嶄綔锛屾鏌ユ潈闄愮瓑 TrOperPrep(&desc, RB_OPER_PURGE); + // 鎵ц鍒犻櫎鎿嶄綔 TrDoPurgeObject(&desc); + + // 鏇存柊鏈湴鍒犻櫎缁撴灉缁熻 localRes->purgedNum++; } PG_CATCH(); @@ -976,229 +1246,355 @@ static bool TrPurgeBatch(TrFetchBeginHook beginHook, TrFetchMatchHook matchHook, int errcode = geterrcode(); if (errcode == ERRCODE_RBIN_LOCK_NOT_AVAILABLE) { errno_t rc; + // 濡傛灉閿佷笉鍙敤锛岃褰曢敊璇秷鎭紝骞跺鍔犺烦杩囨暟閲 rc = strncpy_s(localRes->errMsg, RB_MAX_ERRMSG_SIZE, Geterrmsg(), RB_MAX_ERRMSG_SIZE - 1); securec_check(rc, "\0", "\0"); localRes->skippedNum++; } else if (errcode == ERRCODE_RBIN_UNDEFINED_OBJECT) { + // 濡傛灉瀵硅薄鏈畾涔夛紝澧炲姞鏈畾涔夋暟閲 localRes->undefinedNum++; } else { + // 鍏朵粬寮傚父鎯呭喌锛岄噸鏂版姏鍑哄紓甯 PG_RE_THROW(); } } PG_END_TRY(); + // 濡傛灉杈惧埌鏈澶ф壒娆℃暟閲忥紝璺冲嚭寰幆 if (++count >= maxBatch) { break; } } + // 缁撴潫鍥炴敹绔欏璞℃彁鍙栨搷浣 TrFetchEnd(sd); + // 鎻愪氦浜嬪姟 CommitTransactionCommand(); + // 杩斿洖鎵规鏄惁缁撴潫鐨勬爣蹇 return eof; } +/* + * 鍔熻兘锛氬紑濮嬫彁鍙栨寚瀹氳〃绌洪棿涓嬬殑鍥炴敹绔欏璞 + * 鍙傛暟鍒楄〃锛 + * sd锛氱敤浜庢壂鎻忕殑 SysScanDesc 鎸囬拡 + * spcId锛氳〃绌洪棿鐨処D + */ static void TrFetchBeginSpace(SysScanDesc *sd, Oid spcId) { ScanKeyData skey[2]; Relation rbRel; + // 鎵撳紑鍥炴敹绔欏叧绯 rbRel = heap_open(RecyclebinRelationId, AccessShareLock); - ScanKeyInit(&skey[0], Anum_pg_recyclebin_rcytablespace, BTEqualStrategyNumber, - F_OIDEQ, ObjectIdGetDatum(spcId)); - ScanKeyInit(&skey[1], Anum_pg_recyclebin_rcydbid, BTEqualStrategyNumber, - F_OIDEQ, ObjectIdGetDatum(u_sess->proc_cxt.MyDatabaseId)); + // 鍒濆鍖栨壂鎻忛敭 + ScanKeyInit(&skey[0], Anum_pg_recyclebin_rcytablespace, BTEqualStrategyNumber, F_OIDEQ, ObjectIdGetDatum(spcId)); + ScanKeyInit(&skey[1], Anum_pg_recyclebin_rcydbid, BTEqualStrategyNumber, F_OIDEQ, + ObjectIdGetDatum(u_sess->proc_cxt.MyDatabaseId)); + // 寮濮嬫壂鎻忓洖鏀剁珯瀵硅薄 *sd = systable_beginscan(rbRel, RecyclebinDbidSpcidRcycsnIndexId, true, NULL, 2, skey); } +/* + * 鍔熻兘锛氬尮閰嶅洖鏀剁珯瀵硅薄鏄惁灞炰簬鎸囧畾鐨勮〃绌洪棿 + * 鍙傛暟鍒楄〃锛 + * rbRel锛氬洖鏀剁珯鍏崇郴 + * rbTup锛氬綋鍓嶇殑鍥炴敹绔欏厓缁 + * objId锛氳鍖归厤鐨勫璞D + */ static bool TrFetchMatchSpace(Relation rbRel, HeapTuple rbTup, Oid objId) { Form_pg_recyclebin rbForm = (Form_pg_recyclebin)GETSTRUCT(rbTup); return rbForm->rcytablespace == objId; } +/* + * 鍔熻兘锛氭竻闄ゆ寚瀹氳〃绌洪棿涓嬬殑鍥炴敹绔欏璞 + * 鍙傛暟鍒楄〃锛 + * id锛氬洖鏀剁珯娑堟伅鐨処D + */ void TrPurgeTablespace(int64 id) { - PurgeMsgReq *req = &RbMsg(id)->req; - PurgeMsgRes localRes; - bool eof = false; + PurgeMsgReq *req = &RbMsg(id)->req; // 鑾峰彇鍥炴敹绔欐秷鎭殑璇锋眰淇℃伅 + PurgeMsgRes localRes; // 鏈湴鐨勬竻闄ょ粨鏋 + bool eof = false; // 琛ㄧず鏄惁鍒拌揪鍥炴敹绔欏璞$殑鏈熬 do { + // 閫愭壒娓呴櫎鍥炴敹绔欏璞 eof = TrPurgeBatch(TrFetchBeginSpace, TrFetchMatchSpace, req->objId, req->authId, PURGE_BATCH, &localRes); + + // 鏇存柊娑堟伅鐨勭粺璁′俊鎭 RbMsgSetStatistics(id, &localRes); } while (!eof && localRes.skippedNum == 0); } +/* + * 鍔熻兘锛氫互閫愪釜瀵硅薄鏂瑰紡娓呴櫎鎸囧畾琛ㄧ┖闂翠笅鐨勫洖鏀剁珯瀵硅薄 + * 鍙傛暟鍒楄〃锛 + * id锛氬洖鏀剁珯娑堟伅鐨処D + */ void TrPurgeTablespaceDML(int64 id) { - PurgeMsgReq *req = &RbMsg(id)->req; - PurgeMsgRes localRes; - bool eof = false; + PurgeMsgReq *req = &RbMsg(id)->req; // 鑾峰彇鍥炴敹绔欐秷鎭殑璇锋眰淇℃伅 + PurgeMsgRes localRes; // 鏈湴鐨勬竻闄ょ粨鏋 + bool eof = false; // 琛ㄧず鏄惁鍒拌揪鍥炴敹绔欏璞$殑鏈熬 do { + // 閫愪釜瀵硅薄娓呴櫎鍥炴敹绔欏璞 eof = TrPurgeBatch(TrFetchBeginSpace, TrFetchMatchSpace, req->objId, req->authId, PURGE_SINGL, &localRes); + + // 鏇存柊娑堟伅鐨勭粺璁′俊鎭 RbMsgSetStatistics(id, &localRes); } while (!eof && localRes.purgedNum == 0); } - +/* + * 鍔熻兘锛氬垵濮嬪寲鍥炴敹绔欎腑鎸囧畾瀵硅薄鐨勬壂鎻 + * 鍙傛暟鍒楄〃锛 + * sd锛歋ysScanDesc 缁撴瀯鐨勬寚閽堬紝鐢ㄤ簬鎺ユ敹鎵弿鎻忚堪 + * objId锛氳鍒濆鍖栨壂鎻忕殑瀵硅薄鐨処D + */ static void TrFetchBeginRecyclebin(SysScanDesc *sd, Oid objId) { - ScanKeyData skey[2]; - Relation rbRel; + ScanKeyData skey[2]; // 鎵弿閿暟缁 + Relation rbRel; // 鍥炴敹绔欏叧绯诲璞 - rbRel = heap_open(RecyclebinRelationId, AccessShareLock); + rbRel = heap_open(RecyclebinRelationId, AccessShareLock); // 鎵撳紑鍥炴敹绔欏叧绯诲璞 - ScanKeyInit(&skey[0], Anum_pg_recyclebin_rcydbid, BTEqualStrategyNumber, - F_OIDEQ, ObjectIdGetDatum(u_sess->proc_cxt.MyDatabaseId)); + // 鍒濆鍖栨壂鎻忛敭锛岄氳繃鏁版嵁搴揑D鏉ョ瓫閫夊洖鏀剁珯涓殑瀵硅薄 + ScanKeyInit(&skey[0], Anum_pg_recyclebin_rcydbid, BTEqualStrategyNumber, F_OIDEQ, + ObjectIdGetDatum(u_sess->proc_cxt.MyDatabaseId)); + // 寮濮嬫壂鎻忓洖鏀剁珯鍏崇郴瀵硅薄 *sd = systable_beginscan(rbRel, RecyclebinDbidRelidIndexId, true, NULL, 1, skey); } +/* + * 鍔熻兘锛氭鏌ュ洖鏀剁珯瀵硅薄鏄惁鍖归厤锛屽缁堣繑鍥 true锛屽嵆琛ㄧず鍖归厤浠讳綍鍥炴敹绔欏璞 + * 鍙傛暟鍒楄〃锛 + * rbRel锛氬洖鏀剁珯鍏崇郴瀵硅薄 + * rbTup锛氬洖鏀剁珯鍏冪粍锛圚eapTuple锛 + * objId锛氳鍖归厤鐨勫璞$殑ID锛堟棤鏁堢殑锛 + */ static bool TrFetchMatchRecyclebin(Relation rbRel, HeapTuple rbTup, Oid objId) { - return true; + return true; // 濮嬬粓杩斿洖 true锛岃〃绀哄尮閰嶄换浣曞洖鏀剁珯瀵硅薄 } +/* + * 鍔熻兘锛氭案涔呭垹闄ゅ洖鏀剁珯涓殑瀵硅薄 + * 鍙傛暟鍒楄〃锛 + * id锛氭秷鎭疘D + */ void TrPurgeRecyclebin(int64 id) { - PurgeMsgReq *req = &RbMsg(id)->req; - PurgeMsgRes localRes; - bool eof = false; + PurgeMsgReq *req = &RbMsg(id)->req; // 鑾峰彇娑堟伅璇锋眰 + PurgeMsgRes localRes; // 鐢ㄤ簬淇濆瓨鏈湴娓呴櫎缁撴灉 + bool eof = false; // 鏍囪瘑鎵弿鏄惁缁撴潫 do { - eof = TrPurgeBatch(TrFetchBeginRecyclebin, TrFetchMatchRecyclebin, - InvalidOid, req->authId, PURGE_BATCH, &localRes); + // 鎵ц鍥炴敹绔欏璞$殑鎵归噺娓呴櫎 + eof = TrPurgeBatch(TrFetchBeginRecyclebin, TrFetchMatchRecyclebin, InvalidOid, req->authId, PURGE_BATCH, + &localRes); + + // 鏇存柊娑堟伅鐨勭粺璁′俊鎭 RbMsgSetStatistics(id, &localRes); - } while (!eof && localRes.skippedNum == 0); + } while (!eof && localRes.skippedNum == 0); // 缁х画寰幆鐩村埌鎵弿缁撴潫鎴栨病鏈夎璺宠繃鐨勫璞 } +/* + * 鍔熻兘锛氬紑濮嬪湪鍥炴敹绔欎腑鎵弿涓庢寚瀹氭ā寮忓尮閰嶇殑瀵硅薄 + * 鍙傛暟鍒楄〃锛 + * sd锛氭壂鎻忔弿杩扮鎸囬拡锛岀敤浜庡瓨鍌ㄦ壂鎻忕粨鏋 + * objId锛氳鍖归厤鐨勬ā寮忕殑ID + */ static void TrFetchBeginSchema(SysScanDesc *sd, Oid objId) { - ScanKeyData skey[2]; - Relation rbRel; + ScanKeyData skey[2]; // 鎵弿閿暟缁 + Relation rbRel; // 鍥炴敹绔欏叧绯诲璞 - rbRel = heap_open(RecyclebinRelationId, AccessShareLock); - ScanKeyInit(&skey[0], Anum_pg_recyclebin_rcynamespace, BTEqualStrategyNumber, - F_OIDEQ, ObjectIdGetDatum(objId)); - ScanKeyInit(&skey[1], Anum_pg_recyclebin_rcydbid, BTEqualStrategyNumber, - F_OIDEQ, ObjectIdGetDatum(u_sess->proc_cxt.MyDatabaseId)); + rbRel = heap_open(RecyclebinRelationId, AccessShareLock); // 鎵撳紑鍥炴敹绔欏叧绯诲璞 + ScanKeyInit(&skey[0], Anum_pg_recyclebin_rcynamespace, BTEqualStrategyNumber, F_OIDEQ, + ObjectIdGetDatum(objId)); // 鍒濆鍖栨壂鎻忛敭锛屽尮閰嶆ā寮忕殑鍛藉悕绌洪棿 + ScanKeyInit(&skey[1], Anum_pg_recyclebin_rcydbid, BTEqualStrategyNumber, F_OIDEQ, + ObjectIdGetDatum(u_sess->proc_cxt.MyDatabaseId)); // 鍒濆鍖栨壂鎻忛敭锛屽尮閰嶅綋鍓嶆暟鎹簱ID - *sd = systable_beginscan(rbRel, RecyclebinDbidNspOrinameIndexId, true, NULL, 2, skey); + *sd = systable_beginscan(rbRel, RecyclebinDbidNspOrinameIndexId, true, NULL, 2, skey); // 寮濮嬫壂鎻 } +/* + * 鍔熻兘锛氬湪鍥炴敹绔欎腑鍖归厤鎸囧畾妯″紡鐨勫璞 + * 鍙傛暟鍒楄〃锛 + * rbRel锛氬洖鏀剁珯鍏崇郴瀵硅薄 + * rbTup锛氬洖鏀剁珯涓殑鍏冪粍 + * objId锛氳鍖归厤鐨勬ā寮忕殑ID + */ static bool TrFetchMatchSchema(Relation rbRel, HeapTuple rbTup, Oid objId) { - Form_pg_recyclebin rbForm = (Form_pg_recyclebin)GETSTRUCT(rbTup); - return rbForm->rcynamespace == objId; + Form_pg_recyclebin rbForm = (Form_pg_recyclebin)GETSTRUCT(rbTup); // 鑾峰彇鍏冪粍鐨勬暟鎹粨鏋勪綋 + return rbForm->rcynamespace == objId; // 杩斿洖鏄惁鍖归厤妯″紡鐨勫懡鍚嶇┖闂 } +/* + * 鍔熻兘锛氭墽琛屽洖鏀剁珯涓寚瀹氭ā寮忕殑瀵硅薄鐨勬案涔呭垹闄ゆ搷浣 + * 鍙傛暟鍒楄〃锛 + * id锛氳鍒犻櫎鐨勬ā寮忕殑ID + */ void TrPurgeSchema(int64 id) { - PurgeMsgReq *req = &RbMsg(id)->req; - PurgeMsgRes localRes; + PurgeMsgReq *req = &RbMsg(id)->req; // 鑾峰彇璇锋眰娑堟伅 + PurgeMsgRes localRes; // 鐢ㄤ簬瀛樺偍鍒犻櫎鎿嶄綔鐨勭粨鏋 bool eof = false; do { - eof = TrPurgeBatch(TrFetchBeginSchema, TrFetchMatchSchema, req->objId, req->authId, PURGE_BATCH, &localRes); - RbMsgSetStatistics(id, &localRes); - } while (!eof && localRes.skippedNum == 0); + eof = TrPurgeBatch(TrFetchBeginSchema, TrFetchMatchSchema, req->objId, req->authId, PURGE_BATCH, + &localRes); // 鎵ц鎵归噺姘镐箙鍒犻櫎鎿嶄綔 + RbMsgSetStatistics(id, &localRes); // 鏇存柊鍒犻櫎缁熻淇℃伅 + } while (!eof && localRes.skippedNum == 0); // 褰撴壒閲忓垹闄ゆ湭瀹屾垚涓旀湭璺宠繃浠讳綍鎿嶄綔鏃剁户缁墽琛 } +/* + * 鍔熻兘锛氬湪鍥炴敹绔欎腑鏍规嵁鐢ㄦ埛ID寮濮嬫壂鎻忓尮閰嶇殑瀵硅薄 + * 鍙傛暟鍒楄〃锛 + * sd锛氭壂鎻忔弿杩扮鎸囬拡锛岀敤浜庡瓨鍌ㄦ壂鎻忕粨鏋 + * objId锛氳鍖归厤鐨勫璞$殑ID锛堝湪杩欓噷鏄敤鎴稩D锛 + */ static void TrFetchBeginUser(SysScanDesc *sd, Oid objId) { - ScanKeyData skey[2]; - Relation rbRel; + ScanKeyData skey[2]; // 鎵弿閿暟缁 + Relation rbRel; // 鍥炴敹绔欏叧绯诲璞 - rbRel = heap_open(RecyclebinRelationId, AccessShareLock); + rbRel = heap_open(RecyclebinRelationId, AccessShareLock); // 鎵撳紑鍥炴敹绔欏叧绯诲璞★紝鑾峰彇璁块棶鍏变韩閿 - ScanKeyInit(&skey[0], Anum_pg_recyclebin_rcydbid, BTEqualStrategyNumber, - F_OIDEQ, ObjectIdGetDatum(u_sess->proc_cxt.MyDatabaseId)); + // 鍒濆鍖栨壂鎻忛敭 + ScanKeyInit(&skey[0], Anum_pg_recyclebin_rcydbid, BTEqualStrategyNumber, F_OIDEQ, + ObjectIdGetDatum(u_sess->proc_cxt.MyDatabaseId)); + // 寮濮嬫壂鎻忓洖鏀剁珯鍏崇郴瀵硅薄锛屽苟灏嗘壂鎻忕粨鏋滃瓨鍌ㄥ埌鎵弿鎻忚堪绗︿腑 *sd = systable_beginscan(rbRel, RecyclebinDbidRelidIndexId, true, NULL, 1, skey); } +/* + * 鍔熻兘锛氬湪鍥炴敹绔欎腑鍖归厤鎸囧畾鐢ㄦ埛鐨勫璞 + * 鍙傛暟鍒楄〃锛 + * rbRel锛氬洖鏀剁珯鍏崇郴瀵硅薄 + * rbTup锛氬洖鏀剁珯涓殑鍏冪粍 + * objId锛氳鍖归厤鐨勭敤鎴风殑ID + */ static bool TrFetchMatchUser(Relation rbRel, HeapTuple rbTup, Oid objId) { - Form_pg_recyclebin rbForm = (Form_pg_recyclebin)GETSTRUCT(rbTup); - return rbForm->rcyowner == objId; + Form_pg_recyclebin rbForm = (Form_pg_recyclebin)GETSTRUCT(rbTup); // 鑾峰彇鍏冪粍鐨勬暟鎹粨鏋勪綋 + return rbForm->rcyowner == objId; // 杩斿洖鏄惁鍖归厤鎸囧畾鐢ㄦ埛鐨勬墍鏈夎 } +/* + * 鍔熻兘锛氭墽琛屽洖鏀剁珯涓寚瀹氱敤鎴风殑瀵硅薄鐨勬案涔呭垹闄ゆ搷浣 + * 鍙傛暟鍒楄〃锛 + * id锛氳鍒犻櫎鐨勭敤鎴风殑ID + */ void TrPurgeUser(int64 id) { - PurgeMsgReq *req = &RbMsg(id)->req; - PurgeMsgRes localRes; + PurgeMsgReq *req = &RbMsg(id)->req; // 鑾峰彇璇锋眰娑堟伅 + PurgeMsgRes localRes; // 鐢ㄤ簬瀛樺偍鍒犻櫎鎿嶄綔鐨勭粨鏋 bool eof = false; do { - eof = TrPurgeBatch(TrFetchBeginUser, TrFetchMatchUser, req->objId, req->authId, PURGE_BATCH, &localRes); - RbMsgSetStatistics(id, &localRes); - } while (!eof && localRes.skippedNum == 0); + eof = TrPurgeBatch(TrFetchBeginUser, TrFetchMatchUser, req->objId, req->authId, PURGE_BATCH, + &localRes); // 鎵ц鎵归噺姘镐箙鍒犻櫎鎿嶄綔 + RbMsgSetStatistics(id, &localRes); // 鏇存柊鍒犻櫎缁熻淇℃伅 + } while (!eof && localRes.skippedNum == 0); // 褰撴壒閲忓垹闄ゆ湭瀹屾垚涓旀湭璺宠繃浠讳綍鎿嶄綔鏃剁户缁墽琛 } +/* + * 鍔熻兘锛氬湪鍥炴敹绔欎腑鏍规嵁鑷姩娓呯悊绛栫暐寮濮嬫壂鎻忓尮閰嶇殑瀵硅薄 + * 鍙傛暟鍒楄〃锛 + * sd锛氭壂鎻忔弿杩扮鎸囬拡锛岀敤浜庡瓨鍌ㄦ壂鎻忕粨鏋 + * objId锛氳鍖归厤鐨勫璞$殑ID锛堝湪杩欓噷鏄棤鏁堢殑锛屼笉浣跨敤锛 + */ static void TrFetchBeginAuto(SysScanDesc *sd, Oid objId) { - ScanKeyData skey[2]; - Relation rbRel; + ScanKeyData skey[2]; // 鎵弿閿暟缁 + Relation rbRel; // 鍥炴敹绔欏叧绯诲璞 - rbRel = heap_open(RecyclebinRelationId, AccessShareLock); + rbRel = heap_open(RecyclebinRelationId, AccessShareLock); // 鎵撳紑鍥炴敹绔欏叧绯诲璞★紝鑾峰彇璁块棶鍏变韩閿 - ScanKeyInit(&skey[0], Anum_pg_recyclebin_rcydbid, BTEqualStrategyNumber, - F_OIDEQ, ObjectIdGetDatum(u_sess->proc_cxt.MyDatabaseId)); + // 鍒濆鍖栨壂鎻忛敭 + ScanKeyInit(&skey[0], Anum_pg_recyclebin_rcydbid, BTEqualStrategyNumber, F_OIDEQ, + ObjectIdGetDatum(u_sess->proc_cxt.MyDatabaseId)); + // 寮濮嬫壂鎻忓洖鏀剁珯鍏崇郴瀵硅薄锛屽苟灏嗘壂鎻忕粨鏋滃瓨鍌ㄥ埌鎵弿鎻忚堪绗︿腑 *sd = systable_beginscan(rbRel, RecyclebinDbidRelidIndexId, true, NULL, 1, skey); } - +/* + * 鍔熻兘锛氬湪鍥炴敹绔欎腑鍖归厤鑷姩鍒犻櫎鐨勫璞★紝鍒ゆ柇鏄惁婊¤冻鑷姩鍒犻櫎鏉′欢 + * 鍙傛暟鍒楄〃锛 + * rbRel锛氬洖鏀剁珯鍏崇郴瀵硅薄 + * rbTup锛氬洖鏀剁珯涓殑鍏冪粍 + * objId锛氳鍖归厤鐨勫璞$殑ID + */ static bool TrFetchMatchAuto(Relation rbRel, HeapTuple rbTup, Oid objId) { bool isNull = false; - Datum datumRcyTime = heap_getattr(rbTup, Anum_pg_recyclebin_rcyrecycletime, - RelationGetDescr(rbRel), &isNull); + Datum datumRcyTime = heap_getattr(rbTup, Anum_pg_recyclebin_rcyrecycletime, RelationGetDescr(rbRel), &isNull); long secs; int msecs; - TimestampDifference(isNull ? 0 : DatumGetTimestampTz(datumRcyTime), - GetCurrentTimestamp(), &secs, &msecs); + TimestampDifference(isNull ? 0 : DatumGetTimestampTz(datumRcyTime), GetCurrentTimestamp(), &secs, &msecs); - return secs > u_sess->attr.attr_storage.recyclebin_retention_time || secs < 0; + return secs > u_sess->attr.attr_storage.recyclebin_retention_time || secs < 0; // 鍒ゆ柇鏄惁婊¤冻鑷姩鍒犻櫎鏉′欢 } +/* + * 鍔熻兘锛氭墽琛屽洖鏀剁珯涓嚜鍔ㄥ垹闄ょ殑瀵硅薄鐨勬案涔呭垹闄ゆ搷浣 + * 鍙傛暟鍒楄〃锛 + * id锛氳鍒犻櫎鐨勫璞$殑ID + */ void TrPurgeAuto(int64 id) { - PurgeMsgReq *req = &RbMsg(id)->req; - PurgeMsgRes localRes; + PurgeMsgReq *req = &RbMsg(id)->req; // 鑾峰彇璇锋眰娑堟伅 + PurgeMsgRes localRes; // 鐢ㄤ簬瀛樺偍鍒犻櫎鎿嶄綔鐨勭粨鏋 bool eof = false; - do { - eof = TrPurgeBatch(TrFetchBeginAuto, TrFetchMatchAuto, InvalidOid, req->authId, PURGE_BATCH, &localRes); - RbMsgSetStatistics(id, &localRes); - } while (!eof); -} + do { + eof = TrPurgeBatch(TrFetchBeginAuto, TrFetchMatchAuto, InvalidOid, req->authId, PURGE_BATCH, + &localRes); // 鎵ц鎵归噺姘镐箙鍒犻櫎鎿嶄綔 + RbMsgSetStatistics(id, &localRes); // 鏇存柊鍒犻櫎缁熻淇℃伅 + } while (!eof); // 褰撴壒閲忓垹闄ゆ湭瀹屾垚鏃剁户缁墽琛 +} +/* + * 鍔熻兘锛氫氦鎹㈠洖鏀剁珯瀵硅薄鍜屽叧绯诲璞$殑鏂囦欢鑺傜偣淇℃伅 + * 鍙傛暟鍒楄〃锛 + * rbRel锛氬洖鏀剁珯鍏崇郴瀵硅薄 + * rbTup锛氬洖鏀剁珯涓殑瀵硅薄鍏冪粍 + * isPart锛氭槸鍚︽槸鍒嗗尯瀵硅薄 + */ void TrSwapRelfilenode(Relation rbRel, HeapTuple rbTup, bool isPart) { - Relation relRel; - HeapTuple relTup; - HeapTuple newTup; - TrObjDesc desc; - int maxNattr = 0; - Datum *values = NULL; - bool *nulls = NULL; - bool *replaces = NULL; - NameData name; - errno_t rc = EOK; - bool isNull = false; - int relfilenoIndex = 0; - int frozenxidIndex = 0; - int frozenxid64Index = 0; - bool isPartition = false; - + Relation relRel; // 鍏崇郴瀵硅薄鐨勫叧绯绘弿杩扮 + HeapTuple relTup; // 鍏崇郴瀵硅薄鍏冪粍 + HeapTuple newTup; // 鏂板叧绯诲璞″厓缁 + TrObjDesc desc; // 鍥炴敹绔欏璞$殑鎻忚堪淇℃伅 + int maxNattr = 0; // 鏈澶у睘鎬ф暟 + Datum *values = NULL; // 灞炴у兼暟缁 + bool *nulls = NULL; // NULL鍊兼暟缁 + bool *replaces = NULL; // 闇瑕佹浛鎹㈢殑灞炴ф暟缁 + NameData name; // 鍚嶇О鏁版嵁 + errno_t rc = EOK; // 閿欒鐮 + bool isNull = false; // 鏄惁涓篘ULL + int relfilenoIndex = 0; // relfileno灞炴х殑绱㈠紩 + int frozenxidIndex = 0; // frozenxid灞炴х殑绱㈠紩 + int frozenxid64Index = 0; // frozenxid64灞炴х殑绱㈠紩 + bool isPartition = false; // 鏄惁涓哄垎鍖哄璞 + // 璇诲彇鍥炴敹绔欏璞℃弿杩 TrDescRead(&desc, rbTup); - - if (desc.type == RB_OBJ_PARTITION || (desc.type == RB_OBJ_INDEX && isPart)) { + // 鍒ゆ柇鏄惁涓哄垎鍖哄璞 + if (desc.type == RB_OBJ_PARTITION || (desc.type == RB_OBJ_INDEX && isPart)) { isPartition = true; } + // 鏍规嵁瀵硅薄绫诲瀷纭畾瑕佹搷浣滅殑绯荤粺琛 if (isPartition) { maxNattr = Max(Natts_pg_partition, Natts_pg_recyclebin); relRel = heap_open(PartitionRelationId, RowExclusiveLock); @@ -1217,15 +1613,13 @@ void TrSwapRelfilenode(Relation rbRel, HeapTuple rbTup, bool isPart) /* 1. Update pg_class or pg_partition */ if (!HeapTupleIsValid(relTup)) { - ereport(ERROR, - (errcode(ERRCODE_UNDEFINED_TABLE), - errmsg("cache lookup failed for relation %u", desc.relid))); + ereport(ERROR, (errcode(ERRCODE_UNDEFINED_TABLE), errmsg("cache lookup failed for relation %u", desc.relid))); } - + // 涓烘洿鏂版瀯閫犲睘鎬у笺佹槸鍚︿负绌哄拰鏄惁鏇存柊鐨勬暟缁 values = (Datum *)palloc0(sizeof(Datum) * maxNattr); nulls = (bool *)palloc0(sizeof(bool) * maxNattr); replaces = (bool *)palloc0(sizeof(bool) * maxNattr); - + // 璁剧疆闇瑕佹洿鏂扮殑灞炴у拰瀵瑰簲鐨勬柊鍊 replaces[relfilenoIndex - 1] = true; values[relfilenoIndex - 1] = ObjectIdGetDatum(desc.relfilenode); @@ -1234,11 +1628,11 @@ void TrSwapRelfilenode(Relation rbRel, HeapTuple rbTup, bool isPart) replaces[frozenxid64Index - 1] = true; values[frozenxid64Index - 1] = TransactionIdGetDatum(desc.frozenxid64); - + // 鏋勯犳柊鐨勫厓缁 newTup = heap_modify_tuple(relTup, RelationGetDescr(relRel), values, nulls, replaces); - + // 鎵ц鍫嗚〃鏇存柊鎿嶄綔 simple_heap_update(relRel, &newTup->t_self, newTup); - + // 鏇存柊绱㈠紩 CatalogUpdateIndexes(relRel, newTup); heap_freetuple_ext(newTup); @@ -1250,7 +1644,7 @@ void TrSwapRelfilenode(Relation rbRel, HeapTuple rbTup, bool isPart) securec_check(rc, "\0", "\0"); rc = memset_s(replaces, sizeof(bool) * maxNattr, false, sizeof(bool) * maxNattr); securec_check(rc, "\0", "\0"); - + // 鐢熸垚鍥炴敹绔欏璞″悕 (void)TrGenObjName(NameStr(name), RelationRelationId, desc.relid); replaces[Anum_pg_recyclebin_rcyname - 1] = true; values[Anum_pg_recyclebin_rcyname - 1] = NameGetDatum(&name); @@ -1287,87 +1681,118 @@ void TrSwapRelfilenode(Relation rbRel, HeapTuple rbTup, bool isPart) } replaces[Anum_pg_recyclebin_rcyfrozenxid64 - 1] = true; - Datum xid64datum = heap_getattr(relTup, frozenxid64Index, RelationGetDescr(relRel), &isNull); - values[Anum_pg_recyclebin_rcyfrozenxid64 - 1] = DatumGetTransactionId(xid64datum); + if (isPartition) { + // 濡傛灉鏄垎鍖哄璞★紝灏嗗垎鍖哄璞$殑relfrozenxid64璁剧疆涓哄洖鏀剁珯鍏冪粍鐨勫睘鎬у + values[Anum_pg_recyclebin_rcyfrozenxid64 - 1] = + ShortTransactionIdGetDatum(((Form_pg_partition)GETSTRUCT(relTup))->relfrozenxid); + } else { + // 濡傛灉鏄潪鍒嗗尯瀵硅薄锛屽皢鍏崇郴瀵硅薄鐨剅elfrozenxid64璁剧疆涓哄洖鏀剁珯鍏冪粍鐨勫睘鎬у + values[Anum_pg_recyclebin_rcyfrozenxid64 - 1] = + ShortTransactionIdGetDatum(((Form_pg_class)GETSTRUCT(relTup))->relfrozenxid); + } + // 鏋勯犳柊鐨勫洖鏀剁珯鍏冪粍 newTup = heap_modify_tuple(rbTup, RelationGetDescr(rbRel), values, nulls, replaces); + // 鎵ц鍫嗚〃鏇存柊鎿嶄綔 simple_heap_update(rbRel, &newTup->t_self, newTup); + // 鏇存柊绱㈠紩 CatalogUpdateIndexes(rbRel, newTup); heap_freetuple_ext(newTup); + // 閲婃斁鍔ㄦ佸垎閰嶇殑鍐呭瓨 pfree(values); pfree(nulls); pfree(replaces); + // 閲婃斁鍏崇郴瀵硅薄鍏冪粍鐨勫唴瀛樺苟鍏抽棴鍏崇郴瀵硅薄鐨勮〃 heap_freetuple_ext(relTup); heap_close(relRel, RowExclusiveLock); return; } +/* + * 鍔熻兘锛氶獙璇佸熀琛ㄤ笌鍥炴敹绔欏璞℃槸鍚﹀尮閰 + * 鍙傛暟鍒楄〃锛 + * baseDesc锛氬熀琛ㄥ璞$殑鎻忚堪淇℃伅 + */ void TrBaseRelMatched(TrObjDesc *baseDesc) { - ObjectAddress obj = {RelationRelationId, baseDesc->relid}; - if (TrIsRefRbObject(&obj)) { + ObjectAddress obj = {RelationRelationId, baseDesc->relid}; // 鍒涘缓ObjectAddress缁撴瀯浣擄紝琛ㄧず鍩鸿〃瀵硅薄鐨勫湴鍧淇℃伅 + if (TrIsRefRbObject(&obj)) { // 鍒ゆ柇鍩鸿〃鏄惁鏈夊叧鑱旂殑鍥炴敹绔欏璞 + ereport(ERROR, (errcode(ERRCODE_UNDEFINED_OBJECT), + errmsg("relation \"%s\" does not exist", baseDesc->originname))); // 鎶ラ敊锛屾彁绀哄熀琛ㄤ笉瀛樺湪 + } + + Relation rel = RelationIdGetRelation(baseDesc->relid); // 鏍规嵁鍩鸿〃鐨凮ID鑾峰彇鍩鸿〃鐨凴elation缁撴瀯浣 + Assert(RelationIsValid(rel)); // 鏂█锛岀‘淇濊幏鍙栫殑Relation缁撴瀯浣撴槸鏈夋晥鐨 + if (RelationGetCreatecsn(rel) != + (CommitSeqNo)baseDesc->createcsn) { // 姣旇緝鍩鸿〃鐨勫垱寤篊SN涓庡洖鏀剁珯瀵硅薄鐨刢reatecsn鏄惁鍖归厤 + ereport(ERROR, (errmsg("The recycle object \"%s\" and relation \"%s\" mismatched.", baseDesc->name, + RelationGetRelationName(rel)))); // 鎶ラ敊锛屾彁绀哄洖鏀剁珯瀵硅薄鍜屽熀琛ㄤ笉鍖归厤 + } + + if (RelationGetChangecsn(rel) > + (CommitSeqNo)baseDesc->changecsn) { // 姣旇緝鍩鸿〃鐨勪慨鏀笴SN涓庡洖鏀剁珯瀵硅薄鐨刢hangecsn鏄惁鍖归厤 ereport(ERROR, - (errcode(ERRCODE_UNDEFINED_OBJECT), - errmsg("relation \"%s\" does not exist", baseDesc->originname))); + (errcode(ERRCODE_INTERNAL_ERROR), errmsg("The table definition of \"%s\" has been changed.", + RelationGetRelationName(rel)))); // 鎶ラ敊锛屾彁绀哄熀琛ㄥ畾涔夊凡鏇存敼 } - Relation rel = RelationIdGetRelation(baseDesc->relid); - Assert(RelationIsValid(rel)); - if (RelationGetCreatecsn(rel) != (CommitSeqNo)baseDesc->createcsn) { - ereport(ERROR, - (errmsg("The recycle object \"%s\" and relation \"%s\" mismatched.", - baseDesc->name, RelationGetRelationName(rel)))); - } - - if (RelationGetChangecsn(rel) > (CommitSeqNo)baseDesc->changecsn) { - ereport(ERROR, (errcode(ERRCODE_INTERNAL_ERROR), - errmsg("The table definition of \"%s\" has been changed.", - RelationGetRelationName(rel)))); - } - - RelationClose(rel); + RelationClose(rel); // 鍏抽棴鍩鸿〃鐨凴elation缁撴瀯浣 } +/* + * 鍔熻兘锛氭牴鎹洖鏀剁珯瀵硅薄鐨勫喕缁揦ID64鏉ヨ皟鏁翠紶鍏ョ殑frozenXID + * 鍙傛暟鍒楄〃锛 + * dbid锛氭暟鎹簱鐨凮ID + * frozenXID锛氫紶鍏ョ殑鍐荤粨XID鎸囬拡锛屽皢鏍规嵁鍥炴敹绔欏璞$殑XID鏉ヨ繘琛岃皟鏁 + */ void TrAdjustFrozenXid64(Oid dbid, TransactionId *frozenXID) { Relation rbRel; SysScanDesc sd; HeapTuple rbtup; - if (!TcapFeatureAvail()) { + if (!TcapFeatureAvail()) { // 妫鏌ユ槸鍚︽敮鎸乀CAP鍔熻兘 return; } - rbRel = heap_open(RecyclebinRelationId, AccessShareLock); + rbRel = heap_open(RecyclebinRelationId, AccessShareLock); // 鎵撳紑鍥炴敹绔欏叧绯 + + sd = systable_beginscan(rbRel, InvalidOid, false, NULL, 0, NULL); // 寮濮嬫壂鎻忓洖鏀剁珯鍏崇郴琛 + while ((rbtup = systable_getnext(sd)) != NULL) { // 寰幆閬嶅巻鍥炴敹绔欏璞 + Form_pg_recyclebin rbForm = (Form_pg_recyclebin)GETSTRUCT(rbtup); // 鑾峰彇鍥炴敹绔欏璞$殑鍏冪粍缁撴瀯 - sd = systable_beginscan(rbRel, InvalidOid, false, NULL, 0, NULL); - while ((rbtup = systable_getnext(sd)) != NULL) { - Form_pg_recyclebin rbForm = (Form_pg_recyclebin)GETSTRUCT(rbtup); TransactionId rcyfrozenxid64; if (rbForm->rcydbid != dbid || (rbForm->rcytype != RB_OBJ_TABLE && rbForm->rcytype != RB_OBJ_TOAST)) { - continue; + // 妫鏌ュ洖鏀剁珯瀵硅薄鏄惁涓庣粰瀹氱殑鏁版嵁搴揑D鍖归厤锛屽苟涓旂被鍨嬫槸琛ㄦ垨TOAST + continue; // 鑻ヤ笉鍖归厤锛岀户缁笅涓涓洖鏀剁珯瀵硅薄 } - rcyfrozenxid64 = TrRbGetRcyfrozenxid64(rbtup, rbRel); - Assert(TransactionIdIsNormal(rcyfrozenxid64)); + rcyfrozenxid64 = TrRbGetRcyfrozenxid64(rbtup, rbRel); // 鑾峰彇鍥炴敹绔欏璞$殑鍐荤粨XID64 + Assert(TransactionIdIsNormal(rcyfrozenxid64)); // 鏂█锛氱‘淇濊幏鍙栫殑XID64鏄甯哥殑浜嬪姟ID if (TransactionIdPrecedes(rcyfrozenxid64, *frozenXID)) { - *frozenXID = rcyfrozenxid64; + // 姣旇緝鍥炴敹绔欏璞$殑鍐荤粨XID64鍜屼紶鍏ョ殑鍐荤粨XID + *frozenXID = rcyfrozenxid64; // 鏇存柊浼犲叆鐨勫喕缁揦ID涓鸿緝灏忕殑XID64鍊 } } - systable_endscan(sd); - heap_close(rbRel, AccessShareLock); + systable_endscan(sd); // 缁撴潫鎵弿 + heap_close(rbRel, AccessShareLock); // 鍏抽棴鍥炴敹绔欏叧绯 return; } +/* + * 鍔熻兘锛氭鏌ユ寚瀹氭暟鎹簱鏄惁涓虹┖鐨勫洖鏀剁珯 + * 鍙傛暟鍒楄〃锛 + * dbid锛氭暟鎹簱鐨凮ID + */ bool TrRbIsEmptyDb(Oid dbid) { Relation rbRel; @@ -1375,18 +1800,23 @@ bool TrRbIsEmptyDb(Oid dbid) HeapTuple tup; ScanKeyData skey[1]; - ScanKeyInit(&skey[0], Anum_pg_recyclebin_rcydbid, BTEqualStrategyNumber, F_OIDEQ, - ObjectIdGetDatum(dbid)); + ScanKeyInit(&skey[0], Anum_pg_recyclebin_rcydbid, BTEqualStrategyNumber, F_OIDEQ, ObjectIdGetDatum(dbid)); - rbRel = heap_open(RecyclebinRelationId, AccessShareLock); - sd = systable_beginscan(rbRel, RecyclebinDbidRelidIndexId, true, NULL, 1, skey); - tup = systable_getnext(sd); - systable_endscan(sd); - heap_close(rbRel, AccessShareLock); + rbRel = heap_open(RecyclebinRelationId, AccessShareLock); // 鎵撳紑鍥炴敹绔欏叧绯 - return tup == NULL; + sd = systable_beginscan(rbRel, RecyclebinDbidRelidIndexId, true, NULL, 1, skey); // 寮濮嬫壂鎻忓洖鏀剁珯鍏崇郴琛 + tup = systable_getnext(sd); // 鑾峰彇鎵弿缁撴灉鐨勪笅涓涓厓缁 + systable_endscan(sd); // 缁撴潫鎵弿 + heap_close(rbRel, AccessShareLock); // 鍏抽棴鍥炴敹绔欏叧绯 + + return tup == NULL; // 鑻ュ厓缁勪负绌猴紝杩斿洖true锛屽惁鍒欒繑鍥瀎alse } +/* + * 鍔熻兘锛氭鏌ユ寚瀹氳〃绌洪棿鏄惁涓虹┖鐨勫洖鏀剁珯 + * 鍙傛暟鍒楄〃锛 + * spcId锛氳〃绌洪棿鐨凮ID + */ bool TrRbIsEmptySpc(Oid spcId) { Relation rbRel; @@ -1394,19 +1824,24 @@ bool TrRbIsEmptySpc(Oid spcId) ScanKeyData skey[1]; HeapTuple tup; - rbRel = heap_open(RecyclebinRelationId, AccessShareLock); + rbRel = heap_open(RecyclebinRelationId, AccessShareLock); // 鎵撳紑鍥炴敹绔欏叧绯 - ScanKeyInit(&skey[0], Anum_pg_recyclebin_rcytablespace, BTEqualStrategyNumber, - F_OIDEQ, ObjectIdGetDatum(spcId)); + ScanKeyInit(&skey[0], Anum_pg_recyclebin_rcytablespace, BTEqualStrategyNumber, F_OIDEQ, + ObjectIdGetDatum(spcId)); // 鍒涘缓鎵弿閿紝鍖归厤鎸囧畾琛ㄧ┖闂寸殑鍥炴敹绔欒褰 - sd = systable_beginscan(rbRel, RecyclebinDbidSpcidRcycsnIndexId, true, NULL, 1, skey); - tup = systable_getnext(sd); - systable_endscan(sd); - heap_close(rbRel, AccessShareLock); + sd = systable_beginscan(rbRel, RecyclebinDbidSpcidRcycsnIndexId, true, NULL, 1, skey); // 寮濮嬫壂鎻忓洖鏀剁珯鍏崇郴琛 + tup = systable_getnext(sd); // 鑾峰彇鎵弿缁撴灉鐨勪笅涓涓厓缁 + systable_endscan(sd); // 缁撴潫鎵弿 + heap_close(rbRel, AccessShareLock); // 鍏抽棴鍥炴敹绔欏叧绯 - return tup == NULL; + return tup == NULL; // 鑻ュ厓缁勪负绌猴紝杩斿洖true锛屽惁鍒欒繑鍥瀎alse } +/* + * 鍔熻兘锛氭鏌ユ寚瀹氭ā寮忔槸鍚︿负绌虹殑鍥炴敹绔 + * 鍙傛暟鍒楄〃锛 + * nspId锛氭ā寮忕殑OID + */ bool TrRbIsEmptySchema(Oid nspId) { Relation rbRel; @@ -1414,22 +1849,27 @@ bool TrRbIsEmptySchema(Oid nspId) ScanKeyData skey[2]; HeapTuple tup; - rbRel = heap_open(RecyclebinRelationId, AccessShareLock); + rbRel = heap_open(RecyclebinRelationId, AccessShareLock); // 鎵撳紑鍥炴敹绔欏叧绯 - ScanKeyInit(&skey[0], Anum_pg_recyclebin_rcynamespace, BTEqualStrategyNumber, - F_OIDEQ, ObjectIdGetDatum(nspId)); - ScanKeyInit(&skey[1], Anum_pg_recyclebin_rcydbid, BTEqualStrategyNumber, - F_OIDEQ, ObjectIdGetDatum(u_sess->proc_cxt.MyDatabaseId)); + ScanKeyInit(&skey[0], Anum_pg_recyclebin_rcynamespace, BTEqualStrategyNumber, F_OIDEQ, + ObjectIdGetDatum(nspId)); // 鍒涘缓鎵弿閿紝鍖归厤鎸囧畾妯″紡鐨勫洖鏀剁珯璁板綍 + ScanKeyInit(&skey[1], Anum_pg_recyclebin_rcydbid, BTEqualStrategyNumber, F_OIDEQ, + ObjectIdGetDatum(u_sess->proc_cxt.MyDatabaseId)); // 鍒涘缓鎵弿閿紝鍖归厤褰撳墠鏁版嵁搴揑D - sd = systable_beginscan(rbRel, RecyclebinDbidNspOrinameIndexId, true, NULL, 2, skey); - tup = systable_getnext(sd); + sd = systable_beginscan(rbRel, RecyclebinDbidNspOrinameIndexId, true, NULL, 2, skey); // 寮濮嬫壂鎻忓洖鏀剁珯鍏崇郴琛 + tup = systable_getnext(sd); // 鑾峰彇鎵弿缁撴灉鐨勪笅涓涓厓缁 - systable_endscan(sd); - heap_close(rbRel, AccessShareLock); + systable_endscan(sd); // 缁撴潫鎵弿 + heap_close(rbRel, AccessShareLock); // 鍏抽棴鍥炴敹绔欏叧绯 - return tup == NULL; + return tup == NULL; // 鑻ュ厓缁勪负绌猴紝杩斿洖true锛屽惁鍒欒繑鍥瀎alse } +/* + * 鍔熻兘锛氭鏌ユ寚瀹氱敤鎴锋槸鍚︿负绌虹殑鍥炴敹绔 + * 鍙傛暟鍒楄〃锛 + * roleId锛氱敤鎴风殑OID + */ bool TrRbIsEmptyUser(Oid roleId) { Relation rbRel; @@ -1437,11 +1877,11 @@ bool TrRbIsEmptyUser(Oid roleId) HeapTuple tup; bool found = false; - rbRel = heap_open(RecyclebinRelationId, AccessShareLock); + rbRel = heap_open(RecyclebinRelationId, AccessShareLock); // 鎵撳紑鍥炴敹绔欏叧绯 - sd = systable_beginscan(rbRel, InvalidOid, false, NULL, 0, NULL); + sd = systable_beginscan(rbRel, InvalidOid, false, NULL, 0, NULL); // 寮濮嬫壂鎻忓洖鏀剁珯鍏崇郴琛 - while ((tup = systable_getnext(sd)) != NULL) { + while ((tup = systable_getnext(sd)) != NULL) { // 寰幆鑾峰彇鎵弿缁撴灉鐨勪笅涓涓厓缁 Form_pg_recyclebin rbForm = (Form_pg_recyclebin)GETSTRUCT(tup); if ((TrObjType)rbForm->rcytype != RB_OBJ_TABLE || rbForm->rcyowner != roleId) { continue; @@ -1451,111 +1891,132 @@ bool TrRbIsEmptyUser(Oid roleId) break; } - systable_endscan(sd); - heap_close(rbRel, AccessShareLock); + systable_endscan(sd); // 缁撴潫鎵弿 + heap_close(rbRel, AccessShareLock); // 鍏抽棴鍥炴敹绔欏叧绯 - return !found; + return !found; // 鑻ユ壘涓嶅埌涓庣敤鎴风浉鍏崇殑鍥炴敹绔欏璞★紝杩斿洖true锛屽惁鍒欒繑鍥瀎alse } +/* + * 鍔熻兘锛氭鏌ョ粰瀹歄ID鏄惁瀛樺湪浜庢寚瀹氱殑OID鍒楄〃涓 + * 鍙傛暟鍒楄〃锛 + * lOid锛歄ID鍒楄〃 + * oid锛氳妫鏌ョ殑OID + */ static bool TrOidExists(const List *lOid, Oid oid) { ListCell *cell = NULL; - if (lOid == NULL) { - return false; + if (lOid == NULL) { // 妫鏌ID鍒楄〃鏄惁涓虹┖ + return false; // 濡傛灉涓虹┖锛岃繑鍥瀎alse } - foreach (cell, lOid) { - if (oid == (*(Oid *)lfirst(cell))) { - return true; + foreach (cell, lOid) { // 閬嶅巻OID鍒楄〃涓殑姣忎釜鍏冪礌 + if (oid == (*(Oid *)lfirst(cell))) { // 妫鏌ュ綋鍓嶅厓绱犳槸鍚︿笌鎸囧畾鐨凮ID鐩哥瓑 + return true; // 濡傛灉鐩哥瓑锛岃繑鍥瀟rue } } - return false; + return false; // 濡傛灉娌℃湁鎵惧埌鍖归厤鐨凮ID锛岃繑鍥瀎alse } +/* + * 鍔熻兘锛氳幏鍙栧寘鍚洖鏀剁珯涓瓨鍦ㄧ殑鏁版嵁搴撳悕绉扮殑鍒楄〃 + */ List *TrGetDbListRcy(void) { Relation rbRel; SysScanDesc sd; HeapTuple tup; - List *lName = NIL; - List *lOid = NIL; - char *dbname = NULL; + List *lName = NIL; // 鐢ㄤ簬瀛樺偍鏁版嵁搴撳悕绉扮殑List + List *lOid = NIL; // 鐢ㄤ簬瀛樺偍鏁版嵁搴揙ID鐨凩ist + char *dbname = NULL; // 鐢ㄤ簬瀛樺偍鏁版嵁搴撳悕绉扮殑涓存椂鍙橀噺 - rbRel = heap_open(RecyclebinRelationId, AccessShareLock); + rbRel = heap_open(RecyclebinRelationId, AccessShareLock); // 鎵撳紑鍥炴敹绔欒〃 - sd = systable_beginscan(rbRel, InvalidOid, false, NULL, 0, NULL); + sd = systable_beginscan(rbRel, InvalidOid, false, NULL, 0, NULL); // 寮濮嬬郴缁熻〃鎵弿 - while ((tup = systable_getnext(sd)) != NULL) { + while ((tup = systable_getnext(sd)) != NULL) { // 閬嶅巻绯荤粺琛ㄦ壂鎻忕粨鏋 Form_pg_recyclebin rbForm = (Form_pg_recyclebin)GETSTRUCT(tup); - if (TrOidExists(lOid, rbForm->rcydbid)) { - continue; - } - Oid *oid = (Oid *)palloc0(sizeof(Oid)); - *oid = rbForm->rcydbid; - lOid = lappend(lOid, oid); - dbname = get_database_name(rbForm->rcydbid); - if (dbname == NULL) { - ereport(ERROR, - (errcode(ERRCODE_UNDEFINED_DATABASE), - errmsg("database \"%u\" does not exist", rbForm->rcydbid))); + if (TrOidExists(lOid, rbForm->rcydbid)) { // 妫鏌ュ綋鍓嶆暟鎹簱OID鏄惁宸插瓨鍦ㄤ簬lOid鍒楄〃涓 + continue; // 濡傛灉瀛樺湪锛岀户缁笅涓娆″惊鐜 } - lName = lappend(lName, dbname); + + Oid *oid = (Oid *)palloc0(sizeof(Oid)); // 涓烘暟鎹簱OID鍒嗛厤鍐呭瓨 + *oid = rbForm->rcydbid; // 灏嗗綋鍓嶆暟鎹簱OID璧嬪肩粰oid + lOid = lappend(lOid, oid); // 灏唎id娣诲姞鍒發Oid鍒楄〃涓 + + dbname = get_database_name(rbForm->rcydbid); // 鑾峰彇褰撳墠鏁版嵁搴揙ID瀵瑰簲鐨勬暟鎹簱鍚嶇О + if (dbname == NULL) { // 妫鏌ユ暟鎹簱鍚嶇О鏄惁涓虹┖ + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_DATABASE), errmsg("database \"%u\" does not exist", rbForm->rcydbid))); + } + lName = lappend(lName, dbname); // 灏嗘暟鎹簱鍚嶇О娣诲姞鍒發Name鍒楄〃涓 } - list_free_deep(lOid); + list_free_deep(lOid); // 閲婃斁lOid鍒楄〃涓殑鍐呭瓨 - systable_endscan(sd); - heap_close(rbRel, AccessShareLock); + systable_endscan(sd); // 缁撴潫绯荤粺琛ㄦ壂鎻 + heap_close(rbRel, AccessShareLock); // 鍏抽棴鍥炴敹绔欒〃 - return lName; + return lName; // 杩斿洖鍖呭惈鏁版嵁搴撳悕绉扮殑List } +/* + * 鍔熻兘锛氳幏鍙栧洖鏀剁珯涓寚瀹氳〃绌洪棿涓瓨鍦ㄧ殑鏁版嵁搴撳悕绉扮殑鍒楄〃 + * 鍙傛暟鍒楄〃锛 + * spcId锛氳〃绌洪棿OID + */ List *TrGetDbListSpc(Oid spcId) { - List *lName = NIL; - List *lOid = NIL; - char *dbname = NULL; + List *lName = NIL; // 鐢ㄤ簬瀛樺偍鏁版嵁搴撳悕绉扮殑List + List *lOid = NIL; // 鐢ㄤ簬瀛樺偍鏁版嵁搴揙ID鐨凩ist + char *dbname = NULL; // 鐢ㄤ簬瀛樺偍鏁版嵁搴撳悕绉扮殑涓存椂鍙橀噺 Relation rbRel; SysScanDesc sd; ScanKeyData skey[1]; HeapTuple tup; - rbRel = heap_open(RecyclebinRelationId, AccessShareLock); + rbRel = heap_open(RecyclebinRelationId, AccessShareLock); // 鎵撳紑鍥炴敹绔欒〃 - ScanKeyInit(&skey[0], Anum_pg_recyclebin_rcytablespace, BTEqualStrategyNumber, - F_OIDEQ, ObjectIdGetDatum(spcId)); + ScanKeyInit(&skey[0], Anum_pg_recyclebin_rcytablespace, BTEqualStrategyNumber, F_OIDEQ, + ObjectIdGetDatum(spcId)); // 鍒濆鍖栨壂鎻忛敭锛屾牴鎹〃绌洪棿OID绛涢 - sd = systable_beginscan(rbRel, RecyclebinDbidSpcidRcycsnIndexId, true, NULL, 1, skey); + sd = systable_beginscan(rbRel, RecyclebinDbidSpcidRcycsnIndexId, true, NULL, 1, skey); // 寮濮嬬郴缁熻〃鎵弿 - while ((tup = systable_getnext(sd)) != NULL) { + while ((tup = systable_getnext(sd)) != NULL) { // 閬嶅巻绯荤粺琛ㄦ壂鎻忕粨鏋 Form_pg_recyclebin rbForm = (Form_pg_recyclebin)GETSTRUCT(tup); - if (TrOidExists(lOid, rbForm->rcydbid)) { - continue; - } - Oid *oid = (Oid *)palloc0(sizeof(Oid)); - *oid = rbForm->rcydbid; - lOid = lappend(lOid, oid); - dbname = get_database_name(rbForm->rcydbid); - if (dbname == NULL) { - ereport(ERROR, - (errcode(ERRCODE_UNDEFINED_DATABASE), - errmsg("database \"%u\" does not exist", rbForm->rcydbid))); + if (TrOidExists(lOid, rbForm->rcydbid)) { // 妫鏌ュ綋鍓嶆暟鎹簱OID鏄惁宸插瓨鍦ㄤ簬lOid鍒楄〃涓 + continue; // 濡傛灉瀛樺湪锛岀户缁笅涓娆″惊鐜 } - lName = lappend(lName, dbname); + + Oid *oid = (Oid *)palloc0(sizeof(Oid)); // 涓烘暟鎹簱OID鍒嗛厤鍐呭瓨 + *oid = rbForm->rcydbid; // 灏嗗綋鍓嶆暟鎹簱OID璧嬪肩粰oid + lOid = lappend(lOid, oid); // 灏唎id娣诲姞鍒發Oid鍒楄〃涓 + + dbname = get_database_name(rbForm->rcydbid); // 鑾峰彇褰撳墠鏁版嵁搴揙ID瀵瑰簲鐨勬暟鎹簱鍚嶇О + if (dbname == NULL) { // 妫鏌ユ暟鎹簱鍚嶇О鏄惁涓虹┖ + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_DATABASE), errmsg("database \"%u\" does not exist", rbForm->rcydbid))); + } + lName = lappend(lName, dbname); // 灏嗘暟鎹簱鍚嶇О娣诲姞鍒發Name鍒楄〃涓 } - list_free_deep(lOid); + list_free_deep(lOid); // 閲婃斁lOid鍒楄〃涓殑鍐呭瓨 - systable_endscan(sd); - heap_close(rbRel, AccessShareLock); + systable_endscan(sd); // 缁撴潫绯荤粺琛ㄦ壂鎻 + heap_close(rbRel, AccessShareLock); // 鍏抽棴鍥炴敹绔欒〃 - return lName; + return lName; // 杩斿洖鍖呭惈鏁版嵁搴撳悕绉扮殑List } +/* + * 鍔熻兘锛氳幏鍙栧洖鏀剁珯涓寚瀹氭ā寮忎腑瀛樺湪鐨勬暟鎹簱鍚嶇О鐨勫垪琛 + * 鍙傛暟鍒楄〃锛 + * nspId锛氭ā寮廜ID + */ List *TrGetDbListSchema(Oid nspId) { Relation rbRel; @@ -1563,116 +2024,136 @@ List *TrGetDbListSchema(Oid nspId) ScanKeyData skey[1]; HeapTuple tup; - List *lName = NIL; - List *lOid = NIL; - char *dbname = NULL; + List *lName = NIL; // 鐢ㄤ簬瀛樺偍鏁版嵁搴撳悕绉扮殑List + List *lOid = NIL; // 鐢ㄤ簬瀛樺偍鏁版嵁搴揙ID鐨凩ist + char *dbname = NULL; // 鐢ㄤ簬瀛樺偍鏁版嵁搴撳悕绉扮殑涓存椂鍙橀噺 - rbRel = heap_open(RecyclebinRelationId, AccessShareLock); + rbRel = heap_open(RecyclebinRelationId, AccessShareLock); // 鎵撳紑鍥炴敹绔欒〃 - ScanKeyInit(&skey[0], Anum_pg_recyclebin_rcynamespace, BTEqualStrategyNumber, - F_OIDEQ, ObjectIdGetDatum(nspId)); + ScanKeyInit(&skey[0], Anum_pg_recyclebin_rcynamespace, BTEqualStrategyNumber, F_OIDEQ, + ObjectIdGetDatum(nspId)); // 鍒濆鍖栨壂鎻忛敭锛屾牴鎹ā寮廜ID绛涢 - sd = systable_beginscan(rbRel, RecyclebinDbidNspOrinameIndexId, true, NULL, 1, skey); + sd = systable_beginscan(rbRel, RecyclebinDbidNspOrinameIndexId, true, NULL, 1, skey); // 寮濮嬬郴缁熻〃鎵弿 - while ((tup = systable_getnext(sd)) != NULL) { + while ((tup = systable_getnext(sd)) != NULL) { // 閬嶅巻绯荤粺琛ㄦ壂鎻忕粨鏋 Form_pg_recyclebin rbForm = (Form_pg_recyclebin)GETSTRUCT(tup); - if (TrOidExists(lOid, rbForm->rcydbid)) { - continue; - } - Oid *oid = (Oid *)palloc0(sizeof(Oid)); - *oid = rbForm->rcydbid; - lOid = lappend(lOid, oid); - dbname = get_database_name(rbForm->rcydbid); - if (dbname == NULL) { - ereport(ERROR, - (errcode(ERRCODE_UNDEFINED_DATABASE), - errmsg("database \"%u\" does not exist", rbForm->rcydbid))); + if (TrOidExists(lOid, rbForm->rcydbid)) { // 妫鏌ュ綋鍓嶆暟鎹簱OID鏄惁宸插瓨鍦ㄤ簬lOid鍒楄〃涓 + continue; // 濡傛灉瀛樺湪锛岀户缁笅涓娆″惊鐜 } - lName = lappend(lName, dbname); + + Oid *oid = (Oid *)palloc0(sizeof(Oid)); // 涓烘暟鎹簱OID鍒嗛厤鍐呭瓨 + *oid = rbForm->rcydbid; // 灏嗗綋鍓嶆暟鎹簱OID璧嬪肩粰oid + lOid = lappend(lOid, oid); // 灏唎id娣诲姞鍒發Oid鍒楄〃涓 + + dbname = get_database_name(rbForm->rcydbid); // 鑾峰彇褰撳墠鏁版嵁搴揙ID瀵瑰簲鐨勬暟鎹簱鍚嶇О + if (dbname == NULL) { // 妫鏌ユ暟鎹簱鍚嶇О鏄惁涓虹┖ + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_DATABASE), errmsg("database \"%u\" does not exist", rbForm->rcydbid))); + } + lName = lappend(lName, dbname); // 灏嗘暟鎹簱鍚嶇О娣诲姞鍒發Name鍒楄〃涓 } - list_free_deep(lOid); + list_free_deep(lOid); // 閲婃斁lOid鍒楄〃涓殑鍐呭瓨 - systable_endscan(sd); - heap_close(rbRel, AccessShareLock); + systable_endscan(sd); // 缁撴潫绯荤粺琛ㄦ壂鎻 + heap_close(rbRel, AccessShareLock); // 鍏抽棴鍥炴敹绔欒〃 - return lName; + return lName; // 杩斿洖鍖呭惈鏁版嵁搴撳悕绉扮殑List } +/* + * 鍔熻兘锛氳幏鍙栧洖鏀剁珯涓寚瀹氳鑹叉嫢鏈夌殑鏁版嵁搴撳悕绉扮殑鍒楄〃 + * 鍙傛暟鍒楄〃锛 + * roleId锛氳鑹睴ID + */ List *TrGetDbListUser(Oid roleId) { Relation rbRel; SysScanDesc sd; HeapTuple tup; - List *lName = NIL; - List *lOid = NIL; - char *dbname = NULL; + List *lName = NIL; // 鐢ㄤ簬瀛樺偍鏁版嵁搴撳悕绉扮殑List + List *lOid = NIL; // 鐢ㄤ簬瀛樺偍鏁版嵁搴揙ID鐨凩ist + char *dbname = NULL; // 鐢ㄤ簬瀛樺偍鏁版嵁搴撳悕绉扮殑涓存椂鍙橀噺 - rbRel = heap_open(RecyclebinRelationId, AccessShareLock); + rbRel = heap_open(RecyclebinRelationId, AccessShareLock); // 鎵撳紑鍥炴敹绔欒〃 - sd = systable_beginscan(rbRel, InvalidOid, false, NULL, 0, NULL); + sd = systable_beginscan(rbRel, InvalidOid, false, NULL, 0, NULL); // 寮濮嬬郴缁熻〃鎵弿 - while ((tup = systable_getnext(sd)) != NULL) { + while ((tup = systable_getnext(sd)) != NULL) { // 閬嶅巻绯荤粺琛ㄦ壂鎻忕粨鏋 Form_pg_recyclebin rbForm = (Form_pg_recyclebin)GETSTRUCT(tup); + + // 妫鏌ュ綋鍓嶈褰曟槸鍚︿负琛ㄥ璞′笖鎷ユ湁鎸囧畾瑙掕壊 if ((TrObjType)rbForm->rcytype != RB_OBJ_TABLE || rbForm->rcyowner != roleId) { - continue; + continue; // 濡傛灉涓嶆弧瓒虫潯浠讹紝缁х画涓嬩竴娆″惊鐜 } - if (TrOidExists(lOid, rbForm->rcydbid)) { - continue; - } - Oid *oid = (Oid *)palloc0(sizeof(Oid)); - *oid = rbForm->rcydbid; - lOid = lappend(lOid, oid); - dbname = get_database_name(rbForm->rcydbid); - if (dbname == NULL) { + if (TrOidExists(lOid, rbForm->rcydbid)) { // 妫鏌ュ綋鍓嶆暟鎹簱OID鏄惁宸插瓨鍦ㄤ簬lOid鍒楄〃涓 + continue; // 濡傛灉瀛樺湪锛岀户缁笅涓娆″惊鐜 + } + + Oid *oid = (Oid *)palloc0(sizeof(Oid)); // 涓烘暟鎹簱OID鍒嗛厤鍐呭瓨 + *oid = rbForm->rcydbid; // 灏嗗綋鍓嶆暟鎹簱OID璧嬪肩粰oid + lOid = lappend(lOid, oid); // 灏唎id娣诲姞鍒發Oid鍒楄〃涓 + + dbname = get_database_name(rbForm->rcydbid); // 鑾峰彇褰撳墠鏁版嵁搴揙ID瀵瑰簲鐨勬暟鎹簱鍚嶇О + if (dbname == NULL) { // 妫鏌ユ暟鎹簱鍚嶇О鏄惁涓虹┖ ereport(ERROR, - (errcode(ERRCODE_UNDEFINED_DATABASE), - errmsg("database \"%u\" does not exist", rbForm->rcydbid))); + (errcode(ERRCODE_UNDEFINED_DATABASE), errmsg("database \"%u\" does not exist", rbForm->rcydbid))); } - - lName = lappend(lName, dbname); + lName = lappend(lName, dbname); // 灏嗘暟鎹簱鍚嶇О娣诲姞鍒發Name鍒楄〃涓 } - list_free_deep(lOid); + list_free_deep(lOid); // 閲婃斁lOid鍒楄〃涓殑鍐呭瓨 - systable_endscan(sd); - heap_close(rbRel, AccessShareLock); + systable_endscan(sd); // 缁撴潫绯荤粺琛ㄦ壂鎻 + heap_close(rbRel, AccessShareLock); // 鍏抽棴鍥炴敹绔欒〃 - return lName; + return lName; // 杩斿洖鍖呭惈鏁版嵁搴撳悕绉扮殑List } /* * TrGetDatabaseList * Return a list of all databases found in pg_database. */ +/* + * 鍔熻兘锛氳幏鍙栭潪妯℃澘鏁版嵁搴撶殑鍚嶇О鍒楄〃 + */ List *TrGetDbListAuto(void) { - List* dblist = NIL; + List *dblist = NIL; // 鐢ㄤ簬瀛樺偍鏁版嵁搴撳悕绉扮殑List Relation rel; SysScanDesc sd; HeapTuple tup; - rel = heap_open(DatabaseRelationId, AccessShareLock); - sd = systable_beginscan(rel, InvalidOid, false, NULL, 0, NULL); + rel = heap_open(DatabaseRelationId, AccessShareLock); // 鎵撳紑鏁版嵁搴撳叧绯昏〃 - while ((tup = systable_getnext(sd)) != NULL) { + sd = systable_beginscan(rel, InvalidOid, false, NULL, 0, NULL); // 寮濮嬬郴缁熻〃鎵弿 + + while ((tup = systable_getnext(sd)) != NULL) { // 閬嶅巻绯荤粺琛ㄦ壂鎻忕粨鏋 Form_pg_database pgdatabase = (Form_pg_database)GETSTRUCT(tup); - if (strcmp(NameStr(pgdatabase->datname), "template0") == 0 || + + // 妫鏌ユ暟鎹簱鍚嶇О鏄惁涓 "template0" 鎴 "template1" + if (strcmp(NameStr(pgdatabase->datname), "template0") == 0 || strcmp(NameStr(pgdatabase->datname), "template1") == 0) { - continue; + continue; // 濡傛灉鏄ā鏉挎暟鎹簱锛岀户缁笅涓娆″惊鐜 } - dblist = lappend(dblist, pstrdup(NameStr(pgdatabase->datname))); + + dblist = lappend(dblist, pstrdup(NameStr(pgdatabase->datname))); // 灏嗛潪妯℃澘鏁版嵁搴撳悕绉版坊鍔犲埌dblist鍒楄〃涓 } - systable_endscan(sd); - heap_close(rel, AccessShareLock); + systable_endscan(sd); // 缁撴潫绯荤粺琛ㄦ壂鎻 + heap_close(rel, AccessShareLock); // 鍏抽棴鏁版嵁搴撳叧绯昏〃 - return dblist; + return dblist; // 杩斿洖鍖呭惈闈炴ā鏉挎暟鎹簱鍚嶇О鐨凩ist } +/* + * 鍔熻兘锛氭鏌ョ粰瀹氬璞℃槸鍚﹀湪鍥炴敹绔欎腑 + * 鍙傛暟鍒楄〃锛 + * obj锛氳妫鏌ョ殑瀵硅薄鐨勫湴鍧 + */ static bool TrObjInRecyclebin(const ObjectAddress *obj) { Relation rbRel; @@ -1681,17 +2162,20 @@ static bool TrObjInRecyclebin(const ObjectAddress *obj) ScanKeyData skey[2]; bool found = false; + // 妫鏌ュ璞℃槸鍚︽槸鍏崇郴绫 if (getObjectClass(obj) != OCLASS_CLASS) { return false; } + // 璁剧疆鎵弿閿硷紝鐢ㄤ簬妫绱笌鏁版嵁搴揑D鍜屽叧绯籌D鍖归厤鐨勫洖鏀剁珯鏉$洰 ScanKeyInit(&skey[0], Anum_pg_recyclebin_rcydbid, BTEqualStrategyNumber, F_OIDEQ, - ObjectIdGetDatum(u_sess->proc_cxt.MyDatabaseId)); - ScanKeyInit(&skey[1], Anum_pg_recyclebin_rcyrelid, BTEqualStrategyNumber, F_OIDEQ, - ObjectIdGetDatum(obj->objectId)); + ObjectIdGetDatum(u_sess->proc_cxt.MyDatabaseId)); + ScanKeyInit(&skey[1], Anum_pg_recyclebin_rcyrelid, BTEqualStrategyNumber, F_OIDEQ, ObjectIdGetDatum(obj->objectId)); - rbRel = heap_open(RecyclebinRelationId, AccessShareLock); - sd = systable_beginscan(rbRel, RecyclebinDbidRelidIndexId, true, NULL, 2, skey); + rbRel = heap_open(RecyclebinRelationId, AccessShareLock); // 鎵撳紑鍥炴敹绔欏叧绯昏〃 + sd = systable_beginscan(rbRel, RecyclebinDbidRelidIndexId, true, NULL, 2, skey); // 寮濮嬬郴缁熻〃鎵弿 + + // 閬嶅巻鎵弿缁撴灉锛屾鏌ユ槸鍚︽湁涓庢搷浣滀负鍒犻櫎鐨勫洖鏀剁珯鏉$洰鍖归厤 while ((tup = systable_getnext(sd)) != NULL) { Form_pg_recyclebin rbForm = (Form_pg_recyclebin)GETSTRUCT(tup); if ((TrObjType)rbForm->rcyoperation == 'd') { @@ -1699,38 +2183,44 @@ static bool TrObjInRecyclebin(const ObjectAddress *obj) break; } } - systable_endscan(sd); - heap_close(rbRel, AccessShareLock); + systable_endscan(sd); // 缁撴潫绯荤粺琛ㄦ壂鎻 + heap_close(rbRel, AccessShareLock); // 鍏抽棴鍥炴敹绔欏叧绯昏〃 - return found; + return found; // 杩斿洖鏄惁鎵惧埌涓庢搷浣滀负鍒犻櫎鐨勫洖鏀剁珯鏉$洰鍖归厤鐨勬爣蹇 } - /* * May this object be a recyclebin object? * true: with "BIN$" prefix, or not a Relation\Type\Trigger\Constraint\Rule * false: without "BIN$" prefix, or not exists */ +/* + * 鍔熻兘锛氭鏌ュ璞℃槸鍚﹀彲鑳芥槸鍥炴敹绔欏璞 + * 鍙傛暟鍒楄〃锛 + * classid锛氬璞℃墍灞炵殑绫诲埆ID + * objid锛氬璞$殑ID + * objname锛氬璞$殑鍚嶇О锛堝彲閫夛級 + */ static bool TrMaybeRbObject(Oid classid, Oid objid, const char *objname = NULL) { HeapTuple tup; - /* Note: we preserve rule origin name when RbDrop. */ + /* 娉ㄦ剰锛氬湪 RbDrop 鏃讹紝鎴戜滑淇濈暀瑙勫垯婧愬悕绉般*/ if (classid != RewriteRelationId && objname) { - return strncmp(objname, "BIN$", 4) == 0; + return strncmp(objname, "BIN$", 4) == 0; // 濡傛灉瀵硅薄鍚嶇О浠 "BIN$" 寮澶达紝杩斿洖 true } switch (classid) { case RelationRelationId: - tup = SearchSysCache1(RELOID, ObjectIdGetDatum(objid)); + tup = SearchSysCache1(RELOID, ObjectIdGetDatum(objid)); // 鍦ㄧ郴缁熺紦瀛樹腑鏌ユ壘鍏崇郴绫诲璞 if (tup != NULL) { - objname = NameStr(((Form_pg_class)GETSTRUCT(tup))->relname); + objname = NameStr(((Form_pg_class)GETSTRUCT(tup))->relname); // 鑾峰彇鍏崇郴绫诲璞$殑鍚嶇О ReleaseSysCache(tup); } break; case TypeRelationId: - tup = SearchSysCache1(TYPEOID, ObjectIdGetDatum(objid)); + tup = SearchSysCache1(TYPEOID, ObjectIdGetDatum(objid)); // 鍦ㄧ郴缁熺紦瀛樹腑鏌ユ壘绫诲瀷瀵硅薄 if (tup != NULL) { - objname = NameStr(((Form_pg_type)GETSTRUCT(tup))->typname); + objname = NameStr(((Form_pg_type)GETSTRUCT(tup))->typname); // 鑾峰彇绫诲瀷瀵硅薄鐨勫悕绉 ReleaseSysCache(tup); } break; @@ -1739,158 +2229,2687 @@ static bool TrMaybeRbObject(Oid classid, Oid objid, const char *objname = NULL) ScanKeyData skey[1]; SysScanDesc sd; - relTrig = heap_open(TriggerRelationId, AccessShareLock); - ScanKeyInit(&skey[0], ObjectIdAttributeNumber, BTEqualStrategyNumber, - F_OIDEQ, ObjectIdGetDatum(objid)); - sd = systable_beginscan(relTrig, TriggerOidIndexId, true, NULL, 1, skey); + relTrig = heap_open(TriggerRelationId, AccessShareLock); // 鎵撳紑瑙﹀彂鍣ㄥ叧绯昏〃 + ScanKeyInit(&skey[0], ObjectIdAttributeNumber, BTEqualStrategyNumber, F_OIDEQ, ObjectIdGetDatum(objid)); + sd = systable_beginscan(relTrig, TriggerOidIndexId, true, NULL, 1, skey); // 寮濮嬬郴缁熻〃鎵弿 if ((tup = systable_getnext(sd)) != NULL) { - objname = NameStr(((Form_pg_trigger)GETSTRUCT(tup))->tgname); + objname = NameStr(((Form_pg_trigger)GETSTRUCT(tup))->tgname); // 鑾峰彇瑙﹀彂鍣ㄥ璞$殑鍚嶇О } - systable_endscan(sd); - heap_close(relTrig, AccessShareLock); + systable_endscan(sd); // 缁撴潫绯荤粺琛ㄦ壂鎻 + heap_close(relTrig, AccessShareLock); // 鍏抽棴瑙﹀彂鍣ㄥ叧绯昏〃 break; } case ConstraintRelationId: - tup = SearchSysCache1(CONSTROID, ObjectIdGetDatum(objid)); + tup = SearchSysCache1(CONSTROID, ObjectIdGetDatum(objid)); // 鍦ㄧ郴缁熺紦瀛樹腑鏌ユ壘绾︽潫瀵硅薄 if (tup != NULL) { - objname = NameStr(((Form_pg_constraint)GETSTRUCT(tup))->conname); + objname = NameStr(((Form_pg_constraint)GETSTRUCT(tup))->conname); // 鑾峰彇绾︽潫瀵硅薄鐨勫悕绉 ReleaseSysCache(tup); } break; case NamespaceRelationId: - /* Treate Namespace as non-recyclebin object. */ + /* 灏嗗懡鍚嶇┖闂磋涓洪潪鍥炴敹绔欏璞° */ return false; default: - /* May be a recyclebin object. */ + /* 鍙兘鏄洖鏀剁珯瀵硅薄銆 */ return true; } if (objname) { - return strncmp(objname, "BIN$", 4) == 0; + return strncmp(objname, "BIN$", 4) == 0; // 濡傛灉瀵硅薄鍚嶇О浠 "BIN$" 寮澶达紝杩斿洖 true } - return false; + return false; // 榛樿鎯呭喌涓嬶紝杩斿洖 false } +/* + * 鍔熻兘锛氶掑綊鍦版鏌ュ璞″強鍏跺紩鐢ㄥ璞℃槸鍚﹀湪鍥炴敹绔欎腑 + * 鍙傛暟鍒楄〃锛 + * depRel锛氬璞℃墍鍦ㄥ叧绯 + * obj锛氬緟妫鏌ョ殑瀵硅薄鍦板潃 + * objSet锛氬璞″湴鍧闆嗗悎 + */ static bool TrIsRefRbObjectImpl(Relation depRel, const ObjectAddress *obj, ObjectAddresses *objSet) { int startIdx; - if (TrObjInRecyclebin(obj)) { + if (TrObjInRecyclebin(obj)) { // 妫鏌ュ璞℃槸鍚﹀湪鍥炴敹绔欎腑 return true; } - startIdx = objSet->numrefs; + startIdx = objSet->numrefs; // 璁板綍瀵硅薄鍦板潃闆嗗悎涓殑寮曠敤瀵硅薄鏁伴噺 - if (!TrMaybeRbObject(obj->classId, obj->objectId)) { + if (!TrMaybeRbObject(obj->classId, obj->objectId)) { // 妫鏌ュ璞℃槸鍚﹀彲鑳芥槸鍥炴敹绔欏璞 return false; } - TrFindAllRefObjs(depRel, obj, objSet, true); - TrFindAllInternalObjs(depRel, obj, objSet, true); + TrFindAllRefObjs(depRel, obj, objSet, true); // 鏌ユ壘瀵硅薄鐨勬墍鏈夊紩鐢ㄥ璞 + TrFindAllInternalObjs(depRel, obj, objSet, true); // 鏌ユ壘瀵硅薄鐨勬墍鏈夊唴閮ㄥ璞 - for (int i = startIdx; i < objSet->numrefs; i++) { + for (int i = startIdx; i < objSet->numrefs; i++) { // 閬嶅巻鏂版坊鍔犵殑寮曠敤瀵硅薄 if (TrIsRefRbObjectImpl(depRel, &objSet->refs[i], objSet)) { - return true; + return true; // 濡傛灉寮曠敤瀵硅薄鎴栧叾寮曠敤瀵硅薄鍦ㄥ洖鏀剁珯涓紝杩斿洖 true } } - return false; + return false; // 榛樿鎯呭喌涓嬶紝杩斿洖 false } /* object is a rb object, or reference to a rb object. */ +/* + * 鍔熻兘锛氭鏌ュ璞″強鍏跺紩鐢ㄥ璞℃槸鍚﹀湪鍥炴敹绔欎腑锛堣皟鐢ㄥ疄鐜板嚱鏁帮級 + * 鍙傛暟鍒楄〃锛 + * obj锛氬緟妫鏌ョ殑瀵硅薄鍦板潃 + * depRel锛氬璞℃墍鍦ㄥ叧绯 + */ static bool TrIsRefRbObject(const ObjectAddress *obj, Relation depRel) { - ObjectAddresses *objSet = new_object_addresses(); - bool relArgNull = depRel == NULL; + ObjectAddresses *objSet = new_object_addresses(); // 鍒涘缓瀵硅薄鍦板潃闆嗗悎 + bool relArgNull = depRel == NULL; // 妫鏌ヤ紶鍏ョ殑鍏崇郴瀵硅薄鏄惁涓虹┖ bool result = false; if (relArgNull) { - depRel = heap_open(DependRelationId, AccessShareLock); + depRel = heap_open(DependRelationId, AccessShareLock); // 鑻ヤ负绌猴紝鎵撳紑 DependRelation 琛 } /* Note: we not care obj->deptype here. */ - add_object_address_ext1(obj, objSet); + add_object_address_ext1(obj, objSet); // 灏嗗緟妫鏌ョ殑瀵硅薄鍦板潃娣诲姞鍒板璞″湴鍧闆嗗悎涓 - result = TrIsRefRbObjectImpl(depRel, obj, objSet); + result = TrIsRefRbObjectImpl(depRel, obj, objSet); // 璋冪敤瀹炵幇鍑芥暟妫鏌ュ璞″強鍏跺紩鐢ㄥ璞℃槸鍚﹀湪鍥炴敹绔欎腑 - free_object_addresses(objSet); + free_object_addresses(objSet); // 閲婃斁瀵硅薄鍦板潃闆嗗悎鐨勫唴瀛 if (relArgNull) { - heap_close(depRel, AccessShareLock); + heap_close(depRel, AccessShareLock); // 鑻ヤ箣鍓嶆墦寮浜嗗叧绯昏〃锛屽垯鍏抽棴瀹 } - return result; + return result; // 杩斿洖妫鏌ョ粨鏋滐紝瀵硅薄鎴栧叾寮曠敤瀵硅薄鏄惁鍦ㄥ洖鏀剁珯涓 } +/* + * 鍔熻兘锛氭鏌ュ璞″強鍏跺紩鐢ㄥ璞℃槸鍚﹀湪鍥炴敹绔欎腑锛堟墿灞曞嚱鏁帮級 + * 鍙傛暟鍒楄〃锛 + * classid锛氬璞$殑绫诲埆鏍囪瘑 + * objid锛氬璞$殑鏍囪瘑 + * objname锛氬璞$殑鍚嶇О + */ bool TrIsRefRbObjectEx(Oid classid, Oid objid, const char *objname) { if (!TcapFeatureAvail()) { - return false; + return false; // 濡傛灉 Tcap 鍔熻兘涓嶅彲鐢紝鍒欒繑鍥 false } /* Note: we preserve rule origin name when RbDrop. */ if (TrRbIsEmptyDb(u_sess->proc_cxt.MyDatabaseId)) { - return false; + return false; // 濡傛灉褰撳墠鏁版嵁搴撲负绌猴紝鍒欒繑鍥 false } if (classid != RewriteRelationId && objname && strncmp(objname, "BIN$", 4) != 0) { - return false; + return false; // 濡傛灉瀵硅薄涓嶆槸 RewriteRelation锛屼笖瀵硅薄鍚嶇О涓嶄互 "BIN$" 寮澶达紝鍒欒繑鍥 false } - ObjectAddress obj = {classid, objid}; + ObjectAddress obj = {classid, objid}; // 鍒涘缓瀵硅薄鍦板潃缁撴瀯 - return TrIsRefRbObject(&obj); + return TrIsRefRbObject(&obj); // 璋冪敤 TrIsRefRbObject 鍑芥暟妫鏌ュ璞″強鍏跺紩鐢ㄥ璞℃槸鍚﹀湪鍥炴敹绔欎腑 } -void TrForbidAccessRbDependencies(Relation depRel, const ObjectAddress *depender, - const ObjectAddress *referenced, int nreferenced) +/* + * 鍔熻兘锛氱姝㈣闂笌鍥炴敹绔欏璞$浉鍏崇殑渚濊禆鍏崇郴 + * 鍙傛暟锛 + * depRel锛氫緷璧栧叧绯昏〃鐨勫叧绯 + * depender锛氫緷璧栧璞″湴鍧 + * referenced锛氳渚濊禆瀵硅薄鍦板潃鐨勬暟缁 + * nreferenced锛氳渚濊禆瀵硅薄鍦板潃鏁扮粍鐨勯暱搴 + */ +void TrForbidAccessRbDependencies(Relation depRel, const ObjectAddress *depender, const ObjectAddress *referenced, + int nreferenced) { if (!TcapFeatureAvail()) { - return; + return; // 濡傛灉 Tcap 鍔熻兘涓嶅彲鐢紝鍒欑洿鎺ヨ繑鍥 } if (IsInitdb || TrRbIsEmptyDb(u_sess->proc_cxt.MyDatabaseId)) { - return; + return; // 濡傛灉鏄 Initdb 妯″紡锛屾垨鑰呭綋鍓嶆暟鎹簱涓虹┖锛屽垯鐩存帴杩斿洖 } if (TrIsRefRbObject(depender, depRel)) { - elog (ERROR, "can not access recycle object."); + elog(ERROR, "can not access recycle object."); // 濡傛灉渚濊禆瀵硅薄鎴栧叾寮曠敤瀵硅薄鍦ㄥ洖鏀剁珯涓紝鍒欐姤閿欙紝涓嶅厑璁歌闂 } for (int i = 0; i < nreferenced; i++, referenced++) { if (TrIsRefRbObject(referenced, depRel)) { - elog (ERROR, "can not access recycle object."); + elog(ERROR, "can not access recycle object."); // 濡傛灉琚緷璧栧璞℃垨鍏跺紩鐢ㄥ璞″湪鍥炴敹绔欎腑锛屽垯鎶ラ敊锛屼笉鍏佽璁块棶 } } return; } +/* + * 鍔熻兘锛氱姝㈣闂洖鏀剁珯瀵硅薄 + * 鍙傛暟鍒楄〃锛 + * classid锛氬璞$被鍒殑 OID + * objid锛氬璞$殑 OID + * objname锛氬璞$殑鍚嶇О + */ void TrForbidAccessRbObject(Oid classid, Oid objid, const char *objname) { if (!TcapFeatureAvail()) { - return; + return; // 濡傛灉 Tcap 鍔熻兘涓嶅彲鐢紝鍒欑洿鎺ヨ繑鍥 } if (TrRbIsEmptyDb(u_sess->proc_cxt.MyDatabaseId) || !TrMaybeRbObject(classid, objid, objname)) { - return; + return; // 濡傛灉褰撳墠鏁版嵁搴撲负绌猴紝鎴栬呭璞″彲鑳戒笉鏄洖鏀剁珯瀵硅薄锛屽垯鐩存帴杩斿洖 } ObjectAddress obj = {classid, objid}; if (TrIsRefRbObject(&obj)) { - elog (ERROR, "can not access recycle object."); + elog(ERROR, "can not access recycle object."); // 濡傛灉瀵硅薄鎴栧叾寮曠敤瀵硅薄鍦ㄥ洖鏀剁珯涓紝鍒欐姤閿欙紝涓嶅厑璁歌闂 } return; } +/* + * 鍔熻兘锛氬垽鏂槸鍚︿负鍥炴敹绔欏璞$殑 PostgreSQL 鍑芥暟 + * 鍙傛暟鍒楄〃锛 + * classid锛氬璞$被鍒殑 OID + * objid锛氬璞$殑 OID + * objname锛氬璞$殑鍚嶇О + */ Datum gs_is_recycle_object(PG_FUNCTION_ARGS) { - int classid = PG_GETARG_INT32(0); - int objid = PG_GETARG_INT32(1); - Name objname = PG_GETARG_NAME(2); - bool result = false; + int classid = PG_GETARG_INT32(0); // 鑾峰彇鍑芥暟鍙傛暟涓殑瀵硅薄绫诲埆 OID + int objid = PG_GETARG_INT32(1); // 鑾峰彇鍑芥暟鍙傛暟涓殑瀵硅薄 OID + Name objname = PG_GETARG_NAME(2); // 鑾峰彇鍑芥暟鍙傛暟涓殑瀵硅薄鍚嶇О + bool result = false; // 鐢ㄤ簬瀛樺偍鍒ゆ柇缁撴灉锛岄粯璁や负 false + + // 璋冪敤 TrIsRefRbObjectEx 鍑芥暟鍒ゆ柇缁欏畾瀵硅薄鏄惁涓哄洖鏀剁珯瀵硅薄锛屽苟灏嗙粨鏋滃瓨鍌ㄥ湪 result 涓 result = TrIsRefRbObjectEx(classid, objid, NameStr(*objname)); + + // 杩斿洖甯冨皵鍊肩粨鏋 PG_RETURN_BOOL(result); } +======= +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2020-2020. All rights reserved. + * + * openGauss is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * + * http://license.coscl.org.cn/MulanPSL2 + * + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + * --------------------------------------------------------------------------------------- + * + * tcap_manager.cpp + * Routines to support Timecapsule `Recyclebin-based query, restore`. + * We use Tr prefix to indicate it in following coding. + * + * IDENTIFICATION + * src/gausskernel/storage/tcap/tcap_manager.cpp + * + * --------------------------------------------------------------------------------------- + */ + +#include "postgres.h" + +#include "pgstat.h" +#include "access/reloptions.h" +#include "access/sysattr.h" +#include "access/xlog.h" +#include "catalog/pg_database.h" +#include "catalog/dependency.h" +#include "catalog/heap.h" +#include "catalog/index.h" +#include "catalog/indexing.h" +#include "catalog/objectaccess.h" +#include "catalog/pg_collation_fn.h" +#include "catalog/pg_collation.h" +#include "catalog/pg_constraint.h" +#include "catalog/pg_conversion_fn.h" +#include "catalog/pg_conversion.h" +#include "catalog/pg_depend.h" +#include "catalog/pg_extension_data_source.h" +#include "catalog/pg_extension.h" +#include "catalog/pg_foreign_data_wrapper.h" +#include "catalog/pg_foreign_server.h" +#include "catalog/pg_job.h" +#include "catalog/pg_language.h" +#include "catalog/pg_largeobject.h" +#include "catalog/pg_object.h" +#include "catalog/pg_opclass.h" +#include "catalog/pg_operator.h" +#include "catalog/pg_opfamily.h" +#include "catalog/pg_partition_fn.h" +#include "catalog/pg_proc.h" +#include "catalog/pg_recyclebin.h" +#include "catalog/pg_rewrite.h" +#include "catalog/pg_rlspolicy.h" +#include "catalog/pg_synonym.h" +#include "catalog/pg_tablespace.h" +#include "catalog/pg_trigger.h" +#include "catalog/pg_ts_config.h" +#include "catalog/pg_ts_dict.h" +#include "catalog/pg_ts_parser.h" +#include "catalog/pg_ts_template.h" +#include "catalog/pgxc_class.h" +#include "catalog/pg_partition.h" +#include "catalog/storage.h" +#include "commands/comment.h" +#include "commands/dbcommands.h" +#include "commands/directory.h" +#include "commands/extension.h" +#include "commands/proclang.h" +#include "commands/schemacmds.h" +#include "commands/seclabel.h" +#include "commands/sec_rls_cmds.h" +#include "commands/tablecmds.h" +#include "commands/tablespace.h" +#include "commands/trigger.h" +#include "commands/typecmds.h" +#include "executor/node/nodeModifyTable.h" +#include "rewrite/rewriteRemove.h" +#include "storage/lmgr.h" +#include "storage/predicate.h" +#include "storage/smgr/relfilenode.h" +#include "utils/acl.h" +#include "utils/builtins.h" +#include "utils/fmgroids.h" +#include "utils/inval.h" +#include "utils/lsyscache.h" +#include "utils/relcache.h" +#include "utils/snapmgr.h" +#include "utils/syscache.h" + +#include "storage/tcap.h" +#include "storage/tcap_impl.h" + +static bool TrIsRefRbObject(const ObjectAddress *obj, Relation depRel = NULL); +void TrDoPurgeObjectDrop(TrObjDesc *desc); +/* + * 鍔熻兘锛氱敓鎴愬懡鍚嶅璞$殑鍚嶇О锛屽苟灏嗙粨鏋滃瓨鍌ㄥ湪rbname鎸囧悜鐨勭紦鍐插尯涓 + * 鍙傛暟鍒楄〃锛 + * rbname锛氭寚鍚戝瓧绗︾紦鍐插尯鐨勬寚閽堬紝鐢ㄤ簬瀛樺偍鐢熸垚鐨勫璞″悕绉 + * classId锛氬璞$殑绫诲埆ID + * objid锛氬璞$殑ID + */ +char *TrGenObjName(char *rbname, Oid classId, Oid objid) +{ + int rc = EOK;// 澹版槑骞跺垵濮嬪寲涓涓暣鏁板彉閲弐c锛岀敤浜庡偍瀛樻墽琛岀殑缁撴灉 + // 浣跨敤snprintf_s鍑芥暟灏嗘牸寮忓寲鐨勫瓧绗︿覆鍐欏叆rbname缂撳啿鍖 + rc = snprintf_s(rbname, NAMEDATALEN, NAMEDATALEN - 1, "BIN$%X%X%X$%llX==$0", + u_sess->proc_cxt.MyDatabaseId, classId, objid, (uint64)GetXLogInsertRecPtr()); + securec_check_ss_c(rc, "\0", "\0");// 妫鏌nprintf_s鍑芥暟鐨勬墽琛岀粨鏋滐紝纭繚娌℃湁閿欒鍙戠敓 + + return rbname;// 杩斿洖瀛樺偍瀵硅薄鍚嶇О鐨勭紦鍐插尯鐨勫湴鍧浣滀负鍑芥暟缁撴灉 +} +/* + * 鍔熻兘锛氫粠HeapTuple涓幏鍙栧洖鏀剁珯涓殑鍐荤粨浜嬪姟ID锛64浣嶏級锛屽苟杩斿洖璇D + * 鍙傛暟鍒楄〃锛 + * - rbtup锛氭寚鍚戝緟澶勭悊鐨凥eapTuple鐨勬寚閽 + * - rbRel锛歊ecycle Bin鍏崇郴鐨凴elation锛堝彲閫夊弬鏁帮級 + */ +static TransactionId TrRbGetRcyfrozenxid64(HeapTuple rbtup, Relation rbRel = NULL) +{ + Datum datum;// 瀛樺偍灞炴у肩殑鏁版嵁绫诲瀷 + bool isNull = false;// 鏍囪瘑灞炴у兼槸鍚︿负NULL + TransactionId rcyfrozenxid64;// 瀛樺偍鍥炴敹绔欎腑鐨勫喕缁撲簨鍔D锛64浣嶏級 + bool relArgNull = rbRel == NULL;// 妫鏌bRel鏄惁涓篘ULL鐨勬爣蹇 + // 濡傛灉rbRel涓篘ULL锛屽垯鎵撳紑Recycle Bin鍏崇郴锛圧ecycle Bin琛級 + if (relArgNull) { + rbRel = heap_open(RecyclebinRelationId, AccessShareLock); + } + // 浠嶩eapTuple涓幏鍙杙g_recyclebin琛ㄤ腑rcyfrozenxid64灞炴х殑鍊 + datum = heap_getattr(rbtup, Anum_pg_recyclebin_rcyfrozenxid64, RelationGetDescr(rbRel), &isNull); + Assert(!isNull);// 鏂█灞炴у间笉搴斾负NULL + // 灏哾atum杞崲涓篢ransactionId绫诲瀷锛屽苟璧嬪肩粰rcyfrozenxid64 + rcyfrozenxid64 = DatumGetTransactionId(datum); + // 濡傛灉rbRel涓篘ULL锛屽垯鍏抽棴Recycle Bin鍏崇郴 + if (relArgNull) { + heap_close(rbRel, AccessShareLock); + } + + return rcyfrozenxid64;// 杩斿洖鑾峰彇鐨勫喕缁撲簨鍔D锛64浣嶏級 +} +/* + * 鍔熻兘锛氬垵濮嬪寲TrObjDesc缁撴瀯浣擄紝瀛樺偍鍏充簬瀵硅薄鐨勬弿杩颁俊鎭 + * 鍙傛暟鍒楄〃锛 + * rel锛氭寚鍚戠洰鏍囧叧绯荤殑Relation + * desc锛氭寚鍚慣rObjDesc缁撴瀯浣撶殑鎸囬拡锛岀敤浜庡瓨鍌ㄥ璞℃弿杩颁俊鎭 + * operType锛氭搷浣滅被鍨嬶紝琛ㄧず瀵硅薄鐨勬搷浣滐紙鍒涘缓銆佸垹闄ょ瓑锛 + * objType锛氬璞$被鍨嬶紝琛ㄧず瀵硅薄鐨勭被鍨嬶紙琛ㄣ佺储寮曠瓑锛 + * canpurge锛氭槸鍚﹀厑璁告竻闄ゅ璞℃爣蹇 + * isBaseObj锛氭槸鍚﹀熀鏈璞℃爣蹇 + */ +void TrDescInit(Relation rel, TrObjDesc *desc, TrObjOperType operType, + TrObjType objType, bool canpurge, bool isBaseObj) +{ + errno_t rc = EOK;// 澹版槑骞跺垵濮嬪寲涓涓敊璇彿鍙橀噺rc锛岀敤浜庡瓨鍌ㄥ嚱鏁版墽琛岀殑缁撴灉 + + /* Notice: desc->id, desc->baseid will be assigned by invoker later. */ + desc->dbid = u_sess->proc_cxt.MyDatabaseId;// 灏嗗綋鍓嶄細璇濇墍鍦ㄧ殑鏁版嵁搴揑D璧嬪肩粰desc->dbid + desc->relid = RelationGetRelid(rel);// 灏嗙洰鏍囧叧绯荤殑Relid璧嬪肩粰desc->relid + // 鐢熸垚瀵硅薄鐨勫悕绉帮紝瀛樺偍鍦╠esc->name涓 + (void)TrGenObjName(desc->name, RelationRelationId, desc->relid); + // 灏嗙洰鏍囧叧绯荤殑鍚嶇О鎷疯礉鍒癲esc->originname涓 + rc = strncpy_s(desc->originname, NAMEDATALEN, RelationGetRelationName(rel), + strlen(RelationGetRelationName(rel))); + securec_check(rc, "\0", "\0"); + // 鍒濆鍖栧璞℃弿杩扮殑鍚勪釜瀛楁 + desc->operation = operType; + desc->type = objType; + desc->recyclecsn = t_thrd.xact_cxt.ShmemVariableCache->nextCommitSeqNo; + desc->recycletime = GetCurrentTimestamp(); + desc->createcsn = RelationGetCreatecsn(rel); + desc->changecsn = RelationGetChangecsn(rel); + desc->nspace = RelationGetNamespace(rel); + desc->owner = RelationGetOwner(rel); + desc->tablespace = RelationGetTablespace(rel); + desc->relfilenode = RelationGetRelFileNode(rel); + desc->frozenxid = RelationGetRelFrozenxid(rel); + desc->frozenxid64 = RelationGetRelFrozenxid64(rel); + desc->canrestore = objType == RB_OBJ_TABLE; + desc->canpurge = canpurge; +} +/* + * 鍔熻兘锛氬垵濮嬪寲TrObjDesc缁撴瀯浣擄紝瀛樺偍鍏充簬鍒嗗尯瀵硅薄鐨勬弿杩颁俊鎭 + * 鍙傛暟鍒楄〃锛 + * rel锛氭寚鍚戠埗鍏崇郴鐨凴elation + * part锛氭寚鍚戝垎鍖虹殑Partition + * desc锛氭寚鍚慣rObjDesc缁撴瀯浣撶殑鎸囬拡锛岀敤浜庡瓨鍌ㄥ璞℃弿杩颁俊鎭 + * operType锛氭搷浣滅被鍨嬶紝琛ㄧず瀵硅薄鐨勬搷浣滐紙鍒涘缓銆佸垹闄ょ瓑锛 + * objType锛氬璞$被鍨嬶紝琛ㄧず瀵硅薄鐨勭被鍨嬶紙琛ㄣ佺储寮曠瓑锛 + * canpurge锛氭槸鍚﹀厑璁告竻闄ゅ璞℃爣蹇 + * isBaseObj锛氭槸鍚﹀熀鏈璞℃爣蹇 + */ +void TrPartDescInit(Relation rel, Partition part, TrObjDesc *desc, TrObjOperType operType, + TrObjType objType, bool canpurge, bool isBaseObj) +{ + errno_t rc = EOK;// 澹版槑骞跺垵濮嬪寲涓涓敊璇彿鍙橀噺rc锛岀敤浜庡瓨鍌ㄥ嚱鏁版墽琛岀殑缁撴灉 + + /* Notice: desc->id, desc->baseid will be assigned by invoker later. */ + desc->dbid = u_sess->proc_cxt.MyDatabaseId;// 灏嗗綋鍓嶄細璇濇墍鍦ㄧ殑鏁版嵁搴揑D璧嬪肩粰desc->dbid + desc->relid = part->pd_id;// 灏嗗垎鍖虹殑pd_id璧嬪肩粰desc->relid + // 鐢熸垚瀵硅薄鐨勫悕绉帮紝瀛樺偍鍦╠esc->name涓 + (void)TrGenObjName(desc->name, PartitionRelationId, desc->relid); + // 灏嗙埗鍏崇郴鐨勫悕绉板拰鍒嗗尯鐨勫悕绉拌繛鎺ヨ捣鏉ワ紝瀛樺偍鍦╠esc->originname涓 + rc = strncpy_s(desc->originname, NAMEDATALEN, RelationGetRelationName(rel), + strlen(RelationGetRelationName(rel))); + securec_check(rc, "\0", "\0"); + + int len = strlen(PartitionGetPartitionName(part)) + strlen(RelationGetRelationName(rel)) + 1; + rc = strcat_s(desc->originname, len, PartitionGetPartitionName(part)); + securec_check(rc, "\0", "\0"); + // 鍒濆鍖栧璞℃弿杩扮殑鍚勪釜瀛楁 + desc->operation = operType; + desc->type = objType; + desc->recyclecsn = t_thrd.xact_cxt.ShmemVariableCache->nextCommitSeqNo; + desc->recycletime = GetCurrentTimestamp(); + desc->createcsn = RelationGetCreatecsn(rel); + desc->changecsn = RelationGetChangecsn(rel); + desc->nspace = RelationGetNamespace(rel); + desc->owner = RelationGetOwner(rel); + desc->tablespace = part->pd_part->reltablespace; + desc->relfilenode = part->pd_part->relfilenode; + desc->frozenxid = part->pd_part->relfrozenxid; + desc->frozenxid64 = PartGetRelFrozenxid64(part); + desc->canrestore = false; + desc->canpurge = canpurge; +} +/* + * 鍔熻兘锛氫粠HeapTuple涓鍙栧苟濉厖瀵硅薄鎻忚堪淇℃伅鍒癟rObjDesc缁撴瀯浣 + * 鍙傛暟鍒楄〃锛 + * desc锛氭寚鍚慣rObjDesc缁撴瀯浣撶殑鎸囬拡锛岀敤浜庡瓨鍌ㄥ璞℃弿杩颁俊鎭 + * rbtup锛氭寚鍚慔eapTuple鐨勬寚閽堬紝琛ㄧず浠庡洖鏀剁珯鍏崇郴璇诲彇鐨勫厓缁 + */ +static void TrDescRead(TrObjDesc *desc, HeapTuple rbtup) +{ + Form_pg_recyclebin rbForm = (Form_pg_recyclebin)GETSTRUCT(rbtup); + + // 浠嶩eapTuple涓幏鍙栧璞$殑Oid锛岃祴鍊肩粰desc->id + desc->id = HeapTupleGetOid(rbtup); + // 浠嶩eapTuple涓幏鍙栧璞$殑鍩虹ID锛岃祴鍊肩粰desc->baseid + desc->baseid = rbForm->rcybaseid; + + // 浠嶩eapTuple涓幏鍙栧璞$殑鏁版嵁搴揑D锛岃祴鍊肩粰desc->dbid + desc->dbid = rbForm->rcydbid; + // 浠嶩eapTuple涓幏鍙栧璞$殑鍏崇郴ID锛岃祴鍊肩粰desc->relid + desc->relid = rbForm->rcyrelid; + // 浠嶩eapTuple涓幏鍙栧璞$殑鍚嶇О锛屾嫹璐濆埌desc->name + (void)namestrcpy((Name)desc->name, NameStr(rbForm->rcyname)); + // 浠嶩eapTuple涓幏鍙栧璞$殑鍘熷鍚嶇О锛屾嫹璐濆埌desc->originname + (void)namestrcpy((Name)desc->originname, NameStr(rbForm->rcyoriginname)); + // 鏍规嵁HeapTuple涓殑鎿嶄綔绫诲瀷鏍囧織锛岃缃甦esc->operation + desc->operation = (rbForm->rcyoperation == 'd') ? RB_OPER_DROP : RB_OPER_TRUNCATE; + // 灏咹eapTuple涓殑瀵硅薄绫诲瀷杞崲涓篢rObjType锛岃祴鍊肩粰desc->type + desc->type = (TrObjType)rbForm->rcytype; + // 浠嶩eapTuple涓幏鍙栧璞$殑鍥炴敹CSN锛岃祴鍊肩粰desc->recyclecsn + desc->recyclecsn = rbForm->rcyrecyclecsn; + // 浠嶩eapTuple涓幏鍙栧璞$殑鍥炴敹鏃堕棿锛岃祴鍊肩粰desc->recycletime + desc->recycletime = rbForm->rcyrecycletime; + // 浠嶩eapTuple涓幏鍙栧璞$殑鍒涘缓CSN锛岃祴鍊肩粰desc->createcsn + desc->createcsn = rbForm->rcycreatecsn; + // 浠嶩eapTuple涓幏鍙栧璞$殑鍙樻洿CSN锛岃祴鍊肩粰desc->changecsn + desc->changecsn = rbForm->rcychangecsn; + // 浠嶩eapTuple涓幏鍙栧璞$殑鍛藉悕绌洪棿锛岃祴鍊肩粰desc->nspace + desc->nspace = rbForm->rcynamespace; + // 浠嶩eapTuple涓幏鍙栧璞$殑鍛藉悕绌洪棿锛岃祴鍊肩粰desc->nspace + desc->owner = rbForm->rcyowner; + // 浠嶩eapTuple涓幏鍙栧璞$殑琛ㄧ┖闂达紝璧嬪肩粰desc->tablespace + desc->tablespace = rbForm->rcytablespace; + // 浠嶩eapTuple涓幏鍙栧璞$殑鍏崇郴鏂囦欢鑺傜偣锛岃祴鍊肩粰desc->relfilenode + desc->relfilenode = rbForm->rcyrelfilenode; + // 浠嶩eapTuple涓幏鍙栧璞$殑鍙仮澶嶆爣蹇楋紝璧嬪肩粰desc->canrestore + desc->canrestore = rbForm->rcycanrestore; + // 浠嶩eapTuple涓幏鍙栧璞$殑鍙竻闄ゆ爣蹇楋紝璧嬪肩粰desc->canpurge + desc->canpurge = rbForm->rcycanpurge; + // 浠嶩eapTuple涓幏鍙栧璞$殑鍐荤粨浜嬪姟ID锛岃祴鍊肩粰desc->frozenxid + desc->frozenxid = rbForm->rcyfrozenxid; + // 璋冪敤TrRbGetRcyfrozenxid64鍑芥暟锛岃幏鍙64浣嶅喕缁撲簨鍔D锛岃祴鍊肩粰desc->frozenxid64 + desc->frozenxid64 = TrRbGetRcyfrozenxid64(rbtup); +} +/* + * 鍔熻兘锛氬皢TrObjDesc缁撴瀯浣撲腑鐨勫璞℃弿杩颁俊鎭啓鍏ュ洖鏀剁珯鍏崇郴 + * 鍙傛暟鍒楄〃锛 + * desc锛氭寚鍚慣rObjDesc缁撴瀯浣撶殑鎸囬拡锛屽寘鍚鍐欏叆鍥炴敹绔欏叧绯荤殑瀵硅薄鎻忚堪淇℃伅 + */ +Oid TrDescWrite(TrObjDesc *desc) +{ + Relation rel; + HeapTuple tup; + bool nulls[Natts_pg_recyclebin] = {0}; + Datum values[Natts_pg_recyclebin]; + NameData name; + NameData originname; + Oid rbid; + + // 濉厖灞炴ф暟缁剉alues锛屽皢瀵硅薄鎻忚堪淇℃伅涓殑鍚勫睘鎬у艰祴鍊肩粰瀵瑰簲浣嶇疆 + values[Anum_pg_recyclebin_rcydbid - 1] = ObjectIdGetDatum(desc->dbid); + values[Anum_pg_recyclebin_rcybaseid - 1] = ObjectIdGetDatum(desc->baseid); + values[Anum_pg_recyclebin_rcyrelid - 1] = ObjectIdGetDatum(desc->relid); + (void)namestrcpy(&name, desc->name); + values[Anum_pg_recyclebin_rcyname - 1] = NameGetDatum(&name); + (void)namestrcpy(&originname, desc->originname); + values[Anum_pg_recyclebin_rcyoriginname - 1] = NameGetDatum(&originname); + values[Anum_pg_recyclebin_rcyoperation - 1] = (desc->operation == RB_OPER_DROP) ? 'd' : 't'; + values[Anum_pg_recyclebin_rcytype - 1] = Int32GetDatum(desc->type); + values[Anum_pg_recyclebin_rcyrecyclecsn - 1] = Int64GetDatum(desc->recyclecsn); + values[Anum_pg_recyclebin_rcyrecycletime - 1] = TimestampTzGetDatum(desc->recycletime); + values[Anum_pg_recyclebin_rcycreatecsn - 1] = Int64GetDatum(desc->createcsn); + values[Anum_pg_recyclebin_rcychangecsn - 1] = Int64GetDatum(desc->changecsn); + values[Anum_pg_recyclebin_rcynamespace - 1] = ObjectIdGetDatum(desc->nspace); + values[Anum_pg_recyclebin_rcyowner - 1] = ObjectIdGetDatum(desc->owner); + values[Anum_pg_recyclebin_rcytablespace - 1] = ObjectIdGetDatum(desc->tablespace); + values[Anum_pg_recyclebin_rcyrelfilenode - 1] = ObjectIdGetDatum(desc->relfilenode); + values[Anum_pg_recyclebin_rcycanrestore - 1] = BoolGetDatum(desc->canrestore); + values[Anum_pg_recyclebin_rcycanpurge - 1] = BoolGetDatum(desc->canpurge); + values[Anum_pg_recyclebin_rcyfrozenxid - 1] = ShortTransactionIdGetDatum(desc->frozenxid); + values[Anum_pg_recyclebin_rcyfrozenxid64 - 1] = TransactionIdGetDatum(desc->frozenxid64); + + rel = heap_open(RecyclebinRelationId, RowExclusiveLock);// 鎵撳紑鍥炴敹绔欏叧绯 + // 鍒涘缓涓涓柊鐨凥eapTuple锛屽~鍏呭睘鎬у煎拰null鏍囧織 + tup = heap_form_tuple(RelationGetDescr(rel), values, nulls); + // 鍦ㄥ叧绯讳腑鎻掑叆鏂扮殑鍏冪粍锛岃幏鍙栨柊鍏冪粍鐨勫璞D锛坮bid锛 + rbid = simple_heap_insert(rel, tup); + // 鏇存柊鍏崇郴鐨勭储寮 + CatalogUpdateIndexes(rel, tup); + // 閲婃斁HeapTuple + heap_freetuple_ext(tup); + // 鍏抽棴鍥炴敹绔欏叧绯 + heap_close(rel, RowExclusiveLock); + // 澧炲姞鍛戒护璁℃暟鍣紝浠ヤ繚璇佸厓鏁版嵁鐨勪竴鑷存 + CommandCounterIncrement(); + + return rbid; +} +/* + * 鍔熻兘锛氬湪鍥炴敹绔欏叧绯讳腑鏍规嵁鍛藉悕绌洪棿銆佸師濮嬪悕绉般佺被鍨嬪拰鎿嶄綔妯″紡鎼滅储骞惰幏鍙栧璞℃弿杩颁俊鎭 + * 鍙傛暟鍒楄〃锛 + * nspId锛氬懡鍚嶇┖闂碔D锛屾寚瀹氳鎼滅储鐨勫懡鍚嶇┖闂 + * oriname锛氬璞$殑鍘熷鍚嶇О锛岃鎼滅储鐨勫璞″悕绉 + * type锛歍rObjType锛屾寚瀹氬璞$殑绫诲瀷 + * desc锛氭寚鍚慣rObjDesc缁撴瀯浣撶殑鎸囬拡锛岀敤浜庡瓨鍌ㄦ壘鍒扮殑瀵硅薄鎻忚堪淇℃伅 + * operMode锛歍rOperMode锛屾寚瀹氭搷浣滄ā寮忥紙杩樺師妯″紡锛 + */ +static bool TrFetchOrinameImpl(Oid nspId, const char *oriname, TrObjType type, + TrObjDesc *desc, TrOperMode operMode) +{ + Relation rbRel; + SysScanDesc sd; + ScanKeyData skey[3]; + HeapTuple tup; + bool found = false; + // 濡傛灉鍛藉悕绌洪棿ID鏃犳晥锛岀洿鎺ヨ繑鍥瀎alse + if (!OidIsValid(nspId)) { + return false; + } + // 鎵撳紑鍥炴敹绔欏叧绯伙紝鑾峰彇鍏变韩閿 + rbRel = heap_open(RecyclebinRelationId, AccessShareLock); + // 鍒濆鍖栨壂鎻忛敭锛屾寜鐓у懡鍚嶇┖闂淬佹暟鎹簱ID鍜屽師濮嬪悕绉拌繘琛屾悳绱 + ScanKeyInit(&skey[0], Anum_pg_recyclebin_rcynamespace, BTEqualStrategyNumber, + F_OIDEQ, ObjectIdGetDatum(nspId)); + ScanKeyInit(&skey[1], Anum_pg_recyclebin_rcydbid, BTEqualStrategyNumber, + F_OIDEQ, ObjectIdGetDatum(u_sess->proc_cxt.MyDatabaseId)); + ScanKeyInit(&skey[2], Anum_pg_recyclebin_rcyoriginname, BTEqualStrategyNumber, + F_NAMEEQ, CStringGetDatum(oriname)); + // 寮濮嬫壂鎻忓洖鏀剁珯鍏崇郴锛屼娇鐢ㄩ瀹氫箟绱㈠紩鍜屾壂鎻忛敭 + sd = systable_beginscan(rbRel, RecyclebinDbidNspOrinameIndexId, true, NULL, 3, skey); + while ((tup = systable_getnext(sd)) != NULL) { + Form_pg_recyclebin rbForm = (Form_pg_recyclebin)GETSTRUCT(tup); + // 妫鏌ュ璞$被鍨嬪拰鎿嶄綔妯″紡鏄惁鍖归厤 + if ((rbForm->rcytype != type && rbForm->rcytype == RB_OBJ_TABLE) || + (rbForm->rcytype != type && rbForm->rcytype == RB_OBJ_INDEX) || + (operMode == RB_OPER_RESTORE_DROP && rbForm->rcyoperation != 'd') || + (operMode == RB_OPER_RESTORE_TRUNCATE && rbForm->rcyoperation != 't')) { + continue; + } + // 鎵惧埌鍖归厤鐨勫璞★紝璇诲彇瀵硅薄鎻忚堪淇℃伅骞舵爣璁颁负鎵惧埌 + found = true; + TrDescRead(desc, tup); + break; + } + // 缁撴潫鎵弿骞跺叧闂洖鏀剁珯鍏崇郴 + systable_endscan(sd); + heap_close(rbRel, AccessShareLock); + + return found; +} +/* + * 鍔熻兘锛氬湪鍥炴敹绔欏叧绯讳腑鏍规嵁瀵硅薄鍚嶇О銆佺被鍨嬪拰鎿嶄綔妯″紡鎼滅储骞惰幏鍙栧璞℃弿杩颁俊鎭 + * 鍙傛暟鍒楄〃锛 + * rcyname锛氳鎼滅储鐨勫洖鏀剁珯瀵硅薄鐨勫悕绉 + * type锛歍rObjType锛屾寚瀹氬璞$殑绫诲瀷 + * desc锛氭寚鍚慣rObjDesc缁撴瀯浣撶殑鎸囬拡锛岀敤浜庡瓨鍌ㄦ壘鍒扮殑瀵硅薄鎻忚堪淇℃伅 + * operMode锛歍rOperMode锛屾寚瀹氭搷浣滄ā寮忥紙杩樺師妯″紡锛 + */ +bool TrFetchName(const char *rcyname, TrObjType type, TrObjDesc *desc, TrOperMode operMode) +{ + Relation rbRel; + SysScanDesc sd; + ScanKeyData skey[1]; + HeapTuple tup; + bool found = false; + // 鎵撳紑鍥炴敹绔欏叧绯伙紝鑾峰彇鍏变韩閿 + rbRel = heap_open(RecyclebinRelationId, AccessShareLock); + // 鍒濆鍖栨壂鎻忛敭锛屾寜鐓у璞″悕绉拌繘琛屾悳绱 + ScanKeyInit(&skey[0], Anum_pg_recyclebin_rcyname, BTEqualStrategyNumber, + F_NAMEEQ, CStringGetDatum(rcyname)); + // 寮濮嬫壂鎻忓洖鏀剁珯鍏崇郴锛屼娇鐢ㄩ瀹氫箟绱㈠紩鍜屾壂鎻忛敭 + sd = systable_beginscan(rbRel, RecyclebinNameIndexId, true, NULL, 1, skey); + if ((tup = systable_getnext(sd)) != NULL) { + Form_pg_recyclebin rbForm = (Form_pg_recyclebin)GETSTRUCT(tup); + // 妫鏌ュ璞$被鍨嬫槸鍚﹀尮閰 + if ((rbForm->rcytype != type && rbForm->rcytype == RB_OBJ_TABLE) || + (rbForm->rcytype != type && rbForm->rcytype == RB_OBJ_INDEX)) { + ereport(ERROR, + (errmsg("The recycle object \"%s\" type mismatched.", rcyname))); + } + // 妫鏌ユ搷浣滄ā寮忔槸鍚﹀尮閰 + if ((operMode == RB_OPER_RESTORE_DROP && rbForm->rcyoperation != 'd') || + (operMode == RB_OPER_RESTORE_TRUNCATE && rbForm->rcyoperation != 't')) { + ereport(ERROR, + (errmsg("recycle object \"%s\" desired does not exist", rcyname))); + } + // 鎵惧埌鍖归厤鐨勫璞★紝璇诲彇瀵硅薄鎻忚堪淇℃伅骞舵爣璁颁负鎵惧埌 + found = true; + TrDescRead(desc, tup); + } + // 缁撴潫鎵弿骞跺叧闂洖鏀剁珯鍏崇郴 + systable_endscan(sd); + heap_close(rbRel, AccessShareLock); + + return found; +} +/* + * 鍔熻兘锛氬湪鍥炴敹绔欏叧绯讳腑鏍规嵁妯″紡鍚嶇О銆佸璞″悕绉般佺被鍨嬪拰鎿嶄綔妯″紡鎼滅储骞惰幏鍙栧璞℃弿杩颁俊鎭 + * 鍙傛暟鍒楄〃锛 + * schemaname锛氭ā寮忓悕绉帮紝鍙夌殑鍛藉悕绌洪棿鍚嶇О + * relname锛氳鎼滅储鐨勫洖鏀剁珯瀵硅薄鐨勫悕绉 + * type锛歍rObjType锛屾寚瀹氬璞$殑绫诲瀷 + * desc锛氭寚鍚慣rObjDesc缁撴瀯浣撶殑鎸囬拡锛岀敤浜庡瓨鍌ㄦ壘鍒扮殑瀵硅薄鎻忚堪淇℃伅 + * operMode锛歍rOperMode锛屾寚瀹氭搷浣滄ā寮忥紙杩樺師妯″紡锛 + */ +static bool TrFetchOriname(const char *schemaname, const char *relname, TrObjType type, + TrObjDesc *desc, TrOperMode operMode) +{ + bool found = false; + Oid nspId; + // 濡傛灉缁欏畾浜嗘ā寮忓悕绉 + if (schemaname) { + // 鑾峰彇妯″紡鐨勫懡鍚嶇┖闂碔D + nspId = get_namespace_oid(schemaname, true); + // 璋冪敤TrFetchOrinameImpl鍑芥暟杩涜鎼滅储 + found = TrFetchOrinameImpl(nspId, relname, type, desc, operMode); + } else { + List *activeSearchPath = NIL; + ListCell *l = NULL; + + // 閲嶆柊璁$畻鍛藉悕绌洪棿鎼滅储璺緞 + recomputeNamespacePath(); + // 澶嶅埗褰撳墠鐨勫懡鍚嶇┖闂存悳绱㈣矾寰 + activeSearchPath = list_copy(u_sess->catalog_cxt.activeSearchPath); + // 閬嶅巻鍛藉悕绌洪棿鎼滅储璺緞 + foreach (l, activeSearchPath) { + nspId = lfirst_oid(l); + // 璋冪敤TrFetchOrinameImpl鍑芥暟杩涜鎼滅储锛屽鏋滄壘鍒板垯鏍囪涓烘壘鍒板苟閫鍑哄惊鐜 + if (TrFetchOrinameImpl(nspId, relname, type, desc, operMode)) { + found = true; + break; + } + } + // 閲婃斁鍛藉悕绌洪棿鎼滅储璺緞鍒楄〃 + list_free_ext(activeSearchPath); + // 濡傛灉鍦ㄥ綋鍓嶆悳绱㈣矾寰勪腑鏈壘鍒帮紝鍒欏湪PG_TOAST鍛藉悕绌洪棿涓悳绱 + if (!found) { + nspId = PG_TOAST_NAMESPACE; + found = TrFetchOrinameImpl(nspId, relname, type, desc, operMode); + } + } + + return found; +} +/* + * 鍔熻兘锛氭洿鏂板洖鏀剁珯鍏崇郴涓寚瀹氬璞$殑baseid瀛楁 + * 鍙傛暟鍒楄〃锛 + * desc锛氭寚鍚慣rObjDesc缁撴瀯浣撶殑鎸囬拡锛屽寘鍚緟鏇存柊瀵硅薄鐨勬弿杩颁俊鎭 + */ +void TrUpdateBaseid(const TrObjDesc *desc) +{ + // 澹版槑鍥炴敹绔欏叧绯 + Relation rbRel; + // 澹版槑绯荤粺鎵弿鎻忚堪绗 + SysScanDesc sd; + // 澹版槑鎵弿閿暟缁勶紝鐢ㄤ簬鏋勫缓鎵弿鏉′欢 + ScanKeyData skey[1]; + // 澹版槑鍘熷鐨勫爢鍏冪粍 + HeapTuple tup; + // 澹版槑鐢ㄤ簬鏇存柊鐨勬柊鍫嗗厓缁 + HeapTuple newtup; + // 澹版槑鍊兼暟缁勶紝鐢ㄤ簬瀛樺偍寰呮洿鏂扮殑瀛楁鍊 + Datum values[Natts_pg_recyclebin] = { 0 }; + // 澹版槑绌哄兼暟缁勶紝鏍囪瘑瀛楁鏄惁涓虹┖ + bool nulls[Natts_pg_recyclebin] = { false }; + // 澹版槑鏇挎崲鏍囧織鏁扮粍锛屾爣璇嗘槸鍚﹁鏇挎崲瀵瑰簲瀛楁 + bool replaces[Natts_pg_recyclebin] = { false }; + // 鎵撳紑鍥炴敹绔欏叧绯伙紝鑾峰彇琛岀嫭鍗犻攣 + rbRel = heap_open(RecyclebinRelationId, RowExclusiveLock); + // 鍒濆鍖栨壂鎻忛敭锛屾寜鐓у璞$殑id杩涜鎼滅储 + ScanKeyInit(&skey[0], ObjectIdAttributeNumber, BTEqualStrategyNumber, + F_OIDEQ, ObjectIdGetDatum(desc->id)); + // 寮濮嬫壂鎻忓洖鏀剁珯鍏崇郴锛屼娇鐢ㄩ瀹氫箟绱㈠紩鍜屾壂鎻忛敭 + sd = systable_beginscan(rbRel, RecyclebinIdIndexId, true, NULL, 1, skey); + if ((tup = systable_getnext(sd)) == NULL) { + // 濡傛灉鏈壘鍒板尮閰嶇殑瀵硅薄锛屾姤鍛婇敊璇 + ereport(ERROR, (errmsg("recycle object %u does not exist", desc->id))); + } + // 鍑嗗鏇存柊瀛楁鐨勫煎拰鏍囧織 + replaces[Anum_pg_recyclebin_rcybaseid - 1] = true; + values[Anum_pg_recyclebin_rcybaseid - 1] = ObjectIdGetDatum(desc->baseid); + // 鏍规嵁鏂板煎垱寤烘柊鐨勫厓缁 + newtup = heap_modify_tuple(tup, RelationGetDescr(rbRel), values, nulls, replaces); + // 鎵ц鍏冪粍鏇存柊 + simple_heap_update(rbRel, &newtup->t_self, newtup); + // 鏇存柊绱㈠紩 + CatalogUpdateIndexes(rbRel, newtup); + // 閲婃斁鍐呭瓨 + heap_freetuple_ext(newtup); + // 缁撴潫鎵弿骞跺叧闂洖鏀剁珯鍏崇郴 + systable_endscan(sd); + heap_close(rbRel, RowExclusiveLock); + + return; +} +/* + * 鍔熻兘锛氬湪鍥炴敹绔欏璞′腑鍔犻攣鎸囧畾鐨勫叧绯伙紝骞舵鏌ュ叧绯绘槸鍚﹀瓨鍦 + * 鍙傛暟鍒楄〃锛 + * relid锛氳鍔犻攣鐨勫叧绯荤殑瀵硅薄ID + * type锛氬璞$殑绫诲瀷锛堣〃銆佺储寮曘佸垎鍖虹瓑锛 + */ +static void TrLockRelationImpl(Oid relid, TrObjType type) +{ + /* + * Lock failed may due to concurrently purge/timecapsule/DQL + * on recycle object, or access on normal relation. + */ + if (!ConditionalLockRelationOid(relid, AccessExclusiveLock)) { + ereport(ERROR, + (errcode(ERRCODE_RBIN_LOCK_NOT_AVAILABLE), + errmsg("could not obtain lock on relation \"%u\"", relid))); + } + + /* + * Now that we have the lock, probe to see if the relation + * really exists or not. + */ + AcceptInvalidationMessages(); + if (!SearchSysCacheExists1(RELOID, ObjectIdGetDatum(relid)) && type != RB_OBJ_PARTITION) { + /* Clean already held locks if error return. */ + UnlockRelationOid(relid, AccessExclusiveLock); + ereport(ERROR, + (errcode(ERRCODE_RBIN_UNDEFINED_OBJECT), + errmsg("relation \"%u\" does not exist", relid))); + } else if (!SearchSysCacheExists1(PARTRELID, ObjectIdGetDatum(relid)) && type == RB_OBJ_PARTITION) { + /* Clean already held locks if error return. */ + UnlockRelationOid(relid, AccessExclusiveLock); + ereport(ERROR, + (errcode(ERRCODE_RBIN_UNDEFINED_OBJECT), + errmsg("partition \"%u\" does not exist", relid))); + } +} +/* + * 鍔熻兘锛氬鍥炴敹绔欏璞′腑鐨勫叧绯昏繘琛屽姞閿侊紝棣栧厛閿佸畾绱㈠紩鍏崇郴锛堝鏋滄湁锛夛紝鐒跺悗閿佸畾鍏崇郴鑷韩 + * 鍙傛暟鍒楄〃锛 + * desc锛氬洖鏀剁珯瀵硅薄鎻忚堪 + */ +static void TrLockRelation(TrObjDesc *desc) +{ + Oid heapOid = InvalidOid; + + /* Lock heap relation for index first */ + if (desc->type == RB_OBJ_INDEX) { + heapOid = IndexGetRelation(desc->relid, true); + if (!OidIsValid(heapOid)) { + ereport(ERROR, + (errcode(ERRCODE_RBIN_UNDEFINED_OBJECT), + errmsg("relation \"%u\" does not exist", desc->relid))); + } + TrLockRelationImpl(heapOid, desc->type); + } + + /* Use TRY-CATCH block to clean locks already held if error. */ + PG_TRY(); + { + /* Lock relation self */ + TrLockRelationImpl(desc->relid, desc->type); + } + PG_CATCH(); + { + if (desc->type == RB_OBJ_INDEX) { + UnlockRelationOid(heapOid, AccessExclusiveLock); + } + PG_RE_THROW(); + } + PG_END_TRY(); +} +/* + * 鍔熻兘锛氬鍥炴敹绔欎腑鐨勬寚瀹氬璞¤繘琛岃В閿 + * 鍙傛暟鍒楄〃锛 + * desc锛氬洖鏀剁珯瀵硅薄鎻忚堪 + */ +static void TrUnlockTrItem(TrObjDesc *desc) +{ + // 瀵规寚瀹氱殑鍥炴敹绔欏璞¤繘琛岃В閿 + UnlockDatabaseObject(RecyclebinRelationId, desc->id, 0, + AccessExclusiveLock); +} + +static void TrLockTrItem(TrObjDesc *desc) +{ + Relation rbRel; + SysScanDesc sd; + ScanKeyData skey[1]; + HeapTuple tup; + + /* 1. Try to lock rb item in AccessExclusiveLock */ + if (!ConditionalLockDatabaseObject(RecyclebinRelationId, desc->id, 0, AccessExclusiveLock)) { + ereport(ERROR, + (errcode(ERRCODE_RBIN_LOCK_NOT_AVAILABLE), + errmsg("could not obtain lock on recycle object '%s'", desc->name))); + } + + /* + * 2. Now that we have the lock, probe to see if the rb item really + * exists or not. + */ + AcceptInvalidationMessages(); + + rbRel = heap_open(RecyclebinRelationId, AccessShareLock); + + ScanKeyInit(&skey[0], ObjectIdAttributeNumber, BTEqualStrategyNumber, + F_OIDEQ, ObjectIdGetDatum(desc->id)); + + sd = systable_beginscan(rbRel, RecyclebinIdIndexId, true, NULL, 1, skey); + if ((tup = systable_getnext(sd)) == NULL) { + UnlockDatabaseObject(RecyclebinRelationId, desc->id, 0, AccessExclusiveLock); + systable_endscan(sd); + heap_close(rbRel, AccessShareLock); + ereport(ERROR, + (errcode(ERRCODE_RBIN_UNDEFINED_OBJECT), + errmsg("recycle object \"%s\" does not exist", desc->name))); + } + + systable_endscan(sd); + heap_close(rbRel, AccessShareLock); + + return; +} +/* + * 鍔熻兘锛氶獙璇佸洖鏀剁珯鎿嶄綔鏄惁鍖归厤瀵硅薄鐨勫睘鎬 + * + * 鍙傛暟鍒楄〃: + * desc锛氬洖鏀剁珯瀵硅薄鎻忚堪淇℃伅 + * operMode锛氭搷浣滄ā寮 + */ +static void TrOperMatch(const TrObjDesc *desc, TrOperMode operMode) +{ + switch (operMode) { + case RB_OPER_PURGE: + /* 瀵硅薄涓嶅厑璁歌娓呴櫎涓斾笉鏄垎鍖哄璞★紝鎶ュ憡鏃犳硶娓呴櫎鐨勯敊璇 */ + if (!desc->canpurge && desc->type != RB_OBJ_PARTITION) { + ereport(ERROR, + (errcode(ERRCODE_INVALID_OPERATION), + errmsg("recycle object \"%s\" cannot be purged", desc->name))); + } + break; + + case RB_OPER_RESTORE_DROP: + /* 瀵硅薄涓嶅厑璁歌鎭㈠涓斾笉鏄垎鍖哄璞★紝鎴栬呮搷浣滅被鍨嬩笉鏄疍ROP锛屾姤鍛婃棤娉曟仮澶嶇殑閿欒 */ + if ((!desc->canrestore && desc->type != RB_OBJ_PARTITION) || desc->operation != RB_OPER_DROP) { + ereport(ERROR, + (errcode(ERRCODE_INVALID_OPERATION), + errmsg("recycle object \"%s\" cannot be restored", desc->name))); + } + break; + + case RB_OPER_RESTORE_TRUNCATE: + /* 瀵硅薄涓嶅厑璁歌鎭㈠涓斾笉鏄垎鍖哄璞★紝鎴栬呮搷浣滅被鍨嬩笉鏄疶RUNCATE锛屾姤鍛婃棤娉曟仮澶嶇殑閿欒 */ + if ((!desc->canrestore && desc->type != RB_OBJ_PARTITION) || desc->operation != RB_OPER_TRUNCATE) { + ereport(ERROR, + (errcode(ERRCODE_INVALID_OPERATION), + errmsg("recycle object \"%s\" cannot be restored", desc->name))); + } + break; + + default: + /* 鏈煡鐨勫洖鏀剁珯鎿嶄綔绫诲瀷锛屾姤鍛婃棤娉曡瘑鍒殑閿欒 */ + ereport(ERROR, + (errcode(ERRCODE_UNRECOGNIZED_NODE_TYPE), + errmsg("unrecognized recyclebin operation: %u", operMode))); + break; + } +} + +/* + * Fetch object from recycle bin for rb operations - purge, restore : + * Prefer to fetch as original name, then recycle name. + */ +void TrOperFetch(const RangeVar *purobj, TrObjType objtype, TrObjDesc *desc, TrOperMode operMode) +{ + bool found = false; + + AcceptInvalidationMessages(); + + /* Prefer to fetch as original name */ + found = TrFetchOriname(purobj->schemaname, purobj->relname, objtype, desc, operMode); + /* if not found, then fetch as recycle name */ + if (!found) { + found = TrFetchName(purobj->relname, objtype, desc, operMode); + } + + /* not found, throw error */ + if (!found) { + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_TABLE), + errmsg("recycle object \"%s\" desired does not exist", purobj->relname))); + } + + TrOperMatch(desc, operMode); + + return; +} +/* + * 鍔熻兘锛氭仮澶嶅洖鏀剁珯瀵硅薄鏃剁殑鏉冮檺妫鏌 + * + * 鍙傛暟鍒楄〃: + * desc锛氬洖鏀剁珯瀵硅薄鎻忚堪淇℃伅 + * operMode锛氭搷浣滄ā寮 + */ +static void TrPermRestore(TrObjDesc *desc, TrOperMode operMode) +{ + AclResult aclCreateResult; + + /* Check namespace permissions. */ + aclCreateResult = pg_namespace_aclcheck(desc->nspace, desc->authid, ACL_CREATE); + if (aclCreateResult != ACLCHECK_OK) { + aclcheck_error(aclCreateResult, ACL_KIND_NAMESPACE, get_namespace_name(desc->nspace)); + } + + AclResult aclUsageResult = pg_namespace_aclcheck(desc->nspace, desc->authid, ACL_USAGE); + if (aclUsageResult != ACLCHECK_OK) { + aclcheck_error(aclUsageResult, ACL_KIND_NAMESPACE, get_namespace_name(desc->nspace)); + } + + /* Allow restore to either table owner or schema owner */ + if (!pg_class_ownercheck(desc->relid, desc->authid) && !pg_namespace_ownercheck(desc->nspace, desc->authid)) { + aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_CLASS, desc->name); + return; + } + /* 濡傛灉鎿嶄綔妯″紡鏄仮澶嶄负鎴柇锛屽垯妫鏌ヨ〃鎴柇鏉冮檺 */ + if (operMode == RB_OPER_RESTORE_TRUNCATE) { + AclResult aclTruncateResult = pg_class_aclcheck(desc->relid, desc->authid, ACL_TRUNCATE); + if (aclTruncateResult != ACLCHECK_OK) { + aclcheck_error(aclTruncateResult, ACL_KIND_CLASS, desc->name); + } + } +} +/* + * 鍔熻兘锛氶獙璇佸洖鏀剁珯娓呴櫎鎿嶄綔鐨勬潈闄 + * 鍙傛暟鍒楄〃: + * desc锛氬洖鏀剁珯瀵硅薄鎻忚堪淇℃伅 + * operMode锛氭搷浣滄ā寮 + */ +static void TrPermPurge(TrObjDesc *desc, TrOperMode operMode) +{ + AclResult result; + /* 妫鏌ュ懡鍚嶇┖闂寸殑浣跨敤鏉冮檺 */ + result = pg_namespace_aclcheck(desc->nspace, desc->authid, ACL_USAGE); + if (result != ACLCHECK_OK) { + aclcheck_error(result, ACL_KIND_NAMESPACE, get_namespace_name(desc->nspace)); + } + /* 鍏佽娓呴櫎鐨勬潯浠讹細鏄〃鐨勬墍鏈夎呮垨鑰呮槸鍛藉悕绌洪棿鐨勬墍鏈夎 */ + if (!pg_class_ownercheck(desc->relid, desc->authid) && !pg_namespace_ownercheck(desc->nspace, desc->authid)) { + aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_CLASS, desc->name); + } +} + +/* + * Check permission for rb operations - purge, restore + */ + /* + * 鍔熻兘锛氶獙璇佸洖鏀剁珯鎿嶄綔鐨勬潈闄 + * 鍙傛暟鍒楄〃: + * desc锛氬洖鏀剁珯瀵硅薄鎻忚堪淇℃伅 + * operMode锛氭搷浣滄ā寮忥紙鎿嶄綔绫诲瀷锛 + */ +static void TrPerm(TrObjDesc *desc, TrOperMode operMode) +{ + switch (operMode) { + case RB_OPER_RESTORE_DROP: + case RB_OPER_RESTORE_TRUNCATE: + TrPermRestore(desc, operMode);// 璋冪敤 TrPermRestore 楠岃瘉鎭㈠鎿嶄綔鏉冮檺 + break; + case RB_OPER_PURGE: + TrPermPurge(desc, operMode);// 璋冪敤 TrPermPurge 楠岃瘉娓呴櫎鎿嶄綔鏉冮檺 + break; + default: + Assert(0); + break; + } +} + +/* + * Prepare for rb operations - purge, restore : + * check permission, lock objects + */ +/* + * TrOperPrep - 鍑嗗杩涜鍥炴敹鎿嶄綔 + * + * 姝ゅ嚱鏁扮敤浜庡噯澶囪繘琛屽洖鏀舵搷浣溿傚畠鎵ц浠ヤ笅姝ラ锛 + * 1. 妫鏌ユ潈闄愩 + * 2. 鑾峰彇鍥炴敹绔欐潯鐩殑閿侊紝浠ラ伩鍏嶅苟鍙戠殑娓呴櫎鍜屾仮澶嶆搷浣溿 + * 3. 鑾峰彇鍏崇郴鐨勯攣锛屼互閬垮厤骞跺彂鐨勬暟鎹煡璇㈡搷浣溿傛敞鎰忥細褰撹繘琛屾竻闄ゆ埅鏂叧绯绘搷浣滄椂锛屽拷鐣ユ姝ラ锛 + * 鍥犱负鍩虹鍏崇郴鍙兘涓嶅瓨鍦ㄣ + * + * 鍙傛暟鍒楄〃: + * desc: 鍥炴敹绔欏璞℃弿杩扮锛岀敤浜庤〃绀鸿杩涜鎿嶄綔鐨勫洖鏀剁珯瀵硅薄 + * operMode: 鍥炴敹鎿嶄綔鐨勬ā寮忥紝琛ㄧず鎵ц鐨勫叿浣撴搷浣滅被鍨 + */ +void TrOperPrep(TrObjDesc *desc, TrOperMode operMode) +{ + bool needLockRelation = false; + + /* + * 1. Check permission. + */ + TrPerm(desc, operMode); + + /* + * 2. Acquire lock on rb item, avoid concurrently purge, restore. + */ + TrLockTrItem(desc); + + /* + * 3. Acquire lock on relation, avoid concurrently DQL. + * Notice: ignore this step when we purge truncated relation + * as base relation may not exists. + */ + needLockRelation = !(operMode == RB_OPER_PURGE && desc->operation == RB_OPER_TRUNCATE); + if (needLockRelation) { + /* Use TRY-CATCH block to clean locks already held if error. */ + PG_TRY(); + { + TrLockRelation(desc); + } + PG_CATCH(); + { + TrUnlockTrItem(desc); + PG_RE_THROW(); + } + PG_END_TRY(); + } +} +/* + * 鍔熻兘锛氭牴鎹紶鍏ョ殑鍏崇郴ID锛坮elid锛夊垽鏂槸鍚﹀彲浠ュ璇ュ叧绯昏繘琛屽洖鏀舵搷浣溿 + * + * 鍙傛暟鍒楄〃: + * relid: 鍏崇郴ID + * + */ +bool NeedTrComm(Oid relid) +{ + Relation rel; + Form_pg_class classForm; + + if (/* + *Disable Recyclebin-based-Drop/Truncate when + */ + /* recyclebin disabled, or */ + !u_sess->attr.attr_storage.enable_recyclebin || + /* target db is template1, or */ + u_sess->proc_cxt.MyDatabaseId == TemplateDbOid || + /* in maintenance mode, or */ + u_sess->attr.attr_common.xc_maintenance_mode || + /* in in-place upgrade mode, or */ + t_thrd.proc->workingVersionNum < 92350 || + /* in non-singlenode mode, or */ + (g_instance.role != VSINGLENODE) || + /* in bootstrap mode. */ + IsInitdb) { + return false; + } + + rel = relation_open(relid, NoLock); + classForm = rel->rd_rel; + if (/* + * Disable Recyclebin-based-Drop/Truncate if + */ + /* table is non ordinary table, or */ + classForm->relkind != RELKIND_RELATION || + /* is non heap table, or */ + rel->rd_tam_type == TAM_HEAP || + /* is non regular table, or */ + classForm->relpersistence != RELPERSISTENCE_PERMANENT || + /* is shared table across databases, or */ + classForm->relisshared || + /* has derived classes, or */ + classForm->relhassubclass || + /* has any PARTIAL CLUSTER KEY, or */ + classForm->relhasclusterkey || + /* is cstore table, or */ + (rel->rd_options && StdRelOptIsColStore(rel->rd_options)) || RelationIsColStore(rel) || + /* is hbkt table, or */ + (RELATION_HAS_BUCKET(rel) || RELATION_OWN_BUCKET(rel)) || + /* is dfs table, or */ + RelationIsPAXFormat(rel) || + /* is resizing, or */ + RelationInClusterResizing(rel) || + /* is in system namespace. */ + (IsSystemNamespace(classForm->relnamespace) || IsToastNamespace(classForm->relnamespace) || + IsCStoreNamespace(classForm->relnamespace))) { + relation_close(rel, NoLock);// 鍏抽棴鍏崇郴 + return false; + } + + relation_close(rel, NoLock);// 鍏抽棴鍏崇郴 + + return true; +} +/* + * 鍔熻兘锛氭鍑芥暟鏍规嵁浼犲叆鐨勫懡鍚嶇┖闂碔D鍜屽叧绯荤被鍨嬫爣璇嗭紝纭畾骞惰繑鍥炲搴旂殑鍥炴敹瀵硅薄绫诲瀷銆 + * + * 鍙傛暟鍒楄〃: + * nspId: 鍛藉悕绌洪棿ID锛岀敤浜庡垽鏂璞℃槸鍚﹀湪TOAST鍛藉悕绌洪棿 + * relKind: 鍏崇郴绫诲瀷鏍囪瘑锛岃〃绀哄璞$殑绫诲瀷 + */ +TrObjType TrGetObjType(Oid nspId, char relKind) +{ + // 榛樿鍥炴敹瀵硅薄绫诲瀷涓鸿〃 RB_OBJ_TABLE + TrObjType type = RB_OBJ_TABLE; + // 鏍规嵁鍏崇郴绫诲瀷鏍囪瘑杩涜鍒ゆ柇骞惰缃搴旂殑鍥炴敹瀵硅薄绫诲瀷 + switch (relKind) { + case RELKIND_INDEX: + // 濡傛灉鏄储寮曞璞★紝鏍规嵁鏄惁鍦═OAST鍛藉悕绌洪棿鍒ゆ柇鏄疶OAST绱㈠紩杩樻槸鏅氱储寮 + type = IsToastNamespace(nspId) ? RB_OBJ_TOAST_INDEX : RB_OBJ_INDEX; + break; + case RELKIND_RELATION: + // 濡傛灉鏄〃瀵硅薄锛岃缃负琛ㄧ被鍨 + type = RB_OBJ_TABLE; + break; + case RELKIND_SEQUENCE: + case RELKIND_LARGE_SEQUENCE: + // 濡傛灉鏄簭鍒楀璞★紝璁剧疆涓哄簭鍒楃被鍨 + type = RB_OBJ_SEQUENCE; + break; + case RELKIND_TOASTVALUE: + // 濡傛灉鏄疶OAST鍊煎璞★紝璁剧疆涓篢OAST绫诲瀷 + type = RB_OBJ_TOAST; + break; + case PARTTYPE_PARTITIONED_RELATION: + // 濡傛灉鏄垎鍖鸿〃瀵硅薄锛岃缃负鍒嗗尯琛ㄧ被鍨 + type = RB_OBJ_PARTITION; + break; + case RELKIND_GLOBAL_INDEX: + // 濡傛灉鏄叏灞绱㈠紩瀵硅薄锛岃缃负鍏ㄥ眬绱㈠紩绫诲瀷 + type = RB_OBJ_GLOBAL_INDEX; + break; + case RELKIND_MATVIEW: + // 濡傛灉鏄墿鍖栬鍥惧璞★紝璁剧疆涓虹墿鍖栬鍥剧被鍨 + type = RB_OBJ_MATVIEW; + break; + default: + /* Never reached here. */ + // 瀵逛簬鍏朵粬鏈煡鐨勫叧绯荤被鍨嬶紝鏂█鎶ラ敊锛屽洜涓轰笉搴旇鍒拌揪杩欎釜鍒嗘敮 + Assert(0); + break; + } + // 杩斿洖纭畾鐨勫洖鏀跺璞$被鍨 + return type; +} +/* + * 鍔熻兘锛氱敤浜庢鏌ョ粰瀹氱殑瀵硅薄鍦板潃鏄惁瀛樺湪浜庣粰瀹氱殑瀵硅薄鍦板潃闆嗗悎涓 + * + * 鍙傛暟鍒楄〃: + * classid: 瀵硅薄鐨勭被鍒爣璇 + * objid: 瀵硅薄鐨勫敮涓鏍囪瘑 + * objSet: 瀵硅薄鍦板潃闆嗗悎锛屽寘鍚涓璞$殑鍦板潃淇℃伅 + */ +static bool TrObjAddrExists(Oid classid, Oid objid, ObjectAddresses *objSet) +{ + int i; + // 閬嶅巻瀵硅薄鍦板潃闆嗗悎涓殑姣忎釜瀵硅薄鍦板潃 + for (i = 0; i < objSet->numrefs; i++) { + // 濡傛灉缁欏畾鐨勫璞″湴鍧鍜岄泦鍚堜腑鐨勫璞″湴鍧鍖归厤锛岃繑鍥 true + if (TrObjIsEqualEx(classid, objid, &objSet->refs[i])) { + return true; + } + } + // 鑻ラ亶鍘嗗畬鎵鏈夊璞″湴鍧浠嶆湭鎵惧埌鍖归厤椤癸紝杩斿洖 false + return false; +} + +/* + * output: refobjs + */ +/* + * 鍔熻兘鐢ㄤ簬鏌ユ壘寮曠敤缁欏畾瀵硅薄鐨勬墍鏈夊叾浠栧璞★紝骞跺皢杩欎簺寮曠敤瀵硅薄鐨勫湴鍧娣诲姞鍒版寚瀹氱殑瀵硅薄鍦板潃闆嗗悎涓 + * + * 鍙傛暟鍒楄〃: + * depRel: 鐢ㄤ簬鎵弿渚濊禆鍏崇郴鐨勫叧绯诲璞 + * subobj: 琚紩鐢ㄥ璞$殑鍦板潃淇℃伅 + * refobjs: 瀛樺偍寮曠敤瀵硅薄鍦板潃鐨勫璞″湴鍧闆嗗悎 + * ignoreObjSubId: 鏄惁蹇界暐琚紩鐢ㄥ璞$殑瀛愭爣璇嗭紝榛樿涓 false + */ +void TrFindAllRefObjs(Relation depRel, const ObjectAddress *subobj, + ObjectAddresses *refobjs, bool ignoreObjSubId) +{ + SysScanDesc sd; + HeapTuple tuple; + ScanKeyData key[3]; + int nkeys; + // 鍒濆鍖栫敤浜庢壂鎻忕殑閿 + ScanKeyInit(&key[0], Anum_pg_depend_classid, BTEqualStrategyNumber, F_OIDEQ, + ObjectIdGetDatum(subobj->classId)); + ScanKeyInit(&key[1], Anum_pg_depend_objid, BTEqualStrategyNumber, F_OIDEQ, + ObjectIdGetDatum(subobj->objectId)); + nkeys = 2; + // 濡傛灉涓嶅拷鐣ュ璞$殑瀛愭爣璇嗕笖瀛愭爣璇嗕笉涓0锛屾坊鍔犵涓変釜閿 + if (!ignoreObjSubId && subobj->objectSubId != 0) { + ScanKeyInit(&key[2], Anum_pg_depend_objsubid, BTEqualStrategyNumber, F_INT4EQ, + Int32GetDatum(subobj->objectSubId)); + nkeys = 3; + } + // 寮濮嬫壂鎻忎緷璧栧叧绯 + sd = systable_beginscan(depRel, DependDependerIndexId, true, NULL, nkeys, key); + while (HeapTupleIsValid(tuple = systable_getnext(sd))) { + Form_pg_depend depForm = (Form_pg_depend)GETSTRUCT(tuple); + /* Cascaded clean rb object in `DROP SCHEMA` command. */ + if (depForm->refclassid == NamespaceRelationId) { + continue; + } + + /* We keep `objSet` unique when `ignoreObjSubId = true` to avoid circle recursive. */ + if (!ignoreObjSubId || !TrObjAddrExists(depForm->refclassid, depForm->refobjid, refobjs)) { + add_object_address_ext(depForm->refclassid, depForm->refobjid, + depForm->refobjsubid, depForm->deptype, refobjs); + } + } + + systable_endscan(sd);//缁撴潫鎵弿 + return; +} +/* + * 鍔熻兘锛氱敤浜庢煡鎵惧紩鐢ㄧ粰瀹氬璞$殑鎵鏈夊唴閮ㄥ璞★紝骞跺皢杩欎簺鍐呴儴瀵硅薄鐨勫湴鍧娣诲姞鍒版寚瀹氱殑瀵硅薄鍦板潃闆嗗悎涓 + * + * 鍙傛暟鍒楄〃: + * depRel: 鐢ㄤ簬鎵弿渚濊禆鍏崇郴鐨勫叧绯诲璞 + * refobj: 琚紩鐢ㄥ璞$殑鍦板潃淇℃伅 + * objSet: 瀛樺偍鍐呴儴瀵硅薄鍦板潃鐨勫璞″湴鍧闆嗗悎 + * ignoreObjSubId: 鏄惁蹇界暐琚紩鐢ㄥ璞$殑瀛愭爣璇嗭紝榛樿涓 false + */ +static void TrFindAllInternalObjs(Relation depRel, const ObjectAddress *refobj, + ObjectAddresses *objSet, bool ignoreObjSubId = false) +{ + SysScanDesc sd; + HeapTuple tuple; + ScanKeyData key[3]; + int nkeys; + // 鍒濆鍖栫敤浜庢壂鎻忕殑閿 + ScanKeyInit(&key[0], Anum_pg_depend_refclassid, BTEqualStrategyNumber, F_OIDEQ, + ObjectIdGetDatum(refobj->classId)); + ScanKeyInit(&key[1], Anum_pg_depend_refobjid, BTEqualStrategyNumber, F_OIDEQ, + ObjectIdGetDatum(refobj->objectId)); + nkeys = 2; + // 濡傛灉涓嶅拷鐣ュ璞$殑瀛愭爣璇嗕笖瀛愭爣璇嗕笉涓0锛屾坊鍔犵涓変釜閿 + if (!ignoreObjSubId && refobj->objectSubId != 0) { + ScanKeyInit(&key[2], Anum_pg_depend_refobjsubid, BTEqualStrategyNumber, F_INT4EQ, + Int32GetDatum(refobj->objectSubId)); + nkeys = 3; + } + // 寮濮嬫壂鎻忎緷璧栧叧绯 + sd = systable_beginscan(depRel, DependReferenceIndexId, true, NULL, nkeys, key); + while (HeapTupleIsValid(tuple = systable_getnext(sd))) { + Form_pg_depend depForm = (Form_pg_depend)GETSTRUCT(tuple); + // 浠呭鐞 deptype 涓 'i' 鐨勫璞 + if (depForm->deptype != 'i') { + continue; + } + + /* We keep `objSet` unique when `ignoreObjSubId = true` to avoid circle recursive. */ + if (!ignoreObjSubId || !TrObjAddrExists(depForm->classid, depForm->objid, objSet)) { + // 灏嗗唴閮ㄥ璞$殑鍦板潃娣诲姞鍒板璞″湴鍧闆嗗悎涓 + add_object_address_ext(depForm->classid, depForm->objid, + depForm->objsubid, depForm->deptype, objSet); + } + } + + systable_endscan(sd);// 缁撴潫鎵弿 + return; +} +/* + * 鍔熻兘鏍规嵁鍥炴敹绔欏璞$殑鎿嶄綔绫诲瀷锛堟搷浣滅爜锛夋潵鎵ц鐩稿簲鐨勬竻闄ゆ搷浣溿傚彲浠ユ槸 DROP 鎴 TRUNCATE銆 + * + * 鍙傛暟鍒楄〃: + * desc: 寰呮竻闄ょ殑鍥炴敹绔欏璞℃弿杩 + */ +static void TrDoPurgeObject(TrObjDesc *desc) +{ + if (desc->operation == RB_OPER_DROP) { + TrDoPurgeObjectDrop(desc); + } else { + TrDoPurgeObjectTruncate(desc); + } +} +/* + * 鍔熻兘锛氭墽琛屽洖鏀剁珯瀵硅薄鐨勬案涔呭垹闄ゆ搷浣 + * 鍙傛暟鍒楄〃锛 + * purobj锛氳姘镐箙鍒犻櫎鐨勫璞$殑鑼冨洿鍙橀噺 + * type锛氬璞$殑绫诲瀷锛堜緥濡傝〃銆佺储寮曠瓑锛 + */ +void TrPurgeObject(RangeVar *purobj, TrObjType type) +{ + TrObjDesc desc; + + // 鑾峰彇鍥炴敹绔欏璞$殑鎻忚堪淇℃伅 + TrOperFetch(purobj, type, &desc, RB_OPER_PURGE); + + // 璁剧疆鎿嶄綔鐨勬巿鏉冪敤鎴 ID + desc.authid = GetUserId(); + + // 鍑嗗鎵ц鍒犻櫎鎿嶄綔锛屽寘鎷潈闄愭鏌ョ瓑 + TrOperPrep(&desc, RB_OPER_PURGE); + + // 鎵ц瀹為檯鐨勬案涔呭垹闄ゆ搷浣 + TrDoPurgeObject(&desc); + + return; +} +// 涓娆℃案涔呭垹闄ゆ搷浣滀腑瑕佸鐞嗙殑瀵硅薄鏁伴噺锛堟壒閲忓鐞嗙殑澶у皬锛 +const int PURGE_BATCH = 64; +// 鍗曚釜姘镐箙鍒犻櫎鎿嶄綔涓澶勭悊鐨勫璞℃暟閲 +const int PURGE_SINGL = 64; +// TrFetchBeginHook 鏄嚱鏁版寚閽堢被鍨嬶紝鐢ㄤ簬鎸囧悜鍦ㄨ幏鍙栧洖鏀剁珯瀵硅薄鍓嶆墽琛岀殑閽╁瓙鍑芥暟銆 +// 璇ラ挬瀛愬嚱鏁版帴鍙 SysScanDesc 鎸囬拡鍜屽璞$殑 ID 浣滀负鍙傛暟锛岀敤浜庡垵濮嬪寲鎵弿浠ヨ幏鍙栧洖鏀剁珯瀵硅薄銆 +typedef void (*TrFetchBeginHook)(SysScanDesc *sd, Oid objId); +// TrFetchMatchHook 鏄嚱鏁版寚閽堢被鍨嬶紝鐢ㄤ簬鎸囧悜鍦ㄨ幏鍙栧洖鏀剁珯瀵硅薄鍚庢墽琛岀殑閽╁瓙鍑芥暟銆 +// 璇ラ挬瀛愬嚱鏁版帴鍙楀洖鏀剁珯鍏崇郴銆佸爢鍏冪粍鍜屽璞 ID 浣滀负鍙傛暟锛岀敤浜庢鏌ュ洖鏀剁珯瀵硅薄鏄惁鍖归厤銆 +typedef bool (*TrFetchMatchHook)(Relation rbRel, HeapTuple rbTup, Oid objId); +/* + * 鍔熻兘锛氬紑濮嬫墽琛屽洖鏀剁珯瀵硅薄鎻愬彇鎿嶄綔鐨勯挬瀛愬嚱鏁 + * 鍙傛暟鍒楄〃锛 + * fetchHook锛氭彁鍙栨搷浣滅殑閽╁瓙鍑芥暟鎸囬拡 + * sd锛氱郴缁熸壂鎻忔弿杩扮鎸囬拡 + * objId锛氬璞$殑鏍囪瘑绗 + */ +static void TrFetchBegin(TrFetchBeginHook fetchHook, SysScanDesc *sd, Oid objId) +{ + // 璋冪敤鎻愬彇鎿嶄綔鐨勯挬瀛愬嚱鏁帮紝浼犲叆绯荤粺鎵弿鎻忚堪绗﹀拰瀵硅薄鏍囪瘑绗 + fetchHook(sd, objId); +} + +// @return: true for eof +/* + * 鍔熻兘锛氭墽琛屽洖鏀剁珯瀵硅薄鎻愬彇鎿嶄綔鐨勬墽琛屽嚱鏁 + * 鍙傛暟鍒楄〃锛 + * matchHook锛氬尮閰嶆搷浣滅殑閽╁瓙鍑芥暟鎸囬拡 + * objId锛氬璞$殑鏍囪瘑绗 + * sd锛氱郴缁熸壂鎻忔弿杩扮 + * desc锛氬洖鏀剁珯瀵硅薄鎻忚堪缁撴瀯鐨勬寚閽 + */ +static bool TrFetchExec(TrFetchMatchHook matchHook, Oid objId, SysScanDesc sd, TrObjDesc *desc) +{ + HeapTuple tup; + while ((tup = systable_getnext(sd)) != NULL) { + // 鑾峰彇鍫嗗厓缁勭殑缁撴瀯浣撳舰寮 + Form_pg_recyclebin rbForm = (Form_pg_recyclebin)GETSTRUCT(tup); + + // 鏍规嵁鍥炴敹绔欏璞$被鍨嬪拰鍖归厤鎿嶄綔鐨勭粨鏋滆繘琛屽鐞 + if ((rbForm->rcytype == RB_OBJ_TABLE) && matchHook(sd->heap_rel, tup, objId)) { + // 鏂█鍥炴敹绔欏璞″彲浠ユ案涔呭垹闄 + Assert(rbForm->rcycanpurge); + + // 璇诲彇鍥炴敹绔欏璞℃弿杩颁俊鎭 + TrDescRead(desc, tup); + + // 杩斿洖 false锛岃〃绀烘垚鍔熷尮閰嶅苟鎻愬彇瀵硅薄 + return false; + } else if ((rbForm->rcytype == RB_OBJ_PARTITION) && matchHook(sd->heap_rel, tup, objId)) { + // 鏂█鍥炴敹绔欏璞′笉鍙案涔呭垹闄 + Assert(!rbForm->rcycanpurge); + + // 璇诲彇鍥炴敹绔欏璞℃弿杩颁俊鎭 + TrDescRead(desc, tup); + + // 杩斿洖 false锛岃〃绀烘垚鍔熷尮閰嶅苟鎻愬彇瀵硅薄 + return false; + } + } + + // 濡傛灉娌℃湁鍖归厤鐨勫璞★紝杩斿洖 true + return true; +} + +/* + * 鍔熻兘锛氱粨鏉熷洖鏀剁珯瀵硅薄鎻愬彇鎿嶄綔鐨勬壂鎻忓苟閲婃斁鐩稿叧璧勬簮 + * 鍙傛暟鍒楄〃锛 + * sd锛氱郴缁熸壂鎻忔弿杩扮 + */ +static void TrFetchEnd(SysScanDesc sd) +{ + // 鑾峰彇鍥炴敹绔欏叧绯荤殑寮曠敤 + Relation rbRel = sd->heap_rel; + + // 缁撴潫绯荤粺鎵弿 + systable_endscan(sd); + + // 鍏抽棴鍥炴敹绔欏叧绯伙紝閲婃斁鍏变韩閿 + heap_close(rbRel, AccessShareLock); +} + + +/* + * 鍔熻兘锛氭壒閲忔案涔呭垹闄ゅ洖鏀剁珯瀵硅薄 + * 鍙傛暟鍒楄〃锛 + * beginHook锛氬紑濮嬫彁鍙栫殑閽╁瓙鍑芥暟 + * matchHook锛氬尮閰嶇殑閽╁瓙鍑芥暟 + * objId锛氬璞$殑ID + * roleid锛氳鑹茬殑ID + * maxBatch锛氭渶澶ф壒娆℃暟閲 + * localRes锛氱敤浜庡瓨鍌ㄥ垹闄ょ粨鏋滅殑缁撴瀯浣撴寚閽 + */ +static bool TrPurgeBatch(TrFetchBeginHook beginHook, TrFetchMatchHook matchHook, + Oid objId, Oid roleid, uint32 maxBatch, PurgeMsgRes *localRes) +{ + SysScanDesc sd = NULL; + TrObjDesc desc; + uint32 count = 0; + bool eof = false; + + // 閲嶇疆鏈湴鍒犻櫎缁撴灉淇℃伅 + RbMsgResetRes(localRes); + + // 寮鍚簨鍔 + StartTransactionCommand(); + + // 寮濮嬫彁鍙栧洖鏀剁珯瀵硅薄 + TrFetchBegin(beginHook, &sd, objId); + + // 寰幆鎵ц鎵归噺鍒犻櫎鎿嶄綔锛岀洿鍒版壒娆$粨鏉 + while (!(eof = TrFetchExec(matchHook, objId, sd, &desc))) { + CHECK_FOR_INTERRUPTS(); + + // 浣跨敤 TRY-CATCH 鍧楁潵澶勭悊鍒犻櫎杩囩▼涓殑寮傚父鎯呭喌 + PG_TRY(); + { + // 璁剧疆瑕佹墽琛屽垹闄ょ殑瑙掕壊 + desc.authid = roleid; + + // 鍑嗗鍒犻櫎鎿嶄綔锛屾鏌ユ潈闄愮瓑 + TrOperPrep(&desc, RB_OPER_PURGE); + + // 鎵ц鍒犻櫎鎿嶄綔 + TrDoPurgeObject(&desc); + + // 鏇存柊鏈湴鍒犻櫎缁撴灉缁熻 + localRes->purgedNum++; + } + PG_CATCH(); + { + int errcode = geterrcode(); + if (errcode == ERRCODE_RBIN_LOCK_NOT_AVAILABLE) { + errno_t rc; + // 濡傛灉閿佷笉鍙敤锛岃褰曢敊璇秷鎭紝骞跺鍔犺烦杩囨暟閲 + rc = strncpy_s(localRes->errMsg, RB_MAX_ERRMSG_SIZE, Geterrmsg(), RB_MAX_ERRMSG_SIZE - 1); + securec_check(rc, "\0", "\0"); + localRes->skippedNum++; + } else if (errcode == ERRCODE_RBIN_UNDEFINED_OBJECT) { + // 濡傛灉瀵硅薄鏈畾涔夛紝澧炲姞鏈畾涔夋暟閲 + localRes->undefinedNum++; + } else { + // 鍏朵粬寮傚父鎯呭喌锛岄噸鏂版姏鍑哄紓甯 + PG_RE_THROW(); + } + } + PG_END_TRY(); + + // 濡傛灉杈惧埌鏈澶ф壒娆℃暟閲忥紝璺冲嚭寰幆 + if (++count >= maxBatch) { + break; + } + } + + // 缁撴潫鍥炴敹绔欏璞℃彁鍙栨搷浣 + TrFetchEnd(sd); + + // 鎻愪氦浜嬪姟 + CommitTransactionCommand(); + + // 杩斿洖鎵规鏄惁缁撴潫鐨勬爣蹇 + return eof; +} + + +/* + * 鍔熻兘锛氬紑濮嬫彁鍙栨寚瀹氳〃绌洪棿涓嬬殑鍥炴敹绔欏璞 + * 鍙傛暟鍒楄〃锛 + * sd锛氱敤浜庢壂鎻忕殑 SysScanDesc 鎸囬拡 + * spcId锛氳〃绌洪棿鐨処D + */ +static void TrFetchBeginSpace(SysScanDesc *sd, Oid spcId) +{ + ScanKeyData skey[2]; + Relation rbRel; + + // 鎵撳紑鍥炴敹绔欏叧绯 + rbRel = heap_open(RecyclebinRelationId, AccessShareLock); + + // 鍒濆鍖栨壂鎻忛敭 + ScanKeyInit(&skey[0], Anum_pg_recyclebin_rcytablespace, BTEqualStrategyNumber, + F_OIDEQ, ObjectIdGetDatum(spcId)); + ScanKeyInit(&skey[1], Anum_pg_recyclebin_rcydbid, BTEqualStrategyNumber, + F_OIDEQ, ObjectIdGetDatum(u_sess->proc_cxt.MyDatabaseId)); + + // 寮濮嬫壂鎻忓洖鏀剁珯瀵硅薄 + *sd = systable_beginscan(rbRel, RecyclebinDbidSpcidRcycsnIndexId, true, NULL, 2, skey); +} + +/* + * 鍔熻兘锛氬尮閰嶅洖鏀剁珯瀵硅薄鏄惁灞炰簬鎸囧畾鐨勮〃绌洪棿 + * 鍙傛暟鍒楄〃锛 + * rbRel锛氬洖鏀剁珯鍏崇郴 + * rbTup锛氬綋鍓嶇殑鍥炴敹绔欏厓缁 + * objId锛氳鍖归厤鐨勫璞D + */ +static bool TrFetchMatchSpace(Relation rbRel, HeapTuple rbTup, Oid objId) +{ + Form_pg_recyclebin rbForm = (Form_pg_recyclebin)GETSTRUCT(rbTup); + return rbForm->rcytablespace == objId; +} + +/* + * 鍔熻兘锛氭竻闄ゆ寚瀹氳〃绌洪棿涓嬬殑鍥炴敹绔欏璞 + * 鍙傛暟鍒楄〃锛 + * id锛氬洖鏀剁珯娑堟伅鐨処D + */ +void TrPurgeTablespace(int64 id) +{ + PurgeMsgReq *req = &RbMsg(id)->req; // 鑾峰彇鍥炴敹绔欐秷鎭殑璇锋眰淇℃伅 + PurgeMsgRes localRes; // 鏈湴鐨勬竻闄ょ粨鏋 + bool eof = false; // 琛ㄧず鏄惁鍒拌揪鍥炴敹绔欏璞$殑鏈熬 + + do { + // 閫愭壒娓呴櫎鍥炴敹绔欏璞 + eof = TrPurgeBatch(TrFetchBeginSpace, TrFetchMatchSpace, req->objId, req->authId, PURGE_BATCH, &localRes); + + // 鏇存柊娑堟伅鐨勭粺璁′俊鎭 + RbMsgSetStatistics(id, &localRes); + } while (!eof && localRes.skippedNum == 0); +} + + +/* + * 鍔熻兘锛氫互閫愪釜瀵硅薄鏂瑰紡娓呴櫎鎸囧畾琛ㄧ┖闂翠笅鐨勫洖鏀剁珯瀵硅薄 + * 鍙傛暟鍒楄〃锛 + * id锛氬洖鏀剁珯娑堟伅鐨処D + */ +void TrPurgeTablespaceDML(int64 id) +{ + PurgeMsgReq *req = &RbMsg(id)->req; // 鑾峰彇鍥炴敹绔欐秷鎭殑璇锋眰淇℃伅 + PurgeMsgRes localRes; // 鏈湴鐨勬竻闄ょ粨鏋 + bool eof = false; // 琛ㄧず鏄惁鍒拌揪鍥炴敹绔欏璞$殑鏈熬 + + do { + // 閫愪釜瀵硅薄娓呴櫎鍥炴敹绔欏璞 + eof = TrPurgeBatch(TrFetchBeginSpace, TrFetchMatchSpace, req->objId, req->authId, PURGE_SINGL, &localRes); + + // 鏇存柊娑堟伅鐨勭粺璁′俊鎭 + RbMsgSetStatistics(id, &localRes); + } while (!eof && localRes.purgedNum == 0); +} +/* + * 鍔熻兘锛氬垵濮嬪寲鍥炴敹绔欎腑鎸囧畾瀵硅薄鐨勬壂鎻 + * 鍙傛暟鍒楄〃锛 + * sd锛歋ysScanDesc 缁撴瀯鐨勬寚閽堬紝鐢ㄤ簬鎺ユ敹鎵弿鎻忚堪 + * objId锛氳鍒濆鍖栨壂鎻忕殑瀵硅薄鐨処D + */ +static void TrFetchBeginRecyclebin(SysScanDesc *sd, Oid objId) +{ + ScanKeyData skey[2]; // 鎵弿閿暟缁 + Relation rbRel; // 鍥炴敹绔欏叧绯诲璞 + + rbRel = heap_open(RecyclebinRelationId, AccessShareLock); // 鎵撳紑鍥炴敹绔欏叧绯诲璞 + + // 鍒濆鍖栨壂鎻忛敭锛岄氳繃鏁版嵁搴揑D鏉ョ瓫閫夊洖鏀剁珯涓殑瀵硅薄 + ScanKeyInit(&skey[0], Anum_pg_recyclebin_rcydbid, BTEqualStrategyNumber, + F_OIDEQ, ObjectIdGetDatum(u_sess->proc_cxt.MyDatabaseId)); + + // 寮濮嬫壂鎻忓洖鏀剁珯鍏崇郴瀵硅薄 + *sd = systable_beginscan(rbRel, RecyclebinDbidRelidIndexId, true, NULL, 1, skey); +} + + +/* + * 鍔熻兘锛氭鏌ュ洖鏀剁珯瀵硅薄鏄惁鍖归厤锛屽缁堣繑鍥 true锛屽嵆琛ㄧず鍖归厤浠讳綍鍥炴敹绔欏璞 + * 鍙傛暟鍒楄〃锛 + * rbRel锛氬洖鏀剁珯鍏崇郴瀵硅薄 + * rbTup锛氬洖鏀剁珯鍏冪粍锛圚eapTuple锛 + * objId锛氳鍖归厤鐨勫璞$殑ID锛堟棤鏁堢殑锛 + */ +static bool TrFetchMatchRecyclebin(Relation rbRel, HeapTuple rbTup, Oid objId) +{ + return true; // 濮嬬粓杩斿洖 true锛岃〃绀哄尮閰嶄换浣曞洖鏀剁珯瀵硅薄 +} + +/* + * 鍔熻兘锛氭案涔呭垹闄ゅ洖鏀剁珯涓殑瀵硅薄 + * 鍙傛暟鍒楄〃锛 + * id锛氭秷鎭疘D + */ +void TrPurgeRecyclebin(int64 id) +{ + PurgeMsgReq *req = &RbMsg(id)->req; // 鑾峰彇娑堟伅璇锋眰 + PurgeMsgRes localRes; // 鐢ㄤ簬淇濆瓨鏈湴娓呴櫎缁撴灉 + bool eof = false; // 鏍囪瘑鎵弿鏄惁缁撴潫 + + do { + // 鎵ц鍥炴敹绔欏璞$殑鎵归噺娓呴櫎 + eof = TrPurgeBatch(TrFetchBeginRecyclebin, TrFetchMatchRecyclebin, + InvalidOid, req->authId, PURGE_BATCH, &localRes); + + // 鏇存柊娑堟伅鐨勭粺璁′俊鎭 + RbMsgSetStatistics(id, &localRes); + } while (!eof && localRes.skippedNum == 0); // 缁х画寰幆鐩村埌鎵弿缁撴潫鎴栨病鏈夎璺宠繃鐨勫璞 +} + + +/* + * 鍔熻兘锛氬紑濮嬪湪鍥炴敹绔欎腑鎵弿涓庢寚瀹氭ā寮忓尮閰嶇殑瀵硅薄 + * 鍙傛暟鍒楄〃锛 + * sd锛氭壂鎻忔弿杩扮鎸囬拡锛岀敤浜庡瓨鍌ㄦ壂鎻忕粨鏋 + * objId锛氳鍖归厤鐨勬ā寮忕殑ID + */ +static void TrFetchBeginSchema(SysScanDesc *sd, Oid objId) +{ + ScanKeyData skey[2]; // 鎵弿閿暟缁 + Relation rbRel; // 鍥炴敹绔欏叧绯诲璞 + + rbRel = heap_open(RecyclebinRelationId, AccessShareLock); // 鎵撳紑鍥炴敹绔欏叧绯诲璞 + ScanKeyInit(&skey[0], Anum_pg_recyclebin_rcynamespace, BTEqualStrategyNumber, + F_OIDEQ, ObjectIdGetDatum(objId)); // 鍒濆鍖栨壂鎻忛敭锛屽尮閰嶆ā寮忕殑鍛藉悕绌洪棿 + ScanKeyInit(&skey[1], Anum_pg_recyclebin_rcydbid, BTEqualStrategyNumber, + F_OIDEQ, ObjectIdGetDatum(u_sess->proc_cxt.MyDatabaseId)); // 鍒濆鍖栨壂鎻忛敭锛屽尮閰嶅綋鍓嶆暟鎹簱ID + + *sd = systable_beginscan(rbRel, RecyclebinDbidNspOrinameIndexId, true, NULL, 2, skey); // 寮濮嬫壂鎻 +} + + +/* + * 鍔熻兘锛氬湪鍥炴敹绔欎腑鍖归厤鎸囧畾妯″紡鐨勫璞 + * 鍙傛暟鍒楄〃锛 + * rbRel锛氬洖鏀剁珯鍏崇郴瀵硅薄 + * rbTup锛氬洖鏀剁珯涓殑鍏冪粍 + * objId锛氳鍖归厤鐨勬ā寮忕殑ID + */ +static bool TrFetchMatchSchema(Relation rbRel, HeapTuple rbTup, Oid objId) +{ + Form_pg_recyclebin rbForm = (Form_pg_recyclebin)GETSTRUCT(rbTup); // 鑾峰彇鍏冪粍鐨勬暟鎹粨鏋勪綋 + return rbForm->rcynamespace == objId; // 杩斿洖鏄惁鍖归厤妯″紡鐨勫懡鍚嶇┖闂 +} + +/* + * 鍔熻兘锛氭墽琛屽洖鏀剁珯涓寚瀹氭ā寮忕殑瀵硅薄鐨勬案涔呭垹闄ゆ搷浣 + * 鍙傛暟鍒楄〃锛 + * id锛氳鍒犻櫎鐨勬ā寮忕殑ID + */ +void TrPurgeSchema(int64 id) +{ + PurgeMsgReq *req = &RbMsg(id)->req; // 鑾峰彇璇锋眰娑堟伅 + PurgeMsgRes localRes; // 鐢ㄤ簬瀛樺偍鍒犻櫎鎿嶄綔鐨勭粨鏋 + bool eof = false; + + do { + eof = TrPurgeBatch(TrFetchBeginSchema, TrFetchMatchSchema, req->objId, req->authId, PURGE_BATCH, &localRes); // 鎵ц鎵归噺姘镐箙鍒犻櫎鎿嶄綔 + RbMsgSetStatistics(id, &localRes); // 鏇存柊鍒犻櫎缁熻淇℃伅 + } while (!eof && localRes.skippedNum == 0); // 褰撴壒閲忓垹闄ゆ湭瀹屾垚涓旀湭璺宠繃浠讳綍鎿嶄綔鏃剁户缁墽琛 +} + +/* + * 鍔熻兘锛氬湪鍥炴敹绔欎腑鏍规嵁鐢ㄦ埛ID寮濮嬫壂鎻忓尮閰嶇殑瀵硅薄 + * 鍙傛暟鍒楄〃锛 + * sd锛氭壂鎻忔弿杩扮鎸囬拡锛岀敤浜庡瓨鍌ㄦ壂鎻忕粨鏋 + * objId锛氳鍖归厤鐨勫璞$殑ID锛堝湪杩欓噷鏄敤鎴稩D锛 + */ +static void TrFetchBeginUser(SysScanDesc *sd, Oid objId) +{ + ScanKeyData skey[2]; // 鎵弿閿暟缁 + Relation rbRel; // 鍥炴敹绔欏叧绯诲璞 + + rbRel = heap_open(RecyclebinRelationId, AccessShareLock); // 鎵撳紑鍥炴敹绔欏叧绯诲璞★紝鑾峰彇璁块棶鍏变韩閿 + + // 鍒濆鍖栨壂鎻忛敭 + ScanKeyInit(&skey[0], Anum_pg_recyclebin_rcydbid, BTEqualStrategyNumber, + F_OIDEQ, ObjectIdGetDatum(u_sess->proc_cxt.MyDatabaseId)); + + // 寮濮嬫壂鎻忓洖鏀剁珯鍏崇郴瀵硅薄锛屽苟灏嗘壂鎻忕粨鏋滃瓨鍌ㄥ埌鎵弿鎻忚堪绗︿腑 + *sd = systable_beginscan(rbRel, RecyclebinDbidRelidIndexId, true, NULL, 1, skey); +} + +/* + * 鍔熻兘锛氬湪鍥炴敹绔欎腑鍖归厤鎸囧畾鐢ㄦ埛鐨勫璞 + * 鍙傛暟鍒楄〃锛 + * rbRel锛氬洖鏀剁珯鍏崇郴瀵硅薄 + * rbTup锛氬洖鏀剁珯涓殑鍏冪粍 + * objId锛氳鍖归厤鐨勭敤鎴风殑ID + */ +static bool TrFetchMatchUser(Relation rbRel, HeapTuple rbTup, Oid objId) +{ + Form_pg_recyclebin rbForm = (Form_pg_recyclebin)GETSTRUCT(rbTup); // 鑾峰彇鍏冪粍鐨勬暟鎹粨鏋勪綋 + return rbForm->rcyowner == objId; // 杩斿洖鏄惁鍖归厤鎸囧畾鐢ㄦ埛鐨勬墍鏈夎 +} + +/* + * 鍔熻兘锛氭墽琛屽洖鏀剁珯涓寚瀹氱敤鎴风殑瀵硅薄鐨勬案涔呭垹闄ゆ搷浣 + * 鍙傛暟鍒楄〃锛 + * id锛氳鍒犻櫎鐨勭敤鎴风殑ID + */ +void TrPurgeUser(int64 id) +{ + PurgeMsgReq *req = &RbMsg(id)->req; // 鑾峰彇璇锋眰娑堟伅 + PurgeMsgRes localRes; // 鐢ㄤ簬瀛樺偍鍒犻櫎鎿嶄綔鐨勭粨鏋 + bool eof = false; + + do { + eof = TrPurgeBatch(TrFetchBeginUser, TrFetchMatchUser, req->objId, req->authId, PURGE_BATCH, &localRes); // 鎵ц鎵归噺姘镐箙鍒犻櫎鎿嶄綔 + RbMsgSetStatistics(id, &localRes); // 鏇存柊鍒犻櫎缁熻淇℃伅 + } while (!eof && localRes.skippedNum == 0); // 褰撴壒閲忓垹闄ゆ湭瀹屾垚涓旀湭璺宠繃浠讳綍鎿嶄綔鏃剁户缁墽琛 +} + +/* + * 鍔熻兘锛氬湪鍥炴敹绔欎腑鏍规嵁鑷姩娓呯悊绛栫暐寮濮嬫壂鎻忓尮閰嶇殑瀵硅薄 + * 鍙傛暟鍒楄〃锛 + * sd锛氭壂鎻忔弿杩扮鎸囬拡锛岀敤浜庡瓨鍌ㄦ壂鎻忕粨鏋 + * objId锛氳鍖归厤鐨勫璞$殑ID锛堝湪杩欓噷鏄棤鏁堢殑锛屼笉浣跨敤锛 + */ +static void TrFetchBeginAuto(SysScanDesc *sd, Oid objId) +{ + ScanKeyData skey[2]; // 鎵弿閿暟缁 + Relation rbRel; // 鍥炴敹绔欏叧绯诲璞 + + rbRel = heap_open(RecyclebinRelationId, AccessShareLock); // 鎵撳紑鍥炴敹绔欏叧绯诲璞★紝鑾峰彇璁块棶鍏变韩閿 + + // 鍒濆鍖栨壂鎻忛敭 + ScanKeyInit(&skey[0], Anum_pg_recyclebin_rcydbid, BTEqualStrategyNumber, + F_OIDEQ, ObjectIdGetDatum(u_sess->proc_cxt.MyDatabaseId)); + + // 寮濮嬫壂鎻忓洖鏀剁珯鍏崇郴瀵硅薄锛屽苟灏嗘壂鎻忕粨鏋滃瓨鍌ㄥ埌鎵弿鎻忚堪绗︿腑 + *sd = systable_beginscan(rbRel, RecyclebinDbidRelidIndexId, true, NULL, 1, skey); +} +/* + * 鍔熻兘锛氬湪鍥炴敹绔欎腑鍖归厤鑷姩鍒犻櫎鐨勫璞★紝鍒ゆ柇鏄惁婊¤冻鑷姩鍒犻櫎鏉′欢 + * 鍙傛暟鍒楄〃锛 + * rbRel锛氬洖鏀剁珯鍏崇郴瀵硅薄 + * rbTup锛氬洖鏀剁珯涓殑鍏冪粍 + * objId锛氳鍖归厤鐨勫璞$殑ID + */ +static bool TrFetchMatchAuto(Relation rbRel, HeapTuple rbTup, Oid objId) +{ + bool isNull = false; + Datum datumRcyTime = heap_getattr(rbTup, Anum_pg_recyclebin_rcyrecycletime, + RelationGetDescr(rbRel), &isNull); + + long secs; + int msecs; + TimestampDifference(isNull ? 0 : DatumGetTimestampTz(datumRcyTime), + GetCurrentTimestamp(), &secs, &msecs); + + return secs > u_sess->attr.attr_storage.recyclebin_retention_time || secs < 0; // 鍒ゆ柇鏄惁婊¤冻鑷姩鍒犻櫎鏉′欢 +} + +/* + * 鍔熻兘锛氭墽琛屽洖鏀剁珯涓嚜鍔ㄥ垹闄ょ殑瀵硅薄鐨勬案涔呭垹闄ゆ搷浣 + * 鍙傛暟鍒楄〃锛 + * id锛氳鍒犻櫎鐨勫璞$殑ID + */ +void TrPurgeAuto(int64 id) +{ + PurgeMsgReq *req = &RbMsg(id)->req; // 鑾峰彇璇锋眰娑堟伅 + PurgeMsgRes localRes; // 鐢ㄤ簬瀛樺偍鍒犻櫎鎿嶄綔鐨勭粨鏋 + bool eof = false; + + do { + eof = TrPurgeBatch(TrFetchBeginAuto, TrFetchMatchAuto, InvalidOid, req->authId, PURGE_BATCH, &localRes); // 鎵ц鎵归噺姘镐箙鍒犻櫎鎿嶄綔 + RbMsgSetStatistics(id, &localRes); // 鏇存柊鍒犻櫎缁熻淇℃伅 + } while (!eof); // 褰撴壒閲忓垹闄ゆ湭瀹屾垚鏃剁户缁墽琛 +} +/* + * 鍔熻兘锛氫氦鎹㈠洖鏀剁珯瀵硅薄鍜屽叧绯诲璞$殑鏂囦欢鑺傜偣淇℃伅 + * 鍙傛暟鍒楄〃锛 + * rbRel锛氬洖鏀剁珯鍏崇郴瀵硅薄 + * rbTup锛氬洖鏀剁珯涓殑瀵硅薄鍏冪粍 + * isPart锛氭槸鍚︽槸鍒嗗尯瀵硅薄 + */ +void TrSwapRelfilenode(Relation rbRel, HeapTuple rbTup, bool isPart) +{ + Relation relRel; // 鍏崇郴瀵硅薄鐨勫叧绯绘弿杩扮 + HeapTuple relTup; // 鍏崇郴瀵硅薄鍏冪粍 + HeapTuple newTup; // 鏂板叧绯诲璞″厓缁 + TrObjDesc desc; // 鍥炴敹绔欏璞$殑鎻忚堪淇℃伅 + int maxNattr = 0; // 鏈澶у睘鎬ф暟 + Datum *values = NULL; // 灞炴у兼暟缁 + bool *nulls = NULL; // NULL鍊兼暟缁 + bool *replaces = NULL; // 闇瑕佹浛鎹㈢殑灞炴ф暟缁 + NameData name; // 鍚嶇О鏁版嵁 + errno_t rc = EOK; // 閿欒鐮 + bool isNull = false; // 鏄惁涓篘ULL + int relfilenoIndex = 0; // relfileno灞炴х殑绱㈠紩 + int frozenxidIndex = 0; // frozenxid灞炴х殑绱㈠紩 + int frozenxid64Index = 0; // frozenxid64灞炴х殑绱㈠紩 + bool isPartition = false; // 鏄惁涓哄垎鍖哄璞 + // 璇诲彇鍥炴敹绔欏璞℃弿杩 + TrDescRead(&desc, rbTup); + // 鍒ゆ柇鏄惁涓哄垎鍖哄璞 + if (desc.type == RB_OBJ_PARTITION || (desc.type == RB_OBJ_INDEX && isPart)) { + isPartition = true; + } + // 鏍规嵁瀵硅薄绫诲瀷纭畾瑕佹搷浣滅殑绯荤粺琛 + if (isPartition) { + maxNattr = Max(Natts_pg_partition, Natts_pg_recyclebin); + relRel = heap_open(PartitionRelationId, RowExclusiveLock); + relTup = SearchSysCacheCopy1(PARTRELID, ObjectIdGetDatum(desc.relid)); + relfilenoIndex = Anum_pg_partition_relfilenode; + frozenxidIndex = Anum_pg_partition_relfrozenxid; + frozenxid64Index = Anum_pg_partition_relfrozenxid64; + } else { + maxNattr = Max(Natts_pg_class, Natts_pg_recyclebin); + relRel = heap_open(RelationRelationId, RowExclusiveLock); + relTup = SearchSysCacheCopy1(RELOID, ObjectIdGetDatum(desc.relid)); + relfilenoIndex = Anum_pg_class_relfilenode; + frozenxidIndex = Anum_pg_class_relfrozenxid; + frozenxid64Index = Anum_pg_class_relfrozenxid64; + } + + /* 1. Update pg_class or pg_partition */ + if (!HeapTupleIsValid(relTup)) { + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_TABLE), + errmsg("cache lookup failed for relation %u", desc.relid))); + } + // 涓烘洿鏂版瀯閫犲睘鎬у笺佹槸鍚︿负绌哄拰鏄惁鏇存柊鐨勬暟缁 + values = (Datum *)palloc0(sizeof(Datum) * maxNattr); + nulls = (bool *)palloc0(sizeof(bool) * maxNattr); + replaces = (bool *)palloc0(sizeof(bool) * maxNattr); + // 璁剧疆闇瑕佹洿鏂扮殑灞炴у拰瀵瑰簲鐨勬柊鍊 + replaces[relfilenoIndex - 1] = true; + values[relfilenoIndex - 1] = ObjectIdGetDatum(desc.relfilenode); + + replaces[frozenxidIndex - 1] = true; + values[frozenxidIndex - 1] = ShortTransactionIdGetDatum(desc.frozenxid); + + replaces[frozenxid64Index - 1] = true; + values[frozenxid64Index - 1] = TransactionIdGetDatum(desc.frozenxid64); + // 鏋勯犳柊鐨勫厓缁 + newTup = heap_modify_tuple(relTup, RelationGetDescr(relRel), values, nulls, replaces); + // 鎵ц鍫嗚〃鏇存柊鎿嶄綔 + simple_heap_update(relRel, &newTup->t_self, newTup); + // 鏇存柊绱㈠紩 + CatalogUpdateIndexes(relRel, newTup); + + heap_freetuple_ext(newTup); + + /* 2. Update pg_recyclebin */ + rc = memset_s(values, sizeof(Datum) * maxNattr, 0, sizeof(Datum) * maxNattr); + securec_check(rc, "\0", "\0"); + rc = memset_s(nulls, sizeof(bool) * maxNattr, false, sizeof(bool) * maxNattr); + securec_check(rc, "\0", "\0"); + rc = memset_s(replaces, sizeof(bool) * maxNattr, false, sizeof(bool) * maxNattr); + securec_check(rc, "\0", "\0"); + // 鐢熸垚鍥炴敹绔欏璞″悕 + (void)TrGenObjName(NameStr(name), RelationRelationId, desc.relid); + replaces[Anum_pg_recyclebin_rcyname - 1] = true; + values[Anum_pg_recyclebin_rcyname - 1] = NameGetDatum(&name); + + replaces[Anum_pg_recyclebin_rcyoriginname - 1] = true; + if (isPartition) { + values[Anum_pg_recyclebin_rcyoriginname - 1] = NameGetDatum(&desc.originname); + } else { + values[Anum_pg_recyclebin_rcyoriginname - 1] = NameGetDatum(&((Form_pg_class)GETSTRUCT(relTup))->relname); + } + + replaces[Anum_pg_recyclebin_rcyrecyclecsn - 1] = true; + values[Anum_pg_recyclebin_rcyrecyclecsn - 1] = Int64GetDatum(t_thrd.xact_cxt.ShmemVariableCache->nextCommitSeqNo); + + replaces[Anum_pg_recyclebin_rcyrecycletime - 1] = true; + values[Anum_pg_recyclebin_rcyrecycletime - 1] = TimestampTzGetDatum(GetCurrentTimestamp()); + + replaces[Anum_pg_recyclebin_rcyrelfilenode - 1] = true; + if (isPartition) { + values[Anum_pg_recyclebin_rcyrelfilenode - 1] = + ObjectIdGetDatum(((Form_pg_partition)GETSTRUCT(relTup))->relfilenode); + } else { + values[Anum_pg_recyclebin_rcyrelfilenode - 1] = + ObjectIdGetDatum(((Form_pg_class)GETSTRUCT(relTup))->relfilenode); + } + + replaces[Anum_pg_recyclebin_rcyfrozenxid - 1] = true; + if (isPartition) { + values[Anum_pg_recyclebin_rcyfrozenxid - 1] = + ShortTransactionIdGetDatum(((Form_pg_partition)GETSTRUCT(relTup))->relfrozenxid); + } else { + values[Anum_pg_recyclebin_rcyfrozenxid - 1] = + ShortTransactionIdGetDatum(((Form_pg_class)GETSTRUCT(relTup))->relfrozenxid); + } + + replaces[Anum_pg_recyclebin_rcyfrozenxid64 - 1] = true; + if (isPartition) { + // 濡傛灉鏄垎鍖哄璞★紝灏嗗垎鍖哄璞$殑relfrozenxid64璁剧疆涓哄洖鏀剁珯鍏冪粍鐨勫睘鎬у + values[Anum_pg_recyclebin_rcyfrozenxid64 - 1] = + ShortTransactionIdGetDatum(((Form_pg_partition)GETSTRUCT(relTup))->relfrozenxid); + } else { + // 濡傛灉鏄潪鍒嗗尯瀵硅薄锛屽皢鍏崇郴瀵硅薄鐨剅elfrozenxid64璁剧疆涓哄洖鏀剁珯鍏冪粍鐨勫睘鎬у + values[Anum_pg_recyclebin_rcyfrozenxid64 - 1] = + ShortTransactionIdGetDatum(((Form_pg_class)GETSTRUCT(relTup))->relfrozenxid); + } + + // 鏋勯犳柊鐨勫洖鏀剁珯鍏冪粍 + newTup = heap_modify_tuple(rbTup, RelationGetDescr(rbRel), values, nulls, replaces); + + // 鎵ц鍫嗚〃鏇存柊鎿嶄綔 + simple_heap_update(rbRel, &newTup->t_self, newTup); + + // 鏇存柊绱㈠紩 + CatalogUpdateIndexes(rbRel, newTup); + + heap_freetuple_ext(newTup); + + // 閲婃斁鍔ㄦ佸垎閰嶇殑鍐呭瓨 + pfree(values); + pfree(nulls); + pfree(replaces); + + // 閲婃斁鍏崇郴瀵硅薄鍏冪粍鐨勫唴瀛樺苟鍏抽棴鍏崇郴瀵硅薄鐨勮〃 + heap_freetuple_ext(relTup); + heap_close(relRel, RowExclusiveLock); + return; +} + +/* + * 鍔熻兘锛氶獙璇佸熀琛ㄤ笌鍥炴敹绔欏璞℃槸鍚﹀尮閰 + * 鍙傛暟鍒楄〃锛 + * baseDesc锛氬熀琛ㄥ璞$殑鎻忚堪淇℃伅 + */ +void TrBaseRelMatched(TrObjDesc *baseDesc) +{ + ObjectAddress obj = {RelationRelationId, baseDesc->relid}; // 鍒涘缓ObjectAddress缁撴瀯浣擄紝琛ㄧず鍩鸿〃瀵硅薄鐨勫湴鍧淇℃伅 + if (TrIsRefRbObject(&obj)) { // 鍒ゆ柇鍩鸿〃鏄惁鏈夊叧鑱旂殑鍥炴敹绔欏璞 + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_OBJECT), + errmsg("relation \"%s\" does not exist", baseDesc->originname))); // 鎶ラ敊锛屾彁绀哄熀琛ㄤ笉瀛樺湪 + } + + Relation rel = RelationIdGetRelation(baseDesc->relid); // 鏍规嵁鍩鸿〃鐨凮ID鑾峰彇鍩鸿〃鐨凴elation缁撴瀯浣 + Assert(RelationIsValid(rel)); // 鏂█锛岀‘淇濊幏鍙栫殑Relation缁撴瀯浣撴槸鏈夋晥鐨 + if (RelationGetCreatecsn(rel) != (CommitSeqNo)baseDesc->createcsn) { // 姣旇緝鍩鸿〃鐨勫垱寤篊SN涓庡洖鏀剁珯瀵硅薄鐨刢reatecsn鏄惁鍖归厤 + ereport(ERROR, + (errmsg("The recycle object \"%s\" and relation \"%s\" mismatched.", + baseDesc->name, RelationGetRelationName(rel)))); // 鎶ラ敊锛屾彁绀哄洖鏀剁珯瀵硅薄鍜屽熀琛ㄤ笉鍖归厤 + } + + if (RelationGetChangecsn(rel) > (CommitSeqNo)baseDesc->changecsn) { // 姣旇緝鍩鸿〃鐨勪慨鏀笴SN涓庡洖鏀剁珯瀵硅薄鐨刢hangecsn鏄惁鍖归厤 + ereport(ERROR, (errcode(ERRCODE_INTERNAL_ERROR), + errmsg("The table definition of \"%s\" has been changed.", + RelationGetRelationName(rel)))); // 鎶ラ敊锛屾彁绀哄熀琛ㄥ畾涔夊凡鏇存敼 + } + + RelationClose(rel); // 鍏抽棴鍩鸿〃鐨凴elation缁撴瀯浣 +} + +/* + * 鍔熻兘锛氭牴鎹洖鏀剁珯瀵硅薄鐨勫喕缁揦ID64鏉ヨ皟鏁翠紶鍏ョ殑frozenXID + * 鍙傛暟鍒楄〃锛 + * dbid锛氭暟鎹簱鐨凮ID + * frozenXID锛氫紶鍏ョ殑鍐荤粨XID鎸囬拡锛屽皢鏍规嵁鍥炴敹绔欏璞$殑XID鏉ヨ繘琛岃皟鏁 + */ +void TrAdjustFrozenXid64(Oid dbid, TransactionId *frozenXID) +{ + Relation rbRel; + SysScanDesc sd; + HeapTuple rbtup; + + if (!TcapFeatureAvail()) { // 妫鏌ユ槸鍚︽敮鎸乀CAP鍔熻兘 + return; + } + + rbRel = heap_open(RecyclebinRelationId, AccessShareLock); // 鎵撳紑鍥炴敹绔欏叧绯 + + sd = systable_beginscan(rbRel, InvalidOid, false, NULL, 0, NULL); // 寮濮嬫壂鎻忓洖鏀剁珯鍏崇郴琛 + while ((rbtup = systable_getnext(sd)) != NULL) { // 寰幆閬嶅巻鍥炴敹绔欏璞 + Form_pg_recyclebin rbForm = (Form_pg_recyclebin)GETSTRUCT(rbtup); // 鑾峰彇鍥炴敹绔欏璞$殑鍏冪粍缁撴瀯 + + TransactionId rcyfrozenxid64; + + if (rbForm->rcydbid != dbid || (rbForm->rcytype != RB_OBJ_TABLE && rbForm->rcytype != RB_OBJ_TOAST)) { + // 妫鏌ュ洖鏀剁珯瀵硅薄鏄惁涓庣粰瀹氱殑鏁版嵁搴揑D鍖归厤锛屽苟涓旂被鍨嬫槸琛ㄦ垨TOAST + continue; // 鑻ヤ笉鍖归厤锛岀户缁笅涓涓洖鏀剁珯瀵硅薄 + } + + rcyfrozenxid64 = TrRbGetRcyfrozenxid64(rbtup, rbRel); // 鑾峰彇鍥炴敹绔欏璞$殑鍐荤粨XID64 + Assert(TransactionIdIsNormal(rcyfrozenxid64)); // 鏂█锛氱‘淇濊幏鍙栫殑XID64鏄甯哥殑浜嬪姟ID + + if (TransactionIdPrecedes(rcyfrozenxid64, *frozenXID)) { + // 姣旇緝鍥炴敹绔欏璞$殑鍐荤粨XID64鍜屼紶鍏ョ殑鍐荤粨XID + *frozenXID = rcyfrozenxid64; // 鏇存柊浼犲叆鐨勫喕缁揦ID涓鸿緝灏忕殑XID64鍊 + } + } + + systable_endscan(sd); // 缁撴潫鎵弿 + heap_close(rbRel, AccessShareLock); // 鍏抽棴鍥炴敹绔欏叧绯 + + return; +} + +/* + * 鍔熻兘锛氭鏌ユ寚瀹氭暟鎹簱鏄惁涓虹┖鐨勫洖鏀剁珯 + * 鍙傛暟鍒楄〃锛 + * dbid锛氭暟鎹簱鐨凮ID + */ +bool TrRbIsEmptyDb(Oid dbid) +{ + Relation rbRel; + SysScanDesc sd; + HeapTuple tup; + ScanKeyData skey[1]; + + ScanKeyInit(&skey[0], Anum_pg_recyclebin_rcydbid, BTEqualStrategyNumber, F_OIDEQ, + ObjectIdGetDatum(dbid)); + + rbRel = heap_open(RecyclebinRelationId, AccessShareLock); // 鎵撳紑鍥炴敹绔欏叧绯 + + sd = systable_beginscan(rbRel, RecyclebinDbidRelidIndexId, true, NULL, 1, skey); // 寮濮嬫壂鎻忓洖鏀剁珯鍏崇郴琛 + tup = systable_getnext(sd); // 鑾峰彇鎵弿缁撴灉鐨勪笅涓涓厓缁 + systable_endscan(sd); // 缁撴潫鎵弿 + heap_close(rbRel, AccessShareLock); // 鍏抽棴鍥炴敹绔欏叧绯 + + return tup == NULL; // 鑻ュ厓缁勪负绌猴紝杩斿洖true锛屽惁鍒欒繑鍥瀎alse +} + + +/* + * 鍔熻兘锛氭鏌ユ寚瀹氳〃绌洪棿鏄惁涓虹┖鐨勫洖鏀剁珯 + * 鍙傛暟鍒楄〃锛 + * spcId锛氳〃绌洪棿鐨凮ID + */ +bool TrRbIsEmptySpc(Oid spcId) +{ + Relation rbRel; + SysScanDesc sd; + ScanKeyData skey[1]; + HeapTuple tup; + + rbRel = heap_open(RecyclebinRelationId, AccessShareLock); // 鎵撳紑鍥炴敹绔欏叧绯 + + ScanKeyInit(&skey[0], Anum_pg_recyclebin_rcytablespace, BTEqualStrategyNumber, + F_OIDEQ, ObjectIdGetDatum(spcId)); // 鍒涘缓鎵弿閿紝鍖归厤鎸囧畾琛ㄧ┖闂寸殑鍥炴敹绔欒褰 + + sd = systable_beginscan(rbRel, RecyclebinDbidSpcidRcycsnIndexId, true, NULL, 1, skey); // 寮濮嬫壂鎻忓洖鏀剁珯鍏崇郴琛 + tup = systable_getnext(sd); // 鑾峰彇鎵弿缁撴灉鐨勪笅涓涓厓缁 + systable_endscan(sd); // 缁撴潫鎵弿 + heap_close(rbRel, AccessShareLock); // 鍏抽棴鍥炴敹绔欏叧绯 + + return tup == NULL; // 鑻ュ厓缁勪负绌猴紝杩斿洖true锛屽惁鍒欒繑鍥瀎alse +} + + +/* + * 鍔熻兘锛氭鏌ユ寚瀹氭ā寮忔槸鍚︿负绌虹殑鍥炴敹绔 + * 鍙傛暟鍒楄〃锛 + * nspId锛氭ā寮忕殑OID + */ +bool TrRbIsEmptySchema(Oid nspId) +{ + Relation rbRel; + SysScanDesc sd; + ScanKeyData skey[2]; + HeapTuple tup; + + rbRel = heap_open(RecyclebinRelationId, AccessShareLock); // 鎵撳紑鍥炴敹绔欏叧绯 + + ScanKeyInit(&skey[0], Anum_pg_recyclebin_rcynamespace, BTEqualStrategyNumber, + F_OIDEQ, ObjectIdGetDatum(nspId)); // 鍒涘缓鎵弿閿紝鍖归厤鎸囧畾妯″紡鐨勫洖鏀剁珯璁板綍 + ScanKeyInit(&skey[1], Anum_pg_recyclebin_rcydbid, BTEqualStrategyNumber, + F_OIDEQ, ObjectIdGetDatum(u_sess->proc_cxt.MyDatabaseId)); // 鍒涘缓鎵弿閿紝鍖归厤褰撳墠鏁版嵁搴揑D + + sd = systable_beginscan(rbRel, RecyclebinDbidNspOrinameIndexId, true, NULL, 2, skey); // 寮濮嬫壂鎻忓洖鏀剁珯鍏崇郴琛 + tup = systable_getnext(sd); // 鑾峰彇鎵弿缁撴灉鐨勪笅涓涓厓缁 + + systable_endscan(sd); // 缁撴潫鎵弿 + heap_close(rbRel, AccessShareLock); // 鍏抽棴鍥炴敹绔欏叧绯 + + return tup == NULL; // 鑻ュ厓缁勪负绌猴紝杩斿洖true锛屽惁鍒欒繑鍥瀎alse +} + + +/* + * 鍔熻兘锛氭鏌ユ寚瀹氱敤鎴锋槸鍚︿负绌虹殑鍥炴敹绔 + * 鍙傛暟鍒楄〃锛 + * roleId锛氱敤鎴风殑OID + */ +bool TrRbIsEmptyUser(Oid roleId) +{ + Relation rbRel; + SysScanDesc sd; + HeapTuple tup; + bool found = false; + + rbRel = heap_open(RecyclebinRelationId, AccessShareLock); // 鎵撳紑鍥炴敹绔欏叧绯 + + sd = systable_beginscan(rbRel, InvalidOid, false, NULL, 0, NULL); // 寮濮嬫壂鎻忓洖鏀剁珯鍏崇郴琛 + + while ((tup = systable_getnext(sd)) != NULL) { // 寰幆鑾峰彇鎵弿缁撴灉鐨勪笅涓涓厓缁 + Form_pg_recyclebin rbForm = (Form_pg_recyclebin)GETSTRUCT(tup); + if ((TrObjType)rbForm->rcytype != RB_OBJ_TABLE || rbForm->rcyowner != roleId) { + continue; + } + + found = true; + break; + } + + systable_endscan(sd); // 缁撴潫鎵弿 + heap_close(rbRel, AccessShareLock); // 鍏抽棴鍥炴敹绔欏叧绯 + + return !found; // 鑻ユ壘涓嶅埌涓庣敤鎴风浉鍏崇殑鍥炴敹绔欏璞★紝杩斿洖true锛屽惁鍒欒繑鍥瀎alse +} + + +/* + * 鍔熻兘锛氭鏌ョ粰瀹歄ID鏄惁瀛樺湪浜庢寚瀹氱殑OID鍒楄〃涓 + * 鍙傛暟鍒楄〃锛 + * lOid锛歄ID鍒楄〃 + * oid锛氳妫鏌ョ殑OID + */ +static bool TrOidExists(const List *lOid, Oid oid) +{ + ListCell *cell = NULL; + if (lOid == NULL) { // 妫鏌ID鍒楄〃鏄惁涓虹┖ + return false; // 濡傛灉涓虹┖锛岃繑鍥瀎alse + } + + foreach (cell, lOid) { // 閬嶅巻OID鍒楄〃涓殑姣忎釜鍏冪礌 + if (oid == (*(Oid *)lfirst(cell))) { // 妫鏌ュ綋鍓嶅厓绱犳槸鍚︿笌鎸囧畾鐨凮ID鐩哥瓑 + return true; // 濡傛灉鐩哥瓑锛岃繑鍥瀟rue + } + } + return false; // 濡傛灉娌℃湁鎵惧埌鍖归厤鐨凮ID锛岃繑鍥瀎alse +} + + +/* + * 鍔熻兘锛氳幏鍙栧寘鍚洖鏀剁珯涓瓨鍦ㄧ殑鏁版嵁搴撳悕绉扮殑鍒楄〃 + */ +List *TrGetDbListRcy(void) +{ + Relation rbRel; + SysScanDesc sd; + HeapTuple tup; + + List *lName = NIL; // 鐢ㄤ簬瀛樺偍鏁版嵁搴撳悕绉扮殑List + List *lOid = NIL; // 鐢ㄤ簬瀛樺偍鏁版嵁搴揙ID鐨凩ist + char *dbname = NULL; // 鐢ㄤ簬瀛樺偍鏁版嵁搴撳悕绉扮殑涓存椂鍙橀噺 + + rbRel = heap_open(RecyclebinRelationId, AccessShareLock); // 鎵撳紑鍥炴敹绔欒〃 + + sd = systable_beginscan(rbRel, InvalidOid, false, NULL, 0, NULL); // 寮濮嬬郴缁熻〃鎵弿 + + while ((tup = systable_getnext(sd)) != NULL) { // 閬嶅巻绯荤粺琛ㄦ壂鎻忕粨鏋 + Form_pg_recyclebin rbForm = (Form_pg_recyclebin)GETSTRUCT(tup); + + if (TrOidExists(lOid, rbForm->rcydbid)) { // 妫鏌ュ綋鍓嶆暟鎹簱OID鏄惁宸插瓨鍦ㄤ簬lOid鍒楄〃涓 + continue; // 濡傛灉瀛樺湪锛岀户缁笅涓娆″惊鐜 + } + + Oid *oid = (Oid *)palloc0(sizeof(Oid)); // 涓烘暟鎹簱OID鍒嗛厤鍐呭瓨 + *oid = rbForm->rcydbid; // 灏嗗綋鍓嶆暟鎹簱OID璧嬪肩粰oid + lOid = lappend(lOid, oid); // 灏唎id娣诲姞鍒發Oid鍒楄〃涓 + + dbname = get_database_name(rbForm->rcydbid); // 鑾峰彇褰撳墠鏁版嵁搴揙ID瀵瑰簲鐨勬暟鎹簱鍚嶇О + if (dbname == NULL) { // 妫鏌ユ暟鎹簱鍚嶇О鏄惁涓虹┖ + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_DATABASE), + errmsg("database \"%u\" does not exist", rbForm->rcydbid))); + } + lName = lappend(lName, dbname); // 灏嗘暟鎹簱鍚嶇О娣诲姞鍒發Name鍒楄〃涓 + } + + list_free_deep(lOid); // 閲婃斁lOid鍒楄〃涓殑鍐呭瓨 + + systable_endscan(sd); // 缁撴潫绯荤粺琛ㄦ壂鎻 + heap_close(rbRel, AccessShareLock); // 鍏抽棴鍥炴敹绔欒〃 + + return lName; // 杩斿洖鍖呭惈鏁版嵁搴撳悕绉扮殑List +} + + +/* + * 鍔熻兘锛氳幏鍙栧洖鏀剁珯涓寚瀹氳〃绌洪棿涓瓨鍦ㄧ殑鏁版嵁搴撳悕绉扮殑鍒楄〃 + * 鍙傛暟鍒楄〃锛 + * spcId锛氳〃绌洪棿OID + */ +List *TrGetDbListSpc(Oid spcId) +{ + List *lName = NIL; // 鐢ㄤ簬瀛樺偍鏁版嵁搴撳悕绉扮殑List + List *lOid = NIL; // 鐢ㄤ簬瀛樺偍鏁版嵁搴揙ID鐨凩ist + char *dbname = NULL; // 鐢ㄤ簬瀛樺偍鏁版嵁搴撳悕绉扮殑涓存椂鍙橀噺 + + Relation rbRel; + SysScanDesc sd; + ScanKeyData skey[1]; + HeapTuple tup; + + rbRel = heap_open(RecyclebinRelationId, AccessShareLock); // 鎵撳紑鍥炴敹绔欒〃 + + ScanKeyInit(&skey[0], Anum_pg_recyclebin_rcytablespace, BTEqualStrategyNumber, + F_OIDEQ, ObjectIdGetDatum(spcId)); // 鍒濆鍖栨壂鎻忛敭锛屾牴鎹〃绌洪棿OID绛涢 + + sd = systable_beginscan(rbRel, RecyclebinDbidSpcidRcycsnIndexId, true, NULL, 1, skey); // 寮濮嬬郴缁熻〃鎵弿 + + while ((tup = systable_getnext(sd)) != NULL) { // 閬嶅巻绯荤粺琛ㄦ壂鎻忕粨鏋 + Form_pg_recyclebin rbForm = (Form_pg_recyclebin)GETSTRUCT(tup); + + if (TrOidExists(lOid, rbForm->rcydbid)) { // 妫鏌ュ綋鍓嶆暟鎹簱OID鏄惁宸插瓨鍦ㄤ簬lOid鍒楄〃涓 + continue; // 濡傛灉瀛樺湪锛岀户缁笅涓娆″惊鐜 + } + + Oid *oid = (Oid *)palloc0(sizeof(Oid)); // 涓烘暟鎹簱OID鍒嗛厤鍐呭瓨 + *oid = rbForm->rcydbid; // 灏嗗綋鍓嶆暟鎹簱OID璧嬪肩粰oid + lOid = lappend(lOid, oid); // 灏唎id娣诲姞鍒發Oid鍒楄〃涓 + + dbname = get_database_name(rbForm->rcydbid); // 鑾峰彇褰撳墠鏁版嵁搴揙ID瀵瑰簲鐨勬暟鎹簱鍚嶇О + if (dbname == NULL) { // 妫鏌ユ暟鎹簱鍚嶇О鏄惁涓虹┖ + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_DATABASE), + errmsg("database \"%u\" does not exist", rbForm->rcydbid))); + } + lName = lappend(lName, dbname); // 灏嗘暟鎹簱鍚嶇О娣诲姞鍒發Name鍒楄〃涓 + } + + list_free_deep(lOid); // 閲婃斁lOid鍒楄〃涓殑鍐呭瓨 + + systable_endscan(sd); // 缁撴潫绯荤粺琛ㄦ壂鎻 + heap_close(rbRel, AccessShareLock); // 鍏抽棴鍥炴敹绔欒〃 + + return lName; // 杩斿洖鍖呭惈鏁版嵁搴撳悕绉扮殑List +} + + +/* + * 鍔熻兘锛氳幏鍙栧洖鏀剁珯涓寚瀹氭ā寮忎腑瀛樺湪鐨勬暟鎹簱鍚嶇О鐨勫垪琛 + * 鍙傛暟鍒楄〃锛 + * nspId锛氭ā寮廜ID + */ +List *TrGetDbListSchema(Oid nspId) +{ + Relation rbRel; + SysScanDesc sd; + ScanKeyData skey[1]; + HeapTuple tup; + + List *lName = NIL; // 鐢ㄤ簬瀛樺偍鏁版嵁搴撳悕绉扮殑List + List *lOid = NIL; // 鐢ㄤ簬瀛樺偍鏁版嵁搴揙ID鐨凩ist + char *dbname = NULL; // 鐢ㄤ簬瀛樺偍鏁版嵁搴撳悕绉扮殑涓存椂鍙橀噺 + + rbRel = heap_open(RecyclebinRelationId, AccessShareLock); // 鎵撳紑鍥炴敹绔欒〃 + + ScanKeyInit(&skey[0], Anum_pg_recyclebin_rcynamespace, BTEqualStrategyNumber, + F_OIDEQ, ObjectIdGetDatum(nspId)); // 鍒濆鍖栨壂鎻忛敭锛屾牴鎹ā寮廜ID绛涢 + + sd = systable_beginscan(rbRel, RecyclebinDbidNspOrinameIndexId, true, NULL, 1, skey); // 寮濮嬬郴缁熻〃鎵弿 + + while ((tup = systable_getnext(sd)) != NULL) { // 閬嶅巻绯荤粺琛ㄦ壂鎻忕粨鏋 + Form_pg_recyclebin rbForm = (Form_pg_recyclebin)GETSTRUCT(tup); + + if (TrOidExists(lOid, rbForm->rcydbid)) { // 妫鏌ュ綋鍓嶆暟鎹簱OID鏄惁宸插瓨鍦ㄤ簬lOid鍒楄〃涓 + continue; // 濡傛灉瀛樺湪锛岀户缁笅涓娆″惊鐜 + } + + Oid *oid = (Oid *)palloc0(sizeof(Oid)); // 涓烘暟鎹簱OID鍒嗛厤鍐呭瓨 + *oid = rbForm->rcydbid; // 灏嗗綋鍓嶆暟鎹簱OID璧嬪肩粰oid + lOid = lappend(lOid, oid); // 灏唎id娣诲姞鍒發Oid鍒楄〃涓 + + dbname = get_database_name(rbForm->rcydbid); // 鑾峰彇褰撳墠鏁版嵁搴揙ID瀵瑰簲鐨勬暟鎹簱鍚嶇О + if (dbname == NULL) { // 妫鏌ユ暟鎹簱鍚嶇О鏄惁涓虹┖ + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_DATABASE), + errmsg("database \"%u\" does not exist", rbForm->rcydbid))); + } + lName = lappend(lName, dbname); // 灏嗘暟鎹簱鍚嶇О娣诲姞鍒發Name鍒楄〃涓 + } + + list_free_deep(lOid); // 閲婃斁lOid鍒楄〃涓殑鍐呭瓨 + + systable_endscan(sd); // 缁撴潫绯荤粺琛ㄦ壂鎻 + heap_close(rbRel, AccessShareLock); // 鍏抽棴鍥炴敹绔欒〃 + + return lName; // 杩斿洖鍖呭惈鏁版嵁搴撳悕绉扮殑List +} + + +/* + * 鍔熻兘锛氳幏鍙栧洖鏀剁珯涓寚瀹氳鑹叉嫢鏈夌殑鏁版嵁搴撳悕绉扮殑鍒楄〃 + * 鍙傛暟鍒楄〃锛 + * roleId锛氳鑹睴ID + */ +List *TrGetDbListUser(Oid roleId) +{ + Relation rbRel; + SysScanDesc sd; + HeapTuple tup; + + List *lName = NIL; // 鐢ㄤ簬瀛樺偍鏁版嵁搴撳悕绉扮殑List + List *lOid = NIL; // 鐢ㄤ簬瀛樺偍鏁版嵁搴揙ID鐨凩ist + char *dbname = NULL; // 鐢ㄤ簬瀛樺偍鏁版嵁搴撳悕绉扮殑涓存椂鍙橀噺 + + rbRel = heap_open(RecyclebinRelationId, AccessShareLock); // 鎵撳紑鍥炴敹绔欒〃 + + sd = systable_beginscan(rbRel, InvalidOid, false, NULL, 0, NULL); // 寮濮嬬郴缁熻〃鎵弿 + + while ((tup = systable_getnext(sd)) != NULL) { // 閬嶅巻绯荤粺琛ㄦ壂鎻忕粨鏋 + Form_pg_recyclebin rbForm = (Form_pg_recyclebin)GETSTRUCT(tup); + + // 妫鏌ュ綋鍓嶈褰曟槸鍚︿负琛ㄥ璞′笖鎷ユ湁鎸囧畾瑙掕壊 + if ((TrObjType)rbForm->rcytype != RB_OBJ_TABLE || rbForm->rcyowner != roleId) { + continue; // 濡傛灉涓嶆弧瓒虫潯浠讹紝缁х画涓嬩竴娆″惊鐜 + } + + if (TrOidExists(lOid, rbForm->rcydbid)) { // 妫鏌ュ綋鍓嶆暟鎹簱OID鏄惁宸插瓨鍦ㄤ簬lOid鍒楄〃涓 + continue; // 濡傛灉瀛樺湪锛岀户缁笅涓娆″惊鐜 + } + + Oid *oid = (Oid *)palloc0(sizeof(Oid)); // 涓烘暟鎹簱OID鍒嗛厤鍐呭瓨 + *oid = rbForm->rcydbid; // 灏嗗綋鍓嶆暟鎹簱OID璧嬪肩粰oid + lOid = lappend(lOid, oid); // 灏唎id娣诲姞鍒發Oid鍒楄〃涓 + + dbname = get_database_name(rbForm->rcydbid); // 鑾峰彇褰撳墠鏁版嵁搴揙ID瀵瑰簲鐨勬暟鎹簱鍚嶇О + if (dbname == NULL) { // 妫鏌ユ暟鎹簱鍚嶇О鏄惁涓虹┖ + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_DATABASE), + errmsg("database \"%u\" does not exist", rbForm->rcydbid))); + } + lName = lappend(lName, dbname); // 灏嗘暟鎹簱鍚嶇О娣诲姞鍒發Name鍒楄〃涓 + } + + list_free_deep(lOid); // 閲婃斁lOid鍒楄〃涓殑鍐呭瓨 + + systable_endscan(sd); // 缁撴潫绯荤粺琛ㄦ壂鎻 + heap_close(rbRel, AccessShareLock); // 鍏抽棴鍥炴敹绔欒〃 + + return lName; // 杩斿洖鍖呭惈鏁版嵁搴撳悕绉扮殑List +} + + +/* + * TrGetDatabaseList + * Return a list of all databases found in pg_database. + */ +/* + * 鍔熻兘锛氳幏鍙栭潪妯℃澘鏁版嵁搴撶殑鍚嶇О鍒楄〃 + */ +List *TrGetDbListAuto(void) +{ + List* dblist = NIL; // 鐢ㄤ簬瀛樺偍鏁版嵁搴撳悕绉扮殑List + Relation rel; + SysScanDesc sd; + HeapTuple tup; + + rel = heap_open(DatabaseRelationId, AccessShareLock); // 鎵撳紑鏁版嵁搴撳叧绯昏〃 + + sd = systable_beginscan(rel, InvalidOid, false, NULL, 0, NULL); // 寮濮嬬郴缁熻〃鎵弿 + + while ((tup = systable_getnext(sd)) != NULL) { // 閬嶅巻绯荤粺琛ㄦ壂鎻忕粨鏋 + Form_pg_database pgdatabase = (Form_pg_database)GETSTRUCT(tup); + + // 妫鏌ユ暟鎹簱鍚嶇О鏄惁涓 "template0" 鎴 "template1" + if (strcmp(NameStr(pgdatabase->datname), "template0") == 0 || + strcmp(NameStr(pgdatabase->datname), "template1") == 0) { + continue; // 濡傛灉鏄ā鏉挎暟鎹簱锛岀户缁笅涓娆″惊鐜 + } + + dblist = lappend(dblist, pstrdup(NameStr(pgdatabase->datname))); // 灏嗛潪妯℃澘鏁版嵁搴撳悕绉版坊鍔犲埌dblist鍒楄〃涓 + } + + systable_endscan(sd); // 缁撴潫绯荤粺琛ㄦ壂鎻 + heap_close(rel, AccessShareLock); // 鍏抽棴鏁版嵁搴撳叧绯昏〃 + + return dblist; // 杩斿洖鍖呭惈闈炴ā鏉挎暟鎹簱鍚嶇О鐨凩ist +} + +/* + * 鍔熻兘锛氭鏌ョ粰瀹氬璞℃槸鍚﹀湪鍥炴敹绔欎腑 + * 鍙傛暟鍒楄〃锛 + * obj锛氳妫鏌ョ殑瀵硅薄鐨勫湴鍧 + */ +static bool TrObjInRecyclebin(const ObjectAddress *obj) +{ + Relation rbRel; + SysScanDesc sd; + HeapTuple tup; + ScanKeyData skey[2]; + bool found = false; + + // 妫鏌ュ璞℃槸鍚︽槸鍏崇郴绫 + if (getObjectClass(obj) != OCLASS_CLASS) { + return false; + } + + // 璁剧疆鎵弿閿硷紝鐢ㄤ簬妫绱笌鏁版嵁搴揑D鍜屽叧绯籌D鍖归厤鐨勫洖鏀剁珯鏉$洰 + ScanKeyInit(&skey[0], Anum_pg_recyclebin_rcydbid, BTEqualStrategyNumber, F_OIDEQ, + ObjectIdGetDatum(u_sess->proc_cxt.MyDatabaseId)); + ScanKeyInit(&skey[1], Anum_pg_recyclebin_rcyrelid, BTEqualStrategyNumber, F_OIDEQ, + ObjectIdGetDatum(obj->objectId)); + + rbRel = heap_open(RecyclebinRelationId, AccessShareLock); // 鎵撳紑鍥炴敹绔欏叧绯昏〃 + sd = systable_beginscan(rbRel, RecyclebinDbidRelidIndexId, true, NULL, 2, skey); // 寮濮嬬郴缁熻〃鎵弿 + + // 閬嶅巻鎵弿缁撴灉锛屾鏌ユ槸鍚︽湁涓庢搷浣滀负鍒犻櫎鐨勫洖鏀剁珯鏉$洰鍖归厤 + while ((tup = systable_getnext(sd)) != NULL) { + Form_pg_recyclebin rbForm = (Form_pg_recyclebin)GETSTRUCT(tup); + if ((TrObjType)rbForm->rcyoperation == 'd') { + found = true; + break; + } + } + systable_endscan(sd); // 缁撴潫绯荤粺琛ㄦ壂鎻 + heap_close(rbRel, AccessShareLock); // 鍏抽棴鍥炴敹绔欏叧绯昏〃 + + return found; // 杩斿洖鏄惁鎵惧埌涓庢搷浣滀负鍒犻櫎鐨勫洖鏀剁珯鏉$洰鍖归厤鐨勬爣蹇 +} +/* + * May this object be a recyclebin object? + * true: with "BIN$" prefix, or not a Relation\Type\Trigger\Constraint\Rule + * false: without "BIN$" prefix, or not exists + */ +/* + * 鍔熻兘锛氭鏌ュ璞℃槸鍚﹀彲鑳芥槸鍥炴敹绔欏璞 + * 鍙傛暟鍒楄〃锛 + * classid锛氬璞℃墍灞炵殑绫诲埆ID + * objid锛氬璞$殑ID + * objname锛氬璞$殑鍚嶇О锛堝彲閫夛級 + */ +static bool TrMaybeRbObject(Oid classid, Oid objid, const char *objname = NULL) +{ + HeapTuple tup; + + /* 娉ㄦ剰锛氬湪 RbDrop 鏃讹紝鎴戜滑淇濈暀瑙勫垯婧愬悕绉般*/ + if (classid != RewriteRelationId && objname) { + return strncmp(objname, "BIN$", 4) == 0; // 濡傛灉瀵硅薄鍚嶇О浠 "BIN$" 寮澶达紝杩斿洖 true + } + + switch (classid) { + case RelationRelationId: + tup = SearchSysCache1(RELOID, ObjectIdGetDatum(objid)); // 鍦ㄧ郴缁熺紦瀛樹腑鏌ユ壘鍏崇郴绫诲璞 + if (tup != NULL) { + objname = NameStr(((Form_pg_class)GETSTRUCT(tup))->relname); // 鑾峰彇鍏崇郴绫诲璞$殑鍚嶇О + ReleaseSysCache(tup); + } + break; + case TypeRelationId: + tup = SearchSysCache1(TYPEOID, ObjectIdGetDatum(objid)); // 鍦ㄧ郴缁熺紦瀛樹腑鏌ユ壘绫诲瀷瀵硅薄 + if (tup != NULL) { + objname = NameStr(((Form_pg_type)GETSTRUCT(tup))->typname); // 鑾峰彇绫诲瀷瀵硅薄鐨勫悕绉 + ReleaseSysCache(tup); + } + break; + case TriggerRelationId: { + Relation relTrig; + ScanKeyData skey[1]; + SysScanDesc sd; + + relTrig = heap_open(TriggerRelationId, AccessShareLock); // 鎵撳紑瑙﹀彂鍣ㄥ叧绯昏〃 + ScanKeyInit(&skey[0], ObjectIdAttributeNumber, BTEqualStrategyNumber, + F_OIDEQ, ObjectIdGetDatum(objid)); + sd = systable_beginscan(relTrig, TriggerOidIndexId, true, NULL, 1, skey); // 寮濮嬬郴缁熻〃鎵弿 + if ((tup = systable_getnext(sd)) != NULL) { + objname = NameStr(((Form_pg_trigger)GETSTRUCT(tup))->tgname); // 鑾峰彇瑙﹀彂鍣ㄥ璞$殑鍚嶇О + } + systable_endscan(sd); // 缁撴潫绯荤粺琛ㄦ壂鎻 + heap_close(relTrig, AccessShareLock); // 鍏抽棴瑙﹀彂鍣ㄥ叧绯昏〃 + break; + } + case ConstraintRelationId: + tup = SearchSysCache1(CONSTROID, ObjectIdGetDatum(objid)); // 鍦ㄧ郴缁熺紦瀛樹腑鏌ユ壘绾︽潫瀵硅薄 + if (tup != NULL) { + objname = NameStr(((Form_pg_constraint)GETSTRUCT(tup))->conname); // 鑾峰彇绾︽潫瀵硅薄鐨勫悕绉 + ReleaseSysCache(tup); + } + break; + case NamespaceRelationId: + /* 灏嗗懡鍚嶇┖闂磋涓洪潪鍥炴敹绔欏璞° */ + return false; + default: + /* 鍙兘鏄洖鏀剁珯瀵硅薄銆 */ + return true; + } + + if (objname) { + return strncmp(objname, "BIN$", 4) == 0; // 濡傛灉瀵硅薄鍚嶇О浠 "BIN$" 寮澶达紝杩斿洖 true + } + + return false; // 榛樿鎯呭喌涓嬶紝杩斿洖 false +} + + +/* + * 鍔熻兘锛氶掑綊鍦版鏌ュ璞″強鍏跺紩鐢ㄥ璞℃槸鍚﹀湪鍥炴敹绔欎腑 + * 鍙傛暟鍒楄〃锛 + * depRel锛氬璞℃墍鍦ㄥ叧绯 + * obj锛氬緟妫鏌ョ殑瀵硅薄鍦板潃 + * objSet锛氬璞″湴鍧闆嗗悎 + */ +static bool TrIsRefRbObjectImpl(Relation depRel, const ObjectAddress *obj, ObjectAddresses *objSet) +{ + int startIdx; + + if (TrObjInRecyclebin(obj)) { // 妫鏌ュ璞℃槸鍚﹀湪鍥炴敹绔欎腑 + return true; + } + + startIdx = objSet->numrefs; // 璁板綍瀵硅薄鍦板潃闆嗗悎涓殑寮曠敤瀵硅薄鏁伴噺 + + if (!TrMaybeRbObject(obj->classId, obj->objectId)) { // 妫鏌ュ璞℃槸鍚﹀彲鑳芥槸鍥炴敹绔欏璞 + return false; + } + + TrFindAllRefObjs(depRel, obj, objSet, true); // 鏌ユ壘瀵硅薄鐨勬墍鏈夊紩鐢ㄥ璞 + TrFindAllInternalObjs(depRel, obj, objSet, true); // 鏌ユ壘瀵硅薄鐨勬墍鏈夊唴閮ㄥ璞 + + for (int i = startIdx; i < objSet->numrefs; i++) { // 閬嶅巻鏂版坊鍔犵殑寮曠敤瀵硅薄 + if (TrIsRefRbObjectImpl(depRel, &objSet->refs[i], objSet)) { + return true; // 濡傛灉寮曠敤瀵硅薄鎴栧叾寮曠敤瀵硅薄鍦ㄥ洖鏀剁珯涓紝杩斿洖 true + } + } + + return false; // 榛樿鎯呭喌涓嬶紝杩斿洖 false +} + + +/* object is a rb object, or reference to a rb object. */ +/* + * 鍔熻兘锛氭鏌ュ璞″強鍏跺紩鐢ㄥ璞℃槸鍚﹀湪鍥炴敹绔欎腑锛堣皟鐢ㄥ疄鐜板嚱鏁帮級 + * 鍙傛暟鍒楄〃锛 + * obj锛氬緟妫鏌ョ殑瀵硅薄鍦板潃 + * depRel锛氬璞℃墍鍦ㄥ叧绯 + */ +static bool TrIsRefRbObject(const ObjectAddress *obj, Relation depRel) +{ + ObjectAddresses *objSet = new_object_addresses(); // 鍒涘缓瀵硅薄鍦板潃闆嗗悎 + bool relArgNull = depRel == NULL; // 妫鏌ヤ紶鍏ョ殑鍏崇郴瀵硅薄鏄惁涓虹┖ + bool result = false; + + if (relArgNull) { + depRel = heap_open(DependRelationId, AccessShareLock); // 鑻ヤ负绌猴紝鎵撳紑 DependRelation 琛 + } + + /* Note: we not care obj->deptype here. */ + add_object_address_ext1(obj, objSet); // 灏嗗緟妫鏌ョ殑瀵硅薄鍦板潃娣诲姞鍒板璞″湴鍧闆嗗悎涓 + + result = TrIsRefRbObjectImpl(depRel, obj, objSet); // 璋冪敤瀹炵幇鍑芥暟妫鏌ュ璞″強鍏跺紩鐢ㄥ璞℃槸鍚﹀湪鍥炴敹绔欎腑 + + free_object_addresses(objSet); // 閲婃斁瀵硅薄鍦板潃闆嗗悎鐨勫唴瀛 + + if (relArgNull) { + heap_close(depRel, AccessShareLock); // 鑻ヤ箣鍓嶆墦寮浜嗗叧绯昏〃锛屽垯鍏抽棴瀹 + } + + return result; // 杩斿洖妫鏌ョ粨鏋滐紝瀵硅薄鎴栧叾寮曠敤瀵硅薄鏄惁鍦ㄥ洖鏀剁珯涓 +} + + +/* + * 鍔熻兘锛氭鏌ュ璞″強鍏跺紩鐢ㄥ璞℃槸鍚﹀湪鍥炴敹绔欎腑锛堟墿灞曞嚱鏁帮級 + * 鍙傛暟鍒楄〃锛 + * classid锛氬璞$殑绫诲埆鏍囪瘑 + * objid锛氬璞$殑鏍囪瘑 + * objname锛氬璞$殑鍚嶇О + */ +bool TrIsRefRbObjectEx(Oid classid, Oid objid, const char *objname) +{ + if (!TcapFeatureAvail()) { + return false; // 濡傛灉 Tcap 鍔熻兘涓嶅彲鐢紝鍒欒繑鍥 false + } + + /* Note: we preserve rule origin name when RbDrop. */ + if (TrRbIsEmptyDb(u_sess->proc_cxt.MyDatabaseId)) { + return false; // 濡傛灉褰撳墠鏁版嵁搴撲负绌猴紝鍒欒繑鍥 false + } + + if (classid != RewriteRelationId && objname && strncmp(objname, "BIN$", 4) != 0) { + return false; // 濡傛灉瀵硅薄涓嶆槸 RewriteRelation锛屼笖瀵硅薄鍚嶇О涓嶄互 "BIN$" 寮澶达紝鍒欒繑鍥 false + } + + ObjectAddress obj = {classid, objid}; // 鍒涘缓瀵硅薄鍦板潃缁撴瀯 + + return TrIsRefRbObject(&obj); // 璋冪敤 TrIsRefRbObject 鍑芥暟妫鏌ュ璞″強鍏跺紩鐢ㄥ璞℃槸鍚﹀湪鍥炴敹绔欎腑 +} + + +/* + * 鍔熻兘锛氱姝㈣闂笌鍥炴敹绔欏璞$浉鍏崇殑渚濊禆鍏崇郴 + * 鍙傛暟锛 + * depRel锛氫緷璧栧叧绯昏〃鐨勫叧绯 + * depender锛氫緷璧栧璞″湴鍧 + * referenced锛氳渚濊禆瀵硅薄鍦板潃鐨勬暟缁 + * nreferenced锛氳渚濊禆瀵硅薄鍦板潃鏁扮粍鐨勯暱搴 + */ +void TrForbidAccessRbDependencies(Relation depRel, const ObjectAddress *depender, + const ObjectAddress *referenced, int nreferenced) +{ + if (!TcapFeatureAvail()) { + return; // 濡傛灉 Tcap 鍔熻兘涓嶅彲鐢紝鍒欑洿鎺ヨ繑鍥 + } + + if (IsInitdb || TrRbIsEmptyDb(u_sess->proc_cxt.MyDatabaseId)) { + return; // 濡傛灉鏄 Initdb 妯″紡锛屾垨鑰呭綋鍓嶆暟鎹簱涓虹┖锛屽垯鐩存帴杩斿洖 + } + + if (TrIsRefRbObject(depender, depRel)) { + elog (ERROR, "can not access recycle object."); // 濡傛灉渚濊禆瀵硅薄鎴栧叾寮曠敤瀵硅薄鍦ㄥ洖鏀剁珯涓紝鍒欐姤閿欙紝涓嶅厑璁歌闂 + } + + for (int i = 0; i < nreferenced; i++, referenced++) { + if (TrIsRefRbObject(referenced, depRel)) { + elog (ERROR, "can not access recycle object."); // 濡傛灉琚緷璧栧璞℃垨鍏跺紩鐢ㄥ璞″湪鍥炴敹绔欎腑锛屽垯鎶ラ敊锛屼笉鍏佽璁块棶 + } + } + + return; +} + + +/* + * 鍔熻兘锛氱姝㈣闂洖鏀剁珯瀵硅薄 + * 鍙傛暟鍒楄〃锛 + * classid锛氬璞$被鍒殑 OID + * objid锛氬璞$殑 OID + * objname锛氬璞$殑鍚嶇О + */ +void TrForbidAccessRbObject(Oid classid, Oid objid, const char *objname) +{ + if (!TcapFeatureAvail()) { + return; // 濡傛灉 Tcap 鍔熻兘涓嶅彲鐢紝鍒欑洿鎺ヨ繑鍥 + } + + if (TrRbIsEmptyDb(u_sess->proc_cxt.MyDatabaseId) || !TrMaybeRbObject(classid, objid, objname)) { + return; // 濡傛灉褰撳墠鏁版嵁搴撲负绌猴紝鎴栬呭璞″彲鑳戒笉鏄洖鏀剁珯瀵硅薄锛屽垯鐩存帴杩斿洖 + } + + ObjectAddress obj = {classid, objid}; + if (TrIsRefRbObject(&obj)) { + elog (ERROR, "can not access recycle object."); // 濡傛灉瀵硅薄鎴栧叾寮曠敤瀵硅薄鍦ㄥ洖鏀剁珯涓紝鍒欐姤閿欙紝涓嶅厑璁歌闂 + } + + return; +} + +/* + * 鍔熻兘锛氬垽鏂槸鍚︿负鍥炴敹绔欏璞$殑 PostgreSQL 鍑芥暟 + * 鍙傛暟鍒楄〃锛 + * classid锛氬璞$被鍒殑 OID + * objid锛氬璞$殑 OID + * objname锛氬璞$殑鍚嶇О + */ +Datum gs_is_recycle_object(PG_FUNCTION_ARGS) +{ + int classid = PG_GETARG_INT32(0); // 鑾峰彇鍑芥暟鍙傛暟涓殑瀵硅薄绫诲埆 OID + int objid = PG_GETARG_INT32(1); // 鑾峰彇鍑芥暟鍙傛暟涓殑瀵硅薄 OID + Name objname = PG_GETARG_NAME(2); // 鑾峰彇鍑芥暟鍙傛暟涓殑瀵硅薄鍚嶇О + bool result = false; // 鐢ㄤ簬瀛樺偍鍒ゆ柇缁撴灉锛岄粯璁や负 false + + // 璋冪敤 TrIsRefRbObjectEx 鍑芥暟鍒ゆ柇缁欏畾瀵硅薄鏄惁涓哄洖鏀剁珯瀵硅薄锛屽苟灏嗙粨鏋滃瓨鍌ㄥ湪 result 涓 + result = TrIsRefRbObjectEx(classid, objid, NameStr(*objname)); + + // 杩斿洖甯冨皵鍊肩粨鏋 + PG_RETURN_BOOL(result); +} +>>>>>>> cb3246a73302b04edef5793406589f699676c34d diff --git a/src/gausskernel/storage/tcap/tcap_truncate.cpp b/src/gausskernel/storage/tcap/tcap_truncate.cpp index 0303a2640..b6737248b 100644 --- a/src/gausskernel/storage/tcap/tcap_truncate.cpp +++ b/src/gausskernel/storage/tcap/tcap_truncate.cpp @@ -1,3 +1,4 @@ +<<<<<<< HEAD /* * Copyright (c) 2020 Huawei Technologies Co.,Ltd. * @@ -96,25 +97,31 @@ #include "storage/tcap.h" #include "storage/tcap_impl.h" - +/* + * 鍔熻兘锛氫负缁欏畾鐨勫叧绯昏缃柊鐨勫叧绯绘枃浠惰妭鐐 + * 鍙傛暟鍒楄〃锛 + * relation锛氬叧绯诲璞 + * freezeXid锛氫簨鍔D + * baseDesc锛氬熀纭鎻忚堪瀵硅薄鎸囬拡 + */ void TrRelationSetNewRelfilenode(Relation relation, TransactionId freezeXid, void *baseDesc) { - TrObjDesc desc; - TrObjDesc *trBaseDesc = (TrObjDesc *)baseDesc; - RelFileNodeBackend newrnode; + TrObjDesc desc; // 瀹氫箟涓涓猅rObjDesc绫诲瀷鐨勫彉閲廳esc锛岀敤浜庤褰曞叧绯荤殑鎻忚堪淇℃伅 + TrObjDesc *trBaseDesc = (TrObjDesc *)baseDesc; // 灏嗕紶鍏ョ殑baseDesc鎸囬拡杞崲涓篢rObjDesc绫诲瀷鐨勬寚閽 + RelFileNodeBackend newrnode; // 瀹氫箟涓涓猂elFileNodeBackend绫诲瀷鐨勫彉閲弉ewrnode锛岃〃绀烘柊鐨勫叧绯绘枃浠惰妭鐐 /* Indexes, sequences must have Invalid frozenxid; other rels must not. */ Assert((((relation->rd_rel->relkind == RELKIND_INDEX) || (relation->rd_rel->relkind == RELKIND_GLOBAL_INDEX) || - (RELKIND_IS_SEQUENCE(relation->rd_rel->relkind))) ? - (freezeXid == InvalidTransactionId) : - TransactionIdIsNormal(freezeXid)) || - relation->rd_rel->relkind == RELKIND_RELATION); + (RELKIND_IS_SEQUENCE(relation->rd_rel->relkind))) + ? (freezeXid == InvalidTransactionId) + : TransactionIdIsNormal(freezeXid)) || + relation->rd_rel->relkind == RELKIND_RELATION); /* Record the old relfilenode to recyclebin. */ - desc = *trBaseDesc; + desc = *trBaseDesc; // 灏哹aseDesc鎸囬拡鎸囧悜鐨勫璞″鍒跺埌desc鍙橀噺涓 if (!TR_IS_BASE_OBJ_EX(trBaseDesc, RelationGetRelid(relation))) { TrDescInit(relation, &desc, RB_OPER_TRUNCATE, - TrGetObjType(RelationGetNamespace(relation), RelationGetRelkind(relation)), false); + TrGetObjType(RelationGetNamespace(relation), RelationGetRelkind(relation)), false); TrDescWrite(&desc); } @@ -153,31 +160,38 @@ void TrRelationSetNewRelfilenode(Relation relation, TransactionId freezeXid, voi /* ... and now we have eoxact cleanup work to do */ SetRelCacheNeedEOXActWork(true); } - +/* + * 鍔熻兘锛氫负缁欏畾鐨勫垎鍖鸿缃柊鐨勫叧绯绘枃浠惰妭鐐 + * 鍙傛暟鍒楄〃锛 + * parent锛氱埗鍏崇郴瀵硅薄 + * part锛氬垎鍖哄璞 + * freezeXid锛氫簨鍔D锛岀敤浜庡喕缁撳垎鍖 + * baseDesc锛氬熀纭鎻忚堪瀵硅薄鎸囬拡 + */ void TrPartitionSetNewRelfilenode(Relation parent, Partition part, TransactionId freezeXid, void *baseDesc) { - RelFileNodeBackend newrnode; - TrObjDesc desc; - TrObjDesc *trBaseDesc = (TrObjDesc *)baseDesc; + RelFileNodeBackend newrnode; // 瀹氫箟涓涓猂elFileNodeBackend绫诲瀷鐨勫彉閲弉ewrnode锛岃〃绀烘柊鐨勫叧绯绘枃浠惰妭鐐 + TrObjDesc desc; // 瀹氫箟涓涓猅rObjDesc绫诲瀷鐨勫彉閲廳esc锛岀敤浜庤褰曞叧绯荤殑鎻忚堪淇℃伅 + TrObjDesc *trBaseDesc = (TrObjDesc *)baseDesc; // 灏嗕紶鍏ョ殑baseDesc鎸囬拡杞崲涓篢rObjDesc绫诲瀷鐨勬寚閽 Assert((parent->rd_rel->relkind == RELKIND_INDEX || RELKIND_IS_SEQUENCE(parent->rd_rel->relkind)) ? freezeXid == InvalidTransactionId : TransactionIdIsNormal(freezeXid)); /* Record the old relfilenode to recyclebin. */ - desc = *trBaseDesc; + desc = *trBaseDesc; // 灏哹aseDesc鎸囬拡鎸囧悜鐨勫璞″鍒跺埌desc鍙橀噺涓 if (!TR_IS_BASE_OBJ_EX(trBaseDesc, part->pd_id)) { TrPartDescInit(parent, part, &desc, RB_OPER_TRUNCATE, - TrGetObjType(RelationGetNamespace(parent), RelationGetRelkind(parent)), false); + TrGetObjType(RelationGetNamespace(parent), RelationGetRelkind(parent)), false); TrDescWrite(&desc); } /* Allocate a new relfilenode */ - newrnode = CreateNewRelfilenodePart(parent, part); + newrnode = CreateNewRelfilenodePart(parent, part); - UpdatePartition(parent, part, freezeXid, &newrnode); + UpdatePartition(parent, part, freezeXid, &newrnode); - CommandCounterIncrement(); + CommandCounterIncrement(); // 澧炲姞鍛戒护璁℃暟鍣紝浣挎渶杩戠殑鏇存敼鍙 /* * Mark the part as having been given a new relfilenode in the current @@ -187,13 +201,17 @@ void TrPartitionSetNewRelfilenode(Relation parent, Partition part, TransactionId part->pd_newRelfilenodeSubid = GetCurrentSubTransactionId(); /* ... and now we have eoxact cleanup work to do */ - SetPartCacheNeedEOXActWork(true); + SetPartCacheNeedEOXActWork(true); // 璁剧疆鏍囧織锛岃〃绀洪渶瑕佸湪浜嬪姟缁撴潫鏃舵墽琛屾竻鐞嗗伐浣 } - +/* + * 鍔熻兘锛氭鏌ユ槸鍚﹀彲浠ヤ娇鐢≧ecyclebin杩涜鎴柇鎿嶄綔 + * 鍙傛暟鍒楄〃锛 + * stmt锛氭埅鏂鍙ュ璞 + */ bool TrCheckRecyclebinTruncate(const TruncateStmt *stmt) { - RangeVar *rel = NULL; - Oid relid; + RangeVar *rel = NULL; // 瀹氫箟涓涓猂angeVar绫诲瀷鐨勬寚閽坮el锛屽垵濮嬪寲涓篘ULL + Oid relid; // 瀹氫箟涓涓狾id绫诲瀷鐨勫彉閲弐elid锛岀敤浜庡瓨鍌ㄥ叧绯荤殑瀵硅薄鏍囪瘑绗 if (/* * Disable Recyclebin-based-Truncate when with purge option, or @@ -209,34 +227,44 @@ bool TrCheckRecyclebinTruncate(const TruncateStmt *stmt) return false; } - rel = (RangeVar *)linitial(stmt->relations); - relid = RangeVarGetRelid(rel, NoLock, false); + rel = (RangeVar *)linitial(stmt->relations); // 鑾峰彇鎴柇璇彞涓殑鍏崇郴 + relid = RangeVarGetRelid(rel, NoLock, false); // 鑾峰彇鍏崇郴鐨勫璞℃爣璇嗙 - return NeedTrComm(relid); + return NeedTrComm(relid); // 鍒ゆ柇鏄惁闇瑕丷ecyclebin澶勭悊璇ュ叧绯荤殑鎴柇 } - +/* + * 鍔熻兘锛氭埅鏂竴涓垎鍖 + * 鍙傛暟鍒楄〃锛 + * rel锛氬叧绯诲璞 + * tup锛氬垎鍖哄厓缁 + * insertBaseid锛氭彃鍏ョ殑鍩虹ID + */ void TrTruncateOnePart(Relation rel, HeapTuple tup, Oid insertBaseid) { - Oid toastOid = ((Form_pg_partition)GETSTRUCT(tup))->reltoastrelid; - Relation toastRel = NULL; - Oid partOid = HeapTupleGetOid(tup); - Partition p = partitionOpen(rel, partOid, AccessExclusiveLock); - TrObjDesc baseDesc; - TrPartDescInit(rel, p, &baseDesc, RB_OPER_TRUNCATE, RB_OBJ_PARTITION, false); - baseDesc.id = baseDesc.baseid = insertBaseid; - (void)TrDescWrite(&baseDesc); - TrUpdateBaseid(&baseDesc); + Oid toastOid = ((Form_pg_partition)GETSTRUCT(tup))->reltoastrelid; // 鑾峰彇鍒嗗尯鍏冪粍涓殑toast鍏崇郴瀵硅薄鏍囪瘑绗 + Relation toastRel = NULL; // 瀹氫箟涓涓猂elation绫诲瀷鐨勬寚閽坱oastRel锛屽垵濮嬪寲涓篘ULL + Oid partOid = HeapTupleGetOid(tup); // 鑾峰彇鍒嗗尯鍏冪粍鐨勫璞℃爣璇嗙 + Partition p = partitionOpen(rel, partOid, AccessExclusiveLock); // 鎵撳紑鍒嗗尯锛岃幏鍙朠artition瀵硅薄 + TrObjDesc baseDesc; // 瀹氫箟涓涓猅rObjDesc绫诲瀷鐨勫彉閲廱aseDesc锛岀敤浜庤褰曞熀纭鎻忚堪淇℃伅 + // 鍒濆鍖朾aseDesc鎻忚堪瀵硅薄锛岃缃负鍒嗗尯鎴柇鎿嶄綔 + TrPartDescInit(rel, p, &baseDesc, RB_OPER_TRUNCATE, RB_OBJ_PARTITION, false); + baseDesc.id = baseDesc.baseid = insertBaseid; // 璁剧疆baseDesc鐨処D鍜屽熀纭ID + (void)TrDescWrite(&baseDesc); // 灏哹aseDesc鎻忚堪淇℃伅鍐欏叆瀛樺偍 + TrUpdateBaseid(&baseDesc); // 鏇存柊鍩虹ID + + // 涓哄垎鍖鸿缃柊鐨勫叧绯绘枃浠惰妭鐐 TrPartitionSetNewRelfilenode(rel, p, u_sess->utils_cxt.RecentXmin, &baseDesc); /* process the toast table */ if (OidIsValid(toastOid)) { - Assert(rel->rd_rel->relpersistence != RELPERSISTENCE_UNLOGGED); - toastRel = heap_open(toastOid, AccessExclusiveLock); - TrRelationSetNewRelfilenode(toastRel, u_sess->utils_cxt.RecentXmin, &baseDesc); - heap_close(toastRel, AccessExclusiveLock); + Assert(rel->rd_rel->relpersistence != RELPERSISTENCE_UNLOGGED); // 鏂█楠岃瘉鍏崇郴鐨勬寔涔呮 + toastRel = heap_open(toastOid, AccessExclusiveLock); // 鎵撳紑toast鍏崇郴 + TrRelationSetNewRelfilenode(toastRel, u_sess->utils_cxt.RecentXmin, + &baseDesc); // 涓簍oast鍏崇郴璁剧疆鏂扮殑鍏崇郴鏂囦欢鑺傜偣 + heap_close(toastRel, AccessExclusiveLock); // 鍏抽棴toast鍏崇郴 } - partitionClose(rel, p, AccessExclusiveLock); + partitionClose(rel, p, AccessExclusiveLock); // 鍏抽棴鍒嗗尯 /* report truncate partition to PgStatCollector */ pgstat_report_truncate(partOid, rel->rd_id, rel->rd_rel->relisshared); @@ -245,8 +273,8 @@ void TrTruncateOnePart(Relation rel, HeapTuple tup, Oid insertBaseid) void TrPartitionTableProcess(Relation rel, Oid insertBaseid) { /* truncate partitioned table */ - List* partTupleList = NIL; - ListCell* partCell = NULL; + List *partTupleList = NIL; + ListCell *partCell = NULL; Oid heap_relid; bool is_shared = rel->rd_rel->relisshared; @@ -263,8 +291,8 @@ void TrPartitionTableProcess(Relation rel, Oid insertBaseid) Oid partOid = HeapTupleGetOid(tup); Partition p = partitionOpen(rel, partOid, AccessExclusiveLock); Relation partRel = partitionGetRelation(rel, p); - List* subPartTupleList = searchPgPartitionByParentId(PART_OBJ_TYPE_TABLE_SUB_PARTITION, partOid); - ListCell* subPartCell = NULL; + List *subPartTupleList = searchPgPartitionByParentId(PART_OBJ_TYPE_TABLE_SUB_PARTITION, partOid); + ListCell *subPartCell = NULL; foreach (subPartCell, subPartTupleList) { HeapTuple tup = (HeapTuple)lfirst(subPartCell); TrTruncateOnePart(partRel, tup, insertBaseid); @@ -286,7 +314,7 @@ void TrPartitionTableProcess(Relation rel, Oid insertBaseid) void TrTruncate(const TruncateStmt *stmt) { - RangeVar *rv = (RangeVar*)linitial(stmt->relations); + RangeVar *rv = (RangeVar *)linitial(stmt->relations); Relation rel; Oid relid; Oid toastRelid; @@ -302,9 +330,8 @@ void TrTruncate(const TruncateStmt *stmt) /* find matview exists or not. */ Oid mlogid = find_matview_mlog_table(relid); if (OidIsValid(mlogid)) { - ereport(ERROR, - (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - errmsg("Not support truncate table under materialized view."))); + ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("Not support truncate table under materialized view."))); } TrForbidAccessRbObject(RelationRelationId, relid, rv->relname); @@ -323,7 +350,7 @@ void TrTruncate(const TruncateStmt *stmt) * 2. Create a new empty storage file for the relation, and assign it * as the relfilenode value, and record the old relfilenode to recyclebin. */ - + TrDescInit(rel, &baseDesc, RB_OPER_TRUNCATE, RB_OBJ_TABLE, true, true); baseDesc.id = baseDesc.baseid = TrDescWrite(&baseDesc); TrUpdateBaseid(&baseDesc); @@ -373,6 +400,11 @@ void TrTruncate(const TruncateStmt *stmt) * RelationDropStorage * Schedule unlinking of physical storage at transaction commit. */ +/* + *鍔熻兘锛 杩欎釜鍑芥暟鐢ㄤ簬娓呯悊琚埅鏂紙truncate锛夌殑瀵硅薄鐨勪俊鎭紝浠庡洖鏀剁珯涓垹闄ょ浉鍏宠褰曪紝浠ュ強鍦ㄤ簨鍔℃彁浜ゆ椂瀹夋帓鍙栨秷閾炬帴鏃у瓨鍌ㄣ + *鍙傛暟鍒楄〃锛 + *desc锛氬璞℃弿杩帮紝鍏朵腑鍖呭惈瀵硅薄鐨勭浉鍏充俊鎭 + */ void TrDoPurgeObjectTruncate(TrObjDesc *desc) { Relation rbRel; @@ -380,46 +412,50 @@ void TrDoPurgeObjectTruncate(TrObjDesc *desc) ScanKeyData skey[1]; HeapTuple tup; - Assert (((desc->type == RB_OBJ_TABLE) && desc->canpurge) || ((desc->type == RB_OBJ_PARTITION) && !desc->canpurge)); + // 鏂█锛氬鏋滄槸琛ㄧ被鍨嬬殑瀵硅薄骞朵笖鍙互杩涜娓呯悊锛屾垨鑰呮槸鍒嗗尯瀵硅薄浣嗕笉鑳借繘琛屾竻鐞嗭紝鍒欐弧瓒虫潯浠 + Assert(((desc->type == RB_OBJ_TABLE) && desc->canpurge) || ((desc->type == RB_OBJ_PARTITION) && !desc->canpurge)); + // 鎵撳紑鍥炴敹绔欏叧绯伙紝鑾峰彇鎺掍粬閿 rbRel = heap_open(RecyclebinRelationId, RowExclusiveLock); - ScanKeyInit(&skey[0], Anum_pg_recyclebin_rcybaseid, BTEqualStrategyNumber, - F_INT8EQ, Int64GetDatum(desc->baseid)); + // 鍒濆鍖栨壂鎻忛敭 + ScanKeyInit(&skey[0], Anum_pg_recyclebin_rcybaseid, BTEqualStrategyNumber, F_INT8EQ, Int64GetDatum(desc->baseid)); + // 寮濮嬪鍥炴敹绔欏叧绯昏繘琛屾壂鎻 sd = systable_beginscan(rbRel, RecyclebinBaseidIndexId, true, NULL, 1, skey); while (HeapTupleIsValid(tup = systable_getnext(sd))) { Form_pg_recyclebin rbForm = (Form_pg_recyclebin)GETSTRUCT(tup); RelFileNode rnode; + // 鏋勯犺〃绌洪棿銆佹暟鎹簱鍜屽叧绯昏妭鐐逛俊鎭 rnode.spcNode = ConvertToRelfilenodeTblspcOid(rbForm->rcytablespace); - rnode.dbNode = (rnode.spcNode == GLOBALTABLESPACE_OID) ? InvalidOid : - u_sess->proc_cxt.MyDatabaseId; + rnode.dbNode = (rnode.spcNode == GLOBALTABLESPACE_OID) ? InvalidOid : u_sess->proc_cxt.MyDatabaseId; rnode.relNode = rbForm->rcyrelfilenode; rnode.opt = 0; rnode.bucketNode = InvalidBktId; /* - * Schedule unlinking of the old storage at transaction commit. + * 灏嗘棫瀛樺偍鐨勫彇娑堥摼鎺ュ畨鎺掑湪浜嬪姟鎻愪氦鏃惰繘琛 */ - InsertStorageIntoPendingList( - &rnode, InvalidAttrNumber, InvalidBackendId, rbForm->rcyowner, true, false); + InsertStorageIntoPendingList(&rnode, InvalidAttrNumber, InvalidBackendId, rbForm->rcyowner, true, false); + // 鍒犻櫎鍥炴敹绔欎腑鐨勮褰 simple_heap_delete(rbRel, &tup->t_self); - ereport(LOG, (errmsg("Delete truncated object %u/%u/%u", rnode.spcNode, - rnode.dbNode, rnode.relNode))); + ereport(LOG, (errmsg("Delete truncated object %u/%u/%u", rnode.spcNode, rnode.dbNode, rnode.relNode))); } + // 缁撴潫鎵弿 systable_endscan(sd); + + // 鍏抽棴鍥炴敹绔欏叧绯 heap_close(rbRel, RowExclusiveLock); - /* ... and now we have eoxact cleanup work to do */ + // 璁剧疆鍏崇郴缂撳瓨闇瑕佸湪浜嬪姟缁撴潫鏃惰繘琛屾竻鐞 SetRelCacheNeedEOXActWork(true); /* - * CommandCounterIncrement here to ensure that preceding changes are all - * visible to the next deletion step. + * 鍦ㄨ繖閲屾墽琛 CommandCounterIncrement锛屼互纭繚涔嬪墠鐨勬洿鏀瑰涓嬩竴涓垹闄ゆ楠ら兘鍙銆 */ CommandCounterIncrement(); } @@ -454,7 +490,7 @@ void TrRestoreTruncate(const TimeCapsuleStmt *stmt) if (found) { stmt->relation->relname = desc.name; } - + /* 1. Fetch the latest available recycle object. */ TrOperFetch(stmt->relation, RB_OBJ_TABLE, &baseDesc, RB_OPER_RESTORE_TRUNCATE); @@ -468,8 +504,7 @@ void TrRestoreTruncate(const TimeCapsuleStmt *stmt) /* 4. Do restore. */ rbRel = heap_open(RecyclebinRelationId, RowExclusiveLock); - ScanKeyInit(&skey[0], Anum_pg_recyclebin_rcybaseid, BTEqualStrategyNumber, - F_INT8EQ, Int64GetDatum(baseDesc.id)); + ScanKeyInit(&skey[0], Anum_pg_recyclebin_rcybaseid, BTEqualStrategyNumber, F_INT8EQ, Int64GetDatum(baseDesc.id)); sd = systable_beginscan(rbRel, RecyclebinBaseidIndexId, true, NULL, 1, skey); while (HeapTupleIsValid(tup = systable_getnext(sd))) { @@ -492,3 +527,533 @@ void TrRestoreTruncate(const TimeCapsuleStmt *stmt) return; } +======= +/* + * Copyright (c) 2020 Huawei Technologies Co.,Ltd. + * + * openGauss is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * + * http://license.coscl.org.cn/MulanPSL2 + * + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + * --------------------------------------------------------------------------------------- + * + * tcap_truncate.cpp + * Routines to support Timecapsule `Recyclebin-based query, restore`. + * We use Tr prefix to indicate it in following coding. + * + * IDENTIFICATION + * src/gausskernel/storage/tcap/tcap_truncate.cpp + * + * --------------------------------------------------------------------------------------- + */ + +#include "postgres.h" + +#include "pgstat.h" +#include "access/reloptions.h" +#include "access/sysattr.h" +#include "access/xlog.h" +#include "catalog/dependency.h" +#include "catalog/heap.h" +#include "catalog/index.h" +#include "catalog/indexing.h" +#include "catalog/objectaccess.h" +#include "catalog/pg_collation_fn.h" +#include "catalog/pg_collation.h" +#include "catalog/pg_constraint.h" +#include "catalog/pg_conversion_fn.h" +#include "catalog/pg_conversion.h" +#include "catalog/pg_depend.h" +#include "catalog/pg_extension_data_source.h" +#include "catalog/pg_extension.h" +#include "catalog/pg_foreign_data_wrapper.h" +#include "catalog/pg_foreign_server.h" +#include "catalog/pg_job.h" +#include "catalog/pg_language.h" +#include "catalog/pg_largeobject.h" +#include "catalog/pg_object.h" +#include "catalog/pg_opclass.h" +#include "catalog/pg_operator.h" +#include "catalog/pg_opfamily.h" +#include "catalog/pg_proc.h" +#include "catalog/pg_recyclebin.h" +#include "catalog/pg_rewrite.h" +#include "catalog/pg_rlspolicy.h" +#include "catalog/pg_synonym.h" +#include "catalog/pg_tablespace.h" +#include "catalog/pg_trigger.h" +#include "catalog/pg_ts_config.h" +#include "catalog/pg_ts_dict.h" +#include "catalog/pg_ts_parser.h" +#include "catalog/pg_ts_template.h" +#include "catalog/pgxc_class.h" +#include "catalog/storage.h" +#include "catalog/pg_partition_fn.h" +#include "commands/comment.h" +#include "commands/dbcommands.h" +#include "commands/directory.h" +#include "commands/extension.h" +#include "commands/matview.h" +#include "commands/proclang.h" +#include "commands/schemacmds.h" +#include "commands/seclabel.h" +#include "commands/sec_rls_cmds.h" +#include "commands/tablecmds.h" +#include "commands/tablespace.h" +#include "commands/trigger.h" +#include "commands/typecmds.h" +#include "executor/node/nodeModifyTable.h" +#include "rewrite/rewriteRemove.h" +#include "storage/lmgr.h" +#include "storage/predicate.h" +#include "storage/smgr/relfilenode.h" +#include "utils/acl.h" +#include "utils/builtins.h" +#include "utils/fmgroids.h" +#include "utils/inval.h" +#include "utils/knl_partcache.h" +#include "utils/knl_relcache.h" +#include "utils/lsyscache.h" +#include "utils/relcache.h" +#include "utils/snapmgr.h" +#include "utils/syscache.h" + +#include "storage/tcap.h" +#include "storage/tcap_impl.h" +/* + * 鍔熻兘锛氫负缁欏畾鐨勫叧绯昏缃柊鐨勫叧绯绘枃浠惰妭鐐 + * 鍙傛暟鍒楄〃锛 + * relation锛氬叧绯诲璞 + * freezeXid锛氫簨鍔D + * baseDesc锛氬熀纭鎻忚堪瀵硅薄鎸囬拡 + */ +void TrRelationSetNewRelfilenode(Relation relation, TransactionId freezeXid, void *baseDesc) +{ + TrObjDesc desc; // 瀹氫箟涓涓猅rObjDesc绫诲瀷鐨勫彉閲廳esc锛岀敤浜庤褰曞叧绯荤殑鎻忚堪淇℃伅 + TrObjDesc *trBaseDesc = (TrObjDesc *)baseDesc; // 灏嗕紶鍏ョ殑baseDesc鎸囬拡杞崲涓篢rObjDesc绫诲瀷鐨勬寚閽 + RelFileNodeBackend newrnode; // 瀹氫箟涓涓猂elFileNodeBackend绫诲瀷鐨勫彉閲弉ewrnode锛岃〃绀烘柊鐨勫叧绯绘枃浠惰妭鐐 + + /* Indexes, sequences must have Invalid frozenxid; other rels must not. */ + Assert((((relation->rd_rel->relkind == RELKIND_INDEX) || (relation->rd_rel->relkind == RELKIND_GLOBAL_INDEX) || + (RELKIND_IS_SEQUENCE(relation->rd_rel->relkind))) + ? (freezeXid == InvalidTransactionId) + : TransactionIdIsNormal(freezeXid)) || + relation->rd_rel->relkind == RELKIND_RELATION); + + /* Record the old relfilenode to recyclebin. */ + desc = *trBaseDesc; // 灏哹aseDesc鎸囬拡鎸囧悜鐨勫璞″鍒跺埌desc鍙橀噺涓 + if (!TR_IS_BASE_OBJ_EX(trBaseDesc, RelationGetRelid(relation))) { + TrDescInit(relation, &desc, RB_OPER_TRUNCATE, + TrGetObjType(RelationGetNamespace(relation), RelationGetRelkind(relation)), false); + TrDescWrite(&desc); + } + + /* Allocate a new relfilenode, create storage for the main fork. */ + newrnode = CreateNewRelfilenode(relation, freezeXid); + + /* + * NOTE: if the relation was created in this transaction, it will now be + * present in the pending-delete list twice, once with atCommit true and + * once with atCommit false. Hence, it will be physically deleted at end + * of xact in either case (and the other entry will be ignored by + * smgrDoPendingDeletes, so no error will occur). We could instead remove + * the existing list entry and delete the physical file immediately, but + * for now I'll keep the logic simple. + */ + RelationCloseSmgr(relation); + + /* + * Update pg_class entry for new relfilenode. + */ + UpdatePgclass(relation, freezeXid, &newrnode); + + /* + * Make the pg_class row change visible, as well as the relation map + * change if any. This will cause the relcache entry to get updated, too. + */ + CommandCounterIncrement(); + + /* + * Mark the rel as having been given a new relfilenode in the current + * (sub) transaction. This is a hint that can be used to optimize later + * operations on the rel in the same transaction. + */ + relation->rd_newRelfilenodeSubid = GetCurrentSubTransactionId(); + + /* ... and now we have eoxact cleanup work to do */ + SetRelCacheNeedEOXActWork(true); +} +/* + * 鍔熻兘锛氫负缁欏畾鐨勫垎鍖鸿缃柊鐨勫叧绯绘枃浠惰妭鐐 + * 鍙傛暟鍒楄〃锛 + * parent锛氱埗鍏崇郴瀵硅薄 + * part锛氬垎鍖哄璞 + * freezeXid锛氫簨鍔D锛岀敤浜庡喕缁撳垎鍖 + * baseDesc锛氬熀纭鎻忚堪瀵硅薄鎸囬拡 + */ +void TrPartitionSetNewRelfilenode(Relation parent, Partition part, TransactionId freezeXid, void *baseDesc) +{ + RelFileNodeBackend newrnode; // 瀹氫箟涓涓猂elFileNodeBackend绫诲瀷鐨勫彉閲弉ewrnode锛岃〃绀烘柊鐨勫叧绯绘枃浠惰妭鐐 + TrObjDesc desc; // 瀹氫箟涓涓猅rObjDesc绫诲瀷鐨勫彉閲廳esc锛岀敤浜庤褰曞叧绯荤殑鎻忚堪淇℃伅 + TrObjDesc *trBaseDesc = (TrObjDesc *)baseDesc; // 灏嗕紶鍏ョ殑baseDesc鎸囬拡杞崲涓篢rObjDesc绫诲瀷鐨勬寚閽 + + Assert((parent->rd_rel->relkind == RELKIND_INDEX || RELKIND_IS_SEQUENCE(parent->rd_rel->relkind)) + ? freezeXid == InvalidTransactionId + : TransactionIdIsNormal(freezeXid)); + + /* Record the old relfilenode to recyclebin. */ + desc = *trBaseDesc; // 灏哹aseDesc鎸囬拡鎸囧悜鐨勫璞″鍒跺埌desc鍙橀噺涓 + if (!TR_IS_BASE_OBJ_EX(trBaseDesc, part->pd_id)) { + TrPartDescInit(parent, part, &desc, RB_OPER_TRUNCATE, + TrGetObjType(RelationGetNamespace(parent), RelationGetRelkind(parent)), false); + TrDescWrite(&desc); + } + + /* Allocate a new relfilenode */ + newrnode = CreateNewRelfilenodePart(parent, part); + + UpdatePartition(parent, part, freezeXid, &newrnode); + + CommandCounterIncrement(); // 澧炲姞鍛戒护璁℃暟鍣紝浣挎渶杩戠殑鏇存敼鍙 + + /* + * Mark the part as having been given a new relfilenode in the current + * (sub) transaction. This is a hint that can be used to optimize later + * operations on the rel in the same transaction. + */ + part->pd_newRelfilenodeSubid = GetCurrentSubTransactionId(); + + /* ... and now we have eoxact cleanup work to do */ + SetPartCacheNeedEOXActWork(true); // 璁剧疆鏍囧織锛岃〃绀洪渶瑕佸湪浜嬪姟缁撴潫鏃舵墽琛屾竻鐞嗗伐浣 +} +/* + * 鍔熻兘锛氭鏌ユ槸鍚﹀彲浠ヤ娇鐢≧ecyclebin杩涜鎴柇鎿嶄綔 + * 鍙傛暟鍒楄〃锛 + * stmt锛氭埅鏂鍙ュ璞 + */ +bool TrCheckRecyclebinTruncate(const TruncateStmt *stmt) +{ + RangeVar *rel = NULL; // 瀹氫箟涓涓猂angeVar绫诲瀷鐨勬寚閽坮el锛屽垵濮嬪寲涓篘ULL + Oid relid; // 瀹氫箟涓涓狾id绫诲瀷鐨勫彉閲弐elid锛岀敤浜庡瓨鍌ㄥ叧绯荤殑瀵硅薄鏍囪瘑绗 + + if (/* + * Disable Recyclebin-based-Truncate when with purge option, or + */ + /* recyblebin disabled, or */ + !u_sess->attr.attr_storage.enable_recyclebin || + /* with purge option, or */ + stmt->purge || + /* with restart_seqs option, or */ + stmt->restart_seqs || + /* multi objects truncate. */ + list_length(stmt->relations) != 1) { + return false; + } + + rel = (RangeVar *)linitial(stmt->relations); // 鑾峰彇鎴柇璇彞涓殑鍏崇郴 + relid = RangeVarGetRelid(rel, NoLock, false); // 鑾峰彇鍏崇郴鐨勫璞℃爣璇嗙 + + return NeedTrComm(relid); // 鍒ゆ柇鏄惁闇瑕丷ecyclebin澶勭悊璇ュ叧绯荤殑鎴柇 +} +/* + * 鍔熻兘锛氭埅鏂竴涓垎鍖 + * 鍙傛暟鍒楄〃锛 + * rel锛氬叧绯诲璞 + * tup锛氬垎鍖哄厓缁 + * insertBaseid锛氭彃鍏ョ殑鍩虹ID + */ +void TrTruncateOnePart(Relation rel, HeapTuple tup, Oid insertBaseid) +{ + Oid toastOid = ((Form_pg_partition)GETSTRUCT(tup))->reltoastrelid; // 鑾峰彇鍒嗗尯鍏冪粍涓殑toast鍏崇郴瀵硅薄鏍囪瘑绗 + Relation toastRel = NULL; // 瀹氫箟涓涓猂elation绫诲瀷鐨勬寚閽坱oastRel锛屽垵濮嬪寲涓篘ULL + Oid partOid = HeapTupleGetOid(tup); // 鑾峰彇鍒嗗尯鍏冪粍鐨勫璞℃爣璇嗙 + Partition p = partitionOpen(rel, partOid, AccessExclusiveLock); // 鎵撳紑鍒嗗尯锛岃幏鍙朠artition瀵硅薄 + TrObjDesc baseDesc; // 瀹氫箟涓涓猅rObjDesc绫诲瀷鐨勫彉閲廱aseDesc锛岀敤浜庤褰曞熀纭鎻忚堪淇℃伅 + + // 鍒濆鍖朾aseDesc鎻忚堪瀵硅薄锛岃缃负鍒嗗尯鎴柇鎿嶄綔 + TrPartDescInit(rel, p, &baseDesc, RB_OPER_TRUNCATE, RB_OBJ_PARTITION, false); + baseDesc.id = baseDesc.baseid = insertBaseid; // 璁剧疆baseDesc鐨処D鍜屽熀纭ID + (void)TrDescWrite(&baseDesc); // 灏哹aseDesc鎻忚堪淇℃伅鍐欏叆瀛樺偍 + TrUpdateBaseid(&baseDesc); // 鏇存柊鍩虹ID + + // 涓哄垎鍖鸿缃柊鐨勫叧绯绘枃浠惰妭鐐 + TrPartitionSetNewRelfilenode(rel, p, u_sess->utils_cxt.RecentXmin, &baseDesc); + + /* process the toast table */ + if (OidIsValid(toastOid)) { + Assert(rel->rd_rel->relpersistence != RELPERSISTENCE_UNLOGGED); // 鏂█楠岃瘉鍏崇郴鐨勬寔涔呮 + toastRel = heap_open(toastOid, AccessExclusiveLock); // 鎵撳紑toast鍏崇郴 + TrRelationSetNewRelfilenode(toastRel, u_sess->utils_cxt.RecentXmin, + &baseDesc); // 涓簍oast鍏崇郴璁剧疆鏂扮殑鍏崇郴鏂囦欢鑺傜偣 + heap_close(toastRel, AccessExclusiveLock); // 鍏抽棴toast鍏崇郴 + } + partitionClose(rel, p, AccessExclusiveLock); // 鍏抽棴鍒嗗尯 + + /* report truncate partition to PgStatCollector */ + pgstat_report_truncate(partOid, rel->rd_id, rel->rd_rel->relisshared); +} + +void TrPartitionTableProcess(Relation rel, Oid insertBaseid) +{ + /* truncate partitioned table */ + List *partTupleList = NIL; + ListCell *partCell = NULL; + Oid heap_relid; + bool is_shared = rel->rd_rel->relisshared; + + heap_relid = RelationGetRelid(rel); + /* partitioned table unspport the unlogged table */ + Assert(rel->rd_rel->relpersistence != RELPERSISTENCE_UNLOGGED); + + /* process all partition */ + partTupleList = searchPgPartitionByParentId(PART_OBJ_TYPE_TABLE_PARTITION, rel->rd_id); + foreach (partCell, partTupleList) { + if (RelationIsSubPartitioned(rel)) { + /* the "tup" just for get partOid, UHeapTup has no HEAP_HASOID flag, so here use HeapTuple */ + HeapTuple tup = (HeapTuple)lfirst(partCell); + Oid partOid = HeapTupleGetOid(tup); + Partition p = partitionOpen(rel, partOid, AccessExclusiveLock); + Relation partRel = partitionGetRelation(rel, p); + List *subPartTupleList = searchPgPartitionByParentId(PART_OBJ_TYPE_TABLE_SUB_PARTITION, partOid); + ListCell *subPartCell = NULL; + foreach (subPartCell, subPartTupleList) { + HeapTuple tup = (HeapTuple)lfirst(subPartCell); + TrTruncateOnePart(partRel, tup, insertBaseid); + } + freePartList(subPartTupleList); + + releaseDummyRelation(&partRel); + partitionClose(rel, p, AccessExclusiveLock); + } else { + HeapTuple tup = (HeapTuple)lfirst(partCell); + TrTruncateOnePart(rel, tup, insertBaseid); + } + } + + freePartList(partTupleList); + /* report truncate partitioned table to PgStatCollector */ + pgstat_report_truncate(heap_relid, InvalidOid, is_shared); +} + +void TrTruncate(const TruncateStmt *stmt) +{ + RangeVar *rv = (RangeVar *)linitial(stmt->relations); + Relation rel; + Oid relid; + Oid toastRelid; + TrObjDesc baseDesc; + + /* + * 1. Open relation in AccessExclusiveLock, and check permission, etc. + */ + + rel = heap_openrv(rv, AccessExclusiveLock); + relid = RelationGetRelid(rel); + + /* find matview exists or not. */ + Oid mlogid = find_matview_mlog_table(relid); + if (OidIsValid(mlogid)) { + ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("Not support truncate table under materialized view."))); + } + + TrForbidAccessRbObject(RelationRelationId, relid, rv->relname); + + truncate_check_rel(rel); + + /* + * This effectively deletes all rows in the table, and may be done + * in a serializable transaction. In that case we must record a + * rw-conflict in to this transaction from each transaction + * holding a predicate lock on the table. + */ + CheckTableForSerializableConflictIn(rel); + + /* + * 2. Create a new empty storage file for the relation, and assign it + * as the relfilenode value, and record the old relfilenode to recyclebin. + */ + + TrDescInit(rel, &baseDesc, RB_OPER_TRUNCATE, RB_OBJ_TABLE, true, true); + baseDesc.id = baseDesc.baseid = TrDescWrite(&baseDesc); + TrUpdateBaseid(&baseDesc); + + /* + * step 2.1. If rel is partition table, find all partitions, and Create some new empty + * storage file for the all partitions of the relation, and assign them as the + * relfilenodes value, and record the old relfilenodes to recyclebin. + */ + if (RELATION_IS_PARTITIONED(rel)) { + TrPartitionTableProcess(rel, baseDesc.baseid); + } + + TrRelationSetNewRelfilenode(rel, u_sess->utils_cxt.RecentXmin, &baseDesc); + + /* + * 3. The same for the toast table, if any. + */ + + toastRelid = rel->rd_rel->reltoastrelid; + if (OidIsValid(toastRelid) && !RELATION_IS_PARTITIONED(rel)) { + Relation relToast = relation_open(toastRelid, AccessExclusiveLock); + TrRelationSetNewRelfilenode(relToast, u_sess->utils_cxt.RecentXmin, &baseDesc); + heap_close(relToast, NoLock); + } + + /* + * 4. Reconstruct the indexes to match, and we're done. + */ + + (void)ReindexRelation(relid, REINDEX_REL_PROCESS_TOAST, REINDEX_ALL_INDEX, &baseDesc); + + /* + * 5. Report stat, and clean. + */ + + /* report truncate to PgStatCollector */ + pgstat_report_truncate(relid, InvalidOid, false); + + /* Record time of truancate relation. */ + recordRelationMTime(relid, rel->rd_rel->relkind); + + heap_close(rel, NoLock); +} + +/* + * RelationDropStorage + * Schedule unlinking of physical storage at transaction commit. + */ +/* + *鍔熻兘锛 杩欎釜鍑芥暟鐢ㄤ簬娓呯悊琚埅鏂紙truncate锛夌殑瀵硅薄鐨勪俊鎭紝浠庡洖鏀剁珯涓垹闄ょ浉鍏宠褰曪紝浠ュ強鍦ㄤ簨鍔℃彁浜ゆ椂瀹夋帓鍙栨秷閾炬帴鏃у瓨鍌ㄣ + *鍙傛暟鍒楄〃锛 + *desc锛氬璞℃弿杩帮紝鍏朵腑鍖呭惈瀵硅薄鐨勭浉鍏充俊鎭 + */ +void TrDoPurgeObjectTruncate(TrObjDesc *desc) +{ + Relation rbRel; + SysScanDesc sd; + ScanKeyData skey[1]; + HeapTuple tup; + + // 鏂█锛氬鏋滄槸琛ㄧ被鍨嬬殑瀵硅薄骞朵笖鍙互杩涜娓呯悊锛屾垨鑰呮槸鍒嗗尯瀵硅薄浣嗕笉鑳借繘琛屾竻鐞嗭紝鍒欐弧瓒虫潯浠 + Assert(((desc->type == RB_OBJ_TABLE) && desc->canpurge) || ((desc->type == RB_OBJ_PARTITION) && !desc->canpurge)); + + // 鎵撳紑鍥炴敹绔欏叧绯伙紝鑾峰彇鎺掍粬閿 + rbRel = heap_open(RecyclebinRelationId, RowExclusiveLock); + + // 鍒濆鍖栨壂鎻忛敭 + ScanKeyInit(&skey[0], Anum_pg_recyclebin_rcybaseid, BTEqualStrategyNumber, F_INT8EQ, Int64GetDatum(desc->baseid)); + + // 寮濮嬪鍥炴敹绔欏叧绯昏繘琛屾壂鎻 + sd = systable_beginscan(rbRel, RecyclebinBaseidIndexId, true, NULL, 1, skey); + while (HeapTupleIsValid(tup = systable_getnext(sd))) { + Form_pg_recyclebin rbForm = (Form_pg_recyclebin)GETSTRUCT(tup); + RelFileNode rnode; + + // 鏋勯犺〃绌洪棿銆佹暟鎹簱鍜屽叧绯昏妭鐐逛俊鎭 + rnode.spcNode = ConvertToRelfilenodeTblspcOid(rbForm->rcytablespace); + rnode.dbNode = (rnode.spcNode == GLOBALTABLESPACE_OID) ? InvalidOid : u_sess->proc_cxt.MyDatabaseId; + rnode.relNode = rbForm->rcyrelfilenode; + rnode.opt = 0; + rnode.bucketNode = InvalidBktId; + + /* + * 灏嗘棫瀛樺偍鐨勫彇娑堥摼鎺ュ畨鎺掑湪浜嬪姟鎻愪氦鏃惰繘琛 + */ + InsertStorageIntoPendingList(&rnode, InvalidAttrNumber, InvalidBackendId, rbForm->rcyowner, true, false); + + // 鍒犻櫎鍥炴敹绔欎腑鐨勮褰 + simple_heap_delete(rbRel, &tup->t_self); + + ereport(LOG, (errmsg("Delete truncated object %u/%u/%u", rnode.spcNode, rnode.dbNode, rnode.relNode))); + } + + // 缁撴潫鎵弿 + systable_endscan(sd); + + // 鍏抽棴鍥炴敹绔欏叧绯 + heap_close(rbRel, RowExclusiveLock); + + // 璁剧疆鍏崇郴缂撳瓨闇瑕佸湪浜嬪姟缁撴潫鏃惰繘琛屾竻鐞 + SetRelCacheNeedEOXActWork(true); + + /* + * 鍦ㄨ繖閲屾墽琛 CommandCounterIncrement锛屼互纭繚涔嬪墠鐨勬洿鏀瑰涓嬩竴涓垹闄ゆ楠ら兘鍙銆 + */ + CommandCounterIncrement(); +} + +/* flashback table to before truncate */ +void TrRestoreTruncate(const TimeCapsuleStmt *stmt) +{ + TrObjDesc baseDesc; + Relation rbRel; + SysScanDesc sd; + ScanKeyData skey[1]; + HeapTuple tup; + Relation rel; + Oid relid; + bool found = false; + TrObjDesc desc; + + /* process restore truncate fail: TIMECAPSULE TABLE "BIN$3C534EBE021$4930808==$0" TO BEFORE TRUNCATE; */ + found = TrFetchName(stmt->relation->relname, RB_OBJ_TABLE, &desc, RB_OPER_RESTORE_TRUNCATE); + if (found) { + stmt->relation->relname = desc.originname; + } + + rel = heap_openrv(stmt->relation, AccessExclusiveLock); + relid = RelationGetRelid(rel); + if (rel->rd_tam_type == TAM_HEAP) { + heap_close(rel, NoLock); + elog(ERROR, "timecapsule does not support astore yet"); + return; + } + + if (found) { + stmt->relation->relname = desc.name; + } + + /* 1. Fetch the latest available recycle object. */ + TrOperFetch(stmt->relation, RB_OBJ_TABLE, &baseDesc, RB_OPER_RESTORE_TRUNCATE); + + /* 2. Lock recycle object and base relation. */ + baseDesc.authid = GetUserId(); + TrOperPrep(&baseDesc, RB_OPER_RESTORE_TRUNCATE); + + /* 3. Check base relation whether normal and matched. */ + TrBaseRelMatched(&baseDesc); + + /* 4. Do restore. */ + rbRel = heap_open(RecyclebinRelationId, RowExclusiveLock); + + ScanKeyInit(&skey[0], Anum_pg_recyclebin_rcybaseid, BTEqualStrategyNumber, F_INT8EQ, Int64GetDatum(baseDesc.id)); + + sd = systable_beginscan(rbRel, RecyclebinBaseidIndexId, true, NULL, 1, skey); + while (HeapTupleIsValid(tup = systable_getnext(sd))) { + if (!RELATION_IS_PARTITIONED(rel)) { + TrSwapRelfilenode(rbRel, tup, false); + } else { + TrSwapRelfilenode(rbRel, tup, true); + } + } + + systable_endscan(sd); + heap_close(rbRel, RowExclusiveLock); + heap_close(rel, NoLock); + + /* + * CommandCounterIncrement here to ensure that preceding changes are all + * visible to the next deletion step. + */ + CommandCounterIncrement(); + + return; +} +>>>>>>> cb3246a73302b04edef5793406589f699676c34d diff --git a/src/gausskernel/storage/tcap/tcap_version.cpp b/src/gausskernel/storage/tcap/tcap_version.cpp index aad39ed3f..20eb627bc 100644 --- a/src/gausskernel/storage/tcap/tcap_version.cpp +++ b/src/gausskernel/storage/tcap/tcap_version.cpp @@ -53,74 +53,78 @@ #include "storage/tcap.h" #include "catalog/pg_constraint.h" - +//鐢ㄤ簬鍒ゆ柇鎸囧畾鍏崇郴琛ㄦ槸鍚﹀寘鍚閿害鏉 static bool TvIsContainsForeignKey(Oid relid) { - Relation rbRel; - SysScanDesc sd; - ScanKeyData key; - HeapTuple tup; - bool isContainsForeignKey = false; + Relation rbRel; //鐢ㄤ簬璁块棶绯荤粺鐩綍琛ㄧ殑鍏崇郴瀵硅薄 + SysScanDesc sd; //鐢ㄤ簬鎵弿绯荤粺鐩綍琛ㄧ殑鎵弿鎻忚堪瀵硅薄 + ScanKeyData key;//鎵弿閿璞★紝鐢ㄤ簬璁剧疆鎵弿鐨勬潯浠 + HeapTuple tup; //琛ㄧず绯荤粺鐩綍琛ㄤ腑鐨勪竴涓厓缁 + bool isContainsForeignKey = false;// 琛ㄧず鏄惁鍖呭惈澶栭敭绾︽潫锛屽垵濮嬪间负鍋 + //鎵撳紑绯荤粺鐩綍琛紝骞跺皢缁撴灉璧嬪肩粰鍙橀噺 rbRel锛屼互渚垮悗缁殑鎿嶄綔鍙互浣跨敤杩欎釜鍏崇郴瀵硅薄鏉ヨ闂郴缁熺洰褰曡〃涓殑淇℃伅 rbRel = heap_open(ConstraintRelationId, AccessShareLock); - + ScanKeyInit(&key, Anum_pg_constraint_conrelid, BTEqualStrategyNumber, - F_OIDEQ, ObjectIdGetDatum(relid)); - + F_OIDEQ, ObjectIdGetDatum(relid));//鍒濆鍖栨壂鎻忛敭锛岀敤浜庡湪绯荤粺鐩綍琛ㄤ笂杩涜鎵弿 + //鍦ㄧ郴缁熺洰褰曡〃涓婂惎鍔ㄤ竴涓壂鎻忔搷浣滐紝骞跺皢鎵弿鎻忚堪瀵硅薄璧嬪肩粰鍙橀噺 sd锛岀敤浜庣鐞嗘壂鎻忚繃绋 sd = systable_beginscan(rbRel, ConstraintRelidIndexId, true, SnapshotNow, 1, &key); while ((tup = systable_getnext(sd)) != NULL) { - Form_pg_constraint con = (Form_pg_constraint)GETSTRUCT(tup); + Form_pg_constraint con = (Form_pg_constraint)GETSTRUCT(tup);//鑾峰彇鍏冪粍鐨勬暟鎹 /* Contains a foreign key or referenced by foreign key */ if (con->contype == CONSTRAINT_FOREIGN && con->conrelid == relid) { - isContainsForeignKey = true; + isContainsForeignKey = true;//濡傛灉鎵惧埌绗﹀悎鏉′欢鐨勫閿害鏉燂紝璁剧疆鏍囧織涓虹湡 break; } } - systable_endscan(sd); + systable_endscan(sd);//缁撴潫鎵弿 heap_close(rbRel, AccessShareLock); - return isContainsForeignKey; + return isContainsForeignKey;//杩斿洖鏄惁鍖呭惈澶栭敭绾︽潫鐨勭粨鏋 } - +// 鐢ㄤ簬妫鏌ユ寚瀹氬叧绯昏〃鏄惁琚閿害鏉熷紩鐢 static bool TvIsReferencedByForeignKey(Oid relid) { - Relation rbRel; - SysScanDesc sd; - HeapTuple tup; - bool isReferencedByForeignKey = false; - - rbRel = heap_open(ConstraintRelationId, AccessShareLock); + Relation rbRel;//鐢ㄤ簬璁块棶绯荤粺鐩綍琛ㄧ殑鍏崇郴瀵硅薄 + SysScanDesc sd;//鐢ㄤ簬鎵弿绯荤粺鐩綍琛ㄧ殑鎵弿鎻忚堪瀵硅薄 + HeapTuple tup; //琛ㄧず绯荤粺鐩綍琛ㄤ腑鐨勪竴涓厓缁 + bool isReferencedByForeignKey = false;//琛ㄧず鏄惁琚閿害鏉熷紩鐢紝鍒濆鍊间负鍋 + rbRel = heap_open(ConstraintRelationId, AccessShareLock);//鎵撳紑绯荤粺鐩綍琛 + + //鍦ㄧ郴缁熺洰褰曡〃涓婂惎鍔ㄤ竴涓壂鎻忔搷浣滐紝鏃犻渶绱㈠紩锛屼笉閿佸畾鎵弿琛岋紝浣跨敤蹇収涓哄綋鍓嶆椂鍒伙紝涓嶈缃壂鎻忔潯浠 sd = systable_beginscan(rbRel, InvalidOid, false, SnapshotNow, 0, NULL); while ((tup = systable_getnext(sd)) != NULL) { - Form_pg_constraint con = (Form_pg_constraint)GETSTRUCT(tup); + Form_pg_constraint con = (Form_pg_constraint)GETSTRUCT(tup);//鑾峰彇鍏冪粍鐨勬暟鎹 /* Not referenced by foreign key */ if (con->confrelid == relid) { - isReferencedByForeignKey = true; + isReferencedByForeignKey = true;//濡傛灉鎵惧埌绗﹀悎鏉′欢鐨勫紩鐢紝璁剧疆鏍囧織涓虹湡 break; } } - systable_endscan(sd); - heap_close(rbRel, AccessShareLock); + systable_endscan(sd);//缁撴潫鎵弿 + heap_close(rbRel, AccessShareLock);//鍏抽棴绯荤粺鐩綍琛 - return isReferencedByForeignKey; + return isReferencedByForeignKey;//杩斿洖鏄惁琚閿害鏉熷紩鐢ㄧ殑缁撴灉 } - +//鐢ㄤ簬妫鏌ユ寚瀹氬叧绯昏〃鏄惁鍖呭惈澶栭敭绾︽潫鎴栬澶栭敭绾︽潫寮曠敤 static bool TvForeignKeyCheck(Oid relid) -{ - return (TvIsContainsForeignKey(relid) || TvIsReferencedByForeignKey(relid)); +{ + //璋冪敤TvIsContainsForeignKey鍑芥暟鍜孴vIsReferencedByForeignKey鍑芥暟鏉ュ垽鏂寚瀹氬叧绯昏〃鏄惁鍖呭惈澶栭敭绾︽潫鎴栬澶栭敭绾︽潫寮曠敤 + //褰撹繑鍥瀟rue鏃惰鏄庢鍏崇郴琛ㄥ寘鍚閿害鏉熸垨琚閿害鏉熷紩鐢紝鍙嶄箣鍒欎笉鍖呭惈 + return (TvIsContainsForeignKey(relid) || TvIsReferencedByForeignKey(relid));/ } - +//姝ゅ嚱鏁扮敤浜庢鏌ユ寚瀹氬叧绯昏〃鏄惁鏀寔TimeCapsule鐗规 static bool TvFeatureSupport(Oid relid, char **errstr, bool isTimecapsuleTable) { Relation rel = RelationIdGetRelation(relid); - Form_pg_class classForm; + Form_pg_class classForm;//瀛樺偍琛ㄧ殑鍏冩暟鎹俊鎭 if (!RelationIsValid(rel)) { ereport( @@ -128,9 +132,9 @@ static bool TvFeatureSupport(Oid relid, char **errstr, bool isTimecapsuleTable) errmsg("could not open relation with OID %u", relid))); } - classForm = rel->rd_rel; + classForm = rel->rd_rel;// 鑾峰彇琛ㄧ殑鍏冩暟鎹俊鎭 if (classForm->relkind != RELKIND_RELATION) { - *errstr = "timecapsule feature does not support non-ordinary table"; + *errstr = "timecapsule feature does not support non-ordinary table";//鍚勭涓嶆敮鎸乀imeCapsule鐗规х殑鍘熷洜 } else if (is_sys_table(RelationGetRelid(rel))) { *errstr = "timecapsule feature does not support system table"; } else if (classForm->relpersistence != RELPERSISTENCE_PERMANENT) { @@ -159,17 +163,19 @@ static bool TvFeatureSupport(Oid relid, char **errstr, bool isTimecapsuleTable) *errstr = NULL; } - RelationClose(rel); + RelationClose(rel);// 鍏抽棴琛ㄥ叧绯诲璞 return *errstr == NULL; } - +//鐢ㄤ簬鍦ㄦ寚瀹氳寖鍥翠笅妫娴嬭〃鏄惁鏀寔TimeCapsule鐗规 void TvCheckVersionScan(RangeTblEntry *rte) { - char *errstr = NULL; + char *errstr = NULL;// 鍒濆鍖栧瓨鍌ㄩ敊璇俊鎭殑瀛楃涓叉寚閽 + //璋冪敤TvFeatureSupport鍑芥暟妫鏌ョ粰瀹氳〃鏄惁鏀寔 TimeCapsule 鐗规 if (!TvFeatureSupport(rte->relid, &errstr, false)) { + // 濡傛灉涓嶆敮鎸侊紝杈撳嚭閿欒淇℃伅 ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), (errmsg("%s", errstr)))); @@ -178,69 +184,71 @@ void TvCheckVersionScan(RangeTblEntry *rte) return; } +//鐢ㄤ簬妫鏌ョ粰瀹氱殑鎵弿鐘舵佹槸鍚︽槸鐗堟湰琛ㄦ壂鎻 bool TvIsVersionScan(const ScanState *ss) { - EState *estate = ss->ps.state; - Scan *scan = (Scan *)ss->ps.plan; + EState *estate = ss->ps.state;//鑾峰彇鎵弿鐘舵佸叧鑱旂殑鎵ц鐘舵佸璞 + Scan *scan = (Scan *)ss->ps.plan;//鑾峰彇鎵弿鐘舵佸叧鑱旂殑鎵弿璁″垝鑺傜偣 TimeCapsuleClause *tcc = rt_fetch(scan->scanrelid, estate->es_range_table)->timecapsule; - - return tcc != NULL; + // 鑾峰彇鏌ヨ鑼冨洿琛ㄤ腑涓庢壂鎻忚鍒掕妭鐐瑰叧鑱旂殑 TimeCapsule 瀛愬彞 + return tcc != NULL;//鏍规嵁杩斿洖缁撴灉鍒ゆ柇鏄惁鏄増鏈〃鎵弿 } /* * Whether the plan contains version table scan. */ +//鐢ㄤ簬妫鏌ョ粰瀹氱殑鏌ヨ璁″垝鏄惁鍖呭惈鐗堟湰琛ㄦ壂鎻 bool TvIsVersionPlan(const PlannedStmt *stmt) { - ListCell *l = NULL; - foreach (l, stmt->rtable) { + ListCell *l = NULL;//鍒濆鍖栭摼琛ㄩ亶鍘嗙敤鐨勬寚閽 + foreach (l, stmt->rtable) {//閬嶅巻鏌ヨ璁″垝涓殑鑼冨洿琛ㄦ潯鐩 RangeTblEntry *rte = (RangeTblEntry *)lfirst(l); - if (rte->timecapsule != NULL) { - return true; + if (rte->timecapsule != NULL) {//濡傛灉鑼冨洿琛ㄦ潯鐩叿鏈塗imeCapsule瀛愬彞 + return true;//杩斿洖鐪燂紝璇存槑鍖呭惈鐗堟湰琛ㄦ壂鎻 } } return false; } - +//鐢ㄤ簬灏嗙増鏈〃杈惧紡瑙勮寖鍖 Node *TvTransformVersionExpr(ParseState *pstate, TvVersionType tvtype, Node *tvver) { - Node *verExpr = tvver; + Node *verExpr = tvver;//鐢ㄤ簬瀛樺偍鐗堟湰琛ㄨ揪寮忕殑鍙橀噺 - verExpr = transformExpr(pstate, tvver); - if (checkExprHasSubLink(verExpr)) { + verExpr = transformExpr(pstate, tvver);//浣跨敤transformExpr鍑芥暟杞崲鐗堟湰琛ㄨ揪寮 + if (checkExprHasSubLink(verExpr)) {//妫鏌ヨ〃杈惧紡鏄惁鍖呭惈瀛愰摼鎺 ereport(ERROR, (errcode(ERRCODE_INVALID_OPERATION), errmsg("timecapsule clause not support sublink."))); } - + //鏍规嵁鐗堟湰绫诲瀷杩涜寮哄埗杞崲 if (tvtype == TV_VERSION_TIMESTAMP) { verExpr = coerce_to_specific_type(pstate, verExpr, TIMESTAMPTZOID, "TIMESTAMP"); } else { - verExpr = coerce_to_specific_type(pstate, verExpr, INT8OID, "CSN"); + verExpr = coerce_to_specific_type(pstate, verExpr, INT8OID, "CSN");//鍒嗛厤琛ㄨ揪寮忕殑鎺掑簭瑙勫垯 } assign_expr_collations(pstate, verExpr); - return verExpr; + return verExpr;//杩斿洖瑙勮寖鍖栧悗鐨勭増鏈〃杈惧紡 } - +//鐢ㄤ簬璁$畻鐗堟湰琛ㄨ揪寮忕殑甯搁噺鍊 static Const *TvEvalVerExpr(TvVersionType tvtype, Node *tvver) { - Const *result = (Const *)tvver; + Const *result = (Const *)tvver;//鐢ㄤ簬瀛樺偍鐗堟湰琛ㄨ揪寮忕殑甯搁噺缁撴灉 - if (!IsA(result, Const)) { + if (!IsA(result, Const)) {//濡傛灉鐗堟湰琛ㄨ揪寮忛潪甯搁噺 Node *verExpr; - ParseState *pstate = make_parsestate(NULL); - - verExpr = TvTransformVersionExpr(pstate, tvtype, tvver); - free_parsestate(pstate); + ParseState *pstate = make_parsestate(NULL);//鍒涘缓瑙f瀽鐘舵佸璞 + verExpr = TvTransformVersionExpr(pstate, tvtype, tvver);//灏嗙増鏈〃杈惧紡瑙勮寖鍖 + free_parsestate(pstate);//閲婃斁瑙f瀽鐘舵佸璞 + // 浣跨敤evaluate_expr鍑芥暟瀵硅浆鎹㈠悗鐨勮〃杈惧紡杩涜璇勪及锛岃幏鍙栧父閲忓 result = (Const *)evaluate_expr((Expr *)verExpr, exprType(verExpr), exprTypmod(verExpr), exprCollation(verExpr)); } - + //妫鏌ョ粨鏋滄槸鍚︽槸甯搁噺涓旈潪绌 if (!IsA(result, Const) || result->constisnull) { ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), @@ -265,12 +273,12 @@ TransactionId TvFetchSnpxminRecycle(TimestampTz tz) Datum value; bool isnull = false; TransactionId snapxmin = FirstNormalTransactionId; - + // 鎵撳紑蹇収琛ㄤ互杩涜璁块棶 rel = heap_open(SnapshotRelationId, AccessShareLock); - + // 鍒濆鍖栨壂鎻忛敭锛岄檺鍒舵椂闂村皬浜庣瓑浜庣粰瀹氭椂闂 ScanKeyInit(&skey[0], Anum_pg_snapshot_snptime, BTLessEqualStrategyNumber, F_TIMESTAMP_LE, TimestampTzGetDatum(tz)); - + // 寮濮嬫壂鎻忓揩鐓ц〃锛屾牴鎹椂闂磋寖鍥存绱㈣褰 sd = systable_beginscan(rel, SnapshotTimeCsnIndexId, true, NULL, 1, skey); tup = systable_getnext(sd); /* Limit 1 */ @@ -291,6 +299,7 @@ TransactionId TvFetchSnpxminRecycle(TimestampTz tz) * We use the round-down way to obtain snapshots. that is, * select * from gs_txn_snapshot where snptime <= :tz order by snptime desc limit 1; */ +// 鑾峰彇鎸囧畾鏃堕棿鐨勫揩鐓т俊鎭 static void TvFetchSnapTz(TimestampTz tz, Snapshot snap) { Relation rel; @@ -318,10 +327,10 @@ static void TvFetchSnapTz(TimestampTz tz, Snapshot snap) ereport(ERROR, (errcode(ERRCODE_INTERNAL_ERROR), errmsg("cannot find the restore point"))); } - + //鑾峰彇璁板綍涓殑蹇収淇℃伅鍊 value = heap_getattr(tup, Anum_pg_snapshot_snpsnapshot, RelationGetDescr(rel), &isnull); snapstr = TextDatumGetCString(value); - + //鍙嶅簭鍒楀寲蹇収淇℃伅瀛楃涓蹭负蹇収瀵硅薄 TxnSnapDeserialize(snapstr, snap); systable_endscan(sd); @@ -337,6 +346,7 @@ static void TvFetchSnapTz(TimestampTz tz, Snapshot snap) * We use the round-down way to obtain snapshots. that is, * select * from gs_txn_snapshot where snpcsn <= :csn order by snpcsn desc limit 1; */ +//璺烠SN搴忓垪鍙疯幏鍙栧揩鐓т俊鎭 static void TvFetchSnapCsn(int64 csn, Snapshot snap) { Relation rel; @@ -380,6 +390,7 @@ static void TvFetchSnapCsn(int64 csn, Snapshot snap) * must be set to MaxTransactionId to ensure the correctness. */ if ((CommitSeqNo)csn != snap->snapshotcsn) { + //濡傛灉鎸囧畾鐨凜SN涓庡揩鐓х殑CSN涓嶇浉绛夛紝鍒欐洿鏂板揩鐓у璞$殑涓浜涘睘鎬 snap->snapshotcsn = (CommitSeqNo)csn; snap->timeline = 0; snap->xmin = snap->xmin; @@ -393,31 +404,38 @@ static void TvFetchSnapCsn(int64 csn, Snapshot snap) return; } - +//鏍规嵁鐗堟湰绫诲瀷鍜屽艰幏鍙栧揩鐓т俊鎭 static Snapshot TvFetchSnap(TvVersionType type, Const *value) { - Snapshot snap = (Snapshot)palloc0(sizeof(SnapshotData)); - + Snapshot snap = (Snapshot)palloc0(sizeof(SnapshotData));//涓哄揩鐓у璞″垎閰嶅唴瀛 + //鏍规嵁鐗堟湰绫诲瀷鑾峰彇蹇収淇℃伅 if (type == TV_VERSION_TIMESTAMP) { TvFetchSnapTz(DatumGetTimestampTz(value->constvalue), snap); } else { TvFetchSnapCsn(DatumGetInt64(value->constvalue), snap); } - snap->satisfies = SNAPSHOT_VERSION_MVCC; + snap->satisfies = SNAPSHOT_VERSION_MVCC;//灏嗗揩鐓у璞$殑闅旂绾у埆璁剧疆涓哄鐗堟湰骞跺彂鎺у埗 return snap; } - +/* + * 鍔熻兘锛氱敤浜庤幏鍙栫壒瀹氱増鏈殑蹇収瀵硅薄 + * 鍙傛暟锛 + * relation: 瑕佽幏鍙栧揩鐓х殑鍏崇郴锛堣〃锛 + * tvtype: 鐗堟湰绫诲瀷锛堟椂闂存埑鎴 CSN锛 + * tvver: 鐢ㄤ簬纭畾蹇収鐨勭増鏈 + */ static Snapshot TvGetSnap(Relation relation, TvVersionType tvtype, Node *tvver) { - Const *value; - Snapshot snap; + Const *value;//鐢ㄤ簬瀛樺偍鐗堟湰鍊肩殑甯搁噺瀵硅薄 + Snapshot snap;//蹇収瀵硅薄 + //閫氳繃TvEvalVerExpr鍑芥暟璁$畻鐗堟湰鍊 value = TvEvalVerExpr(tvtype, tvver); - + //楠岃瘉蹇収鏄惁閫傜敤浜庣粰瀹氱殑鍏崇郴 snap = TvFetchSnap(tvtype, value); - + //楠岃瘉蹇収鏄惁閫傜敤浜庣粰瀹氱殑鍏崇郴 if (!tableam_tcap_validate_snap(relation, snap)) { ereport(ERROR, (errcode(ERRCODE_INTERNAL_ERROR), errmsg("Restore point too old"))); @@ -425,18 +443,23 @@ static Snapshot TvGetSnap(Relation relation, TvVersionType tvtype, Node *tvver) return snap; } - +/* + * 鍔熻兘锛氱敤浜庨獙璇佸叧绯昏〃鐨勫畾涔夋槸鍚︿笌鎸囧畾鐨勫揩鐓х浉鍖归厤 + * 鍙傛暟锛 + * - relid: 瑕侀獙璇佺殑鍏崇郴鐨 OID + * - snapcsn: 蹇収鐨勬彁浜ゅ簭鍒楀彿 + */ static void TvValidateRelDDL(Oid relid, CommitSeqNo snapcsn) { - Relation rel = RelationIdGetRelation(relid); - if (!RelationIsValid(rel)) { + Relation rel = RelationIdGetRelation(relid);//閫氳繃id鑾峰彇瑕侀獙璇佺殑鍏崇郴 + if (!RelationIsValid(rel)) {//妫鏌ュ叧绯绘槸鍚︽湁鏁 ereport( - ERROR, (errcode(ERRCODE_RELATION_OPEN_ERROR), + ERROR, (errcode(ERRCODE_RELATION_OPEN_ERROR), //鏃犳晥鏃舵姤閿 errmsg("could not open relation with OID %u", relid))); } - + //妫鏌ュ叧绯荤殑鍙樻洿CSN鏄惁澶т簬绛変簬蹇収鐨凜SN if (RelationGetChangecsn(rel) >= snapcsn) { - ereport(ERROR, (errcode(ERRCODE_INTERNAL_ERROR), + ereport(ERROR, (errcode(ERRCODE_INTERNAL_ERROR), //涓嶅尮閰嶆椂鎶ラ敊 errmsg("The table definition of \"%s\" has been changed.", RelationGetRelationName(rel)))); } @@ -450,37 +473,51 @@ static void TvValidateRelDDL(Oid relid, CommitSeqNo snapcsn) * Choose user-specified snapshot if TimeCapsule clause exists, otherwise * estate->es_snapshot instead. */ +/* + * 鍔熻兘锛氱敤浜庨夋嫨鐢ㄤ簬鎵弿鐨勫揩鐓 + * 鍙傛暟锛 + * relation: 鎵弿鍏宠仈鐨勫叧绯诲璞 + * scan: 鎵弿璁″垝鑺傜偣 + * ss: 鎵弿鐘舵 + */ Snapshot TvChooseScanSnap(Relation relation, Scan *scan, ScanState *ss) { - EState *estate = ss->ps.state; - Snapshot snap = estate->es_snapshot; + EState *estate = ss->ps.state;//鑾峰彇鎵ц鐘舵佸璞 + Snapshot snap = estate->es_snapshot;//鑾峰彇鎵ц鐘舵佷腑鐨勫揩鐓 + //鑾峰彇鑼冨洿琛ㄤ腑涓庢壂鎻忓叧鑱旂殑鏉$洰 RangeTblEntry *rte = rt_fetch(scan->scanrelid, estate->es_range_table); TimeCapsuleClause *tcc = rte->timecapsule; if (likely(tcc == NULL)) { - return snap; + return snap;//杩斿洖榛樿鐨勫揩鐓 } else { bool isnull = false; ExprContext *econtext; Datum val; Const *con; - + //鍒涘缓琛ㄨ揪寮忕殑涓婁笅鏂囦俊鎭 econtext = CreateExprContext(estate); val = ExecEvalExprSwitchContext(ExecInitExpr((Expr *)tcc->tvver, &ss->ps), - econtext, &isnull, NULL); + econtext, &isnull, NULL);//璁$畻鐗堟湰鍊 con = makeConst((tcc->tvtype == TV_VERSION_TIMESTAMP) ? TIMESTAMPTZOID : INT8OID, - -1, InvalidOid, 8, val, isnull, true); - + -1, InvalidOid, 8, val, isnull, true);//鍒涘缓瀵瑰簲绫诲瀷鐨勫父閲忚妭鐐 + //鑾峰彇閫傜敤浜庢寚瀹氱増鏈殑蹇収 snap = TvGetSnap(relation, tcc->tvtype, (Node *)con); + //楠岃瘉蹇収鐗堟湰鏄惁鍏佽鎵ц鐩稿叧鎿嶄綔 TvValidateRelDDL(rte->relid, snap->snapshotcsn); - + //閲婃斁琛ㄨ揪寮忎笂涓嬫枃鍜屽父閲忚妭鐐 FreeExprContext(econtext, true); pfree(con); } return snap; } - +/* + * 鍔熻兘锛氱敤浜庢牴鎹揩鐓у垹闄よ〃涓殑鏁版嵁 + * 鍙傛暟锛 + * relid: 鍏崇郴瀵硅薄鐨 OID + * snap: 鐢ㄤ簬鍒犻櫎鏁版嵁鐨勫揩鐓 + */ void TvDeleteDelta(Oid relid, Snapshot snap) { Relation rel; @@ -490,33 +527,42 @@ void TvDeleteDelta(Oid relid, Snapshot snap) /* Notice: invoker already acquired lock */ rel = heap_open(relid, NoLock); - sd = tableam_scan_begin(rel, snap, 0, NULL); + sd = tableam_scan_begin(rel, snap, 0, NULL);//寮濮嬫壂鎻 while ((tup = (HeapTuple)tableam_scan_getnexttuple(sd, ForwardScanDirection)) != NULL) { - simple_heap_delete(rel, &tup->t_self); + simple_heap_delete(rel, &tup->t_self);//寰幆鍒犻櫎鏁版嵁鐩磋嚦鎵弿缁撴潫 } tableam_scan_end(sd); heap_close(rel, NoLock); return; } - +/* + * 鍔熻兘锛氱敤浜庢牴鎹粰瀹氱殑蹇収锛屽垹闄ゅ叧绯绘垨鍒嗗尯鍏崇郴涓笉鍐嶉渶瑕佺殑鏁版嵁琛 + * 鍙傛暟锛 + * rel锛氫富鍏崇郴 + * partRel锛氬垎鍖哄叧绯 + * p锛氬垎鍖哄璞 + * snap锛氬揩鐓у璞 + */ void TvUheapDeleteDeltaRel(Relation rel, Relation partRel, Partition p, Snapshot snap) { + //澹版槑鍙橀噺锛岀敤浜庡瓨鍌ㄦ壂鎻忔暟鎹佷簨鍔℃爣璇嗙瓑淇℃伅 TableScanDesc sd; UHeapTuple tup; TupleTableSlot *oldslot = NULL; TransactionId tmfdXmin = InvalidTransactionId; - - Snapshot snapshotNow = (Snapshot)palloc0(sizeof(SnapshotData)); + + Snapshot snapshotNow = (Snapshot)palloc0(sizeof(SnapshotData));//鍒嗛厤骞跺垵濮嬪寲涓涓猄napshot瀵硅薄 (void)GetSnapshotData(snapshotNow, false); - snap->user_data = (void *)snapshotNow; + snap->user_data = (void *)snapshotNow;//灏嗗揩鐓т笌snapshotNow鍏宠仈 - EState *estate = CreateExecutorState(); + EState *estate = CreateExecutorState();//鍒涘缓鎵ц鐘舵 /* * We need a ResultRelInfo so we can use the regular executor's * index-entry-making machinery. (There used to be a huge amount of code * here that basically duplicated execUtils.c ...) */ + //鍒涘缓涓涓猂esultRelInfo瀵硅薄 ResultRelInfo *resultRelInfo = makeNode(ResultRelInfo); resultRelInfo->ri_RangeTableIndex = 1; /* dummy */ resultRelInfo->ri_RelationDesc = rel; @@ -525,12 +571,14 @@ void TvUheapDeleteDeltaRel(Relation rel, Relation partRel, Partition p, Snapshot estate->es_num_result_relations = 1; estate->es_result_relation_info = resultRelInfo; + //鏍规嵁鏄惁瀛樺湪鍒嗗尯鍏崇郴閫夋嫨瑕佹壂鎻忕殑鍏崇郴 Relation relRel = (partRel != NULL) ? partRel : rel; - sd = tableam_scan_begin(relRel, snap, 0, NULL); + sd = tableam_scan_begin(relRel, snap, 0, NULL);//鏍规嵁閫夋嫨鐨勬壂鎻忓叧绯诲垵濮嬪寲琛ㄦ壂鎻忔弿杩扮 + while ((tup = (UHeapTuple)tableam_scan_getnexttuple(sd, ForwardScanDirection)) != NULL) { SimpleUHeapDelete(relRel, &tup->ctid, snapshotNow, &oldslot, &tmfdXmin); ExecDeleteIndexTuples(oldslot, &tup->ctid, estate, relRel, p, NULL, false); - if (relRel != NULL && relRel->rd_mlogoid != InvalidOid) { + if (relRel != NULL && relRel->rd_mlogoid != InvalidOid) {//濡傛灉鍏崇郴瀛樺湪骞朵笖鍏锋湁鏈夋晥鐨刴logoid锛屽垯灏嗗垹闄や俊鎭彃鍏log琛 insert_into_mlog_table(relRel, relRel->rd_mlogoid, NULL, &tup->ctid, tmfdXmin, 'D'); } if (oldslot) { @@ -554,11 +602,18 @@ void TvUheapDeleteDeltaRel(Relation rel, Relation partRel, Partition p, Snapshot return; } - +/* + * 鍔熻兘锛氭牴鎹粰瀹氱殑蹇収锛岄掑綊鍒犻櫎涓诲叧绯诲強鍏舵墍鏈夊垎鍖哄叧绯讳腑涓嶅啀闇瑕佺殑鏁版嵁琛屻 + * + * 鍙傛暟鍒楄〃锛 + * rel锛氫富鍏崇郴銆 + * relid锛氫富鍏崇郴鐨凮ID銆 + * snap锛氬揩鐓у璞° + */ void TvUheapDeleteDeltaPart(Relation rel, Oid relid, Snapshot snap) { - List* partTupleList = NIL; - ListCell* partCell = NULL; + List* partTupleList = NIL;//鍒嗗尯鍏冪粍鍒楄〃 + ListCell* partCell = NULL;//鍒嗗尯鍏冪粍閬嶅巻鎸囬拡 /* Open partition table, find all partition names based on the parentId. * partitioned table unspport the unlogged table. @@ -570,59 +625,91 @@ void TvUheapDeleteDeltaPart(Relation rel, Oid relid, Snapshot snap) foreach (partCell, partTupleList) { /* the "tup" just for get partOid, UHeapTup has no HEAP_HASOID flag, so here use HeapTuple */ HeapTuple tup = (HeapTuple)lfirst(partCell); - Oid partOid = HeapTupleGetOid(tup); - Partition p = partitionOpen(rel, partOid, AccessExclusiveLock); - Relation partRel = partitionGetRelation(rel, p); + Oid partOid = HeapTupleGetOid(tup);//鑾峰彇鍒嗗尯OID + Partition p = partitionOpen(rel, partOid, AccessExclusiveLock);//鎵撳紑鍒嗗尯 + Relation partRel = partitionGetRelation(rel, p);//鑾峰彇鍒嗗尯鍏崇郴 - if (RelationIsSubPartitioned(rel)) { - List* subPartTupleList = searchPgPartitionByParentId(PART_OBJ_TYPE_TABLE_SUB_PARTITION, partOid); - ListCell* subPartCell = NULL; - foreach (subPartCell, subPartTupleList) { + if (RelationIsSubPartitioned(rel)) {//褰撲富鍏崇郴瀛樺湪瀛愬垎鍖烘墽琛屼互涓嬫搷浣 + List* subPartTupleList = searchPgPartitionByParentId(PART_OBJ_TYPE_TABLE_SUB_PARTITION, partOid);//鏌ユ壘瀛愬垎鍖哄厓缁勫垪琛 + ListCell* subPartCell = NULL;//鍒濆鍖栧瓙鍒嗗尯鍏冪粍閬嶅巻鎸囬拡 + foreach (subPartCell, subPartTupleList) {//閬嶅巻瀛愬垎鍖 HeapTuple subTup = (HeapTuple)lfirst(subPartCell); - Oid subPartOid = HeapTupleGetOid(subTup); - Partition subPar = partitionOpen(partRel, subPartOid, AccessExclusiveLock); - Relation subPartRel = partitionGetRelation(partRel, subPar); - TvUheapDeleteDeltaRel(rel, subPartRel, subPar, snap); - releaseDummyRelation(&subPartRel); - partitionClose(partRel, subPar, NoLock); + Oid subPartOid = HeapTupleGetOid(subTup);//鑾峰彇瀛愬垎鍖篛ID + Partition subPar = partitionOpen(partRel, subPartOid, AccessExclusiveLock);//瀛愬垎鍖哄厓缁勯亶鍘 + Relation subPartRel = partitionGetRelation(partRel, subPar);//鑾峰彇瀛愬垎鍖哄叧绯 + TvUheapDeleteDeltaRel(rel, subPartRel, subPar, snap);//鍒犻櫎瀛愬垎鍖虹殑涓嶅啀闇瑕佺殑鏁版嵁琛 + releaseDummyRelation(&subPartRel);//閲婃斁瀛愬垎鍖哄叧绯 + partitionClose(partRel, subPar, NoLock);//鍏抽棴瀛愬垎鍖 } - freePartList(subPartTupleList); + freePartList(subPartTupleList);//閲婃斁瀛愬垎鍖哄厓缁勫垪琛 } else { - TvUheapDeleteDeltaRel(rel, partRel, p, snap); + TvUheapDeleteDeltaRel(rel, partRel, p, snap);//鍒犻櫎鍒嗗尯鐨勪笉鍐嶉渶瑕佺殑鏁版嵁琛 } - releaseDummyRelation(&partRel); - partitionClose(rel, p, NoLock); + releaseDummyRelation(&partRel);//閲婃斁鍒嗗尯鍏崇郴 + partitionClose(rel, p, NoLock);//鍏抽棴鍒嗗尯 } - freePartList(partTupleList); + freePartList(partTupleList);//閲婃斁鍒嗗尯鍏冪粍鍒楄〃 return; } - +/* + * 鍔熻兘锛氭牴鎹粰瀹氱殑蹇収锛屽垹闄や富鍏崇郴鎴栧叾鍒嗗尯鍏崇郴涓笉鍐嶉渶瑕佺殑鏁版嵁琛屻 + * + * 鍙傛暟鍒楄〃锛 + * relid锛氬叧绯荤殑OID銆 + * snap锛氬揩鐓у璞° + */ void TvUheapDeleteDelta(Oid relid, Snapshot snap) { - Relation rel = heap_open(relid, NoLock); - if (RELATION_IS_PARTITIONED(rel)) { + Relation rel = heap_open(relid, NoLock);//浠oLock鏃犻攣妯″紡璁块棶寰呮搷浣滅殑鍏崇郴 + if (RELATION_IS_PARTITIONED(rel)) {//鏍规嵁鍏崇郴鏄惁涓哄垎鍖鸿〃杩涜涓嶅悓鐨勬搷浣 + //濡傛灉鏄垎鍖鸿〃锛屽垯璋冪敤TvUheapDeleteDeltaPart鍑芥暟鏉ュ垹闄ゆ瘡涓垎鍖虹殑Delta鏁版嵁 TvUheapDeleteDeltaPart(rel, relid, snap); } else { + //鍚﹀垯鐩存帴璋冪敤TvUheapDeleteDeltaRel鍑芥暟鏉ュ垹闄elta鏁版嵁 TvUheapDeleteDeltaRel(rel, NULL, NULL, snap); } heap_close(rel, NoLock); } - +/* + * 鍔熻兘锛氱敤浜庤幏鍙栨暟鎹簱涓殑鍏冪粍 + * + * 鍙傛暟鍒楄〃锛 + * arg锛氬嚱鏁版寚閽 + */ typedef HeapTuple (*TvFetchTupleHook)(void *arg); static HeapTuple TvFetchTuple(void *arg) { + //璋冪敤tableam_scan_getnexttuple鍑芥暟鏉ヨ幏鍙栦笅涓涓厓缁 HeapTuple tup = (HeapTuple)tableam_scan_getnexttuple((TableScanDesc)arg, ForwardScanDirection); - + //濡傛灉鑾峰彇鍒颁簡鍏冪粍璋冪敤tableam_tops_copy_tuple鍑芥暟瀵瑰厓缁勮繘琛屾嫹璐濓紝骞惰繑鍥炴嫹璐濆悗鐨勭粨鏋 + //鍚﹀垯锛岃繑鍥濶ULL琛ㄧず娌℃湁鑾峰彇鍒板厓缁 return tup ? (HeapTuple)tableam_tops_copy_tuple(tup) : NULL; } - +/* + * 鍔熻兘锛氱敤浜庤幏鍙栨暟鎹簱涓殑UHeapTuple鍏冪粍 + * + * 鍙傛暟鍒楄〃锛 + * arg锛氬嚱鏁版寚閽 + */ typedef UHeapTuple (*TvUheapFetchTupleHook)(void *arg); static UHeapTuple TvUheapFetchTuple(void *arg) { return (UHeapTuple)tableam_scan_getnexttuple((TableScanDesc)arg, ForwardScanDirection); } - +/* + * 鍔熻兘锛氱敤浜庡悜鍏崇郴涓壒閲忔彃鍏ュ厓缁勶紝鍗虫壒閲忔彃鍏ユ搷浣 + * 鍙傛暟锛 + * rel锛氳鎻掑叆鍏冪粍鐨勫叧绯汇 + * estate锛氭墽琛岀姸鎬佷俊鎭 + * mycid锛氬綋鍓嶅懡浠ょ殑 CommandId銆 + * hiOptions锛氭彃鍏ラ夐」銆 + * resultRelInfo锛氱粨鏋滃叧绯讳俊鎭 + * myslot锛氬厓缁勬Ы锛岀敤浜庝复鏃跺瓨鍌ㄥ厓缁勩 + * bistate锛氭壒閲忔彃鍏ョ姸鎬佷俊鎭 + * nBufferedTuples锛氳鎻掑叆鐨勫厓缁勬暟閲忋 + * bufferedTuples锛氳鎻掑叆鐨勫厓缁勬暟缁勩 + */ static void TvBatchInsert(Relation rel, EState *estate, CommandId mycid, int hiOptions, ResultRelInfo *resultRelInfo, TupleTableSlot *myslot, BulkInsertState bistate, @@ -647,9 +734,9 @@ static void TvBatchInsert(Relation rel, EState *estate, CommandId mycid, int i; for (i = 0; i < nBufferedTuples; i++) { List *recheckIndexes = NULL; - + //灏嗗綋鍓嶈鎻掑叆鐨勫厓缁勫瓨鍌ㄥ埌鍏冪粍妲戒腑 (void)ExecStoreTuple(bufferedTuples[i], myslot, InvalidBuffer, false); - + //鎵ц绱㈠紩鎻掑叆鎿嶄綔锛岃繑鍥為渶瑕侀噸鏂版鏌ョ殑绱㈠紩鍒楄〃 recheckIndexes = ExecInsertIndexTuples(myslot, &(bufferedTuples[i]->t_self), estate, @@ -658,7 +745,7 @@ static void TvBatchInsert(Relation rel, EState *estate, CommandId mycid, InvalidBktId, NULL, NULL); - + //閲婃斁閲嶆柊妫鏌ョ储寮曞垪琛ㄧ殑鍐呭瓨 list_free(recheckIndexes); } } @@ -668,6 +755,14 @@ static void TvBatchInsert(Relation rel, EState *estate, CommandId mycid, const int MAX_BUFFERED_TUPLES_TCAP = 1000; const int MAX_BUFFERED_TUPLES_NUM_TCAP = 65535; +/* + * 鍔熻兘锛氱敤浜庢墽琛屾彃鍏ヤ涪澶卞厓缁勬搷浣滅殑瀹炵幇鍑芥暟銆 + * 鍙傛暟锛 + * rel锛氳鎻掑叆鍏冪粍鐨勫叧绯汇 + * snap锛氬綋鍓嶄簨鍔$殑蹇収銆 + * fetchTupleHook锛氳幏鍙栧厓缁勭殑閽╁瓙鍑芥暟銆 + * arg锛氶挬瀛愬嚱鏁扮殑鍙傛暟銆 + */ static void TvInsertLostImpl(Relation rel, Snapshot snap, TvFetchTupleHook fetchTupleHook, void *arg) { HeapTuple tuple; @@ -680,8 +775,8 @@ static void TvInsertLostImpl(Relation rel, Snapshot snap, TvFetchTupleHook fetch BulkInsertState bistate; int nBufferedTuples = 0; - HeapTuple *bufferedTuples = NULL; - Size bufferedTuplesSize = 0; + HeapTuple *bufferedTuples = NULL;//缂撳啿鐨勫厓缁勬暟缁 + Size bufferedTuplesSize = 0;//缂撳啿鐨勫厓缁勬诲ぇ灏 /* * We need a ResultRelInfo so we can use the regular executor's @@ -734,8 +829,8 @@ static void TvInsertLostImpl(Relation rel, Snapshot snap, TvFetchTupleHook fetch ExecConstraints(resultRelInfo, slot, estate); } - bufferedTuples[nBufferedTuples++] = tuple; - bufferedTuplesSize += tuple->t_len; + bufferedTuples[nBufferedTuples++] = tuple;//灏嗗厓缁勫姞鍏ョ紦鍐叉暟缁 + bufferedTuplesSize += tuple->t_len;//澧炲姞缂撳啿鍏冪粍鎬诲ぇ灏 /* * If the buffer filled up, flush it. Also flush if the total @@ -747,32 +842,43 @@ static void TvInsertLostImpl(Relation rel, Snapshot snap, TvFetchTupleHook fetch TvBatchInsert(rel, estate, mycid, hiOptions, resultRelInfo, myslot, bistate, nBufferedTuples, bufferedTuples); - nBufferedTuples = 0; - bufferedTuplesSize = 0; + nBufferedTuples = 0;//閲嶇疆缂撳啿鍏冪粍鏁伴噺 + bufferedTuplesSize = 0;//閲嶇疆缂撳啿鍏冪粍鏁伴噺 } } /* Flush any remaining buffered tuples */ if (nBufferedTuples > 0) { + //濡傛灉浠嶆湁缂撳啿鐨勫厓缁勶紝璋冪敤TvBatchInsert鍑芥暟灏嗗畠浠竴骞舵彃鍏 TvBatchInsert(rel, estate, mycid, hiOptions, resultRelInfo, myslot, bistate, nBufferedTuples, bufferedTuples); } - + //閲婃斁BulkInsertState瀵硅薄鐨勮祫婧 FreeBulkInsertState(bistate); - + //鍒囨崲鍥炴棫鐨勫唴瀛樹笂涓嬫枃 MemoryContextSwitchTo(oldcontext); - + //閲嶇疆鎵ц鍣ㄧ殑鍏冪粍琛紝閲婃斁鍏朵腑鐨勮祫婧 ExecResetTupleTable(estate->es_tupleTable, false); - + //鍏抽棴鎵鏈夌殑绱㈠紩 ExecCloseIndices(resultRelInfo); - + //閲婃斁鎵ц鐘舵佸璞$殑璧勬簮 FreeExecutorState(estate); - + //閲婃斁缂撳啿鍏冪粍鏁扮粍鐨勫唴瀛 pfree(bufferedTuples); + //閲婃斁ResultRelInfo瀵硅薄鐨勫唴瀛 pfree(resultRelInfo); return; } - +/* + * 鍔熻兘锛氬湪UHeap琛ㄤ腑鎵归噺鎻掑叆涓㈠け鐨勫厓缁勩 + * 鍙傛暟鍒楄〃锛 + * rel锛氳〃绀鸿鎻掑叆鐨勫叧绯 + * partRel锛氳〃绀哄垎鍖哄叧绯 + * p锛氬垎鍖哄璞 + * snap锛氬揩鐓у璞 + * fetchTupleHook锛氬厓缁勮幏鍙栭挬瀛愬嚱鏁 + * arg锛氬厓缁勮幏鍙栭挬瀛愬嚱鏁扮殑鍙傛暟 + */ static void TvUheapInsertLostImpl(Relation rel, Relation partRel, Partition p, Snapshot snap, TvUheapFetchTupleHook fetchTupleHook, void *arg) { @@ -780,7 +886,7 @@ static void TvUheapInsertLostImpl(Relation rel, Relation partRel, Partition p, ResultRelInfo *resultRelInfo; EState *estate = CreateExecutorState(); TupleTableSlot *myslot; - CommandId mycid = GetCurrentCommandId(true); + CommandId mycid = GetCurrentCommandId(true);//鑾峰彇褰撳墠鍛戒护鐨処D /* * We need a ResultRelInfo so we can use the regular executor's * index-entry-making machinery. (There used to be a huge amount of code @@ -789,12 +895,12 @@ static void TvUheapInsertLostImpl(Relation rel, Relation partRel, Partition p, resultRelInfo = makeNode(ResultRelInfo); resultRelInfo->ri_RangeTableIndex = 1; /* dummy */ resultRelInfo->ri_RelationDesc = rel; - ExecOpenIndices(resultRelInfo, false); + ExecOpenIndices(resultRelInfo, false);//鎵撳紑绱㈠紩 estate->es_result_relations = resultRelInfo; estate->es_num_result_relations = 1; estate->es_result_relation_info = resultRelInfo; - Relation relRel = (partRel != NULL) ? partRel : rel; + Relation relRel = (partRel != NULL) ? partRel : rel;//鏍规嵁鍒嗗尯鍏崇郴鏄惁鏈夋寚瀹氶夋嫨瑕佹彃鍏ョ殑琛 /* Set up a tuple slot too */ myslot = ExecInitExtraTupleSlot(estate, TAM_USTORE); ExecSetSlotDescriptor(myslot, RelationGetDescr(relRel)); @@ -819,7 +925,9 @@ static void TvUheapInsertLostImpl(Relation rel, Relation partRel, Partition p, UHeapInsert(relRel, tuple, mycid, NULL); List *recheckIndexes = NULL; + //鎵ц绱㈠紩鎻掑叆鎿嶄綔 recheckIndexes = ExecInsertIndexTuples(myslot, &tuple->ctid, estate, partRel, p, InvalidBktId, NULL, NULL); + //濡傛灉琛ㄦ湁鏇存敼璁板綍鏃ュ織琛紙mlog锛夛紝鍒欐彃鍏ョ浉搴旂殑鏇存敼鏃ュ織 if (relRel != NULL && relRel->rd_mlogoid != InvalidOid) { HeapTuple htup = NULL; Assert(relRel->rd_tam_type == TAM_USTORE); @@ -829,24 +937,29 @@ static void TvUheapInsertLostImpl(Relation rel, Relation partRel, Partition p, } list_free(recheckIndexes); } - MemoryContextSwitchTo(oldcontext); + MemoryContextSwitchTo(oldcontext);//鍒囨崲鍥炰箣鍓嶇殑鍐呭瓨涓婁笅鏂 - ExecResetTupleTable(estate->es_tupleTable, false); + ExecResetTupleTable(estate->es_tupleTable, false);//閲嶇疆鎵ц鍣ㄧ殑鍏冪粍琛 - ExecCloseIndices(resultRelInfo); + ExecCloseIndices(resultRelInfo);//鍏抽棴鎵鏈夌殑绱㈠紩 /* free the fakeRelationCache */ if (estate->esfRelations != NULL) { FakeRelationCacheDestroy(estate->esfRelations); } - FreeExecutorState(estate); + FreeExecutorState(estate);//閲婃斁鎵ц鐘舵佸璞$殑璧勬簮 pfree(resultRelInfo); return; } - +/* + * 鍔熻兘锛氬湪缁欏畾鐨勫叧绯伙紙琛級涓彃鍏ヤ涪澶辩殑鍏冪粍銆 + * 鍙傛暟鍒楄〃锛 + * relid锛氳鎻掑叆鍏冪粍鐨勫叧绯伙紙琛級鐨勬爣璇嗙 + * snap锛氬揩鐓у璞 + */ void TvInsertLost(Oid relid, Snapshot snap) { Relation rel; @@ -864,10 +977,18 @@ void TvInsertLost(Oid relid, Snapshot snap) heap_close(rel, NoLock); return; } - +/* + * 鍔熻兘锛氱敤浜庡湪缁欏畾鐨勫叧绯伙紙琛級鎴栧叾鍒嗗尯涓彃鍏ヤ涪澶辩殑鍏冪粍銆 + * 鍙傛暟鍒楄〃锛 + * rel锛氬叧绯伙紙琛級鐨勬弿杩 + * partRel锛氬垎鍖哄叧绯伙紙琛級鐨勬弿杩 + * p锛氬垎鍖哄璞 + * snap锛氬揩鐓у璞 + */ void TvUheapInsertLostRel(Relation rel, Relation partRel, Partition p, Snapshot snap) { TableScanDesc sd; + //濡傛灉partRel涓篘ULL锛屽垯鍦ㄥ叧绯伙紙琛級涓婂紑濮嬫壂鎻忥紝鍚﹀垯鍦ㄥ垎鍖哄叧绯伙紙琛級涓婂紑濮嬫壂鎻 if (partRel == NULL) { sd = tableam_scan_begin(rel, snap, 0, NULL); } else { @@ -878,7 +999,13 @@ void TvUheapInsertLostRel(Relation rel, Relation partRel, Partition p, Snapshot tableam_scan_end(sd); return; } - +/* + * 鍔熻兘锛氱敤浜庡湪缁欏畾鐨勫垎鍖鸿〃鐨勬墍鏈夊垎鍖轰腑鎻掑叆涓㈠け鐨勫厓缁勩 + * 鍙傛暟鍒楄〃锛 + * rel锛氬叧绯伙紙琛級鐨勬弿杩 + * relid锛氬厓缁勭殑鍏崇郴锛堣〃锛夌殑鏍囪瘑绗 + * snap锛氬揩鐓у璞 + */ void TvUheapInsertLostPart(Relation rel, Oid relid, Snapshot snap) { List* partTupleList = NIL; @@ -898,20 +1025,29 @@ void TvUheapInsertLostPart(Relation rel, Oid relid, Snapshot snap) Partition p = partitionOpen(rel, partOid, AccessExclusiveLock); Relation partRel = partitionGetRelation(rel, p); - if (RelationIsSubPartitioned(rel)) { + if (RelationIsSubPartitioned(rel)) {//濡傛灉鍒嗗尯琛ㄥ瓨鍦ㄥ瓙鍒嗗尯 + //鑾峰彇鎵鏈夊瓙鍒嗗尯鍏冪粍鍒楄〃 List* subPartTupleList = searchPgPartitionByParentId(PART_OBJ_TYPE_TABLE_SUB_PARTITION, partOid); ListCell* subPartCell = NULL; + //閬嶅巻姣忎釜瀛愬垎鍖哄厓缁 foreach (subPartCell, subPartTupleList) { + //鑾峰彇瀛愬垎鍖哄厓缁勫拰鍏舵爣璇嗙 HeapTuple subTup = (HeapTuple)lfirst(subPartCell); Oid subPartOid = HeapTupleGetOid(subTup); + //鎵撳紑瀛愬垎鍖哄苟鑾峰彇瀛愬垎鍖虹殑鎻忚堪 Partition subPar = partitionOpen(partRel, subPartOid, AccessExclusiveLock); Relation subPartRel = partitionGetRelation(partRel, subPar); + //璋冪敤TvUheapInsertLostRel鍑芥暟鎻掑叆涓㈠け鐨勫厓缁勫埌瀛愬垎鍖轰腑 TvUheapInsertLostRel(rel, subPartRel, subPar, snap); + //閲婃斁瀛愬垎鍖虹殑鍏崇郴鎻忚堪 releaseDummyRelation(&subPartRel); + //鍏抽棴瀛愬垎鍖 partitionClose(partRel, subPar, AccessExclusiveLock); } + //閲婃斁瀛愬垎鍖哄厓缁勫垪琛ㄧ殑鍐呭瓨 freePartList(subPartTupleList); } else { + //璋冪敤TvUheapInsertLostRel鍑芥暟鎻掑叆涓㈠け鐨勫厓缁勫埌褰撳墠鍒嗗尯涓 TvUheapInsertLostRel(rel, partRel, p, snap); } releaseDummyRelation(&partRel); @@ -922,18 +1058,41 @@ void TvUheapInsertLostPart(Relation rel, Oid relid, Snapshot snap) } +/* + * 鍔熻兘锛氱敤浜庡皢鍘嗗彶鏁版嵁鎻掑叆 TimeCapsule 鐗堟湰琛 + * + * 鍙傛暟鍒楄〃锛 + * relid锛氳鎵ц杩樺師鐨勫叧绯伙紙琛級OID + * snap锛氱敤浜庤鍙栧巻鍙叉暟鎹殑蹇収 + */ void TvUheapInsertLost(Oid relid, Snapshot snap) { + // 鎵撳紑缁欏畾 OID 瀵瑰簲鐨勫叧绯昏〃锛屼笉鍔犱换浣曢攣 Relation rel = heap_open(relid, NoLock); + + // 妫鏌ュ叧绯绘槸鍚︽槸鍒嗗尯琛 if (RELATION_IS_PARTITIONED(rel)) { + // 濡傛灉鏄垎鍖鸿〃锛屽垯鎵ц TvUheapInsertLostPart 鍑芥暟锛屼负姣忎釜鍒嗗尯鎵ц鍘嗗彶鏁版嵁鎻掑叆鎿嶄綔 TvUheapInsertLostPart(rel, relid, snap); } else { + // 濡傛灉涓嶆槸鍒嗗尯琛紝鍒欐墽琛 TvUheapInsertLostRel 鍑芥暟锛屾墽琛屽巻鍙叉暟鎹彃鍏ユ搷浣 + // 姝ゅ鐨 NULL 鍙傛暟琛ㄧず娌℃湁鍒嗗尯鍏崇郴鍜屽垎鍖猴紝浠呴拡瀵规暣涓叧绯昏繘琛屾搷浣 TvUheapInsertLostRel(rel, NULL, NULL, snap); } + + // 鍏抽棴鎵撳紑鐨勫叧绯昏〃锛屼笉鍔犱换浣曢攣 heap_close(rel, NoLock); + + // 鍑芥暟缁撴潫锛岃繑鍥 return; } +/* + * 鍔熻兘锛氭鏌ユ槸鍚﹀厑璁歌繕鍘熺壒瀹氱増鏈紝骞舵墽琛岃繕鍘熸搷浣 + * + * 鍙傛暟鍒楄〃锛 + * rel锛氳杩樺師鐗堟湰鐨勫叧绯伙紙琛級瀵硅薄 + */ static void TvCheckVersionRestore(Relation rel) { char *errstr = NULL; @@ -956,7 +1115,12 @@ static void TvCheckVersionRestore(Relation rel) return; } - +/* + * 鍔熻兘锛氭墽琛岀増鏈繕鍘熸搷浣 + * + * 鍙傛暟鍒楄〃锛 + * stmt锛氭椂闂磋兌鍥婅鍙 + */ void TvRestoreVersion(TimeCapsuleStmt *stmt) { Relation rel; @@ -1001,4 +1165,3 @@ void TvRestoreVersion(TimeCapsuleStmt *stmt) return; } - diff --git a/src/gausskernel/storage/xlog_share_storage/xlog_share_storage.cpp b/src/gausskernel/storage/xlog_share_storage/xlog_share_storage.cpp index 0eb3b6429..df83a4ed2 100644 --- a/src/gausskernel/storage/xlog_share_storage/xlog_share_storage.cpp +++ b/src/gausskernel/storage/xlog_share_storage/xlog_share_storage.cpp @@ -37,7 +37,7 @@ #include "miscadmin.h" #include "pgstat.h" #include "replication/syncrep_gramparse.h" -#include "replication/walsender_private.h" +#include "replication/ walsender_private.h" #include "storage/ipc.h" #include "storage/dorado_operation/dorado_fd.h" #include "storage/xlog_share_storage/xlog_share_storage.h" @@ -53,33 +53,39 @@ const static uint32 CHECK_LOCK_INTERVAL = 0xFF; const static uint32 MAX_SIZE_CAN_COPY_TO_SHARE = 128 * 1024 * 1024; const static uint32 PTR_PRINT_SHIFT_SIZE = 32; - +// 杩欎釜鍑芥暟鏄敤鏉ュ鐞 SIGHUP 淇″彿鐨勩 +// 鍔熻兘鏄湪鎺ユ敹鍒 SIGHUP 淇″彿鏃讹紝璁剧疆涓涓爣蹇楁潵鎸囩ず宸茬粡鏀跺埌淇″彿锛屽苟灏濊瘯鍞ら啋杩涚▼銆 +// 浠ヤ究杩涚▼鍙互鍦ㄩ渶瑕佹椂鎵ц鐩稿簲鐨勬搷浣溿 static void SharedStorageXlogCopyBackendSigHupHandler(SIGNAL_ARGS) { - int save_errno = errno; + int save_errno = errno; // 淇濆瓨褰撳墠鐨勯敊璇俊鍙峰埌 save_errno 鍙橀噺銆 + // 鏀瑰彉鏍囧織琛ㄧず宸茬粡鏀跺埌浜 SIGHUP 淇″彿銆 t_thrd.sharestoragexlogcopyer_cxt.got_SIGHUP = true; + /* + *妫鏌ュ叏灞鍙橀噺 t_thrd.proc: + *濡傛灉涓嶄负绌猴紝灏辫皟鐢 SetLatch 鍑芥暟銆 + *璇ュ嚱鏁颁細瑙﹀彂璇ヨ繘绋嬬殑绛夊緟鏍囧織锛圠atch锛夛紝浠ヤ究鍦ㄩ渶瑕佺殑鏃跺欏敜閱掕繘绋嬫墽琛屼竴浜涙搷浣溿 + */ if (t_thrd.proc) { SetLatch(&t_thrd.proc->procLatch); } - errno = save_errno; + errno = save_errno; // 灏嗛敊璇俊鍙锋仮澶嶄负涔嬪墠淇濆瓨鐨勫笺 } - +// 鐢ㄦ潵澶勭悊鍏抽棴淇″彿,鍜 SharedStorageXlogCopyBackendSigHupHandler()鍑芥暟绫讳技 static void SharedStorageXlogCopyBackendShutdownHandler(SIGNAL_ARGS) { int save_errno = errno; - t_thrd.sharestoragexlogcopyer_cxt.shutdown_requested = true; - if (t_thrd.proc) SetLatch(&t_thrd.proc->procLatch); errno = save_errno; } - +// 鐢ㄤ簬蹇熺粓姝㈣繘绋嬬殑淇″彿澶勭悊鍑芥暟銆傚畠鐨勪富瑕佷綔鐢ㄦ槸閫鍑鸿繘绋嬶紝骞跺湪閫鍑轰箣鍓嶆墽琛屼竴浜涙竻鐞嗘搷浣溿 static void SharedStorageXlogCopyBackendQuickDie(SIGNAL_ARGS) { - gs_signal_setmask(&t_thrd.libpq_cxt.BlockSig, NULL); + gs_signal_setmask(&t_thrd.libpq_cxt.BlockSig, NULL); // 鐢ㄤ簬璁剧疆淇″彿鎺╃爜,涓轰簡闃叉鍦ㄩ鍑鸿繃绋嬩腑鍙楀埌鍏朵粬淇″彿鐨勫共鎵般 /* * We DO NOT want to run proc_exit() callbacks -- we're here because @@ -89,7 +95,7 @@ static void SharedStorageXlogCopyBackendQuickDie(SIGNAL_ARGS) * things by calling exit() directly, we have to reset the callbacks * explicitly to make this work as intended. */ - on_exit_reset(); + on_exit_reset(); // 涓轰簡閲嶇疆鍦ㄨ繘绋嬮鍑烘椂搴旇璋冪敤鐨勫洖璋冨嚱鏁帮紝浠ョ‘淇濅笉鎵ц浠讳綍宸叉敞鍐岀殑閫鍑哄洖璋冨嚱鏁般 /* * Note we do exit(2) not exit(0). This is to force the postmaster into a @@ -99,14 +105,16 @@ static void SharedStorageXlogCopyBackendQuickDie(SIGNAL_ARGS) * should ensure the postmaster sees this as a crash, too, but no harm in * being doubly sure.) */ - exit(2); + exit(2); // 璋冪敤 exit锛屼娇杩涚▼浠ョ姸鎬佺爜 2 缁堟銆 } - +// 鐢ㄤ簬澶勭悊 SigUsr1淇″彿鐨勪俊鍙峰鐞嗗嚱鏁般 static void SharedStorageXlogCopyBackendSigUsr1Handler(SIGNAL_ARGS) { + // 淇濆瓨褰撳墠鐨勯敊璇俊鍙峰埌 save_errno 鍙橀噺銆 + // 鐩殑鏄负浜嗗湪鍑芥暟鎵ц鏈熼棿涓嶅奖鍝嶅叾浠栭儴鍒嗗閿欒鍙风殑浣跨敤銆 int saveErrno = errno; - latch_sigusr1_handler(); + latch_sigusr1_handler(); // SetLatch浣跨敤SigUsr1鍞ら啋鍦╨atch涓婄瓑寰呯殑杩涚▼銆傚鏋滄垜浠湪绛夊緟锛屽敜閱 WaitLatch銆 errno = saveErrno; } @@ -117,29 +125,32 @@ void LocalXLogRead(char *buf, XLogRecPtr startptr, Size count) XLogRecPtr recptr; Size nbytes; - p = buf; - recptr = startptr; - nbytes = count; + p = buf; // 鎸囧悜缂撳啿鍖虹殑鎸囬拡 + recptr = startptr; // 褰撳墠鐨刉AL鏃ュ織鎸囬拡 + nbytes = count; // 瑕佽鍙栫殑瀛楄妭鏁 while (nbytes > 0) { uint32 startoff; int segbytes; int readbytes; - startoff = recptr % XLogSegSize; + startoff = recptr % XLogSegSize; // 璁$畻褰撳墠WAL鏃ュ織鎸囬拡鍦╔LOG娈靛唴鐨勫亸绉婚噺 /* Do we need to switch to a different xlog segment? */ - if (t_thrd.sharestoragexlogcopyer_cxt.readFile < 0 || - !XLByteInSeg(recptr, t_thrd.sharestoragexlogcopyer_cxt.readSegNo)) { + // 妫鏌ユ槸鍚﹂渶瑕佸垏鎹㈠埌涓嶅悓鐨刋LOG娈 + if (t_thrd.sharestoragexlogcopyer_cxt.readFile < + 0 || // 妫鏌ュ悕涓 readFile 鐨勬枃浠舵弿杩扮鏄惁涓鸿礋鍊硷紝浠庤屽垽鏂枃浠舵槸鍚﹀凡缁忓叧闂垨鏃犳晥銆 + !XLByteInSeg(recptr, t_thrd.sharestoragexlogcopyer_cxt + .readSegNo)) { // 鏉′欢鍒ゆ柇琛ㄨ揪寮忥紝鐢ㄤ簬妫鏌ョ粰瀹氱殑WAL鏃ュ織浣嶇疆鏄惁鍦ㄥ綋鍓嶇殑XLOG娈靛唴銆 char path[MAXPGPATH]; - + // 濡傛灉涔嬪墠鎵撳紑鐨勬枃浠舵弿杩扮鏈夋晥锛屽垯鍏抽棴瀹 if (t_thrd.sharestoragexlogcopyer_cxt.readFile >= 0) { (void)close(t_thrd.sharestoragexlogcopyer_cxt.readFile); } - + // 璁$畻鏂扮殑XLOG娈垫枃浠惰矾寰 XLByteToSeg(recptr, t_thrd.sharestoragexlogcopyer_cxt.readSegNo); XLogFilePath(path, MAXPGPATH, t_thrd.xlog_cxt.ThisTimeLineID, t_thrd.sharestoragexlogcopyer_cxt.readSegNo); - + // 鎵撳紑鏂扮殑XLOG娈垫枃浠惰繘琛岃鍙 t_thrd.sharestoragexlogcopyer_cxt.readFile = BasicOpenFile(path, O_RDONLY | PG_BINARY, 0); if (t_thrd.sharestoragexlogcopyer_cxt.readFile < 0) { /* @@ -147,24 +158,29 @@ void LocalXLogRead(char *buf, XLogRecPtr startptr, Size count) * asked for a too old WAL segment that has already been * removed or recycled. */ + // 濡傛灉鏂囦欢涓嶅瓨鍦紝鍙兘鏄洜涓鸿姹傜殑WAL娈靛凡琚垹闄ゆ垨鍥炴敹 if (errno == ENOENT) { ereport(ERROR, (errcode_for_file_access(), errmsg("requested WAL segment %s has already been removed", XLogFileNameP(t_thrd.xlog_cxt.ThisTimeLineID, t_thrd.sharestoragexlogcopyer_cxt.readSegNo)))); } else { + // 鎵撳紑鏂囦欢澶辫触锛屾姤鍛婇敊璇 ereport(ERROR, (errcode_for_file_access(), errmsg("could not open file \"%s\" (log segment %s): %m", path, XLogFileNameP(t_thrd.xlog_cxt.ThisTimeLineID, t_thrd.sharestoragexlogcopyer_cxt.readSegNo)))); } } - t_thrd.sharestoragexlogcopyer_cxt.readOff = 0; + t_thrd.sharestoragexlogcopyer_cxt.readOff = 0; // 閲嶇疆璇诲彇鍋忕Щ閲 } /* Need to seek in the file? */ + // 閲嶇疆璇诲彇鍋忕Щ閲 if (t_thrd.sharestoragexlogcopyer_cxt.readOff != startoff) { + // 瀹氫綅鍒版寚瀹氱殑鍋忕Щ閲 if (lseek(t_thrd.sharestoragexlogcopyer_cxt.readFile, (off_t)startoff, SEEK_SET) < 0) { + // 瀹氫綅澶辫触锛屽叧闂枃浠跺苟鎶ュ憡閿欒 (void)close(t_thrd.sharestoragexlogcopyer_cxt.readFile); t_thrd.sharestoragexlogcopyer_cxt.readFile = -1; ereport(ERROR, @@ -173,22 +189,27 @@ void LocalXLogRead(char *buf, XLogRecPtr startptr, Size count) t_thrd.sharestoragexlogcopyer_cxt.readSegNo), startoff))); } - t_thrd.sharestoragexlogcopyer_cxt.readOff = startoff; + t_thrd.sharestoragexlogcopyer_cxt.readOff = startoff; // 鏇存柊璇诲彇鍋忕Щ閲 } /* How many bytes are within this segment? */ + // 璁$畻鍦ㄥ綋鍓峏LOG娈典腑瑕佽鍙栫殑瀛楄妭鏁 if (nbytes > (XLogSegSize - startoff)) { segbytes = XLogSegSize - startoff; } else { segbytes = nbytes; } - + // 鎶ュ憡WAL璇诲彇绛夊緟浜嬩欢 pgstat_report_waitevent(WAIT_EVENT_WAL_READ); + // 浠庢枃浠朵腑璇诲彇鏁版嵁 readbytes = read(t_thrd.sharestoragexlogcopyer_cxt.readFile, p, segbytes); + // 鎶ュ憡WAL璇诲彇瀹屾垚浜嬩欢 pgstat_report_waitevent(WAIT_EVENT_END); + // 妫鏌ヨ鍙栨槸鍚﹀け璐 if (readbytes <= 0) { + // 璇诲彇澶辫触锛屽叧闂枃浠跺苟鎶ュ憡閿欒 (void)close(t_thrd.sharestoragexlogcopyer_cxt.readFile); - t_thrd.sharestoragexlogcopyer_cxt.readFile = -1; + t_thrd.sharestoragexlogcopyer_cxt.readFile = -1; // 鏍囧織璇诲彇澶辫触 ereport(ERROR, (errcode_for_file_access(), errmsg("could not read from log segment %s, offset %u, length %lu: %m", @@ -201,226 +222,284 @@ void LocalXLogRead(char *buf, XLogRecPtr startptr, Size count) t_thrd.sharestoragexlogcopyer_cxt.readOff += readbytes; nbytes -= readbytes; - p += readbytes; + p += readbytes; // 鏇存柊缂撳啿鍖烘寚閽 } } - +// 鐢ㄤ簬閫氱煡绛夊緟鍚屾鐨勫悗绔紙濡傛祦澶嶅埗鐨勪粠鑺傜偣锛夋湁鏂扮殑鏃ュ織浣嶇疆闇瑕佸悓姝ャ void NotifySyncWaiters(XLogRecPtr newPos) { - volatile WalSndCtlData *walsndctl = t_thrd.walsender_cxt.WalSndCtl; + volatile WalSndCtlData *walsndctl = t_thrd.walsender_cxt.WalSndCtl; + // 鑾峰彇鍚屾澶嶅埗閿佷互纭繚鍘熷瓙鎬у湴鏇存柊鍚屾绛夊緟鐘舵 (void)LWLockAcquire(SyncRepLock, LW_EXCLUSIVE); /* * Set the lsn first so that when we wake backends they will release up to * this location. + * 妫鏌ュ綋鍓嶄綅缃槸鍚﹀ぇ浜庣瓑寰呮帴鏀躲佺瓑寰呭啓鍏ュ拰绛夊緟鍒锋柊鐨凩SN锛 + * 濡傛灉鏄紝鍒欐洿鏂板搴旂殑LSN骞跺敜閱掔浉搴旂殑绛夊緟闃熷垪銆 */ + // 濡傛灉鏂颁綅缃ぇ浜庣瓑寰呮帴鏀剁殑LSN锛屽垯鏇存柊骞跺敜閱掔瓑寰呮帴鏀剁殑闃熷垪 if (XLByteLT(walsndctl->lsn[SYNC_REP_WAIT_RECEIVE], newPos)) { walsndctl->lsn[SYNC_REP_WAIT_RECEIVE] = newPos; (void)SyncRepWakeQueue(false, SYNC_REP_WAIT_RECEIVE); } + // 濡傛灉鏂颁綅缃ぇ浜庣瓑寰呭啓鍏ョ殑LSN锛屽垯鏇存柊骞跺敜閱掔瓑寰呭啓鍏ョ殑闃熷垪 if (XLByteLT(walsndctl->lsn[SYNC_REP_WAIT_WRITE], newPos)) { walsndctl->lsn[SYNC_REP_WAIT_WRITE] = newPos; (void)SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } + // 濡傛灉鏂颁綅缃ぇ浜庣瓑寰呭埛鏂扮殑LSN锛屽垯鏇存柊骞跺敜閱掔瓑寰呭埛鏂扮殑闃熷垪 if (XLByteLT(walsndctl->lsn[SYNC_REP_WAIT_FLUSH], newPos)) { walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = newPos; (void)SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - + // 閲婃斁鍚屾澶嶅埗閿 LWLockRelease(SyncRepLock); } - +/* + * 璇ュ嚱鏁扮敤浜庡皢鏂扮殑LSN淇℃伅鍐欏叆鍏变韩瀛樺偍锛岀‘淇濈浉鍏虫帶鍒朵俊鎭拰鏁版嵁鎸佷箙鍖栵紝 + * 骞堕氳繃鏃ュ織鍜岄氱煡鏈哄埗锛岀‘淇濆悓姝ョ瓑寰呯殑鍚庣鑳藉寰楃煡鏂扮殑LSN鍙敤锛屼粠鑰岃繘琛岀浉搴旂殑鍚屾鎿嶄綔銆 + */ void PushCtlLsn(XLogRecPtr flushPtr) { ShareStorageXLogCtl *sharestorageCtl = g_instance.xlog_cxt.shareStorageXLogCtl; + // 灏唂lushPtr璁剧疆涓哄叡浜瓨鍌╔Log鎺у埗缁撴瀯涓殑insertHead瀛楁銆 sharestorageCtl->insertHead = flushPtr; + // 濡傛灉insertHead鍜宨nsertTail涔嬮棿鐨勮窛绂诲ぇ浜巟logFileSize锛岃皟鏁磇nsertTail鐨勫 if ((sharestorageCtl->insertHead - sharestorageCtl->insertTail) > sharestorageCtl->xlogFileSize) { sharestorageCtl->insertTail = sharestorageCtl->insertHead - sharestorageCtl->xlogFileSize; } + // 璁$畻鍏变韩瀛樺偍XLog鎺у埗缁撴瀯鐨凜RC鏍¢獙鐮 sharestorageCtl->crc = CalShareStorageCtlInfoCrc(sharestorageCtl); + // 鏇存柊鍏变韩瀛樺偍XLog鎺у埗淇℃伅 UpdateShareStorageCtlInfo(sharestorageCtl); + // 灏哫LOG鏁版嵁鍒峰啓鍒板叡浜瓨鍌 FsyncXlogToShareStorage(); + // 鏍规嵁HaModuleDebug璁剧疆鏃ュ織绾у埆 int mode = u_sess->attr.attr_storage.HaModuleDebug ? LOG : DEBUG2; + // 浠ユ寚瀹氱殑鏃ュ織绾у埆杈撳嚭娑堟伅锛屾樉绀篿nsertHead鐨凩SN const uint32 shftSz = 32; ereport(mode, (errmsg("[PushCtlLsn]insertHead lsn %08X/%08X\n", (uint32)(flushPtr >> shftSz), (uint32)flushPtr))); + // 閫氱煡绛夊緟鍚屾鐨勫悗绔紝鏈夋柊鐨凩SN鍙敤 NotifySyncWaiters(flushPtr); } - +// 璇ュ嚱鏁扮敤浜庡湪缁欏畾鐨勭害鏉熶笅璁$畻瑕佸啓鍏ュ叡浜瓨鍌ㄧ殑瀹為檯鏁版嵁闀垮害锛 +// 纭繚鏁版嵁鍐欏叆鐨勪綅缃拰杈圭晫绗﹀悎鍧楀ぇ灏忓拰鍏变韩瀛樺偍缂撳啿鍖哄ぇ灏忕殑瑕佹眰銆 static inline int CalcWriteLen(XLogRecPtr startWrite, XLogRecPtr endPtr) { + // 纭繚startWrite鐨勫亸绉婚噺鏄疿LOG_BLCKSZ鐨勫嶆暟锛屽嵆璧峰浣嶇疆涓哄潡鐨勫紑濮嬶紝濡傛灉鏂█澶辫触锛屽氨浼氱粓姝㈢▼搴 Assert((startWrite % XLOG_BLCKSZ) == 0); + // 璁$畻瀵归綈鐨勫啓鍏ョ粨鏉熶綅缃紝浣垮叾涓嶴hareStorageBufSize瀵归綈 XLogRecPtr alignWriteEnd = startWrite - startWrite % ShareStorageBufSize + ShareStorageBufSize; + // 濡傛灉瀵归綈鍚庣殑鍐欏叆缁撴潫浣嶇疆澶т簬endPtr锛屾墽琛屼互涓嬫搷浣 if (alignWriteEnd > endPtr) { + // 浣跨敤TYPEALIGN璁$畻瀵归綈鐨勫疄闄呭啓鍏ョ粨鏉熶綅缃 XLogRecPtr ActualCopyEnd = TYPEALIGN(XLOG_BLCKSZ, endPtr); + // 璁$畻瑕佸啓鍏ョ殑鏁版嵁闀垮害锛屽苟灏嗗叾杞崲涓篿nt绫诲瀷杩斿洖 return static_cast(ActualCopyEnd - startWrite); } else { + // 濡傛灉瀵归綈鍚庣殑鍐欏叆缁撴潫浣嶇疆涓嶅ぇ浜巈ndPtr锛岃绠楄鍐欏叆鐨勬暟鎹暱搴︼紝骞跺皢鍏惰浆鎹负 int绫诲瀷杩斿洖 return static_cast(alignWriteEnd - startWrite); } } - +// 璇ュ嚱鏁扮敤浜庤幏鍙栧彲浠ヨ繘琛岃鍐欑殑鏈澶Log浣嶇疆銆 XLogRecPtr GetMaxPosCanOverWrite() { + // 濡傛灉涓嶅湪Postmaster杩涚▼涓紝鐩存帴杩斿洖鏈澶х殑XLog浣嶇疆 if (!IsUnderPostmaster) { return MAX_XLOG_REC_PTR; } - + // 鍒濆鍖栨渶澶у埛鏂颁綅缃负鏃犳晥浣嶇疆 XLogRecPtr maxFlush = InvalidXLogRecPtr; + // 閬嶅巻鎵鏈夌殑WAL鍙戦佽咃紝鎵惧埌鏈澶х殑鍒锋柊浣嶇疆 for (int i = 0; i < g_instance.attr.attr_storage.max_wal_senders; i++) { /* use volatile pointer to prevent code rearrangement */ volatile WalSnd *walsnd = &t_thrd.walsender_cxt.WalSndCtl->walsnds[i]; SpinLockAcquire(&walsnd->mutex); + // 濡傛灉WAL鍙戦佽呯殑杩涚▼ID涓嶄负0涓攑eer_role涓篠TANDBY_CLUSTER_MODE if (walsnd->pid != 0 && walsnd->peer_role == STANDBY_CLUSTER_MODE) { if (XLByteLT(maxFlush, walsnd->flush)) { - maxFlush = walsnd->flush; + maxFlush = walsnd->flush; // 鏇存柊鏈澶у埛鏂颁綅缃 } } SpinLockRelease(&walsnd->mutex); } - + // 濡傛灉娌℃湁鎵惧埌鏈夋晥鐨勫埛鏂颁綅缃紝杩斿洖鏈澶х殑XLog浣嶇疆 if (maxFlush == InvalidXLogRecPtr) { return MAX_XLOG_REC_PTR; } - + // 杩斿洖鍙繘琛岃鍐欑殑鏈澶т綅缃紝鍗硏log_file_size鍔犱笂鏈澶у埛鏂颁綅缃 return g_instance.attr.attr_storage.xlog_file_size + maxFlush; } - -void AddXLogPageHeader(char* buf, XLogRecPtr startWrite, int writeLen, XLogRecPtr endPtr) +// 璇ュ嚱鏁扮敤浜庣‘淇濆啓鍏ョ殑姣忎釜鏁版嵁鍧楅兘鏈夋纭殑XLog椤甸潰澶撮儴锛屼互渚垮湪鍚庣画鐨勬搷浣滀腑鑳藉姝g‘璇嗗埆鍜屽鐞嗗啓鍏ョ殑WAL鏁版嵁銆 +void AddXLogPageHeader(char *buf, XLogRecPtr startWrite, int writeLen, XLogRecPtr endPtr) { int offset = 0; - while (offset < writeLen) { + // 浣跨敤寰幆鍚戞瘡涓啓鍏ョ殑鍧楁坊鍔燲Log椤甸潰澶撮儴 + while (offset < writeLen) { + // 璁$畻褰撳墠鍋忕Щ澶勭殑XLog椤甸潰澶撮儴 XLogPageHeader xlogPageHeader = (XLogPageHeader)(buf + offset); + // 璁剧疆XLog椤甸潰澶撮儴鐨勬婚暱搴︿负XLOG_BLCKSZ锛堝嵆鍧楃殑澶у皬锛 xlogPageHeader->xlp_total_len = XLOG_BLCKSZ; + // 绉诲姩鍋忕Щ锛屽噯澶囧鐞嗕笅涓涓潡 offset += XLOG_BLCKSZ; } - + // 濡傛灉endPtr灏忎簬锛堜笉鍖呮嫭绛変簬锛塻tartWrite + writeLen锛岃〃绀哄啓鍏ョ殑鏁版嵁璺ㄨ秺浜嗕竴涓潡鐨勮竟鐣 if (XLByteLT(endPtr, startWrite + writeLen)) { + // 璁$畻璺ㄨ秺鐨勯儴鍒嗗湪鏈鍚庝竴涓潡涓殑闀垮害 XLogPageHeader xlogPageHeader = (XLogPageHeader)(buf + writeLen - XLOG_BLCKSZ); + // 璁剧疆鏈鍚庝竴涓潡涓璛Log椤甸潰澶撮儴鐨勬婚暱搴︼紝浠ョ‘淇濅笉瓒呰繃鍐欏叆鐨勬暟鎹殑杈圭晫 xlogPageHeader->xlp_total_len = endPtr % XLOG_BLCKSZ; } } - +// 璇ュ嚱鏁扮敤浜庢墽琛孹Log鏁版嵁鐨勬嫹璐濇搷浣 void DoXlogCopy(XLogRecPtr targetPtr) { uint64 writeLength = 0; ShareStorageXLogCtl *sharestorageCtl = g_instance.xlog_cxt.shareStorageXLogCtl; + // 鏂█鐩爣浣嶇疆鏈夋晥 Assert(targetPtr != InvalidXLogRecPtr); + // 濡傛灉鐩爣浣嶇疆灏忎簬绛変簬褰撳墠鎻掑叆澶翠綅缃紝鏃犻渶杩涜XLog鎷疯礉 if (XLByteLE(targetPtr, sharestorageCtl->insertHead)) { return; } - + // 璁$畻璧峰鍐欏叆浣嶇疆锛堟暣鍧楀榻愶級 XLogRecPtr startWrite = sharestorageCtl->insertHead - (sharestorageCtl->insertHead % XLOG_BLCKSZ); + // 寰幆杩涜XLog鎷疯礉 while (XLByteLT(startWrite, targetPtr)) { + // 璁$畻鏈鍐欏叆鐨勯暱搴 int writeLen = CalcWriteLen(startWrite, targetPtr); + // 浠庢湰鍦癤Log涓鍙栨暟鎹 LocalXLogRead(t_thrd.sharestoragexlogcopyer_cxt.buf, startWrite, static_cast(writeLen)); + // 涓哄啓鍏ユ暟鎹潡娣诲姞XLog椤甸潰澶撮儴 AddXLogPageHeader(t_thrd.sharestoragexlogcopyer_cxt.buf, startWrite, writeLen, targetPtr); + // 灏嗘暟鎹潡鍐欏叆鍏变韩瀛樺偍 (void)WriteXlogToShareStorage(startWrite, t_thrd.sharestoragexlogcopyer_cxt.buf, writeLen); + // 鏇存柊璧峰鍐欏叆浣嶇疆锛屽苟绱鍐欏叆闀垮害 startWrite += writeLen; writeLength += writeLen; + // 濡傛灉绱鍐欏叆闀垮害杈惧埌浜嗕竴涓猉Log娈电殑澶у皬锛屾垨鑰呯洰鏍囦綅缃皬浜庤捣濮嬪啓鍏ヤ綅缃紝鎺ㄨ繘鎺у埗LSN骞堕噸缃疮璁″啓鍏ラ暱搴 if ((writeLength >= XLogSegSize) || (XLByteLT(targetPtr, startWrite))) { PushCtlLsn(XLByteLE(startWrite, targetPtr) ? startWrite : targetPtr); writeLength = 0; } } - + // 鏈鍚庡鏋滆繕鏈夋湭鎺ㄨ繘鐨凩SN锛岃繘琛屾帹杩 if (writeLength > 0) { PushCtlLsn(targetPtr); } } - +// 鑾峰彇閿 static bool GetLock() { + // 濡傛灉XLog閿佹枃浠惰矾寰勪负NULL锛岃〃绀烘棤闇鑾峰彇閿侊紝鐩存帴杩斿洖鎴愬姛 if (g_instance.attr.attr_storage.xlog_lock_file_path == NULL) { return true; } - + // 灏濊瘯鑾峰彇NAS鍐欓攣锛屽鏋滄垚鍔熻幏鍙栭攣鍒欒繑鍥炴垚鍔 if (LockNasWriteFile(g_instance.xlog_cxt.shareStorageLockFd)) { return true; } + // 濡傛灉鑾峰彇閿佸け璐ワ紝鎶ュ憡鑷村懡閿欒锛屾寚鏄庢棤娉曢攣瀹歑Log閿佹枃浠 ereport(FATAL, (errmsg("could not lock lock file(%d) %s", g_instance.xlog_cxt.shareStorageLockFd, - g_instance.attr.attr_storage.xlog_lock_file_path))); + g_instance.attr.attr_storage.xlog_lock_file_path))); return false; } - +// 閲婃斁閿 static bool ReleaseLock() { + // 濡傛灉XLog閿佹枃浠惰矾寰勪负NULL锛岃〃绀烘棤闇閲婃斁閿侊紝鐩存帴杩斿洖鎴愬姛 if (g_instance.attr.attr_storage.xlog_lock_file_path == NULL) { return true; } - + // 灏濊瘯閲婃斁NAS鍐欓攣锛屽鏋滄垚鍔熼噴鏀鹃攣鍒欒繑鍥炴垚鍔 if (UnlockNasWriteFile(g_instance.xlog_cxt.shareStorageLockFd)) { return true; } - + // 濡傛灉閲婃斁閿佸け璐ワ紝鎶ュ憡鑷村懡閿欒锛屾寚鏄庢棤娉曡В閿乆Log閿佹枃浠 ereport(FATAL, (errmsg("could not unlock lock file(%d) %s", g_instance.xlog_cxt.shareStorageLockFd, - g_instance.attr.attr_storage.xlog_lock_file_path))); + g_instance.attr.attr_storage.xlog_lock_file_path))); return false; } - +// 妫鏌ュ苟鎷疯礉XLog鏁版嵁 bool CheckAndCopyXLog(bool forceCopy) { ShareStorageXLogCtl *sharestorageCtl = g_instance.xlog_cxt.shareStorageXLogCtl; do { XLogRecPtr localFlush = InvalidXLogRecPtr; + // 濡傛灉褰撳墠涓轰富澶囨ā寮忥紝鑾峰彇涓诲鍚屾浣嶇疆锛屽惁鍒欒幏鍙栨湰鍦板埛鍐欎綅缃 if (IS_SHARED_STORAGE_MAIN_STANDBY_MODE) { localFlush = GetFlushMainStandby(); } else { localFlush = GetFlushRecPtr(); } + // 濡傛灉鏈湴鍒峰啓浣嶇疆灏忎簬绛変簬鍏变韩瀛樺偍涓彃鍏ヤ綅缃紝琛ㄧず鏃犻渶鎷疯礉 if (XLByteLE(localFlush, sharestorageCtl->insertHead)) { return true; } - + // 鑾峰彇鍙互瑕嗗啓鐨勬渶澶т綅缃 XLogRecPtr maxPosCanWrite = GetMaxPosCanOverWrite(); + // 濡傛灉鍏变韩瀛樺偍鎻掑叆浣嶇疆灏忎簬鏈澶у彲瑕嗗啓浣嶇疆锛岃繘琛孹Log鎷疯礉 if (XLByteLT(sharestorageCtl->insertHead, maxPosCanWrite)) { + // 璁$畻鏈熸湜鐨勬嫹璐濅綅缃紝涓烘湰鍦板埛鍐欎綅缃笌鏈澶у彲瑕嗗啓浣嶇疆涓緝灏忕殑鍊 XLogRecPtr expectPos = XLByteLT(localFlush, maxPosCanWrite) ? localFlush : maxPosCanWrite; + // 璁$畻鏈熸湜鐨勬嫹璐濅綅缃紝涓烘湰鍦板埛鍐欎綅缃笌鏈澶у彲瑕嗗啓浣嶇疆涓緝灏忕殑鍊 if ((expectPos - sharestorageCtl->insertHead) > MAX_SIZE_CAN_COPY_TO_SHARE) { expectPos = sharestorageCtl->insertHead + MAX_SIZE_CAN_COPY_TO_SHARE; } + // 鎵цXLog鏁版嵁鎷疯礉 DoXlogCopy(expectPos); } } while (forceCopy && GetLock()); - return false; + return false; // 杩斿洖false琛ㄧず鏈垚鍔熸墽琛屾嫹璐 } - +// 璇ュ嚱鏁扮敤浜庡叧闂叡浜瓨鍌ㄧ殑XLog鎷疯礉鎿嶄綔 void ShutdownShareStorageXLogCopy() { + // 濡傛灉鏈厤缃甔Log鏂囦欢璺緞锛岀洿鎺ヨ繑鍥 if (g_instance.attr.attr_storage.xlog_file_path == NULL) { return; } - + // 鍒嗛厤鍜屽垵濮嬪寲鎷疯礉缂撳啿鍖 if (t_thrd.sharestoragexlogcopyer_cxt.originBuf == NULL) { t_thrd.sharestoragexlogcopyer_cxt.originBuf = (char *)palloc(ShareStorageBufSize + g_instance.xlog_cxt.shareStorageopCtl.blkSize); t_thrd.sharestoragexlogcopyer_cxt.buf = (char *)TYPEALIGN(g_instance.xlog_cxt.shareStorageopCtl.blkSize, t_thrd.sharestoragexlogcopyer_cxt.originBuf); } - + // 璇诲彇鍏变韩瀛樺偍鎺у埗淇℃伅骞舵墽琛孹Log鎷疯礉 ReadShareStorageCtlInfo(g_instance.xlog_cxt.shareStorageXLogCtl); CheckAndCopyXLog(true); + // 濡傛灉璇诲彇鏂囦欢鎻忚堪绗︽湁鏁堬紝鍏抽棴鏂囦欢 if (t_thrd.sharestoragexlogcopyer_cxt.readFile >= 0) { (void)close(t_thrd.sharestoragexlogcopyer_cxt.readFile); } - + // 閲婃斁鎷疯礉缂撳啿鍖虹殑鍐呭瓨 if (t_thrd.sharestoragexlogcopyer_cxt.originBuf != NULL) { pfree(t_thrd.sharestoragexlogcopyer_cxt.originBuf); t_thrd.sharestoragexlogcopyer_cxt.originBuf = NULL; t_thrd.sharestoragexlogcopyer_cxt.buf = NULL; } - + // 娓呴櫎鐩稿叧鐨凩atch鍜屾爣蹇 g_instance.proc_base->ShareStoragexlogCopyerLatch = NULL; + // 鎵撳嵃鏃ュ織锛岃〃绀篨Log鎷疯礉宸插仠姝 ereport(LOG, (errmsg("stopped xlog copy at %X/%X", - (uint32)(g_instance.xlog_cxt.shareStorageXLogCtl->insertHead >> PTR_PRINT_SHIFT_SIZE), - (uint32)g_instance.xlog_cxt.shareStorageXLogCtl->insertHead))); + (uint32)(g_instance.xlog_cxt.shareStorageXLogCtl->insertHead >> PTR_PRINT_SHIFT_SIZE), + (uint32)g_instance.xlog_cxt.shareStorageXLogCtl->insertHead))); } - +// 璇ュ嚱鏁扮敤浜庢鏌ユ枃浠跺ぇ灏忔槸鍚﹀彲浠ユ洿鏂 bool FileSizeCanUpdate() { + // 鑾峰彇缁撴潫妫鏌ョ偣鐨勪綅缃 XLogRecPtr endCheckpointPtr = sizeof(CheckPointPlus) + t_thrd.shemem_ptr_cxt.ControlFile->checkPoint; + // 鑾峰彇鍏变韩瀛樺偍鎺у埗淇℃伅 ShareStorageXLogCtl *ctlInfo = g_instance.xlog_cxt.shareStorageXLogCtl; + // 璁$畻妫鏌ョ偣浣嶇疆鍜屾彃鍏ヤ綅缃殑鍋忕Щ閲 uint64 checkpointPos = endCheckpointPtr % ctlInfo->xlogFileSize; uint64 headPos = ctlInfo->insertHead % ctlInfo->xlogFileSize; + // 濡傛灉婊¤冻涓瀹氭潯浠讹紝杩斿洖true琛ㄧず鏂囦欢澶у皬鍙互鏇存柊锛屽惁鍒欒繑鍥瀎alse if ((XLByteLE(endCheckpointPtr, ctlInfo->insertHead) && checkpointPos <= headPos) || XLByteLT(ctlInfo->insertHead, endCheckpointPtr)) { return true; @@ -428,32 +507,37 @@ bool FileSizeCanUpdate() return false; } - +// 璇ュ嚱鏁扮敤浜庢鏌ュ叡浜瓨鍌ㄦ帶鍒朵俊鎭 void CheckShareStorageCtlInfo(XLogRecPtr localEnd) { + // 濡傛灉涓嶅浜庡叡浜瓨鍌ㄦā寮忥紝鐩存帴杩斿洖 if (!IS_SHARED_STORAGE_MODE) { return; } - + // 鑾峰彇鍏变韩瀛樺偍鐨勬帶鍒朵俊鎭 ShareStorageXLogCtl *ctlInfo = g_instance.xlog_cxt.shareStorageXLogCtl; ReadShareStorageCtlInfo(ctlInfo); - + // 妫鏌ョ郴缁熸爣璇嗘槸鍚︿竴鑷达紝涓嶄竴鑷存椂鎶ラ敊 if (ctlInfo->systemIdentifier != GetSystemIdentifier()) { ereport(FATAL, (errmsg("database system version is different between shared storage %lu and local %lu", ctlInfo->systemIdentifier, GetSystemIdentifier()))); } - + // 鍒濆鍖 uint32 shiftSize = 32; - XLogRecPtr shareStorageLatestRecordStart = InvalidXLogRecPtr; + XLogRecPtr shareStorageLatestRecordStart = InvalidXLogRecPtr; // 鍒濆鍖栦负鏃犳晥鐨勪綅缃 int shareStorageLatestRecordLen; pg_crc32 shareStorageLatestRecordCrc; + // 鍦ㄥ叡浜瓨鍌ㄤ腑鏌ユ壘鏈鍚庝竴涓褰曠殑淇℃伅 FindLastRecordCheckInfoOnShareStorage(&shareStorageLatestRecordStart, &shareStorageLatestRecordCrc, &shareStorageLatestRecordLen); - + // 鏂█鍏变韩瀛樺偍鏈鏂拌褰曠殑璧峰浣嶇疆鍔犻暱搴﹀皬浜庣瓑浜庢彃鍏ヤ綅缃紝纭繚鍏变韩瀛樺偍鏁版嵁姝g‘鎬 Assert(XLByteLE(shareStorageLatestRecordStart + shareStorageLatestRecordLen, ctlInfo->insertHead)); + // 濡傛灉鏈湴鐨勭粨鏉熶綅缃皬浜庡叡浜瓨鍌ㄧ殑鎻掑叆浣嶇疆 if (XLByteLT(localEnd, ctlInfo->insertHead)) { + // 濡傛灉鍏变韩瀛樺偍鏈鏂拌褰曠殑璧峰浣嶇疆鏄棤鏁堢殑锛屾垨鑰呮湰鍦扮殑缁撴潫浣嶇疆鍜屾渶鏂拌褰曠殑璧峰浣嶇疆鍔犲榻愰暱搴︿笉涓鑷 if (XLByteEQ(shareStorageLatestRecordStart, InvalidXLogRecPtr) || !XLByteEQ(localEnd, shareStorageLatestRecordStart + MAXALIGN(shareStorageLatestRecordLen))) { + // 鎶ラ敊锛岃〃绀烘湰鍦板ご閮ㄥ皬浜庡叡浜瓨鍌ㄥご閮 ereport(FATAL, (errmsg("the local's head is smaller than The shared storage's head"), errdetail("The shared storage's head %X/%X, the local's head is %X/%X. " "lastrecord on share storage: startlsn:%X/%X crc %u, len %d", @@ -465,10 +549,12 @@ void CheckShareStorageCtlInfo(XLogRecPtr localEnd) shareStorageLatestRecordLen))); } + // 鎵撳嵃鏃ュ織锛岃〃绀轰慨鏀瑰叡浜瓨鍌ㄥご閮 ereport(LOG, (errmsg("modify share storage head from %X/%X to %X/%X", static_cast(ctlInfo->insertHead >> shiftSize), static_cast(ctlInfo->insertHead), static_cast(localEnd >> shiftSize), static_cast(localEnd)))); + // 淇敼鍏变韩瀛樺偍鎺у埗淇℃伅鐨勬彃鍏ヤ綅缃拰CRC锛岀劧鍚庡埛鏂板埌鍏变韩瀛樺偍 ctlInfo->insertHead = localEnd; ctlInfo->crc = CalShareStorageCtlInfoCrc(ctlInfo); UpdateShareStorageCtlInfo(ctlInfo); @@ -476,10 +562,12 @@ void CheckShareStorageCtlInfo(XLogRecPtr localEnd) } else { char path[MAXPGPATH]; XLogSegNo sendSegNo; + // 灏嗘彃鍏ヤ綅缃浆鎹负XLog娈靛彿锛屽苟鑾峰彇璺緞 XLByteToSeg(ctlInfo->insertHead, sendSegNo); XLogFilePath(path, MAXPGPATH, t_thrd.xlog_cxt.ThisTimeLineID, sendSegNo); struct stat stat_buf; + // 濡傛灉璺緞瀵瑰簲鐨勬枃浠朵笉瀛樺湪锛屾姤閿欙紝琛ㄧず鏈湴灏鹃儴澶т簬鍏变韩瀛樺偍澶撮儴 if (stat(path, &stat_buf) != 0) { ereport(FATAL, (errmsg("the local's tail is bigger than The shared storage's head %X/%X", static_cast(ctlInfo->insertHead >> shiftSize), @@ -488,7 +576,9 @@ void CheckShareStorageCtlInfo(XLogRecPtr localEnd) bool crcValid = false; + // 鑾峰彇鍏变韩瀛樺偍鏈鏂拌褰曠殑CRC鏍¢獙鍊硷紝鐢ㄤ簬姣旇緝鏈湴璁板綍鐨勬牎楠屽 pg_crc32 localCheckCrc = GetXlogRecordCrc(shareStorageLatestRecordStart, crcValid, XLogPageRead, 0); + // 濡傛灉鏍¢獙鍊间笉鍖归厤锛屾姤閿欙紝琛ㄧず鍏变韩瀛樺偍璇锋眰鐨凩SN鐨 if (shareStorageLatestRecordCrc != localCheckCrc) { ereport(FATAL, (errmsg("shared storage request lsn[%X/%X]'s crc mismatched (share, local):[%u,%u].", static_cast(shareStorageLatestRecordStart >> shiftSize), @@ -497,8 +587,8 @@ void CheckShareStorageCtlInfo(XLogRecPtr localEnd) } } - uint32 localTerm = Max(g_instance.comm_cxt.localinfo_cxt.term_from_file, - g_instance.comm_cxt.localinfo_cxt.term_from_xlog); + uint32 localTerm = + Max(g_instance.comm_cxt.localinfo_cxt.term_from_file, g_instance.comm_cxt.localinfo_cxt.term_from_xlog); if (localTerm > ctlInfo->term) { ctlInfo->term = localTerm; ctlInfo->crc = CalShareStorageCtlInfoCrc(ctlInfo); @@ -506,48 +596,55 @@ void CheckShareStorageCtlInfo(XLogRecPtr localEnd) FsyncXlogToShareStorage(); } } - +// 鏇存柊鍏变韩瀛樺偍鎺у埗淇℃伅 void UpdateShareStorageCtlInfo() { bool changed = false; ShareStorageXLogCtl *ctlInfo = g_instance.xlog_cxt.shareStorageXLogCtl; ReadShareStorageCtlInfo(ctlInfo); + // 妫鏌ョ増鏈彿鏄惁涓鑷达紝濡傛灉涓嶄竴鑷村垯鏇存柊鐗堟湰鍙凤紝骞惰缃甤hanged鏍囧織涓簍rue if (ctlInfo->version != CURRENT_SHARE_STORAGE_CTL_VERSION) { ctlInfo->version = CURRENT_SHARE_STORAGE_CTL_VERSION; changed = true; } + // 妫鏌ラ暱搴︽槸鍚︿竴鑷达紝濡傛灉涓嶄竴鑷村垯鏇存柊闀垮害锛屽苟璁剧疆changed鏍囧織涓簍rue if (ctlInfo->length != SizeOfShareStorageXLogCtl) { ctlInfo->length = SizeOfShareStorageXLogCtl; changed = true; } + // 妫鏌log鏂囦欢澶у皬鏄惁涓鑷达紝濡傛灉涓嶄竴鑷村垯鏇存柊xlog鏂囦欢澶у皬锛屽苟璁剧疆changed鏍囧織涓簍rue if (ctlInfo->xlogFileSize != (uint64)g_instance.attr.attr_storage.xlog_file_size) { Assert(g_instance.xlog_cxt.shareStorageopCtl.xlogFileSize == ctlInfo->xlogFileSize); + // 濡傛灉鏂囦欢澶у皬鏃犳硶鏇存柊锛屾姤閿 if (!FileSizeCanUpdate()) { ereport(FATAL, (errmsg("could not update share storage size."), errdetail("current size:%lu, new size:%lu", ctlInfo->xlogFileSize, g_instance.attr.attr_storage.xlog_file_size))); } + // 鏇存柊鍏变韩瀛樺偍鎿嶄綔鎺у埗涓殑xlog鏂囦欢澶у皬锛屽苟灏嗘帶鍒朵俊鎭腑鐨剎log鏂囦欢澶у皬璁剧疆涓烘柊鍊 g_instance.xlog_cxt.shareStorageopCtl.xlogFileSize = g_instance.attr.attr_storage.xlog_file_size; ctlInfo->xlogFileSize = g_instance.xlog_cxt.shareStorageopCtl.xlogFileSize; changed = true; } + // 濡傛灉鏈夋洿鏂帮紝鍒欓噸鏂拌绠桟RC鏍¢獙鍊硷紝鐒跺悗鏇存柊鎺у埗淇℃伅 if (changed) { ctlInfo->crc = CalShareStorageCtlInfoCrc(ctlInfo); UpdateShareStorageCtlInfo(ctlInfo); } } - +// 鍏变韩瀛樺偍XLog澶嶅埗鍚庡彴閫鍑哄強娓呯悊鍑芥暟 static void SharedStorageXlogCopyBackendQuitAndClean(int code, Datum arg) { + // 鎵撳嵃鏃ュ織锛岃〃绀鸿В閿佹枃浠 ereport(LOG, (errmsg("SharedStorageXlogCopyBackendMain unlock file(%d) %s", g_instance.xlog_cxt.shareStorageLockFd, - g_instance.attr.attr_storage.xlog_lock_file_path))); - ReleaseLock(); + g_instance.attr.attr_storage.xlog_lock_file_path))); + ReleaseLock(); // 閲婃斁閿 } - +// 杩欐浠g爜鐨勭洰鐨勬槸纭繚绾跨▼鑳藉姝g‘鍦板搷搴斿悇绉嶇郴缁熷拰鑷畾涔夌殑淇″彿锛屼互淇濊瘉绋嬪簭鐨勭ǔ瀹氳繍琛屽拰姝g‘閫鍑恒 static void InitThreadSignal() { (void)gspqsignal(SIGHUP, SharedStorageXlogCopyBackendSigHupHandler); /* reload config file */ @@ -570,31 +667,37 @@ static void InitThreadSignal() gs_signal_setmask(&t_thrd.libpq_cxt.UnBlockSig, NULL); (void)gs_signal_unblock_sigusr2(); } - +// 璇ュ嚱鏁颁富瑕佺敤浜庡湪鍚庡彴杩涚▼涓墽琛屽叡浜瓨鍌ㄧ殑 XLog 澶嶅埗鎿嶄綔 void SharedStorageXlogCopyBackendMain(void) { + // 鍒濆鍖栫嚎绋嬩俊鍙峰鐞 InitThreadSignal(); + if (IS_SHARED_STORAGE_MAIN_STANDBY_MODE) { + // 妫鏌ュ叡浜瓨鍌ㄧ殑鍐欓攣鏄惁宸茬粡鑾峰彇锛屽鏋滄病鏈夎幏鍙栧埌鍐欓攣锛屽垯浼氬皾璇曡幏鍙栧啓閿併 CheckShareStorageWriteLock(); } + // 濡傛灉澶勪簬鎭㈠鐘舵佷笖涓嶆槸涓-澶囨ā寮忥紝璁板綍涓鏉℃棩蹇楀苟閫鍑 if (RecoveryInProgress() && !IS_SHARED_STORAGE_MAIN_STANDBY_MODE) { ereport(LOG, (errmsg("stopped xlog copy in recovery"))); proc_exit(0); /* done */ } - + // 娉ㄥ唽杩涚▼閫鍑烘椂鐨勬竻鐞嗗嚱鏁 on_proc_exit(SharedStorageXlogCopyBackendQuitAndClean, 0); - + // 璁剧疆杩涚▼ latch锛岀敤浜庢爣璇嗚繘绋嬫椿鍔 g_instance.proc_base->ShareStoragexlogCopyerLatch = &t_thrd.proc->procLatch; - + // 鍒嗛厤鐢ㄤ簬澶嶅埗 XLog 鏁版嵁鐨勭紦鍐插尯 t_thrd.sharestoragexlogcopyer_cxt.originBuf = (char *)palloc(ShareStorageBufSize + g_instance.xlog_cxt.shareStorageopCtl.blkSize); - t_thrd.sharestoragexlogcopyer_cxt.buf = (char *)TYPEALIGN(g_instance.xlog_cxt.shareStorageopCtl.blkSize, - t_thrd.sharestoragexlogcopyer_cxt.originBuf); + t_thrd.sharestoragexlogcopyer_cxt.buf = + (char *)TYPEALIGN(g_instance.xlog_cxt.shareStorageopCtl.blkSize, t_thrd.sharestoragexlogcopyer_cxt.originBuf); + // 鏇存柊鍏变韩瀛樺偍鎺у埗淇℃伅 UpdateShareStorageCtlInfo(); + // 璁板綍 XLog 澶嶅埗鎿嶄綔鐨勫紑濮 ereport(LOG, (errmsg("start xlog copy at %X/%X", - (uint32)(g_instance.xlog_cxt.shareStorageXLogCtl->insertHead >> PTR_PRINT_SHIFT_SIZE), - (uint32)g_instance.xlog_cxt.shareStorageXLogCtl->insertHead))); - + (uint32)(g_instance.xlog_cxt.shareStorageXLogCtl->insertHead >> PTR_PRINT_SHIFT_SIZE), + (uint32)g_instance.xlog_cxt.shareStorageXLogCtl->insertHead))); + // 鏍规嵁妯″紡纭畾褰撳墠鏃堕棿绾 ID if (IS_SHARED_STORAGE_MAIN_STANDBY_MODE) { t_thrd.xlog_cxt.ThisTimeLineID = GetRecoveryTargetTLI(); } else { @@ -604,47 +707,54 @@ void SharedStorageXlogCopyBackendMain(void) uint64 checkLockCount = 0; pgstat_report_activity(STATE_IDLE, NULL); + // 涓诲惊鐜紝澶勭悊 XLog 澶嶅埗鍜屽悗鍙版椿鍔 for (;;) { ResetLatch(&t_thrd.proc->procLatch); pgstat_report_activity(STATE_RUNNING, NULL); - + // 姣忔寰幆瀹氭湡妫鏌ュ苟鑾峰彇閿 ++checkLockCount; if (checkLockCount & CHECK_LOCK_INTERVAL) { GetLock(); } + // 妫鏌ユ槸鍚︽湁鍏抽棴璇锋眰锛屽鏋滄湁锛屾墽琛岀浉鍏虫竻鐞嗘搷浣滃苟閫鍑 if (t_thrd.sharestoragexlogcopyer_cxt.shutdown_requested) { t_thrd.sharestoragexlogcopyer_cxt.shutdown_requested = false; g_instance.proc_base->ShareStoragexlogCopyerLatch = NULL; ShutdownShareStorageXLogCopy(); - proc_exit(0); /* done */ + proc_exit(0); /*缁堟褰撳墠杩涚▼鎴栫嚎绋*/ } + // 妫鏌ユ槸鍚︽敹鍒 SIGHUP 淇″彿锛屽鏋滄槸锛岄噸鏂板姞杞介厤缃枃浠 if (t_thrd.sharestoragexlogcopyer_cxt.got_SIGHUP) { t_thrd.sharestoragexlogcopyer_cxt.got_SIGHUP = false; ProcessConfigFile(PGC_SIGHUP); } + // 妫鏌ュ苟澶嶅埗 XLog 鏁版嵁锛屽鏋滈渶瑕佺瓑寰呭垯缁х画涓嬩竴娆″惊鐜 bool waitCopy = CheckAndCopyXLog(false); if (waitCopy) { continue; } + // 鎶ュ憡杩涚▼鐘舵佷负绌洪棽骞剁瓑寰呮椿鍔 pgstat_report_activity(STATE_IDLE, NULL); const long sleepTime = 1000L; (void)WaitLatch(&t_thrd.proc->procLatch, WL_LATCH_SET | WL_TIMEOUT | WL_POSTMASTER_DEATH, sleepTime); } + // 娓呯悊鎿嶄綔骞堕鍑鸿繘绋 g_instance.proc_base->ShareStoragexlogCopyerLatch = NULL; ereport(LOG, (errmsg("stopped xlog copy at %X/%X", - (uint32)(g_instance.xlog_cxt.shareStorageXLogCtl->insertHead >> PTR_PRINT_SHIFT_SIZE), - (uint32)g_instance.xlog_cxt.shareStorageXLogCtl->insertHead))); + (uint32)(g_instance.xlog_cxt.shareStorageXLogCtl->insertHead >> PTR_PRINT_SHIFT_SIZE), + (uint32)g_instance.xlog_cxt.shareStorageXLogCtl->insertHead))); proc_exit(0); } - +// 姝ゅ嚱鏁扮殑浣滅敤鏄敜閱掑悕涓 XLogCopyerBackend 鐨勫悗鍙扮嚎绋嬨 void WakeUpXLogCopyerBackend() { if (g_instance.proc_base->ShareStoragexlogCopyerLatch != NULL) { + // 鐢ㄤ簬灏嗛棭閿佽缃负婵娲荤姸鎬侊紝浠庤屽敜閱掔瓑寰呬腑鐨 XLogCopyerBackend 绾跨▼缁х画鎵ц銆 SetLatch(g_instance.proc_base->ShareStoragexlogCopyerLatch); } } @@ -714,8 +824,8 @@ bool XLogOverwriteFromLocal(bool force) ReadShareStorageCtlInfo(ctlInfo); if (ctlInfo->systemIdentifier != GetSystemIdentifier()) { ereport(WARNING, (errmsg("database system version is different between shared storage and local"), - errdetail("The shared storage's system version is %lu, the local's system version is %lu.", - ctlInfo->systemIdentifier, GetSystemIdentifier()))); + errdetail("The shared storage's system version is %lu, the local's system version is %lu.", + ctlInfo->systemIdentifier, GetSystemIdentifier()))); if (!force) { return false; } @@ -826,8 +936,8 @@ static bool XLogCopyWrite(char *buf, int nbytes, XLogRecPtr recptr) if (copyFile >= 0) { if (close(copyFile) != 0) { - ereport(WARNING, (errcode_for_file_access(), - errmsg("could not close log file %s: %m", XLogFileNameP(copyFileTLI, copySegNo)))); + ereport(WARNING, (errcode_for_file_access(), errmsg("could not close log file %s: %m", + XLogFileNameP(copyFileTLI, copySegNo)))); return false; } } @@ -852,7 +962,7 @@ static bool XLogCopyWrite(char *buf, int nbytes, XLogRecPtr recptr) if (copyOff != (uint32)startoff) { if (lseek(copyFile, (off_t)startoff, SEEK_SET) < 0) { ereport(WARNING, (errcode_for_file_access(), errmsg("could not seek in log file %s to offset %lu: %m", - XLogFileNameP(copyFileTLI, copySegNo), startoff))); + XLogFileNameP(copyFileTLI, copySegNo), startoff))); return false; } copyOff = startoff; @@ -868,16 +978,16 @@ static bool XLogCopyWrite(char *buf, int nbytes, XLogRecPtr recptr) errno = ENOSPC; } ereport(WARNING, (errcode_for_file_access(), - errmsg("could not write to log file %s at offset %u, length %lu: %m", - XLogFileNameP(copyFileTLI, copySegNo), copyOff, INT2ULONG(segbytes)))); + errmsg("could not write to log file %s at offset %u, length %lu: %m", + XLogFileNameP(copyFileTLI, copySegNo), copyOff, INT2ULONG(segbytes)))); return false; } if (copyOff == (uint32)0 && segbytes >= (int)sizeof(XLogPageHeaderData)) { if (((XLogPageHeader)buf)->xlp_magic == XLOG_PAGE_MAGIC && (copySegNo * XLogSegSize) != ((XLogPageHeader)buf)->xlp_pageaddr) { ereport(WARNING, (errcode_for_file_access(), - errmsg("unexpected page addr %lu of log file %s", ((XLogPageHeader)buf)->xlp_pageaddr, - XLogFileNameP(copyFileTLI, copySegNo)))); + errmsg("unexpected page addr %lu of log file %s", ((XLogPageHeader)buf)->xlp_pageaddr, + XLogFileNameP(copyFileTLI, copySegNo)))); return false; } } @@ -912,7 +1022,7 @@ static bool DoXLogCopyFromShare(XLogRecPtr copyStart) xlogreader = XLogReaderAllocate(SharedStorageXLogPageRead, 0, g_instance.xlog_cxt.shareStorageopCtl.blkSize); if (xlogreader == NULL) { ereport(WARNING, (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of memory"), - errdetail("Failed while allocating an XLog reading processor"))); + errdetail("Failed while allocating an XLog reading processor"))); return false; } xlogreader->system_identifier = GetSystemIdentifier(); @@ -937,7 +1047,7 @@ static bool DoXLogCopyFromShare(XLogRecPtr copyStart) if (copyFile >= 0) { if (close(copyFile) != 0) { ereport(WARNING, (errcode_for_file_access(), - errmsg("could not close log file %s: %m", XLogFileNameP(copyFileTLI, copySegNo)))); + errmsg("could not close log file %s: %m", XLogFileNameP(copyFileTLI, copySegNo)))); return false; } } @@ -967,8 +1077,8 @@ bool XLogOverwriteFromShare() if (ctlInfo->systemIdentifier != GetSystemIdentifier()) { ereport(WARNING, (errmsg("database system version is different between shared storage and local"), - errdetail("The shared storage's system version is %lu, the local's system version is %lu.", - ctlInfo->systemIdentifier, GetSystemIdentifier()))); + errdetail("The shared storage's system version is %lu, the local's system version is %lu.", + ctlInfo->systemIdentifier, GetSystemIdentifier()))); return false; } /* The local log is consistent with the local data and cannot be simply overwritten from the shared storage. @@ -1062,4 +1172,3 @@ bool UnlockNasWriteFile(int fd) ereport(WARNING, (errcode_for_file_access(), errmsg("could not unlock lock file : %m"))); return false; } - diff --git a/src/include/postmaster/autovacuum.h b/src/include/postmaster/autovacuum.h index ff967d4be..a5e73e0a6 100644 --- a/src/include/postmaster/autovacuum.h +++ b/src/include/postmaster/autovacuum.h @@ -118,28 +118,28 @@ typedef struct av_toastid_mainid { /* struct to keep track of tables to vacuum and/or analyze, in 1st pass */ typedef struct av_relation { Oid ar_relid; /* hash key - must be first */ - bool ar_hasrelopts; + bool ar_hasrelopts; // 琛ㄦ槸鍚︽湁鍏宠仈鐨勯夐」 AutoVacOpts ar_reloptions; /* copy of AutoVacOpts from the main table's * reloptions, or NULL if none */ } av_relation; /* struct to keep track of tables to vacuum and/or analyze, after rechecking */ typedef struct autovac_table { - Oid at_relid; - int at_flags; - bool at_dovacuum; - bool at_doanalyze; - bool at_needfreeze; - bool at_sharedrel; - int64 at_freeze_min_age; - int64 at_freeze_table_age; - int at_vacuum_cost_delay; - int at_vacuum_cost_limit; - char* at_partname; - char* at_relname; - char* at_nspname; - char* at_datname; - bool at_is_toast; + Oid at_relid; // 琛ㄧ殑瀵硅薄鏍囪瘑绗︼紙OID锛 + int at_flags; // 琛ㄧ姸鎬佹爣蹇椾綅 + bool at_dovacuum; // 鏄惁鎵ц鑷姩娓呯悊 + bool at_doanalyze; // 鏄惁鎵ц鑷姩鍒嗘瀽 + bool at_needfreeze; // 鏄惁闇瑕佹墽琛屽喕缁撴搷浣 + bool at_sharedrel; // 琛ㄦ槸鍚︽槸鍏变韩鍏崇郴 + int64 at_freeze_min_age; // 鏈灏忓喕缁撳勾榫 + int64 at_freeze_table_age; // 琛ㄥ喕缁撳勾榫 + int at_vacuum_cost_delay; // 鑷姩娓呯悊寤惰繜鎴愭湰 + int at_vacuum_cost_limit; // 鑷姩娓呯悊寤惰繜鎴愭湰闄愬埗 + char* at_partname; // 鍒嗗尯琛ㄥ悕 + char* at_relname; // 琛ㄥ悕 + char* at_nspname; // 鍛藉悕绌洪棿鍚 + char* at_datname; // 鏁版嵁搴撳悕 + bool at_is_toast; // 琛ㄦ槸鍚︽槸 TOAST 琛 } autovac_table; /* partitioned table's autovac state */ @@ -171,17 +171,17 @@ typedef struct at_partitioned_table { * ------------- */ typedef struct WorkerInfoData { - SHM_QUEUE wi_links; - Oid wi_dboid; - Oid wi_tableoid; - Oid wi_parentoid; - bool wi_ispartition; - bool wi_sharedrel; - PGPROC* wi_proc; - TimestampTz wi_launchtime; - int wi_cost_delay; - int wi_cost_limit; - int wi_cost_limit_base; + SHM_QUEUE wi_links; // 鐢ㄤ簬灏嗗伐浣滆繘绋嬮摼鎺ュ埌闃熷垪涓 + Oid wi_dboid; // 鏁版嵁搴撶殑鏍囪瘑绗 + Oid wi_tableoid; // 琛ㄧ殑鏍囪瘑绗 + Oid wi_parentoid; // 鐖惰〃鐨勬爣璇嗙 + bool wi_ispartition; // 鏍囪瘑姝ゅ伐浣滆繘绋嬫槸鍚﹀鐞嗗垎鍖鸿〃 + bool wi_sharedrel; // 鏍囪瘑鍏宠仈鐨勮〃鏄惁鏄叡浜殑 + PGPROC* wi_proc; // 鎸囧悜宸ヤ綔杩涚▼鍏宠仈鐨 PGPROC 缁撴瀯鐨勬寚閽 + TimestampTz wi_launchtime; // 宸ヤ綔杩涚▼鍚姩鏃堕棿鐨勬椂闂存埑 + int wi_cost_delay; // 鑷姩娓呯悊寤惰繜鎴愭湰 + int wi_cost_limit; // 鑷姩娓呯悊寤惰繜闄愬埗鎴愭湰 + int wi_cost_limit_base; // 鍩虹闄愬埗鎴愭湰 } WorkerInfoData; typedef struct WorkerInfoData* WorkerInfo; @@ -213,11 +213,12 @@ typedef enum { * ------------- */ typedef struct AutoVacuumShmemStruct { - sig_atomic_t av_signal[AutoVacNumSignals]; - ThreadId av_launcherpid; - WorkerInfo av_freeWorkers; - SHM_QUEUE av_runningWorkers; - WorkerInfo av_startingWorker; + sig_atomic_t av_signal[AutoVacNumSignals]; // 鐢ㄤ簬瀛樺偍涓庤嚜鍔ㄦ竻鐞嗚繃绋嬬浉鍏崇殑淇″彿鎴栨爣蹇 + ThreadId av_launcherpid; // 鑷姩娓呯悊鍚姩鍣ㄨ繘绋嬬殑杩涚▼ID + WorkerInfo av_freeWorkers; // 瀛樺偍绌洪棽宸ヤ綔杩涚▼鐨勪俊鎭 + SHM_QUEUE av_runningWorkers; // 瀛樺偍姝e湪杩愯鐨勫伐浣滆繘绋嬮槦鍒 + WorkerInfo av_startingWorker; // 姝e湪鍚姩鎴栧垵濮嬪寲鐨勫伐浣滆繘绋嬬殑淇℃伅 + } AutoVacuumShmemStruct; #endif /* AUTOVACUUM_H */ diff --git a/src/include/postmaster/bgworker.h b/src/include/postmaster/bgworker.h index fa683da54..47081433a 100644 --- a/src/include/postmaster/bgworker.h +++ b/src/include/postmaster/bgworker.h @@ -43,45 +43,50 @@ struct BgWorkerContext; typedef void (*bgworker_main)(const BgWorkerContext *bwc); typedef void (*bgworker_exit)(const BgWorkerContext *bwc); +// 鐢ㄤ簬瀛樺偍鍚庡彴宸ヤ綔杩涚▼鐨勪笂涓嬫枃淇℃伅 typedef struct BgWorkerContext { - StreamTxnContext transactionCxt; - void *bgshared; - PGPROC *leader; - char *databaseName; - char *userName; - bool enable_cluster_resize; - bgworker_main main_entry; - bgworker_exit exit_entry; + StreamTxnContext transactionCxt; // 浜嬪姟涓婁笅鏂囷紝鐢ㄤ簬鍚庡彴宸ヤ綔杩涚▼鐨勪簨鍔$鐞 + void *bgshared; // 鍚庡彴宸ヤ綔杩涚▼鍏变韩鍐呭瓨鐨勬寚閽 + PGPROC *leader; // 棰嗗杩涚▼鐨 PGPROC 鎸囬拡 + char *databaseName; // 鏁版嵁搴撳悕 + char *userName; // 鐢ㄦ埛鍚 + bool enable_cluster_resize; // 鏄惁鍚敤闆嗙兢璋冩暣澶у皬 + bgworker_main main_entry; // 鍚庡彴宸ヤ綔杩涚▼鐨勪富鍑芥暟鍏ュ彛 + bgworker_exit exit_entry; // 鍚庡彴宸ヤ綔杩涚▼鐨勯鍑哄嚱鏁板叆鍙 } BgWorkerContext; +// 鐢ㄤ簬瀛樺偍鍚庡彴宸ヤ綔杩涚▼鐨勯敊璇俊鎭 typedef struct BgWorkerErrorData { - int elevel; - int sqlerrcode; - char message[BGWORKER_MAX_ERROR_LEN]; - char detail[BGWORKER_MAX_ERROR_LEN]; + int elevel; // 閿欒鐨勭骇鍒紝閫氬父涓庢棩蹇楁秷鎭殑涓ラ噸绋嬪害鐩稿叧 + int sqlerrcode; // 閿欒鐨 SQL 閿欒鐮侊紝鐢ㄤ簬鏍囪瘑涓嶅悓绫诲瀷鐨勯敊璇 + char message[BGWORKER_MAX_ERROR_LEN]; // 瀛樺偍閿欒鐨勪富瑕佷俊鎭紝浠ュ瓧绗︿覆鐨勫舰寮忚〃绀 + char detail[BGWORKER_MAX_ERROR_LEN]; // 瀛樺偍閿欒鐨勮缁嗕俊鎭紝浠ュ瓧绗︿覆鐨勫舰寮忚〃绀 } BgWorkerErrorData; +// 琛ㄧず鍚庡彴宸ヤ綔杩涚▼鐨勪俊鎭拰鐘舵 typedef struct BackgroundWorker { - SHM_QUEUE links; /* list link if process is in a list */ - uint64 bgw_id; - ThreadId bgw_notify_pid; /* SIGUSR1 this backend on start/stop */ - BgwHandleStatus bgw_status; /* Status of this bgworker */ - uint64 bgw_status_dur; /* duration in this status */ - BgWorkerErrorData bgw_edata; /* error information of a bgworker */ - pg_atomic_uint32 disable_count; /* indicate whether the bgworker is disabled */ - slist_node rw_lnode; /* list link */ + SHM_QUEUE links; // 鍦ㄨ繘绋嬪垪琛ㄤ腑鐨勯摼鎺/* list link if process is in a list */ + uint64 bgw_id; // 鍚庡彴宸ヤ綔杩涚▼鐨勫敮涓鏍囪瘑绗 + ThreadId bgw_notify_pid; // 鍚庡彴宸ヤ綔杩涚▼鍚姩/鍋滄鏃跺悜璇ヨ繘绋嬪彂閫 SIGUSR1 淇″彿鐨勮繘绋 ID/* SIGUSR1 this backend on start/stop */ + BgwHandleStatus bgw_status; // 鍚庡彴宸ヤ綔杩涚▼鐨勭姸鎬侊紝鎸囩ず鍏舵槸鍚︽鍦ㄨ繍琛屻佸凡澶辫触鎴栧凡缁堟绛 /* Status of this bgworker */ + uint64 bgw_status_dur; // 鍚庡彴宸ヤ綔杩涚▼鍦ㄥ綋鍓嶇姸鎬佷笅鎸佺画鐨勬椂闂 /* duration in this status */ + BgWorkerErrorData bgw_edata; // 璁板綍鍚庡彴宸ヤ綔杩涚▼閿欒鐨勬暟鎹紝鍖呮嫭閿欒绾у埆鍜 SQL 閿欒鐮 /* error information of a bgworker */ + pg_atomic_uint32 disable_count; // 鎸囩ず鍚庡彴宸ヤ綔杩涚▼鏄惁宸茶绂佺敤鐨勮鏁板櫒/* indicate whether the bgworker is disabled */ + slist_node rw_lnode; // 鐢ㄤ簬灏嗗悗鍙板伐浣滆繘绋嬫坊鍔犲埌鍒楄〃涓/* list link */ } BackgroundWorker; +// 鐢ㄤ簬绠$悊鍚庡彴宸ヤ綔杩涚▼鐨勭浉鍏充俊鎭 typedef struct BGW_HDR { - pg_atomic_uint64 bgw_id_seq; - BackgroundWorker* bgws; - BackgroundWorker* free_bgws; + pg_atomic_uint64 bgw_id_seq; // 鍚庡彴宸ヤ綔杩涚▼ ID 搴忓垪 + BackgroundWorker* bgws; // 鍚庡彴宸ヤ綔杩涚▼鏁扮粍 + BackgroundWorker* free_bgws; // 绌洪棽鍚庡彴宸ヤ綔杩涚▼閾捐〃 } BGW_HDR; +// 鐢ㄤ簬浼犻掑悗鍙板伐浣滆繘绋嬬浉鍏崇殑鍙傛暟鍜屼俊鎭 typedef struct BackgroundWorkerArgs { - BgWorkerContext *bgwcontext; - BackgroundWorker *bgworker; - uint64 bgworkerId; + BgWorkerContext *bgwcontext; // 鎸囧悜鍚庡彴宸ヤ綔杩涚▼涓婁笅鏂囩殑鎸囬拡 + BackgroundWorker *bgworker; // 鎸囧悜 BackgroundWorker 缁撴瀯浣撶殑鎸囬拡 + uint64 bgworkerId; // 鍚庡彴宸ヤ綔杩涚▼鐨勫敮涓鏍囪瘑绗 } BackgroundWorkerArgs; /* Register a new bgworker during shared_preload_libraries */ diff --git a/src/include/postmaster/snapcapturer.h b/src/include/postmaster/snapcapturer.h index 02541ff4a..67d42aea9 100644 --- a/src/include/postmaster/snapcapturer.h +++ b/src/include/postmaster/snapcapturer.h @@ -23,21 +23,24 @@ #define SNAPCAPTURER_H #include "utils/snapshot.h" - +// 瀹氫箟浜嗕笁绉嶄笉鍚岀殑浜嬪姟蹇収宸ヤ綔杩涚▼鐘舵侊紝鐢ㄤ簬璺熻釜杩涚▼鐨勬墽琛岀姸鎬 typedef enum TxnWorkerStatus { - TXNWORKER_DEFAULT, - TXNWORKER_STARTED, - TXNWORKER_DONE + TXNWORKER_DEFAULT, // 琛ㄧず浜嬪姟蹇収宸ヤ綔杩涚▼鐨勯粯璁ょ姸鎬侊紝閫氬父鍦ㄨ繘绋嬪惎鍔ㄥ墠浣跨敤 + TXNWORKER_STARTED, // 琛ㄧず浜嬪姟蹇収宸ヤ綔杩涚▼宸茬粡鍚姩骞舵鍦ㄨ繍琛 + TXNWORKER_DONE // 琛ㄧず浜嬪姟蹇収宸ヤ綔杩涚▼宸插畬鎴愬叾浠诲姟 } TxnWorkerStatus; +// 瀛樺偍鏈夊叧浜嬪姟蹇収宸ヤ綔杩涚▼鐨勪俊鎭紝浠ヤ究鍏朵粬缁勪欢鍙互璁块棶鍜屾搷浣滆繖浜涗俊鎭 typedef struct TxnSnapWorkerInfo { - NameData dbName; - ThreadId snapworkerPid; /* PID (0 if not started) */ - TxnWorkerStatus status; - Latch latch; + NameData dbName; // 瀛樺偍浜嗘暟鎹簱鍚嶇О鐨勬暟鎹粨鏋 + ThreadId snapworkerPid; /* PID (0 if not started) */ // 琛ㄧず浜嬪姟蹇収宸ヤ綔杩涚▼鐨勮繘绋婭D + TxnWorkerStatus status; // 琛ㄧず浜嬪姟蹇収宸ヤ綔杩涚▼鐨勭姸鎬 + Latch latch; // 鐢ㄤ簬绾跨▼鍚屾鐨勪俊鍙烽噺锛岀敤浜庣瓑寰呬簨浠剁殑鍙戠敓鎴栭氱煡鍏朵粬杩涚▼ } TxnSnapWorkerInfo; + +// 鐢ㄤ簬瀹氫箟鍏变韩鍐呭瓨涓瓨鍌 typedef struct TxnSnapCapShmemStruct { - TxnSnapWorkerInfo workerInfo; + TxnSnapWorkerInfo workerInfo; // 瀛樺偍鏈夊叧浜嬪姟蹇収宸ヤ綔杩涚▼鐨勪俊鎭,浠ヤ究鍗忓悓宸ヤ綔 } TxnSnapCapShmemStruct; extern Size TxnSnapCapShmemSize(void); diff --git a/src/include/postmaster/syslogger.h b/src/include/postmaster/syslogger.h index f48f1dd5f..d7af81bcc 100644 --- a/src/include/postmaster/syslogger.h +++ b/src/include/postmaster/syslogger.h @@ -68,31 +68,20 @@ enum LogType { LOG_TYPE_UPLIMIT = 127 }; +// 鐢ㄤ簬绠$悊鏃ュ織鎺у埗鐩稿叧鐨勬暟鎹 typedef struct LogControlData { - bool inited; - uint16 ver; - - /* rotation request */ - volatile sig_atomic_t rotation_requested; - - /* to flush buffer request */ - volatile sig_atomic_t flush_requested; - - /* log directory */ - char* log_dir; - - /* pattern of log file name */ - char* filename_pattern; - char* file_suffix; - - /* current log file name and its fd */ - char* now_file_name; - FILE* now_file_fd; - - /* log chunk buffer */ - char* log_buf; - int cur_len; - int max_len; + bool inited; //-> 鏍囪瘑鏃ュ織鎺у埗鏄惁宸茬粡鍒濆鍖 + uint16 ver; //-> 鐢ㄤ簬璁板綍鏃ュ織鎺у埗鐨勭増鏈俊鎭 + volatile sig_atomic_t rotation_requested; //-> 鐢ㄤ簬琛ㄧず鏄惁璇锋眰鎵ц鏃ュ織杞崲鎿嶄綔鐨勬爣蹇 + volatile sig_atomic_t flush_requested; //-> 鐢ㄤ簬琛ㄧず鏄惁璇锋眰鍒锋柊鏃ュ織缂撳啿鍖虹殑鏍囧織 + char* log_dir; //-> 瀛樺偍鏃ュ織鏂囦欢鐨勭洰褰曡矾寰 + char* filename_pattern; //-> 瀛樺偍鏃ュ織鏂囦欢鍚嶇殑妯″紡 + char* file_suffix; //-> 瀛樺偍鏃ュ織鏂囦欢鐨勫悗缂 + char* now_file_name; //-> 瀛樺偍褰撳墠鏃ュ織鏂囦欢鐨勫悕绉 + FILE* now_file_fd; //-> 瀛樺偍褰撳墠鏃ュ織鏂囦欢鐨勬枃浠舵弿杩扮 + char* log_buf; //-> 瀛樺偍鏃ュ織鏁版嵁鐨勭紦鍐插尯 + int cur_len; //-> 褰撳墠缂撳啿鍖轰腑鐨勬棩蹇楁暟鎹暱搴 + int max_len; //->缂撳啿鍖虹殑鏈澶у閲 } LogControlData; /* @@ -110,14 +99,15 @@ typedef struct LogControlData { #define PROFILE_LOG_VERSION 1 /* header data in each binary log file */ +// 瀛樺偍浜岃繘鍒舵棩蹇楁枃浠剁殑澶撮儴淇℃伅 typedef struct { /* must be the first */ - unsigned long fst_magic; + unsigned long fst_magic; //-> 琛ㄧず鏃ュ織鏂囦欢澶寸殑璧峰鏍囧織 - uint16 version; - uint8 hostname_len; - uint8 nodename_len; - uint16 timezone_len; + uint16 version; //-> 瀛樺偍鏃ュ織鏂囦欢鐨勭増鏈俊鎭 + uint8 hostname_len; //-> 瀛樺偍涓绘満鍚嶇殑闀垮害 + uint8 nodename_len; //-> 瀛樺偍鑺傜偣鍚嶇О鐨勯暱搴 + uint16 timezone_len; //-> 瀛樺偍鏃跺尯淇℃伅鐨勯暱搴 /* * part1: hostname <- hostname_len @@ -126,24 +116,27 @@ typedef struct { */ /* must be the last */ - unsigned long lst_magic; + unsigned long lst_magic; //->琛ㄧず鏃ュ織鏂囦欢澶寸殑缁撴潫鏍囧織 } LogFileHeader; +// 鎻忚堪绠¢亾閫氫俊涓殑鍗忚澶翠俊鎭 typedef struct { - char nuls[2]; /* always \0\0 */ - uint16 len; /* size of this chunk (counts data only) */ - char logtype; /* which log type, see LogType */ + char nuls[2]; /* always \0\0 */ // -> 鐢ㄤ簬瀵归綈缁撴瀯浣撲互纭繚鍚庣画鎴愬憳鎸夌収姝g‘鐨勫瓧鑺傝竟鐣屾帓鍒 + uint16 len; /* size of this chunk (counts data only) */ // -> 琛ㄧず褰撳墠鏁版嵁鍧楃殑澶у皬 + char logtype; /* which log type, see LogType */ // -> 琛ㄧず鏃ュ織鐨勭被鍨 char is_last; /* last chunk of message? 't' or 'f' ('T' or * 'F' for CSV case) */ + // -> 琛ㄧず鏄惁鏄秷鎭殑鏈鍚庝竴涓潡 /* writer's pid. be placed the last, and make data 8 bytes alligned */ - ThreadId pid; - uint64 magic; /* magic number to check the proto header */ - char data[FLEXIBLE_ARRAY_MEMBER]; /* data payload starts here */ + ThreadId pid; // -> 琛ㄧず鍐欏叆鏁版嵁鐨勭嚎绋嬬殑杩涚▼鏍囪瘑绗 + uint64 magic; /* magic number to check the proto header */ // -> 鐢ㄤ簬妫鏌ュ崗璁ご鐨勫畬鏁存 + char data[FLEXIBLE_ARRAY_MEMBER]; /* data payload starts here */ // -> 鐢ㄤ簬瀛樺偍瀹為檯鐨勬暟鎹唴瀹 } LogPipeProtoHeader; +// 鍦ㄧ閬撻氫俊涓敤浜庢暟鎹殑浼犺緭 typedef union { - LogPipeProtoHeader proto; - char filler[LOGPIPE_CHUNK_SIZE]; + LogPipeProtoHeader proto; //-> 琛ㄧず绠¢亾閫氫俊鐨勫崗璁ご淇℃伅 + char filler[LOGPIPE_CHUNK_SIZE]; //-> 鐢ㄤ簬鍗犵敤涓瀹氱殑鍐呭瓨绌洪棿锛屼互淇濊瘉缁撴瀯浣撶殑澶у皬 } LogPipeProtoChunk; #define LOGPIPE_HEADER_SIZE offsetof(LogPipeProtoHeader, data) diff --git a/src/include/storage/smgr/segment_internal.h b/src/include/storage/smgr/segment_internal.h index c5c263059..3d1debd6c 100644 --- a/src/include/storage/smgr/segment_internal.h +++ b/src/include/storage/smgr/segment_internal.h @@ -71,23 +71,23 @@ typedef struct SegPhysicalFile { const int DF_ARRAY_EXTEND_STEP = 4; const ssize_t DF_FILE_EXTEND_STEP_BLOCKS = RELSEG_SIZE / 8; -const ssize_t DF_FILE_EXTEND_STEP_SIZE = DF_FILE_EXTEND_STEP_BLOCKS * BLCKSZ; // 128MB +const ssize_t DF_FILE_EXTEND_STEP_SIZE = DF_FILE_EXTEND_STEP_BLOCKS * BLCKSZ; // 128MB const ssize_t DF_FILE_SLICE_BLOCKS = RELSEG_SIZE; -const ssize_t DF_FILE_SLICE_SIZE = DF_FILE_SLICE_BLOCKS * BLCKSZ; // 1GB +const ssize_t DF_FILE_SLICE_SIZE = DF_FILE_SLICE_BLOCKS * BLCKSZ; // 1GB const ssize_t DF_FILE_MIN_BLOCKS = DF_FILE_EXTEND_STEP_BLOCKS; #define DF_OFFSET_TO_SLICENO(offset) (offset / DF_FILE_SLICE_SIZE) #define DF_OFFSET_TO_SLICE_OFFSET(offset) (offset % DF_FILE_SLICE_SIZE) typedef struct SegLogicFile { - SegPhysicalFile *segfiles; - RelFileNode relNode; - ForkNumber forknum; - int vector_capacity; // current segfile array capacity - int file_num; - BlockNumber total_blocks; - char filename[MAXPGPATH]; - pthread_mutex_t filelock; + SegPhysicalFile *segfiles; // 鐢ㄤ簬璺熻釜涓庨昏緫鏂囦欢鐩稿叧鐨勭墿鐞嗘枃浠剁殑淇℃伅 + RelFileNode relNode; // 涓庤閫昏緫鏂囦欢鍏宠仈鐨勬枃浠惰妭鐐 + ForkNumber forknum; // 涓庤閫昏緫鏂囦欢鍏宠仈鐨 fork 绫诲瀷 + int vector_capacity; // current segfile array capacity + int file_num; // 褰撳墠閫昏緫鏂囦欢鍖呭惈鐨勭墿鐞嗘枃浠舵暟閲 + BlockNumber total_blocks; // 閫昏緫鏂囦欢鐨勬诲潡鏁 + char filename[MAXPGPATH]; // 閫昏緫鏂囦欢鐨勬枃浠跺悕鎴栬矾寰 + pthread_mutex_t filelock; // 涓涓簰鏂ラ攣锛岀敤浜庡悓姝ュ閫昏緫鏂囦欢鐨勫苟鍙戣闂紝浠ョ‘淇濈嚎绋嬪畨鍏 } SegLogicFile; void df_ctrl_init(SegLogicFile *sf, RelFileNode relNode, ForkNumber forknum); @@ -105,9 +105,9 @@ void df_flush_data(SegLogicFile *sf, BlockNumber blocknum, BlockNumber nblocks); * Data files status in the segment space; */ enum SpaceDataFileStatus { - EMPTY, // space has not been created; there is no data file - CRASHED, // space data files are crashed, only because creation failed halfway - NORMAL // space data files are consistent and able to provide services + EMPTY, // space has not been created; there is no data file + CRASHED, // space data files are crashed, only because creation failed halfway + NORMAL // space data files are consistent and able to provide services }; /* @@ -161,7 +161,7 @@ typedef enum ExtentTotalPages { } ExtentTotalPages; typedef enum EXTENT_TYPE { - EXTENT_INVALID = 0, // 0 means invalid + EXTENT_INVALID = 0, // 0 means invalid EXTENT_1 = 1, EXTENT_8 = 2, EXTENT_128 = 3, @@ -170,8 +170,8 @@ typedef enum EXTENT_TYPE { } EXTENT_TYPE; #ifdef ENABLE_SEGMENT_TEST -#define SEGMENTTEST(TEST_CODE, msg) \ - if (SEGMETN_TEST_STUB(TEST_CODE)) { \ +#define SEGMENTTEST(TEST_CODE, msg) \ + if (SEGMETN_TEST_STUB(TEST_CODE)) { \ ereport(g_instance.segment_test_param_instance->elevel, msg); \ } #else @@ -195,16 +195,16 @@ typedef enum EXTENT_TYPE { #define DF_MAP_UNSET(bitmap, pos) ((bitmap)[(pos) >> 3] &= ~(1 << ((pos)&0x07))) typedef struct st_df_map_group { - BlockNumber first_map; // start page id of bitmap pages of this group + BlockNumber first_map; // start page id of bitmap pages of this group uint32 free_page; // first free page of this group - uint8 page_count; // count of bitmap pages of this group - uint8 reserved[DF_MAP_GROUP_RESERVED]; + uint8 page_count; // count of bitmap pages of this group + uint8 reserved[DF_MAP_GROUP_RESERVED]; } df_map_group_t; typedef struct st_df_map_head { - uint16 bit_unit; // page count that managed by one bit - uint16 group_count; // count of bitmap group that already exists - uint32 free_group; // first free group + uint16 bit_unit; // page count that managed by one bit + uint16 group_count; // count of bitmap group that already exists + uint32 free_group; // first free group uint32 reserved; uint32 allocated_extents; uint32 high_water_mark; @@ -212,12 +212,12 @@ typedef struct st_df_map_head { } df_map_head_t; typedef struct st_df_map_page { - BlockNumber first_page; // first page managed by this bitmap - uint16 free_begin; // first free bit - uint16 dirty_last; // last dirty bit - uint16 free_bits; // free bits + BlockNumber first_page; // first page managed by this bitmap + uint16 free_begin; // first free bit + uint16 dirty_last; // last dirty bit + uint16 free_bits; // free bits uint16 reserved; - uint8 bitmap[0]; // following is the bitmap + uint8 bitmap[0]; // following is the bitmap } df_map_page_t; typedef struct SpaceMapLocation { @@ -258,7 +258,7 @@ typedef struct SegExtentGroup { int extent_size; SegSpace *space; pthread_mutex_t lock; - BlockNumber map_head_entry; // default is DF_MAP_HEAD_PAGE + BlockNumber map_head_entry; // default is DF_MAP_HEAD_PAGE df_map_head_t *map_head; Buffer map_head_buffer; } SegExtentGroup; @@ -267,8 +267,8 @@ typedef struct SegmentSpaceStat { uint32 extent_size; ForkNumber forknum; uint32 total_blocks; - uint32 meta_data_blocks; // Including MapHead, MapPage. - uint32 used_data_blocks; // Including segment head, normal data extent. + uint32 meta_data_blocks; // Including MapHead, MapPage. + uint32 used_data_blocks; // Including segment head, normal data extent. float utilization; uint32 high_water_mark; } SegmentSpaceStat; @@ -281,30 +281,30 @@ typedef struct SegmentSpaceStat { * equal to the last valid type value + 1. */ enum ExtentUsageType { - NOT_USED = 0, // default - SEGMENT_HEAD, // non-bucket table main segment head - FORK_HEAD, // non-bucket table fork segment head - BUCKET_SEGMENT, // segment head for the whole bucket table - BUCKET_MAP, // bucket table map block - BUCKET_HEAD, // segment head for single bucket - DATA_EXTENT, // extent used to store table data + NOT_USED = 0, // default + SEGMENT_HEAD, // non-bucket table main segment head + FORK_HEAD, // non-bucket table fork segment head + BUCKET_SEGMENT, // segment head for the whole bucket table + BUCKET_MAP, // bucket table map block + BUCKET_HEAD, // segment head for single bucket + DATA_EXTENT, // extent used to store table data - INVALID_EXTNT_USAGE, // must always be the last value in this enumerate. + INVALID_EXTNT_USAGE, // must always be the last value in this enumerate. }; -#define SEGMENT_HEAD_MAGIC 0x44414548544e454d -#define BUCKET_SEGMENT_MAGIC 0x544e454d47455354 -#define BUCKETMAP_MAGIC 0x50414d54454b4355 -#define BMTLEVEL0_MAGIC 0x306c6576654c544d +#define SEGMENT_HEAD_MAGIC 0x44414548544e454d +#define BUCKET_SEGMENT_MAGIC 0x544e454d47455354 +#define BUCKETMAP_MAGIC 0x50414d54454b4355 +#define BMTLEVEL0_MAGIC 0x306c6576654c544d -#define IsNormalSegmentHead(head) (((SegmentHead*)(head))->magic == SEGMENT_HEAD_MAGIC) -#define IsBucketMainHead(head) (((BktMainHead*)(head))->magic == BUCKET_SEGMENT_MAGIC) -#define IsBucketMapBlock(head) (((BktHeadMapBlock*)(head))->magic == BUCKETMAP_MAGIC) -#define IsBMTLevel0Block(head) (((BMTLevel0Page*)(head))->magic == BMTLEVEL0_MAGIC) +#define IsNormalSegmentHead(head) (((SegmentHead *)(head))->magic == SEGMENT_HEAD_MAGIC) +#define IsBucketMainHead(head) (((BktMainHead *)(head))->magic == BUCKET_SEGMENT_MAGIC) +#define IsBucketMapBlock(head) (((BktHeadMapBlock *)(head))->magic == BUCKETMAP_MAGIC) +#define IsBMTLevel0Block(head) (((BMTLevel0Page *)(head))->magic == BMTLEVEL0_MAGIC) typedef struct ExtentInversePointer { uint32 flag; - BlockNumber owner; // owner oid (or block number) + BlockNumber owner; // owner oid (or block number) } ExtentInversePointer; /* @@ -320,11 +320,11 @@ typedef struct ExtentInversePointer { #define SPC_INVRSPTR_SPECIAL_DATA_MASK ((1U << 18) - 1) #define SPC_INVRSPTR_GET_SPECIAL_DATA(eip) ((eip).flag & SPC_INVRSPTR_SPECIAL_DATA_MASK) -#define InversePointerIsValid(eip) \ +#define InversePointerIsValid(eip) \ (SPC_INVRSPTR_GET_USAGE(eip) > NOT_USED && SPC_INVRSPTR_GET_USAGE(eip) < INVALID_EXTNT_USAGE) /* Assemble usage and special_data into one uint32 variable */ -#define SPC_INVRSPTR_ASSEMBLE_FLAG(usage, special_data) \ +#define SPC_INVRSPTR_ASSEMBLE_FLAG(usage, special_data) \ ((((uint32)(special_data)) & SPC_INVRSPTR_SPECIAL_DATA_MASK) + (((uint32)(usage)) << SPC_INVRSPTR_USAGE_SHIFT)) /* Inverse pointer array size in each block */ @@ -353,7 +353,7 @@ void eg_ctrl_init(SegSpace *spc, SegExtentGroup *seg, int extent_size, ForkNumbe SpaceDataFileStatus eg_status(SegExtentGroup *eg); BlockNumber eg_alloc_extent(SegExtentGroup *seg, BlockNumber preassigned_block, ExtentInversePointer iptr); -void eg_free_extent(SegExtentGroup* seg, BlockNumber blocknum); +void eg_free_extent(SegExtentGroup *seg, BlockNumber blocknum); bool eg_empty(SegExtentGroup *seg); void eg_clean_data_files(SegExtentGroup *eg); @@ -378,11 +378,11 @@ typedef struct SegSpace { SegExtentGroup extent_group[EXTENT_TYPES][SEGMENT_MAX_FORKNUM + 1]; } SegSpace; -#define SMgrOpenSpace(reln) \ - do { \ - if ((reln)->seg_space == NULL) { \ - (reln)->seg_space = spc_open((reln)->smgr_rnode.node.spcNode, (reln)->smgr_rnode.node.dbNode, false); \ - } \ +#define SMgrOpenSpace(reln) \ + do { \ + if ((reln)->seg_space == NULL) { \ + (reln)->seg_space = spc_open((reln)->smgr_rnode.node.spcNode, (reln)->smgr_rnode.node.dbNode, false); \ + } \ } while (0) extern void InitSegSpcCache(void); @@ -413,7 +413,7 @@ extern void spc_shrink_files(SegExtentGroup *seg, BlockNumber target_size, bool /* * Block Map Tree (BMT) related constants */ -static const int BMT_HEADER_LEVEL0_SLOTS = 1255; // level0 slots must bigger or equal than EXT_SIZE_1024_BOUNDARY +static const int BMT_HEADER_LEVEL0_SLOTS = 1255; // level0 slots must bigger or equal than EXT_SIZE_1024_BOUNDARY static const int BMT_HEADER_LEVEL1_SLOTS = 256; static const int BMT_HEADER_LEVEL0_TOTAL_PAGES = EXT_SIZE_1024_TOTAL_PAGES + (BMT_HEADER_LEVEL0_SLOTS - EXT_SIZE_1024_BOUNDARY) * EXT_SIZE_8192; @@ -424,11 +424,11 @@ static const uint32_t BMT_LEVEL0_SLOTS = 2000; typedef struct SegmentHead { uint64 magic; XLogRecPtr lsn; - uint32 nblocks; // block number reported to upper layer - uint32 nextents; // extent number allocated to this segment - uint32 nslots : 16; // not used yet - int bucketid : 16; // not used yet - uint32 total_blocks; // total blocks can be allocated to table (exclude metadata pages) + uint32 nblocks; // block number reported to upper layer + uint32 nextents; // extent number allocated to this segment + uint32 nslots : 16; // not used yet + int bucketid : 16; // not used yet + uint32 total_blocks; // total blocks can be allocated to table (exclude metadata pages) uint64 reserved; BlockNumber level0_slots[BMT_HEADER_LEVEL0_SLOTS]; BlockNumber level1_slots[BMT_HEADER_LEVEL1_SLOTS]; @@ -450,8 +450,7 @@ typedef struct SegPageLocation { SegPageLocation seg_get_physical_location(RelFileNode rnode, ForkNumber forknum, BlockNumber blocknum); void seg_record_new_extent_on_level0_page(SegSpace *spc, Buffer seg_head_buffer, uint32 new_extent_id, BlockNumber new_extent_first_pageno); -void seg_head_update_xlog(Buffer head_buffer, SegmentHead *seg_head, int level0_slot, - int level1_slot); +void seg_head_update_xlog(Buffer head_buffer, SegmentHead *seg_head, int level0_slot, int level1_slot); BlockNumber seg_extent_location(SegSpace *spc, SegmentHead *seg_head, int extent_id); inline static ExtentSize ExtentSizeByCount(uint32 count) @@ -494,11 +493,11 @@ inline static BlockNumber ExtentIdToLogicBlockNum(uint32 extent_id) /* Segment information in SMgrRelationData */ typedef struct SegmentDesc { - BlockNumber head_blocknum; // Segment Head block number + BlockNumber head_blocknum; // Segment Head block number uint32 timeline; } SegmentDesc; -#define IsNormalForknum(forknum) \ +#define IsNormalForknum(forknum) \ ((forknum) == MAIN_FORKNUM || (forknum) == FSM_FORKNUM || (forknum) == VISIBILITYMAP_FORKNUM) #define ASSERT_NORMAL_FORK(forknum) Assert(IsNormalForknum(forknum)) @@ -538,7 +537,7 @@ inline static bool RequireNewLevel0Page(uint32 new_extent_id) * Luckily, spc_shrink is an extra-low frequent operation. It should not influence the performance. */ #define SegmentHeadPartition(hashcode) ((hashcode) % NUM_SEGMENT_HEAD_PARTITIONS) -#define SegmentHeadPartitionLock(hashcode) \ +#define SegmentHeadPartitionLock(hashcode) \ (&t_thrd.shemem_ptr_cxt.mainLWLockArray[FirstSegmentHeadLock + SegmentHeadPartition(hashcode)].lock) #define SegmentHeadPartitionLockByIndex(i) (&t_thrd.shemem_ptr_cxt.mainLWLockArray[FirstSegmentHeadLock + (i)].lock) @@ -570,21 +569,20 @@ typedef struct BktHeadMapBlock { typedef struct SegRedisInfo { TransactionId redis_xid; - uint32 nwords; - uint32 reserved; - uint32 words[BktBitMaxMapCnt]; + uint32 nwords; + uint32 reserved; + uint32 words[BktBitMaxMapCnt]; } SegRedisInfo; - -#define WORDOFF(x) ((x) / (sizeof(uint32) * 8)) -#define BITOFF(x) ((x) % (sizeof(uint32) * 8)) -#define SET_BKT_MAP_BIT(map, x) (map[WORDOFF(x)] |= ((uint32) 1 << (uint32)BITOFF(x))) -#define GET_BKT_MAP_BIT(map, x) (map[WORDOFF(x)] & ((uint32) 1 << (uint32)BITOFF(x))) +#define WORDOFF(x) ((x) / (sizeof(uint32) * 8)) +#define BITOFF(x) ((x) % (sizeof(uint32) * 8)) +#define SET_BKT_MAP_BIT(map, x) (map[WORDOFF(x)] |= ((uint32)1 << (uint32)BITOFF(x))) +#define GET_BKT_MAP_BIT(map, x) (map[WORDOFF(x)] & ((uint32)1 << (uint32)BITOFF(x))) typedef struct BktMainHead { uint64 magic; XLogRecPtr lsn; - SegRedisInfo redis_info; - uint64 reserved; + SegRedisInfo redis_info; + uint64 reserved; BlockNumber bkt_map[BktMapBlockNumber]; } BktMainHead; @@ -599,7 +597,6 @@ BlockNumber seg_alloc_segment(Oid tablespace_id, Oid database_id, bool isbucket, /* Make sure the segment has enough space for blkno */ void seg_preextend(RelFileNode &rNode, ForkNumber forkNum, BlockNumber blkno); - inline int EXTENT_TYPE_TO_SIZE(int type) { if (type == EXTENT_1) { diff --git a/src/include/utils/rel.h b/src/include/utils/rel.h index 6006fbdaf..1605c9edf 100644 --- a/src/include/utils/rel.h +++ b/src/include/utils/rel.h @@ -306,16 +306,16 @@ typedef struct RelationData { */ /* autovacuum-related reloptions. */ typedef struct AutoVacOpts { - bool enabled; - int vacuum_threshold; - int analyze_threshold; - int vacuum_cost_delay; - int vacuum_cost_limit; - int64 freeze_min_age; - int64 freeze_max_age; - int64 freeze_table_age; - float8 vacuum_scale_factor; - float8 analyze_scale_factor; + bool enabled; // 鏄惁鍚敤鑷姩娓呯悊 + int vacuum_threshold; // 瑙﹀彂鑷姩娓呯悊鐨勯槇鍊 + int analyze_threshold; // 瑙﹀彂鑷姩鍒嗘瀽鐨勯槇鍊 + int vacuum_cost_delay; // 鑷姩娓呯悊鐨勫欢杩熸垚鏈 + int vacuum_cost_limit; // 鑷姩娓呯悊鐨勬垚鏈檺鍒 + int64 freeze_min_age; // 鏈灏忓喕缁撳勾榫 + int64 freeze_max_age; // 鏈澶у喕缁撳勾榫 + int64 freeze_table_age; // 鏁翠釜琛ㄥ喕缁撳勾榫 + float8 vacuum_scale_factor; // 鑷姩娓呯悊鎿嶄綔姣斾緥鍥犲瓙锛岀敤浜庤绠楁竻鐞嗙殑琛屾暟 + float8 analyze_scale_factor; // 鑷姩鍒嗘瀽姣斾緥鍥犲瓙 } AutoVacOpts; typedef enum RedisCtidType { REDIS_START_CTID = 0, REDIS_END_CTID } RedisCtidType;