guc.c

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

C
2,468
字号
					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_REAL:				{					struct config_real *conf = (struct config_real *) 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_STRING:				{					struct config_string *conf = (struct config_string *) gconf;					char	   *str;					if (conf->reset_val == NULL)					{						/* Nothing to reset to, as yet; so do nothing */						break;					}					/* We need not strdup here */					str = conf->reset_val;					if (conf->assign_hook)					{						const char *newstr;						newstr = (*conf->assign_hook) (str, true, true);						if (newstr == NULL)							elog(ERROR, "failed to reset %s", conf->gen.name);						else if (newstr != str)						{							/*							 * See notes in set_config_option about							 * casting							 */							str = (char *) newstr;						}					}					SET_STRING_VARIABLE(conf, str);					SET_STRING_TENTATIVE_VAL(conf, str);					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;				}		}		if (gconf->flags & GUC_REPORT)			ReportGUCOption(gconf);	}}/* * Do GUC processing at transaction commit or abort. */voidAtEOXact_GUC(bool isCommit){	int			i;	/* Quick exit if nothing's changed in this transaction */	if (!guc_dirty)		return;	/* Prevent memory leak if ereport during an assign_hook */	if (guc_string_workspace)	{		free(guc_string_workspace);		guc_string_workspace = NULL;	}	for (i = 0; i < num_guc_variables; i++)	{		struct config_generic *gconf = guc_variables[i];		bool		changed;		/* Skip if nothing's happened to this var in this transaction */		if (gconf->status == 0)			continue;		changed = false;		switch (gconf->vartype)		{			case PGC_BOOL:				{					struct config_bool *conf = (struct config_bool *) gconf;					if (isCommit && (conf->gen.status & GUC_HAVE_TENTATIVE))					{						conf->session_val = conf->tentative_val;						conf->gen.session_source = conf->gen.tentative_source;					}					if (*conf->variable != conf->session_val)					{						if (conf->assign_hook)							if (!(*conf->assign_hook) (conf->session_val,													   true, false))								elog(LOG, "failed to commit %s",									 conf->gen.name);						*conf->variable = conf->session_val;						changed = true;					}					conf->gen.source = conf->gen.session_source;					conf->gen.status = 0;					break;				}			case PGC_INT:				{					struct config_int *conf = (struct config_int *) gconf;					if (isCommit && (conf->gen.status & GUC_HAVE_TENTATIVE))					{						conf->session_val = conf->tentative_val;						conf->gen.session_source = conf->gen.tentative_source;					}					if (*conf->variable != conf->session_val)					{						if (conf->assign_hook)							if (!(*conf->assign_hook) (conf->session_val,													   true, false))								elog(LOG, "failed to commit %s",									 conf->gen.name);						*conf->variable = conf->session_val;						changed = true;					}					conf->gen.source = conf->gen.session_source;					conf->gen.status = 0;					break;				}			case PGC_REAL:				{					struct config_real *conf = (struct config_real *) gconf;					if (isCommit && (conf->gen.status & GUC_HAVE_TENTATIVE))					{						conf->session_val = conf->tentative_val;						conf->gen.session_source = conf->gen.tentative_source;					}					if (*conf->variable != conf->session_val)					{						if (conf->assign_hook)							if (!(*conf->assign_hook) (conf->session_val,													   true, false))								elog(LOG, "failed to commit %s",									 conf->gen.name);						*conf->variable = conf->session_val;						changed = true;					}					conf->gen.source = conf->gen.session_source;					conf->gen.status = 0;					break;				}			case PGC_STRING:				{					struct config_string *conf = (struct config_string *) gconf;					if (isCommit && (conf->gen.status & GUC_HAVE_TENTATIVE))					{						SET_STRING_SESSION_VAL(conf, conf->tentative_val);						conf->gen.session_source = conf->gen.tentative_source;						conf->tentative_val = NULL;		/* transfer ownership */					}					else						SET_STRING_TENTATIVE_VAL(conf, NULL);					if (*conf->variable != conf->session_val)					{						char	   *str = conf->session_val;						if (conf->assign_hook)						{							const char *newstr;							newstr = (*conf->assign_hook) (str, true, false);							if (newstr == NULL)								elog(LOG, "failed to commit %s",									 conf->gen.name);							else if (newstr != str)							{								/*								 * See notes in set_config_option about								 * casting								 */								str = (char *) newstr;								SET_STRING_SESSION_VAL(conf, str);							}						}						SET_STRING_VARIABLE(conf, str);						changed = true;					}					conf->gen.source = conf->gen.session_source;					conf->gen.status = 0;					break;				}		}		if (changed && (gconf->flags & GUC_REPORT))			ReportGUCOption(gconf);	}	guc_dirty = false;}/* * Start up automatic reporting of changes to variables marked GUC_REPORT. * This is executed at completion of backend startup. */voidBeginReportingGUCOptions(void){	int			i;	/*	 * Don't do anything unless talking to an interactive frontend of	 * protocol 3.0 or later.	 */	if (whereToSendOutput != Remote ||		PG_PROTOCOL_MAJOR(FrontendProtocol) < 3)		return;	reporting_enabled = true;	/* Transmit initial values of interesting variables */	for (i = 0; i < num_guc_variables; i++)	{		struct config_generic *conf = guc_variables[i];		if (conf->flags & GUC_REPORT)			ReportGUCOption(conf);	}}/* * ReportGUCOption: if appropriate, transmit option value to frontend */static voidReportGUCOption(struct config_generic * record){	if (reporting_enabled && (record->flags & GUC_REPORT))	{		char	   *val = _ShowOption(record);		StringInfoData msgbuf;		pq_beginmessage(&msgbuf, 'S');		pq_sendstring(&msgbuf, record->name);		pq_sendstring(&msgbuf, val);		pq_endmessage(&msgbuf);		pfree(val);	}}/* * Try to interpret value as boolean value.  Valid values are: true, * false, yes, no, on, off, 1, 0.  If the string parses okay, return * true, else false.  If result is not NULL, return the parsing result * there. */static boolparse_bool(const char *value, bool *result){	size_t		len = strlen(value);	if (strncasecmp(value, "true", len) == 0)	{		if (result)			*result = true;	}	else if (strncasecmp(value, "false", len) == 0)	{		if (result)			*result = false;	}	else if (strncasecmp(value, "yes", len) == 0)	{		if (result)			*result = true;	}	else if (strncasecmp(value, "no", len) == 0)	{		if (result)			*result = false;	}	else if (strcasecmp(value, "on") == 0)	{		if (result)			*result = true;	}	else if (strcasecmp(value, "off") == 0)	{		if (result)			*result = false;	}	else if (strcasecmp(value, "1") == 0)	{		if (result)			*result = true;	}	else if (strcasecmp(value, "0") == 0)	{		if (result)			*result = false;	}	else		return false;	return true;}/* * Try to parse value as an integer.  The accepted formats are the * usual decimal, octal, or hexadecimal formats.  If the string parses * okay, return true, else false.  If result is not NULL, return the * value there. */static boolparse_int(const char *value, int *result){	long		val;	char	   *endptr;	errno = 0;	val = strtol(value, &endptr, 0);	if (endptr == value || *endptr != '\0' || errno == ERANGE#ifdef HAVE_LONG_INT_64	/* if long > 32 bits, check for overflow of int4 */		|| val != (long) ((int32) val)#endif		)		return false;	if (result)		*result = (int) val;	return true;}/* * Try to parse value as a floating point constant in the usual * format.	If the value parsed okay return true, else false.  If * result is not NULL, return the semantic value there. */static boolparse_real(const char *value, double *result){	double		val;	char	   *endptr;	errno = 0;	val = strtod(value, &endptr);	if (endptr == value || *endptr != '\0' || errno == ERANGE)		return false;	if (result)		*result = val;	return true;}/* * Sets option `name' to given value. The value should be a string * which is going to be parsed and converted to the appropriate data * type.  The context and source parameters indicate in which context this * function is being called so it can apply the access restrictions * properly. * * If value is NULL, set the option to its default value. If the * parameter changeVal is false then don't really set the option but do all * the checks to see if it would work. * * If there is an error (non-existing option, invalid value) then an * ereport(ERROR) is thrown *unless* this is called in a context where we * don't want to ereport (currently, startup or SIGHUP config file reread). * In that case we write a suitable error message via ereport(DEBUG) and * return false. This is working around the deficiencies in the ereport * mechanism, so don't blame me.  In all other cases, the function * returns true, including cases where the input is valid but we chose * not to apply it because of context or source-priority considerations. * * See also SetConfigOption for an external interface. */boolset_config_option(const char *name, const char *value,				  GucContext context, GucSource source,				  bool isLocal, bool changeVal){	struct config_generic *record;	int			elevel;	bool		interactive;	bool		makeDefault;	bool		changeVal_orig;	if (context == PGC_SIGHUP || source == PGC_S_DEFAULT)		elevel = DEBUG2;	else if (source == PGC_S_DATABASE || source == PGC_S_USER)		elevel = INFO;	else		elevel = ERROR;	record = find_option(name);	if (record == NULL)	{		ereport(elevel,				(errcode(ERRCODE_UNDEFINED_OBJECT),				 errmsg("unrecognized configuration parameter \"%s\"", name)));		return false;	}	/*	 * Check if the option can be set at this time. See guc.h for the	 * precise rules. Note that we don't want to throw errors if we're in	 * the SIGHUP context. In that case we just ignore the attempt and	 * return true.	 */	switch (record->context)	{		case PGC_INTERNAL:			if (context == PGC_SIGHUP)				return true;			if (context != PGC_INTERNAL)			{				ereport(elevel,						(errcode(ERRCODE_CANT_CHANGE_RUNTIME_PARAM),						 errmsg("parameter \"%s\" cannot be changed",								name)));				return false;			}			break;		case PGC_POSTMASTER:			if (context == PGC_SIGHUP)				return true;			if (context != PGC_POSTMASTER)			{				ereport(elevel,						(errcode(ERRCODE_CANT_CHANGE_RUNTIME_PARAM),					errmsg("parameter \"%s\" cannot be changed after server start",						   name)));				return false;			}			break;		case PGC_SIGHUP:			if (context != PGC_SIGHUP && context != PGC_POSTMASTER)			{				ereport(elevel,						(errcode(ERRCODE_CANT_CHANGE_RUNTIME_PARAM),						 errmsg("parameter \"%s\" cannot be changed now",								name)));				return false;			}			/*			 * Hmm, the idea of the SIGHUP context is "ought to be global,			 * but can be changed after postmaster start". But there's			 * nothing that prevents a crafty administrator from sending			 * SIGHUP signals to individual backends only.			 */			break;		case PGC_BACKEND:			if (context == PGC_SIGHUP)			{				/*				 * If a PGC_BACKEND parameter is changed in the config				 * file, we want to accept the new value in the postmaster				 * (w

⌨️ 快捷键说明

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