diff options
author | Michael P | 2011-11-24 23:30:55 +0000 |
---|---|---|
committer | Michael P | 2011-11-24 23:30:55 +0000 |
commit | 21cde3261299db2b1d468b767e4e86f3ecedf45f (patch) | |
tree | 40bac00310e7322312c60b086f9ec2aec1705a7a | |
parent | 3c1ebb15603a6d52dd84cae8afd019a5ee37d2fd (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.sgmlin | 39 | ||||
-rw-r--r-- | src/backend/pgxc/nodemgr/nodemgr.c | 36 | ||||
-rw-r--r-- | src/backend/pgxc/pool/pgxcnode.c | 3 | ||||
-rw-r--r-- | src/backend/pgxc/pool/poolmgr.c | 123 | ||||
-rw-r--r-- | src/backend/pgxc/pool/poolutils.c | 20 | ||||
-rw-r--r-- | src/backend/utils/init/postinit.c | 4 | ||||
-rw-r--r-- | src/include/catalog/pg_proc.h | 4 | ||||
-rw-r--r-- | src/include/pgxc/nodemgr.h | 4 | ||||
-rw-r--r-- | src/include/pgxc/poolmgr.h | 3 | ||||
-rw-r--r-- | src/include/pgxc/poolutils.h | 4 | ||||
-rw-r--r-- | src/include/utils/builtins.h | 5 |
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 */ |