日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

OpenGauss线程管理-主线程-Postmaster(1)

發布時間:2024/3/24 编程问答 38 豆豆
生活随笔 收集整理的這篇文章主要介紹了 OpenGauss线程管理-主线程-Postmaster(1) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

OpenGauss線程管理-主線程-Postmaster(1)

主線程postmaster負責內存、全局信息、信號、線程池等的初始化,用來創建其他子線程,OpenGauss是單進程多線程,在程序啟動時,一個進程被操作系統創建,同時主線程立刻運行。
主線程運行時可以用來接收前端的命令,對命令做出處理,還會對子線程進行監視,在子線程出現問題時會對子線程進行管理,保證數據庫正常的運行。
主線程是和后端共享的內存,但它不會碰共享內存,避免崩潰、卡住。

PostmasterMain函數

openGauss-server\src\gausskernel\process\postmaster\postmaster.cpp

  • 初始化postmaster配置參數
  • 初始化審計模塊
  • 建立輸入socket監聽
  • 建立共享內存和信號量池
  • 初始化postmaster信號管理
  • 初始化宕機監聽
  • 初始化統計數據收集子系統
  • 初始化工作負載管理器
  • 初始化unique sql資源
  • int PostmasterMain(int argc, char* argv[]) {int opt;int status = STATUS_OK;char* output_config_variable = NULL;char* userDoption = NULL;bool listen_addr_saved = false;int use_pooler_port = -1;int i;OptParseContext optCtxt;errno_t rc = 0;Port port;t_thrd.proc_cxt.MyProcPid = PostmasterPid = gs_thread_self();//設置線程號相關的全局變量MyProcPid、PostmasterPid、MyProgNamet_thrd.proc_cxt.MyStartTime = time(NULL);IsPostmasterEnvironment = true;//設置程序運行環境相關的全局變量IsPostmasterEnvironmentt_thrd.proc_cxt.MyProgName = "gaussmaster";/** 為了安全起見,創建的目錄或文件不能被group或其他方式訪問*/umask(S_IRWXG | S_IRWXO);/** 啟動基本子系統:內存管理*//** 默認情況下,postmaster中的 palloc()請求將在 t_thrd.mem_cxt 中分配. * postmaster_mem_cxt 是后端可以回收的空間。 需要提供給后端的已分配數據* 應在 t_thrd.top_mem_cxt 中分配。*/t_thrd.mem_cxt.postmaster_mem_cxt = AllocSetContextCreate(t_thrd.top_mem_cxt,"Postmaster",ALLOCSET_DEFAULT_MINSIZE,ALLOCSET_DEFAULT_INITSIZE,ALLOCSET_DEFAULT_MAXSIZE);MemoryContextSwitchTo(t_thrd.mem_cxt.postmaster_mem_cxt);/** 初始化版本信息*/initialize_feature_flags();#ifndef ENABLE_LITE_MODE/** @OBS* 創建一個線程之間共享的全局 OBS CA 對象*/initOBSCacheObject();S3_init(); #endif/* 為minizip libs設置內存管理器 */pm_set_unzip_memfuncs();/* 為 cJSON 設置內存管理器 */cJSON_Hooks hooks = {cJSON_internal_malloc, cJSON_internal_free};cJSON_InitHooks(&hooks);#ifdef ENABLE_LLVM_COMPILE/** 準備編譯環境。*/CodeGenProcessInitialize(); #endif/* 初始化安裝文件的路徑 */getInstallationPaths(argv[0]);//設置my_exec_path/** 選項設置(根據各個GUC參數的默認值生成GUC參數的全局變量數組,* 還有統一管理GUC參數的全局變量,并設置與操作系統環境相關的GUC參數)*/InitializeGUCOptions();/**初始化cb_for_getlc的回調函數類型*/SetcbForGetLCName(GetLogicClusterForAlarm);optCtxt.opterr = 1;/** 分析命令行選項。 注意:要與 tcop/postgres.c(選項集不應沖突)* 以及 main/main.c中的 common help() 函數保持同步。*/initOptParseContext(&optCtxt);//如果在啟動gaussdb時使用了非默認的GUC參數,則加載到上一步中創建的全局變量中while ((opt = getopt_r(argc, argv, "A:B:bc:C:D:d:EeFf:h:ijk:lM:N:nOo:Pp:Rr:S:sTt:u:W:g:X:-:", &optCtxt)) != -1) {switch (opt) {case 'A':SetConfigOption("debug_assertions", optCtxt.optarg, PGC_POSTMASTER, PGC_S_ARGV);break;case 'B':SetConfigOption("shared_buffers", optCtxt.optarg, PGC_POSTMASTER, PGC_S_ARGV);break;case 'b':/* 用于二進制升級的未記錄標志 */u_sess->proc_cxt.IsBinaryUpgrade = true;break;case 'C':output_config_variable = optCtxt.optarg;break;case 'D':userDoption = optCtxt.optarg;break;case 'd':set_debug_options(atoi(optCtxt.optarg), PGC_POSTMASTER, PGC_S_ARGV);break;case 'E':SetConfigOption("log_statement", "all", PGC_POSTMASTER, PGC_S_ARGV);break;case 'e':SetConfigOption("datestyle", "euro", PGC_POSTMASTER, PGC_S_ARGV);break;case 'F':SetConfigOption("fsync", "false", PGC_POSTMASTER, PGC_S_ARGV);break;case 'f':if (!set_plan_disabling_options(optCtxt.optarg, PGC_POSTMASTER, PGC_S_ARGV)) {write_stderr("%s: invalid argument for option -f: \"%s\"\n", progname, optCtxt.optarg);ExitPostmaster(1);}break;case 'g':SetConfigOption("xlog_file_path", optCtxt.optarg, PGC_POSTMASTER, PGC_S_ARGV);break;case 'h':SetConfigOption("listen_addresses", optCtxt.optarg, PGC_POSTMASTER, PGC_S_ARGV);break;case 'i':SetConfigOption("listen_addresses", "*", PGC_POSTMASTER, PGC_S_ARGV);break;case 'j':/* 僅由交互式后端使用 */break;case 'k':SetConfigOption("unix_socket_directory", optCtxt.optarg, PGC_POSTMASTER, PGC_S_ARGV);break;case 'l':SetConfigOption("ssl", "true", PGC_POSTMASTER, PGC_S_ARGV);break;case 'M':if (0 == strncmp(optCtxt.optarg, "primary", strlen("primary")) &&'\0' == optCtxt.optarg[strlen("primary")]) {t_thrd.xlog_cxt.server_mode = PRIMARY_MODE;} else if (0 == strncmp(optCtxt.optarg, "standby", strlen("standby")) &&'\0' == optCtxt.optarg[strlen("standby")]) {t_thrd.xlog_cxt.server_mode = STANDBY_MODE;} else if (0 == strncmp(optCtxt.optarg, "pending", strlen("pending")) &&'\0' == optCtxt.optarg[strlen("pending")]) {t_thrd.xlog_cxt.server_mode = PENDING_MODE;} else if (0 == strncmp(optCtxt.optarg, "normal", strlen("normal")) &&'\0' == optCtxt.optarg[strlen("normal")]) {t_thrd.xlog_cxt.server_mode = NORMAL_MODE;} else if (0 == strncmp(optCtxt.optarg, "cascade_standby", strlen("cascade_standby")) &&'\0' == optCtxt.optarg[strlen("cascade_standby")]) {t_thrd.xlog_cxt.server_mode = STANDBY_MODE;t_thrd.xlog_cxt.is_cascade_standby = true;} else if (0 == strncmp(optCtxt.optarg, "hadr_main_standby", strlen("hadr_main_standby")) &&'\0' == optCtxt.optarg[strlen("hadr_main_standby")]) {t_thrd.xlog_cxt.server_mode = STANDBY_MODE;t_thrd.xlog_cxt.is_hadr_main_standby = true;} else {ereport(FATAL, (errmsg("the options of -M is not recognized")));}break;case 'N':SetConfigOption("max_connections", optCtxt.optarg, PGC_POSTMASTER, PGC_S_ARGV);break;case 'n':/* 異常退出后不要重新啟動共享 */ereport(FATAL, (errmsg("the options of -n is deprecated")));break;case 'O':SetConfigOption("allow_system_table_mods", "true", PGC_POSTMASTER, PGC_S_ARGV);break;case 'o':/* 在命令行上傳遞到后端的其他選項 */rc = snprintf_s(g_instance.ExtraOptions + strlen(g_instance.ExtraOptions),sizeof(g_instance.ExtraOptions) - strlen(g_instance.ExtraOptions),sizeof(g_instance.ExtraOptions) - strlen(g_instance.ExtraOptions) - 1," %s",optCtxt.optarg);securec_check_ss(rc, "", "");break;case 'P':SetConfigOption("ignore_system_indexes", "true", PGC_POSTMASTER, PGC_S_ARGV);break;case 'p':SetConfigOption("port", optCtxt.optarg, PGC_POSTMASTER, PGC_S_ARGV);break; #ifdef ENABLE_MULTIPLE_NODEScase 'R':/* 指示運行為 xlogreiver。僅用于 -M 備用 */dummyStandbyMode = true;break; #endifcase 'r':/* 僅由單用戶后端使用 */break;case 'S':SetConfigOption("work_mem", optCtxt.optarg, PGC_POSTMASTER, PGC_S_ARGV);break;case 's':SetConfigOption("log_statement_stats", "true", PGC_POSTMASTER, PGC_S_ARGV);break;case 'T':/** 如果某些后端轉儲了核心,請將 SIGSTOP 而不是 SIGQUIT 發送到其所有對等端。 * 這讓post_hacker收集每個人的核心轉儲。*/ereport(FATAL, (errmsg("the options of -T is deprecated")));break;case 't': {const char* tmp = get_stats_option_name(optCtxt.optarg);if (tmp != NULL) {SetConfigOption(tmp, "true", PGC_POSTMASTER, PGC_S_ARGV);} else {write_stderr("%s: invalid argument for option -t: \"%s\"\n", progname, optCtxt.optarg);ExitPostmaster(1);}break;}case 'u':/* 用于原位或在線升級的無歸檔版本 */errno = 0;pg_atomic_write_u32(&WorkingGrandVersionNum, (uint32)strtoul(optCtxt.optarg, NULL, 10));if (errno != 0 || pg_atomic_read_u32(&WorkingGrandVersionNum) > GRAND_VERSION_NUM) {write_stderr("%s: invalid argument for option -u: \"%s\", GRAND_VERSION_NUM is %u\n",progname,optCtxt.optarg,(uint32)GRAND_VERSION_NUM);ExitPostmaster(1);} else if (pg_atomic_read_u32(&WorkingGrandVersionNum) == INPLACE_UPGRADE_PRECOMMIT_VERSION) {pg_atomic_write_u32(&WorkingGrandVersionNum, GRAND_VERSION_NUM);g_instance.comm_cxt.force_cal_space_info = true;}break;case 'W':SetConfigOption("post_auth_delay", optCtxt.optarg, PGC_POSTMASTER, PGC_S_ARGV);break;case 'X':/* 停止屏障 */if ((optCtxt.optarg != NULL) && (strlen(optCtxt.optarg) > 0)) {if (strlen(optCtxt.optarg) > MAX_BARRIER_ID_LENGTH) {ereport(FATAL, (errmsg("the options of -X is too long")));}rc = strncpy_s(g_instance.csn_barrier_cxt.stopBarrierId, MAX_BARRIER_ID_LENGTH,(char *)optCtxt.optarg, strlen(optCtxt.optarg));securec_check(rc, "\0", "\0");ereport(LOG, (errmsg("Set stop barrierID %s", g_instance.csn_barrier_cxt.stopBarrierId)));}break;case 'c':case '-': {char* name = NULL;char* value = NULL;ParseLongOption(optCtxt.optarg, &name, &value);#ifndef ENABLE_MULTIPLE_NODESif (opt == '-' && (strcmp(name, "coordinator") == 0 || strcmp(name, "datanode") == 0)) {ereport(FATAL,(errcode(ERRCODE_SYNTAX_ERROR),errmsg("Single node mode: must start as single node (--single_node)\n")));} #endif/* 正在激活協調器 */if (name != NULL && strcmp(name, "coordinator") == 0 && value == NULL)g_instance.role = VCOORDINATOR;else if (name != NULL && strcmp(name, "datanode") == 0 && value == NULL)g_instance.role = VDATANODE;/* 正在激活singleDN 模式 */else if (name != NULL && strcmp(name, "single_node") == 0 && value == NULL) {g_instance.role = VSINGLENODE;useLocalXid = true;} else if (name != NULL && strcmp(name, "restoremode") == 0 && value == NULL) {/** 在恢復模式下,協調器和數據節點在內部都被視為數據節點*/isRestoreMode = true;g_instance.role = VDATANODE;} else if (name != NULL && 0 == strcmp(name, "fenced") && value == NULL)FencedUDFMasterMode = true;else if (name != NULL && strlen(name) == SECURITY_MODE_NAME_LEN &&strncmp(name, SECURITY_MODE_NAME, SECURITY_MODE_NAME_LEN) == 0 && value == NULL) {/* 在安全模式下,打開安全策略 */isSecurityMode = true;} else {/* 默認大小寫 */if (value == NULL) {if (opt == '-')ereport(ERROR,(errcode(ERRCODE_SYNTAX_ERROR), errmsg("--%s requires a value", optCtxt.optarg)));elseereport(ERROR,(errcode(ERRCODE_SYNTAX_ERROR), errmsg("-c %s requires a value", optCtxt.optarg)));}SetConfigOption(name, value, PGC_POSTMASTER, PGC_S_ARGV);}pfree(name);if (value != NULL) {pfree(value);}break;}default:write_stderr("Try \"%s --help\" for more information.\n", progname);ExitPostmaster(1);}}/** 找到正確的配置文件和數據目錄,并首次讀取postgresql.conf。*/ #if ((defined ENABLE_PYTHON2) || (defined ENABLE_PYTHON3))if (!SelectConfigFiles(userDoption, progname))ExitPostmaster(1);if (strlen(GetConfigOption(const_cast<char*>("unix_socket_directory"), true, false)) != 0) {PythonFencedMasterModel = true;/* 禁用受防護 UDF 進程的 bbox */SetConfigOption("enable_bbox_dump", "false", PGC_POSTMASTER, PGC_S_ARGV);} #elseif (FencedUDFMasterMode) {/* 禁用受防護 UDF 進程的 bbox */SetConfigOption("enable_bbox_dump", "false", PGC_POSTMASTER, PGC_S_ARGV);} else if (!SelectConfigFiles(userDoption, progname)) {ExitPostmaster(1);} #endifif ((g_instance.attr.attr_security.transparent_encrypted_string != NULL &&g_instance.attr.attr_security.transparent_encrypted_string[0] != '\0') &&(g_instance.attr.attr_common.transparent_encrypt_kms_url != NULL &&g_instance.attr.attr_common.transparent_encrypt_kms_url[0] != '\0') &&(g_instance.attr.attr_security.transparent_encrypt_kms_region != NULL &&g_instance.attr.attr_security.transparent_encrypt_kms_region[0] != '\0')) {isSecurityMode = true;}/** 初始化Postmaster級別的 GUC 選項。** 請注意,由于某些全局變量沒有初始化,所以某些 guc 無法獲得正確的值,* 例如single_node模式,因此需要此函數來初始化 Postmaster 級別的 guc。*/InitializePostmasterGUC();t_thrd.myLogicTid = noProcLogicTid + POSTMASTER_LID;if (output_config_variable != NULL) {/** 處理權限是因為用戶在data dir中讀取數據*/puts(GetConfigOption(output_config_variable, false, false));ExitPostmaster(0);}InitializeNumLwLockPartitions();noProcLogicTid = GLOBAL_ALL_PROCS;if (FencedUDFMasterMode) {/* t_thrd.proc_cxt 必須設置DataDir */if (userDoption != NULL && userDoption[0] == '/') {if (chdir(userDoption) == -1)ExitPostmaster(1);SetDataDir(userDoption);} else {ExitPostmaster(1);}/*初始化除信號監視器之外的所有子線程的線程參數池 */gs_thread_args_pool_init(GLOBAL_ALL_PROCS + EXTERN_SLOTS_NUM, sizeof(BackendParameters));/* 初始化信號管理結構 */gs_signal_slots_init(GLOBAL_ALL_PROCS + EXTERN_SLOTS_NUM);gs_signal_startup_siginfo("PostmasterMain");gs_signal_monitor_startup();g_instance.attr.attr_common.Logging_collector = true;g_instance.global_sysdbcache.Init(INSTANCE_GET_MEM_CXT_GROUP(MEMORY_CONTEXT_DEFAULT));CreateLocalSysDBCache();g_instance.pid_cxt.SysLoggerPID = SysLogger_Start();FencedUDFMasterMain(0, NULL);return 0;}/* 驗證t_thrd.proc_cxt.DataDir看起來是合理的 (確保數據庫安裝成功及PGDATA目錄有效)*/checkDataDir();/* 并將工作目錄切換到其中 */ChangeToDataDir();/** 檢查無效的GUC設置組合。*/CheckGUCConflicts();/* 設置并行恢復配置 */ConfigRecoveryParallelism();ProcessRedoCpuBindInfo();/**如果速度快的話,其他一次性內部檢查可在此處進行。*(在 postmaster.pid 創建之后,把一些緩慢的程序放下。)*/if (!CheckDateTokenTables()) {write_stderr("%s: invalid datetoken tables, please fix\n", progname);ExitPostmaster(1);}initKnlRTOContext();/** 現在我們已經完成了對 postmaster 參數的處理, 重置 getopt(3) 庫,* 以便它將在子進程中正常工作。*/optCtxt.optind = 1; #ifdef HAVE_INT_OPTRESEToptreset = 1; /* 有些系統也需要這個 */ #endifint rc1 = snprintf_s(gaussdb_state_file, sizeof(gaussdb_state_file), MAXPGPATH - 1, "%s/gaussdb.state", t_thrd.proc_cxt.DataDir);securec_check_intval(rc1, , -1);gaussdb_state_file[MAXPGPATH - 1] = '\0';if (!SetDBStateFileState(UNKNOWN_STATE, true)) {write_stderr("Failed to set gaussdb.state with UNKNOWN_STATE");ExitPostmaster(1);}if (g_instance.attr.attr_storage.dcf_attr.enable_dcf) {rc1 = snprintf_s(AddMemberFile, sizeof(AddMemberFile), MAXPGPATH - 1, "%s/addmember", t_thrd.proc_cxt.DataDir);securec_check_intval(rc1, , -1);AddMemberFile[MAXPGPATH - 1] = '\0';rc1 = snprintf_s(RemoveMemberFile, sizeof(RemoveMemberFile), MAXPGPATH - 1, "%s/removemember",t_thrd.proc_cxt.DataDir);securec_check_intval(rc1, , -1);RemoveMemberFile[MAXPGPATH - 1] = '\0';rc1 = snprintf_s(TimeoutFile, sizeof(TimeoutFile), MAXPGPATH - 1, "%s/timeout", t_thrd.proc_cxt.DataDir);securec_check_intval(rc1, , -1);TimeoutFile[MAXPGPATH - 1] = '\0';rc1 = snprintf_s(SwitchoverStatusFile, sizeof(SwitchoverStatusFile), MAXPGPATH - 1, "%s/switchoverstatus",t_thrd.proc_cxt.DataDir);securec_check_intval(rc1, , -1);SwitchoverStatusFile[MAXPGPATH - 1] = '\0';rc1 = snprintf_s(SetRunmodeStatusFile, sizeof(SetRunmodeStatusFile), MAXPGPATH - 1, "%s/setrunmodestatus",t_thrd.proc_cxt.DataDir);securec_check_intval(rc1, , -1);SetRunmodeStatusFile[MAXPGPATH - 1] = '\0';rc1 = snprintf_s(g_changeRoleStatusFile, sizeof(g_changeRoleStatusFile), MAXPGPATH - 1, "%s/changerolestatus",t_thrd.proc_cxt.DataDir);securec_check_intval(rc1, , -1);g_changeRoleStatusFile[MAXPGPATH - 1] = '\0';rc1 =snprintf_s(ChangeRoleFile, sizeof(ChangeRoleFile), MAXPGPATH - 1, "%s/changerole", t_thrd.proc_cxt.DataDir);securec_check_intval(rc1, , -1);ChangeRoleFile[MAXPGPATH - 1] = '\0';rc1 = snprintf_s(StartMinorityFile, sizeof(StartMinorityFile), MAXPGPATH - 1, "%s/startminority",t_thrd.proc_cxt.DataDir);securec_check_intval(rc1, , -1);StartMinorityFile[MAXPGPATH - 1] = '\0';}/* 用于調試:顯示Postmaster環境 */{extern char** environ;char** p;ereport(DEBUG3, (errmsg_internal("%s: PostmasterMain: initial environment dump:", progname)));ereport(DEBUG3, (errmsg_internal("-----------------------------------------")));for (p = environ; *p; ++p)ereport(DEBUG3, (errmsg_internal("\t%s", *p)));ereport(DEBUG3, (errmsg_internal("-----------------------------------------")));}rc = memcpy_s(g_alarmComponentPath, MAXPGPATH - 1, Alarm_component, strlen(Alarm_component));securec_check_c(rc, "\0", "\0");g_alarmReportInterval = AlarmReportInterval;AlarmEnvInitialize();/** 為數據目錄創建lockfile。**我們希望在嘗試獲取輸入套接字之前執行此操作,因為數據目錄互鎖比套*接字文件聯鎖更可靠(感謝決定將套接字文件放入 /tmp :-( 的人。)*出于同樣的原因,最好在Unix套接字之前獲取TCP套接字。*/CreateDataDirLockFile(true);/* 模塊加載回調 */pgaudit_agent_init();auto_explain_init();ledger_hook_init();/** 處理應在Postmaster啟動時預加載的庫*/process_shared_preload_libraries();/** 建立輸入套接字。*/for (i = 0; i < MAXLISTEN; i++)t_thrd.postmaster_cxt.ListenSocket[i] = PGINVALID_SOCKET;if (g_instance.attr.attr_network.ListenAddresses && !dummyStandbyMode) {char* rawstring = NULL;List* elemlist = NULL;ListCell* l = NULL;int success = 0;/** 如果需要,啟動 commproxy*/if (CommProxyNeedSetup()) {CommProxyStartUp();}/* 需要g_instance.attr.attr_network.ListenAddresses的可修改副本 */rawstring = pstrdup(g_instance.attr.attr_network.ListenAddresses);/* 將字符串解析為標識符列表 */if (!SplitIdentifierString(rawstring, ',', &elemlist)) {/* 列表中的語法錯誤 */ereport(FATAL,(errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("invalid list syntax for \"listen_addresses\"")));}bool haswildcard = false;foreach (l, elemlist) {char* curhost = (char*)lfirst(l);if (strcmp(curhost, "*") == 0) {haswildcard = true;break;}}if (haswildcard == true) {char *wildcard = "*";elemlist = list_cell_clear(elemlist, (void *)wildcard, isNotWildcard);}foreach (l, elemlist) {char* curhost = (char*)lfirst(l);if (strcmp(curhost, "*") == 0)status = StreamServerPort(AF_UNSPEC,NULL,(unsigned short)g_instance.attr.attr_network.PostPortNumber,g_instance.attr.attr_network.UnixSocketDir,t_thrd.postmaster_cxt.ListenSocket,MAXLISTEN,true,true,false);elsestatus = StreamServerPort(AF_UNSPEC,curhost,(unsigned short)g_instance.attr.attr_network.PostPortNumber,g_instance.attr.attr_network.UnixSocketDir,t_thrd.postmaster_cxt.ListenSocket,MAXLISTEN,true,true,false);if (status == STATUS_OK)success++;else {print_port_info();ereport(FATAL,(errmsg("could not create listen socket for \"%s:%d\"",curhost,g_instance.attr.attr_network.PostPortNumber)));}/* 目前,我們不監聽NORMAL_MODE下的 replconn 通道,因此需要pooler端口 */use_pooler_port = NeedPoolerPort(curhost);if (t_thrd.xlog_cxt.server_mode == NORMAL_MODE || use_pooler_port == -1) {/* 在 om 和其他維護工具中,pooler端口被硬連線為 gsql 端口加 1 */if (g_instance.attr.attr_network.PoolerPort != (g_instance.attr.attr_network.PostPortNumber + 1)) {ereport(FATAL, (errmsg("pooler_port must equal to gsql listen port plus one!")));}if (strcmp(curhost, "*") == 0) {status = StreamServerPort(AF_UNSPEC,NULL,(unsigned short)g_instance.attr.attr_network.PoolerPort,g_instance.attr.attr_network.UnixSocketDir,t_thrd.postmaster_cxt.ListenSocket,MAXLISTEN,false,false,false);} else {status = StreamServerPort(AF_UNSPEC,curhost,(unsigned short)g_instance.attr.attr_network.PoolerPort,g_instance.attr.attr_network.UnixSocketDir,t_thrd.postmaster_cxt.ListenSocket,MAXLISTEN,false,false,false);}if (status != STATUS_OK)ereport(FATAL,(errmsg("could not create ha listen socket for \"%s:%d\"",curhost,g_instance.attr.attr_network.PoolerPort)));/** 記錄第一個成功的主機addr,addr并不意味著鎖定文件中的“localhost”。* 內部維護工具,如 cm_agent 和 gs_ctl 將使用該主機來連接cn。*/if (!listen_addr_saved && !IsInplicitIp(curhost)) {AddToDataDirLockFile(LOCK_FILE_LINE_LISTEN_ADDR, curhost);listen_addr_saved = true;}}}if (!success && list_length(elemlist))ereport(FATAL, (errmsg("could not create any TCP/IP sockets")));list_free_ext(elemlist);pfree(rawstring);}if (t_thrd.xlog_cxt.server_mode != NORMAL_MODE) {SetListenSocket(t_thrd.postmaster_cxt.ReplConnArray, &listen_addr_saved);ReportResumeAbnormalDataHAInstListeningSocket();}SetListenSocket(t_thrd.postmaster_cxt.CrossClusterReplConnArray, &listen_addr_saved);ReportResumeAbnormalDataHAInstListeningSocket(); #ifdef USE_BONJOUR/* 僅當我們打開了 TCP 套接字時才注冊 Bonjour */if (g_instance.attr.attr_common.enable_bonjour && t_thrd.postmaster_cxt.ListenSocket[0] != PGINVALID_SOCKET) {DNSServiceErrorType err;/**我們為interface_index傳遞 0 ,這將導致在所有“適用”接口上注冊。 *從DNS-SD文檔中并不完全清楚,如果我們只綁定到可用網絡接口的子集,這是否合適。*/err = DNSServiceRegister(&bonjour_sdref,0,0,g_instance.attr.attr_common.bonjour_name,"_postgresql._tcp.",NULL,NULL,htons(g_instance.attr.attr_network.PostPortNumber),0,NULL,NULL,NULL);if (err != kDNSServiceErr_NoError)ereport(LOG, (errmsg("DNSServiceRegister() failed: error code %ld", (long)err)));/** 不必閱讀 mDNS 守護程序的回復,并且我們希望當postmaster* 終止時套接字關閉,它將自動終止我們的注冊。 所以這里沒有什* 么可做的了。 但是,bonjour_sdref保留在周圍,以便fork的子程序* 可以關閉其套接字的副本。*/}#endif#ifdef HAVE_UNIX_SOCKETSif (!dummyStandbyMode) {/* unix socket for gsql port */status = StreamServerPort(AF_UNIX,NULL,(unsigned short)g_instance.attr.attr_network.PostPortNumber,g_instance.attr.attr_network.UnixSocketDir,t_thrd.postmaster_cxt.ListenSocket,MAXLISTEN,false,true,false);if (status != STATUS_OK)ereport(FATAL,(errmsg("could not create Unix-domain socket for \"%s:%d\"",g_instance.attr.attr_network.UnixSocketDir,g_instance.attr.attr_network.PostPortNumber)));/* unix socket for ha port */status = StreamServerPort(AF_UNIX,NULL,(unsigned short)g_instance.attr.attr_network.PoolerPort,g_instance.attr.attr_network.UnixSocketDir,t_thrd.postmaster_cxt.ListenSocket,MAXLISTEN,false,false,false);if (status != STATUS_OK)ereport(FATAL,(errmsg("could not create Unix-domain socket for \"%s:%d\"",g_instance.attr.attr_network.UnixSocketDir,g_instance.attr.attr_network.PoolerPort)));/** 創建監聽的 unix 域套接字以接收來自receiver_loop線程的gs_sock。* 注意:由于我們將在以后使用全局變量sock_path來初始化libcomm,* 因此此套接字必須是最后創建的unix域套接字。否則,sock_path將被其他路徑替換。*/if (g_instance.attr.attr_storage.comm_cn_dn_logic_conn && !isRestoreMode && !IS_SINGLE_NODE) {status = StreamServerPort(AF_UNIX,NULL,(unsigned short)g_instance.attr.attr_network.comm_sctp_port,g_instance.attr.attr_network.UnixSocketDir,t_thrd.postmaster_cxt.ListenSocket,MAXLISTEN,false,true,true);if (status != STATUS_OK)ereport(WARNING, (errmsg("could not create Unix-domain for comm socket")));}} #endif/** 檢查我們是否有一些套接字可以收聽*/if (t_thrd.postmaster_cxt.ListenSocket[0] == PGINVALID_SOCKET) {ereport(FATAL, (errmsg("no socket created for listening")));}/** 設置一個on_proc_exit函數,該函數負責在postmaster關閉時再次關閉套接字。 * 您可能認為我們應該更早地執行此操作,但我們希望它在proc_exit回調刪除* Unix套接字文件之前而不是之后運行。*/on_proc_exit(CloseServerPorts, 0);/** 如果沒有有效的 TCP 端口,請編寫一個空行進行監聽,表示必須使用 Unix 套接字。 * 請注意,在有套接字支持它之前,不會將此行添加到鎖定文件中。*/if (!listen_addr_saved) {AddToDataDirLockFile(LOCK_FILE_LINE_LISTEN_ADDR, "");ereport(WARNING, (errmsg("No explicit IP is configured for listen_addresses GUC.")));}if (g_instance.attr.attr_common.enable_thread_pool) {/* 無需為虛擬備用節點啟動線程池。 */if (!dummyStandbyMode) {g_threadPoolControler = (ThreadPoolControler*)New(INSTANCE_GET_MEM_CXT_GROUP(MEMORY_CONTEXT_EXECUTOR)) ThreadPoolControler();g_threadPoolControler->SetThreadPoolInfo();} else {g_instance.attr.attr_common.enable_thread_pool = false;g_threadPoolControler = NULL;AdjustThreadAffinity();}}/* 初始化 gstrace context */int errcode = gstrace_init(g_instance.attr.attr_network.PostPortNumber);if (errcode != 0) {ereport(LOG, (errmsg("gstrace initializes with failure. errno = %d.", errcode)));}InitGlobalBcm();/** 設置共享內存和信號量。* (主要包括頁面緩存池、各種鎖緩存池、WAL日志緩存池、事務日志緩存池、* 事務(號)概況緩存池、各后臺線程(鎖使用)概況緩存池、各后臺線程等* 待和運行狀態緩存池、兩階段狀態緩存池、檢查點緩存池、WAL日志復制和接* 收緩存池、數據頁復制和接收緩存池等。在后續階段創建出的客戶端后臺線程* 以及各個輔助線程均使用該共享內存空間,不再單獨開辟 )*/reset_shared(g_instance.attr.attr_network.PostPortNumber);/* Alloc 數組進行后端記錄 */BackendArrayAllocation();/* 初始化除信號監視器之外的所有子線程的線程參數池*/gs_thread_args_pool_init(GLOBAL_ALL_PROCS + EXTERN_SLOTS_NUM, sizeof(BackendParameters));// 1.初始化信號管理結構//gs_signal_slots_init(GLOBAL_ALL_PROCS + EXTERN_SLOTS_NUM);gs_signal_startup_siginfo("PostmasterMain");gs_signal_monitor_startup();/** 估計可打開文件的數量。 這必須在設置信號量后發生,* 因為在某些平臺上,信號量算作打開的文件。*/SetHaShmemData();PMInitDBStateFile();set_max_safe_fds();/** 設置堆棧深度檢查的參考點。*/set_stack_base();/** 初始化活動后端的列表。*/g_instance.backend_list = DLNewList();/** 初始化管道(或 Windows 上的進程句柄),允許在postmaster死亡時從休眠狀態中喚醒子線程。*/InitPostmasterDeathWatchHandle();#ifdef WIN32/** 初始化用于提供已死子列表的 I/O 完成端口。*/win32ChildQueue = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 1);if (win32ChildQueue == NULL)ereport(FATAL, (errmsg("could not create I/O completion port for child queue")));#endif/** 記錄postmaster選項。 我們將其推遲到現在,以避免記錄虛假選項* (例如,NBuffers對于可用內存來說太高了)。*/if (!CreateOptsFile(argc, (const char**)argv, (const char*)my_exec_path))ExitPostmaster(1);#ifdef EXEC_BACKEND/* 寫出供子進程使用的非默認 GUC 設置 */write_nondefault_variables(PGC_POSTMASTER); #endif#ifndef ENABLE_LITE_MODE #if defined (ENABLE_MULTIPLE_NODES) || defined (ENABLE_PRIVATEGAUSS)/* init hotpatch */if (hotpatch_remove_signal_file(t_thrd.proc_cxt.DataDir) == HP_OK) {int ret;ret = hotpatch_init(t_thrd.proc_cxt.DataDir, (HOTPATCH_LOG_FUNC)gs_hotpatch_log_callback);if (ret != HP_OK) {write_stderr("hotpatch init failed ret is %d!\n", ret);}} #endif #endif/** 如果需要,寫入外部 PID 文件*/if (g_instance.attr.attr_common.external_pid_file) {FILE* fpidfile = fopen(g_instance.attr.attr_common.external_pid_file, "w");if (fpidfile != NULL) {fprintf(fpidfile, "%lu\n", t_thrd.proc_cxt.MyProcPid);fclose(fpidfile);/* 在postmaster退出時,我們是否應該刪除 pid 文件? *//* 使 PID 文件世界可讀 */if (chmod(g_instance.attr.attr_common.external_pid_file, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) != 0)write_stderr("%s: could not change permissions of external PID file \"%s\": %s\n",progname,g_instance.attr.attr_common.external_pid_file,gs_strerror(errno));} elsewrite_stderr("%s: could not write external PID file \"%s\": %s\n",progname,g_instance.attr.attr_common.external_pid_file,gs_strerror(errno));}/** 為postmaster流程設置信號處理程序。* 注意:更改此列表時,請檢查子進程的信號處理設置是否存在副作用。 * 請參閱 tcop/postgres.c、bootstrap/bootstrap.c、postmaster/bgwriter.c、* postmaster/walwriter.c、postmaster/autovacuum.c、postmaster/pgarch.c、* postmaster/pgstat.c、postmaster/syslogger.c 和 postmaster/checkpointer.c。*/gs_signal_setmask(&t_thrd.libpq_cxt.BlockSig, NULL);gs_signal_block_sigusr2();(void)gspqsignal(SIGHUP, SIGHUP_handler); /* 重新讀取配置文件并讓做同樣的事情 */(void)gspqsignal(SIGINT, pmdie); /* send SIGTERM and shut down */(void)gspqsignal(SIGQUIT, pmdie); /* send SIGQUIT and die */(void)gspqsignal(SIGTERM, pmdie); /* wait for children and shut down */pqsignal(SIGALRM, SIG_IGN); /* ignored */pqsignal(SIGPIPE, SIG_IGN); /* ignored */pqsignal(SIGFPE, FloatExceptionHandler);(void)gspqsignal(SIGUSR1, sigusr1_handler); /* 來自子進程的消息*/(void)gspqsignal(SIGUSR2, dummy_handler); /* unused, reserve for children */(void)gspqsignal(SIGCHLD, reaper); /* handle child termination */(void)gspqsignal(SIGTTIN, SIG_IGN); /* ignored */(void)gspqsignal(SIGTTOU, SIG_IGN); /* ignored *//* 忽略 SIGXFSZ,以便 ulimit 沖突的工作方式類似于磁盤已滿 */ #ifdef SIGXFSZ(void)gspqsignal(SIGXFSZ, SIG_IGN); /* ignored */ #endif/* 核心轉儲注入*/bbox_initialize();/** 初始化stats收集子系統(這不會啟動收集器進程!*/pgstat_init();/* 初始化全局統計信息跟蹤器 */GlobalStatsTrackerInit();/* 初始化工作負載管理器 */InitializeWorkloadManager();g_instance.global_sysdbcache.Init(INSTANCE_GET_MEM_CXT_GROUP(MEMORY_CONTEXT_DEFAULT));CreateLocalSysDBCache();/* Init proc 的 subxid 緩存上下文, 父級是 g_instance.instance_context */ProcSubXidCacheContext = AllocSetContextCreate(g_instance.instance_context,"ProcSubXidCacheContext",ALLOCSET_DEFAULT_MINSIZE,ALLOCSET_DEFAULT_INITSIZE,ALLOCSET_DEFAULT_MAXSIZE,SHARED_CONTEXT);/** 為流線程連接創建 StreamInfoContext,父級為 g_instance.instance_context。所有流線程將共享此上下文。*/StreamInfoContext = AllocSetContextCreate(g_instance.instance_context,"StreamInfoContext",ALLOCSET_DEFAULT_MINSIZE,ALLOCSET_DEFAULT_INITSIZE,ALLOCSET_DEFAULT_MAXSIZE,SHARED_CONTEXT);/* 創建全局高速緩存上下文 */knl_g_cachemem_create();/* 創建節點組緩存哈希表 */ngroup_info_hash_create();/*初始化角色 ID 哈希表*/InitRoleIdHashTable();/* pcmap */RealInitialMMapLockArray();/* 初始化唯一的 sql */InitUniqueSQL();/* 初始化指數 */InitHypopg();InitAsp();/* 初始化 instr 用戶 */InitInstrUser();/* 初始化 Opfusion 函數 id */InitOpfusionFunctionId();/* 初始化捕獲視圖 */init_capture_view();/* 初始化百分位數 */InitPercentile();/* 初始化動態語句跟蹤控制*/InitTrackStmtControl();/* 初始化全局序列 */InitGlobalSeq(); #ifdef ENABLE_MULTIPLE_NODES/* 初始化壓實 */CompactionProcess::init_instance();/** 設置 TsStoreTagsCache*/if (g_instance.attr.attr_common.enable_tsdb) {TagsCacheMgr::GetInstance().init();PartIdMgr::GetInstance().init();Tsdb::PartCacheMgr::GetInstance().init();InitExtensiblePlanMethodsHashTable();} #endif/** 如果啟用,啟動syslog日志收集子進程*/g_instance.pid_cxt.SysLoggerPID = SysLogger_Start();if (IS_PGXC_DATANODE && !dummyStandbyMode && !isRestoreMode) {StreamObj::startUp();StreamNodeGroup::StartUp();pthread_mutex_init(&nodeDefCopyLock, NULL);}/* 初始化 usedDnSpace 哈希表*/InitDnHashTable();/** 加載用于客戶端身份驗證的配置文件。在通信線程之前加載 pg_hba.conf。*/int loadhbaCount = 0;while (!load_hba()) {check_old_hba(true);loadhbaCount++;if (loadhbaCount >= 3) {/** 如果無法加載 HBA 文件,則繼續操作是沒有意義的,* 因為在這種情況下,無法連接到數據庫。*/ereport(FATAL, (errmsg("could not load pg_hba.conf")));}pg_usleep(200000L); /* sleep 200ms for reload next time */}if (ENABLE_THREAD_POOL_DN_LOGICCONN) {InitCommLogicResource();}if ((!IS_SINGLE_NODE) &&((IS_PGXC_DATANODE && !dummyStandbyMode && !isRestoreMode) ||(IS_PGXC_COORDINATOR && g_instance.attr.attr_storage.comm_cn_dn_logic_conn && !isRestoreMode))) {status = init_stream_comm();if (status != STATUS_OK)ereport(FATAL, (errmsg("Init libcomm for stream failed, maybe listen port already in use")));}if (g_instance.attr.attr_security.enable_tde) {/* 初始化云 KMS 消息實例*/TDE::CKMSMessage::get_instance().init();TDE::CKMSMessage::get_instance().load_user_info();/* 初始化 TDE 存儲哈希表 */if (IS_PGXC_DATANODE) {TDE::TDEKeyStorage::get_instance().init();TDE::TDEBufferCache::get_instance().init();}}#ifndef ENABLE_LITE_MODEif (g_instance.attr.attr_storage.enable_adio_function)AioResourceInitialize(); #endif/* 啟動警報檢查器線程。 */if (!dummyStandbyMode)g_instance.pid_cxt.AlarmCheckerPID = startAlarmChecker();/* 啟動收割者后端線程,該線程始終處于活動狀態。 */g_instance.pid_cxt.ReaperBackendPID = initialize_util_thread(REAPER);/** 將 WhereToSendOutput 從 DestDebug(其起始狀態)重置為 DestNone。* 這將阻止 ereport 向 stderr 發送日志消息,除非t_thrd.aes_cxt.Log_destination允許。 * 在postmaster完全啟動之前,我們不會這樣做,因為啟動失敗也可以報告給stderr。*/t_thrd.postgres_cxt.whereToSendOutput = DestNone;/** 初始化autovacum子系統(同樣,尚未啟動進程)*/autovac_init();load_ident();/** 刪除舊的臨時文件。 此時,此目錄中不能運行其他 openGauss 進程,因此這應該是安全的。*/RemovePgTempFiles();RemoveErrorCacheFiles();/** 記住postmaster啟動時間*/t_thrd.time_cxt.pg_start_time = GetCurrentTimestamp();/* 節點統計驗證時間戳 */gs_lock_test_and_set_64(&g_instance.stat_cxt.NodeStatResetTime, GetCurrentTimestamp());/* PostmasterRandom想要自己的拷貝 */gettimeofday(&t_thrd.postmaster_cxt.random_start_time, NULL);/** We're ready to rock and roll...*/ShareStorageInit();g_instance.pid_cxt.StartupPID = initialize_util_thread(STARTUP);Assert(g_instance.pid_cxt.StartupPID != 0);pmState = PM_STARTUP;#ifdef ENABLE_MULTIPLE_NODESif (IS_PGXC_COORDINATOR) {MemoryContext oldcontext = MemoryContextSwitchTo(THREAD_GET_MEM_CXT_GROUP(MEMORY_CONTEXT_DEFAULT));/** 初始化數據節點連接池。pooler 線程不再存在,* StartPoolManager() 是 PoolManagerInit() 的別名。*/StartPoolManager();MemoryContextSwitchTo(oldcontext);}load_searchserver_library(); #endif/* * 保存DCF回調線程的后端變量,保存的后端變量將在DCF回調線程共享內存init函數中恢復。*/if (g_instance.attr.attr_storage.dcf_attr.enable_dcf) {int ss_rc = memset_s(&port, sizeof(port), 0, sizeof(port));securec_check(ss_rc, "\0", "\0");port.sock = PGINVALID_SOCKET;BackendVariablesGlobal = static_cast<BackendParameters *>(palloc(sizeof(BackendParameters)));save_backend_variables(BackendVariablesGlobal, &port);}/* 如果從plpython fenced模式開始,我們只需以fenced模式啟動 */if (PythonFencedMasterModel) {/** 如果啟用,啟動syslog日志收集子進程*/g_instance.attr.attr_common.Logging_collector = true;g_instance.pid_cxt.SysLoggerPID = SysLogger_Start();StartUDFMaster();}if (status == STATUS_OK)status = ServerLoop();/** ServerLoop可能永遠不應該返回,但如果返回,請關閉。*/ExitPostmaster(status != STATUS_OK);return 0; /* not reached */ }

    總結

    以上是生活随笔為你收集整理的OpenGauss线程管理-主线程-Postmaster(1)的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。