guc.c

来自「PostgreSQL7.4.6 for Linux」· C语言 代码 · 共 2,468 行 · 第 1/5 页

C
2,468
字号
	{		/* Can't be set in postgresql.conf */		{"server_version", PGC_INTERNAL, UNGROUPED,			gettext_noop("Shows the server version."),			NULL,			GUC_REPORT | GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE		},		&server_version_string,		PG_VERSION, NULL, NULL	},	{		/* Not for general use --- used by SET SESSION AUTHORIZATION */		{"session_authorization", PGC_USERSET, UNGROUPED,			gettext_noop("Shows the session user name."),			NULL,			GUC_REPORT | GUC_NO_SHOW_ALL | GUC_NO_RESET_ALL | GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE		},		&session_authorization_string,		NULL, assign_session_authorization, show_session_authorization	},#ifdef HAVE_SYSLOG	{		{"syslog_facility", PGC_POSTMASTER, LOGGING_SYSLOG,			gettext_noop("Sets the syslog \"facility\" to be used when syslog enabled."),			gettext_noop("Valid values are LOCAL0, LOCAL1, LOCAL2, LOCAL3, "						 "LOCAL4, LOCAL5, LOCAL6, LOCAL7.")		},		&Syslog_facility,		"LOCAL0", assign_facility, NULL	},	{		{"syslog_ident", PGC_POSTMASTER, LOGGING_SYSLOG,			gettext_noop("Sets the program name used to identify PostgreSQL messages "						 "in syslog."),			NULL		},		&Syslog_ident,		"postgres", NULL, NULL	},#endif	{		{"TimeZone", PGC_USERSET, CLIENT_CONN_LOCALE,			gettext_noop("Sets the time zone for displaying and interpreting time stamps."),			NULL		},		&timezone_string,		"UNKNOWN", assign_timezone, show_timezone	},	{		{"transaction_isolation", PGC_USERSET, CLIENT_CONN_STATEMENT,			gettext_noop("Shows the current transaction's isolation level."),			NULL,			GUC_NO_RESET_ALL | GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE		},		&XactIsoLevel_string,		NULL, assign_XactIsoLevel, show_XactIsoLevel	},	{		{"unix_socket_group", PGC_POSTMASTER, 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.)")		},		&Unix_socket_group,		"", NULL, NULL	},	{		{"unix_socket_directory", PGC_POSTMASTER, CONN_AUTH_SETTINGS,			gettext_noop("Sets the directory where the Unix-domain socket will be created."),			NULL		},		&UnixSocketDir,		"", NULL, NULL	},	{		{"virtual_host", PGC_POSTMASTER, CONN_AUTH_SETTINGS,			gettext_noop("Sets the host name or IP address to listen to."),			NULL		},		&VirtualHost,		"", NULL, NULL	},	{		{"wal_sync_method", PGC_SIGHUP, WAL_SETTINGS,			gettext_noop("Selects the method used for forcing WAL updates out to disk."),			NULL		},		&XLOG_sync_method,		XLOG_sync_method_default, assign_xlog_sync_method, NULL	},	/* End-of-list marker */	{		{NULL, 0, 0, NULL, NULL}, NULL, NULL, NULL, NULL	}};/******** end of options list ********//* * Actual lookup of variables is done through this single, sorted array. */struct config_generic **guc_variables;int			num_guc_variables;static bool guc_dirty;			/* TRUE if need to do commit/abort work */static bool reporting_enabled;	/* TRUE to enable GUC_REPORT */static char *guc_string_workspace;		/* for avoiding memory leaks */static int	guc_var_compare(const void *a, const void *b);static void ReportGUCOption(struct config_generic * record);static char *_ShowOption(struct config_generic * record);/* * Build the sorted array.	This is split out so that it could be * re-executed after startup (eg, we could allow loadable modules to * add vars, and then we'd need to re-sort). */voidbuild_guc_variables(void){	int			num_vars = 0;	struct config_generic **guc_vars;	int			i;	for (i = 0; ConfigureNamesBool[i].gen.name; i++)	{		struct config_bool *conf = &ConfigureNamesBool[i];		/* Rather than requiring vartype to be filled in by hand, do this: */		conf->gen.vartype = PGC_BOOL;		num_vars++;	}	for (i = 0; ConfigureNamesInt[i].gen.name; i++)	{		struct config_int *conf = &ConfigureNamesInt[i];		conf->gen.vartype = PGC_INT;		num_vars++;	}	for (i = 0; ConfigureNamesReal[i].gen.name; i++)	{		struct config_real *conf = &ConfigureNamesReal[i];		conf->gen.vartype = PGC_REAL;		num_vars++;	}	for (i = 0; ConfigureNamesString[i].gen.name; i++)	{		struct config_string *conf = &ConfigureNamesString[i];		conf->gen.vartype = PGC_STRING;		num_vars++;	}	guc_vars = (struct config_generic **)		malloc(num_vars * sizeof(struct config_generic *));	if (!guc_vars)		ereport(FATAL,				(errcode(ERRCODE_OUT_OF_MEMORY),				 errmsg("out of memory")));	num_vars = 0;	for (i = 0; ConfigureNamesBool[i].gen.name; i++)		guc_vars[num_vars++] = &ConfigureNamesBool[i].gen;	for (i = 0; ConfigureNamesInt[i].gen.name; i++)		guc_vars[num_vars++] = &ConfigureNamesInt[i].gen;	for (i = 0; ConfigureNamesReal[i].gen.name; i++)		guc_vars[num_vars++] = &ConfigureNamesReal[i].gen;	for (i = 0; ConfigureNamesString[i].gen.name; i++)		guc_vars[num_vars++] = &ConfigureNamesString[i].gen;	qsort((void *) guc_vars, num_vars, sizeof(struct config_generic *),		  guc_var_compare);	if (guc_variables)		free(guc_variables);	guc_variables = guc_vars;	num_guc_variables = num_vars;}/* * Look up option NAME. If it exists, return a pointer to its record, * else return NULL. */static struct config_generic *find_option(const char *name){	const char **key = &name;	struct config_generic **res;	Assert(name);	/*	 * by equating const char ** with struct config_generic *, we are	 * assuming the name field is first in config_generic.	 */	res = (struct config_generic **) bsearch((void *) &key,											 (void *) guc_variables,											 num_guc_variables,										 sizeof(struct config_generic *),											 guc_var_compare);	if (res)		return *res;	return NULL;}/* * comparator for qsorting and bsearching guc_variables array */static intguc_var_compare(const void *a, const void *b){	struct config_generic *confa = *(struct config_generic **) a;	struct config_generic *confb = *(struct config_generic **) b;	const char *namea;	const char *nameb;	/*	 * The temptation to use strcasecmp() here must be resisted, because	 * the array ordering has to remain stable across setlocale() calls.	 * So, build our own with a simple ASCII-only downcasing.	 */	namea = confa->name;	nameb = confb->name;	while (*namea && *nameb)	{		char		cha = *namea++;		char		chb = *nameb++;		if (cha >= 'A' && cha <= 'Z')			cha += 'a' - 'A';		if (chb >= 'A' && chb <= 'Z')			chb += 'a' - 'A';		if (cha != chb)			return cha - chb;	}	if (*namea)		return 1;				/* a is longer */	if (*nameb)		return -1;				/* b is longer */	return 0;}/* * Initialize GUC options during program startup. */voidInitializeGUCOptions(void){	int			i;	char	   *env;	/*	 * Build sorted array of all GUC variables.	 */	build_guc_variables();	/*	 * Load all variables with their compiled-in defaults, and initialize	 * status fields as needed.	 */	for (i = 0; i < num_guc_variables; i++)	{		struct config_generic *gconf = guc_variables[i];		gconf->status = 0;		gconf->reset_source = PGC_S_DEFAULT;		gconf->session_source = PGC_S_DEFAULT;		gconf->tentative_source = PGC_S_DEFAULT;		gconf->source = PGC_S_DEFAULT;		switch (gconf->vartype)		{			case PGC_BOOL:				{					struct config_bool *conf = (struct config_bool *) gconf;					if (conf->assign_hook)						if (!(*conf->assign_hook) (conf->reset_val, true, false))							elog(FATAL, "failed to initialize %s to %d",								 conf->gen.name, (int) conf->reset_val);					*conf->variable = conf->reset_val;					conf->session_val = conf->reset_val;					break;				}			case PGC_INT:				{					struct config_int *conf = (struct config_int *) gconf;					Assert(conf->reset_val >= conf->min);					Assert(conf->reset_val <= conf->max);					/*					 * Check to make sure we only have valid					 * PGC_USERLIMITs					 */					Assert(conf->gen.context != PGC_USERLIMIT ||						   strcmp(conf->gen.name, "log_min_duration_statement") == 0);					if (conf->assign_hook)						if (!(*conf->assign_hook) (conf->reset_val, true, false))							elog(FATAL, "failed to initialize %s to %d",								 conf->gen.name, conf->reset_val);					*conf->variable = conf->reset_val;					conf->session_val = conf->reset_val;					break;				}			case PGC_REAL:				{					struct config_real *conf = (struct config_real *) gconf;					Assert(conf->reset_val >= conf->min);					Assert(conf->reset_val <= conf->max);					Assert(conf->gen.context != PGC_USERLIMIT);					if (conf->assign_hook)						if (!(*conf->assign_hook) (conf->reset_val, true, false))							elog(FATAL, "failed to initialize %s to %g",								 conf->gen.name, conf->reset_val);					*conf->variable = conf->reset_val;					conf->session_val = conf->reset_val;					break;				}			case PGC_STRING:				{					struct config_string *conf = (struct config_string *) gconf;					char	   *str;					/*					 * Check to make sure we only have valid					 * PGC_USERLIMITs					 */					Assert(conf->gen.context != PGC_USERLIMIT ||						   conf->assign_hook == assign_log_min_messages ||					   conf->assign_hook == assign_client_min_messages ||						conf->assign_hook == assign_min_error_statement);					*conf->variable = NULL;					conf->reset_val = NULL;					conf->session_val = NULL;					conf->tentative_val = NULL;					if (conf->boot_val == NULL)					{						/* Cannot set value yet */						break;					}					str = strdup(conf->boot_val);					if (str == NULL)						ereport(FATAL,								(errcode(ERRCODE_OUT_OF_MEMORY),								 errmsg("out of memory")));					conf->reset_val = str;					if (conf->assign_hook)					{						const char *newstr;						newstr = (*conf->assign_hook) (str, true, false);						if (newstr == NULL)						{							elog(FATAL, "failed to initialize %s to \"%s\"",								 conf->gen.name, str);						}						else if (newstr != str)						{							free(str);							/*							 * See notes in set_config_option about							 * casting							 */							str = (char *) newstr;							conf->reset_val = str;						}					}					*conf->variable = str;					conf->session_val = str;					break;				}		}	}	guc_dirty = false;	reporting_enabled = false;	guc_string_workspace = NULL;	/*	 * Prevent any attempt to override the transaction modes from	 * non-interactive sources.	 */	SetConfigOption("transaction_isolation", "default",					PGC_POSTMASTER, PGC_S_OVERRIDE);	SetConfigOption("transaction_read_only", "no",					PGC_POSTMASTER, PGC_S_OVERRIDE);	/*	 * For historical reasons, some GUC parameters can receive defaults	 * from environment variables.	Process those settings.	 */	env = getenv("PGPORT");	if (env != NULL)		SetConfigOption("port", env, PGC_POSTMASTER, PGC_S_ENV_VAR);	env = getenv("PGDATESTYLE");	if (env != NULL)		SetConfigOption("datestyle", env, PGC_POSTMASTER, PGC_S_ENV_VAR);	env = getenv("TZ");	if (env != NULL)		SetConfigOption("timezone", env, PGC_POSTMASTER, PGC_S_ENV_VAR);	env = getenv("PGCLIENTENCODING");	if (env != NULL)		SetConfigOption("client_encoding", env, PGC_POSTMASTER, PGC_S_ENV_VAR);}/* * Reset all options to their saved default values (implements RESET ALL) */voidResetAllOptions(void){	int			i;	for (i = 0; i < num_guc_variables; i++)	{		struct config_generic *gconf = guc_variables[i];		/* Don't reset non-SET-able values */		if (gconf->context != PGC_SUSET &&			gconf->context != PGC_USERLIMIT &&			gconf->context != PGC_USERSET)			continue;		/* Don't reset if special exclusion from RESET ALL */		if (gconf->flags & GUC_NO_RESET_ALL)			continue;		/* No need to reset if wasn't SET */		if (gconf->source <= PGC_S_OVERRIDE)			continue;		switch (gconf->vartype)		{			case PGC_BOOL:				{					struct config_bool *conf = (struct config_bool *) gconf;					if (conf->assign_hook)						if (!(*conf->assign_hook) (conf->reset_val, true, true))							elog(ERROR, "failed to reset %s", conf->gen.name);					*conf->variable = conf->reset_val;					conf->tentative_val = conf->reset_val;					conf->gen.source = conf->gen.reset_source;					conf->gen.tentative_source = conf->gen.reset_source;					conf->gen.status |= GUC_HAVE_TENTATIVE;					guc_dirty = true;					break;				}			case PGC_INT:				{					struct config_int *conf = (struct config_int *) gconf;					if (conf->assign_hook)						if (!(*conf->assign_hook) (conf->reset_val, true, true))							elog(ERROR, "failed to reset %s", conf->gen.name);					*conf->variable = conf->reset_val;					conf->tentative_val = conf->reset_val;

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?