ADD file via upload

This commit is contained in:
makqmlwy5 2023-10-04 23:18:01 +08:00
parent 92e8042b7b
commit ca568d528b
1 changed files with 567 additions and 0 deletions

View File

@ -0,0 +1,567 @@
/*
*
* main.cpp
* Stub main() routine for the openGauss executable.
*
* This does some essential startup tasks for any incarnation of openGauss
* (postmaster, standalone backend, standalone bootstrap process, or a
* separately exec'd child of a postmaster) and then dispatches to the
* proper FooMain() routine for the incarnation.
*
*
* 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
*
*
* IDENTIFICATION
* src/gausskernel/process/main/main.cpp
*
* -------------------------------------------------------------------------
*/
#include "postgres.h"
#include "knl/knl_variable.h"
#include <pwd.h>
#include <unistd.h>
#if defined(__alpha) && defined(__osf__) /* no __alpha__ ? */
#include <sys/sysinfo.h>
#include "machine/hal_sysinfo.h"
#define ASSEMBLER
#include <sys/proc.h>
#undef ASSEMBLER
#endif
#if defined(__NetBSD__)
#include <sys/param.h>
#endif
#include "bootstrap/bootstrap.h"
#include "postmaster/postmaster.h"
#include "miscadmin.h"
#include "storage/ipc.h"
#include "tcop/tcopprot.h"
#include "utils/fmgrtab.h"
#include "utils/help_config.h"
#include "utils/pg_locale.h"
#include "utils/ps_status.h"
#ifdef WIN32
#include "libpq/pqsignal.h"
#endif
#include "utils/syscall_lock.h"
#include "gssignal/gs_signal.h"
#include "utils/memutils.h"
#include "utils/mmpool.h"
#include "utils/plog.h"
#include "gstrace/gstrace_infra.h"
THR_LOCAL bool IsInitdb = false;
size_t mmap_threshold = (size_t)0xffffffff;
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 syscall_lock_init(void);
extern int encrypte_main(int argc, char* const argv[]);
/*
* Any openGauss server process begins execution here.
*/
int main(int argc, char* argv[])
{
char* mmap_env = NULL;
syscall_lock_init();
// 从环境变量中获取GAUSS_MMAP_THRESHOLD的值并设置mmap_threshold变量
mmap_env = gs_getenv_r("GAUSS_MMAP_THRESHOLD");
if (mmap_env != NULL) {
check_backend_env(mmap_env);
mmap_threshold = (size_t)atol(mmap_env);
}
// 初始化KNL实例
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);
// 创建备机帐号上下文
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.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
*
* Code after this point is allowed to use elog/ereport, though
* localization of messages may not work right away, and messages won't go
* anywhere but stderr until GUC settings get loaded.
*/
// 初始化内存上下文
MemoryContextInit();
// 设置全局变量PmTopMemoryContext为顶层内存上下文
PmTopMemoryContext = t_thrd.top_mem_cxt;
// 初始化线程
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;
// 将当前会话设置为虚拟会话
u_sess = t_thrd.fake_session;
// 设置SelfMemoryContext为默认内存上下文组
SelfMemoryContext = THREAD_GET_MEM_CXT_GROUP(MEMORY_CONTEXT_DEFAULT);
// 切换到默认内存上下文组
MemoryContextSwitchTo(THREAD_GET_MEM_CXT_GROUP(MEMORY_CONTEXT_DEFAULT));
// 获取程序名称
progname = get_progname(argv[0]);
/*
* Platform-specific startup hacks
*/
startup_hacks(progname);
/* if gaussdb's name is gs_encrypt, so run in encrypte_main() */
if (!strcmp(progname, "gs_encrypt")) {
return encrypte_main(argc, argv);
}
// 初始化plog全局内存
init_plog_global_mem();
/*
* Remember the physical location of the initially given argv[] array for
* possible use by ps display. On some platforms, the argv[] storage must
* be overwritten in order to set the process title for ps. In such cases,
* save_ps_display_args makes and returns a new copy of the argv[] array.
*
* save_ps_display_args may also move the environment strings to make
* extra room. Therefore this should be done as early as possible during
* startup, to avoid entanglements with code that might save a getenv()
* result pointer.
*/
argv = save_ps_display_args(argc, argv);
/*
* If supported on the current platform, set up a handler to be called if
* the backend/postmaster crashes with a fatal signal or exception.
*/
#if defined(WIN32) && defined(HAVE_MINIDUMP_TYPE)
pgwin32_install_crashdump_handler();
#endif
/*
* Set up locale information from environment. Note that LC_CTYPE and
* LC_COLLATE will be overridden later from pg_control if we are in an
* already-initialized database. We set them here so that they will be
* available to fill pg_control during initdb. LC_MESSAGES will get set
* later during GUC option processing, but we set it here to allow startup
* error messages to be localized.
*/
set_pglocale_pgservice(argv[0], PG_TEXTDOMAIN("gaussdb"));
#ifdef WIN32
/*
* Windows uses codepages rather than the environment, so we work around
* that by querying the environment explicitly first for LC_COLLATE and
* LC_CTYPE. We have to do this because initdb passes those values in the
* environment. If there is nothing there we fall back on the codepage.
*/
{
char* env_locale = NULL;
if ((env_locale = gs_getenv_r("LC_COLLATE")) != NULL) {
check_backend_env(env_locale);
pg_perm_setlocale(LC_COLLATE, env_locale);
} else
pg_perm_setlocale(LC_COLLATE, "");
if ((env_locale = gs_getenv_r("LC_CTYPE")) != NULL) {
check_backend_env(env_locale);
pg_perm_setlocale(LC_CTYPE, env_locale);
} else
pg_perm_setlocale(LC_CTYPE, "");
}
#else
pg_perm_setlocale(LC_COLLATE, "");
pg_perm_setlocale(LC_CTYPE, "");
#endif
/*
* We keep these set to "C" always, except transiently in pg_locale.c; see
* that file for explanations.
*/
pg_perm_setlocale(LC_MONETARY, "C"); // 将货币格式化设置为"C"语言环境
pg_perm_setlocale(LC_NUMERIC, "C"); // 将数字格式化设置为"C"语言环境
pg_perm_setlocale(LC_TIME, "C"); // 将时间格式化设置为"C"语言环境
/*
* Now that we have absorbed as much as we wish to from the locale
* environment, remove any LC_ALL setting, so that the environment
* variables installed by pg_perm_setlocale have force.
*/
(void)unsetenv("LC_ALL"); // 移除LC_ALL设置以确保pg_perm_setlocale设置的环境变量生效
/*
* Catch standard options before doing much else
*/
if (argc > 1) {
if (strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-?") == 0) {
help(progname); // 显示帮助信息
exit(0);
}
if (strcmp(argv[1], "--version") == 0 || strcmp(argv[1], "-V") == 0) {
puts("gaussdb " DEF_GS_VERSION); // 显示版本号
exit(0);
}
}
/*
* Make sure we are not running as root.
*/
check_root(progname); // 检查是否以root用户身份运行
/*
* Dispatch to one of various subprograms depending on first argument.
*/
#ifdef WIN32
/*
* Start our win32 signal implementation
*
* SubPostmasterMain() will do this for itself, but the remaining modes
* need it here
*/
pgwin32_signal_initialize(); // 在Windows平台上启动信号处理
#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);
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);
}
/*
* @BuiltinFunc
* Create a global BuiltinFunc object shared among threads
*/
if (g_sorted_funcs[0] == NULL) {
initBuiltinFuncs(); // 初始化内置函数相关的全局变量
}
bool isBoot = (argc > 1 && strcmp(argv[1], "--boot") == 0);
if (isBoot) {
IsInitdb = true;
gs_signal_monitor_startup(); // 启动信号监控工作线程
gs_signal_slots_init(1); // 初始化信号插槽
(void)gs_signal_unblock_sigusr2(); // 解除SIGUSR2信号的阻塞
gs_signal_startup_siginfo("AuxiliaryProcessMain"); // 记录启动信息
BootStrapProcessMain(argc, argv); /* does not return */
}
if (argc > 1 && strcmp(argv[1], "--describe-config") == 0)
exit(GucInfoMain()); // 打印GUC参数信息
if (argc > 1 && strcmp(argv[1], "--single") == 0) {
IsInitdb = true;
gs_signal_monitor_startup(); // 启动信号监控工作线程
gs_signal_slots_init(1); // 初始化信号插槽
(void)gs_signal_unblock_sigusr2(); // 解除SIGUSR2信号的阻塞
gs_signal_startup_siginfo("PostgresMain"); // 记录启动信息
exit(PostgresMain(argc, argv, NULL, get_current_username(progname))); // 进入PostgreSQL主循环
}
exit(PostmasterMain(argc, argv)); // 进入Postmaster主循环
/*
* Place platform-specific startup hacks here. This is the right
* place to put code that must be executed early in the launch of any new
* server process. Note that this code will NOT be executed when a backend
* or sub-bootstrap process is forked, unless we are in a fork/exec
* environment (ie EXEC_BACKEND is defined).
*
* XXX The need for code here is proof that the platform in question
* 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)
{
/*
* On some platforms, unaligned memory accesses result in a kernel trap;
* the default kernel behavior is to emulate the memory access, but this
* results in a significant performance penalty. We want PG never to make
* such unaligned memory accesses, so this code disables the kernel
* emulation: unaligned accesses will result in SIGBUS instead.
*/
#ifdef NOFIXADE
#if defined(__alpha) /* no __alpha__ ? */
{
int buffer[] = {SSIN_UACPROC, UAC_SIGBUS | UAC_NOPRINT};
if (setsysinfo(SSI_NVPAIRS, buffer, 1, (caddr_t)NULL, (unsigned long)NULL) < 0)
write_stderr("%s: setsysinfo failed: %s\n", progname, gs_strerror(errno));
}
#endif /* __alpha */
#endif /* NOFIXADE */
/*
* Windows-specific execution environment hacking.
*/
#ifdef WIN32
{
WSADATA wsaData;
int err;
/* Make output streams unbuffered by default */
setvbuf(stdout, NULL, _IONBF, 0);
setvbuf(stderr, NULL, _IONBF, 0);
/* Prepare Winsock */
err = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (err != 0) {
write_stderr("%s: WSAStartup failed: %d\n", progname, err);
exit(1);
}
/* In case of general protection fault, don't show GUI popup box */
SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX);
}
#endif /* WIN32 */
/* Binding static TLS variables for current thread */
EarlyBindingTLSVariables();
}
/*
* Help display should match the options accepted by PostmasterMain()
* and PostgresMain().
*/
static void help(const char* progname)
{
printf(_("%s is the gaussdb server.\n\n"), progname);
printf(_("Usage:\n %s [OPTION]...\n\n"), progname);
printf(_("Options:\n"));
#ifdef USE_ASSERT_CHECKING
printf(_(" -A 1|0 enable/disable run-time assert checking\n"));
#endif
printf(_(" -B NBUFFERS number of shared buffers\n"));
printf(_(" -b BINARY UPGRADES flag used for binary upgrades\n"));
printf(_(" -c NAME=VALUE set run-time parameter\n"));
printf(_(" -C NAME print value of run-time parameter, then exit\n"));
printf(_(" -d 1-5 debugging level\n"));
printf(_(" -D DATADIR database directory\n"));
printf(_(" -e use European date input format (DMY)\n"));
printf(_(" -F turn fsync off\n"));
printf(_(" -h HOSTNAME host name or IP address to listen on\n"));
printf(_(" -i enable TCP/IP connections\n"));
printf(_(" -k DIRECTORY Unix-domain socket location\n"));
#ifdef USE_SSL
printf(_(" -l enable SSL connections\n"));
#endif
printf(_(" -N MAX-CONNECT maximum number of allowed connections\n"));
printf(_(" -M SERVERMODE the database start as the appointed server mode\n"));
printf(_(" -o OPTIONS pass \"OPTIONS\" to each server process (obsolete)\n"));
printf(_(" -p PORT port number to listen on\n"));
#ifdef ENABLE_MULTIPLE_NODES
printf(_(" -R indicate run as xlogreiver.Only used with -M standby\n"));
#endif
printf(_(" -s show statistics after each query\n"));
printf(_(" -S WORK-MEM set amount of memory for sorts (in kB)\n"));
printf(_(" -u NUM set the num of kernel version before upgrade\n"));
printf(_(" -V, --version output version information, then exit\n"));
printf(_(" --NAME=VALUE set run-time parameter\n"));
printf(_(" --describe-config describe configuration parameters, then exit\n"));
printf(_(" --securitymode allow database system run in security mode\n"));
printf(_(" --single_node A SingleDN mode is being activated\n"));
printf(_(" -?, --help show this help, then exit\n"));
printf(_("\nServer mode:\n"));
printf(_(" primary database system starts as a primary server, send xlog to standby server\n"));
printf(_(" standby database system starts as a standby server, receive xlog from primary server\n"));
printf(_(" pending database system starts as a pending server, wait for promoting to primary or "
"demoting to standby\n"));
#ifdef ENABLE_MULTIPLE_NODES
printf(_(" fenced database system starts a fenced master process, serve UDF execution in secure mode "
"(run separately from Gaussdb process)\n"));
#endif
printf(_("\nDeveloper options:\n"));
printf(_(" -f s|i|n|m|h forbid use of some plan types\n"));
printf(_(" -n do not reinitialize shared memory after abnormal exit\n"));
printf(_(" -O allow system table structure changes\n"));
printf(_(" -P disable system indexes\n"));
printf(_(" -t pa|pl|ex show timings after each query\n"));
printf(_(" -T send SIGSTOP to all backend processes if one dies\n"));
printf(_(" -W NUM wait NUM seconds to allow attach from a debugger\n"));
printf(_(" --localxid use local transaction id (used only by gs_initdb)\n"));
printf(_("\nOptions for single-user mode:\n"));
printf(_(" --single selects single-user mode (must be first argument)\n"));
printf(_(" DBNAME database name (defaults to user name)\n"));
printf(_(" -d 0-5 override debugging level\n"));
printf(_(" -E echo statement before execution\n"));
printf(_(" -j do not use newline as interactive query delimiter\n"));
printf(_(" -r FILENAME send stdout and stderr to given file\n"));
printf(_("\nOptions for bootstrapping mode:\n"));
printf(_(" --boot selects bootstrapping mode (must be first argument)\n"));
#ifdef ENABLE_MULTIPLE_NODES
printf(_(" DBNAME database name (mandatory argument in bootstrapping mode)\n"));
#endif
printf(_(" -r FILENAME send stdout and stderr to given file\n"));
printf(_(" -x NUM internal use\n"));
#ifdef ENABLE_MULTIPLE_NODES
printf(_("\nNode options:\n"));
#ifdef ENABLE_MULTIPLE_NODES
printf(_(" --coordinator start as a Coordinator\n"));
printf(_(" --datanode start as a Datanode\n"));
#endif
printf(_(" --restoremode start to restore existing schema on the new node to be added\n"));
printf(_(" --single_node start as single node\n"));
#else
printf(_("\nNode options:\n"));
printf(_(" --single_node start a single node database. This is default setting.\n"));
#endif
printf(_("\nPlease read the documentation for the complete list of run-time\n"
"configuration settings and how to set them on the command line or in\n"
"the configuration file.\n"));
#if ((defined(ENABLE_MULTIPLE_NODES)) || (defined(ENABLE_PRIVATEGAUSS)))
printf(_("\nReport bugs to GaussDB support.\n"));
#else
printf(_("\nReport bugs to openGauss community by raising an issue.\n"));
#endif
}
static void check_root(const char* progname)
{
#ifndef WIN32
if (geteuid() == 0) {
write_stderr("\"root\" execution of the gaussdb server is not permitted.\n"
"The server must be started under an unprivileged user ID to prevent\n"
"possible system security compromise. See the documentation for\n"
"more information on how to properly start the server.\n");
exit(1);
}
/*
* Also make sure that real and effective uids are the same. Executing as
* a setuid program from a root shell is a security hole, since on many
* platforms a nefarious subroutine could setuid back to root if real uid
* is root. (Since nobody actually uses postgres as a setuid program,
* trying to actively fix this situation seems more trouble than it's
* worth; we'll just expend the effort to check for it.)
*/
if (getuid() != geteuid()) {
write_stderr("%s: real and effective user IDs must match\n", progname);
exit(1);
}
#else /* WIN32 */
if (pgwin32_is_admin()) {
write_stderr("Execution of gaussdb by a user with administrative permissions is not\n"
"permitted.\n"
"The server must be started under an unprivileged user ID to prevent\n"
"possible system security compromises. See the documentation for\n"
"more information on how to properly start the server.\n");
exit(1);
}
#endif /* WIN32 */
}
/**
* get_current_username -
* @progname:
*
*
*/
static char* get_current_username(const char* progname)
{
#ifndef WIN32 // 非Windows平台代码
struct passwd* pw = NULL;
char* pRet = NULL;
(void)syscalllockAcquire(&getpwuid_lock); // 获取线程锁
pw = getpwuid(geteuid()); // 获取与实际用户ID关联的密码记录
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 // Windows平台代码
unsigned long namesize = 256 /* UNLEN */ + 1;
char* name = NULL;
name = MemoryContextAlloc(
SESS_GET_MEM_CXT_GROUP(MEMORY_CONTEXT_CBB), namesize); // 分配内存来储存用户名,返回该内存地址
if (!GetUserName(name, &namesize)) { // 获取当前用户的用户名
write_stderr("%s: could not determine user name (GetUserName failed)\n", progname);
exit(1);
}
return name; // 返回用户名
#endif
}
/**
* syscall_lock_init -
*
* getenv线
*/
static void syscall_lock_init(void)
{
syscalllockInit(&getpwuid_lock); // 初始化获取用户ID对应密码记录的线程锁
syscalllockInit(&env_lock); // 初始化 getenv 的线程锁
syscalllockInit(&dlerror_lock); // 初始化 dlerror 的线程锁
syscalllockInit(&kerberos_conn_lock); // 初始化 Kerberos 连接相关的线程锁
syscalllockInit(&read_cipher_lock); // 初始化加密算法相关的线程锁
}