mirror of https://github.com/citusdata/citus.git
Handle errors that are discovered during abort
parent
d9c5c4a8f1
commit
6051aae56e
|
@ -58,7 +58,7 @@ IsResponseOK(PGresult *result)
|
||||||
* ForgetResults clears a connection from pending activity.
|
* ForgetResults clears a connection from pending activity.
|
||||||
*
|
*
|
||||||
* Note that this might require network IO. If that's not acceptable, use
|
* Note that this might require network IO. If that's not acceptable, use
|
||||||
* NonblockingForgetResults().
|
* ClearResultsIfReady().
|
||||||
*
|
*
|
||||||
* ClearResults is variant of this function which can also raise errors.
|
* ClearResults is variant of this function which can also raise errors.
|
||||||
*/
|
*/
|
||||||
|
@ -93,7 +93,7 @@ ForgetResults(MultiConnection *connection)
|
||||||
* is marked critical.
|
* is marked critical.
|
||||||
*
|
*
|
||||||
* Note that this might require network IO. If that's not acceptable, use
|
* Note that this might require network IO. If that's not acceptable, use
|
||||||
* NonblockingForgetResults().
|
* ClearResultsIfReady().
|
||||||
*/
|
*/
|
||||||
bool
|
bool
|
||||||
ClearResults(MultiConnection *connection, bool raiseErrors)
|
ClearResults(MultiConnection *connection, bool raiseErrors)
|
||||||
|
@ -133,12 +133,12 @@ ClearResults(MultiConnection *connection, bool raiseErrors)
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* NonblockingForgetResults clears a connection from pending activity if doing
|
* ClearResultsIfReady clears a connection from pending activity if doing
|
||||||
* so does not require network IO. Returns true if successful, false
|
* so does not require network IO. Returns true if successful, false
|
||||||
* otherwise.
|
* otherwise.
|
||||||
*/
|
*/
|
||||||
bool
|
bool
|
||||||
NonblockingForgetResults(MultiConnection *connection)
|
ClearResultsIfReady(MultiConnection *connection)
|
||||||
{
|
{
|
||||||
PGconn *pgConn = connection->pgConn;
|
PGconn *pgConn = connection->pgConn;
|
||||||
|
|
||||||
|
@ -152,6 +152,7 @@ NonblockingForgetResults(MultiConnection *connection)
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
PGresult *result = NULL;
|
PGresult *result = NULL;
|
||||||
|
ExecStatusType resultStatus;
|
||||||
|
|
||||||
/* just in case there's a lot of results */
|
/* just in case there's a lot of results */
|
||||||
CHECK_FOR_INTERRUPTS();
|
CHECK_FOR_INTERRUPTS();
|
||||||
|
@ -182,19 +183,31 @@ NonblockingForgetResults(MultiConnection *connection)
|
||||||
}
|
}
|
||||||
|
|
||||||
result = PQgetResult(pgConn);
|
result = PQgetResult(pgConn);
|
||||||
if (PQresultStatus(result) == PGRES_COPY_IN ||
|
if (result == NULL)
|
||||||
PQresultStatus(result) == PGRES_COPY_OUT)
|
{
|
||||||
|
/* no more results available */
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
resultStatus = PQresultStatus(result);
|
||||||
|
|
||||||
|
/* only care about the status, can clear now */
|
||||||
|
PQclear(result);
|
||||||
|
|
||||||
|
if (resultStatus == PGRES_COPY_IN || resultStatus == PGRES_COPY_OUT)
|
||||||
{
|
{
|
||||||
/* in copy, can't reliably recover without blocking */
|
/* in copy, can't reliably recover without blocking */
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (result == NULL)
|
if (!(resultStatus == PGRES_SINGLE_TUPLE || resultStatus == PGRES_TUPLES_OK ||
|
||||||
|
resultStatus == PGRES_COMMAND_OK))
|
||||||
{
|
{
|
||||||
return true;
|
/* an error occcurred just when we were aborting */
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
PQclear(result);
|
/* check if there are more results to consume */
|
||||||
}
|
}
|
||||||
|
|
||||||
pg_unreachable();
|
pg_unreachable();
|
||||||
|
|
|
@ -382,7 +382,14 @@ StartRemoteTransactionAbort(MultiConnection *connection)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (!NonblockingForgetResults(connection))
|
/*
|
||||||
|
* In case of a cancellation, the connection might still be working
|
||||||
|
* on some commands. Try to consume the results such that the
|
||||||
|
* connection can be reused, but do not want to wait for commands
|
||||||
|
* to finish. Instead we just close the connection if the command
|
||||||
|
* is still busy.
|
||||||
|
*/
|
||||||
|
if (!ClearResultsIfReady(connection))
|
||||||
{
|
{
|
||||||
ShutdownConnection(connection);
|
ShutdownConnection(connection);
|
||||||
|
|
||||||
|
|
|
@ -27,7 +27,7 @@ extern bool LogRemoteCommands;
|
||||||
extern bool IsResponseOK(struct pg_result *result);
|
extern bool IsResponseOK(struct pg_result *result);
|
||||||
extern void ForgetResults(MultiConnection *connection);
|
extern void ForgetResults(MultiConnection *connection);
|
||||||
extern bool ClearResults(MultiConnection *connection, bool raiseErrors);
|
extern bool ClearResults(MultiConnection *connection, bool raiseErrors);
|
||||||
extern bool NonblockingForgetResults(MultiConnection *connection);
|
extern bool ClearResultsIfReady(MultiConnection *connection);
|
||||||
extern bool SqlStateMatchesCategory(char *sqlStateString, int category);
|
extern bool SqlStateMatchesCategory(char *sqlStateString, int category);
|
||||||
|
|
||||||
/* report errors & warnings */
|
/* report errors & warnings */
|
||||||
|
|
Loading…
Reference in New Issue