From 205f6563faf672b788f4f281855574c57921e8a2 Mon Sep 17 00:00:00 2001 From: Murat Tuncer Date: Wed, 4 Jan 2017 12:28:53 +0300 Subject: [PATCH] Add force option to master_remove_node We can now remove nodes from cluster regardless of them having an active shard placement. --- src/backend/distributed/Makefile | 4 +- .../distributed/citus--6.1-12--6.1-13.sql | 15 ++++++ src/backend/distributed/citus.control | 2 +- src/backend/distributed/utils/node_metadata.c | 12 ++++- .../expected/multi_cluster_management.out | 53 ++++++++++++++----- src/test/regress/expected/multi_extension.out | 1 + .../regress/sql/multi_cluster_management.sql | 11 ++++ src/test/regress/sql/multi_extension.sql | 1 + 8 files changed, 82 insertions(+), 17 deletions(-) create mode 100644 src/backend/distributed/citus--6.1-12--6.1-13.sql diff --git a/src/backend/distributed/Makefile b/src/backend/distributed/Makefile index 7df3ad9cc..1648ec5fb 100644 --- a/src/backend/distributed/Makefile +++ b/src/backend/distributed/Makefile @@ -9,7 +9,7 @@ EXTVERSIONS = 5.0 5.0-1 5.0-2 \ 5.1-1 5.1-2 5.1-3 5.1-4 5.1-5 5.1-6 5.1-7 5.1-8 \ 5.2-1 5.2-2 5.2-3 5.2-4 \ 6.0-1 6.0-2 6.0-3 6.0-4 6.0-5 6.0-6 6.0-7 6.0-8 6.0-9 6.0-10 6.0-11 6.0-12 6.0-13 6.0-14 6.0-15 6.0-16 6.0-17 6.0-18 \ - 6.1-1 6.1-2 6.1-3 6.1-4 6.1-5 6.1-6 6.1-7 6.1-8 6.1-9 6.1-10 6.1-11 6.1-12 + 6.1-1 6.1-2 6.1-3 6.1-4 6.1-5 6.1-6 6.1-7 6.1-8 6.1-9 6.1-10 6.1-11 6.1-12 6.1-13 # All citus--*.sql files in the source directory DATA = $(patsubst $(citus_abs_srcdir)/%.sql,%.sql,$(wildcard $(citus_abs_srcdir)/$(EXTENSION)--*--*.sql)) @@ -119,6 +119,8 @@ $(EXTENSION)--6.1-11.sql: $(EXTENSION)--6.1-10.sql $(EXTENSION)--6.1-10--6.1-11. cat $^ > $@ $(EXTENSION)--6.1-12.sql: $(EXTENSION)--6.1-11.sql $(EXTENSION)--6.1-11--6.1-12.sql cat $^ > $@ +$(EXTENSION)--6.1-13.sql: $(EXTENSION)--6.1-12.sql $(EXTENSION)--6.1-12--6.1-13.sql + cat $^ > $@ NO_PGXS = 1 diff --git a/src/backend/distributed/citus--6.1-12--6.1-13.sql b/src/backend/distributed/citus--6.1-12--6.1-13.sql new file mode 100644 index 000000000..969d4f5c8 --- /dev/null +++ b/src/backend/distributed/citus--6.1-12--6.1-13.sql @@ -0,0 +1,15 @@ +/* citus--6.1-12--6.1-13.sql */ + +SET search_path = 'pg_catalog'; + +DROP FUNCTION IF EXISTS master_remove_node(nodename text, nodeport integer); + +CREATE FUNCTION master_remove_node(nodename text, nodeport integer, + force bool DEFAULT false) + RETURNS void + LANGUAGE C STRICT + AS 'MODULE_PATHNAME', $$master_remove_node$$; +COMMENT ON FUNCTION master_remove_node(nodename text, nodeport integer, force bool) + IS 'remove node from the cluster'; + +RESET search_path; diff --git a/src/backend/distributed/citus.control b/src/backend/distributed/citus.control index d40b2142d..a3c856e4f 100644 --- a/src/backend/distributed/citus.control +++ b/src/backend/distributed/citus.control @@ -1,6 +1,6 @@ # Citus extension comment = 'Citus distributed database' -default_version = '6.1-12' +default_version = '6.1-13' module_pathname = '$libdir/citus' relocatable = false schema = pg_catalog diff --git a/src/backend/distributed/utils/node_metadata.c b/src/backend/distributed/utils/node_metadata.c index ac8254955..2b07fd432 100644 --- a/src/backend/distributed/utils/node_metadata.c +++ b/src/backend/distributed/utils/node_metadata.c @@ -111,6 +111,7 @@ master_remove_node(PG_FUNCTION_ARGS) { text *nodeName = PG_GETARG_TEXT_P(0); int32 nodePort = PG_GETARG_INT32(1); + bool force = PG_GETARG_BOOL(2); char *nodeNameString = text_to_cstring(nodeName); char *nodeDeleteCommand = NULL; bool hasShardPlacements = false; @@ -120,7 +121,16 @@ master_remove_node(PG_FUNCTION_ARGS) EnsureSuperUser(); hasShardPlacements = NodeHasActiveShardPlacements(nodeNameString, nodePort); - if (hasShardPlacements) + if (hasShardPlacements && force) + { + ereport(NOTICE, (errmsg("Node %s:%d has active shard placements. Some " + "queries may fail after this operation. Use " + "select master_add_node('%s', %d) to add this " + "node back.", + nodeNameString, nodePort, nodeNameString, + nodePort))); + } + else if (hasShardPlacements) { ereport(ERROR, (errmsg("you cannot remove a node which has active " "shard placements"))); diff --git a/src/test/regress/expected/multi_cluster_management.out b/src/test/regress/expected/multi_cluster_management.out index b91119739..d9fbc28ed 100644 --- a/src/test/regress/expected/multi_cluster_management.out +++ b/src/test/regress/expected/multi_cluster_management.out @@ -101,6 +101,31 @@ SELECT master_get_active_worker_nodes(); (localhost,57637) (2 rows) +-- try to remove a node with active placements with force = true and see that node is removed +SELECT master_remove_node('localhost', :worker_2_port, true); +NOTICE: Node localhost:57638 has active shard placements. Some queries may fail after this operation. Use select master_add_node('localhost', 57638) to add this node back. + master_remove_node +-------------------- + +(1 row) + +SELECT master_get_active_worker_nodes(); + master_get_active_worker_nodes +-------------------------------- + (localhost,57637) +(1 row) + +-- restore the node for next tests +SELECT master_add_node('localhost', :worker_2_port); + master_add_node +--------------------------------- + (4,4,localhost,57638,default,f) +(1 row) + +-- try to remove a node with active placements with force = false and see that node +-- removal is failed +SELECT master_remove_node('localhost', :worker_2_port, false); +ERROR: you cannot remove a node which has active shard placements -- mark all placements in the candidate node as inactive UPDATE pg_dist_shard_placement SET shardstate=3 WHERE nodeport=:worker_2_port; SELECT shardid, shardstate, nodename, nodeport FROM pg_dist_shard_placement WHERE nodeport=:worker_2_port; @@ -133,7 +158,7 @@ SELECT master_get_active_worker_nodes(); SELECT master_add_node('localhost', :worker_2_port); master_add_node --------------------------------- - (4,4,localhost,57638,default,f) + (5,5,localhost,57638,default,f) (1 row) UPDATE pg_dist_shard_placement SET shardstate=1 WHERE nodeport=:worker_2_port; @@ -149,7 +174,7 @@ UPDATE pg_dist_node SET hasmetadata=true WHERE nodeport=:worker_1_port; SELECT master_add_node('localhost', :worker_2_port); master_add_node --------------------------------- - (5,5,localhost,57638,default,f) + (6,6,localhost,57638,default,f) (1 row) \c - - - :worker_1_port @@ -178,7 +203,7 @@ UPDATE pg_dist_node SET hasmetadata=false WHERE nodeport=:worker_1_port; SELECT master_add_node('localhost', :worker_2_port); master_add_node --------------------------------- - (6,6,localhost,57638,default,f) + (7,7,localhost,57638,default,f) (1 row) \c - - - :worker_1_port @@ -208,14 +233,14 @@ SELECT master_add_node('localhost', :worker_2_port); master_add_node | master_add_node ---------------------------------+--------------------------------- - (7,7,localhost,57637,default,f) | (8,8,localhost,57638,default,f) + (8,8,localhost,57637,default,f) | (9,9,localhost,57638,default,f) (1 row) SELECT * FROM pg_dist_node ORDER BY nodeid; nodeid | groupid | nodename | nodeport | noderack | hasmetadata --------+---------+-----------+----------+----------+------------- - 7 | 7 | localhost | 57637 | default | f - 8 | 8 | localhost | 57638 | default | f + 8 | 8 | localhost | 57637 | default | f + 9 | 9 | localhost | 57638 | default | f (2 rows) -- check that mixed add/remove node commands work fine inside transaction @@ -227,9 +252,9 @@ SELECT master_remove_node('localhost', :worker_2_port); (1 row) SELECT master_add_node('localhost', :worker_2_port); - master_add_node ---------------------------------- - (9,9,localhost,57638,default,f) + master_add_node +----------------------------------- + (10,10,localhost,57638,default,f) (1 row) SELECT master_remove_node('localhost', :worker_2_port); @@ -249,7 +274,7 @@ BEGIN; SELECT master_add_node('localhost', :worker_2_port); master_add_node ----------------------------------- - (10,10,localhost,57638,default,f) + (11,11,localhost,57638,default,f) (1 row) SELECT master_remove_node('localhost', :worker_2_port); @@ -261,7 +286,7 @@ SELECT master_remove_node('localhost', :worker_2_port); SELECT master_add_node('localhost', :worker_2_port); master_add_node ----------------------------------- - (11,11,localhost,57638,default,f) + (12,12,localhost,57638,default,f) (1 row) COMMIT; @@ -289,13 +314,13 @@ SELECT master_remove_node(nodename, nodeport) FROM pg_dist_node; SELECT master_add_node('localhost', :worker_1_port); master_add_node ----------------------------------- - (12,12,localhost,57637,default,f) + (13,13,localhost,57637,default,f) (1 row) SELECT master_add_node('localhost', :worker_2_port); master_add_node ----------------------------------- - (13,13,localhost,57638,default,f) + (14,14,localhost,57638,default,f) (1 row) -- check that a distributed table can be created after adding a node in a transaction @@ -309,7 +334,7 @@ BEGIN; SELECT master_add_node('localhost', :worker_2_port); master_add_node ----------------------------------- - (14,14,localhost,57638,default,f) + (15,15,localhost,57638,default,f) (1 row) CREATE TABLE temp(col1 text, col2 int); diff --git a/src/test/regress/expected/multi_extension.out b/src/test/regress/expected/multi_extension.out index be7433906..e32b44512 100644 --- a/src/test/regress/expected/multi_extension.out +++ b/src/test/regress/expected/multi_extension.out @@ -70,6 +70,7 @@ ALTER EXTENSION citus UPDATE TO '6.1-9'; ALTER EXTENSION citus UPDATE TO '6.1-10'; ALTER EXTENSION citus UPDATE TO '6.1-11'; ALTER EXTENSION citus UPDATE TO '6.1-12'; +ALTER EXTENSION citus UPDATE TO '6.1-13'; -- ensure no objects were created outside pg_catalog SELECT COUNT(*) FROM pg_depend AS pgd, diff --git a/src/test/regress/sql/multi_cluster_management.sql b/src/test/regress/sql/multi_cluster_management.sql index dc765d02d..ddab21b7c 100644 --- a/src/test/regress/sql/multi_cluster_management.sql +++ b/src/test/regress/sql/multi_cluster_management.sql @@ -40,6 +40,17 @@ SELECT shardid, shardstate, nodename, nodeport FROM pg_dist_shard_placement WHER SELECT master_remove_node('localhost', :worker_2_port); SELECT master_get_active_worker_nodes(); +-- try to remove a node with active placements with force = true and see that node is removed +SELECT master_remove_node('localhost', :worker_2_port, true); +SELECT master_get_active_worker_nodes(); + +-- restore the node for next tests +SELECT master_add_node('localhost', :worker_2_port); + +-- try to remove a node with active placements with force = false and see that node +-- removal is failed +SELECT master_remove_node('localhost', :worker_2_port, false); + -- mark all placements in the candidate node as inactive UPDATE pg_dist_shard_placement SET shardstate=3 WHERE nodeport=:worker_2_port; SELECT shardid, shardstate, nodename, nodeport FROM pg_dist_shard_placement WHERE nodeport=:worker_2_port; diff --git a/src/test/regress/sql/multi_extension.sql b/src/test/regress/sql/multi_extension.sql index 72e695767..42e864018 100644 --- a/src/test/regress/sql/multi_extension.sql +++ b/src/test/regress/sql/multi_extension.sql @@ -70,6 +70,7 @@ ALTER EXTENSION citus UPDATE TO '6.1-9'; ALTER EXTENSION citus UPDATE TO '6.1-10'; ALTER EXTENSION citus UPDATE TO '6.1-11'; ALTER EXTENSION citus UPDATE TO '6.1-12'; +ALTER EXTENSION citus UPDATE TO '6.1-13'; -- ensure no objects were created outside pg_catalog SELECT COUNT(*)