summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPavan Deolasee2016-02-08 06:17:40 +0000
committerPavan Deolasee2016-10-18 09:57:39 +0000
commit334e6aa8350615ccfbdaedebd28537ce5ea7b242 (patch)
tree51dfd0a0e0ce288ac968e0fd029b7c6833e7aa8d
parent3366f09175bf4bd77b6a0decba38cb3b32e73dca (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.in1
-rwxr-xr-xconfig/create_msgids.sh55
-rwxr-xr-xconfigure31
-rw-r--r--configure.in9
-rw-r--r--contrib/pgxc_ctl/Makefile2
-rw-r--r--src/Makefile.global.in35
-rw-r--r--src/backend/storage/ipc/ipci.c8
-rw-r--r--src/backend/utils/error/elog.c272
-rw-r--r--src/bin/gtm_ctl/Makefile2
-rw-r--r--src/common/Makefile7
-rw-r--r--src/include/catalog/pg_proc.h30
-rw-r--r--src/include/pg_config.h.in3
-rw-r--r--src/include/utils/builtins.h4
-rw-r--r--src/include/utils/elog.h81
-rw-r--r--src/port/Makefile7
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
diff --git a/configure b/configure
index 0467e3d393..ce73d01e9f 100755
--- a/configure
+++ b/configure
@@ -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
+ $(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
+ $(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