summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael P2011-11-24 23:30:55 +0000
committerMichael P2011-11-24 23:30:55 +0000
commit21cde3261299db2b1d468b767e4e86f3ecedf45f (patch)
tree40bac00310e7322312c60b086f9ec2aec1705a7a
parent3c1ebb15603a6d52dd84cae8afd019a5ee37d2fd (diff)
Addition of system function pgxc_pool_check
This new system function is used to check connection information consistency cached in pooler with pgxc_node. The information checked for consistency is node Oid, connection port and connection host. This function returns a boolean depending on connection data being consistent or not.
-rw-r--r--doc-xc/src/sgml/func.sgmlin39
-rw-r--r--src/backend/pgxc/nodemgr/nodemgr.c36
-rw-r--r--src/backend/pgxc/pool/pgxcnode.c3
-rw-r--r--src/backend/pgxc/pool/poolmgr.c123
-rw-r--r--src/backend/pgxc/pool/poolutils.c20
-rw-r--r--src/backend/utils/init/postinit.c4
-rw-r--r--src/include/catalog/pg_proc.h4
-rw-r--r--src/include/pgxc/nodemgr.h4
-rw-r--r--src/include/pgxc/poolmgr.h3
-rw-r--r--src/include/pgxc/poolutils.h4
-rw-r--r--src/include/utils/builtins.h5
11 files changed, 221 insertions, 24 deletions
diff --git a/doc-xc/src/sgml/func.sgmlin b/doc-xc/src/sgml/func.sgmlin
index c8cf40fa2f..07dab181eb 100644
--- a/doc-xc/src/sgml/func.sgmlin
+++ b/doc-xc/src/sgml/func.sgmlin
@@ -15325,9 +15325,48 @@ SELECT (pg_stat_file('filename')).modification;
locks held by the current session. (This function is implicitly invoked
at session end, even if the client disconnects ungracefully.)
</para>
+
<!## XC>
&xconly;
<para>
+ The functions shown in <xref linkend="functions-pgxc-pooler"> manage
+ Postgres-XC pooler. For details about Postgres-XC pooler, see
+ <xref linkend="xc-overview-pooler">.
+ </para>
+ <table id="functions-pgxc-pooler">
+ <title>Postgres-XC pooler functions</title>
+ <tgroup cols="3">
+ <thead>
+ <row><entry>Name</entry> <entry>Return Type</entry> <entry>Description</entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <literal><function>pgxc_pool_check()</function></literal>
+ </entry>
+ <entry><type>boolean</type></entry>
+ <entry>Check if connection data cached in pooler is consistent with
+ <link linkend="catalog-pgxc-node"><structname>pgxc_node</structname></link>.
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+
+ <indexterm>
+ <primary>pgxc_pool_check</primary>
+ </indexterm>
+ <para>
+ <function>pgxc_pool_check</> verifies if connection data cached in Postgres-XC pooler
+ is consistent with <link linkend="catalog-pgxc-node"><structname>pgxc_node</structname></link>
+ catalog. Data checked for consistency is Node Oid (<literal><link linkend="catalog-pgxc-node"><structname>pgxc_node</structname></link>.oid</literal>),
+ node port (<literal><link linkend="catalog-pgxc-node"><structname>pgxc_node</structname></link>.node_port</literal>)
+ and node host (<literal><link linkend="catalog-pgxc-node"><structname>pgxc_node</structname></link>.node_host</literal>).
+ </para>
+
+&xconly;
+ <para>
Please note that these functions works just locally.
The lock obtained in a coordinator is effective only in the coordinator.
Transaction started at different coordinator can obtain the lock with the same
diff --git a/src/backend/pgxc/nodemgr/nodemgr.c b/src/backend/pgxc/nodemgr/nodemgr.c
index 12e40a63fb..74f83ac959 100644
--- a/src/backend/pgxc/nodemgr/nodemgr.c
+++ b/src/backend/pgxc/nodemgr/nodemgr.c
@@ -132,17 +132,17 @@ cmp_nodes(const void *p1, const void *p2)
* an ordered list of node Oids for each PGXC node type.
*/
void
-PgxcNodeListAndCount(Oid **coOids, Oid **dnOids, Oid **coslaveOids, Oid **dnslaveOids)
+PgxcNodeListAndCount(Oid **coOids, Oid **dnOids, Oid **coslaveOids, Oid **dnslaveOids,
+ int *num_coords, int *num_dns, int *num_co_slaves, int *num_dn_slaves)
{
Relation rel;
HeapScanDesc scan;
HeapTuple tuple;
- /* Reinitialize counts */
- NumCoords = 0;
- NumDataNodes = 0;
- NumCoordSlaves = 0;
- NumDataNodeSlaves = 0;
+ *num_coords = 0;
+ *num_dns = 0;
+ *num_co_slaves = 0;
+ *num_dn_slaves = 0;
/*
* Node information initialization is made in one scan:
@@ -163,23 +163,23 @@ PgxcNodeListAndCount(Oid **coOids, Oid **dnOids, Oid **coslaveOids, Oid **dnslav
switch (nodeForm->node_type)
{
case PGXC_NODE_COORD_MASTER:
- NumCoords++;
- numnodes = NumCoords;
+ (*num_coords)++;
+ numnodes = *num_coords;
nodes = coOids;
break;
case PGXC_NODE_DATANODE_MASTER:
- NumDataNodes++;
- numnodes = NumDataNodes;
+ (*num_dns)++;
+ numnodes = *num_dns;
nodes = dnOids;
break;
case PGXC_NODE_COORD_SLAVE:
- NumCoordSlaves++;
- numnodes = NumCoordSlaves;
+ (*num_co_slaves)++;
+ numnodes = *num_co_slaves;
nodes = coslaveOids;
break;
case PGXC_NODE_DATANODE_SLAVE:
- NumDataNodeSlaves++;
- numnodes = NumDataNodeSlaves;
+ (*num_dn_slaves)++;
+ numnodes = *num_dn_slaves;
nodes = dnslaveOids;
break;
default:
@@ -211,13 +211,13 @@ PgxcNodeListAndCount(Oid **coOids, Oid **dnOids, Oid **coslaveOids, Oid **dnslav
/* Finally sort the lists to be sent back */
if (NumCoords != 0)
- qsort(*coOids, NumCoords, sizeof(Oid), cmp_nodes);
+ qsort(*coOids, *num_coords, sizeof(Oid), cmp_nodes);
if (NumDataNodes != 0)
- qsort(*dnOids, NumDataNodes, sizeof(Oid), cmp_nodes);
+ qsort(*dnOids, *num_dns, sizeof(Oid), cmp_nodes);
if (NumDataNodeSlaves != 0)
- qsort(*coslaveOids, NumCoordSlaves, sizeof(Oid), cmp_nodes);
+ qsort(*coslaveOids, *num_co_slaves, sizeof(Oid), cmp_nodes);
if (NumDataNodeSlaves != 0)
- qsort(*dnslaveOids, NumDataNodeSlaves, sizeof(Oid), cmp_nodes);
+ qsort(*dnslaveOids, *num_dn_slaves, sizeof(Oid), cmp_nodes);
}
/*
diff --git a/src/backend/pgxc/pool/pgxcnode.c b/src/backend/pgxc/pool/pgxcnode.c
index b90c0ba98a..2e82b686d1 100644
--- a/src/backend/pgxc/pool/pgxcnode.c
+++ b/src/backend/pgxc/pool/pgxcnode.c
@@ -127,7 +127,8 @@ InitMultinodeExecutor(void)
return;
/* Get classified list of node Oids */
- PgxcNodeListAndCount(&coOids, &dnOids, &coslaveOids, &dnslaveOids);
+ PgxcNodeListAndCount(&coOids, &dnOids, &coslaveOids, &dnslaveOids,
+ &NumCoords, &NumDataNodes, &NumCoordSlaves, &NumDataNodeSlaves);
/* Do proper initialization of handles */
if (NumDataNodes > 0)
diff --git a/src/backend/pgxc/pool/poolmgr.c b/src/backend/pgxc/pool/poolmgr.c
index bd29ece2fc..43fa441025 100644
--- a/src/backend/pgxc/pool/poolmgr.c
+++ b/src/backend/pgxc/pool/poolmgr.c
@@ -99,6 +99,7 @@ static int is_pool_cleaning = false;
static int server_fd = -1;
static void node_info_load(void);
+static int node_info_check(void);
static void agent_init(PoolAgent *agent, const char *database, const char *user_name);
static void agent_destroy(PoolAgent *agent);
static void agent_create(void);
@@ -245,7 +246,8 @@ node_info_load(void)
Oid *dnslaveOids = NULL;
/* Update number of PGXC nodes saved in cache */
- PgxcNodeListAndCount(&coOids, &dnOids, &coslaveOids, &dnslaveOids);
+ PgxcNodeListAndCount(&coOids, &dnOids, &coslaveOids, &dnslaveOids,
+ &NumCoords, &NumDataNodes, &NumCoordSlaves, &NumDataNodeSlaves);
/* Then initialize the node informations */
if (NumDataNodes != 0)
@@ -299,6 +301,94 @@ node_info_load(void)
}
/*
+ * Check connection info consistency with system catalogs
+ */
+static int
+node_info_check(void)
+{
+ int res = POOL_CHECK_SUCCESS;
+ int num_coord, num_dn,
+ num_coord_slave, num_dn_slave, i, j;
+ Oid *coOids = NULL;
+ Oid *dnOids = NULL;
+ Oid *coslaveOids = NULL;
+ Oid *dnslaveOids = NULL;
+
+ /* Update number of PGXC nodes saved in cache */
+ PgxcNodeListAndCount(&coOids, &dnOids, &coslaveOids, &dnslaveOids,
+ &num_coord, &num_dn, &num_coord_slave, &num_dn_slave);
+
+ /* Check first if node numbers are consistent */
+ if (NumCoords != num_coord ||
+ NumDataNodes != num_dn ||
+ NumCoordSlaves != num_coord_slave ||
+ NumDataNodeSlaves != num_dn_slave)
+ {
+ res = POOL_CHECK_FAILED;
+ goto finish;
+ }
+
+ /* Now do a check element by element */
+ for (i = 0; i < 4; i++)
+ {
+ int numnodes;
+ PGXCNodeConnectionInfo *conninfo;
+ Oid *oid_vector;
+
+ /* Take all the elements necessary for check */
+ switch(i)
+ {
+ case 0:
+ numnodes = NumCoords;
+ oid_vector = coOids;
+ conninfo = coord_connInfos;
+ break;
+ case 1:
+ numnodes = NumDataNodes;
+ oid_vector = dnOids;
+ conninfo = datanode_connInfos;
+ break;
+ case 2:
+ numnodes = NumCoordSlaves;
+ oid_vector = coslaveOids;
+ conninfo = coord_slave_connInfos;
+ break;
+ case 3:
+ numnodes = NumDataNodeSlaves;
+ oid_vector = dnslaveOids;
+ conninfo = datanode_slave_connInfos;
+ break;
+ default:
+ Assert(0);
+ }
+
+ /* Then check data consistency for port, host and node Oid */
+ for (j = 0; j < numnodes; j++)
+ {
+ if (conninfo[j].nodeoid != oid_vector[j] ||
+ conninfo[j].port != get_pgxc_nodeport(oid_vector[j]) ||
+ strcmp(conninfo[j].host, get_pgxc_nodehost(oid_vector[j])))
+ {
+ res = POOL_CHECK_FAILED;
+ goto finish;
+ }
+ }
+ }
+
+finish:
+ /* Clean everything */
+ if (coOids)
+ pfree(coOids);
+ if (dnOids)
+ pfree(dnOids);
+ if (coslaveOids)
+ pfree(coslaveOids);
+ if (dnslaveOids)
+ pfree(dnslaveOids);
+ return res;
+}
+
+/*
* Destroy internal structures
*/
int
@@ -802,6 +892,27 @@ PoolManagerCleanConnection(List *datanodelist, List *coordlist, char *dbname, ch
/*
+ * Check connection information consistency cached in pooler with catalog information
+ */
+bool
+PoolManagerCheckConnectionInfo(void)
+{
+ int res;
+
+ Assert(poolHandle);
+ pool_putmessage(&poolHandle->port, 'q', NULL, 0);
+ pool_flush(&poolHandle->port);
+
+ res = pool_recvres(&poolHandle->port);
+
+ if (res == POOL_CHECK_SUCCESS)
+ return true;
+
+ return false;
+}
+
+
+/*
* Handle messages to agent
*/
static void
@@ -960,9 +1071,17 @@ agent_handle_input(PoolAgent * agent, StringInfo s)
cancel_query_on_connections(agent, datanodelist, coordlist);
list_free(datanodelist);
list_free(coordlist);
-
break;
+ case 'q': /* Check connection info consistency */
+ pool_getmessage(&agent->port, s, 4);
+ pq_getmsgend(s);
+ /* Check cached info consistency */
+ res = node_info_check();
+
+ /* Send result */
+ pool_sendres(&agent->port, res);
+ break;
case 'r': /* RELEASE CONNECTIONS */
pool_getmessage(&agent->port, s, 4);
pq_getmsgend(s);
diff --git a/src/backend/pgxc/pool/poolutils.c b/src/backend/pgxc/pool/poolutils.c
index 9ac7131803..92954993db 100644
--- a/src/backend/pgxc/pool/poolutils.c
+++ b/src/backend/pgxc/pool/poolutils.c
@@ -26,9 +26,27 @@
#include "pgxc/pgxcnode.h"
#include "access/gtm.h"
#include "commands/dbcommands.h"
-#include "utils/lsyscache.h"
#include "utils/acl.h"
+#include "utils/builtins.h"
+#include "utils/lsyscache.h"
+/*
+ * pgxc_pool_check
+ *
+ * Check if Pooler information in catalog is consistent
+ * with information cached.
+ */
+Datum
+pgxc_pool_check(PG_FUNCTION_ARGS)
+{
+ if (!superuser())
+ ereport(ERROR,
+ (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
+ (errmsg("must be superuser to manage pooler"))));
+
+ /* Simply check with pooler */
+ PG_RETURN_BOOL(PoolManagerCheckConnectionInfo());
+}
/*
* CleanConnection()
diff --git a/src/backend/utils/init/postinit.c b/src/backend/utils/init/postinit.c
index fe61ee6645..7f8245ce30 100644
--- a/src/backend/utils/init/postinit.c
+++ b/src/backend/utils/init/postinit.c
@@ -56,7 +56,9 @@
#include "utils/snapmgr.h"
#include "utils/syscache.h"
#include "utils/tqual.h"
-
+#ifdef PGXC
+#include "pgxc/poolmgr.h"
+#endif
static HeapTuple GetDatabaseTuple(const char *dbname);
static HeapTuple GetDatabaseTupleByOid(Oid dboid);
diff --git a/src/include/catalog/pg_proc.h b/src/include/catalog/pg_proc.h
index d6ce6d92d7..cfe923eda9 100644
--- a/src/include/catalog/pg_proc.h
+++ b/src/include/catalog/pg_proc.h
@@ -4341,6 +4341,10 @@ DESCR("fetch the last row value");
DATA(insert OID = 3114 ( nth_value PGNSP PGUID 12 1 0 0 f t f t f i 2 0 2283 "2283 23" _null_ _null_ _null_ _null_ window_nth_value _null_ _null_ _null_ ));
DESCR("fetch the Nth row value");
+#ifdef PGXC
+DATA(insert OID = 3200 ( pgxc_pool_check PGNSP PGUID 12 1 0 0 f f f t f v 0 0 16 "" _null_ _null_ _null_ _null_ pgxc_pool_check _null_ _null_ _null_ ));
+DESCR("check connection information consistency in pooler");
+#endif
/*
* Symbolic values for provolatile column: these indicate whether the result
diff --git a/src/include/pgxc/nodemgr.h b/src/include/pgxc/nodemgr.h
index ff00b56d1d..18e3054456 100644
--- a/src/include/pgxc/nodemgr.h
+++ b/src/include/pgxc/nodemgr.h
@@ -26,7 +26,9 @@ extern int NumCoordSlaves;
extern int NumDataNodeSlaves;
extern void PgxcNodeListAndCount(Oid **coOids, Oid **dnOids,
- Oid **coslaveOids, Oid **dnslaveOids);
+ Oid **coslaveOids, Oid **dnslaveOids,
+ int *num_coords, int *num_dns,
+ int *num_co_slaves, int *num_dn_slaves);
extern void PgxcNodeAlter(AlterNodeStmt *stmt);
extern void PgxcNodeCreate(CreateNodeStmt *stmt);
extern void PgxcNodeRemove(DropNodeStmt *stmt);
diff --git a/src/include/pgxc/poolmgr.h b/src/include/pgxc/poolmgr.h
index cda434d97e..a120c38695 100644
--- a/src/include/pgxc/poolmgr.h
+++ b/src/include/pgxc/poolmgr.h
@@ -157,6 +157,9 @@ extern int *PoolManagerGetConnections(List *datanodelist, List *coordlist);
/* Clean pool connections */
extern void PoolManagerCleanConnection(List *datanodelist, List *coordlist, char *dbname, char *username);
+/* Check consistency of connection information cached in pooler with catalogs */
+extern bool PoolManagerCheckConnectionInfo(void);
+
/* Send Abort signal to transactions being run */
extern int PoolManagerAbortTransactions(char *dbname, char *username, int **proc_pids);
diff --git a/src/include/pgxc/poolutils.h b/src/include/pgxc/poolutils.h
index fff8b9ed1f..a8c216d4e3 100644
--- a/src/include/pgxc/poolutils.h
+++ b/src/include/pgxc/poolutils.h
@@ -26,6 +26,10 @@
#define CLEAN_CONNECTION_TX_REMAIN 2
#define CLEAN_CONNECTION_EOF -1
+/* Results for pooler connection info check */
+#define POOL_CHECK_SUCCESS 0
+#define POOL_CHECK_FAILED 1
+
void CleanConnection(CleanConnStmt *stmt);
void DropDBCleanConnection(char *dbname);
#endif
diff --git a/src/include/utils/builtins.h b/src/include/utils/builtins.h
index b11db63ace..47fb36b9f2 100644
--- a/src/include/utils/builtins.h
+++ b/src/include/utils/builtins.h
@@ -1120,4 +1120,9 @@ extern Datum pg_prepared_statement(PG_FUNCTION_ARGS);
/* utils/mmgr/portalmem.c */
extern Datum pg_cursor(PG_FUNCTION_ARGS);
+#ifdef PGXC
+/* backend/pgxc/pool/poolutils.c */
+extern Datum pgxc_pool_check(PG_FUNCTION_ARGS);
+#endif
+
#endif /* BUILTINS_H */