Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ PostgreSQL installation. It is available from
[github](https://github.com/postgrespro/pg_wait_sampling)
under the same license as
[PostgreSQL](http://www.postgresql.org/about/licence/)
and supports PostgreSQL 13+.
and supports PostgreSQL 14+.

Installation
------------
Expand All @@ -62,10 +62,10 @@ repository: https://download.postgresql.org/pub/repos/
Manual build
------------

`pg_wait_sampling` is PostgreSQL extension which requires PostgreSQL 13 or
`pg_wait_sampling` is PostgreSQL extension which requires PostgreSQL 14 or
higher. Before build and install you should ensure following:

* PostgreSQL version is 13 or higher.
* PostgreSQL version is 14 or higher.
* You have development package of PostgreSQL installed or you built
PostgreSQL from source.
* Your PATH variable is configured so that `pg_config` command available, or
Expand Down
97 changes: 31 additions & 66 deletions pg_wait_sampling.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
* pg_wait_sampling.c
* Track information about wait events.
*
* Copyright (c) 2015-2025, Postgres Professional
* Copyright (c) 2015-2026, Postgres Professional
*
* IDENTIFICATION
* contrib/pg_wait_sampling/pg_wait_sampling.c
Expand Down Expand Up @@ -75,9 +75,7 @@ static shmem_request_hook_type prev_shmem_request_hook = NULL;
static shmem_startup_hook_type prev_shmem_startup_hook = NULL;
static PGPROC *search_proc(int backendPid);
static PlannedStmt *pgws_planner_hook(Query *parse,
#if PG_VERSION_NUM >= 130000
const char *query_string,
#endif
int cursorOptions, ParamListInfo boundParams
#if PG_VERSION_NUM >= 190000
, ExplainState *es
Expand All @@ -87,26 +85,20 @@ static void pgws_ExecutorStart(QueryDesc *queryDesc, int eflags);
static void pgws_ExecutorRun(QueryDesc *queryDesc,
ScanDirection direction,
uint64 count
#if PG_VERSION_NUM >= 100000 && PG_VERSION_NUM < 180000
#if PG_VERSION_NUM < 180000
,bool execute_once
#endif
);
static void pgws_ExecutorFinish(QueryDesc *queryDesc);
static void pgws_ExecutorEnd(QueryDesc *queryDesc);
static void pgws_ProcessUtility(PlannedStmt *pstmt,
const char *queryString,
#if PG_VERSION_NUM >= 140000
bool readOnlyTree,
#endif
ProcessUtilityContext context,
ParamListInfo params,
QueryEnvironment *queryEnv,
DestReceiver *dest,
#if PG_VERSION_NUM >= 130000
QueryCompletion *qc
#else
char *completionTag
#endif
);

/*---- GUC variables ----*/
Expand Down Expand Up @@ -654,6 +646,16 @@ receive_array(SHMRequest request, Size item_size, Size *count)
char *ptr;
MemoryContext oldctx;

/* Check that the collector was started to avoid NULL pointer dereference */
if (!pgws_collector_hdr->latch)
ereport(ERROR, (errcode(ERRCODE_INTERNAL_ERROR),
errmsg("pg_wait_sampling collector wasn't started")));

/* Check that the collector exists to avoid getting stuck in shm_mq_receive */
if (pgws_collector_hdr->latch->owner_pid == 0)
ereport(ERROR, (errcode(ERRCODE_INTERNAL_ERROR),
errmsg("pg_wait_sampling collector doesn't exist")));

/* Ensure nobody else trying to send request to queue */
pgws_init_lock_tag(&queueTag, PGWS_QUEUE_LOCK);
LockAcquire(&queueTag, ExclusiveLock, false, false);
Expand All @@ -664,19 +666,6 @@ receive_array(SHMRequest request, Size item_size, Size *count)
pgws_collector_hdr->request = request;
LockRelease(&collectorTag, ExclusiveLock, false);

/*
* Check that the collector was started to avoid NULL
* pointer dereference.
*/
if (!pgws_collector_hdr->latch)
ereport(ERROR, (errcode(ERRCODE_INTERNAL_ERROR),
errmsg("pg_wait_sampling collector wasn't started")));

/* Check that the collector exists to avoid getting stuck in shm_mq_receive */
if (pgws_collector_hdr->latch->owner_pid == 0)
ereport(ERROR, (errcode(ERRCODE_INTERNAL_ERROR),
errmsg("pg_wait_sampling collector doesn't exist")));

SetLatch(pgws_collector_hdr->latch);

shm_mq_set_receiver(recv_mq, MyProc);
Expand Down Expand Up @@ -837,6 +826,16 @@ pg_wait_sampling_reset_profile(PG_FUNCTION_ARGS)

check_shmem();

/* Check that the collector was started to avoid NULL pointer dereference */
if (!pgws_collector_hdr->latch)
ereport(ERROR, (errcode(ERRCODE_INTERNAL_ERROR),
errmsg("pg_wait_sampling collector wasn't started")));

/* Check that the collector exists to avoid setting pgws_collector_hdr->request */
if (pgws_collector_hdr->latch->owner_pid == 0)
ereport(ERROR, (errcode(ERRCODE_INTERNAL_ERROR),
errmsg("pg_wait_sampling collector doesn't exist")));

pgws_init_lock_tag(&queueTag, PGWS_QUEUE_LOCK);

LockAcquire(&queueTag, ExclusiveLock, false, false);
Expand All @@ -846,14 +845,6 @@ pg_wait_sampling_reset_profile(PG_FUNCTION_ARGS)
pgws_collector_hdr->request = PROFILE_RESET;
LockRelease(&collectorTag, ExclusiveLock, false);

/*
* Check that the collector was started to avoid NULL
* pointer dereference.
*/
if (!pgws_collector_hdr->latch)
ereport(ERROR, (errcode(ERRCODE_INTERNAL_ERROR),
errmsg("pg_wait_sampling collector wasn't started")));

SetLatch(pgws_collector_hdr->latch);

LockRelease(&queueTag, ExclusiveLock, false);
Expand Down Expand Up @@ -959,9 +950,7 @@ pg_wait_sampling_get_history(PG_FUNCTION_ARGS)
*/
static PlannedStmt *
pgws_planner_hook(Query *parse,
#if PG_VERSION_NUM >= 130000
const char *query_string,
#endif
int cursorOptions,
ParamListInfo boundParams
#if PG_VERSION_NUM >= 190000
Expand All @@ -985,19 +974,15 @@ pgws_planner_hook(Query *parse,
/* Invoke original hook if needed */
if (planner_hook_next)
result = planner_hook_next(parse,
#if PG_VERSION_NUM >= 130000
query_string,
#endif
cursorOptions, boundParams
#if PG_VERSION_NUM >= 190000
, es
#endif
);
else
result = standard_planner(parse,
#if PG_VERSION_NUM >= 130000
query_string,
#endif
cursorOptions, boundParams
#if PG_VERSION_NUM >= 190000
, es
Expand Down Expand Up @@ -1043,7 +1028,7 @@ static void
pgws_ExecutorRun(QueryDesc *queryDesc,
ScanDirection direction,
uint64 count
#if PG_VERSION_NUM >= 100000 && PG_VERSION_NUM < 180000
#if PG_VERSION_NUM < 180000
,bool execute_once
#endif
)
Expand All @@ -1055,16 +1040,16 @@ pgws_ExecutorRun(QueryDesc *queryDesc,
PG_TRY();
{
if (prev_ExecutorRun)
#if PG_VERSION_NUM >= 100000 && PG_VERSION_NUM < 180000
prev_ExecutorRun(queryDesc, direction, count, execute_once);
#else
#if PG_VERSION_NUM >= 180000
prev_ExecutorRun(queryDesc, direction, count);
#else
prev_ExecutorRun(queryDesc, direction, count, execute_once);
#endif
else
#if PG_VERSION_NUM >= 100000 && PG_VERSION_NUM < 180000
standard_ExecutorRun(queryDesc, direction, count, execute_once);
#else
#if PG_VERSION_NUM >= 180000
standard_ExecutorRun(queryDesc, direction, count);
#else
standard_ExecutorRun(queryDesc, direction, count, execute_once);
#endif
nesting_level--;
if (nesting_level == 0)
Expand Down Expand Up @@ -1132,18 +1117,12 @@ pgws_ExecutorEnd(QueryDesc *queryDesc)
static void
pgws_ProcessUtility(PlannedStmt *pstmt,
const char *queryString,
#if PG_VERSION_NUM >= 140000
bool readOnlyTree,
#endif
ProcessUtilityContext context,
ParamListInfo params,
QueryEnvironment *queryEnv,
DestReceiver *dest,
#if PG_VERSION_NUM >= 130000
QueryCompletion *qc
#else
char *completionTag
#endif
)
{
int i = MyProc - ProcGlobal->allProcs;
Expand All @@ -1160,30 +1139,16 @@ pgws_ProcessUtility(PlannedStmt *pstmt,
{
if (prev_ProcessUtility)
prev_ProcessUtility(pstmt, queryString,
#if PG_VERSION_NUM >= 140000
readOnlyTree,
#endif
context, params, queryEnv,
dest,
#if PG_VERSION_NUM >= 130000
qc
#else
completionTag
#endif
);
qc);
else
standard_ProcessUtility(pstmt, queryString,
#if PG_VERSION_NUM >= 140000
readOnlyTree,
#endif
context, params, queryEnv,
dest,
#if PG_VERSION_NUM >= 130000
qc
#else
completionTag
#endif
);
qc);
nesting_level--;
if (nesting_level == 0)
pgws_proc_queryids[i] = UINT64CONST(0);
Expand Down
Loading