summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKoichi Suzuki2012-03-29 02:03:25 +0000
committerKoichi Suzuki2012-03-29 02:03:25 +0000
commit0eaba1379aa2dde346a53eb15f8849c0e09861d0 (patch)
tree330512c82b5db46c031b84f2874115860902602f
parentdfda23e7547f457e15d79054f81d30e826faeecf (diff)
This commit adds GUC parameter xc_maintenance_mode. This is needed to control
behavior of some statements to be used to maintain XC database integrity by dedicate utility programs such as pgxc_clean, which is now under the development. Also, this patch modifies implicit 2PC xid to _$XC$%u where %u is the transactionId. Because it is essential to distinguish implicit 2PC from explicit one to maintain database consisitensy, this patch checks xid in PREPARE TRANSACTION and rejects xid for implicit 2PC. See documentation for details.
-rw-r--r--doc-xc/src/sgml/config.sgmlin15
-rw-r--r--doc-xc/src/sgml/ref/prepare_transaction.sgmlin6
-rw-r--r--src/backend/access/transam/xact.c14
-rw-r--r--src/backend/pgxc/Makefile2
-rw-r--r--src/backend/pgxc/xc_maintenance_mode/Makefile19
-rw-r--r--src/backend/pgxc/xc_maintenance_mode/xc_maintenance_mode.c5
-rw-r--r--src/backend/tcop/utility.c13
-rw-r--r--src/backend/utils/misc/guc.c74
-rw-r--r--src/include/access/xact.h1
-rw-r--r--src/include/pgxc/xc_maintenance_mode.h12
-rw-r--r--src/include/utils/guc_tables.h7
11 files changed, 166 insertions, 2 deletions
diff --git a/doc-xc/src/sgml/config.sgmlin b/doc-xc/src/sgml/config.sgmlin
index 23bf4a3385..bf6b738548 100644
--- a/doc-xc/src/sgml/config.sgmlin
+++ b/doc-xc/src/sgml/config.sgmlin
@@ -6932,6 +6932,21 @@ LOG: CleanUpLock: deleting: lock(0xb7acd844) id(24688,24696,0,0,0,1)
</listitem>
</varlistentry>
+ <varlistentry id="guc-xc-maintenance-ode" xreflabel="xc_maintenance_mode">
+ <term><varname>xc_maintenance_mode</varname> (<type>bool</type>)</term>
+ <indexterm>
+ <primary><varname>xc_maintenance_mode</> configuration parameter</primary>
+ </indexterm>
+ <listitem>
+ <para>
+ Specify to enter into maintenance mode. Turning this on will change behavior of several statements.
+ </para>
+ <para>
+ This parameter can only be set by superuser with <literal>SET</literal> command. Otherwise, the setting will be ignored.
+ </para>
+ </listitem>
+ </varlistentry>
+
</variablelist>
</sect1>
diff --git a/doc-xc/src/sgml/ref/prepare_transaction.sgmlin b/doc-xc/src/sgml/ref/prepare_transaction.sgmlin
index fca68de0ea..bf62e19741 100644
--- a/doc-xc/src/sgml/ref/prepare_transaction.sgmlin
+++ b/doc-xc/src/sgml/ref/prepare_transaction.sgmlin
@@ -130,6 +130,12 @@ PREPARE TRANSACTION <replaceable class="PARAMETER">transaction_id</replaceable>
coordinator, <command>COMMIT PREPARED</> will be propagated to
these nodes.
</para>
+
+&xconly;
+ <para>
+ Transaction id beginning with <literal>_$XC$</literal> is reserved by COORDINATOR for
+ internal use. You cannot use this form of transaction_id externaly.
+ </para>
<!## end>
&common;
diff --git a/src/backend/access/transam/xact.c b/src/backend/access/transam/xact.c
index 89615ee0ec..c831660b23 100644
--- a/src/backend/access/transam/xact.c
+++ b/src/backend/access/transam/xact.c
@@ -5459,4 +5459,18 @@ IsTransactionLocalNode(bool write)
else
return false;
}
+
+/*
+ * Check if the given xid is form implicit 2PC
+ */
+bool
+IsXidImplicit(const char *xid)
+{
+#define implicit2PC_head "_$XC$"
+ static size_t implicit2PC_head_len = strlen(implicit2PC_head);
+
+ if (strncmp(xid, implicit2PC_head, implicit2PC_head_len))
+ return false;
+ return true;
+}
#endif
diff --git a/src/backend/pgxc/Makefile b/src/backend/pgxc/Makefile
index 14f9b968d3..312b4d330c 100644
--- a/src/backend/pgxc/Makefile
+++ b/src/backend/pgxc/Makefile
@@ -11,6 +11,6 @@ subdir = src/backend/pgxc
top_builddir = ../../..
include $(top_builddir)/src/Makefile.global
-SUBDIRS = locator plan pool barrier nodemgr
+SUBDIRS = locator plan pool barrier nodemgr xc_maintenance_mode
include $(top_srcdir)/src/backend/common.mk
diff --git a/src/backend/pgxc/xc_maintenance_mode/Makefile b/src/backend/pgxc/xc_maintenance_mode/Makefile
new file mode 100644
index 0000000000..940cb52ec2
--- /dev/null
+++ b/src/backend/pgxc/xc_maintenance_mode/Makefile
@@ -0,0 +1,19 @@
+#-------------------------------------------------------------------------
+#
+# Makefile--
+# Makefile for barrier
+#
+# Portions Copyright (c) 2010-2011 Nippon Telegraph and Telephone Corporation
+#
+# IDENTIFICATION
+# $PostgreSQL$
+#
+#-------------------------------------------------------------------------
+
+subdir = src/backend/pgxc/xc_maintenance_mode
+top_builddir = ../../../..
+include $(top_builddir)/src/Makefile.global
+
+OBJS = xc_maintenance_mode.o
+
+include $(top_srcdir)/src/backend/common.mk
diff --git a/src/backend/pgxc/xc_maintenance_mode/xc_maintenance_mode.c b/src/backend/pgxc/xc_maintenance_mode/xc_maintenance_mode.c
new file mode 100644
index 0000000000..7296b6e8d7
--- /dev/null
+++ b/src/backend/pgxc/xc_maintenance_mode/xc_maintenance_mode.c
@@ -0,0 +1,5 @@
+#include "pgxc/xc_maintenance_mode.h"
+
+bool xc_maintenance_mode;
+GucContext currentGucContext;
+
diff --git a/src/backend/tcop/utility.c b/src/backend/tcop/utility.c
index 97b75ca249..b29e2b47c8 100644
--- a/src/backend/tcop/utility.c
+++ b/src/backend/tcop/utility.c
@@ -73,6 +73,7 @@
#include "pgxc/nodemgr.h"
#include "pgxc/groupmgr.h"
#include "utils/lsyscache.h"
+#include "pgxc/xc_maintenance_mode.h"
static void ExecUtilityStmtOnNodes(const char *queryString, ExecNodes *nodes,
bool force_autocommit, RemoteQueryExecType exec_type,
@@ -436,6 +437,18 @@ standard_ProcessUtility(Node *parsetree,
case TRANS_STMT_PREPARE:
PreventCommandDuringRecovery("PREPARE TRANSACTION");
+#ifdef PGXC
+ /* Add check if xid is valid */
+ if (IS_PGXC_COORDINATOR && !IsConnFromCoord() && !xc_maintenance_mode)
+ {
+ if (IsXidImplicit((const char *)stmt->gid))
+ {
+ elog(ERROR, "Invalid transaciton_id to prepare.");
+ break;
+ }
+ }
+#endif
+
if (!PrepareTransactionBlock(stmt->gid))
{
/* report unsuccessful commit in completionTag */
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 005fceeb99..d71aef982e 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -62,6 +62,7 @@
#include "nodes/nodes.h"
#include "pgxc/poolmgr.h"
#include "pgxc/nodemgr.h"
+#include "pgxc/xc_maintenance_mode.h"
#endif
#include "postmaster/autovacuum.h"
#include "postmaster/bgwriter.h"
@@ -197,6 +198,9 @@ static bool check_bonjour(bool *newval, void **extra, GucSource source);
static bool check_ssl(bool *newval, void **extra, GucSource source);
static bool check_stage_log_stats(bool *newval, void **extra, GucSource source);
static bool check_log_stats(bool *newval, void **extra, GucSource source);
+#ifdef PGXC
+static bool check_pgxc_maintenance_mode(bool *newval, void **extra, GucSource source);
+#endif
static bool check_canonical_path(char **newval, void **extra, GucSource source);
static bool check_timezone_abbreviations(char **newval, void **extra, GucSource source);
static void assign_timezone_abbreviations(const char *newval, void *extra);
@@ -636,6 +640,10 @@ const char *const config_group_names[] =
gettext_noop("Datanodes and Connection Pooling"),
/* GTM */
gettext_noop("GTM Connection"),
+ /* COORDINATORS */
+ gettext_noop("Coordinator Options"),
+ /* XC_HOUSEKEEPING_OPTIONS */
+ gettext_noop("XC Housekeeping Options"),
#endif
/* help_config wants this array to be null-terminated */
NULL
@@ -1489,6 +1497,15 @@ static struct config_bool ConfigureNamesBool[] =
true,
NULL, NULL, NULL
},
+ {
+ {"xc_maintenance_mode", PGC_SUSET, XC_HOUSEKEEPING_OPTIONS,
+ gettext_noop("Turn on XC maintenance mode."),
+ gettext_noop("Can set ON by SET command by superuser.")
+ },
+ &xc_maintenance_mode,
+ false,
+ check_pgxc_maintenance_mode, NULL, NULL
+ },
#endif
{
@@ -5257,6 +5274,14 @@ set_config_option(const char *name, const char *value,
bool prohibitValueChange = false;
bool makeDefault;
+#ifdef PGXC
+ /*
+ * Current GucContest value is needed to check if xc_maintenance_mode parameter
+ * is specified in valid contests. It is allowed only by SET command or
+ * libpq connect parameters so that setting this ON is just temporary.
+ */
+ currentGucContext = context;
+#endif
if (context == PGC_SIGHUP || source == PGC_S_DEFAULT)
{
/*
@@ -8587,6 +8612,55 @@ check_log_stats(bool *newval, void **extra, GucSource source)
return true;
}
+#ifdef PGXC
+/*
+ * K.Suzuki, March, 2012.
+ *
+ * Here, only a warning will be printed to log. Returning false will cause FATAL error and it
+ * will not be good.
+ */
+static bool
+check_pgxc_maintenance_mode(bool *newval, void **extra, GucSource source)
+{
+
+ switch(source)
+ {
+ case PGC_S_DYNAMIC_DEFAULT:
+ case PGC_S_ENV_VAR:
+ case PGC_S_ARGV:
+ GUC_check_errmsg("pgxc_maintenance_mode is not allowed here.");
+ return false;
+ case PGC_S_FILE:
+ switch (currentGucContext)
+ {
+ case PGC_SIGHUP:
+ elog(WARNING, "pgxc_maintenance_mode is not allowed in postgresql.conf. Set to default (false).");
+ *newval = false;
+ return true;
+ default:
+ GUC_check_errmsg("pgxc_maintenance_mode is not allowed in postgresql.conf.");
+ return false;
+ }
+ return false; /* Should not come here */
+ case PGC_S_DATABASE:
+ case PGC_S_USER:
+ case PGC_S_DATABASE_USER:
+ case PGC_S_INTERACTIVE:
+ case PGC_S_TEST:
+ elog(WARNING, "pgxc_maintenance_mode is not allowed here. Set to default (false).");
+ *newval = false;
+ return true;
+ case PGC_S_DEFAULT:
+ case PGC_S_CLIENT:
+ case PGC_S_SESSION:
+ return true;
+ default:
+ GUC_check_errmsg("Unknown source");
+ return false;
+ }
+}
+#endif
+
static bool
check_canonical_path(char **newval, void **extra, GucSource source)
{
diff --git a/src/include/access/xact.h b/src/include/access/xact.h
index 67dbce2d9b..58c09a43e7 100644
--- a/src/include/access/xact.h
+++ b/src/include/access/xact.h
@@ -273,6 +273,7 @@ extern void ForgetTransactionNodes(void);
extern void RegisterTransactionLocalNode(bool write);
extern bool IsTransactionLocalNode(bool write);
extern void ForgetTransactionLocalNode(void);
+extern bool IsXidImplicit(const char *xid);
#endif
extern int xactGetCommittedChildren(TransactionId **ptr);
diff --git a/src/include/pgxc/xc_maintenance_mode.h b/src/include/pgxc/xc_maintenance_mode.h
new file mode 100644
index 0000000000..a96148c385
--- /dev/null
+++ b/src/include/pgxc/xc_maintenance_mode.h
@@ -0,0 +1,12 @@
+#ifndef XC_MAINTENANCE_MODE_H
+#define XC_MAINTENANCE_MODE_H
+
+#include <unistd.h>
+#include "c.h"
+#include "postgres.h"
+#include "utils/guc.h"
+
+extern bool xc_maintenance_mode;
+extern GucContext currentGucContext;
+
+#endif /* XC_MAINTENANCE_MODE_H */
diff --git a/src/include/utils/guc_tables.h b/src/include/utils/guc_tables.h
index 645599b2ab..82fa92c5fd 100644
--- a/src/include/utils/guc_tables.h
+++ b/src/include/utils/guc_tables.h
@@ -93,10 +93,15 @@ enum config_group
ERROR_HANDLING_OPTIONS,
PRESET_OPTIONS,
CUSTOM_OPTIONS,
+#ifdef PGXC
DEVELOPER_OPTIONS,
DATA_NODES,
GTM,
- COORDINATORS
+ COORDINATORS,
+ XC_HOUSEKEEPING_OPTIONS
+#else
+ DEVELOPER_OPTIONS
+#endif
};
/*