/* -------------------------------------------------------------------- * guc_network.cpp * * Support for grand unified configuration schema, including SET * command, configuration file, and command line options. * See src/backend/utils/misc/README for more information. * * * Copyright (c) 2000-2012, PostgreSQL Global Development Group * Portions Copyright (c) 2010-2012 Postgres-XC Development Group * Written by Peter Eisentraut . * * IDENTIFICATION * src/backend/utils/misc/guc/guc_network.cpp * * -------------------------------------------------------------------- */ #include "postgres.h" #include "knl/knl_variable.h" #include #include #include #include #include "utils/elog.h" #ifdef HAVE_SYSLOG #include #endif #include "access/cbmparsexlog.h" #include "access/gin.h" #include "access/gtm.h" #include "pgxc/pgxc.h" #include "access/transam.h" #include "access/twophase.h" #include "access/xact.h" #include "access/xlog.h" #include "gs_bbox.h" #include "catalog/namespace.h" #include "catalog/pgxc_group.h" #include "catalog/storage_gtt.h" #include "commands/async.h" #include "commands/prepare.h" #include "commands/vacuum.h" #include "commands/variable.h" #include "commands/tablespace.h" #include "commands/trigger.h" #include "funcapi.h" #include "instruments/instr_statement.h" #include "job/job_scheduler.h" #include "libpq/auth.h" #include "libpq/be-fsstubs.h" #include "libpq/ip.h" #include "libpq/libpq.h" #include "libpq/pqformat.h" #include "miscadmin.h" #include "opfusion/opfusion.h" #include "optimizer/cost.h" #include "optimizer/geqo.h" #include "optimizer/nodegroups.h" #include "optimizer/paths.h" #include "optimizer/planmain.h" #include "optimizer/prep.h" #include "optimizer/gtmfree.h" #include "parser/parse_expr.h" #include "parser/parse_oper.h" #include "parser/parse_type.h" #include "parser/parser.h" #include "parser/scansup.h" #include "pgstat.h" #include "pgxc/route.h" #include "workload/workload.h" #include "pgaudit.h" #include "instruments/instr_unique_sql.h" #include "commands/tablecmds.h" #include "nodes/nodes.h" #include "optimizer/pgxcship.h" #include "pgxc/execRemote.h" #include "pgxc/locator.h" #include "optimizer/pgxcplan.h" #include "pgxc/poolmgr.h" #include "pgxc/nodemgr.h" #include "utils/lsyscache.h" #include "access/multi_redo_settings.h" #include "catalog/pg_authid.h" #include "commands/user.h" #include "commands/user.h" #include "flock.h" #include "gaussdb_version.h" #include "libcomm/libcomm.h" #include "libpq/libpq-be.h" #include "libpq/md5.h" #include "libpq/sha2.h" #include "optimizer/planner.h" #include "optimizer/streamplan.h" #include "postmaster/alarmchecker.h" #include "postmaster/autovacuum.h" #include "postmaster/bgwriter.h" #include "postmaster/pagewriter.h" #include "postmaster/postmaster.h" #include "postmaster/syslogger.h" #include "postmaster/twophasecleaner.h" #include "postmaster/walwriter.h" #include "postmaster/bgworker.h" #include "replication/dataqueue.h" #include "replication/datareceiver.h" #include "replication/reorderbuffer.h" #include "replication/replicainternal.h" #include "replication/slot.h" #include "replication/syncrep.h" #include "replication/walreceiver.h" #include "replication/walsender.h" #include "storage/buf/bufmgr.h" #include "storage/cucache_mgr.h" #include "storage/smgr/fd.h" #include "storage/predicate.h" #include "storage/procarray.h" #include "storage/standby.h" #include "storage/remote_adapter.h" #include "tcop/tcopprot.h" #include "threadpool/threadpool.h" #include "tsearch/ts_cache.h" #include "utils/acl.h" #include "utils/anls_opt.h" #include "utils/atomic.h" #include "utils/be_module.h" #include "utils/builtins.h" #include "utils/bytea.h" #include "utils/distribute_test.h" #include "utils/segment_test.h" #include "utils/guc_tables.h" #include "utils/memtrack.h" #include "utils/memutils.h" #include "utils/pg_locale.h" #include "utils/plancache.h" #include "utils/portal.h" #include "utils/ps_status.h" #include "utils/rel_gs.h" #include "utils/rel.h" #include "utils/snapmgr.h" #include "utils/syscache.h" #include "access/heapam.h" #include "utils/tzparser.h" #include "utils/xml.h" #include "workload/cpwlm.h" #include "workload/workload.h" #include "utils/guc_network.h" #include "ddes/dms/ss_init.h" static bool check_maxconnections(int* newval, void** extra, GucSource source); static bool check_pooler_maximum_idle_time(int* newval, void** extra, GucSource source); static bool check_sctp_support(bool* newval, void** extra, GucSource source); static void assign_comm_debug_mode(bool newval, void* extra); static void assign_comm_stat_mode(bool newval, void* extra); static void assign_comm_timer_mode(bool newval, void* extra); static void assign_comm_no_delay(bool newval, void* extra); static void assign_comm_ackchk_time(int newval, void* extra); static bool CheckMaxInnerToolConnections(int* newval, void** extra, GucSource source); static bool check_ssl(bool* newval, void** extra, GucSource source); #ifndef ENABLE_MULTIPLE_NODES static bool check_listen_addresses(char **newval, void **extra, GucSource source); static void assign_listen_addresses(const char *newval, void *extra); #endif #ifdef LIBCOMM_SPEED_TEST_ENABLE static void assign_comm_test_thread_num(int newval, void* extra); static void assign_comm_test_msg_len(int newval, void* extra); static void assign_comm_test_send_sleep(int newval, void* extra); static void assign_comm_test_send_once(int newval, void* extra); static void assign_comm_test_recv_sleep(int newval, void* extra); static void assign_comm_test_recv_once(int newval, void* extra); #endif #ifdef LIBCOMM_FAULT_INJECTION_ENABLE static void assign_comm_fault_injection(int newval, void* extra); #endif static const char* show_unix_socket_permissions(void); static bool check_max_datanode(int* newval, void** extra, GucSource source); static void comm_change_datanode(int newval, void* extra); static const char* show_max_datanode(void); static bool check_max_coordnode(int* newval, void** extra, GucSource source); static void comm_change_coordnode(int newval, void* extra); static const char* show_max_coordnode(void); static void InitNetworkConfigureNamesBool(); static void InitNetworkConfigureNamesInt(); static void InitNetworkConfigureNamesInt64(); static void InitNetworkConfigureNamesReal(); static void InitNetworkConfigureNamesString(); static void InitNetworkConfigureNamesEnum(); /* * Contents of GUC tables * * See src/backend/utils/misc/README for design notes. * * TO ADD AN OPTION AS FOLLOWS. * * 1. Declare a global variable of type bool, int, double, or char* * and make use of it. * * 2. Decide at what times it's safe to set the option. See guc.h for * details. * * 3. Decide on a name, a default value, upper and lower bounds (if * applicable), etc. * * 4. Add a record below. * * 5. Add it to src/backend/utils/misc/postgresql_single.conf.sample or * src/backend/utils/misc/postgresql_distribute.conf.sample or both, * if appropriate. * * 6. Don't forget to document the option (at least in config.sgml). * * 7. If it's a new GUC_LIST option you must edit pg_dumpall.c to ensure * it is not single quoted at dump time. */ /* ******* option records follow ******* */ void InitNetworkConfigureNames() { InitNetworkConfigureNamesBool(); InitNetworkConfigureNamesInt(); InitNetworkConfigureNamesInt64(); InitNetworkConfigureNamesReal(); InitNetworkConfigureNamesString(); InitNetworkConfigureNamesEnum(); return; } static void InitNetworkConfigureNamesBool() { struct config_bool localConfigureNamesBool[] = { {{"enable_stateless_pooler_reuse", PGC_POSTMASTER, NODE_DISTRIBUTE, DEVELOPER_OPTIONS, gettext_noop("Pooler stateless reuse mode."), NULL, GUC_NOT_IN_SAMPLE}, &g_instance.attr.attr_network.PoolerStatelessReuse, false, NULL, NULL, NULL}, // Stream communication {{"comm_tcp_mode", PGC_POSTMASTER, NODE_DISTRIBUTE, CLIENT_CONN, gettext_noop("Whether use tcp commucation mode for stream"), NULL, }, &g_instance.attr.attr_network.comm_tcp_mode, true, check_sctp_support, NULL, NULL}, {{"comm_debug_mode", PGC_USERSET, NODE_DISTRIBUTE, DEVELOPER_OPTIONS, gettext_noop("Whether use libcomm debug mode for print debug information"), NULL, }, &u_sess->attr.attr_network.comm_debug_mode, #ifdef ENABLE_LLT true, #else false, #endif NULL, assign_comm_debug_mode, NULL}, {{"comm_stat_mode", PGC_USERSET, NODE_DISTRIBUTE, DEVELOPER_OPTIONS, gettext_noop("Whether use libcomm stat mode for print stat data"), NULL, }, &u_sess->attr.attr_network.comm_stat_mode, #ifdef ENABLE_LLT true, #else false, #endif NULL, assign_comm_stat_mode, NULL}, {{"comm_timer_mode", PGC_USERSET, NODE_DISTRIBUTE, DEVELOPER_OPTIONS, gettext_noop("Whether use libcomm timer debug mode for print timer data"), NULL, }, &u_sess->attr.attr_network.comm_timer_mode, #ifdef ENABLE_LLT true, #else false, #endif NULL, assign_comm_timer_mode, NULL}, {{"comm_no_delay", PGC_USERSET, NODE_DISTRIBUTE, DEVELOPER_OPTIONS, gettext_noop("Whether set NO_DELAY option for libcomm socket"), NULL, }, &u_sess->attr.attr_network.comm_no_delay, false, NULL, assign_comm_no_delay, NULL}, {{"enable_force_reuse_connections", PGC_BACKEND, NODE_DISTRIBUTE, DEVELOPER_OPTIONS, gettext_noop("Session force reuse pooler connections."), NULL, GUC_NOT_IN_SAMPLE}, &u_sess->attr.attr_network.PoolerForceReuse, false, NULL, NULL, NULL}, {{"comm_client_bind", PGC_USERSET, NODE_DISTRIBUTE, DEVELOPER_OPTIONS, gettext_noop("Whether client use bind function"), NULL, }, &u_sess->attr.attr_network.comm_client_bind, false, NULL, NULL, NULL}, {{"comm_ssl", PGC_POSTMASTER, NODE_DISTRIBUTE, CONN_AUTH_SECURITY, gettext_noop("Enables libcomm SSL connections."), NULL}, &g_instance.attr.attr_network.comm_enable_SSL, false, check_ssl, NULL, NULL}, {{"enable_dolphin_proto", PGC_POSTMASTER, NODE_ALL, CONN_AUTH_SECURITY, gettext_noop("Enables dolphin database protocol"), NULL}, &g_instance.attr.attr_network.enable_dolphin_proto, false, NULL, NULL, NULL}, /* End-of-list marker */ {{NULL, (GucContext)0, (GucNodeType)0, (config_group)0, NULL, NULL}, NULL, false, NULL, NULL, NULL} }; Size bytes = sizeof(localConfigureNamesBool); u_sess->utils_cxt.ConfigureNamesBool[GUC_ATTR_NETWORK] = (struct config_bool*)MemoryContextAlloc(SESS_GET_MEM_CXT_GROUP(MEMORY_CONTEXT_CBB), bytes); errno_t rc = memcpy_s(u_sess->utils_cxt.ConfigureNamesBool[GUC_ATTR_NETWORK], bytes, localConfigureNamesBool, bytes); securec_check_ss(rc, "\0", "\0"); } static void InitNetworkConfigureNamesInt() { struct config_int localConfigureNamesInt[] = { {{"max_connections", PGC_POSTMASTER, NODE_ALL, CONN_AUTH_SETTINGS, gettext_noop("Sets the maximum number of concurrent connections for clients."), NULL}, &g_instance.attr.attr_network.MaxConnections, 200, 10, MAX_BACKENDS, check_maxconnections, NULL, NULL}, {{"max_inner_tool_connections", PGC_POSTMASTER, NODE_ALL, CONN_AUTH_SETTINGS, gettext_noop("Sets the maximum number of concurrent connections for inner tools."), NULL}, &g_instance.attr.attr_network.maxInnerToolConnections, 50, 1, MAX_BACKENDS, CheckMaxInnerToolConnections, NULL, NULL}, {{"sysadmin_reserved_connections", PGC_POSTMASTER, NODE_ALL, CONN_AUTH_SETTINGS, gettext_noop("Sets the number of connection slots reserved for system admin."), NULL}, &g_instance.attr.attr_network.ReservedBackends, 3, 0, MAX_BACKENDS, NULL, NULL, NULL}, {{"port", PGC_POSTMASTER, NODE_ALL, CONN_AUTH_SETTINGS, gettext_noop("Sets the TCP port the server listens on."), NULL}, &g_instance.attr.attr_network.PostPortNumber, DEF_PGPORT, 1, 65535, NULL, NULL, NULL}, {{"unix_socket_permissions", PGC_POSTMASTER, NODE_ALL, CONN_AUTH_SETTINGS, gettext_noop("Sets the access permissions of the Unix-domain socket."), gettext_noop("Unix-domain sockets use the usual Unix file system " "permission set. The parameter value is expected " "to be a numeric mode specification in the form " "accepted by the chmod and umask system calls. " "(To use the customary octal format the number must " "start with a 0 (zero).)")}, &g_instance.attr.attr_network.Unix_socket_permissions, 0700, 0000, 0777, NULL, NULL, show_unix_socket_permissions}, {{"pooler_maximum_idle_time", PGC_USERSET, NODE_DISTRIBUTE, DATA_NODES, gettext_noop("Maximum idle time of the pooler links."), NULL, GUC_UNIT_S}, &u_sess->attr.attr_network.PoolerMaxIdleTime, 600, 0, INT_MAX, check_pooler_maximum_idle_time, NULL, NULL}, {{"minimum_pool_size", PGC_USERSET, NODE_DISTRIBUTE, DATA_NODES, gettext_noop("Initial pool size."), gettext_noop("If number of active connections decreased below this value, " "new connections are established")}, &u_sess->attr.attr_network.MinPoolSize, 50, 1, 65535, NULL, NULL, NULL}, // Stream communication {{"comm_sctp_port", PGC_POSTMASTER, NODE_DISTRIBUTE, CONN_AUTH_SETTINGS, gettext_noop("Sets the STCP port the server listens on."), NULL}, &g_instance.attr.attr_network.comm_sctp_port, 7000, 0, 65535, NULL, NULL, NULL}, {{"comm_control_port", PGC_POSTMASTER, NODE_DISTRIBUTE, CONN_AUTH_SETTINGS, gettext_noop("Sets the stream control port the server listens on."), NULL}, &g_instance.attr.attr_network.comm_control_port, 7001, 0, 65535, NULL, NULL, NULL}, {{"comm_quota_size", PGC_POSTMASTER, NODE_DISTRIBUTE, CONN_AUTH_SETTINGS, gettext_noop("Sets the stream quota size in kB."), NULL, GUC_UNIT_KB}, &g_instance.attr.attr_network.comm_quota_size, 1024, 0, 2048000, NULL, NULL, NULL}, {{"comm_usable_memory", PGC_POSTMASTER, NODE_DISTRIBUTE, CONN_AUTH_SETTINGS, gettext_noop("Sets the total usable memory for communication(in kB)."), NULL, GUC_UNIT_KB}, &g_instance.attr.attr_network.comm_usable_memory, 4000 * 1024, 100 * 1024, INT_MAX / 2, NULL, NULL, NULL}, {{"comm_memory_pool", PGC_POSTMASTER, NODE_DISTRIBUTE, CONN_AUTH_SETTINGS, gettext_noop("Sets the memory pool size for communication(in kB)."), NULL, GUC_UNIT_KB}, &g_instance.attr.attr_network.comm_memory_pool, 2000 * 1024, 100 * 1024, INT_MAX / 2, NULL, NULL, NULL}, {{"comm_memory_pool_percent", PGC_POSTMASTER, NODE_DISTRIBUTE, CONN_AUTH_SETTINGS, gettext_noop("Sets the percent of comm_memory_pool for dynamic workload."), NULL}, &g_instance.attr.attr_network.comm_memory_pool_percent, 0, 0, 100, NULL, NULL, NULL}, {{"comm_ackchk_time", PGC_USERSET, NODE_DISTRIBUTE, QUERY_TUNING, gettext_noop("Send ack check package to stream sender periodically."), NULL, GUC_UNIT_MS}, &u_sess->attr.attr_network.comm_ackchk_time, 2000, 0, 20000, NULL, assign_comm_ackchk_time, NULL}, #ifdef LIBCOMM_SPEED_TEST_ENABLE {{"comm_test_thread_num", PGC_USERSET, NODE_DISTRIBUTE, DEVELOPER_OPTIONS, gettext_noop("Libcomm performance testing framework thread number of streams."), NULL}, &u_sess->attr.attr_network.comm_test_thread_num, 0, 0, 65535, NULL, assign_comm_test_thread_num, NULL}, {{"comm_test_msg_len", PGC_USERSET, NODE_DISTRIBUTE, DEVELOPER_OPTIONS, gettext_noop("Libcomm performance testing framework message len."), NULL}, &u_sess->attr.attr_network.comm_test_msg_len, 8192, 1, 65535, NULL, assign_comm_test_msg_len, NULL}, {{"comm_test_send_sleep", PGC_USERSET, NODE_DISTRIBUTE, DEVELOPER_OPTIONS, gettext_noop("Libcomm performance testing framework producer thread sleep time."), NULL}, &u_sess->attr.attr_network.comm_test_send_sleep, 0, 0, INT_MAX, NULL, assign_comm_test_send_sleep, NULL}, {{"comm_test_send_once", PGC_USERSET, NODE_DISTRIBUTE, DEVELOPER_OPTIONS, gettext_noop("Libcomm performance testing framework producer thread send message size once time."), NULL}, &u_sess->attr.attr_network.comm_test_send_once, 8192, 1, INT_MAX, NULL, assign_comm_test_send_once, NULL}, {{"comm_test_recv_sleep", PGC_USERSET, NODE_DISTRIBUTE, DEVELOPER_OPTIONS, gettext_noop("Libcomm performance testing framework consumer thread sleep time."), NULL}, &u_sess->attr.attr_network.comm_test_recv_sleep, 0, 0, INT_MAX, NULL, assign_comm_test_recv_sleep, NULL}, {{"comm_test_rcv_once", PGC_USERSET, NODE_DISTRIBUTE, DEVELOPER_OPTIONS, gettext_noop("Libcomm performance testing framework consumer thread recv message size once time."), NULL}, &u_sess->attr.attr_network.comm_test_recv_once, 8192, 1, INT_MAX, NULL, assign_comm_test_recv_once, NULL}, #endif #ifdef LIBCOMM_FAULT_INJECTION_ENABLE {{"comm_fault_injection", PGC_USERSET, NODE_DISTRIBUTE, DEVELOPER_OPTIONS, gettext_noop("Libcomm fault injection framework."), NULL}, &u_sess->attr.attr_network.comm_fault_injection, 0, -10, INT_MAX, NULL, assign_comm_fault_injection, NULL}, #endif {{"comm_max_receiver", PGC_POSTMASTER, NODE_DISTRIBUTE, CONN_AUTH_SETTINGS, gettext_noop("Maximum number of internal receiver threads."), NULL}, &g_instance.attr.attr_network.comm_max_receiver, 4, 1, 50, NULL, NULL, NULL}, {{"cn_send_buffer_size", PGC_POSTMASTER, NODE_ALL, CLIENT_CONN_STATEMENT, gettext_noop("Sets the send buffer size used in CN, unit in KB."), NULL, GUC_UNIT_KB}, &g_instance.attr.attr_network.cn_send_buffer_size, 8, 8, 128, NULL, NULL, NULL}, {{"comm_sender_buffer_size", PGC_POSTMASTER, NODE_DISTRIBUTE, DEVELOPER_OPTIONS, gettext_noop("The libcomm sender's buffer size in every interaction between DN and CN, " "or DN and DN, unit(KB)"), NULL}, &g_instance.comm_cxt.commutil_cxt.g_comm_sender_buffer_size, 8, 1, 1024, NULL, NULL, NULL}, {{"max_pool_size", PGC_POSTMASTER, NODE_DISTRIBUTE, DATA_NODES, gettext_noop("Max pool size."), gettext_noop("If number of active connections reaches this value, " "other connection requests will be refused")}, &g_instance.attr.attr_network.MaxPoolSize, 400, 1, 65535, NULL, NULL, NULL}, {{"pooler_port", PGC_POSTMASTER, NODE_DISTRIBUTE, COORDINATORS, gettext_noop("Legacy port of the Pool Manager. Now it is used for cn HA port for build and replication " "under thread pool mode."), NULL}, &g_instance.attr.attr_network.PoolerPort, 6667, 1, 65535, NULL, NULL, NULL}, {{"pooler_timeout", PGC_SIGHUP, NODE_DISTRIBUTE, DATA_NODES, gettext_noop("Timeout of the Pool Communication with Other Nodes."), NULL, GUC_UNIT_S}, &u_sess->attr.attr_network.PoolerTimeout, 600, 0, 7200, NULL, NULL, NULL}, {{"pooler_connect_max_loops", PGC_USERSET, NODE_DISTRIBUTE, DATA_NODES, gettext_noop("Max retries of the Pooler Connecting to Other Nodes."), NULL}, &u_sess->attr.attr_network.PoolerConnectMaxLoops, 1, 0, 20, NULL, NULL, NULL}, {{"pooler_connect_interval_time", PGC_USERSET, NODE_DISTRIBUTE, DATA_NODES, gettext_noop("Indicates the interval for each retry."), NULL, GUC_UNIT_S}, &u_sess->attr.attr_network.PoolerConnectIntervalTime, 15, 0, 7200, NULL, NULL, NULL}, {{"pooler_connect_timeout", PGC_SIGHUP, NODE_DISTRIBUTE, DATA_NODES, gettext_noop("Timeout of the Pooler Connecting to Other Nodes."), NULL, GUC_UNIT_S}, &u_sess->attr.attr_network.PoolerConnectTimeout, 60, 0, 7200, NULL, NULL, NULL}, {{"pooler_cancel_timeout", PGC_SIGHUP, NODE_DISTRIBUTE, DATA_NODES, gettext_noop("Timeout of the Pooler Cancel Connections to Other Nodes."), NULL, GUC_UNIT_S}, &u_sess->attr.attr_network.PoolerCancelTimeout, 15, 0, 7200, NULL, NULL, NULL}, {{"max_coordinators", PGC_POSTMASTER, NODE_DISTRIBUTE, DATA_NODES, gettext_noop("Maximum number of Coordinators in the cluster."), gettext_noop("It is not possible to create more Coordinators in the cluster than " "this maximum number.")}, &g_instance.attr.attr_network.MaxCoords, 1024, 2, MAX_CN_NODE_NUM, check_max_coordnode, comm_change_coordnode, show_max_coordnode}, {{"comm_max_datanode", PGC_USERSET, NODE_DISTRIBUTE, DEVELOPER_OPTIONS, gettext_noop("Currently number of Datanodes."), NULL}, &u_sess->attr.attr_network.comm_max_datanode, 256, 1, MAX_DN_NODE_NUM, check_max_datanode, comm_change_datanode, show_max_datanode}, {{"comm_max_stream", PGC_POSTMASTER, NODE_DISTRIBUTE, CONN_AUTH_SETTINGS, gettext_noop("Maximum number of streams."), NULL}, &g_instance.attr.attr_network.comm_max_stream, 1024, 1, 60000, NULL, NULL, NULL}, {{"dolphin_server_port", PGC_POSTMASTER, NODE_ALL, CONN_AUTH_SETTINGS, gettext_noop("Sets the TCP port the server listens on for dolphin client-server protocol."), NULL}, &g_instance.attr.attr_network.dolphin_server_port, 3308, 1024, 65535, NULL, NULL, NULL}, /* End-of-list marker */ {{NULL, (GucContext)0, (GucNodeType)0, (config_group)0, NULL, NULL}, NULL, 0, 0, 0, NULL, NULL, NULL} }; Size bytes = sizeof(localConfigureNamesInt); u_sess->utils_cxt.ConfigureNamesInt[GUC_ATTR_NETWORK] = (struct config_int*)MemoryContextAlloc(SESS_GET_MEM_CXT_GROUP(MEMORY_CONTEXT_CBB), bytes); errno_t rc = memcpy_s(u_sess->utils_cxt.ConfigureNamesInt[GUC_ATTR_NETWORK], bytes, localConfigureNamesInt, bytes); securec_check_ss(rc, "\0", "\0"); } static void InitNetworkConfigureNamesReal() { struct config_real localConfigureNamesReal[] = { /* End-of-list marker */ {{NULL, (GucContext)0, (GucNodeType)0, (config_group)0, NULL, NULL}, NULL, 0.0, 0.0, 0.0, NULL, NULL, NULL} }; Size bytes = sizeof(localConfigureNamesReal); u_sess->utils_cxt.ConfigureNamesReal[GUC_ATTR_NETWORK] = (struct config_real*)MemoryContextAlloc(SESS_GET_MEM_CXT_GROUP(MEMORY_CONTEXT_CBB), bytes); errno_t rc = memcpy_s(u_sess->utils_cxt.ConfigureNamesReal[GUC_ATTR_NETWORK], bytes, localConfigureNamesReal, bytes); securec_check_ss(rc, "\0", "\0"); } static void InitNetworkConfigureNamesInt64() { struct config_int64 localConfigureNamesInt64[] = { /* End-of-list marker */ {{NULL, (GucContext)0, (GucNodeType)0, (config_group)0, NULL, NULL}, NULL, 0, 0, 0, NULL, NULL, NULL} }; Size bytes = sizeof(localConfigureNamesInt64); u_sess->utils_cxt.ConfigureNamesInt64[GUC_ATTR_NETWORK] = (struct config_int64*)MemoryContextAlloc(SESS_GET_MEM_CXT_GROUP(MEMORY_CONTEXT_CBB), bytes); errno_t rc = memcpy_s(u_sess->utils_cxt.ConfigureNamesInt64[GUC_ATTR_NETWORK], bytes, localConfigureNamesInt64, bytes); securec_check_ss(rc, "\0", "\0"); } static void InitNetworkConfigureNamesString() { struct config_string localConfigureNamesString[] = { {{"unix_socket_group", PGC_POSTMASTER, NODE_ALL, CONN_AUTH_SETTINGS, gettext_noop("Sets the owning group of the Unix-domain socket."), gettext_noop("The owning user of the socket is always the user " "that starts the server.")}, &g_instance.attr.attr_network.Unix_socket_group, "", NULL, NULL, NULL}, {{"unix_socket_directory", PGC_POSTMASTER, NODE_ALL, CONN_AUTH_SETTINGS, gettext_noop("Sets the directory where the Unix-domain socket will be created."), NULL, GUC_SUPERUSER_ONLY}, &g_instance.attr.attr_network.UnixSocketDir, "", check_canonical_path, NULL, NULL}, #ifdef ENABLE_MULTIPLE_NODES {{"listen_addresses", PGC_POSTMASTER, NODE_ALL, CONN_AUTH_SETTINGS, gettext_noop("Sets the host name or IP address(es) to listen to."), NULL, GUC_LIST_INPUT}, &g_instance.attr.attr_network.ListenAddresses, "localhost", NULL, NULL, NULL}, #else {{"listen_addresses", PGC_SIGHUP, NODE_ALL, CONN_AUTH_SETTINGS, gettext_noop("Sets the host name or IP address(es) to listen to."), NULL, GUC_LIST_INPUT}, &u_sess->attr.attr_network.ListenAddresses, "localhost", check_listen_addresses, assign_listen_addresses, NULL}, #endif {{"local_bind_address", PGC_POSTMASTER, NODE_ALL, CONN_AUTH_SETTINGS, gettext_noop("Sets the host name or IP address(es) to connect to for sctp."), NULL, GUC_LIST_INPUT}, &g_instance.attr.attr_network.tcp_link_addr, "0.0.0.0", NULL, NULL, NULL}, {{NULL, (GucContext)0, (GucNodeType)0, (config_group)0, NULL, NULL}, NULL, NULL, NULL, NULL, NULL} }; Size bytes = sizeof(localConfigureNamesString); u_sess->utils_cxt.ConfigureNamesString[GUC_ATTR_NETWORK] = (struct config_string*)MemoryContextAlloc(SESS_GET_MEM_CXT_GROUP(MEMORY_CONTEXT_CBB), bytes); errno_t rc = memcpy_s(u_sess->utils_cxt.ConfigureNamesString[GUC_ATTR_NETWORK], bytes, localConfigureNamesString, bytes); securec_check_ss(rc, "\0", "\0"); } static void InitNetworkConfigureNamesEnum() { struct config_enum localConfigureNamesEnum[] = { /* End-of-list marker */ {{NULL, (GucContext)0, (GucNodeType)0, (config_group)0, NULL, NULL}, NULL, 0, NULL, NULL, NULL, NULL} }; Size bytes = sizeof(localConfigureNamesEnum); u_sess->utils_cxt.ConfigureNamesEnum[GUC_ATTR_NETWORK] = (struct config_enum*)MemoryContextAlloc(SESS_GET_MEM_CXT_GROUP(MEMORY_CONTEXT_CBB), bytes); errno_t rc = memcpy_s(u_sess->utils_cxt.ConfigureNamesEnum[GUC_ATTR_NETWORK], bytes, localConfigureNamesEnum, bytes); securec_check_ss(rc, "\0", "\0"); } /* ******* end of options list ******* */ static bool check_maxconnections(int* newval, void** extra, GucSource source) { const int factor = 4; const int min = 64; const int max = 1024; int bgworkers = *newval / factor; /* g_max_worker_processes should be a quarter of max_connections, and between 64 and 1024 */ g_max_worker_processes = Max(bgworkers, min); g_max_worker_processes = Min(g_max_worker_processes, max); #ifdef PGXC if (IS_PGXC_COORDINATOR && *newval > MAX_BACKENDS) { GUC_check_errmsg("PGXC can't support max_connections more than %d.", MAX_BACKENDS); return false; } #endif if (*newval + g_instance.attr.attr_storage.autovacuum_max_workers + g_instance.attr.attr_sql.job_queue_processes + AUXILIARY_BACKENDS + AV_LAUNCHER_PROCS + g_instance.attr.attr_network.maxInnerToolConnections + g_max_worker_processes > MAX_BACKENDS) { return false; } if (g_instance.attr.attr_storage.dms_attr.enable_dms && *newval > DMS_MAX_CONNECTIONS) { GUC_check_errmsg("Shared Storage can't support max_connections more than %d.", DMS_MAX_CONNECTIONS); return false; } return true; } /* * Check if the kernel version greater than suse sp2 (3.0.13) * Only a warning is printed to log. * Returning false will cause FATAL error and it will not be good. */ static bool check_sctp_support(bool* newval, void** extra, GucSource source) { if (*newval == false) { GUC_check_errcode(ERRCODE_FEATURE_NOT_SUPPORTED); GUC_check_errmsg("SET COMM_TCP_MODE TO OFF is no longer supported"); *newval = true; } return true; } static void assign_comm_debug_mode(bool newval, void* extra) { gs_set_debug_mode(newval); return; } static void assign_comm_stat_mode(bool newval, void* extra) { gs_set_stat_mode(newval); return; } static void assign_comm_timer_mode(bool newval, void* extra) { gs_set_timer_mode(newval); return; } static void assign_comm_no_delay(bool newval, void* extra) { gs_set_no_delay(newval); return; } static bool CheckMaxInnerToolConnections(int* newval, void** extra, GucSource source) { if (*newval + g_instance.attr.attr_storage.autovacuum_max_workers + g_instance.attr.attr_sql.job_queue_processes + g_instance.attr.attr_network.MaxConnections + AUXILIARY_BACKENDS + AV_LAUNCHER_PROCS + g_max_worker_processes > MAX_BACKENDS) { return false; } return true; } static bool check_ssl(bool* newval, void** extra, GucSource source) { #ifndef USE_SSL if (*newval) { GUC_check_errmsg("COMM SSL is not supported by this build"); return false; } #endif return true; } static bool check_pooler_maximum_idle_time(int* newval, void** extra, GucSource source) { if (*newval < 0) { GUC_check_errmsg("GaussDB can't support idle time less than 0 or more than %d seconds.", INT_MAX); return false; } return true; } static void assign_comm_ackchk_time(int newval, void* extra) { gs_set_ackchk_time(newval); } #ifndef ENABLE_MULTIPLE_NODES static bool check_listen_addresses(char **newval, void **extra, GucSource source) { if (*newval == NULL || strlen(*newval) == 0) { GUC_check_errmsg("listen_addresses can not set to empty"); return false; } char* rawstring = NULL; List* elemlist = NULL; rawstring = pstrdup(*newval); if (!SplitIdentifierString(rawstring, ',', &elemlist)) { /* syntax error in list */ GUC_check_errmsg("invalid list syntax for \"listen_addresses\": %s", *newval); list_free_ext(elemlist); pfree(rawstring); return false; } list_free_ext(elemlist); pfree(rawstring); return true; } static void transform_ip_to_addr(char* host_name, unsigned short port_number) { char* service = NULL; struct addrinfo* addrs = NULL; struct addrinfo* addr = NULL; struct addrinfo hint; char portNumberStr[32]; int family = AF_UNSPEC; errno_t rc = snprintf_s(portNumberStr, sizeof(portNumberStr), sizeof(portNumberStr) - 1, "%hu", port_number); securec_check_ss(rc, "\0", "\0"); service = portNumberStr; /* Initialize hint structure */ rc = memset_s(&hint, sizeof(hint), 0, sizeof(hint)); securec_check(rc, "\0", "\0"); hint.ai_family = family; hint.ai_flags = AI_PASSIVE; hint.ai_socktype = SOCK_STREAM; int ret = pg_getaddrinfo_all(host_name, service, &hint, &addrs); if (ret || addrs == NULL) { if (host_name != NULL) { ereport(LOG, (errmsg("could not translate host name \"%s\", service \"%s\" to address: %s", host_name, service, gai_strerror(ret)))); } else { ereport(LOG, (errmsg("could not translate service \"%s\" to address: %s", service, gai_strerror(ret)))); } if (addrs != NULL) { pg_freeaddrinfo_all(hint.ai_family, addrs); } return; } for (addr = addrs; addr; addr = addr->ai_next) { if (!IS_AF_UNIX(family) && IS_AF_UNIX(addr->ai_family)) { /* * Only set up a unix domain socket when they really asked for it. * The service/port is different in that case. */ continue; } struct sockaddr* sinp = NULL; char* result = NULL; sinp = (struct sockaddr*)(addr->ai_addr); if (addr->ai_family == AF_INET6) { result = inet_net_ntop(AF_INET6, &((struct sockaddr_in6*)sinp)->sin6_addr, 128, t_thrd.postmaster_cxt.LocalAddrList[t_thrd.postmaster_cxt.LocalIpNum], IP_LEN); } else if (addr->ai_family == AF_INET) { result = inet_net_ntop(AF_INET, &((struct sockaddr_in*)sinp)->sin_addr, 32, t_thrd.postmaster_cxt.LocalAddrList[t_thrd.postmaster_cxt.LocalIpNum], IP_LEN); } if (result == NULL) { ereport(WARNING, (errmsg("inet_net_ntop failed, error: %d", EAFNOSUPPORT))); } else { ereport(DEBUG5, (errmodule(MOD_COMM_FRAMEWORK), errmsg("[reload listen IP]set LocalIpNum[%d] %s", t_thrd.postmaster_cxt.LocalIpNum, t_thrd.postmaster_cxt.LocalAddrList[t_thrd.postmaster_cxt.LocalIpNum]))); t_thrd.postmaster_cxt.LocalIpNum++; } } /* finally free malloc memory */ if (addrs != NULL) { pg_freeaddrinfo_all(hint.ai_family, addrs); } } static void assign_listen_addresses(const char *newval, void *extra) { if (t_thrd.postmaster_cxt.can_listen_addresses_reload && !IsUnderPostmaster) { if (newval != NULL && strlen(newval) != 0 && u_sess->attr.attr_network.ListenAddresses != NULL && strcmp((const char *)newval, u_sess->attr.attr_network.ListenAddresses) != 0) { ereport(WARNING, (errmsg("Postmaster received signal to reload listen_addresses, update \"%s\" to \"%s\".", u_sess->attr.attr_network.ListenAddresses, newval))); t_thrd.postmaster_cxt.is_listen_addresses_reload = true; } } if (IsUnderPostmaster) { int i = 0; errno_t rc = EOK; char* rawstring = NULL; List* elemlist = NULL; rawstring = pstrdup(newval); if (!SplitIdentifierString(rawstring, ',', &elemlist)) { list_free_ext(elemlist); pfree(rawstring); return; } t_thrd.postmaster_cxt.LocalIpNum = 0; for (i = 0; i < MAXLISTEN; i++) { rc = memset_s(t_thrd.postmaster_cxt.LocalAddrList[i], IP_LEN, '\0', IP_LEN); securec_check(rc, "", ""); } ListCell* l = NULL; ListCell* elem = NULL; int checked_num = 0; foreach(l, elemlist) { char* curhost = (char*)lfirst(l); /* Deduplicatd listen IP */ int check = 0; bool has_checked = false; foreach(elem, elemlist) { if (check >= checked_num) { break; } if (strcmp(curhost, (char*)lfirst(elem)) == 0) { has_checked = true; break; } check++; } checked_num++; if (has_checked) { has_checked = false; continue; } if (strcmp(curhost, "*") == 0) { transform_ip_to_addr(NULL, (unsigned short)g_instance.attr.attr_network.PostPortNumber); } else { transform_ip_to_addr(curhost, (unsigned short)g_instance.attr.attr_network.PostPortNumber); } } list_free_ext(elemlist); pfree(rawstring); } } #endif #ifdef LIBCOMM_SPEED_TEST_ENABLE static void assign_comm_test_thread_num(int newval, void* extra) { gs_set_test_thread_num(newval); return; } static void assign_comm_test_msg_len(int newval, void* extra) { gs_set_test_msg_len(newval); return; } static void assign_comm_test_send_sleep(int newval, void* extra) { gs_set_test_send_sleep(newval); return; } static void assign_comm_test_send_once(int newval, void* extra) { gs_set_test_send_once(newval); return; } static void assign_comm_test_recv_sleep(int newval, void* extra) { gs_set_test_recv_sleep(newval); return; } static void assign_comm_test_recv_once(int newval, void* extra) { gs_set_test_recv_once(newval); return; } #endif #ifdef LIBCOMM_FAULT_INJECTION_ENABLE static void assign_comm_fault_injection(int newval, void* extra) { gs_set_fault_injection(newval); return; } #endif static const char* show_unix_socket_permissions(void) { char* buf = t_thrd.buf_cxt.show_unix_socket_permissions_buf; int size = sizeof(t_thrd.buf_cxt.show_unix_socket_permissions_buf); int rcs = 0; rcs = snprintf_s(buf, size, size - 1, "%04o", g_instance.attr.attr_network.Unix_socket_permissions); securec_check_ss(rcs, "\0", "\0"); return buf; } static bool check_max_datanode(int* newval, void** extra, GucSource source) { if (*newval + g_instance.attr.attr_network.MaxCoords > MAX_CN_DN_NODE_NUM) { ereport(LOG, (errmsg("PGXC can't support comm_max_datanode more than %d.", MAX_CN_DN_NODE_NUM - g_instance.attr.attr_network.MaxCoords))); return false; } return true; } static void comm_change_datanode(int newval, void* extra) { // newval is the number of DN. // MaxCoords is CN=16. gs_change_capacity(newval + g_instance.attr.attr_network.MaxCoords); return; } static const char* show_max_datanode(void) { char nbuf[16]; int rcs = 0; rcs = snprintf_s( nbuf, sizeof(nbuf), sizeof(nbuf) - 1, "%d", gs_get_cur_node() - g_instance.attr.attr_network.MaxCoords); securec_check_ss(rcs, "\0", "\0"); return pstrdup(nbuf); } static bool check_max_coordnode(int* newval, void** extra, GucSource source) { if (*newval + u_sess->attr.attr_network.comm_max_datanode > MAX_CN_DN_NODE_NUM) { ereport(LOG, (errmsg("PGXC can't support max_coordinators more than %d.", MAX_CN_DN_NODE_NUM - u_sess->attr.attr_network.comm_max_datanode))); return false; } return true; } static void comm_change_coordnode(int newval, void* extra) { // newval is the number of DN. // MaxCoords is CN=16. gs_change_capacity(newval + u_sess->attr.attr_network.comm_max_datanode); return; } static const char* show_max_coordnode(void) { char nbuf[16]; int rcs = 0; rcs = snprintf_s(nbuf, sizeof(nbuf), sizeof(nbuf) - 1, "%d", g_instance.attr.attr_network.MaxCoords); securec_check_ss(rcs, "\0", "\0"); return pstrdup(nbuf); }