diff options
author | Pavan Deolasee | 2016-02-08 06:17:40 +0000 |
---|---|---|
committer | Pavan Deolasee | 2016-10-18 09:57:39 +0000 |
commit | 334e6aa8350615ccfbdaedebd28537ce5ea7b242 (patch) | |
tree | 51dfd0a0e0ce288ac968e0fd029b7c6833e7aa8d | |
parent | 3366f09175bf4bd77b6a0decba38cb3b32e73dca (diff) |
Add support for overrding default log levels for specfic messages or all
messages in a file or a module.
We now support a new --enable-genmsgids configure option. When compiled with
this, superusers can run pg_msgmodule_set(moduleid, fileid, msgid, newlevel)
command to override the log level specified in the source code.
There are many TODOs and limitations of this approach. We could only, for
example, increase logging level of messages i.e. turn DEBUG2 to DEBUG1 or DEBUG
to LOG. But we can't change ERROR to PANIC or supress a log message. Also, we
are using a very sparse representation of the message log levels. This
increases memory requirements significantly, though should speed up lookups and
keep the code simple.
When configured with --enable-genmsgids, a file named MSGMODULES is created at
the top of the build tree and the module-ids are later picked from that file
while compiling individual files. We would also preprocess each file before
compilation and save all elog() calls, along with the file_name, line_number,
messgae, module_id, file_id, msg_id in MSGIDS file. This file can then be used
to lookup the messages so that correct information is passed. This clearly
needs a lot more polishing and work.
When configued without --enable-genmsgids, we don't expect this facility to add
overhead because all codes gets #ifdef-ed out
-rw-r--r-- | GNUmakefile.in | 1 | ||||
-rwxr-xr-x | config/create_msgids.sh | 55 | ||||
-rwxr-xr-x | configure | 31 | ||||
-rw-r--r-- | configure.in | 9 | ||||
-rw-r--r-- | contrib/pgxc_ctl/Makefile | 2 | ||||
-rw-r--r-- | src/Makefile.global.in | 35 | ||||
-rw-r--r-- | src/backend/storage/ipc/ipci.c | 8 | ||||
-rw-r--r-- | src/backend/utils/error/elog.c | 272 | ||||
-rw-r--r-- | src/bin/gtm_ctl/Makefile | 2 | ||||
-rw-r--r-- | src/common/Makefile | 7 | ||||
-rw-r--r-- | src/include/catalog/pg_proc.h | 30 | ||||
-rw-r--r-- | src/include/pg_config.h.in | 3 | ||||
-rw-r--r-- | src/include/utils/builtins.h | 4 | ||||
-rw-r--r-- | src/include/utils/elog.h | 81 | ||||
-rw-r--r-- | src/port/Makefile | 7 |
15 files changed, 504 insertions, 43 deletions
diff --git a/GNUmakefile.in b/GNUmakefile.in index 15fba9fce0..74b583e8c8 100644 --- a/GNUmakefile.in +++ b/GNUmakefile.in @@ -62,6 +62,7 @@ distclean maintainer-clean: # Garbage from autoconf: @rm -rf autom4te.cache/ rm -f config.cache config.log config.status GNUmakefile + rm -f MSGIDS MSGMODULES check check-tests installcheck installcheck-parallel installcheck-tests: $(MAKE) -C src/test/regress $@ diff --git a/config/create_msgids.sh b/config/create_msgids.sh new file mode 100755 index 0000000000..97ef062a69 --- /dev/null +++ b/config/create_msgids.sh @@ -0,0 +1,55 @@ +#/usr/bin/env sh + +# +# Run this script when configuring with --enable-genmsgids +# +# Recurse through all subdiectories, collecting information about all subdirs +# which has a Makefile/GNUMakefile with "subdir = <subdir_name>" entry and +# assign a module_id for all such subdirs. The Makefile.global then looks up +# this catalog and uses the module_id configured. +# +# The script assumes that every subdir's Makefile has a specific pattern of +# "^subdir = .*", which is thankfully true for subdirs that we care for +# +# We could be a lot smarter than what we are doing, especially avoiding +# module_id assignment for subdirs which do not directly compile any files with +# elog() messages. +# +MSG_MODULE=0 +handle_dir() +{ + MSG_MODULE=`expr $2 + 1` + for subdir in `ls $1`; do + if [ -d $1/$subdir ]; then + makefile1=$1/$subdir/Makefile + makefile2=$1/$subdir/GNUMakefile + if [ -f $makefile1 ]; then + cat $makefile1 | grep -E "^subdir = " > /dev/null + if [ $? -ne 0 ]; then + if [ -f $makefile2 ]; then + cat $makefile2 | grep -E "^subdir = " > /dev/null + if [ $? -eq 0 ]; then + makefile=$makefile2 + else + continue + fi + else + continue + fi + else + makefile=$makefile1 + fi + else + continue + fi + cat $makefile | grep -E "^subdir = " > /dev/null + if [ $? -eq 0 ]; then + moduledir=`cat $makefile | grep -E '^subdir = '` + echo $moduledir:${MSG_MODULE} + fi + handle_dir "$1/$subdir" $MSG_MODULE + fi + done +} + +handle_dir "." $MSG_MODULE @@ -718,6 +718,7 @@ with_tcl enable_thread_safety INCLUDES autodepend +genmsgids TAS GCC CPP @@ -818,6 +819,7 @@ with_wal_blocksize with_wal_segsize with_CC enable_depend +enable_genmsgids enable_cassert enable_thread_safety with_tcl @@ -5194,6 +5196,35 @@ else fi +# +# Automatic msgids generation +# + + +# Check whether --enable-genmsgids was given. +if test "${enable_genmsgids+set}" = set; then : + enableval=$enable_genmsgids; + case $enableval in + yes) + +$as_echo "#define USE_MODULE_MSGIDS 1" >>confdefs.h + + genmsgids=yes + $srcdir/config/create_msgids.sh > MSGMODULES 2>&1 + + ;; + no) + : + ;; + *) + as_fn_error $? "no argument expected for --enable-genmsgids option" "$LINENO" 5 + ;; + esac + +else + enable_genmsgids=no + +fi diff --git a/configure.in b/configure.in index 1455d25a5c..17b061146e 100644 --- a/configure.in +++ b/configure.in @@ -543,7 +543,6 @@ PGAC_ARG_BOOL(enable, depend, no, [turn on automatic dependency tracking], [autodepend=yes]) AC_SUBST(autodepend) - # # Enable assert checks # @@ -553,6 +552,14 @@ PGAC_ARG_BOOL(enable, cassert, no, [enable assertion checks (for debugging)], # +# Enable module msgids +# +PGAC_ARG_BOOL(enable, genmsgids, no, [enable module msgids (for debugging)], + [AC_DEFINE([USE_MODULE_MSGIDS], 1, + [Define to 1 to build with module msgids. (--enable-genmsgids)])]) +AC_SUBST(genmsgids) + +# # Include directories # ac_save_IFS=$IFS diff --git a/contrib/pgxc_ctl/Makefile b/contrib/pgxc_ctl/Makefile index 25ff6ccf0f..e96a46d8f0 100644 --- a/contrib/pgxc_ctl/Makefile +++ b/contrib/pgxc_ctl/Makefile @@ -30,7 +30,7 @@ PG_CONFIG = pg_config PGXS := $(shell $(PG_CONFIG) --pgxs) include $(PGXS) else -subdir = contrib/pgxc_clean +subdir = contrib/pgxc_ctl top_builddir = ../.. include $(top_builddir)/src/Makefile.global include $(top_srcdir)/contrib/contrib-global.mk diff --git a/src/Makefile.global.in b/src/Makefile.global.in index 1287c0d2eb..65e313a7e4 100644 --- a/src/Makefile.global.in +++ b/src/Makefile.global.in @@ -721,7 +721,6 @@ recurse = $(foreach target,$(if $1,$1,$(standard_targets)),$(foreach subdir,$(if # $3: target to run in subdir (defaults to current element of $1) recurse_always = $(foreach target,$(if $1,$1,$(standard_always_targets)),$(foreach subdir,$(if $2,$2,$(ALWAYS_SUBDIRS)),$(eval $(call _create_recursive_target,$(target),$(subdir),$(if $3,$3,$(target)))))) - ########################################################################## # # Automatic dependency generation @@ -838,3 +837,37 @@ coverage-clean: rm -f `find . -name '*.gcda' -print` endif # enable_coverage + +genmsgids = @genmsgids@ + +ifeq ($(genmsgids), yes) +PREPROCESS.c = $(CC) $(CFLAGS) $(CPPFLAGS) -E + +PGXL_MSG_FILEID := 1 +PGXL_MSG_MODULE := $(shell cat $(top_builddir)/MSGMODULES | grep -E "^subdir = $(subdir):" | cut -d ':' -f 2) + +ifeq ($(autodepend), yes) +ifeq ($(GCC), yes) + +# GCC allows us to create object and dependency file in one invocation. +%.o : %.c + @if test ! -d $(DEPDIR); then mkdir -p $(DEPDIR); fi + $(PREPROCESS.c) -DPGXL_MSG_MODULE=$(PGXL_MSG_MODULE) -DPGXL_MSG_FILEID=$(PGXL_MSG_FILEID) -o [email protected] $< -MMD -MP -MF $(DEPDIR)/$(*F).Po + -cat [email protected] | grep -E "do \{ if \(errstart|do \{ if \(elog_start" >> $(top_srcdir)/MSGIDS + -rm -f [email protected] + $(COMPILE.c) -DPGXL_MSG_MODULE=$(PGXL_MSG_MODULE) -DPGXL_MSG_FILEID=$(PGXL_MSG_FILEID) -o $@ $< -MMD -MP -MF $(DEPDIR)/$(*F).Po + $(eval PGXL_MSG_FILEID := $(shell echo $(PGXL_MSG_FILEID) + 1 | bc)) +endif # GCC +else +ifeq ($(GCC), yes) +%.o : %.c + $(PREPROCESS.c) -DPGXL_MSG_MODULE=$(PGXL_MSG_MODULE) -DPGXL_MSG_FILEID=$(PGXL_MSG_FILEID) -o [email protected] $< + -cat [email protected] | grep -E "do \{ if \(errstart|do \{ if \(elog_start" >> $(top_srcdir)/MSGIDS + -rm -f [email protected] + $(COMPILE.c) -DPGXL_MSG_MODULE=$(PGXL_MSG_MODULE) -DPGXL_MSG_FILEID=$(PGXL_MSG_FILEID) -o $@ $< + $(eval PGXL_MSG_FILEID := $(shell echo $(PGXL_MSG_FILEID) + 1 | bc)) +endif # GCC + +endif # autodepend + +endif # enable_genmsgids diff --git a/src/backend/storage/ipc/ipci.c b/src/backend/storage/ipc/ipci.c index 3895031901..6804367fa3 100644 --- a/src/backend/storage/ipc/ipci.c +++ b/src/backend/storage/ipc/ipci.c @@ -166,6 +166,10 @@ CreateSharedMemoryAndSemaphores(bool makePrivate, int port) size = add_size(size, ShmemBackendArraySize()); #endif +#ifdef USE_MODULE_MSGIDS + size = add_size(size, MsgModuleShmemSize()); +#endif + /* freeze the addin request size and include it */ addin_request_allowed = false; size = add_size(size, total_addin_request); @@ -299,6 +303,10 @@ CreateSharedMemoryAndSemaphores(bool makePrivate, int port) ShmemBackendArrayAllocation(); #endif +#ifdef USE_MODULE_MSGIDS + MsgModuleShmemInit(); +#endif + /* Initialize dynamic shared memory facilities. */ if (!IsUnderPostmaster) dsm_postmaster_startup(shim); diff --git a/src/backend/utils/error/elog.c b/src/backend/utils/error/elog.c index 73a19f51fa..eee276e94f 100644 --- a/src/backend/utils/error/elog.c +++ b/src/backend/utils/error/elog.c @@ -176,12 +176,21 @@ static const char *useful_strerror(int errnum); static const char *get_errno_symbol(int errnum); static const char *error_severity(int elevel); static void append_with_tabs(StringInfo buf, const char *str); -static bool is_log_level_output(int elevel, int log_min_level); +static bool is_log_level_output(int elevel, +#ifdef USE_MODULE_MSGIDS + int moduleid, + int fileid, + int msgid, +#endif + int log_min_level); static void write_pipe_chunks(char *data, int len, int dest); static void write_csvlog(ErrorData *edata); static void setup_formatted_log_time(void); static void setup_formatted_start_time(void); +#ifdef USE_MODULE_MSGIDS +char *MsgModuleCtl; +#endif /* * in_error_recursion_trouble --- are we at risk of infinite error recursion? @@ -229,6 +238,9 @@ err_gettext(const char *str) */ bool errstart(int elevel, const char *filename, int lineno, +#ifdef USE_MODULE_MSGIDS + int moduleid, int fileid, int msgid, +#endif const char *funcname, const char *domain) { ErrorData *edata; @@ -288,7 +300,13 @@ errstart(int elevel, const char *filename, int lineno, */ /* Determine whether message is enabled for server log output */ - output_to_server = is_log_level_output(elevel, log_min_messages); + output_to_server = is_log_level_output(elevel, +#ifdef USE_MODULE_MSGIDS + moduleid, + fileid, + msgid, +#endif + log_min_messages); /* Determine whether message is enabled for client output */ if (whereToSendOutput == DestRemote && elevel != COMMERROR) @@ -1290,7 +1308,11 @@ getinternalerrposition(void) * evaluating the format arguments if we do that.) */ void -elog_start(const char *filename, int lineno, const char *funcname) +elog_start(const char *filename, int lineno, +#ifdef USE_MODULE_MSGIDS + int moduleid, int fileid, int msgid, +#endif + const char *funcname) { ErrorData *edata; @@ -1329,6 +1351,11 @@ elog_start(const char *filename, int lineno, const char *funcname) edata->filename = filename; edata->lineno = lineno; edata->funcname = funcname; +#ifdef USE_MODULE_MSGIDS + edata->moduleid = moduleid; + edata->fileid = fileid; + edata->msgid = msgid; +#endif /* errno is saved now so that error parameter eval can't change it */ edata->saved_errno = errno; @@ -1352,7 +1379,12 @@ elog_finish(int elevel, const char *fmt,...) */ errordata_stack_depth--; errno = edata->saved_errno; - if (!errstart(elevel, edata->filename, edata->lineno, edata->funcname, NULL)) + if (!errstart(elevel, edata->filename, edata->lineno, +#ifdef USE_MODULE_MSGIDS + edata->moduleid, + edata->fileid, edata->msgid, +#endif + edata->funcname, NULL)) return; /* nothing to do */ /* @@ -1600,6 +1632,10 @@ ThrowErrorData(ErrorData *edata) MemoryContext oldcontext; if (!errstart(edata->elevel, edata->filename, edata->lineno, +#ifdef USE_MODULE_MSGIDS + edata->moduleid, + edata->fileid, edata->msgid, +#endif edata->funcname, NULL)) return; @@ -1733,7 +1769,12 @@ pg_re_throw(void) */ if (IsPostmasterEnvironment) edata->output_to_server = is_log_level_output(FATAL, - log_min_messages); +#ifdef USE_MODULE_MSGIDS + 0, + 0, + 0, +#endif + log_min_messages); else edata->output_to_server = (FATAL >= log_min_messages); if (whereToSendOutput == DestRemote) @@ -2767,7 +2808,13 @@ write_csvlog(ErrorData *edata) appendStringInfoChar(&buf, ','); /* user query --- only reported if not disabled by the caller */ - if (is_log_level_output(edata->elevel, log_min_error_statement) && + if (is_log_level_output(edata->elevel, +#ifdef USE_MODULE_MSGIDS + edata->moduleid, + edata->fileid, + edata->msgid, +#endif + log_min_error_statement) && debug_query_string != NULL && !edata->hide_stmt) print_stmt = true; @@ -2924,7 +2971,13 @@ send_message_to_server_log(ErrorData *edata) /* * If the user wants the query that generated this error logged, do it. */ - if (is_log_level_output(edata->elevel, log_min_error_statement) && + if (is_log_level_output(edata->elevel, +#ifdef USE_MODULE_MSGIDS + edata->moduleid, + edata->fileid, + edata->msgid, +#endif + log_min_error_statement) && debug_query_string != NULL && !edata->hide_stmt) { @@ -3672,6 +3725,37 @@ write_stderr(const char *fmt,...) va_end(ap); } +#ifdef USE_MODULE_MSGIDS +static int +get_overriden_log_level(int moduleid, int fileid, int msgid, int origlevel) +{ + uint32 position; + + /* + * The shared memory may not set during init processing or in a stand alone + * backend. + */ + if (!IsPostmasterEnvironment || IsInitProcessingMode()) + return origlevel; + + /* + * Reject invalid bounds + */ + if ((moduleid <= 0 || moduleid >= PGXL_MSG_MAX_MODULES) || + (fileid <= 0 || fileid >= PGXL_MSG_MAX_FILEIDS_PER_MODULE) || + (msgid <= 0 || msgid >= PGXL_MSG_MAX_MSGIDS_PER_FILE)) + return origlevel; + + /* + * Get the overridden log level and return it back + */ + position = (moduleid - 1) * PGXL_MSG_MAX_FILEIDS_PER_MODULE * + PGXL_MSG_MAX_MSGIDS_PER_FILE + + (fileid - 1) * PGXL_MSG_MAX_MSGIDS_PER_FILE + + (msgid - 1); + return MsgModuleCtl[position] ? MsgModuleCtl[position] : origlevel; +} +#endif /* * is_log_level_output -- is elevel logically >= log_min_level? @@ -3682,7 +3766,13 @@ write_stderr(const char *fmt,...) * test is correct for testing whether the message should go to the client. */ static bool -is_log_level_output(int elevel, int log_min_level) +is_log_level_output(int elevel, +#ifdef USE_MODULE_MSGIDS + int moduleid, + int fileid, + int msgid, +#endif + int log_min_level) { if (elevel == LOG || elevel == COMMERROR) { @@ -3698,6 +3788,34 @@ is_log_level_output(int elevel, int log_min_level) /* Neither is LOG */ else if (elevel >= log_min_level) return true; +#ifdef USE_MODULE_MSGIDS + /* + * Check if the message's compile time value has been changed during the + * run time. + * + * Currently, we only support increasing the log level of messages and that + * too only for deciding whether the message should go to the server log or + * not. A message which would otherwise not qualify to go to the server + * log, thus can be forced to be logged. + * + * In future, we may also want to go otherway round i.e. supressing a log + * message or also change severity of log messages. The latter may + * especially be useful to turn some specific ERROR messages into FATAL or + * PANIC to be able to get a core dump for analysis. + */ + else + { + int newlevel = get_overriden_log_level(moduleid, fileid, msgid, + elevel); + if (newlevel == LOG) + { + if (log_min_level == LOG || log_min_level <= ERROR) + return true; + } + else if (newlevel >= log_min_level) + return true; + } +#endif return false; } @@ -3726,3 +3844,141 @@ trace_recovery(int trace_level) return trace_level; } + +#ifdef USE_MODULE_MSGIDS +Size +MsgModuleShmemSize(void) +{ + Size mm_size; + + /* + * One byte per message to store overridden log level. + * !!TODO We don't really need a byte and a few bits would be enough. So + * look for improving this/ + * + * What we have done is a very simplisitic representation of msg-ids. The + * overall memory requirement of this representation is too large as + * compared to the actual number of msgs. For example, both + * PGXL_MSG_MAX_MSGIDS_PER_FILE and PGXL_MSG_MAX_FILEIDS_PER_MODULE are set + * to the largest value that any one module uses, but the actual values are + * much smaller + * + * In theory, we could also have separate area for each backend so that + * logging can be controlled at a backend level. But the current + * representation is not at all efficient to do that. + */ + mm_size = mul_size(PGXL_MSG_MAX_MODULES, PGXL_MSG_MAX_FILEIDS_PER_MODULE); + mm_size = mul_size(mm_size, PGXL_MSG_MAX_MSGIDS_PER_FILE); + + return mm_size; +} + +void +MsgModuleShmemInit(void) +{ + bool found; + + MsgModuleCtl = ShmemInitStruct("Message Module Struct", + (PGXL_MSG_MAX_MODULES * + PGXL_MSG_MAX_FILEIDS_PER_MODULE * + PGXL_MSG_MAX_MSGIDS_PER_FILE), + &found); +} + +Datum +pg_msgmodule_set(PG_FUNCTION_ARGS) +{ + int32 moduleid = PG_GETARG_INT32(0); + int32 fileid = PG_GETARG_INT32(1); + int32 msgid = PG_GETARG_INT32(2); + const char *levelstr = PG_GETARG_CSTRING(3); + int32 level; + uint32 start_position; + uint32 len; + + if (!superuser()) + ereport(ERROR, + (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), + (errmsg("must be superuser to change elog message level")))); + + /* + * The only accepted values for the log levels are - LOG, DEBUG[1-5] and + * DEFAULT + */ + if (strcasecmp(levelstr, "LOG") == 0) + level = LOG; + else if (strcasecmp(levelstr, "DEFAULT") == 0) + level = 0; + else if (strcasecmp(levelstr, "DEBUG1") == 0) + level = DEBUG1; + else if (strcasecmp(levelstr, "DEBUG2") == 0) + level = DEBUG2; + else if (strcasecmp(levelstr, "DEBUG3") == 0) + level = DEBUG3; + else if (strcasecmp(levelstr, "DEBUG4") == 0) + level = DEBUG4; + else if (strcasecmp(levelstr, "DEBUG5") == 0) + level = DEBUG5; + else + ereport(ERROR, + (errcode(ERRCODE_INTERNAL_ERROR), + (errmsg("Invalid value \"%s\" for log level", levelstr)))); + + if (moduleid <= 0 || moduleid >= PGXL_MSG_MAX_MODULES) + ereport(ERROR, (errmsg_internal("Invalid module id %d, allowed values 1-%d", + moduleid, PGXL_MSG_MAX_MODULES))); + + if (fileid == -1) + { + /* + * All messages in the given module to be overridden with the given + * level + */ + len = PGXL_MSG_MAX_FILEIDS_PER_MODULE * PGXL_MSG_MAX_MSGIDS_PER_FILE; + start_position = (moduleid - 1) * len; + memset(MsgModuleCtl + start_position, level, len); + PG_RETURN_BOOL(true); + } + else + { + if (fileid <= 0 || fileid >= PGXL_MSG_MAX_FILEIDS_PER_MODULE) + ereport(ERROR, (errmsg_internal("Invalid file id %d, allowed values 1-%d", + fileid, PGXL_MSG_MAX_FILEIDS_PER_MODULE))); + + /* + * All messages in the given <module, file> to be overridden with the + * given level + */ + if (msgid == -1) + { + len = PGXL_MSG_MAX_MSGIDS_PER_FILE; + start_position = ((moduleid - 1) * PGXL_MSG_MAX_FILEIDS_PER_MODULE * PGXL_MSG_MAX_MSGIDS_PER_FILE) + + (fileid - 1) * PGXL_MSG_MAX_MSGIDS_PER_FILE; + memset(MsgModuleCtl + start_position, level, len); + PG_RETURN_BOOL(true); + } + + if (msgid <= 0 || msgid >= PGXL_MSG_MAX_MSGIDS_PER_FILE) + ereport(ERROR, (errmsg_internal("Invalid msg id %d, allowed values 1-%d", + fileid, PGXL_MSG_MAX_MSGIDS_PER_FILE))); + + /* + * Deal with a specific <module, file, msg> + */ + len = sizeof (char); + start_position = ((moduleid - 1) * PGXL_MSG_MAX_FILEIDS_PER_MODULE * PGXL_MSG_MAX_MSGIDS_PER_FILE) + + ((fileid - 1) * PGXL_MSG_MAX_MSGIDS_PER_FILE) + + (msgid - 1); + memset(MsgModuleCtl + start_position, level, len); + PG_RETURN_BOOL(true); + } + PG_RETURN_BOOL(true); +} +#else +Datum +pg_msgmodule_set(PG_FUNCTION_ARGS) +{ + ereport(ERROR, (errmsg_internal("Module msgid support not available. " + "Please recompile with --enable-genmsgids"))); +} +#endif diff --git a/src/bin/gtm_ctl/Makefile b/src/bin/gtm_ctl/Makefile index 48750dfade..14b76d5f48 100644 --- a/src/bin/gtm_ctl/Makefile +++ b/src/bin/gtm_ctl/Makefile @@ -9,7 +9,7 @@ #----------------------------------------------------------------------------- top_builddir=../../.. include $(top_builddir)/src/Makefile.global -subdir=src/bin/gtm_ctl +subdir = src/bin/gtm_ctl override CPPFLAGS := -I$(libpq_srcdir) $(CPPFLAGS) diff --git a/src/common/Makefile b/src/common/Makefile index c47445e768..63a187703d 100644 --- a/src/common/Makefile +++ b/src/common/Makefile @@ -60,8 +60,15 @@ libpgcommon_srv.a: $(OBJS_SRV) # their *.o siblings as well, which do have proper dependencies. It's # a hack that might fail someday if there is a *_srv.o without a # corresponding *.o, but it works for now. +ifeq ($(genmsgids), yes) +PGXL_MSG_FILEID := 1 +%_srv.o: %.c %.o + $(CC) $(CFLAGS) -DPGXL_MSG_MODULE=$(PGXL_MSG_MODULE) -DPGXL_MSG_FILEID=$(PGXL_MSG_FILEID) $(subst -DFRONTEND,, $(CPPFLAGS)) -c $< -o $@ + $(eval PGXL_MSG_FILEID := $(shell echo $(PGXL_MSG_FILEID) + 1 | bc)) +else %_srv.o: %.c %.o $(CC) $(CFLAGS) $(subst -DFRONTEND,, $(CPPFLAGS)) -c $< -o $@ +endif $(OBJS_SRV): | submake-errcodes diff --git a/src/include/catalog/pg_proc.h b/src/include/catalog/pg_proc.h index 9c1d8d5d4e..8e0be6684a 100644 --- a/src/include/catalog/pg_proc.h +++ b/src/include/catalog/pg_proc.h @@ -5370,32 +5370,10 @@ DESCR("get an individual replication origin's replication progress"); DATA(insert OID = 6014 ( pg_show_replication_origin_status PGNSP PGUID 12 1 100 0 0 f f f f f t v 0 0 2249 "" "{26,25,3220,3220}" "{o,o,o,o}" "{local_id, external_id, remote_lsn, local_lsn}" _null_ _null_ pg_show_replication_origin_status _null_ _null_ _null_ )); DESCR("get progress for all replication origins"); -/* tablesample */ -DATA(insert OID = 3335 ( tsm_system_init PGNSP PGUID 12 1 0 0 0 f f f f t f v 3 0 2278 "2281 23 700" _null_ _null_ _null_ _null_ _null_ tsm_system_init _null_ _null_ _null_ )); -DESCR("tsm_system_init(internal)"); -DATA(insert OID = 3336 ( tsm_system_nextblock PGNSP PGUID 12 1 0 0 0 f f f f t f v 2 0 23 "2281 16" _null_ _null_ _null_ _null_ _null_ tsm_system_nextblock _null_ _null_ _null_ )); -DESCR("tsm_system_nextblock(internal)"); -DATA(insert OID = 3337 ( tsm_system_nexttuple PGNSP PGUID 12 1 0 0 0 f f f f t f v 4 0 21 "2281 23 21 16" _null_ _null_ _null_ _null_ _null_ tsm_system_nexttuple _null_ _null_ _null_ )); -DESCR("tsm_system_nexttuple(internal)"); -DATA(insert OID = 3338 ( tsm_system_end PGNSP PGUID 12 1 0 0 0 f f f f t f v 1 0 2278 "2281" _null_ _null_ _null_ _null_ _null_ tsm_system_end _null_ _null_ _null_ )); -DESCR("tsm_system_end(internal)"); -DATA(insert OID = 3339 ( tsm_system_reset PGNSP PGUID 12 1 0 0 0 f f f f t f v 1 0 2278 "2281" _null_ _null_ _null_ _null_ _null_ tsm_system_reset _null_ _null_ _null_ )); -DESCR("tsm_system_reset(internal)"); -DATA(insert OID = 3340 ( tsm_system_cost PGNSP PGUID 12 1 0 0 0 f f f f t f v 7 0 2278 "2281 2281 2281 2281 2281 2281 2281" _null_ _null_ _null_ _null_ _null_ tsm_system_cost _null_ _null_ _null_ )); -DESCR("tsm_system_cost(internal)"); - -DATA(insert OID = 3341 ( tsm_bernoulli_init PGNSP PGUID 12 1 0 0 0 f f f f t f v 3 0 2278 "2281 23 700" _null_ _null_ _null_ _null_ _null_ tsm_bernoulli_init _null_ _null_ _null_ )); -DESCR("tsm_bernoulli_init(internal)"); -DATA(insert OID = 3342 ( tsm_bernoulli_nextblock PGNSP PGUID 12 1 0 0 0 f f f f t f v 2 0 23 "2281 16" _null_ _null_ _null_ _null_ _null_ tsm_bernoulli_nextblock _null_ _null_ _null_ )); -DESCR("tsm_bernoulli_nextblock(internal)"); -DATA(insert OID = 3343 ( tsm_bernoulli_nexttuple PGNSP PGUID 12 1 0 0 0 f f f f t f v 4 0 21 "2281 23 21 16" _null_ _null_ _null_ _null_ _null_ tsm_bernoulli_nexttuple _null_ _null_ _null_ )); -DESCR("tsm_bernoulli_nexttuple(internal)"); -DATA(insert OID = 3344 ( tsm_bernoulli_end PGNSP PGUID 12 1 0 0 0 f f f f t f v 1 0 2278 "2281" _null_ _null_ _null_ _null_ _null_ tsm_bernoulli_end _null_ _null_ _null_ )); -DESCR("tsm_bernoulli_end(internal)"); -DATA(insert OID = 3345 ( tsm_bernoulli_reset PGNSP PGUID 12 1 0 0 0 f f f f t f v 1 0 2278 "2281" _null_ _null_ _null_ _null_ _null_ tsm_bernoulli_reset _null_ _null_ _null_ )); -DESCR("tsm_bernoulli_reset(internal)"); -DATA(insert OID = 3346 ( tsm_bernoulli_cost PGNSP PGUID 12 1 0 0 0 f f f f t f v 7 0 2278 "2281 2281 2281 2281 2281 2281 2281" _null_ _null_ _null_ _null_ _null_ tsm_bernoulli_cost _null_ _null_ _null_ )); -DESCR("tsm_bernoulli_cost(internal)"); +#ifdef USE_MODULE_MSGIDS +DATA(insert OID = 6015 ( pg_msgmodule_set PGNSP PGUID 12 1 1 0 0 f f f f t t i 4 0 16 "20 20 20 2275" _null_ _null_ _null_ _null_ _null_ pg_msgmodule_set _null_ _null_ _null_ )); +DESCR("set debugging level for module/file/msg"); +#endif /* * Symbolic values for provolatile column: these indicate whether the result diff --git a/src/include/pg_config.h.in b/src/include/pg_config.h.in index 064002eaf0..a949d60274 100644 --- a/src/include/pg_config.h.in +++ b/src/include/pg_config.h.in @@ -799,6 +799,9 @@ /* Define to 1 to build with assertion checks. (--enable-cassert) */ #undef USE_ASSERT_CHECKING +/* Define to 1 to build with module msgids. (--enable-genmsgids) */ +#undef USE_MODULE_MSGIDS + /* Define to 1 to build with Bonjour support. (--with-bonjour) */ #undef USE_BONJOUR diff --git a/src/include/utils/builtins.h b/src/include/utils/builtins.h index 667ff5af9a..c13fb9c0ff 100644 --- a/src/include/utils/builtins.h +++ b/src/include/utils/builtins.h @@ -1315,5 +1315,7 @@ extern Datum stormdb_promote_standby(PG_FUNCTION_ARGS); extern Datum pgxc_is_committed(PG_FUNCTION_ARGS); extern Datum pgxc_is_inprogress(PG_FUNCTION_ARGS); #endif - +#ifdef USE_MODULE_MSGIDS +extern Datum pg_msgmodule_set(PG_FUNCTION_ARGS); +#endif #endif /* BUILTINS_H */ diff --git a/src/include/utils/elog.h b/src/include/utils/elog.h index 8e90661195..4d36427ed1 100644 --- a/src/include/utils/elog.h +++ b/src/include/utils/elog.h @@ -110,6 +110,26 @@ * prevents gcc from making the unreachability deduction at optlevel -O0. *---------- */ +#ifdef USE_MODULE_MSGIDS +#ifdef HAVE__BUILTIN_CONSTANT_P +#define ereport_domain(elevel, domain, rest) \ + do { \ + if (errstart(elevel, __FILE__, __LINE__, PGXL_MSG_MODULE, PGXL_MSG_FILEID, __COUNTER__, PG_FUNCNAME_MACRO, domain)) \ + errfinish rest; \ + if (__builtin_constant_p(elevel) && (elevel) >= ERROR) \ + pg_unreachable(); \ + } while(0) +#else /* !HAVE__BUILTIN_CONSTANT_P */ +#define ereport_domain(elevel, domain, rest) \ + do { \ + const int elevel_ = (elevel); \ + if (errstart(elevel, __FILE__, __LINE__, PGXL_MSG_MODULE, PGXL_MSG_FILEID, __COUNTER__, PG_FUNCNAME_MACRO, domain)) \ + errfinish rest; \ + if (elevel_ >= ERROR) \ + pg_unreachable(); \ + } while(0) +#endif /* HAVE__BUILTIN_CONSTANT_P */ +#else #ifdef HAVE__BUILTIN_CONSTANT_P #define ereport_domain(elevel, domain, rest) \ do { \ @@ -122,12 +142,13 @@ #define ereport_domain(elevel, domain, rest) \ do { \ const int elevel_ = (elevel); \ - if (errstart(elevel_, __FILE__, __LINE__, PG_FUNCNAME_MACRO, domain)) \ + if (errstart(elevel, __FILE__, __LINE__, PG_FUNCNAME_MACRO, domain)) \ errfinish rest; \ if (elevel_ >= ERROR) \ pg_unreachable(); \ } while(0) #endif /* HAVE__BUILTIN_CONSTANT_P */ +#endif #define ereport(elevel, rest) \ ereport_domain(elevel, TEXTDOMAIN, rest) @@ -135,7 +156,11 @@ #define TEXTDOMAIN NULL extern bool errstart(int elevel, const char *filename, int lineno, - const char *funcname, const char *domain); +#ifdef USE_MODULE_MSGIDS + int moduleid, int fileid, int msgid, +#endif + const char *funcname, const char *domain + ); extern void errfinish(int dummy,...); extern int errcode(int sqlerrcode); @@ -198,6 +223,7 @@ extern int getinternalerrposition(void); * elog(ERROR, "portal \"%s\" not found", stmt->portalname); *---------- */ +#ifdef USE_MODULE_MSGIDS #ifdef HAVE__VA_ARGS /* * If we have variadic macros, we can give the compiler a hint about the @@ -208,6 +234,32 @@ extern int getinternalerrposition(void); #ifdef HAVE__BUILTIN_CONSTANT_P #define elog(elevel, ...) \ do { \ + elog_start(__FILE__, __LINE__, PGXL_MSG_MODULE, PGXL_MSG_FILEID, __COUNTER__, PG_FUNCNAME_MACRO); \ + elog_finish(elevel, __VA_ARGS__); \ + if (__builtin_constant_p(elevel) && (elevel) >= ERROR) \ + pg_unreachable(); \ + } while(0) +#else /* !HAVE__BUILTIN_CONSTANT_P */ +#define elog(elevel, ...) \ + do { \ + int elevel_; \ + elog_start(__FILE__, __LINE__, PGXL_MSG_MODULE, PGXL_MSG_FILEID, __COUNTER__, PG_FUNCNAME_MACRO); \ + elevel_ = (elevel); \ + elog_finish(elevel_, __VA_ARGS__); \ + if (elevel_ >= ERROR) \ + pg_unreachable(); \ + } while(0) +#endif /* HAVE__BUILTIN_CONSTANT_P */ +#else /* !HAVE__VA_ARGS */ +#define elog \ + elog_start(__FILE__, __LINE__, PGXL_MSG_MODULE, PGXL_MSG_FILEID, __COUNTER__, PG_FUNCNAME_MACRO); \ + elog_finish +#endif /* HAVE__VA_ARGS */ +#else +#ifdef HAVE__VA_ARGS +#ifdef HAVE__BUILTIN_CONSTANT_P +#define elog(elevel, ...) \ + do { \ elog_start(__FILE__, __LINE__, PG_FUNCNAME_MACRO); \ elog_finish(elevel, __VA_ARGS__); \ if (__builtin_constant_p(elevel) && (elevel) >= ERROR) \ @@ -226,11 +278,17 @@ extern int getinternalerrposition(void); #endif /* HAVE__BUILTIN_CONSTANT_P */ #else /* !HAVE__VA_ARGS */ #define elog \ - elog_start(__FILE__, __LINE__, PG_FUNCNAME_MACRO), \ + elog_start(__FILE__, __LINE__, PG_FUNCNAME_MACRO); \ elog_finish #endif /* HAVE__VA_ARGS */ +#endif -extern void elog_start(const char *filename, int lineno, const char *funcname); +extern void elog_start(const char *filename, int lineno, +#ifdef USE_MODULE_MSGIDS + int moduleid, int flieid, int msgid, +#endif + const char *funcname + ); extern void elog_finish(int elevel, const char *fmt,...) pg_attribute_printf(2, 3); @@ -363,11 +421,26 @@ typedef struct ErrorData int internalpos; /* cursor index into internalquery */ char *internalquery; /* text of internally-generated query */ int saved_errno; /* errno at entry */ +#ifdef USE_MODULE_MSGIDS + int moduleid; + int fileid; + int msgid; /* msgid */ +#endif /* context containing associated non-constant strings */ struct MemoryContextData *assoc_context; } ErrorData; +#ifdef USE_MODULE_MSGIDS +#define PGXL_MSG_MAX_MODULES 256 +#define PGXL_MSG_MAX_FILEIDS_PER_MODULE 100 +#define PGXL_MSG_MAX_MSGIDS_PER_FILE 300 + +extern char *MsgModuleCtl; +extern Size MsgModuleShmemSize(void); +extern void MsgModuleShmemInit(void); +#endif + extern void EmitErrorReport(void); extern ErrorData *CopyErrorData(void); extern void FreeErrorData(ErrorData *edata); diff --git a/src/port/Makefile b/src/port/Makefile index bc9b63add0..6bf3dcf868 100644 --- a/src/port/Makefile +++ b/src/port/Makefile @@ -76,8 +76,15 @@ libpgport_srv.a: $(OBJS_SRV) # a hack that might fail someday if there is a *_srv.o without a # corresponding *.o, but it works for now (and those would probably go # into src/backend/port/ anyway). +ifeq ($(genmsgids), yes) +PGXL_MSG_FILEID := 1 +%_srv.o: %.c %.o + $(CC) $(CFLAGS) -DPGXL_MSG_MODULE=$(PGXL_MSG_MODULE) -DPGXL_MSG_FILEID=$(PGXL_MSG_FILEID) $(subst -DFRONTEND,, $(CPPFLAGS)) -c $< -o $@ + $(eval PGXL_MSG_FILEID := $(shell echo $(PGXL_MSG_FILEID) + 1 | bc)) +else %_srv.o: %.c %.o $(CC) $(CFLAGS) $(subst -DFRONTEND,, $(CPPFLAGS)) -c $< -o $@ +endif $(OBJS_SRV): | submake-errcodes |