summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPavan Deolasee2016-10-18 06:30:41 +0000
committerPavan Deolasee2016-10-18 10:07:49 +0000
commitb28193036833f6124b6c828396710ebf264e07d6 (patch)
tree6faa8dbbee55708379713774d8ffd972c02c978b
parentfa1ade0b2cf440967e836f524326dc7249d50fa4 (diff)
Ensure we're not going beyond the configured limits of max_coordinators or
max_datanodes The user can still break things by first setting a high value for max_datanodes or max_coordinators and then lowering it again after adding nodes. So this basic check is not enough, but better than what we've currently.
-rw-r--r--src/backend/pgxc/nodemgr/nodemgr.c94
1 files changed, 90 insertions, 4 deletions
diff --git a/src/backend/pgxc/nodemgr/nodemgr.c b/src/backend/pgxc/nodemgr/nodemgr.c
index 5e3290d419..5ae6fe5f05 100644
--- a/src/backend/pgxc/nodemgr/nodemgr.c
+++ b/src/backend/pgxc/nodemgr/nodemgr.c
@@ -37,6 +37,7 @@
#define MAX_TRIES_FOR_NID 200
static Datum generate_node_id(const char *node_name);
+static void count_coords_datanodes(Relation rel, int *num_coord, int *num_dns);
/*
* GUC parameters.
@@ -222,7 +223,7 @@ check_node_options(const char *node_name, List *options, char **node_host,
if (*node_type == PGXC_NODE_DATANODE && NumDataNodes >= MaxDataNodes)
ereport(ERROR,
(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
- errmsg("Too many datanodes, current value of max_data_nodes is %d",
+ errmsg("Too many datanodes, current value of max_datanodes is %d",
MaxDataNodes)));
#endif
@@ -314,6 +315,39 @@ cmp_nodes(const void *p1, const void *p2)
return 1;
}
+/*
+ * Count the number of coordinators and datanodes configured so far.
+ */
+static void
+count_coords_datanodes(Relation rel, int *num_coord, int *num_dns)
+{
+ int coordCount = 0, dnCount = 0;
+ HeapScanDesc scan;
+ HeapTuple tuple;
+
+ scan = heap_beginscan(rel, SnapshotSelf, 0, NULL);
+ while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
+ {
+ Form_pgxc_node nodeForm = (Form_pgxc_node) GETSTRUCT(tuple);
+
+ /* Take definition for given node type */
+ switch (nodeForm->node_type)
+ {
+ case PGXC_NODE_COORDINATOR:
+ coordCount++;
+ break;
+ case PGXC_NODE_DATANODE:
+ dnCount++;
+ break;
+ default:
+ break;
+ }
+ }
+ heap_endscan(scan);
+
+ *num_coord = coordCount;
+ *num_dns = dnCount;
+}
/*
* PgxcNodeListAndCount
@@ -692,6 +726,7 @@ PgxcNodeCreate(CreateNodeStmt *stmt)
bool is_primary = false;
bool is_preferred = false;
Datum node_id;
+ int coordCount = 0, dnCount = 0;
/* Only a DB administrator can add nodes */
if (!superuser())
@@ -763,7 +798,34 @@ PgxcNodeCreate(CreateNodeStmt *stmt)
* There could be a relation race here if a similar Oid
* being created before the heap is inserted.
*/
- pgxcnodesrel = heap_open(PgxcNodeRelationId, RowExclusiveLock);
+ pgxcnodesrel = heap_open(PgxcNodeRelationId, AccessExclusiveLock);
+
+ /*
+ * Get the count of datanodes and coordinators added so far and make sure
+ * we're not exceeding the configured limits
+ *
+ * XXX This is not full proof because someone may first set
+ * max_coordinators or max_datanodes to a high value, add nodes and then
+ * lower the value again.
+ */
+ count_coords_datanodes(pgxcnodesrel, &coordCount, &dnCount);
+
+ if ((node_type == PGXC_NODE_DATANODE && dnCount >= MaxDataNodes) ||
+ (node_type == PGXC_NODE_COORDINATOR && coordCount >= MaxCoords))
+ {
+ ereport(ERROR,
+ (errcode(ERRCODE_INSUFFICIENT_RESOURCES),
+ errmsg("cannot add more than %d %s",
+ node_type == PGXC_NODE_COORDINATOR ?
+ MaxCoords : MaxDataNodes,
+ node_type == PGXC_NODE_COORDINATOR ?
+ "coordinators" : "datanodes"),
+ errhint("increase the value of %s GUC and restart the cluster",
+ node_type == PGXC_NODE_COORDINATOR ?
+ "max_coordinators" : "max_datanodes"
+ )));
+
+ }
/* Build entry tuple */
values[Anum_pgxc_node_name - 1] = DirectFunctionCall1(namein, CStringGetDatum(node_name));
@@ -781,7 +843,7 @@ PgxcNodeCreate(CreateNodeStmt *stmt)
CatalogUpdateIndexes(pgxcnodesrel, htup);
- heap_close(pgxcnodesrel, RowExclusiveLock);
+ heap_close(pgxcnodesrel, AccessExclusiveLock);
}
/*
@@ -805,6 +867,7 @@ PgxcNodeAlter(AlterNodeStmt *stmt)
bool new_record_nulls[Natts_pgxc_node];
bool new_record_repl[Natts_pgxc_node];
uint32 node_id;
+ int coordCount = 0, dnCount = 0;
/* Only a DB administrator can alter cluster nodes */
if (!superuser())
@@ -813,7 +876,7 @@ PgxcNodeAlter(AlterNodeStmt *stmt)
errmsg("must be superuser to change cluster nodes")));
/* Look at the node tuple, and take exclusive lock on it */
- rel = heap_open(PgxcNodeRelationId, RowExclusiveLock);
+ rel = heap_open(PgxcNodeRelationId, AccessExclusiveLock);
/* Check that node exists */
if (!OidIsValid(nodeOid))
@@ -856,6 +919,29 @@ PgxcNodeAlter(AlterNodeStmt *stmt)
errmsg("PGXC node %s: two nodes cannot be primary",
node_name)));
+ /*
+ * Get the count of datanodes and coordinators added so far and make sure
+ * we're not exceeding the configured limits
+ */
+ count_coords_datanodes(rel, &coordCount, &dnCount);
+
+ if ((node_type == PGXC_NODE_DATANODE && dnCount >= MaxDataNodes) ||
+ (node_type == PGXC_NODE_COORDINATOR && coordCount >= MaxCoords))
+ {
+ ereport(ERROR,
+ (errcode(ERRCODE_INSUFFICIENT_RESOURCES),
+ errmsg("cannot add more than %d %s",
+ node_type == PGXC_NODE_COORDINATOR ?
+ MaxCoords : MaxDataNodes,
+ node_type == PGXC_NODE_COORDINATOR ?
+ "coordinators" : "datanodes"),
+ errhint("increase the value of %s GUC and restart the cluster",
+ node_type == PGXC_NODE_COORDINATOR ?
+ "max_coordinators" : "max_datanodes"
+ )));
+
+ }
+
/* Update values for catalog entry */
MemSet(new_record, 0, sizeof(new_record));
MemSet(new_record_nulls, false, sizeof(new_record_nulls));