diff options
| -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 $@.E $< -MMD -MP -MF $(DEPDIR)/$(*F).Po + -cat $@.E | grep -E "do \{ if \(errstart|do \{ if \(elog_start" >> $(top_srcdir)/MSGIDS + -rm -f $@.E + $(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 $@.E $< + -cat $@.E | grep -E "do \{ if \(errstart|do \{ if \(elog_start" >> $(top_srcdir)/MSGIDS + -rm -f $@.E + $(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 |
