From 38e5d3b7f81eb56951b279e3516e3612f63891e9 Mon Sep 17 00:00:00 2001 From: Alexey Kondratov Date: Wed, 11 Nov 2020 13:39:40 +0300 Subject: [PATCH 1/7] Bump PGXN release to 1.1.2 --- META.json | 4 ++-- Makefile | 7 ++++--- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/META.json b/META.json index 2d4ac16..4bdadfe 100644 --- a/META.json +++ b/META.json @@ -2,7 +2,7 @@ "name": "pg_wait_sampling", "abstract": "Sampling based statistics of wait events", "description": "pg_wait_sampling provides functions for detailed per backend and per query statistics about PostgreSQL wait events", - "version": "1.1.1", + "version": "1.1.2", "maintainer": [ "Alexander Korotkov ", "Ildus Kurbangaliev " @@ -21,7 +21,7 @@ "pg_wait_sampling": { "file": "pg_wait_sampling--1.1.sql", "docfile": "README.md", - "version": "1.1.1", + "version": "1.1.2", "abstract": "Sampling based statistics of wait events" } }, diff --git a/Makefile b/Makefile index 8cd4d9a..65a54e3 100644 --- a/Makefile +++ b/Makefile @@ -28,10 +28,11 @@ $(EXTENSION)--$(EXTVERSION).sql: setup.sql cat $^ > $@ # Prepare the package for PGXN submission -package: dist dist/$(EXTENSION)-$(EXTVERSION).zip +DISTVERSION := $(shell git tag -l | tail -n 1 | cut -d 'v' -f 2) +package: dist dist/$(EXTENSION)-$(DISTVERSION).zip dist: mkdir -p dist -dist/$(EXTENSION)-$(EXTVERSION).zip: - git archive --format zip --prefix=$(EXTENSION)-$(EXTVERSION)/ --output $@ master +dist/$(EXTENSION)-$(DISTVERSION).zip: + git archive --format zip --prefix=$(EXTENSION)-$(DISTVERSION)/ --output $@ HEAD From 085b3c510d24eb83698bdb503da70801f41ce374 Mon Sep 17 00:00:00 2001 From: Alexey Kondratov Date: Tue, 15 Dec 2020 20:50:36 +0300 Subject: [PATCH 2/7] Resolve issue#29: collector hanging after backend exit/error. --- pg_wait_sampling.c | 79 ++++++++++++++++++++++++++++++++-------------- 1 file changed, 56 insertions(+), 23 deletions(-) diff --git a/pg_wait_sampling.c b/pg_wait_sampling.c index 1bd5c76..dbe2959 100644 --- a/pg_wait_sampling.c +++ b/pg_wait_sampling.c @@ -47,6 +47,11 @@ shm_mq *collector_mq = NULL; uint64 *proc_queryids = NULL; CollectorShmqHeader *collector_hdr = NULL; +/* Receiver (backend) local shm_mq pointers and lock */ +shm_mq *recv_mq = NULL; +shm_mq_handle *recv_mqh = NULL; +LOCKTAG queueTag; + static shmem_startup_hook_type prev_shmem_startup_hook = NULL; static PGPROC * search_proc(int backendPid); static PlannedStmt *pgws_planner_hook(Query *parse, @@ -290,6 +295,14 @@ check_shmem(void) } } +static void +pgws_cleanup_callback(int code, Datum arg) +{ + elog(DEBUG3, "pg_wait_sampling cleanup: detaching shm_mq and releasing queue lock"); + shm_mq_detach_compat(recv_mqh, recv_mq); + LockRelease(&queueTag, ExclusiveLock, false); +} + /* * Module load callback */ @@ -499,16 +512,14 @@ init_lock_tag(LOCKTAG *tag, uint32 lock) static void * receive_array(SHMRequest request, Size item_size, Size *count) { - LOCKTAG queueTag; LOCKTAG collectorTag; - shm_mq *mq; - shm_mq_handle *mqh; shm_mq_result res; Size len, i; void *data; Pointer result, ptr; + MemoryContext oldctx; /* Ensure nobody else trying to send request to queue */ init_lock_tag(&queueTag, PGWS_QUEUE_LOCK); @@ -519,7 +530,7 @@ receive_array(SHMRequest request, Size item_size, Size *count) LockAcquire(&collectorTag, ExclusiveLock, false, false); LockRelease(&collectorTag, ExclusiveLock, false); - mq = shm_mq_create(collector_mq, COLLECTOR_QUEUE_SIZE); + recv_mq = shm_mq_create(collector_mq, COLLECTOR_QUEUE_SIZE); collector_hdr->request = request; if (!collector_hdr->latch) @@ -528,33 +539,55 @@ receive_array(SHMRequest request, Size item_size, Size *count) SetLatch(collector_hdr->latch); - shm_mq_set_receiver(mq, MyProc); - mqh = shm_mq_attach(mq, NULL, NULL); + shm_mq_set_receiver(recv_mq, MyProc); - res = shm_mq_receive(mqh, &len, &data, false); - if (res != SHM_MQ_SUCCESS || len != sizeof(*count)) - { - shm_mq_detach_compat(mqh, mq); - elog(ERROR, "Error reading mq."); - } - memcpy(count, data, sizeof(*count)); - - result = palloc(item_size * (*count)); - ptr = result; + /* + * We switch to TopMemoryContext, so that recv_mqh is allocated there + * and is guaranteed to survive until before_shmem_exit callbacks are + * fired. Anyway, shm_mq_detach() will free handler on its own. + */ + oldctx = MemoryContextSwitchTo(TopMemoryContext); + recv_mqh = shm_mq_attach(recv_mq, NULL, NULL); + MemoryContextSwitchTo(oldctx); - for (i = 0; i < *count; i++) + /* + * Now we surely attached to the shm_mq and got collector's attention. + * If anything went wrong (e.g. Ctrl+C received from the client) we have + * to cleanup some things, i.e. detach from the shm_mq, so collector was + * able to continue responding to other requests. + * + * PG_ENSURE_ERROR_CLEANUP() guaranties that cleanup callback will be + * fired for both ERROR and FATAL. + */ + PG_ENSURE_ERROR_CLEANUP(pgws_cleanup_callback, 0); { - res = shm_mq_receive(mqh, &len, &data, false); - if (res != SHM_MQ_SUCCESS || len != item_size) + res = shm_mq_receive(recv_mqh, &len, &data, false); + if (res != SHM_MQ_SUCCESS || len != sizeof(*count)) { - shm_mq_detach_compat(mqh, mq); + shm_mq_detach_compat(recv_mqh, recv_mq); elog(ERROR, "Error reading mq."); } - memcpy(ptr, data, item_size); - ptr += item_size; + memcpy(count, data, sizeof(*count)); + + result = palloc(item_size * (*count)); + ptr = result; + + for (i = 0; i < *count; i++) + { + res = shm_mq_receive(recv_mqh, &len, &data, false); + if (res != SHM_MQ_SUCCESS || len != item_size) + { + shm_mq_detach_compat(recv_mqh, recv_mq); + elog(ERROR, "Error reading mq."); + } + memcpy(ptr, data, item_size); + ptr += item_size; + } } + PG_END_ENSURE_ERROR_CLEANUP(pgws_cleanup_callback, 0); - shm_mq_detach_compat(mqh, mq); + /* We still have to detach and release lock during normal operation. */ + shm_mq_detach_compat(recv_mqh, recv_mq); LockRelease(&queueTag, ExclusiveLock, false); From a0b05e48b12d5324547f32666ee853bae870834a Mon Sep 17 00:00:00 2001 From: Alexey Kondratov Date: Tue, 15 Dec 2020 20:52:45 +0300 Subject: [PATCH 3/7] Correct some collector errors spelling --- collector.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/collector.c b/collector.c index 4e9d882..f3f141c 100644 --- a/collector.c +++ b/collector.c @@ -225,7 +225,7 @@ send_history(History *observations, shm_mq_handle *mqh) { ereport(WARNING, (errmsg("pg_wait_sampling collector: " - "receiver of message queue have been detached"))); + "receiver of message queue has been detached"))); return; } for (i = 0; i < count; i++) @@ -238,7 +238,7 @@ send_history(History *observations, shm_mq_handle *mqh) { ereport(WARNING, (errmsg("pg_wait_sampling collector: " - "receiver of message queue have been detached"))); + "receiver of message queue has been detached"))); return; } } @@ -260,7 +260,7 @@ send_profile(HTAB *profile_hash, shm_mq_handle *mqh) { ereport(WARNING, (errmsg("pg_wait_sampling collector: " - "receiver of message queue have been detached"))); + "receiver of message queue has been detached"))); return; } hash_seq_init(&scan_status, profile_hash); @@ -272,7 +272,7 @@ send_profile(HTAB *profile_hash, shm_mq_handle *mqh) hash_seq_term(&scan_status); ereport(WARNING, (errmsg("pg_wait_sampling collector: " - "receiver of message queue have been detached"))); + "receiver of message queue has been detached"))); return; } } @@ -468,7 +468,7 @@ collector_main(Datum main_arg) case SHM_MQ_DETACHED: ereport(WARNING, (errmsg("pg_wait_sampling collector: " - "receiver of message queue have been " + "receiver of message queue has been " "detached"))); break; default: From 8eb3028fb160bffd49aaa3bf44d4eb0a40e0b399 Mon Sep 17 00:00:00 2001 From: Alexey Kondratov Date: Mon, 18 Jan 2021 14:23:46 +0300 Subject: [PATCH 4/7] Fix pg_wait_sampling build for PG 9.6 --- pg_wait_sampling.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/pg_wait_sampling.c b/pg_wait_sampling.c index dbe2959..5409ae9 100644 --- a/pg_wait_sampling.c +++ b/pg_wait_sampling.c @@ -8,24 +8,27 @@ * contrib/pg_wait_sampling/pg_wait_sampling.c */ #include "postgres.h" -#include "fmgr.h" -#include "funcapi.h" + #include "access/htup_details.h" #include "access/twophase.h" #include "catalog/pg_type.h" +#include "fmgr.h" +#include "funcapi.h" #include "miscadmin.h" #include "optimizer/planner.h" #include "pgstat.h" -#include "storage/spin.h" #include "storage/ipc.h" #include "storage/pg_shmem.h" #include "storage/procarray.h" #include "storage/shm_mq.h" #include "storage/shm_toc.h" +#include "storage/spin.h" #include "utils/builtins.h" #include "utils/datetime.h" -#include "utils/guc.h" #include "utils/guc_tables.h" +#include "utils/guc.h" +#include "utils/memutils.h" /* TopMemoryContext. Actually for PG 9.6 only, + * but there should be no harm for others. */ #include "pg_wait_sampling.h" From 172df44fd61c3b8235cc51c7fb3ce731be31fdbb Mon Sep 17 00:00:00 2001 From: Alexey Kondratov Date: Mon, 18 Jan 2021 17:31:59 +0300 Subject: [PATCH 5/7] Completely rely on pgws_cleanup_callback() + more comments --- pg_wait_sampling.c | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/pg_wait_sampling.c b/pg_wait_sampling.c index 5409ae9..a90a981 100644 --- a/pg_wait_sampling.c +++ b/pg_wait_sampling.c @@ -548,6 +548,9 @@ receive_array(SHMRequest request, Size item_size, Size *count) * We switch to TopMemoryContext, so that recv_mqh is allocated there * and is guaranteed to survive until before_shmem_exit callbacks are * fired. Anyway, shm_mq_detach() will free handler on its own. + * + * NB: we do not pass `seg` to shm_mq_attach(), so it won't set its own + * callback, i.e. we do not interfere here with shm_mq_detach_callback(). */ oldctx = MemoryContextSwitchTo(TopMemoryContext); recv_mqh = shm_mq_attach(recv_mq, NULL, NULL); @@ -566,10 +569,8 @@ receive_array(SHMRequest request, Size item_size, Size *count) { res = shm_mq_receive(recv_mqh, &len, &data, false); if (res != SHM_MQ_SUCCESS || len != sizeof(*count)) - { - shm_mq_detach_compat(recv_mqh, recv_mq); - elog(ERROR, "Error reading mq."); - } + elog(ERROR, "error reading mq"); + memcpy(count, data, sizeof(*count)); result = palloc(item_size * (*count)); @@ -579,10 +580,8 @@ receive_array(SHMRequest request, Size item_size, Size *count) { res = shm_mq_receive(recv_mqh, &len, &data, false); if (res != SHM_MQ_SUCCESS || len != item_size) - { - shm_mq_detach_compat(recv_mqh, recv_mq); - elog(ERROR, "Error reading mq."); - } + elog(ERROR, "error reading mq"); + memcpy(ptr, data, item_size); ptr += item_size; } @@ -591,7 +590,6 @@ receive_array(SHMRequest request, Size item_size, Size *count) /* We still have to detach and release lock during normal operation. */ shm_mq_detach_compat(recv_mqh, recv_mq); - LockRelease(&queueTag, ExclusiveLock, false); return result; From 25a6c141acffc5e6e4b9352b1c181e30476f3581 Mon Sep 17 00:00:00 2001 From: Alexey Kondratov Date: Wed, 27 Jan 2021 13:09:19 +0300 Subject: [PATCH 6/7] Bump PGXN release to 1.1.3 --- META.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/META.json b/META.json index 4bdadfe..f26554e 100644 --- a/META.json +++ b/META.json @@ -2,7 +2,7 @@ "name": "pg_wait_sampling", "abstract": "Sampling based statistics of wait events", "description": "pg_wait_sampling provides functions for detailed per backend and per query statistics about PostgreSQL wait events", - "version": "1.1.2", + "version": "1.1.3", "maintainer": [ "Alexander Korotkov ", "Ildus Kurbangaliev " @@ -21,7 +21,7 @@ "pg_wait_sampling": { "file": "pg_wait_sampling--1.1.sql", "docfile": "README.md", - "version": "1.1.2", + "version": "1.1.3", "abstract": "Sampling based statistics of wait events" } }, From fc6647b0b9b710c346bbcea410037a4a0f738db0 Mon Sep 17 00:00:00 2001 From: Alexey Kondratov Date: Wed, 27 Jan 2021 13:21:11 +0300 Subject: [PATCH 7/7] Add release cycle info into README.md --- README.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/README.md b/README.md index f0a6a6c..0e47ad1 100644 --- a/README.md +++ b/README.md @@ -153,6 +153,16 @@ your bug reports. If you're lacking of some functionality in `pg_wait_sampling` and feeling power to implement it then you're welcome to make pull requests. +Releases +-------- + +New features are developed in feature-branches and then merged into [master](https://github.com/postgrespro/pg_wait_sampling/tree/master). To make a new release: + +1) Bump `PGXN` version in the `META.json`. +2) Merge [master](https://github.com/postgrespro/pg_wait_sampling/tree/master) into [stable](https://github.com/postgrespro/pg_wait_sampling/tree/stable). +3) Tag new release in the [stable](https://github.com/postgrespro/pg_wait_sampling/tree/stable) with `git tag -a v1.1.X`, where the last digit is used for indicating compatible shared library changes and bugfixes. Second digit is used to indicate extension schema change, i.e. when `ALTER EXTENSION pg_wait_sampling UPDATE;` is required. +4) Merge [stable](https://github.com/postgrespro/pg_wait_sampling/tree/stable) into [debian](https://github.com/postgrespro/pg_wait_sampling/tree/debian). This separate branch is used to independently support `Debian` packaging and @anayrat with @df7cb have an access there. + Authors -------