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 + -
显示快捷键?