mirror of https://github.com/citusdata/citus.git
Move multi_client_executor.[ch] ontop of connection_management.[ch].
That way connections can be automatically closed after errors and such, and the connection management infrastructure gets wider testing. It also fixes a few issues around connection string building.pull/863/head
parent
a77cf36778
commit
2374905c89
|
@ -23,6 +23,7 @@
|
||||||
#include "distributed/connection_management.h"
|
#include "distributed/connection_management.h"
|
||||||
#include "distributed/multi_client_executor.h"
|
#include "distributed/multi_client_executor.h"
|
||||||
#include "distributed/multi_server_executor.h"
|
#include "distributed/multi_server_executor.h"
|
||||||
|
#include "distributed/remote_commands.h"
|
||||||
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
@ -39,7 +40,7 @@
|
||||||
|
|
||||||
|
|
||||||
/* Local pool to track active connections */
|
/* Local pool to track active connections */
|
||||||
static PGconn *ClientConnectionArray[MAX_CONNECTION_COUNT];
|
static MultiConnection *ClientConnectionArray[MAX_CONNECTION_COUNT];
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The value at any position on ClientPollingStatusArray is only defined when
|
* The value at any position on ClientPollingStatusArray is only defined when
|
||||||
|
@ -49,8 +50,8 @@ static PostgresPollingStatusType ClientPollingStatusArray[MAX_CONNECTION_COUNT];
|
||||||
|
|
||||||
|
|
||||||
/* Local functions forward declarations */
|
/* Local functions forward declarations */
|
||||||
static void ClearRemainingResults(PGconn *connection);
|
static void ClearRemainingResults(MultiConnection *connection);
|
||||||
static bool ClientConnectionReady(PGconn *connection,
|
static bool ClientConnectionReady(MultiConnection *connection,
|
||||||
PostgresPollingStatusType pollingStatus);
|
PostgresPollingStatusType pollingStatus);
|
||||||
|
|
||||||
|
|
||||||
|
@ -64,7 +65,7 @@ AllocateConnectionId(void)
|
||||||
/* allocate connectionId from connection pool */
|
/* allocate connectionId from connection pool */
|
||||||
for (connIndex = 0; connIndex < MAX_CONNECTION_COUNT; connIndex++)
|
for (connIndex = 0; connIndex < MAX_CONNECTION_COUNT; connIndex++)
|
||||||
{
|
{
|
||||||
PGconn *connection = ClientConnectionArray[connIndex];
|
MultiConnection *connection = ClientConnectionArray[connIndex];
|
||||||
if (connection == NULL)
|
if (connection == NULL)
|
||||||
{
|
{
|
||||||
connectionId = connIndex;
|
connectionId = connIndex;
|
||||||
|
@ -88,12 +89,16 @@ int32
|
||||||
MultiClientConnect(const char *nodeName, uint32 nodePort, const char *nodeDatabase,
|
MultiClientConnect(const char *nodeName, uint32 nodePort, const char *nodeDatabase,
|
||||||
const char *userName)
|
const char *userName)
|
||||||
{
|
{
|
||||||
PGconn *connection = NULL;
|
MultiConnection *connection = NULL;
|
||||||
char connInfoString[STRING_BUFFER_SIZE];
|
|
||||||
ConnStatusType connStatusType = CONNECTION_OK;
|
ConnStatusType connStatusType = CONNECTION_OK;
|
||||||
int32 connectionId = AllocateConnectionId();
|
int32 connectionId = AllocateConnectionId();
|
||||||
char *effectiveDatabaseName = NULL;
|
int connectionFlags = FORCE_NEW_CONNECTION; /* no cached connections for now */
|
||||||
char *effectiveUserName = NULL;
|
|
||||||
|
if (connectionId == INVALID_CONNECTION_ID)
|
||||||
|
{
|
||||||
|
ereport(WARNING, (errmsg("could not allocate connection in connection pool")));
|
||||||
|
return connectionId;
|
||||||
|
}
|
||||||
|
|
||||||
if (XactModificationLevel > XACT_MODIFICATION_NONE)
|
if (XactModificationLevel > XACT_MODIFICATION_NONE)
|
||||||
{
|
{
|
||||||
|
@ -102,46 +107,11 @@ MultiClientConnect(const char *nodeName, uint32 nodePort, const char *nodeDataba
|
||||||
"command within a transaction")));
|
"command within a transaction")));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (connectionId == INVALID_CONNECTION_ID)
|
|
||||||
{
|
|
||||||
ereport(WARNING, (errmsg("could not allocate connection in connection pool")));
|
|
||||||
return connectionId;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (nodeDatabase == NULL)
|
|
||||||
{
|
|
||||||
effectiveDatabaseName = get_database_name(MyDatabaseId);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
effectiveDatabaseName = pstrdup(nodeDatabase);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (userName == NULL)
|
|
||||||
{
|
|
||||||
effectiveUserName = CurrentUserName();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
effectiveUserName = pstrdup(userName);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* FIXME: This code is bad on several levels. It completely forgoes any
|
|
||||||
* escaping, it misses setting a number of parameters, it works with a
|
|
||||||
* limited string size without erroring when it's too long. We shouldn't
|
|
||||||
* even build a query string this way, there's PQconnectdbParams()!
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* transcribe connection paremeters to string */
|
|
||||||
snprintf(connInfoString, STRING_BUFFER_SIZE, CONN_INFO_TEMPLATE,
|
|
||||||
nodeName, nodePort,
|
|
||||||
effectiveDatabaseName, effectiveUserName,
|
|
||||||
CLIENT_CONNECT_TIMEOUT);
|
|
||||||
|
|
||||||
/* establish synchronous connection to worker node */
|
/* establish synchronous connection to worker node */
|
||||||
connection = PQconnectdb(connInfoString);
|
connection = GetNodeUserDatabaseConnection(connectionFlags, nodeName, nodePort,
|
||||||
connStatusType = PQstatus(connection);
|
userName, nodeDatabase);
|
||||||
|
|
||||||
|
connStatusType = PQstatus(connection->pgConn);
|
||||||
|
|
||||||
if (connStatusType == CONNECTION_OK)
|
if (connStatusType == CONNECTION_OK)
|
||||||
{
|
{
|
||||||
|
@ -149,15 +119,11 @@ MultiClientConnect(const char *nodeName, uint32 nodePort, const char *nodeDataba
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
WarnRemoteError(connection, NULL);
|
ReportConnectionError(connection, WARNING);
|
||||||
|
CloseConnection(connection);
|
||||||
PQfinish(connection);
|
|
||||||
connectionId = INVALID_CONNECTION_ID;
|
connectionId = INVALID_CONNECTION_ID;
|
||||||
}
|
}
|
||||||
|
|
||||||
pfree(effectiveDatabaseName);
|
|
||||||
pfree(effectiveUserName);
|
|
||||||
|
|
||||||
return connectionId;
|
return connectionId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -170,12 +136,11 @@ MultiClientConnect(const char *nodeName, uint32 nodePort, const char *nodeDataba
|
||||||
int32
|
int32
|
||||||
MultiClientConnectStart(const char *nodeName, uint32 nodePort, const char *nodeDatabase)
|
MultiClientConnectStart(const char *nodeName, uint32 nodePort, const char *nodeDatabase)
|
||||||
{
|
{
|
||||||
PGconn *connection = NULL;
|
MultiConnection *connection = NULL;
|
||||||
char connInfoString[STRING_BUFFER_SIZE];
|
ConnStatusType connStatusType = CONNECTION_OK;
|
||||||
ConnStatusType connStatusType = CONNECTION_BAD;
|
|
||||||
char *userName = CurrentUserName();
|
|
||||||
|
|
||||||
int32 connectionId = AllocateConnectionId();
|
int32 connectionId = AllocateConnectionId();
|
||||||
|
int connectionFlags = FORCE_NEW_CONNECTION; /* no cached connections for now */
|
||||||
|
|
||||||
if (connectionId == INVALID_CONNECTION_ID)
|
if (connectionId == INVALID_CONNECTION_ID)
|
||||||
{
|
{
|
||||||
ereport(WARNING, (errmsg("could not allocate connection in connection pool")));
|
ereport(WARNING, (errmsg("could not allocate connection in connection pool")));
|
||||||
|
@ -189,13 +154,9 @@ MultiClientConnectStart(const char *nodeName, uint32 nodePort, const char *nodeD
|
||||||
"command within a transaction")));
|
"command within a transaction")));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* transcribe connection paremeters to string */
|
|
||||||
snprintf(connInfoString, STRING_BUFFER_SIZE, CONN_INFO_TEMPLATE,
|
|
||||||
nodeName, nodePort, nodeDatabase, userName, CLIENT_CONNECT_TIMEOUT);
|
|
||||||
|
|
||||||
/* prepare asynchronous request for worker node connection */
|
/* prepare asynchronous request for worker node connection */
|
||||||
connection = PQconnectStart(connInfoString);
|
connection = StartNodeConnection(connectionFlags, nodeName, nodePort);
|
||||||
connStatusType = PQstatus(connection);
|
connStatusType = PQstatus(connection->pgConn);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If prepared, we save the connection, and set its initial polling status
|
* If prepared, we save the connection, and set its initial polling status
|
||||||
|
@ -209,9 +170,9 @@ MultiClientConnectStart(const char *nodeName, uint32 nodePort, const char *nodeD
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
WarnRemoteError(connection, NULL);
|
ReportConnectionError(connection, WARNING);
|
||||||
|
CloseConnection(connection);
|
||||||
|
|
||||||
PQfinish(connection);
|
|
||||||
connectionId = INVALID_CONNECTION_ID;
|
connectionId = INVALID_CONNECTION_ID;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -223,7 +184,7 @@ MultiClientConnectStart(const char *nodeName, uint32 nodePort, const char *nodeD
|
||||||
ConnectStatus
|
ConnectStatus
|
||||||
MultiClientConnectPoll(int32 connectionId)
|
MultiClientConnectPoll(int32 connectionId)
|
||||||
{
|
{
|
||||||
PGconn *connection = NULL;
|
MultiConnection *connection = NULL;
|
||||||
PostgresPollingStatusType pollingStatus = PGRES_POLLING_OK;
|
PostgresPollingStatusType pollingStatus = PGRES_POLLING_OK;
|
||||||
ConnectStatus connectStatus = CLIENT_INVALID_CONNECT;
|
ConnectStatus connectStatus = CLIENT_INVALID_CONNECT;
|
||||||
|
|
||||||
|
@ -241,7 +202,7 @@ MultiClientConnectPoll(int32 connectionId)
|
||||||
bool readReady = ClientConnectionReady(connection, PGRES_POLLING_READING);
|
bool readReady = ClientConnectionReady(connection, PGRES_POLLING_READING);
|
||||||
if (readReady)
|
if (readReady)
|
||||||
{
|
{
|
||||||
ClientPollingStatusArray[connectionId] = PQconnectPoll(connection);
|
ClientPollingStatusArray[connectionId] = PQconnectPoll(connection->pgConn);
|
||||||
connectStatus = CLIENT_CONNECTION_BUSY;
|
connectStatus = CLIENT_CONNECTION_BUSY;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -254,7 +215,7 @@ MultiClientConnectPoll(int32 connectionId)
|
||||||
bool writeReady = ClientConnectionReady(connection, PGRES_POLLING_WRITING);
|
bool writeReady = ClientConnectionReady(connection, PGRES_POLLING_WRITING);
|
||||||
if (writeReady)
|
if (writeReady)
|
||||||
{
|
{
|
||||||
ClientPollingStatusArray[connectionId] = PQconnectPoll(connection);
|
ClientPollingStatusArray[connectionId] = PQconnectPoll(connection->pgConn);
|
||||||
connectStatus = CLIENT_CONNECTION_BUSY;
|
connectStatus = CLIENT_CONNECTION_BUSY;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -264,7 +225,7 @@ MultiClientConnectPoll(int32 connectionId)
|
||||||
}
|
}
|
||||||
else if (pollingStatus == PGRES_POLLING_FAILED)
|
else if (pollingStatus == PGRES_POLLING_FAILED)
|
||||||
{
|
{
|
||||||
WarnRemoteError(connection, NULL);
|
ReportConnectionError(connection, WARNING);
|
||||||
|
|
||||||
connectStatus = CLIENT_CONNECTION_BAD;
|
connectStatus = CLIENT_CONNECTION_BAD;
|
||||||
}
|
}
|
||||||
|
@ -277,14 +238,14 @@ MultiClientConnectPoll(int32 connectionId)
|
||||||
void
|
void
|
||||||
MultiClientDisconnect(int32 connectionId)
|
MultiClientDisconnect(int32 connectionId)
|
||||||
{
|
{
|
||||||
PGconn *connection = NULL;
|
MultiConnection *connection = NULL;
|
||||||
const int InvalidPollingStatus = -1;
|
const int InvalidPollingStatus = -1;
|
||||||
|
|
||||||
Assert(connectionId != INVALID_CONNECTION_ID);
|
Assert(connectionId != INVALID_CONNECTION_ID);
|
||||||
connection = ClientConnectionArray[connectionId];
|
connection = ClientConnectionArray[connectionId];
|
||||||
Assert(connection != NULL);
|
Assert(connection != NULL);
|
||||||
|
|
||||||
PQfinish(connection);
|
CloseConnection(connection);
|
||||||
|
|
||||||
ClientConnectionArray[connectionId] = NULL;
|
ClientConnectionArray[connectionId] = NULL;
|
||||||
ClientPollingStatusArray[connectionId] = InvalidPollingStatus;
|
ClientPollingStatusArray[connectionId] = InvalidPollingStatus;
|
||||||
|
@ -298,7 +259,7 @@ MultiClientDisconnect(int32 connectionId)
|
||||||
bool
|
bool
|
||||||
MultiClientConnectionUp(int32 connectionId)
|
MultiClientConnectionUp(int32 connectionId)
|
||||||
{
|
{
|
||||||
PGconn *connection = NULL;
|
MultiConnection *connection = NULL;
|
||||||
ConnStatusType connStatusType = CONNECTION_OK;
|
ConnStatusType connStatusType = CONNECTION_OK;
|
||||||
bool connectionUp = true;
|
bool connectionUp = true;
|
||||||
|
|
||||||
|
@ -306,7 +267,7 @@ MultiClientConnectionUp(int32 connectionId)
|
||||||
connection = ClientConnectionArray[connectionId];
|
connection = ClientConnectionArray[connectionId];
|
||||||
Assert(connection != NULL);
|
Assert(connection != NULL);
|
||||||
|
|
||||||
connStatusType = PQstatus(connection);
|
connStatusType = PQstatus(connection->pgConn);
|
||||||
if (connStatusType == CONNECTION_BAD)
|
if (connStatusType == CONNECTION_BAD)
|
||||||
{
|
{
|
||||||
connectionUp = false;
|
connectionUp = false;
|
||||||
|
@ -340,7 +301,7 @@ MultiClientExecute(int32 connectionId, const char *query, void **queryResult,
|
||||||
bool
|
bool
|
||||||
MultiClientSendQuery(int32 connectionId, const char *query)
|
MultiClientSendQuery(int32 connectionId, const char *query)
|
||||||
{
|
{
|
||||||
PGconn *connection = NULL;
|
MultiConnection *connection = NULL;
|
||||||
bool success = true;
|
bool success = true;
|
||||||
int querySent = 0;
|
int querySent = 0;
|
||||||
|
|
||||||
|
@ -348,10 +309,10 @@ MultiClientSendQuery(int32 connectionId, const char *query)
|
||||||
connection = ClientConnectionArray[connectionId];
|
connection = ClientConnectionArray[connectionId];
|
||||||
Assert(connection != NULL);
|
Assert(connection != NULL);
|
||||||
|
|
||||||
querySent = PQsendQuery(connection, query);
|
querySent = PQsendQuery(connection->pgConn, query);
|
||||||
if (querySent == 0)
|
if (querySent == 0)
|
||||||
{
|
{
|
||||||
char *errorMessage = PQerrorMessage(connection);
|
char *errorMessage = PQerrorMessage(connection->pgConn);
|
||||||
ereport(WARNING, (errmsg("could not send remote query \"%s\"", query),
|
ereport(WARNING, (errmsg("could not send remote query \"%s\"", query),
|
||||||
errdetail("Client error: %s", errorMessage)));
|
errdetail("Client error: %s", errorMessage)));
|
||||||
|
|
||||||
|
@ -366,7 +327,7 @@ MultiClientSendQuery(int32 connectionId, const char *query)
|
||||||
bool
|
bool
|
||||||
MultiClientCancel(int32 connectionId)
|
MultiClientCancel(int32 connectionId)
|
||||||
{
|
{
|
||||||
PGconn *connection = NULL;
|
MultiConnection *connection = NULL;
|
||||||
PGcancel *cancelObject = NULL;
|
PGcancel *cancelObject = NULL;
|
||||||
int cancelSent = 0;
|
int cancelSent = 0;
|
||||||
bool canceled = true;
|
bool canceled = true;
|
||||||
|
@ -376,7 +337,7 @@ MultiClientCancel(int32 connectionId)
|
||||||
connection = ClientConnectionArray[connectionId];
|
connection = ClientConnectionArray[connectionId];
|
||||||
Assert(connection != NULL);
|
Assert(connection != NULL);
|
||||||
|
|
||||||
cancelObject = PQgetCancel(connection);
|
cancelObject = PQgetCancel(connection->pgConn);
|
||||||
|
|
||||||
cancelSent = PQcancel(cancelObject, errorBuffer, sizeof(errorBuffer));
|
cancelSent = PQcancel(cancelObject, errorBuffer, sizeof(errorBuffer));
|
||||||
if (cancelSent == 0)
|
if (cancelSent == 0)
|
||||||
|
@ -397,7 +358,7 @@ MultiClientCancel(int32 connectionId)
|
||||||
ResultStatus
|
ResultStatus
|
||||||
MultiClientResultStatus(int32 connectionId)
|
MultiClientResultStatus(int32 connectionId)
|
||||||
{
|
{
|
||||||
PGconn *connection = NULL;
|
MultiConnection *connection = NULL;
|
||||||
int consumed = 0;
|
int consumed = 0;
|
||||||
ConnStatusType connStatusType = CONNECTION_OK;
|
ConnStatusType connStatusType = CONNECTION_OK;
|
||||||
ResultStatus resultStatus = CLIENT_INVALID_RESULT_STATUS;
|
ResultStatus resultStatus = CLIENT_INVALID_RESULT_STATUS;
|
||||||
|
@ -406,7 +367,7 @@ MultiClientResultStatus(int32 connectionId)
|
||||||
connection = ClientConnectionArray[connectionId];
|
connection = ClientConnectionArray[connectionId];
|
||||||
Assert(connection != NULL);
|
Assert(connection != NULL);
|
||||||
|
|
||||||
connStatusType = PQstatus(connection);
|
connStatusType = PQstatus(connection->pgConn);
|
||||||
if (connStatusType == CONNECTION_BAD)
|
if (connStatusType == CONNECTION_BAD)
|
||||||
{
|
{
|
||||||
ereport(WARNING, (errmsg("could not maintain connection to worker node")));
|
ereport(WARNING, (errmsg("could not maintain connection to worker node")));
|
||||||
|
@ -414,10 +375,10 @@ MultiClientResultStatus(int32 connectionId)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* consume input to allow status change */
|
/* consume input to allow status change */
|
||||||
consumed = PQconsumeInput(connection);
|
consumed = PQconsumeInput(connection->pgConn);
|
||||||
if (consumed != 0)
|
if (consumed != 0)
|
||||||
{
|
{
|
||||||
int connectionBusy = PQisBusy(connection);
|
int connectionBusy = PQisBusy(connection->pgConn);
|
||||||
if (connectionBusy == 0)
|
if (connectionBusy == 0)
|
||||||
{
|
{
|
||||||
resultStatus = CLIENT_RESULT_READY;
|
resultStatus = CLIENT_RESULT_READY;
|
||||||
|
@ -442,7 +403,7 @@ bool
|
||||||
MultiClientQueryResult(int32 connectionId, void **queryResult, int *rowCount,
|
MultiClientQueryResult(int32 connectionId, void **queryResult, int *rowCount,
|
||||||
int *columnCount)
|
int *columnCount)
|
||||||
{
|
{
|
||||||
PGconn *connection = NULL;
|
MultiConnection *connection = NULL;
|
||||||
PGresult *result = NULL;
|
PGresult *result = NULL;
|
||||||
ConnStatusType connStatusType = CONNECTION_OK;
|
ConnStatusType connStatusType = CONNECTION_OK;
|
||||||
ExecStatusType resultStatus = PGRES_COMMAND_OK;
|
ExecStatusType resultStatus = PGRES_COMMAND_OK;
|
||||||
|
@ -451,14 +412,14 @@ MultiClientQueryResult(int32 connectionId, void **queryResult, int *rowCount,
|
||||||
connection = ClientConnectionArray[connectionId];
|
connection = ClientConnectionArray[connectionId];
|
||||||
Assert(connection != NULL);
|
Assert(connection != NULL);
|
||||||
|
|
||||||
connStatusType = PQstatus(connection);
|
connStatusType = PQstatus(connection->pgConn);
|
||||||
if (connStatusType == CONNECTION_BAD)
|
if (connStatusType == CONNECTION_BAD)
|
||||||
{
|
{
|
||||||
ereport(WARNING, (errmsg("could not maintain connection to worker node")));
|
ereport(WARNING, (errmsg("could not maintain connection to worker node")));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
result = PQgetResult(connection);
|
result = PQgetResult(connection->pgConn);
|
||||||
resultStatus = PQresultStatus(result);
|
resultStatus = PQresultStatus(result);
|
||||||
if (resultStatus == PGRES_TUPLES_OK)
|
if (resultStatus == PGRES_TUPLES_OK)
|
||||||
{
|
{
|
||||||
|
@ -468,7 +429,7 @@ MultiClientQueryResult(int32 connectionId, void **queryResult, int *rowCount,
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
WarnRemoteError(connection, result);
|
ReportResultError(connection, result, WARNING);
|
||||||
PQclear(result);
|
PQclear(result);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
@ -494,7 +455,7 @@ BatchQueryStatus
|
||||||
MultiClientBatchResult(int32 connectionId, void **queryResult, int *rowCount,
|
MultiClientBatchResult(int32 connectionId, void **queryResult, int *rowCount,
|
||||||
int *columnCount)
|
int *columnCount)
|
||||||
{
|
{
|
||||||
PGconn *connection = NULL;
|
MultiConnection *connection = NULL;
|
||||||
PGresult *result = NULL;
|
PGresult *result = NULL;
|
||||||
ConnStatusType connStatusType = CONNECTION_OK;
|
ConnStatusType connStatusType = CONNECTION_OK;
|
||||||
ExecStatusType resultStatus = PGRES_COMMAND_OK;
|
ExecStatusType resultStatus = PGRES_COMMAND_OK;
|
||||||
|
@ -509,14 +470,14 @@ MultiClientBatchResult(int32 connectionId, void **queryResult, int *rowCount,
|
||||||
(*rowCount) = -1;
|
(*rowCount) = -1;
|
||||||
(*columnCount) = -1;
|
(*columnCount) = -1;
|
||||||
|
|
||||||
connStatusType = PQstatus(connection);
|
connStatusType = PQstatus(connection->pgConn);
|
||||||
if (connStatusType == CONNECTION_BAD)
|
if (connStatusType == CONNECTION_BAD)
|
||||||
{
|
{
|
||||||
ereport(WARNING, (errmsg("could not maintain connection to worker node")));
|
ereport(WARNING, (errmsg("could not maintain connection to worker node")));
|
||||||
return CLIENT_BATCH_QUERY_FAILED;
|
return CLIENT_BATCH_QUERY_FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
result = PQgetResult(connection);
|
result = PQgetResult(connection->pgConn);
|
||||||
if (result == NULL)
|
if (result == NULL)
|
||||||
{
|
{
|
||||||
return CLIENT_BATCH_QUERY_DONE;
|
return CLIENT_BATCH_QUERY_DONE;
|
||||||
|
@ -537,7 +498,7 @@ MultiClientBatchResult(int32 connectionId, void **queryResult, int *rowCount,
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
WarnRemoteError(connection, result);
|
ReportResultError(connection, result, WARNING);
|
||||||
PQclear(result);
|
PQclear(result);
|
||||||
queryStatus = CLIENT_BATCH_QUERY_FAILED;
|
queryStatus = CLIENT_BATCH_QUERY_FAILED;
|
||||||
}
|
}
|
||||||
|
@ -576,7 +537,7 @@ MultiClientClearResult(void *queryResult)
|
||||||
QueryStatus
|
QueryStatus
|
||||||
MultiClientQueryStatus(int32 connectionId)
|
MultiClientQueryStatus(int32 connectionId)
|
||||||
{
|
{
|
||||||
PGconn *connection = NULL;
|
MultiConnection *connection = NULL;
|
||||||
PGresult *result = NULL;
|
PGresult *result = NULL;
|
||||||
int tupleCount PG_USED_FOR_ASSERTS_ONLY = 0;
|
int tupleCount PG_USED_FOR_ASSERTS_ONLY = 0;
|
||||||
bool copyResults = false;
|
bool copyResults = false;
|
||||||
|
@ -588,7 +549,7 @@ MultiClientQueryStatus(int32 connectionId)
|
||||||
connection = ClientConnectionArray[connectionId];
|
connection = ClientConnectionArray[connectionId];
|
||||||
Assert(connection != NULL);
|
Assert(connection != NULL);
|
||||||
|
|
||||||
connStatusType = PQstatus(connection);
|
connStatusType = PQstatus(connection->pgConn);
|
||||||
if (connStatusType == CONNECTION_BAD)
|
if (connStatusType == CONNECTION_BAD)
|
||||||
{
|
{
|
||||||
ereport(WARNING, (errmsg("could not maintain connection to worker node")));
|
ereport(WARNING, (errmsg("could not maintain connection to worker node")));
|
||||||
|
@ -600,7 +561,7 @@ MultiClientQueryStatus(int32 connectionId)
|
||||||
* isn't ready yet (the caller didn't wait for the connection to be ready),
|
* isn't ready yet (the caller didn't wait for the connection to be ready),
|
||||||
* we will block on this call.
|
* we will block on this call.
|
||||||
*/
|
*/
|
||||||
result = PQgetResult(connection);
|
result = PQgetResult(connection->pgConn);
|
||||||
resultStatus = PQresultStatus(result);
|
resultStatus = PQresultStatus(result);
|
||||||
|
|
||||||
if (resultStatus == PGRES_COMMAND_OK)
|
if (resultStatus == PGRES_COMMAND_OK)
|
||||||
|
@ -631,7 +592,7 @@ MultiClientQueryStatus(int32 connectionId)
|
||||||
copyResults = true;
|
copyResults = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
WarnRemoteError(connection, result);
|
ReportResultError(connection, result, WARNING);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* clear the result object */
|
/* clear the result object */
|
||||||
|
@ -654,7 +615,7 @@ MultiClientQueryStatus(int32 connectionId)
|
||||||
CopyStatus
|
CopyStatus
|
||||||
MultiClientCopyData(int32 connectionId, int32 fileDescriptor)
|
MultiClientCopyData(int32 connectionId, int32 fileDescriptor)
|
||||||
{
|
{
|
||||||
PGconn *connection = NULL;
|
MultiConnection *connection = NULL;
|
||||||
char *receiveBuffer = NULL;
|
char *receiveBuffer = NULL;
|
||||||
int consumed = 0;
|
int consumed = 0;
|
||||||
int receiveLength = 0;
|
int receiveLength = 0;
|
||||||
|
@ -669,7 +630,7 @@ MultiClientCopyData(int32 connectionId, int32 fileDescriptor)
|
||||||
* Consume input to handle the case where previous copy operation might have
|
* Consume input to handle the case where previous copy operation might have
|
||||||
* received zero bytes.
|
* received zero bytes.
|
||||||
*/
|
*/
|
||||||
consumed = PQconsumeInput(connection);
|
consumed = PQconsumeInput(connection->pgConn);
|
||||||
if (consumed == 0)
|
if (consumed == 0)
|
||||||
{
|
{
|
||||||
ereport(WARNING, (errmsg("could not read data from worker node")));
|
ereport(WARNING, (errmsg("could not read data from worker node")));
|
||||||
|
@ -677,7 +638,7 @@ MultiClientCopyData(int32 connectionId, int32 fileDescriptor)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* receive copy data message in an asynchronous manner */
|
/* receive copy data message in an asynchronous manner */
|
||||||
receiveLength = PQgetCopyData(connection, &receiveBuffer, asynchronous);
|
receiveLength = PQgetCopyData(connection->pgConn, &receiveBuffer, asynchronous);
|
||||||
while (receiveLength > 0)
|
while (receiveLength > 0)
|
||||||
{
|
{
|
||||||
/* received copy data; append these data to file */
|
/* received copy data; append these data to file */
|
||||||
|
@ -698,7 +659,7 @@ MultiClientCopyData(int32 connectionId, int32 fileDescriptor)
|
||||||
|
|
||||||
PQfreemem(receiveBuffer);
|
PQfreemem(receiveBuffer);
|
||||||
|
|
||||||
receiveLength = PQgetCopyData(connection, &receiveBuffer, asynchronous);
|
receiveLength = PQgetCopyData(connection->pgConn, &receiveBuffer, asynchronous);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* we now check the last received length returned by copy data */
|
/* we now check the last received length returned by copy data */
|
||||||
|
@ -710,7 +671,7 @@ MultiClientCopyData(int32 connectionId, int32 fileDescriptor)
|
||||||
else if (receiveLength == -1)
|
else if (receiveLength == -1)
|
||||||
{
|
{
|
||||||
/* received copy done message */
|
/* received copy done message */
|
||||||
PGresult *result = PQgetResult(connection);
|
PGresult *result = PQgetResult(connection->pgConn);
|
||||||
ExecStatusType resultStatus = PQresultStatus(result);
|
ExecStatusType resultStatus = PQresultStatus(result);
|
||||||
|
|
||||||
if (resultStatus == PGRES_COMMAND_OK)
|
if (resultStatus == PGRES_COMMAND_OK)
|
||||||
|
@ -721,7 +682,7 @@ MultiClientCopyData(int32 connectionId, int32 fileDescriptor)
|
||||||
{
|
{
|
||||||
copyStatus = CLIENT_COPY_FAILED;
|
copyStatus = CLIENT_COPY_FAILED;
|
||||||
|
|
||||||
WarnRemoteError(connection, result);
|
ReportResultError(connection, result, WARNING);
|
||||||
}
|
}
|
||||||
|
|
||||||
PQclear(result);
|
PQclear(result);
|
||||||
|
@ -731,7 +692,7 @@ MultiClientCopyData(int32 connectionId, int32 fileDescriptor)
|
||||||
/* received an error */
|
/* received an error */
|
||||||
copyStatus = CLIENT_COPY_FAILED;
|
copyStatus = CLIENT_COPY_FAILED;
|
||||||
|
|
||||||
WarnRemoteError(connection, NULL);
|
ReportConnectionError(connection, WARNING);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* if copy out completed, make sure we drain all results from libpq */
|
/* if copy out completed, make sure we drain all results from libpq */
|
||||||
|
@ -794,7 +755,7 @@ void
|
||||||
MultiClientRegisterWait(WaitInfo *waitInfo, TaskExecutionStatus executionStatus,
|
MultiClientRegisterWait(WaitInfo *waitInfo, TaskExecutionStatus executionStatus,
|
||||||
int32 connectionId)
|
int32 connectionId)
|
||||||
{
|
{
|
||||||
PGconn *connection = NULL;
|
MultiConnection *connection = NULL;
|
||||||
struct pollfd *pollfd = NULL;
|
struct pollfd *pollfd = NULL;
|
||||||
|
|
||||||
Assert(waitInfo->registeredWaiters < waitInfo->maxWaiters);
|
Assert(waitInfo->registeredWaiters < waitInfo->maxWaiters);
|
||||||
|
@ -812,7 +773,7 @@ MultiClientRegisterWait(WaitInfo *waitInfo, TaskExecutionStatus executionStatus,
|
||||||
|
|
||||||
connection = ClientConnectionArray[connectionId];
|
connection = ClientConnectionArray[connectionId];
|
||||||
pollfd = &waitInfo->pollfds[waitInfo->registeredWaiters];
|
pollfd = &waitInfo->pollfds[waitInfo->registeredWaiters];
|
||||||
pollfd->fd = PQsocket(connection);
|
pollfd->fd = PQsocket(connection->pgConn);
|
||||||
if (executionStatus == TASK_STATUS_SOCKET_READ)
|
if (executionStatus == TASK_STATUS_SOCKET_READ)
|
||||||
{
|
{
|
||||||
pollfd->events = POLLERR | POLLIN;
|
pollfd->events = POLLERR | POLLIN;
|
||||||
|
@ -904,13 +865,13 @@ MultiClientWait(WaitInfo *waitInfo)
|
||||||
* query.
|
* query.
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
ClearRemainingResults(PGconn *connection)
|
ClearRemainingResults(MultiConnection *connection)
|
||||||
{
|
{
|
||||||
PGresult *result = PQgetResult(connection);
|
PGresult *result = PQgetResult(connection->pgConn);
|
||||||
while (result != NULL)
|
while (result != NULL)
|
||||||
{
|
{
|
||||||
PQclear(result);
|
PQclear(result);
|
||||||
result = PQgetResult(connection);
|
result = PQgetResult(connection->pgConn);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -921,7 +882,8 @@ ClearRemainingResults(PGconn *connection)
|
||||||
* and libpq_select() at libpqwalreceiver.c.
|
* and libpq_select() at libpqwalreceiver.c.
|
||||||
*/
|
*/
|
||||||
static bool
|
static bool
|
||||||
ClientConnectionReady(PGconn *connection, PostgresPollingStatusType pollingStatus)
|
ClientConnectionReady(MultiConnection *connection,
|
||||||
|
PostgresPollingStatusType pollingStatus)
|
||||||
{
|
{
|
||||||
bool clientConnectionReady = false;
|
bool clientConnectionReady = false;
|
||||||
int pollResult = 0;
|
int pollResult = 0;
|
||||||
|
@ -942,7 +904,7 @@ ClientConnectionReady(PGconn *connection, PostgresPollingStatusType pollingStatu
|
||||||
pollEventMask = POLLERR | POLLOUT;
|
pollEventMask = POLLERR | POLLOUT;
|
||||||
}
|
}
|
||||||
|
|
||||||
pollFileDescriptor.fd = PQsocket(connection);
|
pollFileDescriptor.fd = PQsocket(connection->pgConn);
|
||||||
pollFileDescriptor.events = pollEventMask;
|
pollFileDescriptor.events = pollEventMask;
|
||||||
pollFileDescriptor.revents = 0;
|
pollFileDescriptor.revents = 0;
|
||||||
|
|
||||||
|
|
|
@ -15,10 +15,8 @@
|
||||||
#define MULTI_CLIENT_EXECUTOR_H
|
#define MULTI_CLIENT_EXECUTOR_H
|
||||||
|
|
||||||
#define INVALID_CONNECTION_ID -1 /* identifies an invalid connection */
|
#define INVALID_CONNECTION_ID -1 /* identifies an invalid connection */
|
||||||
#define CLIENT_CONNECT_TIMEOUT 5 /* connection timeout in seconds */
|
|
||||||
#define MAX_CONNECTION_COUNT 2048 /* simultaneous client connection count */
|
#define MAX_CONNECTION_COUNT 2048 /* simultaneous client connection count */
|
||||||
#define STRING_BUFFER_SIZE 1024 /* buffer size for character arrays */
|
#define STRING_BUFFER_SIZE 1024 /* buffer size for character arrays */
|
||||||
#define CONN_INFO_TEMPLATE "host=%s port=%u dbname=%s user=%s connect_timeout=%u"
|
|
||||||
|
|
||||||
|
|
||||||
/* Enumeration to track one client connection's status */
|
/* Enumeration to track one client connection's status */
|
||||||
|
|
Loading…
Reference in New Issue