mirror of https://github.com/citusdata/citus.git
Refactored replication origin functions to utils. added replication
orgin to undistribute table and alter distribure table.pull/6453/head
parent
af68b32ccb
commit
8b857d484f
|
@ -57,6 +57,7 @@
|
||||||
#include "distributed/relation_access_tracking.h"
|
#include "distributed/relation_access_tracking.h"
|
||||||
#include "distributed/shared_library_init.h"
|
#include "distributed/shared_library_init.h"
|
||||||
#include "distributed/shard_utils.h"
|
#include "distributed/shard_utils.h"
|
||||||
|
#include "distributed/replication_origin_session_utils.h"
|
||||||
#include "distributed/worker_protocol.h"
|
#include "distributed/worker_protocol.h"
|
||||||
#include "distributed/worker_transaction.h"
|
#include "distributed/worker_transaction.h"
|
||||||
#include "executor/spi.h"
|
#include "executor/spi.h"
|
||||||
|
@ -402,7 +403,10 @@ UndistributeTable(TableConversionParameters *params)
|
||||||
params->conversionType = UNDISTRIBUTE_TABLE;
|
params->conversionType = UNDISTRIBUTE_TABLE;
|
||||||
params->shardCountIsNull = true;
|
params->shardCountIsNull = true;
|
||||||
TableConversionState *con = CreateTableConversion(params);
|
TableConversionState *con = CreateTableConversion(params);
|
||||||
return ConvertTable(con);
|
ReplicationOriginSessionSetup(NULL);
|
||||||
|
TableConversionReturn *conv = ConvertTable(con);
|
||||||
|
ReplicationOriginSessionReset(NULL);
|
||||||
|
return conv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -441,7 +445,11 @@ AlterDistributedTable(TableConversionParameters *params)
|
||||||
ereport(DEBUG1, (errmsg("setting multi shard modify mode to sequential")));
|
ereport(DEBUG1, (errmsg("setting multi shard modify mode to sequential")));
|
||||||
SetLocalMultiShardModifyModeToSequential();
|
SetLocalMultiShardModifyModeToSequential();
|
||||||
}
|
}
|
||||||
return ConvertTable(con);
|
ReplicationOriginSessionSetup(NULL);
|
||||||
|
TableConversionReturn *conv = ConvertTable(con);
|
||||||
|
ReplicationOriginSessionReset(NULL);
|
||||||
|
|
||||||
|
return conv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -24,7 +24,7 @@
|
||||||
#include "distributed/relation_utils.h"
|
#include "distributed/relation_utils.h"
|
||||||
#include "distributed/version_compat.h"
|
#include "distributed/version_compat.h"
|
||||||
#include "distributed/local_executor.h"
|
#include "distributed/local_executor.h"
|
||||||
#include "replication/origin.h"
|
#include "distributed/replication_origin_session_utils.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* LocalCopyBuffer is used in copy callback to return the copied rows.
|
* LocalCopyBuffer is used in copy callback to return the copied rows.
|
||||||
|
@ -32,17 +32,6 @@
|
||||||
* argument to the copy callback.
|
* argument to the copy callback.
|
||||||
*/
|
*/
|
||||||
static StringInfo LocalCopyBuffer;
|
static StringInfo LocalCopyBuffer;
|
||||||
#define CDC_REPLICATION_ORIGIN_CREATE_IF_NOT_EXISTS_CMD \
|
|
||||||
"SELECT pg_catalog.pg_replication_origin_create('citus_internal_%d') \
|
|
||||||
where (select pg_catalog.pg_replication_origin_oid('citus_internal_%d')) IS NULL;"
|
|
||||||
|
|
||||||
#define CDC_REPLICATION_ORIGIN_SESION_SETUP_CMD \
|
|
||||||
"SELECT pg_catalog.pg_replication_origin_session_setup('citus_internal_%d') \
|
|
||||||
where pg_catalog.pg_replication_origin_session_is_setup()='f';"
|
|
||||||
|
|
||||||
#define CDC_REPLICATION_ORIGIN_SESION_RESET_CMD \
|
|
||||||
"SELECT pg_catalog.pg_replication_origin_session_reset() \
|
|
||||||
where pg_catalog.pg_replication_origin_session_is_setup()='t';"
|
|
||||||
|
|
||||||
typedef struct ShardCopyDestReceiver
|
typedef struct ShardCopyDestReceiver
|
||||||
{
|
{
|
||||||
|
@ -68,9 +57,6 @@ typedef struct ShardCopyDestReceiver
|
||||||
/* local copy if destination shard in same node */
|
/* local copy if destination shard in same node */
|
||||||
bool useLocalCopy;
|
bool useLocalCopy;
|
||||||
|
|
||||||
/* Replication Origin Id for local copy*/
|
|
||||||
RepOriginId originId;
|
|
||||||
|
|
||||||
/* EState for per-tuple memory allocation */
|
/* EState for per-tuple memory allocation */
|
||||||
EState *executorState;
|
EState *executorState;
|
||||||
|
|
||||||
|
@ -95,9 +81,6 @@ static void LocalCopyToShard(ShardCopyDestReceiver *copyDest, CopyOutState
|
||||||
localCopyOutState);
|
localCopyOutState);
|
||||||
static void ConnectToRemoteAndStartCopy(ShardCopyDestReceiver *copyDest);
|
static void ConnectToRemoteAndStartCopy(ShardCopyDestReceiver *copyDest);
|
||||||
|
|
||||||
static void ReplicationOriginSessionCreate(ShardCopyDestReceiver *dest);
|
|
||||||
static void ReplicationOriginSessionSetup(ShardCopyDestReceiver *dest);
|
|
||||||
static void ReplicationOriginSessionReset(ShardCopyDestReceiver *dest);
|
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
CanUseLocalCopy(uint32_t destinationNodeId)
|
CanUseLocalCopy(uint32_t destinationNodeId)
|
||||||
|
@ -107,8 +90,6 @@ CanUseLocalCopy(uint32_t destinationNodeId)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#define REPLICATION_ORIGIN_CMD_BUFFER_SIZE 1024
|
|
||||||
|
|
||||||
/* Connect to node with source shard and trigger copy start. */
|
/* Connect to node with source shard and trigger copy start. */
|
||||||
static void
|
static void
|
||||||
ConnectToRemoteAndStartCopy(ShardCopyDestReceiver *copyDest)
|
ConnectToRemoteAndStartCopy(ShardCopyDestReceiver *copyDest)
|
||||||
|
@ -124,7 +105,7 @@ ConnectToRemoteAndStartCopy(ShardCopyDestReceiver *copyDest)
|
||||||
NULL /* database (current) */);
|
NULL /* database (current) */);
|
||||||
ClaimConnectionExclusively(copyDest->connection);
|
ClaimConnectionExclusively(copyDest->connection);
|
||||||
|
|
||||||
ReplicationOriginSessionSetup(copyDest);
|
ReplicationOriginSessionSetup(copyDest->connection);
|
||||||
|
|
||||||
StringInfo copyStatement = ConstructShardCopyStatement(
|
StringInfo copyStatement = ConstructShardCopyStatement(
|
||||||
copyDest->destinationShardFullyQualifiedName,
|
copyDest->destinationShardFullyQualifiedName,
|
||||||
|
@ -170,7 +151,7 @@ CreateShardCopyDestReceiver(EState *executorState,
|
||||||
copyDest->tuplesSent = 0;
|
copyDest->tuplesSent = 0;
|
||||||
copyDest->connection = NULL;
|
copyDest->connection = NULL;
|
||||||
copyDest->useLocalCopy = CanUseLocalCopy(destinationNodeId);
|
copyDest->useLocalCopy = CanUseLocalCopy(destinationNodeId);
|
||||||
|
elog(LOG, "using local copy: %d", copyDest->useLocalCopy);
|
||||||
return (DestReceiver *) copyDest;
|
return (DestReceiver *) copyDest;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -209,7 +190,7 @@ ShardCopyDestReceiverReceive(TupleTableSlot *slot, DestReceiver *dest)
|
||||||
if (copyDest->useLocalCopy)
|
if (copyDest->useLocalCopy)
|
||||||
{
|
{
|
||||||
/* Setup replication origin session for local copy*/
|
/* Setup replication origin session for local copy*/
|
||||||
ReplicationOriginSessionSetup(copyDest);
|
ReplicationOriginSessionSetup(NULL);
|
||||||
|
|
||||||
WriteLocalTuple(slot, copyDest);
|
WriteLocalTuple(slot, copyDest);
|
||||||
if (copyOutState->fe_msgbuf->len > LocalCopyFlushThresholdByte)
|
if (copyOutState->fe_msgbuf->len > LocalCopyFlushThresholdByte)
|
||||||
|
@ -286,102 +267,6 @@ ShardCopyDestReceiverStartup(DestReceiver *dest, int operation, TupleDesc
|
||||||
copyDest->columnOutputFunctions = ColumnOutputFunctions(inputTupleDescriptor,
|
copyDest->columnOutputFunctions = ColumnOutputFunctions(inputTupleDescriptor,
|
||||||
copyOutState->binary);
|
copyOutState->binary);
|
||||||
copyDest->copyOutState = copyOutState;
|
copyDest->copyOutState = copyOutState;
|
||||||
ReplicationOriginSessionCreate(copyDest);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* ReplicationOriginSessionCreate creates a new replication origin if it does
|
|
||||||
* not already exist already. To make the replication origin name unique
|
|
||||||
* for different nodes, origin node's id is appended to the prefix citus_internal_.*/
|
|
||||||
static void
|
|
||||||
ReplicationOriginSessionCreate(ShardCopyDestReceiver *dest)
|
|
||||||
{
|
|
||||||
int localid = GetLocalNodeId();
|
|
||||||
if (dest->useLocalCopy)
|
|
||||||
{
|
|
||||||
char originName[64];
|
|
||||||
snprintf(originName, sizeof(originName), "citus_internal_%d", localid);
|
|
||||||
RepOriginId originId = replorigin_by_name(originName, true);
|
|
||||||
if (originId == InvalidRepOriginId)
|
|
||||||
{
|
|
||||||
originId = replorigin_create(originName);
|
|
||||||
}
|
|
||||||
dest->originId = originId;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
int connectionFlags = OUTSIDE_TRANSACTION;
|
|
||||||
char *currentUser = CurrentUserName();
|
|
||||||
WorkerNode *workerNode = FindNodeWithNodeId(dest->destinationNodeId,
|
|
||||||
false /* missingOk */);
|
|
||||||
MultiConnection *connection = GetNodeUserDatabaseConnection(connectionFlags,
|
|
||||||
workerNode->workerName,
|
|
||||||
workerNode->workerPort,
|
|
||||||
currentUser,
|
|
||||||
NULL /* database (current) */);
|
|
||||||
|
|
||||||
char replicationOrginCreateCommand[REPLICATION_ORIGIN_CMD_BUFFER_SIZE];
|
|
||||||
snprintf(replicationOrginCreateCommand, REPLICATION_ORIGIN_CMD_BUFFER_SIZE,
|
|
||||||
CDC_REPLICATION_ORIGIN_CREATE_IF_NOT_EXISTS_CMD, localid, localid);
|
|
||||||
|
|
||||||
ExecuteCriticalRemoteCommand(connection, replicationOrginCreateCommand);
|
|
||||||
CloseConnection(connection);
|
|
||||||
dest->originId = InvalidRepOriginId;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* ReplicationOriginSessionSetup sets up a new replication origin session in a
|
|
||||||
* local or remote session depending on the useLocalCopy flag. If useLocalCopy
|
|
||||||
* is set, a local replication origin session is setup, otherwise a remote
|
|
||||||
* replication origin session is setup to the destination node.
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
ReplicationOriginSessionSetup(ShardCopyDestReceiver *dest)
|
|
||||||
{
|
|
||||||
if (dest->useLocalCopy)
|
|
||||||
{
|
|
||||||
/*Setup Replication Origin in local session */
|
|
||||||
if (replorigin_session_origin == InvalidRepOriginId)
|
|
||||||
{
|
|
||||||
replorigin_session_setup(dest->originId);
|
|
||||||
replorigin_session_origin = dest->originId;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/*Setup Replication Origin in remote session */
|
|
||||||
char replicationOrginSetupCommand[REPLICATION_ORIGIN_CMD_BUFFER_SIZE];
|
|
||||||
int localId = GetLocalNodeId();
|
|
||||||
snprintf(replicationOrginSetupCommand, REPLICATION_ORIGIN_CMD_BUFFER_SIZE,
|
|
||||||
CDC_REPLICATION_ORIGIN_SESION_SETUP_CMD, localId);
|
|
||||||
ExecuteCriticalRemoteCommand(dest->connection, replicationOrginSetupCommand);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* ReplicationOriginSessionReset resets the replication origin session in a
|
|
||||||
* local or remote session depending on the useLocalCopy flag.
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
ReplicationOriginSessionReset(ShardCopyDestReceiver *dest)
|
|
||||||
{
|
|
||||||
if (dest->useLocalCopy)
|
|
||||||
{
|
|
||||||
/*Reset Replication Origin in local session */
|
|
||||||
if (replorigin_session_origin != InvalidRepOriginId)
|
|
||||||
{
|
|
||||||
replorigin_session_reset();
|
|
||||||
replorigin_session_origin = InvalidRepOriginId;
|
|
||||||
}
|
|
||||||
dest->originId = InvalidRepOriginId;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/*Reset Replication Origin in remote session */
|
|
||||||
ExecuteCriticalRemoteCommand(dest->connection,
|
|
||||||
CDC_REPLICATION_ORIGIN_SESION_RESET_CMD);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -403,7 +288,7 @@ ShardCopyDestReceiverShutdown(DestReceiver *dest)
|
||||||
/* end the COPY input */
|
/* end the COPY input */
|
||||||
LocalCopyToShard(copyDest, copyDest->copyOutState);
|
LocalCopyToShard(copyDest, copyDest->copyOutState);
|
||||||
}
|
}
|
||||||
ReplicationOriginSessionReset(copyDest);
|
ReplicationOriginSessionReset(NULL);
|
||||||
}
|
}
|
||||||
else if (copyDest->connection != NULL)
|
else if (copyDest->connection != NULL)
|
||||||
{
|
{
|
||||||
|
@ -441,7 +326,7 @@ ShardCopyDestReceiverShutdown(DestReceiver *dest)
|
||||||
|
|
||||||
PQclear(result);
|
PQclear(result);
|
||||||
ForgetResults(copyDest->connection);
|
ForgetResults(copyDest->connection);
|
||||||
ReplicationOriginSessionReset(copyDest);
|
ReplicationOriginSessionReset(copyDest->connection);
|
||||||
|
|
||||||
CloseConnection(copyDest->connection);
|
CloseConnection(copyDest->connection);
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,222 @@
|
||||||
|
/*-------------------------------------------------------------------------
|
||||||
|
*
|
||||||
|
* replication_origin_session_utils.c
|
||||||
|
* Functions for managing replication origin session.
|
||||||
|
*
|
||||||
|
* Copyright (c) Citus Data, Inc.
|
||||||
|
*
|
||||||
|
*-------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "distributed/replication_origin_session_utils.h"
|
||||||
|
#include "distributed/remote_commands.h"
|
||||||
|
#include "distributed/metadata_cache.h"
|
||||||
|
|
||||||
|
static bool isReplicationOriginSessionSetup(MultiConnection *connection);
|
||||||
|
static bool isReplicationOriginCreated(MultiConnection *connection, char *originName,
|
||||||
|
RepOriginId *originId);
|
||||||
|
static RepOriginId ReplicationOriginSessionCreate(MultiConnection *connection,
|
||||||
|
char *originName);
|
||||||
|
static void ReplicationOriginSessionSetupHelper(MultiConnection *connection,
|
||||||
|
RepOriginId originId, char *originName);
|
||||||
|
static bool ExecuteRemoteCommandAndCheckResult(MultiConnection *connection, char *command,
|
||||||
|
char *expected);
|
||||||
|
|
||||||
|
/* ReplicationOriginSessionSetup sets up a new replication origin session in a
|
||||||
|
* local or remote session depending on the useLocalCopy flag. If useLocalCopy
|
||||||
|
* is set, a local replication origin session is setup, otherwise a remote
|
||||||
|
* replication origin session is setup to the destination node.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
ReplicationOriginSessionSetup(MultiConnection *connection)
|
||||||
|
{
|
||||||
|
if (!isReplicationOriginSessionSetup(connection))
|
||||||
|
{
|
||||||
|
int localid = GetLocalNodeId();
|
||||||
|
RepOriginId originId = InvalidRepOriginId;
|
||||||
|
StringInfo originNameString = makeStringInfo();
|
||||||
|
appendStringInfo(originNameString, "citus_internal_%d", localid);
|
||||||
|
if (!isReplicationOriginCreated(connection, originNameString->data, &originId))
|
||||||
|
{
|
||||||
|
originId = ReplicationOriginSessionCreate(connection, originNameString->data);
|
||||||
|
}
|
||||||
|
ReplicationOriginSessionSetupHelper(connection, originId, originNameString->data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* ReplicationOriginSessionReset resets the replication origin session in a
|
||||||
|
* local or remote session depending on the useLocalCopy flag.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
ReplicationOriginSessionReset(MultiConnection *connection)
|
||||||
|
{
|
||||||
|
if (connection == NULL)
|
||||||
|
{
|
||||||
|
/*Reset Replication Origin in local session */
|
||||||
|
if (replorigin_session_origin != InvalidRepOriginId)
|
||||||
|
{
|
||||||
|
replorigin_session_reset();
|
||||||
|
replorigin_session_origin = InvalidRepOriginId;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/*Reset Replication Origin in remote session */
|
||||||
|
StringInfo replicationOriginSessionResetQuery = makeStringInfo();
|
||||||
|
appendStringInfo(replicationOriginSessionResetQuery,
|
||||||
|
"select pg_catalog.pg_replication_origin_session_reset()");
|
||||||
|
ExecuteCriticalRemoteCommand(connection,
|
||||||
|
replicationOriginSessionResetQuery->data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* isReplicationOriginSessionSetup checks if the replication origin is setup
|
||||||
|
* already in the local or remote session.
|
||||||
|
*/
|
||||||
|
static bool
|
||||||
|
isReplicationOriginSessionSetup(MultiConnection *connection)
|
||||||
|
{
|
||||||
|
bool result = false;
|
||||||
|
if (connection == NULL)
|
||||||
|
{
|
||||||
|
return replorigin_session_origin != InvalidRepOriginId;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/*Setup Replication Origin in remote session */
|
||||||
|
StringInfo isReplicationOriginSessionSetupQuery = makeStringInfo();
|
||||||
|
appendStringInfo(isReplicationOriginSessionSetupQuery,
|
||||||
|
"SELECT pg_catalog.pg_replication_origin_session_is_setup()");
|
||||||
|
result =
|
||||||
|
ExecuteRemoteCommandAndCheckResult(connection,
|
||||||
|
isReplicationOriginSessionSetupQuery->data,
|
||||||
|
"t");
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* isReplicationOriginCreated checks if the replication origin is created
|
||||||
|
* in the local or remote session.*/
|
||||||
|
static bool
|
||||||
|
isReplicationOriginCreated(MultiConnection *connection, char *originName,
|
||||||
|
RepOriginId *originId)
|
||||||
|
{
|
||||||
|
bool result = false;
|
||||||
|
if (connection == NULL)
|
||||||
|
{
|
||||||
|
*originId = replorigin_by_name(originName, true);
|
||||||
|
result = (*originId != InvalidRepOriginId);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/*Setup Replication Origin in remote session */
|
||||||
|
StringInfo isReplicationOriginSessionSetupQuery = makeStringInfo();
|
||||||
|
appendStringInfo(isReplicationOriginSessionSetupQuery,
|
||||||
|
"SELECT pg_catalog.pg_replication_origin_oid('%s');",
|
||||||
|
originName);
|
||||||
|
|
||||||
|
/* If the replication origin was already created the above command
|
||||||
|
* will return the id of the entry in pg_replication_origin table.
|
||||||
|
* So to check if the entry is there alreay, the retuen value should
|
||||||
|
* be non-empty and the condition below checks that. */
|
||||||
|
result = !ExecuteRemoteCommandAndCheckResult(connection,
|
||||||
|
isReplicationOriginSessionSetupQuery
|
||||||
|
->data, "");
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* ReplicationOriginSessionCreate creates a new replication origin if it does
|
||||||
|
* not already exist already. To make the replication origin name unique
|
||||||
|
* for different nodes, origin node's id is appended to the prefix citus_internal_.*/
|
||||||
|
static RepOriginId
|
||||||
|
ReplicationOriginSessionCreate(MultiConnection *connection, char *originName)
|
||||||
|
{
|
||||||
|
RepOriginId originId = InvalidRepOriginId;
|
||||||
|
if (connection == NULL)
|
||||||
|
{
|
||||||
|
originId = replorigin_create(originName);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
StringInfo replicationOriginCreateQuery = makeStringInfo();
|
||||||
|
appendStringInfo(replicationOriginCreateQuery,
|
||||||
|
"select pg_catalog.pg_replication_origin_create('%s')",
|
||||||
|
originName);
|
||||||
|
ExecuteCriticalRemoteCommand(connection, replicationOriginCreateQuery->data);
|
||||||
|
}
|
||||||
|
return originId;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* ReplicationOriginSessionSetupHelper sets up a new replication origin session in a
|
||||||
|
* local or remote session depending on the useLocalCopy flag. If useLocalCopy
|
||||||
|
* is set, a local replication origin session is setup, otherwise a remote
|
||||||
|
* replication origin session is setup to the destination node.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
ReplicationOriginSessionSetupHelper(MultiConnection *connection,
|
||||||
|
RepOriginId originId, char *originName)
|
||||||
|
{
|
||||||
|
if (connection == NULL)
|
||||||
|
{
|
||||||
|
/*Setup Replication Origin in local session */
|
||||||
|
replorigin_session_setup(originId);
|
||||||
|
replorigin_session_origin = originId;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/*Setup Replication Origin in remote session */
|
||||||
|
StringInfo replicationOriginSessionSetupQuery = makeStringInfo();
|
||||||
|
appendStringInfo(replicationOriginSessionSetupQuery,
|
||||||
|
"select pg_catalog.pg_replication_origin_session_setup('%s')",
|
||||||
|
originName);
|
||||||
|
ExecuteCriticalRemoteCommand(connection,
|
||||||
|
replicationOriginSessionSetupQuery->data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* ExecuteRemoteCommandAndCheckResult executes the given command in the remote node and
|
||||||
|
* checks if the result is equal to the expected result. If the result is equal to the
|
||||||
|
* expected result, the function returns true, otherwise it returns false.
|
||||||
|
*/
|
||||||
|
static bool
|
||||||
|
ExecuteRemoteCommandAndCheckResult(MultiConnection *connection, char *command,
|
||||||
|
char *expected)
|
||||||
|
{
|
||||||
|
if (!SendRemoteCommand(connection, command))
|
||||||
|
{
|
||||||
|
/* if we cannot connect, we warn and report false */
|
||||||
|
ReportConnectionError(connection, WARNING);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
bool raiseInterrupts = true;
|
||||||
|
PGresult *queryResult = GetRemoteCommandResult(connection, raiseInterrupts);
|
||||||
|
|
||||||
|
/* if remote node throws an error, we also throw an error */
|
||||||
|
if (!IsResponseOK(queryResult))
|
||||||
|
{
|
||||||
|
ReportResultError(connection, queryResult, ERROR);
|
||||||
|
}
|
||||||
|
|
||||||
|
StringInfo queryResultString = makeStringInfo();
|
||||||
|
|
||||||
|
/* Evaluate the queryResult and store it into the queryResultString */
|
||||||
|
bool success = EvaluateSingleQueryResult(connection, queryResult, queryResultString);
|
||||||
|
bool result = false;
|
||||||
|
if (success && strcmp(queryResultString->data, expected) == 0)
|
||||||
|
{
|
||||||
|
result = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
PQclear(queryResult);
|
||||||
|
bool raiseErrors = false;
|
||||||
|
ClearResults(connection, raiseErrors);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
|
@ -0,0 +1,22 @@
|
||||||
|
/*-------------------------------------------------------------------------
|
||||||
|
*
|
||||||
|
* replication_origin_utils.h
|
||||||
|
* Utilities related to replication origin.
|
||||||
|
*
|
||||||
|
* Copyright (c) Citus Data, Inc.
|
||||||
|
*
|
||||||
|
*-------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef REPLICATION_ORIGIN_SESSION_UTILS_H
|
||||||
|
#define REPLICATION_ORIGIN_SESSION_UTILS_H
|
||||||
|
|
||||||
|
#include "postgres.h"
|
||||||
|
#include "replication/origin.h"
|
||||||
|
#include "distributed/connection_management.h"
|
||||||
|
|
||||||
|
void ReplicationOriginSessionSetup(MultiConnection *connection);
|
||||||
|
void ReplicationOriginSessionReset(MultiConnection *connection);
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* REPLICATION_ORIGIN_SESSION_UTILS_H */
|
Loading…
Reference in New Issue