Add NonblockingForgetResults().

This is very similar to ForgetResults() except that no network IO is
performed. Primarily useful in error handling cases.
pull/1650/head
Andres Freund 2017-06-30 18:20:54 -07:00 committed by Metin Doslu
parent c8f7c7fc59
commit 25cabe634e
2 changed files with 71 additions and 2 deletions

View File

@ -46,8 +46,8 @@ IsResponseOK(PGresult *result)
/* /*
* ForgetResults clears a connection from pending activity. * ForgetResults clears a connection from pending activity.
* *
* XXX: In the future it might be a good idea to use use PQcancel() if results * Note that this might require network IO. If that's not acceptable, use
* would require network IO. * NonblockingForgetResults().
*/ */
void void
ForgetResults(MultiConnection *connection) ForgetResults(MultiConnection *connection)
@ -73,6 +73,74 @@ ForgetResults(MultiConnection *connection)
} }
/*
* NonblockingForgetResults clears a connection from pending activity if doing
* so does not require network IO. Returns true if successful, false
* otherwise.
*/
bool
NonblockingForgetResults(MultiConnection *connection)
{
PGconn *pgConn = connection->pgConn;
if (PQstatus(pgConn) != CONNECTION_OK)
{
return false;
}
Assert(PQisnonblocking(pgConn));
while (true)
{
PGresult *result = NULL;
/* just in case there's a lot of results */
CHECK_FOR_INTERRUPTS();
/*
* If busy, there might still be results already received and buffered
* by the OS. As connection is in non-blocking mode, we can check for
* that without blocking.
*/
if (PQisBusy(pgConn))
{
if (PQflush(pgConn) == -1)
{
/* write failed */
return false;
}
if (PQconsumeInput(pgConn) == 0)
{
/* some low-level failure */
return false;
}
}
/* clearing would require blocking IO, return */
if (PQisBusy(pgConn))
{
return false;
}
result = PQgetResult(pgConn);
if (PQresultStatus(result) == PGRES_COPY_IN)
{
/* in copy, can't reliably recover without blocking */
return false;
}
if (result == NULL)
{
return true;
}
PQclear(result);
}
pg_unreachable();
}
/* /*
* SqlStateMatchesCategory returns true if the given sql state (which may be * SqlStateMatchesCategory returns true if the given sql state (which may be
* NULL if unknown) is in the given error category. Note that we use * NULL if unknown) is in the given error category. Note that we use

View File

@ -26,6 +26,7 @@ extern bool LogRemoteCommands;
/* simple helpers */ /* simple helpers */
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 NonblockingForgetResults(MultiConnection *connection);
extern bool SqlStateMatchesCategory(char *sqlStateString, int category); extern bool SqlStateMatchesCategory(char *sqlStateString, int category);
/* report errors & warnings */ /* report errors & warnings */