summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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 $@.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