agora inbox for [email protected]
help / color / mirror / Atom feed[PATCH v5 06/12] consistent language: not implemented
15+ messages / 7 participants
[nested] [flat]
* [PATCH v5 06/12] consistent language: not implemented
@ 2019-05-20 17:57 Justin Pryzby <[email protected]>
0 siblings, 0 replies; 15+ messages in thread
From: Justin Pryzby @ 2019-05-20 17:57 UTC (permalink / raw)
Should we change the rest of these, too ?
git grep 'errmsg.*not yet implemented'
---
src/backend/catalog/index.c | 2 +-
src/backend/commands/indexcmds.c | 4 ++--
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c
index bb60b23..7f607e6 100644
--- a/src/backend/catalog/index.c
+++ b/src/backend/catalog/index.c
@@ -3511,7 +3511,7 @@ reindex_relation(Oid relid, int flags, int options)
{
ereport(WARNING,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
- errmsg("REINDEX of partitioned tables is not yet implemented, skipping \"%s\"",
+ errmsg("REINDEX of partitioned tables is not implemented, skipping \"%s\"",
RelationGetRelationName(rel))));
table_close(rel, ShareLock);
return false;
diff --git a/src/backend/commands/indexcmds.c b/src/backend/commands/indexcmds.c
index 6fa5738..5b0ae20 100644
--- a/src/backend/commands/indexcmds.c
+++ b/src/backend/commands/indexcmds.c
@@ -2898,7 +2898,7 @@ ReindexRelationConcurrently(Oid relationOid, int options)
/* see reindex_relation() */
ereport(WARNING,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
- errmsg("REINDEX of partitioned tables is not yet implemented, skipping \"%s\"",
+ errmsg("REINDEX of partitioned tables is not implemented, skipping \"%s\"",
get_rel_name(relationOid))));
return false;
default:
@@ -3344,7 +3344,7 @@ ReindexPartitionedIndex(Relation parentIdx)
{
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
- errmsg("REINDEX is not yet implemented for partitioned indexes")));
+ errmsg("REINDEX is not implemented for partitioned indexes")));
}
/*
--
2.7.4
--FkmkrVfFsRoUs1wW
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
filename="v5-0007-consistent-language-to-which.patch"
^ permalink raw reply [nested|flat] 15+ messages in thread
* [PATCH v3 06/12] consistent language: not implemented
@ 2019-05-20 17:57 Justin Pryzby <[email protected]>
0 siblings, 0 replies; 15+ messages in thread
From: Justin Pryzby @ 2019-05-20 17:57 UTC (permalink / raw)
Should we change the rest of these, too ?
git grep 'errmsg.*not yet implemented'
---
src/backend/catalog/index.c | 2 +-
src/backend/commands/indexcmds.c | 4 ++--
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c
index c8d22e1..2a2dca3 100644
--- a/src/backend/catalog/index.c
+++ b/src/backend/catalog/index.c
@@ -3506,7 +3506,7 @@ reindex_relation(Oid relid, int flags, int options)
{
ereport(WARNING,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
- errmsg("REINDEX of partitioned tables is not yet implemented, skipping \"%s\"",
+ errmsg("REINDEX of partitioned tables is not implemented, skipping \"%s\"",
RelationGetRelationName(rel))));
table_close(rel, ShareLock);
return false;
diff --git a/src/backend/commands/indexcmds.c b/src/backend/commands/indexcmds.c
index 7e7c03e..b2b15ec 100644
--- a/src/backend/commands/indexcmds.c
+++ b/src/backend/commands/indexcmds.c
@@ -2862,7 +2862,7 @@ ReindexRelationConcurrently(Oid relationOid, int options)
/* see reindex_relation() */
ereport(WARNING,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
- errmsg("REINDEX of partitioned tables is not yet implemented, skipping \"%s\"",
+ errmsg("REINDEX of partitioned tables is not implemented, skipping \"%s\"",
get_rel_name(relationOid))));
return false;
default:
@@ -3306,7 +3306,7 @@ ReindexPartitionedIndex(Relation parentIdx)
{
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
- errmsg("REINDEX is not yet implemented for partitioned indexes")));
+ errmsg("REINDEX is not implemented for partitioned indexes")));
}
/*
--
2.7.4
--cWoXeonUoKmBZSoM
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
filename="v3-0007-overridden-vs-overwritten.patch"
^ permalink raw reply [nested|flat] 15+ messages in thread
* [PATCH] Document RelationGetIndexAttrBitmap better
@ 2023-07-12 12:19 Alvaro Herrera <[email protected]>
0 siblings, 0 replies; 15+ messages in thread
From: Alvaro Herrera @ 2023-07-12 12:19 UTC (permalink / raw)
Commit 19d8e2308bc5 changed the list of set-of-columns that can be
returned by RelationGetIndexAttrBitmap, but didn't update its
"documentation". That was pretty hard to read already, so rewrite to
make it more comprehensible, adding the missing values while at it.
Backpatch to 16, like that commit.
---
src/backend/utils/cache/relcache.c | 12 +++++++++---
src/include/utils/relcache.h | 3 +++
2 files changed, 12 insertions(+), 3 deletions(-)
diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c
index 8e28335915..8e08ca1c68 100644
--- a/src/backend/utils/cache/relcache.c
+++ b/src/backend/utils/cache/relcache.c
@@ -5150,9 +5150,15 @@ RelationGetIndexPredicate(Relation relation)
* simple index keys, but attributes used in expressions and partial-index
* predicates.)
*
- * Depending on attrKind, a bitmap covering the attnums for all index columns,
- * for all potential foreign key columns, or for all columns in the configured
- * replica identity index is returned.
+ * Depending on attrKind, a bitmap covering attnums for certain columns is
+ * returned:
+ * INDEX_ATTR_BITMAP_KEY Columns in non-partial unique indexes not
+ * in expressions (i.e., usable for FKs)
+ * INDEX_ATTR_BITMAP_PRIMARY_KEY Columns in the table's primary key
+ * INDEX_ATTR_BITMAP_IDENTITY_KEY Columns in the table's replica identity
+ * index (empty if FULL)
+ * INDEX_ATTR_BITMAP_HOT_BLOCKING Columns that block updates from being HOT
+ * INDEX_ATTR_BITMAP_SUMMARIZED Columns included in summarizing indexes
*
* Attribute numbers are offset by FirstLowInvalidHeapAttributeNumber so that
* we can include system attributes (e.g., OID) in the bitmap representation.
diff --git a/src/include/utils/relcache.h b/src/include/utils/relcache.h
index beeb28b83c..38524641f4 100644
--- a/src/include/utils/relcache.h
+++ b/src/include/utils/relcache.h
@@ -54,6 +54,9 @@ extern List *RelationGetIndexPredicate(Relation relation);
extern Datum *RelationGetIndexRawAttOptions(Relation indexrel);
extern bytea **RelationGetIndexAttOptions(Relation relation, bool copy);
+/*
+ * Which set of columns to return by RelationGetIndexAttrBitmap.
+ */
typedef enum IndexAttrBitmapKind
{
INDEX_ATTR_BITMAP_KEY,
--
2.39.2
--sr6mye444zs4xrf5--
^ permalink raw reply [nested|flat] 15+ messages in thread
* [PATCH] Document RelationGetIndexAttrBitmap better
@ 2023-07-12 12:19 Alvaro Herrera <[email protected]>
0 siblings, 0 replies; 15+ messages in thread
From: Alvaro Herrera @ 2023-07-12 12:19 UTC (permalink / raw)
Commit 19d8e2308bc5 changed the list of set-of-columns that can be
returned by RelationGetIndexAttrBitmap, but didn't update its
"documentation". That was pretty hard to read already, so rewrite to
make it more comprehensible, adding the missing values while at it.
Backpatch to 16, like that commit.
---
src/backend/utils/cache/relcache.c | 12 +++++++++---
src/include/utils/relcache.h | 3 +++
2 files changed, 12 insertions(+), 3 deletions(-)
diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c
index 8e28335915..8e08ca1c68 100644
--- a/src/backend/utils/cache/relcache.c
+++ b/src/backend/utils/cache/relcache.c
@@ -5150,9 +5150,15 @@ RelationGetIndexPredicate(Relation relation)
* simple index keys, but attributes used in expressions and partial-index
* predicates.)
*
- * Depending on attrKind, a bitmap covering the attnums for all index columns,
- * for all potential foreign key columns, or for all columns in the configured
- * replica identity index is returned.
+ * Depending on attrKind, a bitmap covering attnums for certain columns is
+ * returned:
+ * INDEX_ATTR_BITMAP_KEY Columns in non-partial unique indexes not
+ * in expressions (i.e., usable for FKs)
+ * INDEX_ATTR_BITMAP_PRIMARY_KEY Columns in the table's primary key
+ * INDEX_ATTR_BITMAP_IDENTITY_KEY Columns in the table's replica identity
+ * index (empty if FULL)
+ * INDEX_ATTR_BITMAP_HOT_BLOCKING Columns that block updates from being HOT
+ * INDEX_ATTR_BITMAP_SUMMARIZED Columns included in summarizing indexes
*
* Attribute numbers are offset by FirstLowInvalidHeapAttributeNumber so that
* we can include system attributes (e.g., OID) in the bitmap representation.
diff --git a/src/include/utils/relcache.h b/src/include/utils/relcache.h
index beeb28b83c..38524641f4 100644
--- a/src/include/utils/relcache.h
+++ b/src/include/utils/relcache.h
@@ -54,6 +54,9 @@ extern List *RelationGetIndexPredicate(Relation relation);
extern Datum *RelationGetIndexRawAttOptions(Relation indexrel);
extern bytea **RelationGetIndexAttOptions(Relation relation, bool copy);
+/*
+ * Which set of columns to return by RelationGetIndexAttrBitmap.
+ */
typedef enum IndexAttrBitmapKind
{
INDEX_ATTR_BITMAP_KEY,
--
2.39.2
--sr6mye444zs4xrf5--
^ permalink raw reply [nested|flat] 15+ messages in thread
* [PATCH] Document RelationGetIndexAttrBitmap better
@ 2023-07-12 12:19 Alvaro Herrera <[email protected]>
0 siblings, 0 replies; 15+ messages in thread
From: Alvaro Herrera @ 2023-07-12 12:19 UTC (permalink / raw)
Commit 19d8e2308bc5 changed the list of set-of-columns that can be
returned by RelationGetIndexAttrBitmap, but didn't update its
"documentation". That was pretty hard to read already, so rewrite to
make it more comprehensible, adding the missing values while at it.
Backpatch to 16, like that commit.
---
src/backend/utils/cache/relcache.c | 12 +++++++++---
src/include/utils/relcache.h | 3 +++
2 files changed, 12 insertions(+), 3 deletions(-)
diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c
index 8e28335915..8e08ca1c68 100644
--- a/src/backend/utils/cache/relcache.c
+++ b/src/backend/utils/cache/relcache.c
@@ -5150,9 +5150,15 @@ RelationGetIndexPredicate(Relation relation)
* simple index keys, but attributes used in expressions and partial-index
* predicates.)
*
- * Depending on attrKind, a bitmap covering the attnums for all index columns,
- * for all potential foreign key columns, or for all columns in the configured
- * replica identity index is returned.
+ * Depending on attrKind, a bitmap covering attnums for certain columns is
+ * returned:
+ * INDEX_ATTR_BITMAP_KEY Columns in non-partial unique indexes not
+ * in expressions (i.e., usable for FKs)
+ * INDEX_ATTR_BITMAP_PRIMARY_KEY Columns in the table's primary key
+ * INDEX_ATTR_BITMAP_IDENTITY_KEY Columns in the table's replica identity
+ * index (empty if FULL)
+ * INDEX_ATTR_BITMAP_HOT_BLOCKING Columns that block updates from being HOT
+ * INDEX_ATTR_BITMAP_SUMMARIZED Columns included in summarizing indexes
*
* Attribute numbers are offset by FirstLowInvalidHeapAttributeNumber so that
* we can include system attributes (e.g., OID) in the bitmap representation.
diff --git a/src/include/utils/relcache.h b/src/include/utils/relcache.h
index beeb28b83c..38524641f4 100644
--- a/src/include/utils/relcache.h
+++ b/src/include/utils/relcache.h
@@ -54,6 +54,9 @@ extern List *RelationGetIndexPredicate(Relation relation);
extern Datum *RelationGetIndexRawAttOptions(Relation indexrel);
extern bytea **RelationGetIndexAttOptions(Relation relation, bool copy);
+/*
+ * Which set of columns to return by RelationGetIndexAttrBitmap.
+ */
typedef enum IndexAttrBitmapKind
{
INDEX_ATTR_BITMAP_KEY,
--
2.39.2
--sr6mye444zs4xrf5--
^ permalink raw reply [nested|flat] 15+ messages in thread
* [PATCH v9 04/10] lwlock: Invert meaning of LW_FLAG_RELEASE_OK
@ 2026-01-06 01:40 Andres Freund <[email protected]>
0 siblings, 0 replies; 15+ messages in thread
From: Andres Freund @ 2026-01-06 01:40 UTC (permalink / raw)
Instead of setting a flag whenever a lock release is supposed to wake up
waiters - the majority of the time - set a flag whenever wakeups are
inhibited. The motivation for this that in an upcoming commit, buffer content
locks are implemented separately from lwlocks, and for buffer content locks it
is useful to be able to reset all buffer flags when a buffer invalidated,
alternatively we would have to set the release-ok flag when making a buffer
valid. It seems good to keep the implementation of lwlocks and buffer content
locks as similar as reasonably possible.
Author:
Reviewed-by:
Discussion: https://postgr.es/m/
Backpatch:
---
src/backend/storage/lmgr/lwlock.c | 42 +++++++++++++++----------------
1 file changed, 20 insertions(+), 22 deletions(-)
diff --git a/src/backend/storage/lmgr/lwlock.c b/src/backend/storage/lmgr/lwlock.c
index 6a9f86d5025..148309cc186 100644
--- a/src/backend/storage/lmgr/lwlock.c
+++ b/src/backend/storage/lmgr/lwlock.c
@@ -92,7 +92,7 @@
#define LW_FLAG_HAS_WAITERS ((uint32) 1 << 31)
-#define LW_FLAG_RELEASE_OK ((uint32) 1 << 30)
+#define LW_FLAG_WAKE_IN_PROGRESS ((uint32) 1 << 30)
#define LW_FLAG_LOCKED ((uint32) 1 << 29)
#define LW_FLAG_BITS 3
#define LW_FLAG_MASK (((1<<LW_FLAG_BITS)-1)<<(32-LW_FLAG_BITS))
@@ -246,14 +246,14 @@ PRINT_LWDEBUG(const char *where, LWLock *lock, LWLockMode mode)
ereport(LOG,
(errhidestmt(true),
errhidecontext(true),
- errmsg_internal("%d: %s(%s %p): excl %u shared %u haswaiters %u waiters %u rOK %d",
+ errmsg_internal("%d: %s(%s %p): excl %u shared %u haswaiters %u waiters %u waking %d",
MyProcPid,
where, T_NAME(lock), lock,
(state & LW_VAL_EXCLUSIVE) != 0,
state & LW_SHARED_MASK,
(state & LW_FLAG_HAS_WAITERS) != 0,
pg_atomic_read_u32(&lock->nwaiters),
- (state & LW_FLAG_RELEASE_OK) != 0)));
+ (state & LW_FLAG_WAKE_IN_PROGRESS) != 0)));
}
}
@@ -700,7 +700,7 @@ LWLockInitialize(LWLock *lock, int tranche_id)
/* verify the tranche_id is valid */
(void) GetLWTrancheName(tranche_id);
- pg_atomic_init_u32(&lock->state, LW_FLAG_RELEASE_OK);
+ pg_atomic_init_u32(&lock->state, 0);
#ifdef LOCK_DEBUG
pg_atomic_init_u32(&lock->nwaiters, 0);
#endif
@@ -929,15 +929,13 @@ LWLockWaitListUnlock(LWLock *lock)
static void
LWLockWakeup(LWLock *lock)
{
- bool new_release_ok;
+ bool new_release_in_progress = false;
bool wokeup_somebody = false;
proclist_head wakeup;
proclist_mutable_iter iter;
proclist_init(&wakeup);
- new_release_ok = true;
-
/* lock wait list while collecting backends to wake up */
LWLockWaitListLock(lock);
@@ -958,7 +956,7 @@ LWLockWakeup(LWLock *lock)
* that are just waiting for the lock to become free don't retry
* automatically.
*/
- new_release_ok = false;
+ new_release_in_progress = true;
/*
* Don't wakeup (further) exclusive locks.
@@ -997,10 +995,10 @@ LWLockWakeup(LWLock *lock)
/* compute desired flags */
- if (new_release_ok)
- desired_state |= LW_FLAG_RELEASE_OK;
+ if (new_release_in_progress)
+ desired_state |= LW_FLAG_WAKE_IN_PROGRESS;
else
- desired_state &= ~LW_FLAG_RELEASE_OK;
+ desired_state &= ~LW_FLAG_WAKE_IN_PROGRESS;
if (proclist_is_empty(&lock->waiters))
desired_state &= ~LW_FLAG_HAS_WAITERS;
@@ -1131,10 +1129,10 @@ LWLockDequeueSelf(LWLock *lock)
*/
/*
- * Reset RELEASE_OK flag if somebody woke us before we removed
- * ourselves - they'll have set it to false.
+ * Clear LW_FLAG_WAKE_IN_PROGRESS if somebody woke us before we
+ * removed ourselves - they'll have set it.
*/
- pg_atomic_fetch_or_u32(&lock->state, LW_FLAG_RELEASE_OK);
+ pg_atomic_fetch_and_u32(&lock->state, ~LW_FLAG_WAKE_IN_PROGRESS);
/*
* Now wait for the scheduled wakeup, otherwise our ->lwWaiting would
@@ -1301,7 +1299,7 @@ LWLockAcquire(LWLock *lock, LWLockMode mode)
}
/* Retrying, allow LWLockRelease to release waiters again. */
- pg_atomic_fetch_or_u32(&lock->state, LW_FLAG_RELEASE_OK);
+ pg_atomic_fetch_and_u32(&lock->state, ~LW_FLAG_WAKE_IN_PROGRESS);
#ifdef LOCK_DEBUG
{
@@ -1636,10 +1634,10 @@ LWLockWaitForVar(LWLock *lock, pg_atomic_uint64 *valptr, uint64 oldval,
LWLockQueueSelf(lock, LW_WAIT_UNTIL_FREE);
/*
- * Set RELEASE_OK flag, to make sure we get woken up as soon as the
- * lock is released.
+ * Clear LW_FLAG_WAKE_IN_PROGRESS flag, to make sure we get woken up
+ * as soon as the lock is released.
*/
- pg_atomic_fetch_or_u32(&lock->state, LW_FLAG_RELEASE_OK);
+ pg_atomic_fetch_and_u32(&lock->state, ~LW_FLAG_WAKE_IN_PROGRESS);
/*
* We're now guaranteed to be woken up if necessary. Recheck the lock
@@ -1852,11 +1850,11 @@ LWLockReleaseInternal(LWLock *lock, LWLockMode mode)
TRACE_POSTGRESQL_LWLOCK_RELEASE(T_NAME(lock));
/*
- * We're still waiting for backends to get scheduled, don't wake them up
- * again.
+ * Check if we're still waiting for backends to get scheduled, if so,
+ * don't wake them up again.
*/
- if ((oldstate & (LW_FLAG_HAS_WAITERS | LW_FLAG_RELEASE_OK)) ==
- (LW_FLAG_HAS_WAITERS | LW_FLAG_RELEASE_OK) &&
+ if ((oldstate & LW_FLAG_HAS_WAITERS) &&
+ !(oldstate & LW_FLAG_WAKE_IN_PROGRESS) &&
(oldstate & LW_LOCK_MASK) == 0)
check_waiters = true;
else
--
2.48.1.76.g4e746b1a31.dirty
--rkiyqpij3ajqn7ww
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
filename="v9-0005-bufmgr-Make-definitions-related-to-buffer-descrip.patch"
^ permalink raw reply [nested|flat] 15+ messages in thread
* [PATCH v10 1/8] lwlock: Invert meaning of LW_FLAG_RELEASE_OK
@ 2026-01-06 01:40 Andres Freund <[email protected]>
0 siblings, 0 replies; 15+ messages in thread
From: Andres Freund @ 2026-01-06 01:40 UTC (permalink / raw)
Previously, a flag was set to indicate that a lock release should wake up
waiters. Since waking waiters is the default behavior in the majority of
cases, this logic has been inverted. The new LW_FLAG_WAKE_IN_PROGRESS flag is
now set iff wakeups are explicitly inhibited.
The motivation for this change is that in an upcoming commit, content locks
will be implemented independently of lwlocks, with the lock state stored as
part of BufferDesc.state. As all of a buffer's flags are cleared when the
buffer is invalidated, without this change we would have to re-add the
RELEASE_OK flag after clearing the flags; otherwise, the next lock release
would not wake waiters.
It seems good to keep the implementation of lwlocks and buffer content locks
as similar as reasonably possible.
Discussion: https://postgr.es/m/4csodkvvfbfloxxjlkgsnl2lgfv2mtzdl7phqzd4jxjadxm4o5@usw7feyb5bzf
---
src/backend/storage/lmgr/lwlock.c | 42 +++++++++++++++----------------
1 file changed, 20 insertions(+), 22 deletions(-)
diff --git a/src/backend/storage/lmgr/lwlock.c b/src/backend/storage/lmgr/lwlock.c
index 6a9f86d5025..148309cc186 100644
--- a/src/backend/storage/lmgr/lwlock.c
+++ b/src/backend/storage/lmgr/lwlock.c
@@ -92,7 +92,7 @@
#define LW_FLAG_HAS_WAITERS ((uint32) 1 << 31)
-#define LW_FLAG_RELEASE_OK ((uint32) 1 << 30)
+#define LW_FLAG_WAKE_IN_PROGRESS ((uint32) 1 << 30)
#define LW_FLAG_LOCKED ((uint32) 1 << 29)
#define LW_FLAG_BITS 3
#define LW_FLAG_MASK (((1<<LW_FLAG_BITS)-1)<<(32-LW_FLAG_BITS))
@@ -246,14 +246,14 @@ PRINT_LWDEBUG(const char *where, LWLock *lock, LWLockMode mode)
ereport(LOG,
(errhidestmt(true),
errhidecontext(true),
- errmsg_internal("%d: %s(%s %p): excl %u shared %u haswaiters %u waiters %u rOK %d",
+ errmsg_internal("%d: %s(%s %p): excl %u shared %u haswaiters %u waiters %u waking %d",
MyProcPid,
where, T_NAME(lock), lock,
(state & LW_VAL_EXCLUSIVE) != 0,
state & LW_SHARED_MASK,
(state & LW_FLAG_HAS_WAITERS) != 0,
pg_atomic_read_u32(&lock->nwaiters),
- (state & LW_FLAG_RELEASE_OK) != 0)));
+ (state & LW_FLAG_WAKE_IN_PROGRESS) != 0)));
}
}
@@ -700,7 +700,7 @@ LWLockInitialize(LWLock *lock, int tranche_id)
/* verify the tranche_id is valid */
(void) GetLWTrancheName(tranche_id);
- pg_atomic_init_u32(&lock->state, LW_FLAG_RELEASE_OK);
+ pg_atomic_init_u32(&lock->state, 0);
#ifdef LOCK_DEBUG
pg_atomic_init_u32(&lock->nwaiters, 0);
#endif
@@ -929,15 +929,13 @@ LWLockWaitListUnlock(LWLock *lock)
static void
LWLockWakeup(LWLock *lock)
{
- bool new_release_ok;
+ bool new_release_in_progress = false;
bool wokeup_somebody = false;
proclist_head wakeup;
proclist_mutable_iter iter;
proclist_init(&wakeup);
- new_release_ok = true;
-
/* lock wait list while collecting backends to wake up */
LWLockWaitListLock(lock);
@@ -958,7 +956,7 @@ LWLockWakeup(LWLock *lock)
* that are just waiting for the lock to become free don't retry
* automatically.
*/
- new_release_ok = false;
+ new_release_in_progress = true;
/*
* Don't wakeup (further) exclusive locks.
@@ -997,10 +995,10 @@ LWLockWakeup(LWLock *lock)
/* compute desired flags */
- if (new_release_ok)
- desired_state |= LW_FLAG_RELEASE_OK;
+ if (new_release_in_progress)
+ desired_state |= LW_FLAG_WAKE_IN_PROGRESS;
else
- desired_state &= ~LW_FLAG_RELEASE_OK;
+ desired_state &= ~LW_FLAG_WAKE_IN_PROGRESS;
if (proclist_is_empty(&lock->waiters))
desired_state &= ~LW_FLAG_HAS_WAITERS;
@@ -1131,10 +1129,10 @@ LWLockDequeueSelf(LWLock *lock)
*/
/*
- * Reset RELEASE_OK flag if somebody woke us before we removed
- * ourselves - they'll have set it to false.
+ * Clear LW_FLAG_WAKE_IN_PROGRESS if somebody woke us before we
+ * removed ourselves - they'll have set it.
*/
- pg_atomic_fetch_or_u32(&lock->state, LW_FLAG_RELEASE_OK);
+ pg_atomic_fetch_and_u32(&lock->state, ~LW_FLAG_WAKE_IN_PROGRESS);
/*
* Now wait for the scheduled wakeup, otherwise our ->lwWaiting would
@@ -1301,7 +1299,7 @@ LWLockAcquire(LWLock *lock, LWLockMode mode)
}
/* Retrying, allow LWLockRelease to release waiters again. */
- pg_atomic_fetch_or_u32(&lock->state, LW_FLAG_RELEASE_OK);
+ pg_atomic_fetch_and_u32(&lock->state, ~LW_FLAG_WAKE_IN_PROGRESS);
#ifdef LOCK_DEBUG
{
@@ -1636,10 +1634,10 @@ LWLockWaitForVar(LWLock *lock, pg_atomic_uint64 *valptr, uint64 oldval,
LWLockQueueSelf(lock, LW_WAIT_UNTIL_FREE);
/*
- * Set RELEASE_OK flag, to make sure we get woken up as soon as the
- * lock is released.
+ * Clear LW_FLAG_WAKE_IN_PROGRESS flag, to make sure we get woken up
+ * as soon as the lock is released.
*/
- pg_atomic_fetch_or_u32(&lock->state, LW_FLAG_RELEASE_OK);
+ pg_atomic_fetch_and_u32(&lock->state, ~LW_FLAG_WAKE_IN_PROGRESS);
/*
* We're now guaranteed to be woken up if necessary. Recheck the lock
@@ -1852,11 +1850,11 @@ LWLockReleaseInternal(LWLock *lock, LWLockMode mode)
TRACE_POSTGRESQL_LWLOCK_RELEASE(T_NAME(lock));
/*
- * We're still waiting for backends to get scheduled, don't wake them up
- * again.
+ * Check if we're still waiting for backends to get scheduled, if so,
+ * don't wake them up again.
*/
- if ((oldstate & (LW_FLAG_HAS_WAITERS | LW_FLAG_RELEASE_OK)) ==
- (LW_FLAG_HAS_WAITERS | LW_FLAG_RELEASE_OK) &&
+ if ((oldstate & LW_FLAG_HAS_WAITERS) &&
+ !(oldstate & LW_FLAG_WAKE_IN_PROGRESS) &&
(oldstate & LW_LOCK_MASK) == 0)
check_waiters = true;
else
--
2.48.1.76.g4e746b1a31.dirty
--jmawlk4t5yqwiemy
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
filename="v10-0002-bufmgr-Make-definitions-related-to-buffer-descri.patch"
^ permalink raw reply [nested|flat] 15+ messages in thread
* [PATCH v9 04/10] lwlock: Invert meaning of LW_FLAG_RELEASE_OK
@ 2026-01-06 01:40 Andres Freund <[email protected]>
0 siblings, 0 replies; 15+ messages in thread
From: Andres Freund @ 2026-01-06 01:40 UTC (permalink / raw)
Instead of setting a flag whenever a lock release is supposed to wake up
waiters - the majority of the time - set a flag whenever wakeups are
inhibited. The motivation for this that in an upcoming commit, buffer content
locks are implemented separately from lwlocks, and for buffer content locks it
is useful to be able to reset all buffer flags when a buffer invalidated,
alternatively we would have to set the release-ok flag when making a buffer
valid. It seems good to keep the implementation of lwlocks and buffer content
locks as similar as reasonably possible.
Author:
Reviewed-by:
Discussion: https://postgr.es/m/
Backpatch:
---
src/backend/storage/lmgr/lwlock.c | 42 +++++++++++++++----------------
1 file changed, 20 insertions(+), 22 deletions(-)
diff --git a/src/backend/storage/lmgr/lwlock.c b/src/backend/storage/lmgr/lwlock.c
index 6a9f86d5025..148309cc186 100644
--- a/src/backend/storage/lmgr/lwlock.c
+++ b/src/backend/storage/lmgr/lwlock.c
@@ -92,7 +92,7 @@
#define LW_FLAG_HAS_WAITERS ((uint32) 1 << 31)
-#define LW_FLAG_RELEASE_OK ((uint32) 1 << 30)
+#define LW_FLAG_WAKE_IN_PROGRESS ((uint32) 1 << 30)
#define LW_FLAG_LOCKED ((uint32) 1 << 29)
#define LW_FLAG_BITS 3
#define LW_FLAG_MASK (((1<<LW_FLAG_BITS)-1)<<(32-LW_FLAG_BITS))
@@ -246,14 +246,14 @@ PRINT_LWDEBUG(const char *where, LWLock *lock, LWLockMode mode)
ereport(LOG,
(errhidestmt(true),
errhidecontext(true),
- errmsg_internal("%d: %s(%s %p): excl %u shared %u haswaiters %u waiters %u rOK %d",
+ errmsg_internal("%d: %s(%s %p): excl %u shared %u haswaiters %u waiters %u waking %d",
MyProcPid,
where, T_NAME(lock), lock,
(state & LW_VAL_EXCLUSIVE) != 0,
state & LW_SHARED_MASK,
(state & LW_FLAG_HAS_WAITERS) != 0,
pg_atomic_read_u32(&lock->nwaiters),
- (state & LW_FLAG_RELEASE_OK) != 0)));
+ (state & LW_FLAG_WAKE_IN_PROGRESS) != 0)));
}
}
@@ -700,7 +700,7 @@ LWLockInitialize(LWLock *lock, int tranche_id)
/* verify the tranche_id is valid */
(void) GetLWTrancheName(tranche_id);
- pg_atomic_init_u32(&lock->state, LW_FLAG_RELEASE_OK);
+ pg_atomic_init_u32(&lock->state, 0);
#ifdef LOCK_DEBUG
pg_atomic_init_u32(&lock->nwaiters, 0);
#endif
@@ -929,15 +929,13 @@ LWLockWaitListUnlock(LWLock *lock)
static void
LWLockWakeup(LWLock *lock)
{
- bool new_release_ok;
+ bool new_release_in_progress = false;
bool wokeup_somebody = false;
proclist_head wakeup;
proclist_mutable_iter iter;
proclist_init(&wakeup);
- new_release_ok = true;
-
/* lock wait list while collecting backends to wake up */
LWLockWaitListLock(lock);
@@ -958,7 +956,7 @@ LWLockWakeup(LWLock *lock)
* that are just waiting for the lock to become free don't retry
* automatically.
*/
- new_release_ok = false;
+ new_release_in_progress = true;
/*
* Don't wakeup (further) exclusive locks.
@@ -997,10 +995,10 @@ LWLockWakeup(LWLock *lock)
/* compute desired flags */
- if (new_release_ok)
- desired_state |= LW_FLAG_RELEASE_OK;
+ if (new_release_in_progress)
+ desired_state |= LW_FLAG_WAKE_IN_PROGRESS;
else
- desired_state &= ~LW_FLAG_RELEASE_OK;
+ desired_state &= ~LW_FLAG_WAKE_IN_PROGRESS;
if (proclist_is_empty(&lock->waiters))
desired_state &= ~LW_FLAG_HAS_WAITERS;
@@ -1131,10 +1129,10 @@ LWLockDequeueSelf(LWLock *lock)
*/
/*
- * Reset RELEASE_OK flag if somebody woke us before we removed
- * ourselves - they'll have set it to false.
+ * Clear LW_FLAG_WAKE_IN_PROGRESS if somebody woke us before we
+ * removed ourselves - they'll have set it.
*/
- pg_atomic_fetch_or_u32(&lock->state, LW_FLAG_RELEASE_OK);
+ pg_atomic_fetch_and_u32(&lock->state, ~LW_FLAG_WAKE_IN_PROGRESS);
/*
* Now wait for the scheduled wakeup, otherwise our ->lwWaiting would
@@ -1301,7 +1299,7 @@ LWLockAcquire(LWLock *lock, LWLockMode mode)
}
/* Retrying, allow LWLockRelease to release waiters again. */
- pg_atomic_fetch_or_u32(&lock->state, LW_FLAG_RELEASE_OK);
+ pg_atomic_fetch_and_u32(&lock->state, ~LW_FLAG_WAKE_IN_PROGRESS);
#ifdef LOCK_DEBUG
{
@@ -1636,10 +1634,10 @@ LWLockWaitForVar(LWLock *lock, pg_atomic_uint64 *valptr, uint64 oldval,
LWLockQueueSelf(lock, LW_WAIT_UNTIL_FREE);
/*
- * Set RELEASE_OK flag, to make sure we get woken up as soon as the
- * lock is released.
+ * Clear LW_FLAG_WAKE_IN_PROGRESS flag, to make sure we get woken up
+ * as soon as the lock is released.
*/
- pg_atomic_fetch_or_u32(&lock->state, LW_FLAG_RELEASE_OK);
+ pg_atomic_fetch_and_u32(&lock->state, ~LW_FLAG_WAKE_IN_PROGRESS);
/*
* We're now guaranteed to be woken up if necessary. Recheck the lock
@@ -1852,11 +1850,11 @@ LWLockReleaseInternal(LWLock *lock, LWLockMode mode)
TRACE_POSTGRESQL_LWLOCK_RELEASE(T_NAME(lock));
/*
- * We're still waiting for backends to get scheduled, don't wake them up
- * again.
+ * Check if we're still waiting for backends to get scheduled, if so,
+ * don't wake them up again.
*/
- if ((oldstate & (LW_FLAG_HAS_WAITERS | LW_FLAG_RELEASE_OK)) ==
- (LW_FLAG_HAS_WAITERS | LW_FLAG_RELEASE_OK) &&
+ if ((oldstate & LW_FLAG_HAS_WAITERS) &&
+ !(oldstate & LW_FLAG_WAKE_IN_PROGRESS) &&
(oldstate & LW_LOCK_MASK) == 0)
check_waiters = true;
else
--
2.48.1.76.g4e746b1a31.dirty
--rkiyqpij3ajqn7ww
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
filename="v9-0005-bufmgr-Make-definitions-related-to-buffer-descrip.patch"
^ permalink raw reply [nested|flat] 15+ messages in thread
* [PATCH v9 04/10] lwlock: Invert meaning of LW_FLAG_RELEASE_OK
@ 2026-01-06 01:40 Andres Freund <[email protected]>
0 siblings, 0 replies; 15+ messages in thread
From: Andres Freund @ 2026-01-06 01:40 UTC (permalink / raw)
Instead of setting a flag whenever a lock release is supposed to wake up
waiters - the majority of the time - set a flag whenever wakeups are
inhibited. The motivation for this that in an upcoming commit, buffer content
locks are implemented separately from lwlocks, and for buffer content locks it
is useful to be able to reset all buffer flags when a buffer invalidated,
alternatively we would have to set the release-ok flag when making a buffer
valid. It seems good to keep the implementation of lwlocks and buffer content
locks as similar as reasonably possible.
Author:
Reviewed-by:
Discussion: https://postgr.es/m/
Backpatch:
---
src/backend/storage/lmgr/lwlock.c | 42 +++++++++++++++----------------
1 file changed, 20 insertions(+), 22 deletions(-)
diff --git a/src/backend/storage/lmgr/lwlock.c b/src/backend/storage/lmgr/lwlock.c
index 6a9f86d5025..148309cc186 100644
--- a/src/backend/storage/lmgr/lwlock.c
+++ b/src/backend/storage/lmgr/lwlock.c
@@ -92,7 +92,7 @@
#define LW_FLAG_HAS_WAITERS ((uint32) 1 << 31)
-#define LW_FLAG_RELEASE_OK ((uint32) 1 << 30)
+#define LW_FLAG_WAKE_IN_PROGRESS ((uint32) 1 << 30)
#define LW_FLAG_LOCKED ((uint32) 1 << 29)
#define LW_FLAG_BITS 3
#define LW_FLAG_MASK (((1<<LW_FLAG_BITS)-1)<<(32-LW_FLAG_BITS))
@@ -246,14 +246,14 @@ PRINT_LWDEBUG(const char *where, LWLock *lock, LWLockMode mode)
ereport(LOG,
(errhidestmt(true),
errhidecontext(true),
- errmsg_internal("%d: %s(%s %p): excl %u shared %u haswaiters %u waiters %u rOK %d",
+ errmsg_internal("%d: %s(%s %p): excl %u shared %u haswaiters %u waiters %u waking %d",
MyProcPid,
where, T_NAME(lock), lock,
(state & LW_VAL_EXCLUSIVE) != 0,
state & LW_SHARED_MASK,
(state & LW_FLAG_HAS_WAITERS) != 0,
pg_atomic_read_u32(&lock->nwaiters),
- (state & LW_FLAG_RELEASE_OK) != 0)));
+ (state & LW_FLAG_WAKE_IN_PROGRESS) != 0)));
}
}
@@ -700,7 +700,7 @@ LWLockInitialize(LWLock *lock, int tranche_id)
/* verify the tranche_id is valid */
(void) GetLWTrancheName(tranche_id);
- pg_atomic_init_u32(&lock->state, LW_FLAG_RELEASE_OK);
+ pg_atomic_init_u32(&lock->state, 0);
#ifdef LOCK_DEBUG
pg_atomic_init_u32(&lock->nwaiters, 0);
#endif
@@ -929,15 +929,13 @@ LWLockWaitListUnlock(LWLock *lock)
static void
LWLockWakeup(LWLock *lock)
{
- bool new_release_ok;
+ bool new_release_in_progress = false;
bool wokeup_somebody = false;
proclist_head wakeup;
proclist_mutable_iter iter;
proclist_init(&wakeup);
- new_release_ok = true;
-
/* lock wait list while collecting backends to wake up */
LWLockWaitListLock(lock);
@@ -958,7 +956,7 @@ LWLockWakeup(LWLock *lock)
* that are just waiting for the lock to become free don't retry
* automatically.
*/
- new_release_ok = false;
+ new_release_in_progress = true;
/*
* Don't wakeup (further) exclusive locks.
@@ -997,10 +995,10 @@ LWLockWakeup(LWLock *lock)
/* compute desired flags */
- if (new_release_ok)
- desired_state |= LW_FLAG_RELEASE_OK;
+ if (new_release_in_progress)
+ desired_state |= LW_FLAG_WAKE_IN_PROGRESS;
else
- desired_state &= ~LW_FLAG_RELEASE_OK;
+ desired_state &= ~LW_FLAG_WAKE_IN_PROGRESS;
if (proclist_is_empty(&lock->waiters))
desired_state &= ~LW_FLAG_HAS_WAITERS;
@@ -1131,10 +1129,10 @@ LWLockDequeueSelf(LWLock *lock)
*/
/*
- * Reset RELEASE_OK flag if somebody woke us before we removed
- * ourselves - they'll have set it to false.
+ * Clear LW_FLAG_WAKE_IN_PROGRESS if somebody woke us before we
+ * removed ourselves - they'll have set it.
*/
- pg_atomic_fetch_or_u32(&lock->state, LW_FLAG_RELEASE_OK);
+ pg_atomic_fetch_and_u32(&lock->state, ~LW_FLAG_WAKE_IN_PROGRESS);
/*
* Now wait for the scheduled wakeup, otherwise our ->lwWaiting would
@@ -1301,7 +1299,7 @@ LWLockAcquire(LWLock *lock, LWLockMode mode)
}
/* Retrying, allow LWLockRelease to release waiters again. */
- pg_atomic_fetch_or_u32(&lock->state, LW_FLAG_RELEASE_OK);
+ pg_atomic_fetch_and_u32(&lock->state, ~LW_FLAG_WAKE_IN_PROGRESS);
#ifdef LOCK_DEBUG
{
@@ -1636,10 +1634,10 @@ LWLockWaitForVar(LWLock *lock, pg_atomic_uint64 *valptr, uint64 oldval,
LWLockQueueSelf(lock, LW_WAIT_UNTIL_FREE);
/*
- * Set RELEASE_OK flag, to make sure we get woken up as soon as the
- * lock is released.
+ * Clear LW_FLAG_WAKE_IN_PROGRESS flag, to make sure we get woken up
+ * as soon as the lock is released.
*/
- pg_atomic_fetch_or_u32(&lock->state, LW_FLAG_RELEASE_OK);
+ pg_atomic_fetch_and_u32(&lock->state, ~LW_FLAG_WAKE_IN_PROGRESS);
/*
* We're now guaranteed to be woken up if necessary. Recheck the lock
@@ -1852,11 +1850,11 @@ LWLockReleaseInternal(LWLock *lock, LWLockMode mode)
TRACE_POSTGRESQL_LWLOCK_RELEASE(T_NAME(lock));
/*
- * We're still waiting for backends to get scheduled, don't wake them up
- * again.
+ * Check if we're still waiting for backends to get scheduled, if so,
+ * don't wake them up again.
*/
- if ((oldstate & (LW_FLAG_HAS_WAITERS | LW_FLAG_RELEASE_OK)) ==
- (LW_FLAG_HAS_WAITERS | LW_FLAG_RELEASE_OK) &&
+ if ((oldstate & LW_FLAG_HAS_WAITERS) &&
+ !(oldstate & LW_FLAG_WAKE_IN_PROGRESS) &&
(oldstate & LW_LOCK_MASK) == 0)
check_waiters = true;
else
--
2.48.1.76.g4e746b1a31.dirty
--rkiyqpij3ajqn7ww
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
filename="v9-0005-bufmgr-Make-definitions-related-to-buffer-descrip.patch"
^ permalink raw reply [nested|flat] 15+ messages in thread
* [PATCH v10 1/8] lwlock: Invert meaning of LW_FLAG_RELEASE_OK
@ 2026-01-06 01:40 Andres Freund <[email protected]>
0 siblings, 0 replies; 15+ messages in thread
From: Andres Freund @ 2026-01-06 01:40 UTC (permalink / raw)
Previously, a flag was set to indicate that a lock release should wake up
waiters. Since waking waiters is the default behavior in the majority of
cases, this logic has been inverted. The new LW_FLAG_WAKE_IN_PROGRESS flag is
now set iff wakeups are explicitly inhibited.
The motivation for this change is that in an upcoming commit, content locks
will be implemented independently of lwlocks, with the lock state stored as
part of BufferDesc.state. As all of a buffer's flags are cleared when the
buffer is invalidated, without this change we would have to re-add the
RELEASE_OK flag after clearing the flags; otherwise, the next lock release
would not wake waiters.
It seems good to keep the implementation of lwlocks and buffer content locks
as similar as reasonably possible.
Discussion: https://postgr.es/m/4csodkvvfbfloxxjlkgsnl2lgfv2mtzdl7phqzd4jxjadxm4o5@usw7feyb5bzf
---
src/backend/storage/lmgr/lwlock.c | 42 +++++++++++++++----------------
1 file changed, 20 insertions(+), 22 deletions(-)
diff --git a/src/backend/storage/lmgr/lwlock.c b/src/backend/storage/lmgr/lwlock.c
index 6a9f86d5025..148309cc186 100644
--- a/src/backend/storage/lmgr/lwlock.c
+++ b/src/backend/storage/lmgr/lwlock.c
@@ -92,7 +92,7 @@
#define LW_FLAG_HAS_WAITERS ((uint32) 1 << 31)
-#define LW_FLAG_RELEASE_OK ((uint32) 1 << 30)
+#define LW_FLAG_WAKE_IN_PROGRESS ((uint32) 1 << 30)
#define LW_FLAG_LOCKED ((uint32) 1 << 29)
#define LW_FLAG_BITS 3
#define LW_FLAG_MASK (((1<<LW_FLAG_BITS)-1)<<(32-LW_FLAG_BITS))
@@ -246,14 +246,14 @@ PRINT_LWDEBUG(const char *where, LWLock *lock, LWLockMode mode)
ereport(LOG,
(errhidestmt(true),
errhidecontext(true),
- errmsg_internal("%d: %s(%s %p): excl %u shared %u haswaiters %u waiters %u rOK %d",
+ errmsg_internal("%d: %s(%s %p): excl %u shared %u haswaiters %u waiters %u waking %d",
MyProcPid,
where, T_NAME(lock), lock,
(state & LW_VAL_EXCLUSIVE) != 0,
state & LW_SHARED_MASK,
(state & LW_FLAG_HAS_WAITERS) != 0,
pg_atomic_read_u32(&lock->nwaiters),
- (state & LW_FLAG_RELEASE_OK) != 0)));
+ (state & LW_FLAG_WAKE_IN_PROGRESS) != 0)));
}
}
@@ -700,7 +700,7 @@ LWLockInitialize(LWLock *lock, int tranche_id)
/* verify the tranche_id is valid */
(void) GetLWTrancheName(tranche_id);
- pg_atomic_init_u32(&lock->state, LW_FLAG_RELEASE_OK);
+ pg_atomic_init_u32(&lock->state, 0);
#ifdef LOCK_DEBUG
pg_atomic_init_u32(&lock->nwaiters, 0);
#endif
@@ -929,15 +929,13 @@ LWLockWaitListUnlock(LWLock *lock)
static void
LWLockWakeup(LWLock *lock)
{
- bool new_release_ok;
+ bool new_release_in_progress = false;
bool wokeup_somebody = false;
proclist_head wakeup;
proclist_mutable_iter iter;
proclist_init(&wakeup);
- new_release_ok = true;
-
/* lock wait list while collecting backends to wake up */
LWLockWaitListLock(lock);
@@ -958,7 +956,7 @@ LWLockWakeup(LWLock *lock)
* that are just waiting for the lock to become free don't retry
* automatically.
*/
- new_release_ok = false;
+ new_release_in_progress = true;
/*
* Don't wakeup (further) exclusive locks.
@@ -997,10 +995,10 @@ LWLockWakeup(LWLock *lock)
/* compute desired flags */
- if (new_release_ok)
- desired_state |= LW_FLAG_RELEASE_OK;
+ if (new_release_in_progress)
+ desired_state |= LW_FLAG_WAKE_IN_PROGRESS;
else
- desired_state &= ~LW_FLAG_RELEASE_OK;
+ desired_state &= ~LW_FLAG_WAKE_IN_PROGRESS;
if (proclist_is_empty(&lock->waiters))
desired_state &= ~LW_FLAG_HAS_WAITERS;
@@ -1131,10 +1129,10 @@ LWLockDequeueSelf(LWLock *lock)
*/
/*
- * Reset RELEASE_OK flag if somebody woke us before we removed
- * ourselves - they'll have set it to false.
+ * Clear LW_FLAG_WAKE_IN_PROGRESS if somebody woke us before we
+ * removed ourselves - they'll have set it.
*/
- pg_atomic_fetch_or_u32(&lock->state, LW_FLAG_RELEASE_OK);
+ pg_atomic_fetch_and_u32(&lock->state, ~LW_FLAG_WAKE_IN_PROGRESS);
/*
* Now wait for the scheduled wakeup, otherwise our ->lwWaiting would
@@ -1301,7 +1299,7 @@ LWLockAcquire(LWLock *lock, LWLockMode mode)
}
/* Retrying, allow LWLockRelease to release waiters again. */
- pg_atomic_fetch_or_u32(&lock->state, LW_FLAG_RELEASE_OK);
+ pg_atomic_fetch_and_u32(&lock->state, ~LW_FLAG_WAKE_IN_PROGRESS);
#ifdef LOCK_DEBUG
{
@@ -1636,10 +1634,10 @@ LWLockWaitForVar(LWLock *lock, pg_atomic_uint64 *valptr, uint64 oldval,
LWLockQueueSelf(lock, LW_WAIT_UNTIL_FREE);
/*
- * Set RELEASE_OK flag, to make sure we get woken up as soon as the
- * lock is released.
+ * Clear LW_FLAG_WAKE_IN_PROGRESS flag, to make sure we get woken up
+ * as soon as the lock is released.
*/
- pg_atomic_fetch_or_u32(&lock->state, LW_FLAG_RELEASE_OK);
+ pg_atomic_fetch_and_u32(&lock->state, ~LW_FLAG_WAKE_IN_PROGRESS);
/*
* We're now guaranteed to be woken up if necessary. Recheck the lock
@@ -1852,11 +1850,11 @@ LWLockReleaseInternal(LWLock *lock, LWLockMode mode)
TRACE_POSTGRESQL_LWLOCK_RELEASE(T_NAME(lock));
/*
- * We're still waiting for backends to get scheduled, don't wake them up
- * again.
+ * Check if we're still waiting for backends to get scheduled, if so,
+ * don't wake them up again.
*/
- if ((oldstate & (LW_FLAG_HAS_WAITERS | LW_FLAG_RELEASE_OK)) ==
- (LW_FLAG_HAS_WAITERS | LW_FLAG_RELEASE_OK) &&
+ if ((oldstate & LW_FLAG_HAS_WAITERS) &&
+ !(oldstate & LW_FLAG_WAKE_IN_PROGRESS) &&
(oldstate & LW_LOCK_MASK) == 0)
check_waiters = true;
else
--
2.48.1.76.g4e746b1a31.dirty
--jmawlk4t5yqwiemy
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
filename="v10-0002-bufmgr-Make-definitions-related-to-buffer-descri.patch"
^ permalink raw reply [nested|flat] 15+ messages in thread
* Report index currently being vacuumed in pg_stat_progress_vacuum
@ 2026-05-04 02:00 Bharath Rupireddy <[email protected]>
2026-05-04 04:53 ` Re: Report index currently being vacuumed in pg_stat_progress_vacuum SATYANARAYANA NARLAPURAM <[email protected]>
2026-05-04 09:52 ` Re: Report index currently being vacuumed in pg_stat_progress_vacuum Antonin Houska <[email protected]>
2026-05-05 17:54 ` Re: Report index currently being vacuumed in pg_stat_progress_vacuum Sami Imseih <[email protected]>
0 siblings, 3 replies; 15+ messages in thread
From: Bharath Rupireddy @ 2026-05-04 02:00 UTC (permalink / raw)
To: PostgreSQL Hackers <[email protected]>
Hi,
When VACUUM is in the "vacuuming indexes" or "cleaning up indexes" phase,
there is currently no easy way to tell which specific index is being
processed. The progress report view shows indexes_total and
indexes_processed counters, but not which index is actively being worked on.
This makes it difficult to debug slow or stuck autovacuum workers on tables
with multiple indexes of different types (btree, GIN, GiST, BRIN, HNSW,
etc.), since one cannot determine which index type or which specific index
is causing the delay.
Please find the attached patch adds a new column current_index_relid to
pg_stat_progress_vacuum that reports the OID of the index currently being
vacuumed or cleaned up. The column is reported for both the "vacuuming
indexes" phase and the "cleaning up indexes" phase.
When indexes are being vacuumed in parallel, each parallel worker emits its
own row in pg_stat_progress_vacuum with current_index_relid set to the
index it is currently processing, and leader_pid pointing to the leader
process.
Appreciate any feedback. Thank you!
[1] Example output:
pid | datname | relid | table_name | phase | started_by |
current_index_relid | index_name | leader_pid
------+----------+-------+------------+-------------------+------------+---------------------+---------------+------------
1420 | postgres | 16395 | vac_test | vacuuming indexes | autovacuum |
16398 | vac_test_idx1 |
1421 | postgres | 16395 | vac_test | vacuuming indexes | |
16399 | vac_test_idx2 | 1420
1423 | postgres | 16395 | vac_test | vacuuming indexes | |
16400 | vac_test_idx3 | 1420
(3 rows)
pid | datname | relid | table_name | phase | started_by |
current_index_relid | index_name | leader_pid
------+----------+-------+------------+-------------------+------------+---------------------+---------------+------------
1346 | postgres | 16395 | vac_test | vacuuming indexes | manual |
16398 | vac_test_idx1 |
(1 row)
[2]
SELECT v.pid, v.datname, v.relid, c.relname AS table_name,
v.phase, v.started_by, v.current_index_relid,
COALESCE(ic.relname, '') AS index_name, v.leader_pid
FROM pg_stat_progress_vacuum v
JOIN pg_class c
ON c.oid = v.relid
LEFT JOIN pg_class ic
ON ic.oid = v.current_index_relid
WHERE v.relid = $tbl_oid
ORDER BY
v.leader_pid,
v.pid;
--
Bharath Rupireddy
Amazon Web Services: https://aws.amazon.com
Attachments:
[application/x-patch] v1-0001-Report-index-currently-being-vacuumed-in-pg_stat_.patch (10.5K, ../../CALj2ACUgwSchK6jQ2CdKLBWUADTOE_zKdTff2Zg3E6hOuXKv-w@mail.gmail.com/3-v1-0001-Report-index-currently-being-vacuumed-in-pg_stat_.patch)
download | inline diff:
From 556d8c4a8db1b1ee23f19631e8c94ac702a26042 Mon Sep 17 00:00:00 2001
From: Bharath Rupireddy <[email protected]>
Date: Fri, 17 Apr 2026 22:11:20 +0000
Subject: [PATCH v1] Report index currently being vacuumed in
pg_stat_progress_vacuum
When VACUUM is in the "vacuuming indexes" or "cleaning up indexes"
phase, there is no way to tell which specific index is being
processed. The view shows indexes_total and indexes_processed
counters, but not which index is actively being worked on.
This makes it difficult to debug slow or stuck autovacuum workers
on tables with multiple indexes (btree, GIN, GiST, BRIN, HNSW,
etc.), since one cannot determine which index type or which specific
index is causing the delay.
This commit adds a new column current_index_relid to
pg_stat_progress_vacuum that reports the OID of the index currently
being vacuumed or cleaned up. The value is set before each index
vacuum/cleanup begins and reset to 0 when all indexes have been
processed.
The column is reported for both the "vacuuming indexes" phase and
the "cleaning up indexes" phase.
When indexes are vacuumed in parallel, each parallel worker emits
its own row in pg_stat_progress_vacuum with current_index_relid set
to the index it is processing, and leader_pid set to the PID of the
leader. For the leader process itself (or non-parallel vacuum),
leader_pid is NULL.
---
doc/src/sgml/monitoring.sgml | 26 ++++++++++++++++++++++++++
src/backend/access/heap/vacuumlazy.c | 16 ++++++++++++++++
src/backend/access/transam/parallel.c | 9 +++++++++
src/backend/catalog/system_views.sql | 4 +++-
src/backend/commands/vacuumparallel.c | 21 +++++++++++++++++++++
src/include/access/parallel.h | 1 +
src/include/commands/progress.h | 2 ++
src/test/regress/expected/rules.out | 4 +++-
8 files changed, 81 insertions(+), 2 deletions(-)
diff --git a/doc/src/sgml/monitoring.sgml b/doc/src/sgml/monitoring.sgml
index 08d5b824552..0a7223608e6 100644
--- a/doc/src/sgml/monitoring.sgml
+++ b/doc/src/sgml/monitoring.sgml
@@ -7577,6 +7577,32 @@ FROM pg_stat_get_backend_idset() AS backendid;
</itemizedlist>
</para></entry>
</row>
+
+ <row>
+ <entry role="catalog_table_entry"><para role="column_definition">
+ <structfield>current_index_relid</structfield> <type>oid</type>
+ </para>
+ <para>
+ If <command>VACUUM</command> is currently processing an index, this
+ column shows the OID of the index being vacuumed. The value is set
+ when the phase is <literal>vacuuming indexes</literal> or
+ <literal>cleaning up indexes</literal> and is reset to 0 when all
+ indexes have been processed. During parallel index vacuum, each
+ parallel worker row shows the index that particular worker is
+ processing.
+ </para></entry>
+ </row>
+
+ <row>
+ <entry role="catalog_table_entry"><para role="column_definition">
+ <structfield>leader_pid</structfield> <type>bigint</type>
+ </para>
+ <para>
+ Process ID of the leader process if this process is a parallel
+ vacuum worker; <literal>NULL</literal> if this process is the
+ leader itself or if the vacuum is not running in parallel.
+ </para></entry>
+ </row>
</tbody>
</tgroup>
</table>
diff --git a/src/backend/access/heap/vacuumlazy.c b/src/backend/access/heap/vacuumlazy.c
index 39395aed0d5..ea040036251 100644
--- a/src/backend/access/heap/vacuumlazy.c
+++ b/src/backend/access/heap/vacuumlazy.c
@@ -3025,6 +3025,10 @@ lazy_vacuum_one_index(Relation indrel, IndexBulkDeleteResult *istat,
ivinfo.num_heap_tuples = reltuples;
ivinfo.strategy = vacrel->bstrategy;
+ /* Report which index we're currently processing */
+ pgstat_progress_update_param(PROGRESS_VACUUM_CURRENT_INDEX_RELID,
+ (int64) RelationGetRelid(indrel));
+
/*
* Update error traceback information.
*
@@ -3046,6 +3050,10 @@ lazy_vacuum_one_index(Relation indrel, IndexBulkDeleteResult *istat,
pfree(vacrel->indname);
vacrel->indname = NULL;
+ /* Reset the current index relid to avoid reporting a stale value */
+ pgstat_progress_update_param(PROGRESS_VACUUM_CURRENT_INDEX_RELID,
+ (int64) InvalidOid);
+
return istat;
}
@@ -3076,6 +3084,10 @@ lazy_cleanup_one_index(Relation indrel, IndexBulkDeleteResult *istat,
ivinfo.num_heap_tuples = reltuples;
ivinfo.strategy = vacrel->bstrategy;
+ /* Report which index we're currently processing */
+ pgstat_progress_update_param(PROGRESS_VACUUM_CURRENT_INDEX_RELID,
+ (int64) RelationGetRelid(indrel));
+
/*
* Update error traceback information.
*
@@ -3095,6 +3107,10 @@ lazy_cleanup_one_index(Relation indrel, IndexBulkDeleteResult *istat,
pfree(vacrel->indname);
vacrel->indname = NULL;
+ /* Reset the current index relid to avoid reporting a stale value */
+ pgstat_progress_update_param(PROGRESS_VACUUM_CURRENT_INDEX_RELID,
+ (int64) InvalidOid);
+
return istat;
}
diff --git a/src/backend/access/transam/parallel.c b/src/backend/access/transam/parallel.c
index 89e9d224eec..23a2e5eecf0 100644
--- a/src/backend/access/transam/parallel.c
+++ b/src/backend/access/transam/parallel.c
@@ -131,6 +131,15 @@ static dlist_head pcxt_list = DLIST_STATIC_INIT(pcxt_list);
/* Backend-local copy of data from FixedParallelState. */
static pid_t ParallelLeaderPid;
+/*
+ * Return the PID of the parallel group leader.
+ */
+pid_t
+GetParallelLeaderPid(void)
+{
+ return ParallelLeaderPid;
+}
+
/*
* List of internal parallel worker entry points. We need this for
* reasons explained in LookupParallelWorkerFunction(), below.
diff --git a/src/backend/catalog/system_views.sql b/src/backend/catalog/system_views.sql
index 73a1c1c4670..22e9294bacc 100644
--- a/src/backend/catalog/system_views.sql
+++ b/src/backend/catalog/system_views.sql
@@ -1342,7 +1342,9 @@ CREATE VIEW pg_stat_progress_vacuum AS
CASE S.param13 WHEN 1 THEN 'manual'
WHEN 2 THEN 'autovacuum'
WHEN 3 THEN 'autovacuum_wraparound'
- ELSE NULL END AS started_by
+ ELSE NULL END AS started_by,
+ CAST(S.param14 AS oid) AS current_index_relid,
+ NULLIF(S.param15, 0) AS leader_pid
FROM pg_stat_get_progress_info('VACUUM') AS S
LEFT JOIN pg_database D ON S.datid = D.oid;
diff --git a/src/backend/commands/vacuumparallel.c b/src/backend/commands/vacuumparallel.c
index 979c2be4abd..613b379a3ca 100644
--- a/src/backend/commands/vacuumparallel.c
+++ b/src/backend/commands/vacuumparallel.c
@@ -36,6 +36,7 @@
#include "postgres.h"
#include "access/amapi.h"
+#include "access/parallel.h"
#include "access/table.h"
#include "access/xact.h"
#include "commands/progress.h"
@@ -1076,6 +1077,11 @@ parallel_vacuum_process_one_index(ParallelVacuumState *pvs, Relation indrel,
IndexBulkDeleteResult *istat = NULL;
IndexBulkDeleteResult *istat_res;
IndexVacuumInfo ivinfo;
+ const int progress_index[] = {
+ PROGRESS_VACUUM_PHASE,
+ PROGRESS_VACUUM_CURRENT_INDEX_RELID
+ };
+ int64 progress_val[2];
/*
* Update the pointer to the corresponding bulk-deletion result if someone
@@ -1112,6 +1118,13 @@ parallel_vacuum_process_one_index(ParallelVacuumState *pvs, Relation indrel,
RelationGetRelationName(indrel));
}
+ /* Report which index we're currently processing and the current phase */
+ progress_val[0] = (indstats->status == PARALLEL_INDVAC_STATUS_NEED_BULKDELETE)
+ ? PROGRESS_VACUUM_PHASE_VACUUM_INDEX
+ : PROGRESS_VACUUM_PHASE_INDEX_CLEANUP;
+ progress_val[1] = (int64) RelationGetRelid(indrel);
+ pgstat_progress_update_multi_param(2, progress_index, progress_val);
+
/*
* Copy the index bulk-deletion result returned from ambulkdelete and
* amvacuumcleanup to the DSM segment if it's the first cycle because they
@@ -1307,6 +1320,11 @@ parallel_vacuum_main(dsm_segment *seg, shm_toc *toc)
/* Prepare to track buffer usage during parallel execution */
InstrStartParallelQuery();
+ /* Register this worker for vacuum progress reporting */
+ pgstat_progress_start_command(PROGRESS_COMMAND_VACUUM, shared->relid);
+ pgstat_progress_update_param(PROGRESS_VACUUM_LEADER_PID,
+ (int64) GetParallelLeaderPid());
+
/* Process indexes to perform vacuum/cleanup */
parallel_vacuum_process_safe_indexes(&pvs);
@@ -1326,6 +1344,9 @@ parallel_vacuum_main(dsm_segment *seg, shm_toc *toc)
/* Pop the error context stack */
error_context_stack = errcallback.previous;
+ /* Unregister this worker from vacuum progress reporting */
+ pgstat_progress_end_command();
+
vac_close_indexes(nindexes, indrels, RowExclusiveLock);
table_close(rel, ShareUpdateExclusiveLock);
FreeAccessStrategy(pvs.bstrategy);
diff --git a/src/include/access/parallel.h b/src/include/access/parallel.h
index 60f857675e0..d329a2424bd 100644
--- a/src/include/access/parallel.h
+++ b/src/include/access/parallel.h
@@ -77,6 +77,7 @@ extern void ProcessParallelMessages(void);
extern void AtEOXact_Parallel(bool isCommit);
extern void AtEOSubXact_Parallel(bool isCommit, SubTransactionId mySubId);
extern void ParallelWorkerReportLastRecEnd(XLogRecPtr last_xlog_end);
+extern pid_t GetParallelLeaderPid(void);
extern void ParallelWorkerMain(Datum main_arg);
diff --git a/src/include/commands/progress.h b/src/include/commands/progress.h
index 2a12920c75f..f9f3e187718 100644
--- a/src/include/commands/progress.h
+++ b/src/include/commands/progress.h
@@ -31,6 +31,8 @@
#define PROGRESS_VACUUM_DELAY_TIME 10
#define PROGRESS_VACUUM_MODE 11
#define PROGRESS_VACUUM_STARTED_BY 12
+#define PROGRESS_VACUUM_CURRENT_INDEX_RELID 13
+#define PROGRESS_VACUUM_LEADER_PID 14
/* Phases of vacuum (as advertised via PROGRESS_VACUUM_PHASE) */
#define PROGRESS_VACUUM_PHASE_SCAN_HEAP 1
diff --git a/src/test/regress/expected/rules.out b/src/test/regress/expected/rules.out
index a65a5bf0c4f..00c0af6c24c 100644
--- a/src/test/regress/expected/rules.out
+++ b/src/test/regress/expected/rules.out
@@ -2202,7 +2202,9 @@ pg_stat_progress_vacuum| SELECT s.pid,
WHEN 2 THEN 'autovacuum'::text
WHEN 3 THEN 'autovacuum_wraparound'::text
ELSE NULL::text
- END AS started_by
+ END AS started_by,
+ (s.param14)::oid AS current_index_relid,
+ NULLIF(s.param15, 0) AS leader_pid
FROM (pg_stat_get_progress_info('VACUUM'::text) s(pid, datid, relid, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, param20)
LEFT JOIN pg_database d ON ((s.datid = d.oid)));
pg_stat_recovery| SELECT promote_triggered,
--
2.47.3
^ permalink raw reply [nested|flat] 15+ messages in thread
* Re: Report index currently being vacuumed in pg_stat_progress_vacuum
2026-05-04 02:00 Report index currently being vacuumed in pg_stat_progress_vacuum Bharath Rupireddy <[email protected]>
@ 2026-05-04 04:53 ` SATYANARAYANA NARLAPURAM <[email protected]>
2 siblings, 0 replies; 15+ messages in thread
From: SATYANARAYANA NARLAPURAM @ 2026-05-04 04:53 UTC (permalink / raw)
To: Bharath Rupireddy <[email protected]>; +Cc: PostgreSQL Hackers <[email protected]>
Hi,
On Sun, May 3, 2026 at 7:01 PM Bharath Rupireddy <
[email protected]> wrote:
> Hi,
>
> When VACUUM is in the "vacuuming indexes" or "cleaning up indexes" phase,
> there is currently no easy way to tell which specific index is being
> processed. The progress report view shows indexes_total and
> indexes_processed counters, but not which index is actively being worked on.
>
> This makes it difficult to debug slow or stuck autovacuum workers on
> tables with multiple indexes of different types (btree, GIN, GiST, BRIN,
> HNSW, etc.), since one cannot determine which index type or which specific
> index is causing the delay.
>
> Please find the attached patch adds a new column current_index_relid to
> pg_stat_progress_vacuum that reports the OID of the index currently being
> vacuumed or cleaned up. The column is reported for both the "vacuuming
> indexes" phase and the "cleaning up indexes" phase.
>
> When indexes are being vacuumed in parallel, each parallel worker emits
> its own row in pg_stat_progress_vacuum with current_index_relid set to the
> index it is currently processing, and leader_pid pointing to the leader
> process.
>
> Appreciate any feedback. Thank you!
>
> [1] Example output:
>
> pid | datname | relid | table_name | phase | started_by |
> current_index_relid | index_name | leader_pid
>
> ------+----------+-------+------------+-------------------+------------+---------------------+---------------+------------
> 1420 | postgres | 16395 | vac_test | vacuuming indexes | autovacuum |
> 16398 | vac_test_idx1 |
> 1421 | postgres | 16395 | vac_test | vacuuming indexes | |
> 16399 | vac_test_idx2 | 1420
> 1423 | postgres | 16395 | vac_test | vacuuming indexes | |
> 16400 | vac_test_idx3 | 1420
> (3 rows)
>
> pid | datname | relid | table_name | phase | started_by |
> current_index_relid | index_name | leader_pid
>
> ------+----------+-------+------------+-------------------+------------+---------------------+---------------+------------
> 1346 | postgres | 16395 | vac_test | vacuuming indexes | manual |
> 16398 | vac_test_idx1 |
> (1 row)
>
> [2]
> SELECT v.pid, v.datname, v.relid, c.relname AS table_name,
> v.phase, v.started_by, v.current_index_relid,
> COALESCE(ic.relname, '') AS index_name, v.leader_pid
> FROM pg_stat_progress_vacuum v
> JOIN pg_class c
> ON c.oid = v.relid
> LEFT JOIN pg_class ic
> ON ic.oid = v.current_index_relid
> WHERE v.relid = $tbl_oid
> ORDER BY
> v.leader_pid,
> v.pid;
>
Bharath, thanks for the patch! A few comments:
(1) Do we need a global API? Can we add a leader_pid field in PVShared?
+pid_t
+GetParallelLeaderPid(void)
+{
+ return ParallelLeaderPid;
+}
(2): Looks like current_index_relid is not cleared when we leave the index
phases.As a result, once any index has been processed,
pg_stat_progress_vacuum.current_index_relid keeps reporting that relid
through vacuuming heap, truncating heap, cleaning up indexes.
This will be confusing to the user. Something like below:
1795819|vacuuming heap|0/0|16392|t1_pkey|LEADER
(3) leader_pid type should be integer type similar to pg_Stat_activity?
Thanks,
Satya
^ permalink raw reply [nested|flat] 15+ messages in thread
* Re: Report index currently being vacuumed in pg_stat_progress_vacuum
2026-05-04 02:00 Report index currently being vacuumed in pg_stat_progress_vacuum Bharath Rupireddy <[email protected]>
@ 2026-05-04 09:52 ` Antonin Houska <[email protected]>
2 siblings, 0 replies; 15+ messages in thread
From: Antonin Houska @ 2026-05-04 09:52 UTC (permalink / raw)
To: Bharath Rupireddy <[email protected]>; +Cc: PostgreSQL Hackers <[email protected]>
Bharath Rupireddy <[email protected]> wrote:
> When VACUUM is in the "vacuuming indexes" or "cleaning up indexes" phase, there is currently no easy way to tell which specific index is
> being processed. The progress report view shows indexes_total and indexes_processed counters, but not which index is actively being worked
> on.
>
> This makes it difficult to debug slow or stuck autovacuum workers on tables with multiple indexes of different types (btree, GIN, GiST, BRIN,
> HNSW, etc.), since one cannot determine which index type or which specific index is causing the delay.
>
> Please find the attached patch adds a new column current_index_relid to pg_stat_progress_vacuum that reports the OID of the index
> currently being vacuumed or cleaned up. The column is reported for both the "vacuuming indexes" phase and the "cleaning up indexes"
> phase.
>
> When indexes are being vacuumed in parallel, each parallel worker emits its own row in pg_stat_progress_vacuum with current_index_relid
> set to the index it is currently processing, and leader_pid pointing to the leader process.
>
> Appreciate any feedback. Thank you!
This problem seems to be similar to what I noticed when workign on the REPACK
command: progress reporting of index build needs to be disabled if the build
is part of REPACK, otherwise the index build can overwrite the counters of
REPACK (whether the overwriting actually happens or not is another question).
The solution I suggest is to allow progress tracking of a "sub-command" - see
the attached patch. Wouldn't that also resolve your problem? (My plan is to
incorporate this in the series of REPACK enhancements soon.)
--
Antonin Houska
Web: https://www.cybertec-postgresql.com
^ permalink raw reply [nested|flat] 15+ messages in thread
* Re: Report index currently being vacuumed in pg_stat_progress_vacuum
2026-05-04 02:00 Report index currently being vacuumed in pg_stat_progress_vacuum Bharath Rupireddy <[email protected]>
@ 2026-05-05 17:54 ` Sami Imseih <[email protected]>
2026-06-29 15:31 ` Re: Report index currently being vacuumed in pg_stat_progress_vacuum Bharath Rupireddy <[email protected]>
2 siblings, 1 reply; 15+ messages in thread
From: Sami Imseih @ 2026-05-05 17:54 UTC (permalink / raw)
To: Bharath Rupireddy <[email protected]>; +Cc: PostgreSQL Hackers <[email protected]>
Hi,
> Appreciate any feedback. Thank you!
I think it is valuable to show the index being processed. There is
really no other easy way to get this information except for pstack,
etc. I am +1 for the idea.
However, I am not sure that having a separate row for every parallel
worker is the right approach. The pg_stat_progress_* views are designed
to show progress per row. Each row represents one command with
meaningful progress counters (heap_blks_scanned, indexes_total,
indexes_processed, etc.). A parallel worker row would only show
current_index_relid and leader_pid with no actual progress information
of its own. That is status, not progress, and it does not fit the
view. Also, many columns would remain empty or redundant with the
leader's row.
Instead, could we aggregate the parallel worker information into the
leader's row. For example, an array of worker PIDs in one column and an
array of index relids in another?
--
Sami Imseih
Amazon Web Services (AWS)
^ permalink raw reply [nested|flat] 15+ messages in thread
* Re: Report index currently being vacuumed in pg_stat_progress_vacuum
2026-05-04 02:00 Report index currently being vacuumed in pg_stat_progress_vacuum Bharath Rupireddy <[email protected]>
2026-05-05 17:54 ` Re: Report index currently being vacuumed in pg_stat_progress_vacuum Sami Imseih <[email protected]>
@ 2026-06-29 15:31 ` Bharath Rupireddy <[email protected]>
0 siblings, 0 replies; 15+ messages in thread
From: Bharath Rupireddy @ 2026-06-29 15:31 UTC (permalink / raw)
To: Sami Imseih <[email protected]>; +Cc: PostgreSQL Hackers <[email protected]>
Hi,
On Tue, May 5, 2026 at 10:54 AM Sami Imseih <[email protected]> wrote:
>
> I think it is valuable to show the index being processed. There is
> really no other easy way to get this information except for pstack,
> etc. I am +1 for the idea.
Thanks for reviewing this!
> However, I am not sure that having a separate row for every parallel
> worker is the right approach. The pg_stat_progress_* views are designed
> to show progress per row. Each row represents one command with
> meaningful progress counters (heap_blks_scanned, indexes_total,
> indexes_processed, etc.). A parallel worker row would only show
> current_index_relid and leader_pid with no actual progress information
> of its own. That is status, not progress, and it does not fit the
> view. Also, many columns would remain empty or redundant with the
> leader's row.
>
> Instead, could we aggregate the parallel worker information into the
> leader's row. For example, an array of worker PIDs in one column and an
> array of index relids in another?
Thanks for the review. I read f1889729 and it looks like the
preference was to keep one command = one row, with workers feeding the
leader's row rather than showing up as separate rows. I want to stay
with that approach.
I considered having the leader set up a DSA that workers write into,
shown as an extra column on the leader's row. But that means new
shared memory whose handle has to be stored somewhere other backends
can find it, attached by the reader, and freed safely while a
monitoring query might still be reading it - that's a lot of work for
a small amount of per-worker data.
The simpler approach is to have workers report the index they're
currently on into their own st_progress_param[] slots, which already
exist per backend, along with their leader's pid. The view then groups
the worker entries under the matching leader's pid and shows only the
leader rows, so no new shared memory is needed. The current index oid
column has to be added to that array anyway for the non-parallel case,
which needs it just as much, and the parallel workers already have
their own slots to report into, so there's nothing extra to set up.
One thing to note is that pg_stat_get_progress_info('VACUUM') itself
would still return the worker rows, and the grouping happens in the
pg_stat_progress_vacuum view instead. I prefer keeping it in the view
rather than the function. The function is shared by all the progress
commands and only deals with raw params, while the leader pid grouping
is specific to VACUUM. This way the shared function stays unchanged
and the other progress views are not affected.
While I'm here, in the "vacuuming indexes" phase I also want to report
the total index pages to scan and the pages scanned so far, for the
index currently being vacuumed. On a large index this phase can run
for a long time with no way to tell whether it's making progress.
Does this direction sound reasonable, or do you see a reason to prefer
a different approach?
--
Bharath Rupireddy
Amazon Web Services: https://aws.amazon.com
^ permalink raw reply [nested|flat] 15+ messages in thread
end of thread, other threads:[~2026-06-29 15:31 UTC | newest]
Thread overview: 15+ messages (download: mbox mbox.gz follow: Atom feed)
-- links below jump to the message on this page --
2019-05-20 17:57 [PATCH v5 06/12] consistent language: not implemented Justin Pryzby <[email protected]>
2019-05-20 17:57 [PATCH v3 06/12] consistent language: not implemented Justin Pryzby <[email protected]>
2023-07-12 12:19 [PATCH] Document RelationGetIndexAttrBitmap better Alvaro Herrera <[email protected]>
2023-07-12 12:19 [PATCH] Document RelationGetIndexAttrBitmap better Alvaro Herrera <[email protected]>
2023-07-12 12:19 [PATCH] Document RelationGetIndexAttrBitmap better Alvaro Herrera <[email protected]>
2026-01-06 01:40 [PATCH v9 04/10] lwlock: Invert meaning of LW_FLAG_RELEASE_OK Andres Freund <[email protected]>
2026-01-06 01:40 [PATCH v10 1/8] lwlock: Invert meaning of LW_FLAG_RELEASE_OK Andres Freund <[email protected]>
2026-01-06 01:40 [PATCH v9 04/10] lwlock: Invert meaning of LW_FLAG_RELEASE_OK Andres Freund <[email protected]>
2026-01-06 01:40 [PATCH v9 04/10] lwlock: Invert meaning of LW_FLAG_RELEASE_OK Andres Freund <[email protected]>
2026-01-06 01:40 [PATCH v10 1/8] lwlock: Invert meaning of LW_FLAG_RELEASE_OK Andres Freund <[email protected]>
2026-05-04 02:00 Report index currently being vacuumed in pg_stat_progress_vacuum Bharath Rupireddy <[email protected]>
2026-05-04 04:53 ` Re: Report index currently being vacuumed in pg_stat_progress_vacuum SATYANARAYANA NARLAPURAM <[email protected]>
2026-05-04 09:52 ` Re: Report index currently being vacuumed in pg_stat_progress_vacuum Antonin Houska <[email protected]>
2026-05-05 17:54 ` Re: Report index currently being vacuumed in pg_stat_progress_vacuum Sami Imseih <[email protected]>
2026-06-29 15:31 ` Re: Report index currently being vacuumed in pg_stat_progress_vacuum Bharath Rupireddy <[email protected]>
This inbox is served by agora; see mirroring instructions
for how to clone and mirror all data and code used for this inbox