From a04bb65f70dafdf462e0478ad19e6de56df89bfc Mon Sep 17 00:00:00 2001 From: Robert Haas Date: Fri, 17 Jul 2015 09:12:03 -0400 Subject: Add new function pg_notification_queue_usage. This tells you what fraction of NOTIFY's queue is currently filled. Brendan Jurd, reviewed by Merlin Moncure and Gurjeet Singh. A few further tweaks by me. --- src/backend/commands/async.c | 50 ++++++++++++++++++++++++++++++++++---------- 1 file changed, 39 insertions(+), 11 deletions(-) (limited to 'src/backend/commands/async.c') diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index 2826b7e43c4..3b71174b826 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -371,6 +371,7 @@ static bool asyncQueueIsFull(void); static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); +static double asyncQueueUsage(void); static void asyncQueueFillWarning(void); static bool SignalBackends(void); static void asyncQueueReadAllNotifications(void); @@ -1362,26 +1363,37 @@ asyncQueueAddEntries(ListCell *nextNotify) } /* - * Check whether the queue is at least half full, and emit a warning if so. - * - * This is unlikely given the size of the queue, but possible. - * The warnings show up at most once every QUEUE_FULL_WARN_INTERVAL. + * SQL function to return the fraction of the notification queue currently + * occupied. + */ +Datum +pg_notification_queue_usage(PG_FUNCTION_ARGS) +{ + double usage; + + LWLockAcquire(AsyncQueueLock, LW_SHARED); + usage = asyncQueueUsage(); + LWLockRelease(AsyncQueueLock); + + PG_RETURN_FLOAT8(usage); +} + +/* + * Return the fraction of the queue that is currently occupied. * - * Caller must hold exclusive AsyncQueueLock. + * The caller must hold AysncQueueLock in (at least) shared mode. */ -static void -asyncQueueFillWarning(void) +static double +asyncQueueUsage(void) { int headPage = QUEUE_POS_PAGE(QUEUE_HEAD); int tailPage = QUEUE_POS_PAGE(QUEUE_TAIL); int occupied; - double fillDegree; - TimestampTz t; occupied = headPage - tailPage; if (occupied == 0) - return; /* fast exit for common case */ + return (double) 0; /* fast exit for common case */ if (occupied < 0) { @@ -1389,8 +1401,24 @@ asyncQueueFillWarning(void) occupied += QUEUE_MAX_PAGE + 1; } - fillDegree = (double) occupied / (double) ((QUEUE_MAX_PAGE + 1) / 2); + return (double) occupied / (double) ((QUEUE_MAX_PAGE + 1) / 2); +} + +/* + * Check whether the queue is at least half full, and emit a warning if so. + * + * This is unlikely given the size of the queue, but possible. + * The warnings show up at most once every QUEUE_FULL_WARN_INTERVAL. + * + * Caller must hold exclusive AsyncQueueLock. + */ +static void +asyncQueueFillWarning(void) +{ + double fillDegree; + TimestampTz t; + fillDegree = asyncQueueUsage(); if (fillDegree < 0.5) return; -- cgit v1.2.3