mirror of
https://github.com/postgres/postgres.git
synced 2025-06-11 20:28:21 +03:00
libpq-be-fe-helpers.h: wrap new cancel APIs
Commit 61461a300c
introduced new functions to libpq for cancelling
queries. This commit introduces a helper function that backend-side
libraries and extensions can use to invoke those. This function takes a
timeout and can itself be interrupted while it is waiting for a cancel
request to be sent and processed, instead of being blocked.
This replaces the usage of the old functions in postgres_fdw and dblink.
Finally, it also adds some test coverage for the cancel support in
postgres_fdw.
Author: Jelte Fennema-Nio <postgres@jeltef.nl>
Discussion: https://postgr.es/m/CAGECzQT_VgOWWENUqvUV9xQmbaCyXjtRRAYO8W07oqashk_N+g@mail.gmail.com
This commit is contained in:
@ -133,7 +133,7 @@ static void pgfdw_inval_callback(Datum arg, int cacheid, uint32 hashvalue);
|
||||
static void pgfdw_reject_incomplete_xact_state_change(ConnCacheEntry *entry);
|
||||
static void pgfdw_reset_xact_state(ConnCacheEntry *entry, bool toplevel);
|
||||
static bool pgfdw_cancel_query(PGconn *conn);
|
||||
static bool pgfdw_cancel_query_begin(PGconn *conn);
|
||||
static bool pgfdw_cancel_query_begin(PGconn *conn, TimestampTz endtime);
|
||||
static bool pgfdw_cancel_query_end(PGconn *conn, TimestampTz endtime,
|
||||
bool consume_input);
|
||||
static bool pgfdw_exec_cleanup_query(PGconn *conn, const char *query,
|
||||
@ -1315,36 +1315,31 @@ pgfdw_cancel_query(PGconn *conn)
|
||||
endtime = TimestampTzPlusMilliseconds(GetCurrentTimestamp(),
|
||||
CONNECTION_CLEANUP_TIMEOUT);
|
||||
|
||||
if (!pgfdw_cancel_query_begin(conn))
|
||||
if (!pgfdw_cancel_query_begin(conn, endtime))
|
||||
return false;
|
||||
return pgfdw_cancel_query_end(conn, endtime, false);
|
||||
}
|
||||
|
||||
/*
|
||||
* Submit a cancel request to the given connection, waiting only until
|
||||
* the given time.
|
||||
*
|
||||
* We sleep interruptibly until we receive confirmation that the cancel
|
||||
* request has been accepted, and if it is, return true; if the timeout
|
||||
* lapses without that, or the request fails for whatever reason, return
|
||||
* false.
|
||||
*/
|
||||
static bool
|
||||
pgfdw_cancel_query_begin(PGconn *conn)
|
||||
pgfdw_cancel_query_begin(PGconn *conn, TimestampTz endtime)
|
||||
{
|
||||
PGcancel *cancel;
|
||||
char errbuf[256];
|
||||
char *errormsg = libpqsrv_cancel(conn, endtime);
|
||||
|
||||
/*
|
||||
* Issue cancel request. Unfortunately, there's no good way to limit the
|
||||
* amount of time that we might block inside PQgetCancel().
|
||||
*/
|
||||
if ((cancel = PQgetCancel(conn)))
|
||||
{
|
||||
if (!PQcancel(cancel, errbuf, sizeof(errbuf)))
|
||||
{
|
||||
ereport(WARNING,
|
||||
(errcode(ERRCODE_CONNECTION_FAILURE),
|
||||
errmsg("could not send cancel request: %s",
|
||||
errbuf)));
|
||||
PQfreeCancel(cancel);
|
||||
return false;
|
||||
}
|
||||
PQfreeCancel(cancel);
|
||||
}
|
||||
if (errormsg != NULL)
|
||||
ereport(WARNING,
|
||||
errcode(ERRCODE_CONNECTION_FAILURE),
|
||||
errmsg("could not send cancel request: %s", errormsg));
|
||||
|
||||
return true;
|
||||
return errormsg == NULL;
|
||||
}
|
||||
|
||||
static bool
|
||||
@ -1685,7 +1680,11 @@ pgfdw_abort_cleanup_begin(ConnCacheEntry *entry, bool toplevel,
|
||||
*/
|
||||
if (PQtransactionStatus(entry->conn) == PQTRANS_ACTIVE)
|
||||
{
|
||||
if (!pgfdw_cancel_query_begin(entry->conn))
|
||||
TimestampTz endtime;
|
||||
|
||||
endtime = TimestampTzPlusMilliseconds(GetCurrentTimestamp(),
|
||||
CONNECTION_CLEANUP_TIMEOUT);
|
||||
if (!pgfdw_cancel_query_begin(entry->conn, endtime))
|
||||
return false; /* Unable to cancel running query */
|
||||
*cancel_requested = lappend(*cancel_requested, entry);
|
||||
}
|
||||
|
Reference in New Issue
Block a user