mirror of https://github.com/citusdata/citus.git
Fix crash in citus_copy_shard_placement
parent
76a31f3234
commit
3b57ff2867
|
@ -74,6 +74,8 @@ static void VerifyTablesHaveReplicaIdentity(List *colocatedTableList);
|
||||||
static bool RelationCanPublishAllModifications(Oid relationId);
|
static bool RelationCanPublishAllModifications(Oid relationId);
|
||||||
static bool CanUseLogicalReplication(Oid relationId, char shardReplicationMode);
|
static bool CanUseLogicalReplication(Oid relationId, char shardReplicationMode);
|
||||||
static void ErrorIfTableCannotBeReplicated(Oid relationId);
|
static void ErrorIfTableCannotBeReplicated(Oid relationId);
|
||||||
|
static void ErrorIfTargetNodeIsNotSafeToCopyTo(const char *targetNodeName,
|
||||||
|
int targetNodePort);
|
||||||
static void RepairShardPlacement(int64 shardId, const char *sourceNodeName,
|
static void RepairShardPlacement(int64 shardId, const char *sourceNodeName,
|
||||||
int32 sourceNodePort, const char *targetNodeName,
|
int32 sourceNodePort, const char *targetNodeName,
|
||||||
int32 targetNodePort);
|
int32 targetNodePort);
|
||||||
|
@ -183,6 +185,7 @@ citus_copy_shard_placement(PG_FUNCTION_ARGS)
|
||||||
|
|
||||||
ShardInterval *shardInterval = LoadShardInterval(shardId);
|
ShardInterval *shardInterval = LoadShardInterval(shardId);
|
||||||
ErrorIfTableCannotBeReplicated(shardInterval->relationId);
|
ErrorIfTableCannotBeReplicated(shardInterval->relationId);
|
||||||
|
ErrorIfTargetNodeIsNotSafeToCopyTo(targetNodeName, targetNodePort);
|
||||||
|
|
||||||
AcquirePlacementColocationLock(shardInterval->relationId, ExclusiveLock,
|
AcquirePlacementColocationLock(shardInterval->relationId, ExclusiveLock,
|
||||||
doRepair ? "repair" : "copy");
|
doRepair ? "repair" : "copy");
|
||||||
|
@ -789,6 +792,41 @@ ErrorIfTableCannotBeReplicated(Oid relationId)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ErrorIfTargetNodeIsNotSafeToCopyTo throws an error if the target node is not
|
||||||
|
* eligible for copying shards.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
ErrorIfTargetNodeIsNotSafeToCopyTo(const char *targetNodeName, int targetNodePort)
|
||||||
|
{
|
||||||
|
WorkerNode *workerNode = FindWorkerNode(targetNodeName, targetNodePort);
|
||||||
|
if (workerNode == NULL)
|
||||||
|
{
|
||||||
|
ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
||||||
|
errmsg("Copying shards to a non-existing node is not supported"),
|
||||||
|
errhint(
|
||||||
|
"Add the target node via SELECT citus_add_node('%s', %d);",
|
||||||
|
targetNodeName, targetNodePort)));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!workerNode->isActive)
|
||||||
|
{
|
||||||
|
ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
||||||
|
errmsg("Copying shards to a non-active node is not supported"),
|
||||||
|
errhint(
|
||||||
|
"Activate the target node via SELECT citus_activate_node('%s', %d);",
|
||||||
|
targetNodeName, targetNodePort)));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!NodeIsPrimary(workerNode))
|
||||||
|
{
|
||||||
|
ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
||||||
|
errmsg("Copying shards to a secondary (e.g., replica) node is "
|
||||||
|
"not supported")));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* LookupShardTransferMode maps the oids of citus.shard_transfer_mode enum
|
* LookupShardTransferMode maps the oids of citus.shard_transfer_mode enum
|
||||||
* values to a char.
|
* values to a char.
|
||||||
|
|
|
@ -781,7 +781,51 @@ SELECT create_reference_table('ref_table');
|
||||||
(1 row)
|
(1 row)
|
||||||
|
|
||||||
INSERT INTO ref_table SELECT * FROM generate_series(1, 10);
|
INSERT INTO ref_table SELECT * FROM generate_series(1, 10);
|
||||||
SELECT 1 FROM master_add_node('localhost', :worker_2_port);
|
-- verify direct call to citus_copy_shard_placement errors if target node is not yet added
|
||||||
|
SELECT citus_copy_shard_placement(
|
||||||
|
(SELECT shardid FROM pg_dist_shard WHERE logicalrelid='ref_table'::regclass::oid),
|
||||||
|
'localhost', :worker_1_port,
|
||||||
|
'localhost', :worker_2_port,
|
||||||
|
do_repair := false,
|
||||||
|
transfer_mode := 'block_writes');
|
||||||
|
ERROR: Copying shards to a non-existing node is not supported
|
||||||
|
HINT: Add the target node via SELECT citus_add_node('localhost', 57638);
|
||||||
|
-- verify direct call to citus_copy_shard_placement errors if target node is secondary
|
||||||
|
SELECT citus_add_secondary_node('localhost', :worker_2_port, 'localhost', :worker_1_port);
|
||||||
|
citus_add_secondary_node
|
||||||
|
---------------------------------------------------------------------
|
||||||
|
1370012
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT citus_copy_shard_placement(
|
||||||
|
(SELECT shardid FROM pg_dist_shard WHERE logicalrelid='ref_table'::regclass::oid),
|
||||||
|
'localhost', :worker_1_port,
|
||||||
|
'localhost', :worker_2_port,
|
||||||
|
do_repair := false,
|
||||||
|
transfer_mode := 'block_writes');
|
||||||
|
ERROR: Copying shards to a secondary (e.g., replica) node is not supported
|
||||||
|
SELECT citus_remove_node('localhost', :worker_2_port);
|
||||||
|
citus_remove_node
|
||||||
|
---------------------------------------------------------------------
|
||||||
|
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
-- verify direct call to citus_copy_shard_placement errors if target node is inactive
|
||||||
|
SELECT 1 FROM master_add_inactive_node('localhost', :worker_2_port);
|
||||||
|
?column?
|
||||||
|
---------------------------------------------------------------------
|
||||||
|
1
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT citus_copy_shard_placement(
|
||||||
|
(SELECT shardid FROM pg_dist_shard WHERE logicalrelid='ref_table'::regclass::oid),
|
||||||
|
'localhost', :worker_1_port,
|
||||||
|
'localhost', :worker_2_port,
|
||||||
|
do_repair := false,
|
||||||
|
transfer_mode := 'block_writes');
|
||||||
|
ERROR: Copying shards to a non-active node is not supported
|
||||||
|
HINT: Activate the target node via SELECT citus_activate_node('localhost', 57638);
|
||||||
|
SELECT 1 FROM master_activate_node('localhost', :worker_2_port);
|
||||||
?column?
|
?column?
|
||||||
---------------------------------------------------------------------
|
---------------------------------------------------------------------
|
||||||
1
|
1
|
||||||
|
|
|
@ -509,7 +509,34 @@ CREATE TABLE ref_table(a int);
|
||||||
SELECT create_reference_table('ref_table');
|
SELECT create_reference_table('ref_table');
|
||||||
INSERT INTO ref_table SELECT * FROM generate_series(1, 10);
|
INSERT INTO ref_table SELECT * FROM generate_series(1, 10);
|
||||||
|
|
||||||
SELECT 1 FROM master_add_node('localhost', :worker_2_port);
|
-- verify direct call to citus_copy_shard_placement errors if target node is not yet added
|
||||||
|
SELECT citus_copy_shard_placement(
|
||||||
|
(SELECT shardid FROM pg_dist_shard WHERE logicalrelid='ref_table'::regclass::oid),
|
||||||
|
'localhost', :worker_1_port,
|
||||||
|
'localhost', :worker_2_port,
|
||||||
|
do_repair := false,
|
||||||
|
transfer_mode := 'block_writes');
|
||||||
|
|
||||||
|
-- verify direct call to citus_copy_shard_placement errors if target node is secondary
|
||||||
|
SELECT citus_add_secondary_node('localhost', :worker_2_port, 'localhost', :worker_1_port);
|
||||||
|
SELECT citus_copy_shard_placement(
|
||||||
|
(SELECT shardid FROM pg_dist_shard WHERE logicalrelid='ref_table'::regclass::oid),
|
||||||
|
'localhost', :worker_1_port,
|
||||||
|
'localhost', :worker_2_port,
|
||||||
|
do_repair := false,
|
||||||
|
transfer_mode := 'block_writes');
|
||||||
|
SELECT citus_remove_node('localhost', :worker_2_port);
|
||||||
|
|
||||||
|
-- verify direct call to citus_copy_shard_placement errors if target node is inactive
|
||||||
|
SELECT 1 FROM master_add_inactive_node('localhost', :worker_2_port);
|
||||||
|
SELECT citus_copy_shard_placement(
|
||||||
|
(SELECT shardid FROM pg_dist_shard WHERE logicalrelid='ref_table'::regclass::oid),
|
||||||
|
'localhost', :worker_1_port,
|
||||||
|
'localhost', :worker_2_port,
|
||||||
|
do_repair := false,
|
||||||
|
transfer_mode := 'block_writes');
|
||||||
|
|
||||||
|
SELECT 1 FROM master_activate_node('localhost', :worker_2_port);
|
||||||
|
|
||||||
-- verify we cannot replicate reference tables in a transaction modifying pg_dist_node
|
-- verify we cannot replicate reference tables in a transaction modifying pg_dist_node
|
||||||
BEGIN;
|
BEGIN;
|
||||||
|
|
Loading…
Reference in New Issue