agora inbox for pgsql-hackers@postgresql.org
help / color / mirror / Atom feed[PATCH v2 4/6] Introduce pending flag for GUC assign hooks
319+ messages / 1 participants
[nested] [flat]
* [PATCH v2 4/6] Introduce pending flag for GUC assign hooks
@ 2025-02-19 16:45 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-02-19 16:45 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 2 +-
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 16 ++++----
8 files changed, 57 insertions(+), 36 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index f9bf5ba7509..ff82ba0a53d 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2188,7 +2188,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 4ad6e236d69..f24c2a0d252 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
#ifdef USE_PREFETCH
/*
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index 61ea3722ae2..cdf21847d7e 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1949,7 +1949,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1982,7 +1982,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2005,7 +2005,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2028,7 +2028,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 1149d89d7a1..13fb8c31702 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3555,7 +3555,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 12192445218..bab1c5d08f6 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index 1233e07d7da..ce9f258100d 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 951451a9765..3e380f29e5a 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,12 +81,12 @@ extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
extern bool check_maintenance_io_concurrency(int *newval, void **extra,
GucSource source);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -141,13 +141,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -163,7 +163,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--q7xzg7duksj2kgko
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v2-0005-Allow-to-resize-shared-memory-without-restart.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v2 4/6] Introduce pending flag for GUC assign hooks
@ 2025-02-19 16:45 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-02-19 16:45 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 2 +-
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 16 ++++----
8 files changed, 57 insertions(+), 36 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index f9bf5ba7509..ff82ba0a53d 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2188,7 +2188,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 4ad6e236d69..f24c2a0d252 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
#ifdef USE_PREFETCH
/*
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index 61ea3722ae2..cdf21847d7e 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1949,7 +1949,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1982,7 +1982,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2005,7 +2005,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2028,7 +2028,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 1149d89d7a1..13fb8c31702 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3555,7 +3555,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 12192445218..bab1c5d08f6 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index 1233e07d7da..ce9f258100d 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 951451a9765..3e380f29e5a 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,12 +81,12 @@ extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
extern bool check_maintenance_io_concurrency(int *newval, void **extra,
GucSource source);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -141,13 +141,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -163,7 +163,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--q7xzg7duksj2kgko
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v2-0005-Allow-to-resize-shared-memory-without-restart.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v2 4/6] Introduce pending flag for GUC assign hooks
@ 2025-02-19 16:45 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-02-19 16:45 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 2 +-
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 16 ++++----
8 files changed, 57 insertions(+), 36 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index f9bf5ba7509..ff82ba0a53d 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2188,7 +2188,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 4ad6e236d69..f24c2a0d252 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
#ifdef USE_PREFETCH
/*
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index 61ea3722ae2..cdf21847d7e 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1949,7 +1949,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1982,7 +1982,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2005,7 +2005,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2028,7 +2028,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 1149d89d7a1..13fb8c31702 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3555,7 +3555,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 12192445218..bab1c5d08f6 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index 1233e07d7da..ce9f258100d 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 951451a9765..3e380f29e5a 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,12 +81,12 @@ extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
extern bool check_maintenance_io_concurrency(int *newval, void **extra,
GucSource source);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -141,13 +141,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -163,7 +163,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--q7xzg7duksj2kgko
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v2-0005-Allow-to-resize-shared-memory-without-restart.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v2 4/6] Introduce pending flag for GUC assign hooks
@ 2025-02-19 16:45 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-02-19 16:45 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 2 +-
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 16 ++++----
8 files changed, 57 insertions(+), 36 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index f9bf5ba7509..ff82ba0a53d 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2188,7 +2188,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 4ad6e236d69..f24c2a0d252 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
#ifdef USE_PREFETCH
/*
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index 61ea3722ae2..cdf21847d7e 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1949,7 +1949,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1982,7 +1982,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2005,7 +2005,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2028,7 +2028,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 1149d89d7a1..13fb8c31702 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3555,7 +3555,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 12192445218..bab1c5d08f6 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index 1233e07d7da..ce9f258100d 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 951451a9765..3e380f29e5a 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,12 +81,12 @@ extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
extern bool check_maintenance_io_concurrency(int *newval, void **extra,
GucSource source);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -141,13 +141,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -163,7 +163,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--q7xzg7duksj2kgko
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v2-0005-Allow-to-resize-shared-memory-without-restart.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v2 4/6] Introduce pending flag for GUC assign hooks
@ 2025-02-19 16:45 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-02-19 16:45 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 2 +-
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 16 ++++----
8 files changed, 57 insertions(+), 36 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index f9bf5ba7509..ff82ba0a53d 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2188,7 +2188,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 4ad6e236d69..f24c2a0d252 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
#ifdef USE_PREFETCH
/*
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index 61ea3722ae2..cdf21847d7e 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1949,7 +1949,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1982,7 +1982,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2005,7 +2005,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2028,7 +2028,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 1149d89d7a1..13fb8c31702 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3555,7 +3555,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 12192445218..bab1c5d08f6 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index 1233e07d7da..ce9f258100d 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 951451a9765..3e380f29e5a 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,12 +81,12 @@ extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
extern bool check_maintenance_io_concurrency(int *newval, void **extra,
GucSource source);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -141,13 +141,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -163,7 +163,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--q7xzg7duksj2kgko
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v2-0005-Allow-to-resize-shared-memory-without-restart.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v2 4/6] Introduce pending flag for GUC assign hooks
@ 2025-02-19 16:45 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-02-19 16:45 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 2 +-
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 16 ++++----
8 files changed, 57 insertions(+), 36 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index f9bf5ba7509..ff82ba0a53d 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2188,7 +2188,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 4ad6e236d69..f24c2a0d252 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
#ifdef USE_PREFETCH
/*
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index 61ea3722ae2..cdf21847d7e 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1949,7 +1949,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1982,7 +1982,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2005,7 +2005,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2028,7 +2028,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 1149d89d7a1..13fb8c31702 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3555,7 +3555,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 12192445218..bab1c5d08f6 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index 1233e07d7da..ce9f258100d 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 951451a9765..3e380f29e5a 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,12 +81,12 @@ extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
extern bool check_maintenance_io_concurrency(int *newval, void **extra,
GucSource source);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -141,13 +141,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -163,7 +163,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--q7xzg7duksj2kgko
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v2-0005-Allow-to-resize-shared-memory-without-restart.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v2 4/6] Introduce pending flag for GUC assign hooks
@ 2025-02-19 16:45 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-02-19 16:45 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 2 +-
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 16 ++++----
8 files changed, 57 insertions(+), 36 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index f9bf5ba7509..ff82ba0a53d 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2188,7 +2188,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 4ad6e236d69..f24c2a0d252 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
#ifdef USE_PREFETCH
/*
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index 61ea3722ae2..cdf21847d7e 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1949,7 +1949,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1982,7 +1982,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2005,7 +2005,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2028,7 +2028,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 1149d89d7a1..13fb8c31702 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3555,7 +3555,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 12192445218..bab1c5d08f6 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index 1233e07d7da..ce9f258100d 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 951451a9765..3e380f29e5a 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,12 +81,12 @@ extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
extern bool check_maintenance_io_concurrency(int *newval, void **extra,
GucSource source);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -141,13 +141,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -163,7 +163,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--q7xzg7duksj2kgko
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v2-0005-Allow-to-resize-shared-memory-without-restart.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v2 4/6] Introduce pending flag for GUC assign hooks
@ 2025-02-19 16:45 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-02-19 16:45 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 2 +-
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 16 ++++----
8 files changed, 57 insertions(+), 36 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index f9bf5ba7509..ff82ba0a53d 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2188,7 +2188,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 4ad6e236d69..f24c2a0d252 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
#ifdef USE_PREFETCH
/*
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index 61ea3722ae2..cdf21847d7e 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1949,7 +1949,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1982,7 +1982,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2005,7 +2005,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2028,7 +2028,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 1149d89d7a1..13fb8c31702 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3555,7 +3555,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 12192445218..bab1c5d08f6 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index 1233e07d7da..ce9f258100d 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 951451a9765..3e380f29e5a 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,12 +81,12 @@ extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
extern bool check_maintenance_io_concurrency(int *newval, void **extra,
GucSource source);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -141,13 +141,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -163,7 +163,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--q7xzg7duksj2kgko
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v2-0005-Allow-to-resize-shared-memory-without-restart.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v2 4/6] Introduce pending flag for GUC assign hooks
@ 2025-02-19 16:45 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-02-19 16:45 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 2 +-
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 16 ++++----
8 files changed, 57 insertions(+), 36 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index f9bf5ba7509..ff82ba0a53d 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2188,7 +2188,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 4ad6e236d69..f24c2a0d252 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
#ifdef USE_PREFETCH
/*
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index 61ea3722ae2..cdf21847d7e 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1949,7 +1949,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1982,7 +1982,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2005,7 +2005,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2028,7 +2028,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 1149d89d7a1..13fb8c31702 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3555,7 +3555,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 12192445218..bab1c5d08f6 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index 1233e07d7da..ce9f258100d 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 951451a9765..3e380f29e5a 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,12 +81,12 @@ extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
extern bool check_maintenance_io_concurrency(int *newval, void **extra,
GucSource source);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -141,13 +141,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -163,7 +163,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--q7xzg7duksj2kgko
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v2-0005-Allow-to-resize-shared-memory-without-restart.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v2 4/6] Introduce pending flag for GUC assign hooks
@ 2025-02-19 16:45 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-02-19 16:45 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 2 +-
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 16 ++++----
8 files changed, 57 insertions(+), 36 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index f9bf5ba7509..ff82ba0a53d 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2188,7 +2188,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 4ad6e236d69..f24c2a0d252 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
#ifdef USE_PREFETCH
/*
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index 61ea3722ae2..cdf21847d7e 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1949,7 +1949,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1982,7 +1982,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2005,7 +2005,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2028,7 +2028,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 1149d89d7a1..13fb8c31702 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3555,7 +3555,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 12192445218..bab1c5d08f6 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index 1233e07d7da..ce9f258100d 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 951451a9765..3e380f29e5a 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,12 +81,12 @@ extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
extern bool check_maintenance_io_concurrency(int *newval, void **extra,
GucSource source);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -141,13 +141,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -163,7 +163,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--q7xzg7duksj2kgko
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v2-0005-Allow-to-resize-shared-memory-without-restart.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v2 4/6] Introduce pending flag for GUC assign hooks
@ 2025-02-19 16:45 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-02-19 16:45 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 2 +-
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 16 ++++----
8 files changed, 57 insertions(+), 36 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index f9bf5ba7509..ff82ba0a53d 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2188,7 +2188,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 4ad6e236d69..f24c2a0d252 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
#ifdef USE_PREFETCH
/*
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index 61ea3722ae2..cdf21847d7e 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1949,7 +1949,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1982,7 +1982,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2005,7 +2005,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2028,7 +2028,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 1149d89d7a1..13fb8c31702 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3555,7 +3555,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 12192445218..bab1c5d08f6 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index 1233e07d7da..ce9f258100d 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 951451a9765..3e380f29e5a 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,12 +81,12 @@ extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
extern bool check_maintenance_io_concurrency(int *newval, void **extra,
GucSource source);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -141,13 +141,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -163,7 +163,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--q7xzg7duksj2kgko
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v2-0005-Allow-to-resize-shared-memory-without-restart.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v2 4/6] Introduce pending flag for GUC assign hooks
@ 2025-02-19 16:45 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-02-19 16:45 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 2 +-
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 16 ++++----
8 files changed, 57 insertions(+), 36 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index f9bf5ba7509..ff82ba0a53d 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2188,7 +2188,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 4ad6e236d69..f24c2a0d252 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
#ifdef USE_PREFETCH
/*
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index 61ea3722ae2..cdf21847d7e 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1949,7 +1949,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1982,7 +1982,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2005,7 +2005,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2028,7 +2028,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 1149d89d7a1..13fb8c31702 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3555,7 +3555,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 12192445218..bab1c5d08f6 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index 1233e07d7da..ce9f258100d 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 951451a9765..3e380f29e5a 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,12 +81,12 @@ extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
extern bool check_maintenance_io_concurrency(int *newval, void **extra,
GucSource source);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -141,13 +141,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -163,7 +163,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--q7xzg7duksj2kgko
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v2-0005-Allow-to-resize-shared-memory-without-restart.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v2 4/6] Introduce pending flag for GUC assign hooks
@ 2025-02-19 16:45 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-02-19 16:45 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 2 +-
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 16 ++++----
8 files changed, 57 insertions(+), 36 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index f9bf5ba7509..ff82ba0a53d 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2188,7 +2188,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 4ad6e236d69..f24c2a0d252 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
#ifdef USE_PREFETCH
/*
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index 61ea3722ae2..cdf21847d7e 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1949,7 +1949,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1982,7 +1982,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2005,7 +2005,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2028,7 +2028,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 1149d89d7a1..13fb8c31702 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3555,7 +3555,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 12192445218..bab1c5d08f6 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index 1233e07d7da..ce9f258100d 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 951451a9765..3e380f29e5a 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,12 +81,12 @@ extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
extern bool check_maintenance_io_concurrency(int *newval, void **extra,
GucSource source);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -141,13 +141,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -163,7 +163,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--q7xzg7duksj2kgko
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v2-0005-Allow-to-resize-shared-memory-without-restart.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v2 4/6] Introduce pending flag for GUC assign hooks
@ 2025-02-19 16:45 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-02-19 16:45 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 2 +-
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 16 ++++----
8 files changed, 57 insertions(+), 36 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index f9bf5ba7509..ff82ba0a53d 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2188,7 +2188,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 4ad6e236d69..f24c2a0d252 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
#ifdef USE_PREFETCH
/*
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index 61ea3722ae2..cdf21847d7e 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1949,7 +1949,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1982,7 +1982,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2005,7 +2005,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2028,7 +2028,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 1149d89d7a1..13fb8c31702 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3555,7 +3555,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 12192445218..bab1c5d08f6 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index 1233e07d7da..ce9f258100d 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 951451a9765..3e380f29e5a 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,12 +81,12 @@ extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
extern bool check_maintenance_io_concurrency(int *newval, void **extra,
GucSource source);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -141,13 +141,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -163,7 +163,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--q7xzg7duksj2kgko
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v2-0005-Allow-to-resize-shared-memory-without-restart.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v2 4/6] Introduce pending flag for GUC assign hooks
@ 2025-02-19 16:45 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-02-19 16:45 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 2 +-
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 16 ++++----
8 files changed, 57 insertions(+), 36 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index f9bf5ba7509..ff82ba0a53d 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2188,7 +2188,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 4ad6e236d69..f24c2a0d252 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
#ifdef USE_PREFETCH
/*
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index 61ea3722ae2..cdf21847d7e 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1949,7 +1949,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1982,7 +1982,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2005,7 +2005,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2028,7 +2028,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 1149d89d7a1..13fb8c31702 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3555,7 +3555,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 12192445218..bab1c5d08f6 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index 1233e07d7da..ce9f258100d 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 951451a9765..3e380f29e5a 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,12 +81,12 @@ extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
extern bool check_maintenance_io_concurrency(int *newval, void **extra,
GucSource source);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -141,13 +141,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -163,7 +163,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--q7xzg7duksj2kgko
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v2-0005-Allow-to-resize-shared-memory-without-restart.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v2 4/6] Introduce pending flag for GUC assign hooks
@ 2025-02-19 16:45 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-02-19 16:45 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 2 +-
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 16 ++++----
8 files changed, 57 insertions(+), 36 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index f9bf5ba7509..ff82ba0a53d 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2188,7 +2188,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 4ad6e236d69..f24c2a0d252 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
#ifdef USE_PREFETCH
/*
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index 61ea3722ae2..cdf21847d7e 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1949,7 +1949,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1982,7 +1982,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2005,7 +2005,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2028,7 +2028,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 1149d89d7a1..13fb8c31702 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3555,7 +3555,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 12192445218..bab1c5d08f6 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index 1233e07d7da..ce9f258100d 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 951451a9765..3e380f29e5a 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,12 +81,12 @@ extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
extern bool check_maintenance_io_concurrency(int *newval, void **extra,
GucSource source);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -141,13 +141,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -163,7 +163,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--q7xzg7duksj2kgko
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v2-0005-Allow-to-resize-shared-memory-without-restart.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v2 4/6] Introduce pending flag for GUC assign hooks
@ 2025-02-19 16:45 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-02-19 16:45 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 2 +-
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 16 ++++----
8 files changed, 57 insertions(+), 36 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index f9bf5ba7509..ff82ba0a53d 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2188,7 +2188,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 4ad6e236d69..f24c2a0d252 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
#ifdef USE_PREFETCH
/*
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index 61ea3722ae2..cdf21847d7e 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1949,7 +1949,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1982,7 +1982,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2005,7 +2005,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2028,7 +2028,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 1149d89d7a1..13fb8c31702 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3555,7 +3555,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 12192445218..bab1c5d08f6 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index 1233e07d7da..ce9f258100d 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 951451a9765..3e380f29e5a 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,12 +81,12 @@ extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
extern bool check_maintenance_io_concurrency(int *newval, void **extra,
GucSource source);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -141,13 +141,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -163,7 +163,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--q7xzg7duksj2kgko
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v2-0005-Allow-to-resize-shared-memory-without-restart.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v2 4/6] Introduce pending flag for GUC assign hooks
@ 2025-02-19 16:45 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-02-19 16:45 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 2 +-
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 16 ++++----
8 files changed, 57 insertions(+), 36 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index f9bf5ba7509..ff82ba0a53d 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2188,7 +2188,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 4ad6e236d69..f24c2a0d252 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
#ifdef USE_PREFETCH
/*
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index 61ea3722ae2..cdf21847d7e 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1949,7 +1949,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1982,7 +1982,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2005,7 +2005,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2028,7 +2028,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 1149d89d7a1..13fb8c31702 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3555,7 +3555,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 12192445218..bab1c5d08f6 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index 1233e07d7da..ce9f258100d 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 951451a9765..3e380f29e5a 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,12 +81,12 @@ extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
extern bool check_maintenance_io_concurrency(int *newval, void **extra,
GucSource source);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -141,13 +141,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -163,7 +163,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--q7xzg7duksj2kgko
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v2-0005-Allow-to-resize-shared-memory-without-restart.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v2 4/6] Introduce pending flag for GUC assign hooks
@ 2025-02-19 16:45 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-02-19 16:45 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 2 +-
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 16 ++++----
8 files changed, 57 insertions(+), 36 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index f9bf5ba7509..ff82ba0a53d 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2188,7 +2188,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 4ad6e236d69..f24c2a0d252 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
#ifdef USE_PREFETCH
/*
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index 61ea3722ae2..cdf21847d7e 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1949,7 +1949,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1982,7 +1982,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2005,7 +2005,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2028,7 +2028,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 1149d89d7a1..13fb8c31702 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3555,7 +3555,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 12192445218..bab1c5d08f6 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index 1233e07d7da..ce9f258100d 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 951451a9765..3e380f29e5a 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,12 +81,12 @@ extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
extern bool check_maintenance_io_concurrency(int *newval, void **extra,
GucSource source);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -141,13 +141,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -163,7 +163,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--q7xzg7duksj2kgko
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v2-0005-Allow-to-resize-shared-memory-without-restart.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v2 4/6] Introduce pending flag for GUC assign hooks
@ 2025-02-19 16:45 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-02-19 16:45 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 2 +-
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 16 ++++----
8 files changed, 57 insertions(+), 36 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index f9bf5ba7509..ff82ba0a53d 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2188,7 +2188,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 4ad6e236d69..f24c2a0d252 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
#ifdef USE_PREFETCH
/*
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index 61ea3722ae2..cdf21847d7e 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1949,7 +1949,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1982,7 +1982,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2005,7 +2005,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2028,7 +2028,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 1149d89d7a1..13fb8c31702 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3555,7 +3555,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 12192445218..bab1c5d08f6 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index 1233e07d7da..ce9f258100d 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 951451a9765..3e380f29e5a 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,12 +81,12 @@ extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
extern bool check_maintenance_io_concurrency(int *newval, void **extra,
GucSource source);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -141,13 +141,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -163,7 +163,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--q7xzg7duksj2kgko
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v2-0005-Allow-to-resize-shared-memory-without-restart.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v2 4/6] Introduce pending flag for GUC assign hooks
@ 2025-02-19 16:45 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-02-19 16:45 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 2 +-
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 16 ++++----
8 files changed, 57 insertions(+), 36 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index f9bf5ba7509..ff82ba0a53d 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2188,7 +2188,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 4ad6e236d69..f24c2a0d252 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
#ifdef USE_PREFETCH
/*
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index 61ea3722ae2..cdf21847d7e 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1949,7 +1949,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1982,7 +1982,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2005,7 +2005,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2028,7 +2028,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 1149d89d7a1..13fb8c31702 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3555,7 +3555,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 12192445218..bab1c5d08f6 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index 1233e07d7da..ce9f258100d 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 951451a9765..3e380f29e5a 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,12 +81,12 @@ extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
extern bool check_maintenance_io_concurrency(int *newval, void **extra,
GucSource source);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -141,13 +141,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -163,7 +163,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--q7xzg7duksj2kgko
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v2-0005-Allow-to-resize-shared-memory-without-restart.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v2 4/6] Introduce pending flag for GUC assign hooks
@ 2025-02-19 16:45 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-02-19 16:45 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 2 +-
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 16 ++++----
8 files changed, 57 insertions(+), 36 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index f9bf5ba7509..ff82ba0a53d 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2188,7 +2188,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 4ad6e236d69..f24c2a0d252 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
#ifdef USE_PREFETCH
/*
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index 61ea3722ae2..cdf21847d7e 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1949,7 +1949,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1982,7 +1982,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2005,7 +2005,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2028,7 +2028,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 1149d89d7a1..13fb8c31702 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3555,7 +3555,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 12192445218..bab1c5d08f6 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index 1233e07d7da..ce9f258100d 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 951451a9765..3e380f29e5a 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,12 +81,12 @@ extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
extern bool check_maintenance_io_concurrency(int *newval, void **extra,
GucSource source);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -141,13 +141,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -163,7 +163,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--q7xzg7duksj2kgko
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v2-0005-Allow-to-resize-shared-memory-without-restart.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v2 4/6] Introduce pending flag for GUC assign hooks
@ 2025-02-19 16:45 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-02-19 16:45 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 2 +-
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 16 ++++----
8 files changed, 57 insertions(+), 36 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index f9bf5ba7509..ff82ba0a53d 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2188,7 +2188,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 4ad6e236d69..f24c2a0d252 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
#ifdef USE_PREFETCH
/*
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index 61ea3722ae2..cdf21847d7e 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1949,7 +1949,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1982,7 +1982,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2005,7 +2005,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2028,7 +2028,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 1149d89d7a1..13fb8c31702 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3555,7 +3555,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 12192445218..bab1c5d08f6 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index 1233e07d7da..ce9f258100d 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 951451a9765..3e380f29e5a 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,12 +81,12 @@ extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
extern bool check_maintenance_io_concurrency(int *newval, void **extra,
GucSource source);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -141,13 +141,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -163,7 +163,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--q7xzg7duksj2kgko
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v2-0005-Allow-to-resize-shared-memory-without-restart.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v2 4/6] Introduce pending flag for GUC assign hooks
@ 2025-02-19 16:45 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-02-19 16:45 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 2 +-
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 16 ++++----
8 files changed, 57 insertions(+), 36 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index f9bf5ba7509..ff82ba0a53d 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2188,7 +2188,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 4ad6e236d69..f24c2a0d252 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
#ifdef USE_PREFETCH
/*
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index 61ea3722ae2..cdf21847d7e 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1949,7 +1949,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1982,7 +1982,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2005,7 +2005,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2028,7 +2028,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 1149d89d7a1..13fb8c31702 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3555,7 +3555,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 12192445218..bab1c5d08f6 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index 1233e07d7da..ce9f258100d 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 951451a9765..3e380f29e5a 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,12 +81,12 @@ extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
extern bool check_maintenance_io_concurrency(int *newval, void **extra,
GucSource source);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -141,13 +141,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -163,7 +163,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--q7xzg7duksj2kgko
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v2-0005-Allow-to-resize-shared-memory-without-restart.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v2 4/6] Introduce pending flag for GUC assign hooks
@ 2025-02-19 16:45 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-02-19 16:45 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 2 +-
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 16 ++++----
8 files changed, 57 insertions(+), 36 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index f9bf5ba7509..ff82ba0a53d 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2188,7 +2188,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 4ad6e236d69..f24c2a0d252 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
#ifdef USE_PREFETCH
/*
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index 61ea3722ae2..cdf21847d7e 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1949,7 +1949,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1982,7 +1982,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2005,7 +2005,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2028,7 +2028,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 1149d89d7a1..13fb8c31702 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3555,7 +3555,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 12192445218..bab1c5d08f6 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index 1233e07d7da..ce9f258100d 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 951451a9765..3e380f29e5a 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,12 +81,12 @@ extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
extern bool check_maintenance_io_concurrency(int *newval, void **extra,
GucSource source);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -141,13 +141,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -163,7 +163,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--q7xzg7duksj2kgko
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v2-0005-Allow-to-resize-shared-memory-without-restart.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v2 4/6] Introduce pending flag for GUC assign hooks
@ 2025-02-19 16:45 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-02-19 16:45 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 2 +-
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 16 ++++----
8 files changed, 57 insertions(+), 36 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index f9bf5ba7509..ff82ba0a53d 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2188,7 +2188,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 4ad6e236d69..f24c2a0d252 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
#ifdef USE_PREFETCH
/*
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index 61ea3722ae2..cdf21847d7e 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1949,7 +1949,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1982,7 +1982,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2005,7 +2005,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2028,7 +2028,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 1149d89d7a1..13fb8c31702 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3555,7 +3555,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 12192445218..bab1c5d08f6 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index 1233e07d7da..ce9f258100d 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 951451a9765..3e380f29e5a 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,12 +81,12 @@ extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
extern bool check_maintenance_io_concurrency(int *newval, void **extra,
GucSource source);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -141,13 +141,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -163,7 +163,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--q7xzg7duksj2kgko
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v2-0005-Allow-to-resize-shared-memory-without-restart.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v2 4/6] Introduce pending flag for GUC assign hooks
@ 2025-02-19 16:45 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-02-19 16:45 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 2 +-
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 16 ++++----
8 files changed, 57 insertions(+), 36 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index f9bf5ba7509..ff82ba0a53d 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2188,7 +2188,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 4ad6e236d69..f24c2a0d252 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
#ifdef USE_PREFETCH
/*
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index 61ea3722ae2..cdf21847d7e 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1949,7 +1949,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1982,7 +1982,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2005,7 +2005,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2028,7 +2028,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 1149d89d7a1..13fb8c31702 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3555,7 +3555,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 12192445218..bab1c5d08f6 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index 1233e07d7da..ce9f258100d 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 951451a9765..3e380f29e5a 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,12 +81,12 @@ extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
extern bool check_maintenance_io_concurrency(int *newval, void **extra,
GucSource source);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -141,13 +141,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -163,7 +163,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--q7xzg7duksj2kgko
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v2-0005-Allow-to-resize-shared-memory-without-restart.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v2 4/6] Introduce pending flag for GUC assign hooks
@ 2025-02-19 16:45 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-02-19 16:45 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 2 +-
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 16 ++++----
8 files changed, 57 insertions(+), 36 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index f9bf5ba7509..ff82ba0a53d 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2188,7 +2188,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 4ad6e236d69..f24c2a0d252 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
#ifdef USE_PREFETCH
/*
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index 61ea3722ae2..cdf21847d7e 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1949,7 +1949,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1982,7 +1982,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2005,7 +2005,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2028,7 +2028,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 1149d89d7a1..13fb8c31702 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3555,7 +3555,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 12192445218..bab1c5d08f6 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index 1233e07d7da..ce9f258100d 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 951451a9765..3e380f29e5a 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,12 +81,12 @@ extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
extern bool check_maintenance_io_concurrency(int *newval, void **extra,
GucSource source);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -141,13 +141,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -163,7 +163,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--q7xzg7duksj2kgko
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v2-0005-Allow-to-resize-shared-memory-without-restart.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v2 4/6] Introduce pending flag for GUC assign hooks
@ 2025-02-19 16:45 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-02-19 16:45 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 2 +-
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 16 ++++----
8 files changed, 57 insertions(+), 36 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index f9bf5ba7509..ff82ba0a53d 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2188,7 +2188,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 4ad6e236d69..f24c2a0d252 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
#ifdef USE_PREFETCH
/*
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index 61ea3722ae2..cdf21847d7e 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1949,7 +1949,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1982,7 +1982,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2005,7 +2005,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2028,7 +2028,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 1149d89d7a1..13fb8c31702 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3555,7 +3555,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 12192445218..bab1c5d08f6 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index 1233e07d7da..ce9f258100d 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 951451a9765..3e380f29e5a 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,12 +81,12 @@ extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
extern bool check_maintenance_io_concurrency(int *newval, void **extra,
GucSource source);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -141,13 +141,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -163,7 +163,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--q7xzg7duksj2kgko
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v2-0005-Allow-to-resize-shared-memory-without-restart.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v2 4/6] Introduce pending flag for GUC assign hooks
@ 2025-02-19 16:45 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-02-19 16:45 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 2 +-
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 16 ++++----
8 files changed, 57 insertions(+), 36 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index f9bf5ba7509..ff82ba0a53d 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2188,7 +2188,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 4ad6e236d69..f24c2a0d252 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
#ifdef USE_PREFETCH
/*
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index 61ea3722ae2..cdf21847d7e 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1949,7 +1949,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1982,7 +1982,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2005,7 +2005,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2028,7 +2028,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 1149d89d7a1..13fb8c31702 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3555,7 +3555,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 12192445218..bab1c5d08f6 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index 1233e07d7da..ce9f258100d 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 951451a9765..3e380f29e5a 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,12 +81,12 @@ extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
extern bool check_maintenance_io_concurrency(int *newval, void **extra,
GucSource source);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -141,13 +141,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -163,7 +163,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--q7xzg7duksj2kgko
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v2-0005-Allow-to-resize-shared-memory-without-restart.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v2 4/6] Introduce pending flag for GUC assign hooks
@ 2025-02-19 16:45 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-02-19 16:45 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 2 +-
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 16 ++++----
8 files changed, 57 insertions(+), 36 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index f9bf5ba7509..ff82ba0a53d 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2188,7 +2188,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 4ad6e236d69..f24c2a0d252 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
#ifdef USE_PREFETCH
/*
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index 61ea3722ae2..cdf21847d7e 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1949,7 +1949,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1982,7 +1982,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2005,7 +2005,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2028,7 +2028,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 1149d89d7a1..13fb8c31702 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3555,7 +3555,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 12192445218..bab1c5d08f6 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index 1233e07d7da..ce9f258100d 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 951451a9765..3e380f29e5a 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,12 +81,12 @@ extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
extern bool check_maintenance_io_concurrency(int *newval, void **extra,
GucSource source);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -141,13 +141,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -163,7 +163,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--q7xzg7duksj2kgko
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v2-0005-Allow-to-resize-shared-memory-without-restart.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v2 4/6] Introduce pending flag for GUC assign hooks
@ 2025-02-19 16:45 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-02-19 16:45 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 2 +-
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 16 ++++----
8 files changed, 57 insertions(+), 36 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index f9bf5ba7509..ff82ba0a53d 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2188,7 +2188,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 4ad6e236d69..f24c2a0d252 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
#ifdef USE_PREFETCH
/*
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index 61ea3722ae2..cdf21847d7e 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1949,7 +1949,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1982,7 +1982,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2005,7 +2005,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2028,7 +2028,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 1149d89d7a1..13fb8c31702 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3555,7 +3555,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 12192445218..bab1c5d08f6 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index 1233e07d7da..ce9f258100d 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 951451a9765..3e380f29e5a 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,12 +81,12 @@ extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
extern bool check_maintenance_io_concurrency(int *newval, void **extra,
GucSource source);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -141,13 +141,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -163,7 +163,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--q7xzg7duksj2kgko
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v2-0005-Allow-to-resize-shared-memory-without-restart.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v2 4/6] Introduce pending flag for GUC assign hooks
@ 2025-02-19 16:45 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-02-19 16:45 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 2 +-
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 16 ++++----
8 files changed, 57 insertions(+), 36 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index f9bf5ba7509..ff82ba0a53d 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2188,7 +2188,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 4ad6e236d69..f24c2a0d252 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
#ifdef USE_PREFETCH
/*
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index 61ea3722ae2..cdf21847d7e 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1949,7 +1949,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1982,7 +1982,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2005,7 +2005,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2028,7 +2028,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 1149d89d7a1..13fb8c31702 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3555,7 +3555,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 12192445218..bab1c5d08f6 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index 1233e07d7da..ce9f258100d 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 951451a9765..3e380f29e5a 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,12 +81,12 @@ extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
extern bool check_maintenance_io_concurrency(int *newval, void **extra,
GucSource source);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -141,13 +141,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -163,7 +163,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--q7xzg7duksj2kgko
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v2-0005-Allow-to-resize-shared-memory-without-restart.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v2 4/6] Introduce pending flag for GUC assign hooks
@ 2025-02-19 16:45 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-02-19 16:45 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 2 +-
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 16 ++++----
8 files changed, 57 insertions(+), 36 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index f9bf5ba7509..ff82ba0a53d 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2188,7 +2188,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 4ad6e236d69..f24c2a0d252 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
#ifdef USE_PREFETCH
/*
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index 61ea3722ae2..cdf21847d7e 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1949,7 +1949,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1982,7 +1982,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2005,7 +2005,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2028,7 +2028,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 1149d89d7a1..13fb8c31702 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3555,7 +3555,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 12192445218..bab1c5d08f6 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index 1233e07d7da..ce9f258100d 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 951451a9765..3e380f29e5a 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,12 +81,12 @@ extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
extern bool check_maintenance_io_concurrency(int *newval, void **extra,
GucSource source);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -141,13 +141,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -163,7 +163,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--q7xzg7duksj2kgko
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v2-0005-Allow-to-resize-shared-memory-without-restart.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v2 4/6] Introduce pending flag for GUC assign hooks
@ 2025-02-19 16:45 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-02-19 16:45 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 2 +-
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 16 ++++----
8 files changed, 57 insertions(+), 36 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index f9bf5ba7509..ff82ba0a53d 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2188,7 +2188,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 4ad6e236d69..f24c2a0d252 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
#ifdef USE_PREFETCH
/*
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index 61ea3722ae2..cdf21847d7e 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1949,7 +1949,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1982,7 +1982,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2005,7 +2005,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2028,7 +2028,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 1149d89d7a1..13fb8c31702 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3555,7 +3555,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 12192445218..bab1c5d08f6 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index 1233e07d7da..ce9f258100d 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 951451a9765..3e380f29e5a 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,12 +81,12 @@ extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
extern bool check_maintenance_io_concurrency(int *newval, void **extra,
GucSource source);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -141,13 +141,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -163,7 +163,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--q7xzg7duksj2kgko
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v2-0005-Allow-to-resize-shared-memory-without-restart.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v2 4/6] Introduce pending flag for GUC assign hooks
@ 2025-02-19 16:45 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-02-19 16:45 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 2 +-
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 16 ++++----
8 files changed, 57 insertions(+), 36 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index f9bf5ba7509..ff82ba0a53d 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2188,7 +2188,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 4ad6e236d69..f24c2a0d252 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
#ifdef USE_PREFETCH
/*
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index 61ea3722ae2..cdf21847d7e 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1949,7 +1949,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1982,7 +1982,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2005,7 +2005,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2028,7 +2028,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 1149d89d7a1..13fb8c31702 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3555,7 +3555,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 12192445218..bab1c5d08f6 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index 1233e07d7da..ce9f258100d 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 951451a9765..3e380f29e5a 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,12 +81,12 @@ extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
extern bool check_maintenance_io_concurrency(int *newval, void **extra,
GucSource source);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -141,13 +141,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -163,7 +163,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--q7xzg7duksj2kgko
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v2-0005-Allow-to-resize-shared-memory-without-restart.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v2 4/6] Introduce pending flag for GUC assign hooks
@ 2025-02-19 16:45 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-02-19 16:45 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 2 +-
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 16 ++++----
8 files changed, 57 insertions(+), 36 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index f9bf5ba7509..ff82ba0a53d 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2188,7 +2188,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 4ad6e236d69..f24c2a0d252 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
#ifdef USE_PREFETCH
/*
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index 61ea3722ae2..cdf21847d7e 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1949,7 +1949,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1982,7 +1982,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2005,7 +2005,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2028,7 +2028,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 1149d89d7a1..13fb8c31702 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3555,7 +3555,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 12192445218..bab1c5d08f6 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index 1233e07d7da..ce9f258100d 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 951451a9765..3e380f29e5a 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,12 +81,12 @@ extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
extern bool check_maintenance_io_concurrency(int *newval, void **extra,
GucSource source);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -141,13 +141,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -163,7 +163,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--q7xzg7duksj2kgko
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v2-0005-Allow-to-resize-shared-memory-without-restart.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v2 4/6] Introduce pending flag for GUC assign hooks
@ 2025-02-19 16:45 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-02-19 16:45 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 2 +-
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 16 ++++----
8 files changed, 57 insertions(+), 36 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index f9bf5ba7509..ff82ba0a53d 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2188,7 +2188,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 4ad6e236d69..f24c2a0d252 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
#ifdef USE_PREFETCH
/*
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index 61ea3722ae2..cdf21847d7e 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1949,7 +1949,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1982,7 +1982,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2005,7 +2005,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2028,7 +2028,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 1149d89d7a1..13fb8c31702 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3555,7 +3555,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 12192445218..bab1c5d08f6 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index 1233e07d7da..ce9f258100d 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 951451a9765..3e380f29e5a 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,12 +81,12 @@ extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
extern bool check_maintenance_io_concurrency(int *newval, void **extra,
GucSource source);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -141,13 +141,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -163,7 +163,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--q7xzg7duksj2kgko
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v2-0005-Allow-to-resize-shared-memory-without-restart.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v2 4/6] Introduce pending flag for GUC assign hooks
@ 2025-02-19 16:45 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-02-19 16:45 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 2 +-
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 16 ++++----
8 files changed, 57 insertions(+), 36 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index f9bf5ba7509..ff82ba0a53d 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2188,7 +2188,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 4ad6e236d69..f24c2a0d252 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
#ifdef USE_PREFETCH
/*
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index 61ea3722ae2..cdf21847d7e 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1949,7 +1949,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1982,7 +1982,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2005,7 +2005,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2028,7 +2028,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 1149d89d7a1..13fb8c31702 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3555,7 +3555,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 12192445218..bab1c5d08f6 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index 1233e07d7da..ce9f258100d 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 951451a9765..3e380f29e5a 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,12 +81,12 @@ extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
extern bool check_maintenance_io_concurrency(int *newval, void **extra,
GucSource source);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -141,13 +141,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -163,7 +163,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--q7xzg7duksj2kgko
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v2-0005-Allow-to-resize-shared-memory-without-restart.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v2 4/6] Introduce pending flag for GUC assign hooks
@ 2025-02-19 16:45 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-02-19 16:45 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 2 +-
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 16 ++++----
8 files changed, 57 insertions(+), 36 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index f9bf5ba7509..ff82ba0a53d 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2188,7 +2188,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 4ad6e236d69..f24c2a0d252 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
#ifdef USE_PREFETCH
/*
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index 61ea3722ae2..cdf21847d7e 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1949,7 +1949,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1982,7 +1982,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2005,7 +2005,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2028,7 +2028,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 1149d89d7a1..13fb8c31702 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3555,7 +3555,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 12192445218..bab1c5d08f6 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index 1233e07d7da..ce9f258100d 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 951451a9765..3e380f29e5a 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,12 +81,12 @@ extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
extern bool check_maintenance_io_concurrency(int *newval, void **extra,
GucSource source);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -141,13 +141,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -163,7 +163,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--q7xzg7duksj2kgko
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v2-0005-Allow-to-resize-shared-memory-without-restart.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v2 4/6] Introduce pending flag for GUC assign hooks
@ 2025-02-19 16:45 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-02-19 16:45 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 2 +-
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 16 ++++----
8 files changed, 57 insertions(+), 36 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index f9bf5ba7509..ff82ba0a53d 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2188,7 +2188,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 4ad6e236d69..f24c2a0d252 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
#ifdef USE_PREFETCH
/*
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index 61ea3722ae2..cdf21847d7e 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1949,7 +1949,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1982,7 +1982,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2005,7 +2005,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2028,7 +2028,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 1149d89d7a1..13fb8c31702 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3555,7 +3555,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 12192445218..bab1c5d08f6 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index 1233e07d7da..ce9f258100d 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 951451a9765..3e380f29e5a 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,12 +81,12 @@ extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
extern bool check_maintenance_io_concurrency(int *newval, void **extra,
GucSource source);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -141,13 +141,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -163,7 +163,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--q7xzg7duksj2kgko
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v2-0005-Allow-to-resize-shared-memory-without-restart.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v2 4/6] Introduce pending flag for GUC assign hooks
@ 2025-02-19 16:45 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-02-19 16:45 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 2 +-
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 16 ++++----
8 files changed, 57 insertions(+), 36 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index f9bf5ba7509..ff82ba0a53d 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2188,7 +2188,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 4ad6e236d69..f24c2a0d252 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
#ifdef USE_PREFETCH
/*
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index 61ea3722ae2..cdf21847d7e 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1949,7 +1949,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1982,7 +1982,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2005,7 +2005,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2028,7 +2028,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 1149d89d7a1..13fb8c31702 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3555,7 +3555,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 12192445218..bab1c5d08f6 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index 1233e07d7da..ce9f258100d 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 951451a9765..3e380f29e5a 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,12 +81,12 @@ extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
extern bool check_maintenance_io_concurrency(int *newval, void **extra,
GucSource source);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -141,13 +141,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -163,7 +163,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--q7xzg7duksj2kgko
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v2-0005-Allow-to-resize-shared-memory-without-restart.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v2 4/6] Introduce pending flag for GUC assign hooks
@ 2025-02-19 16:45 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-02-19 16:45 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 2 +-
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 16 ++++----
8 files changed, 57 insertions(+), 36 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index f9bf5ba7509..ff82ba0a53d 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2188,7 +2188,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 4ad6e236d69..f24c2a0d252 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
#ifdef USE_PREFETCH
/*
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index 61ea3722ae2..cdf21847d7e 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1949,7 +1949,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1982,7 +1982,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2005,7 +2005,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2028,7 +2028,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 1149d89d7a1..13fb8c31702 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3555,7 +3555,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 12192445218..bab1c5d08f6 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index 1233e07d7da..ce9f258100d 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 951451a9765..3e380f29e5a 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,12 +81,12 @@ extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
extern bool check_maintenance_io_concurrency(int *newval, void **extra,
GucSource source);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -141,13 +141,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -163,7 +163,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--q7xzg7duksj2kgko
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v2-0005-Allow-to-resize-shared-memory-without-restart.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v2 4/6] Introduce pending flag for GUC assign hooks
@ 2025-02-19 16:45 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-02-19 16:45 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 2 +-
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 16 ++++----
8 files changed, 57 insertions(+), 36 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index f9bf5ba7509..ff82ba0a53d 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2188,7 +2188,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 4ad6e236d69..f24c2a0d252 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
#ifdef USE_PREFETCH
/*
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index 61ea3722ae2..cdf21847d7e 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1949,7 +1949,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1982,7 +1982,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2005,7 +2005,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2028,7 +2028,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 1149d89d7a1..13fb8c31702 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3555,7 +3555,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 12192445218..bab1c5d08f6 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index 1233e07d7da..ce9f258100d 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 951451a9765..3e380f29e5a 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,12 +81,12 @@ extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
extern bool check_maintenance_io_concurrency(int *newval, void **extra,
GucSource source);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -141,13 +141,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -163,7 +163,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--q7xzg7duksj2kgko
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v2-0005-Allow-to-resize-shared-memory-without-restart.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v2 4/6] Introduce pending flag for GUC assign hooks
@ 2025-02-19 16:45 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-02-19 16:45 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 2 +-
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 16 ++++----
8 files changed, 57 insertions(+), 36 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index f9bf5ba7509..ff82ba0a53d 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2188,7 +2188,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 4ad6e236d69..f24c2a0d252 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
#ifdef USE_PREFETCH
/*
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index 61ea3722ae2..cdf21847d7e 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1949,7 +1949,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1982,7 +1982,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2005,7 +2005,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2028,7 +2028,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 1149d89d7a1..13fb8c31702 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3555,7 +3555,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 12192445218..bab1c5d08f6 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index 1233e07d7da..ce9f258100d 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 951451a9765..3e380f29e5a 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,12 +81,12 @@ extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
extern bool check_maintenance_io_concurrency(int *newval, void **extra,
GucSource source);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -141,13 +141,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -163,7 +163,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--q7xzg7duksj2kgko
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v2-0005-Allow-to-resize-shared-memory-without-restart.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v2 4/6] Introduce pending flag for GUC assign hooks
@ 2025-02-19 16:45 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-02-19 16:45 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 2 +-
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 16 ++++----
8 files changed, 57 insertions(+), 36 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index f9bf5ba7509..ff82ba0a53d 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2188,7 +2188,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 4ad6e236d69..f24c2a0d252 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
#ifdef USE_PREFETCH
/*
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index 61ea3722ae2..cdf21847d7e 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1949,7 +1949,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1982,7 +1982,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2005,7 +2005,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2028,7 +2028,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 1149d89d7a1..13fb8c31702 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3555,7 +3555,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 12192445218..bab1c5d08f6 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index 1233e07d7da..ce9f258100d 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 951451a9765..3e380f29e5a 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,12 +81,12 @@ extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
extern bool check_maintenance_io_concurrency(int *newval, void **extra,
GucSource source);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -141,13 +141,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -163,7 +163,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--q7xzg7duksj2kgko
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v2-0005-Allow-to-resize-shared-memory-without-restart.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v2 4/6] Introduce pending flag for GUC assign hooks
@ 2025-02-19 16:45 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-02-19 16:45 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 2 +-
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 16 ++++----
8 files changed, 57 insertions(+), 36 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index f9bf5ba7509..ff82ba0a53d 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2188,7 +2188,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 4ad6e236d69..f24c2a0d252 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
#ifdef USE_PREFETCH
/*
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index 61ea3722ae2..cdf21847d7e 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1949,7 +1949,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1982,7 +1982,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2005,7 +2005,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2028,7 +2028,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 1149d89d7a1..13fb8c31702 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3555,7 +3555,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 12192445218..bab1c5d08f6 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index 1233e07d7da..ce9f258100d 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 951451a9765..3e380f29e5a 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,12 +81,12 @@ extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
extern bool check_maintenance_io_concurrency(int *newval, void **extra,
GucSource source);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -141,13 +141,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -163,7 +163,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--q7xzg7duksj2kgko
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v2-0005-Allow-to-resize-shared-memory-without-restart.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v2 4/6] Introduce pending flag for GUC assign hooks
@ 2025-02-19 16:45 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-02-19 16:45 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 2 +-
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 16 ++++----
8 files changed, 57 insertions(+), 36 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index f9bf5ba7509..ff82ba0a53d 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2188,7 +2188,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 4ad6e236d69..f24c2a0d252 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
#ifdef USE_PREFETCH
/*
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index 61ea3722ae2..cdf21847d7e 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1949,7 +1949,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1982,7 +1982,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2005,7 +2005,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2028,7 +2028,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 1149d89d7a1..13fb8c31702 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3555,7 +3555,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 12192445218..bab1c5d08f6 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index 1233e07d7da..ce9f258100d 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 951451a9765..3e380f29e5a 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,12 +81,12 @@ extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
extern bool check_maintenance_io_concurrency(int *newval, void **extra,
GucSource source);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -141,13 +141,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -163,7 +163,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--q7xzg7duksj2kgko
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v2-0005-Allow-to-resize-shared-memory-without-restart.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v2 4/6] Introduce pending flag for GUC assign hooks
@ 2025-02-19 16:45 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-02-19 16:45 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 2 +-
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 16 ++++----
8 files changed, 57 insertions(+), 36 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index f9bf5ba7509..ff82ba0a53d 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2188,7 +2188,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 4ad6e236d69..f24c2a0d252 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
#ifdef USE_PREFETCH
/*
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index 61ea3722ae2..cdf21847d7e 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1949,7 +1949,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1982,7 +1982,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2005,7 +2005,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2028,7 +2028,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 1149d89d7a1..13fb8c31702 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3555,7 +3555,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 12192445218..bab1c5d08f6 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index 1233e07d7da..ce9f258100d 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 951451a9765..3e380f29e5a 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,12 +81,12 @@ extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
extern bool check_maintenance_io_concurrency(int *newval, void **extra,
GucSource source);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -141,13 +141,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -163,7 +163,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--q7xzg7duksj2kgko
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v2-0005-Allow-to-resize-shared-memory-without-restart.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v2 4/6] Introduce pending flag for GUC assign hooks
@ 2025-02-19 16:45 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-02-19 16:45 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 2 +-
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 16 ++++----
8 files changed, 57 insertions(+), 36 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index f9bf5ba7509..ff82ba0a53d 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2188,7 +2188,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 4ad6e236d69..f24c2a0d252 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
#ifdef USE_PREFETCH
/*
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index 61ea3722ae2..cdf21847d7e 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1949,7 +1949,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1982,7 +1982,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2005,7 +2005,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2028,7 +2028,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 1149d89d7a1..13fb8c31702 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3555,7 +3555,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 12192445218..bab1c5d08f6 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index 1233e07d7da..ce9f258100d 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 951451a9765..3e380f29e5a 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,12 +81,12 @@ extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
extern bool check_maintenance_io_concurrency(int *newval, void **extra,
GucSource source);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -141,13 +141,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -163,7 +163,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--q7xzg7duksj2kgko
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v2-0005-Allow-to-resize-shared-memory-without-restart.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v2 4/6] Introduce pending flag for GUC assign hooks
@ 2025-02-19 16:45 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-02-19 16:45 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 2 +-
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 16 ++++----
8 files changed, 57 insertions(+), 36 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index f9bf5ba7509..ff82ba0a53d 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2188,7 +2188,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 4ad6e236d69..f24c2a0d252 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
#ifdef USE_PREFETCH
/*
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index 61ea3722ae2..cdf21847d7e 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1949,7 +1949,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1982,7 +1982,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2005,7 +2005,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2028,7 +2028,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 1149d89d7a1..13fb8c31702 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3555,7 +3555,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 12192445218..bab1c5d08f6 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index 1233e07d7da..ce9f258100d 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 951451a9765..3e380f29e5a 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,12 +81,12 @@ extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
extern bool check_maintenance_io_concurrency(int *newval, void **extra,
GucSource source);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -141,13 +141,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -163,7 +163,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--q7xzg7duksj2kgko
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v2-0005-Allow-to-resize-shared-memory-without-restart.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v2 4/6] Introduce pending flag for GUC assign hooks
@ 2025-02-19 16:45 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-02-19 16:45 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 2 +-
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 16 ++++----
8 files changed, 57 insertions(+), 36 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index f9bf5ba7509..ff82ba0a53d 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2188,7 +2188,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 4ad6e236d69..f24c2a0d252 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
#ifdef USE_PREFETCH
/*
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index 61ea3722ae2..cdf21847d7e 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1949,7 +1949,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1982,7 +1982,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2005,7 +2005,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2028,7 +2028,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 1149d89d7a1..13fb8c31702 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3555,7 +3555,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 12192445218..bab1c5d08f6 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index 1233e07d7da..ce9f258100d 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 951451a9765..3e380f29e5a 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,12 +81,12 @@ extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
extern bool check_maintenance_io_concurrency(int *newval, void **extra,
GucSource source);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -141,13 +141,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -163,7 +163,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--q7xzg7duksj2kgko
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v2-0005-Allow-to-resize-shared-memory-without-restart.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v2 4/6] Introduce pending flag for GUC assign hooks
@ 2025-02-19 16:45 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-02-19 16:45 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 2 +-
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 16 ++++----
8 files changed, 57 insertions(+), 36 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index f9bf5ba7509..ff82ba0a53d 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2188,7 +2188,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 4ad6e236d69..f24c2a0d252 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
#ifdef USE_PREFETCH
/*
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index 61ea3722ae2..cdf21847d7e 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1949,7 +1949,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1982,7 +1982,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2005,7 +2005,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2028,7 +2028,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 1149d89d7a1..13fb8c31702 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3555,7 +3555,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 12192445218..bab1c5d08f6 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index 1233e07d7da..ce9f258100d 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 951451a9765..3e380f29e5a 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,12 +81,12 @@ extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
extern bool check_maintenance_io_concurrency(int *newval, void **extra,
GucSource source);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -141,13 +141,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -163,7 +163,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--q7xzg7duksj2kgko
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v2-0005-Allow-to-resize-shared-memory-without-restart.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v2 4/6] Introduce pending flag for GUC assign hooks
@ 2025-02-19 16:45 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-02-19 16:45 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 2 +-
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 16 ++++----
8 files changed, 57 insertions(+), 36 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index f9bf5ba7509..ff82ba0a53d 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2188,7 +2188,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 4ad6e236d69..f24c2a0d252 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
#ifdef USE_PREFETCH
/*
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index 61ea3722ae2..cdf21847d7e 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1949,7 +1949,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1982,7 +1982,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2005,7 +2005,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2028,7 +2028,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 1149d89d7a1..13fb8c31702 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3555,7 +3555,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 12192445218..bab1c5d08f6 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index 1233e07d7da..ce9f258100d 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 951451a9765..3e380f29e5a 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,12 +81,12 @@ extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
extern bool check_maintenance_io_concurrency(int *newval, void **extra,
GucSource source);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -141,13 +141,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -163,7 +163,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--q7xzg7duksj2kgko
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v2-0005-Allow-to-resize-shared-memory-without-restart.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v2 4/6] Introduce pending flag for GUC assign hooks
@ 2025-02-19 16:45 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-02-19 16:45 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 2 +-
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 16 ++++----
8 files changed, 57 insertions(+), 36 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index f9bf5ba7509..ff82ba0a53d 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2188,7 +2188,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 4ad6e236d69..f24c2a0d252 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
#ifdef USE_PREFETCH
/*
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index 61ea3722ae2..cdf21847d7e 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1949,7 +1949,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1982,7 +1982,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2005,7 +2005,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2028,7 +2028,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 1149d89d7a1..13fb8c31702 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3555,7 +3555,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 12192445218..bab1c5d08f6 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index 1233e07d7da..ce9f258100d 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 951451a9765..3e380f29e5a 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,12 +81,12 @@ extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
extern bool check_maintenance_io_concurrency(int *newval, void **extra,
GucSource source);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -141,13 +141,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -163,7 +163,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--q7xzg7duksj2kgko
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v2-0005-Allow-to-resize-shared-memory-without-restart.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v2 4/6] Introduce pending flag for GUC assign hooks
@ 2025-02-19 16:45 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-02-19 16:45 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 2 +-
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 16 ++++----
8 files changed, 57 insertions(+), 36 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index f9bf5ba7509..ff82ba0a53d 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2188,7 +2188,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 4ad6e236d69..f24c2a0d252 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
#ifdef USE_PREFETCH
/*
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index 61ea3722ae2..cdf21847d7e 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1949,7 +1949,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1982,7 +1982,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2005,7 +2005,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2028,7 +2028,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 1149d89d7a1..13fb8c31702 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3555,7 +3555,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 12192445218..bab1c5d08f6 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index 1233e07d7da..ce9f258100d 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 951451a9765..3e380f29e5a 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,12 +81,12 @@ extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
extern bool check_maintenance_io_concurrency(int *newval, void **extra,
GucSource source);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -141,13 +141,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -163,7 +163,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--q7xzg7duksj2kgko
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v2-0005-Allow-to-resize-shared-memory-without-restart.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v2 4/6] Introduce pending flag for GUC assign hooks
@ 2025-02-19 16:45 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-02-19 16:45 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 2 +-
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 16 ++++----
8 files changed, 57 insertions(+), 36 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index f9bf5ba7509..ff82ba0a53d 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2188,7 +2188,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 4ad6e236d69..f24c2a0d252 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
#ifdef USE_PREFETCH
/*
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index 61ea3722ae2..cdf21847d7e 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1949,7 +1949,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1982,7 +1982,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2005,7 +2005,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2028,7 +2028,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 1149d89d7a1..13fb8c31702 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3555,7 +3555,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 12192445218..bab1c5d08f6 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index 1233e07d7da..ce9f258100d 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 951451a9765..3e380f29e5a 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,12 +81,12 @@ extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
extern bool check_maintenance_io_concurrency(int *newval, void **extra,
GucSource source);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -141,13 +141,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -163,7 +163,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--q7xzg7duksj2kgko
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v2-0005-Allow-to-resize-shared-memory-without-restart.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v2 4/6] Introduce pending flag for GUC assign hooks
@ 2025-02-19 16:45 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-02-19 16:45 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 2 +-
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 16 ++++----
8 files changed, 57 insertions(+), 36 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index f9bf5ba7509..ff82ba0a53d 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2188,7 +2188,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 4ad6e236d69..f24c2a0d252 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
#ifdef USE_PREFETCH
/*
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index 61ea3722ae2..cdf21847d7e 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1949,7 +1949,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1982,7 +1982,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2005,7 +2005,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2028,7 +2028,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 1149d89d7a1..13fb8c31702 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3555,7 +3555,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 12192445218..bab1c5d08f6 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index 1233e07d7da..ce9f258100d 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 951451a9765..3e380f29e5a 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,12 +81,12 @@ extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
extern bool check_maintenance_io_concurrency(int *newval, void **extra,
GucSource source);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -141,13 +141,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -163,7 +163,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--q7xzg7duksj2kgko
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v2-0005-Allow-to-resize-shared-memory-without-restart.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v2 4/6] Introduce pending flag for GUC assign hooks
@ 2025-02-19 16:45 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-02-19 16:45 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 2 +-
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 16 ++++----
8 files changed, 57 insertions(+), 36 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index f9bf5ba7509..ff82ba0a53d 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2188,7 +2188,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 4ad6e236d69..f24c2a0d252 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
#ifdef USE_PREFETCH
/*
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index 61ea3722ae2..cdf21847d7e 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1949,7 +1949,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1982,7 +1982,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2005,7 +2005,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2028,7 +2028,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 1149d89d7a1..13fb8c31702 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3555,7 +3555,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 12192445218..bab1c5d08f6 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index 1233e07d7da..ce9f258100d 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 951451a9765..3e380f29e5a 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,12 +81,12 @@ extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
extern bool check_maintenance_io_concurrency(int *newval, void **extra,
GucSource source);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -141,13 +141,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -163,7 +163,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--q7xzg7duksj2kgko
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v2-0005-Allow-to-resize-shared-memory-without-restart.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v2 4/6] Introduce pending flag for GUC assign hooks
@ 2025-02-19 16:45 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-02-19 16:45 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 2 +-
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 16 ++++----
8 files changed, 57 insertions(+), 36 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index f9bf5ba7509..ff82ba0a53d 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2188,7 +2188,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 4ad6e236d69..f24c2a0d252 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
#ifdef USE_PREFETCH
/*
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index 61ea3722ae2..cdf21847d7e 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1949,7 +1949,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1982,7 +1982,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2005,7 +2005,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2028,7 +2028,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 1149d89d7a1..13fb8c31702 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3555,7 +3555,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 12192445218..bab1c5d08f6 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index 1233e07d7da..ce9f258100d 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 951451a9765..3e380f29e5a 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,12 +81,12 @@ extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
extern bool check_maintenance_io_concurrency(int *newval, void **extra,
GucSource source);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -141,13 +141,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -163,7 +163,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--q7xzg7duksj2kgko
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v2-0005-Allow-to-resize-shared-memory-without-restart.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v2 4/6] Introduce pending flag for GUC assign hooks
@ 2025-02-19 16:45 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-02-19 16:45 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 2 +-
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 16 ++++----
8 files changed, 57 insertions(+), 36 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index f9bf5ba7509..ff82ba0a53d 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2188,7 +2188,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 4ad6e236d69..f24c2a0d252 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
#ifdef USE_PREFETCH
/*
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index 61ea3722ae2..cdf21847d7e 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1949,7 +1949,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1982,7 +1982,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2005,7 +2005,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2028,7 +2028,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 1149d89d7a1..13fb8c31702 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3555,7 +3555,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 12192445218..bab1c5d08f6 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index 1233e07d7da..ce9f258100d 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 951451a9765..3e380f29e5a 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,12 +81,12 @@ extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
extern bool check_maintenance_io_concurrency(int *newval, void **extra,
GucSource source);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -141,13 +141,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -163,7 +163,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--q7xzg7duksj2kgko
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v2-0005-Allow-to-resize-shared-memory-without-restart.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v2 4/6] Introduce pending flag for GUC assign hooks
@ 2025-02-19 16:45 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-02-19 16:45 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 2 +-
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 16 ++++----
8 files changed, 57 insertions(+), 36 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index f9bf5ba7509..ff82ba0a53d 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2188,7 +2188,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 4ad6e236d69..f24c2a0d252 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
#ifdef USE_PREFETCH
/*
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index 61ea3722ae2..cdf21847d7e 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1949,7 +1949,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1982,7 +1982,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2005,7 +2005,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2028,7 +2028,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 1149d89d7a1..13fb8c31702 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3555,7 +3555,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 12192445218..bab1c5d08f6 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index 1233e07d7da..ce9f258100d 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 951451a9765..3e380f29e5a 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,12 +81,12 @@ extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
extern bool check_maintenance_io_concurrency(int *newval, void **extra,
GucSource source);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -141,13 +141,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -163,7 +163,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--q7xzg7duksj2kgko
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v2-0005-Allow-to-resize-shared-memory-without-restart.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v2 4/6] Introduce pending flag for GUC assign hooks
@ 2025-02-19 16:45 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-02-19 16:45 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 2 +-
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 16 ++++----
8 files changed, 57 insertions(+), 36 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index f9bf5ba7509..ff82ba0a53d 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2188,7 +2188,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 4ad6e236d69..f24c2a0d252 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
#ifdef USE_PREFETCH
/*
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index 61ea3722ae2..cdf21847d7e 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1949,7 +1949,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1982,7 +1982,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2005,7 +2005,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2028,7 +2028,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 1149d89d7a1..13fb8c31702 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3555,7 +3555,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 12192445218..bab1c5d08f6 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index 1233e07d7da..ce9f258100d 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 951451a9765..3e380f29e5a 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,12 +81,12 @@ extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
extern bool check_maintenance_io_concurrency(int *newval, void **extra,
GucSource source);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -141,13 +141,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -163,7 +163,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--q7xzg7duksj2kgko
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v2-0005-Allow-to-resize-shared-memory-without-restart.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v2 4/6] Introduce pending flag for GUC assign hooks
@ 2025-02-19 16:45 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-02-19 16:45 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 2 +-
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 16 ++++----
8 files changed, 57 insertions(+), 36 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index f9bf5ba7509..ff82ba0a53d 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2188,7 +2188,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 4ad6e236d69..f24c2a0d252 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
#ifdef USE_PREFETCH
/*
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index 61ea3722ae2..cdf21847d7e 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1949,7 +1949,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1982,7 +1982,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2005,7 +2005,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2028,7 +2028,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 1149d89d7a1..13fb8c31702 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3555,7 +3555,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 12192445218..bab1c5d08f6 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index 1233e07d7da..ce9f258100d 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 951451a9765..3e380f29e5a 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,12 +81,12 @@ extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
extern bool check_maintenance_io_concurrency(int *newval, void **extra,
GucSource source);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -141,13 +141,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -163,7 +163,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--q7xzg7duksj2kgko
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v2-0005-Allow-to-resize-shared-memory-without-restart.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v2 4/6] Introduce pending flag for GUC assign hooks
@ 2025-02-19 16:45 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-02-19 16:45 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 2 +-
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 16 ++++----
8 files changed, 57 insertions(+), 36 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index f9bf5ba7509..ff82ba0a53d 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2188,7 +2188,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 4ad6e236d69..f24c2a0d252 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
#ifdef USE_PREFETCH
/*
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index 61ea3722ae2..cdf21847d7e 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1949,7 +1949,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1982,7 +1982,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2005,7 +2005,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2028,7 +2028,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 1149d89d7a1..13fb8c31702 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3555,7 +3555,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 12192445218..bab1c5d08f6 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index 1233e07d7da..ce9f258100d 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 951451a9765..3e380f29e5a 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,12 +81,12 @@ extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
extern bool check_maintenance_io_concurrency(int *newval, void **extra,
GucSource source);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -141,13 +141,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -163,7 +163,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--q7xzg7duksj2kgko
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v2-0005-Allow-to-resize-shared-memory-without-restart.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v2 4/6] Introduce pending flag for GUC assign hooks
@ 2025-02-19 16:45 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-02-19 16:45 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 2 +-
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 16 ++++----
8 files changed, 57 insertions(+), 36 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index f9bf5ba7509..ff82ba0a53d 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2188,7 +2188,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 4ad6e236d69..f24c2a0d252 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
#ifdef USE_PREFETCH
/*
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index 61ea3722ae2..cdf21847d7e 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1949,7 +1949,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1982,7 +1982,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2005,7 +2005,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2028,7 +2028,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 1149d89d7a1..13fb8c31702 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3555,7 +3555,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 12192445218..bab1c5d08f6 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index 1233e07d7da..ce9f258100d 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 951451a9765..3e380f29e5a 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,12 +81,12 @@ extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
extern bool check_maintenance_io_concurrency(int *newval, void **extra,
GucSource source);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -141,13 +141,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -163,7 +163,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--q7xzg7duksj2kgko
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v2-0005-Allow-to-resize-shared-memory-without-restart.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v2 4/6] Introduce pending flag for GUC assign hooks
@ 2025-02-19 16:45 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-02-19 16:45 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 2 +-
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 16 ++++----
8 files changed, 57 insertions(+), 36 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index f9bf5ba7509..ff82ba0a53d 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2188,7 +2188,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 4ad6e236d69..f24c2a0d252 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
#ifdef USE_PREFETCH
/*
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index 61ea3722ae2..cdf21847d7e 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1949,7 +1949,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1982,7 +1982,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2005,7 +2005,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2028,7 +2028,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 1149d89d7a1..13fb8c31702 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3555,7 +3555,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 12192445218..bab1c5d08f6 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index 1233e07d7da..ce9f258100d 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 951451a9765..3e380f29e5a 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,12 +81,12 @@ extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
extern bool check_maintenance_io_concurrency(int *newval, void **extra,
GucSource source);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -141,13 +141,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -163,7 +163,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--q7xzg7duksj2kgko
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v2-0005-Allow-to-resize-shared-memory-without-restart.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v2 4/6] Introduce pending flag for GUC assign hooks
@ 2025-02-19 16:45 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-02-19 16:45 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 2 +-
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 16 ++++----
8 files changed, 57 insertions(+), 36 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index f9bf5ba7509..ff82ba0a53d 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2188,7 +2188,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 4ad6e236d69..f24c2a0d252 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
#ifdef USE_PREFETCH
/*
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index 61ea3722ae2..cdf21847d7e 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1949,7 +1949,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1982,7 +1982,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2005,7 +2005,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2028,7 +2028,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 1149d89d7a1..13fb8c31702 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3555,7 +3555,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 12192445218..bab1c5d08f6 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index 1233e07d7da..ce9f258100d 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 951451a9765..3e380f29e5a 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,12 +81,12 @@ extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
extern bool check_maintenance_io_concurrency(int *newval, void **extra,
GucSource source);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -141,13 +141,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -163,7 +163,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--q7xzg7duksj2kgko
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v2-0005-Allow-to-resize-shared-memory-without-restart.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v2 4/6] Introduce pending flag for GUC assign hooks
@ 2025-02-19 16:45 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-02-19 16:45 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 2 +-
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 16 ++++----
8 files changed, 57 insertions(+), 36 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index f9bf5ba7509..ff82ba0a53d 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2188,7 +2188,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 4ad6e236d69..f24c2a0d252 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
#ifdef USE_PREFETCH
/*
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index 61ea3722ae2..cdf21847d7e 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1949,7 +1949,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1982,7 +1982,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2005,7 +2005,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2028,7 +2028,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 1149d89d7a1..13fb8c31702 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3555,7 +3555,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 12192445218..bab1c5d08f6 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index 1233e07d7da..ce9f258100d 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 951451a9765..3e380f29e5a 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,12 +81,12 @@ extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
extern bool check_maintenance_io_concurrency(int *newval, void **extra,
GucSource source);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -141,13 +141,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -163,7 +163,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--q7xzg7duksj2kgko
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v2-0005-Allow-to-resize-shared-memory-without-restart.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v2 4/6] Introduce pending flag for GUC assign hooks
@ 2025-02-19 16:45 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-02-19 16:45 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 2 +-
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 16 ++++----
8 files changed, 57 insertions(+), 36 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index f9bf5ba7509..ff82ba0a53d 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2188,7 +2188,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 4ad6e236d69..f24c2a0d252 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
#ifdef USE_PREFETCH
/*
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index 61ea3722ae2..cdf21847d7e 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1949,7 +1949,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1982,7 +1982,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2005,7 +2005,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2028,7 +2028,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 1149d89d7a1..13fb8c31702 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3555,7 +3555,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 12192445218..bab1c5d08f6 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index 1233e07d7da..ce9f258100d 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 951451a9765..3e380f29e5a 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,12 +81,12 @@ extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
extern bool check_maintenance_io_concurrency(int *newval, void **extra,
GucSource source);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -141,13 +141,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -163,7 +163,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--q7xzg7duksj2kgko
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v2-0005-Allow-to-resize-shared-memory-without-restart.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v2 4/6] Introduce pending flag for GUC assign hooks
@ 2025-02-19 16:45 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-02-19 16:45 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 2 +-
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 16 ++++----
8 files changed, 57 insertions(+), 36 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index f9bf5ba7509..ff82ba0a53d 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2188,7 +2188,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 4ad6e236d69..f24c2a0d252 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
#ifdef USE_PREFETCH
/*
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index 61ea3722ae2..cdf21847d7e 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1949,7 +1949,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1982,7 +1982,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2005,7 +2005,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2028,7 +2028,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 1149d89d7a1..13fb8c31702 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3555,7 +3555,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 12192445218..bab1c5d08f6 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index 1233e07d7da..ce9f258100d 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 951451a9765..3e380f29e5a 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,12 +81,12 @@ extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
extern bool check_maintenance_io_concurrency(int *newval, void **extra,
GucSource source);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -141,13 +141,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -163,7 +163,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--q7xzg7duksj2kgko
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v2-0005-Allow-to-resize-shared-memory-without-restart.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v2 4/6] Introduce pending flag for GUC assign hooks
@ 2025-02-19 16:45 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-02-19 16:45 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 2 +-
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 16 ++++----
8 files changed, 57 insertions(+), 36 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index f9bf5ba7509..ff82ba0a53d 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2188,7 +2188,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 4ad6e236d69..f24c2a0d252 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
#ifdef USE_PREFETCH
/*
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index 61ea3722ae2..cdf21847d7e 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1949,7 +1949,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1982,7 +1982,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2005,7 +2005,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2028,7 +2028,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 1149d89d7a1..13fb8c31702 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3555,7 +3555,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 12192445218..bab1c5d08f6 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index 1233e07d7da..ce9f258100d 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 951451a9765..3e380f29e5a 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,12 +81,12 @@ extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
extern bool check_maintenance_io_concurrency(int *newval, void **extra,
GucSource source);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -141,13 +141,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -163,7 +163,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--q7xzg7duksj2kgko
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v2-0005-Allow-to-resize-shared-memory-without-restart.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v2 4/6] Introduce pending flag for GUC assign hooks
@ 2025-02-19 16:45 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-02-19 16:45 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 2 +-
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 16 ++++----
8 files changed, 57 insertions(+), 36 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index f9bf5ba7509..ff82ba0a53d 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2188,7 +2188,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 4ad6e236d69..f24c2a0d252 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
#ifdef USE_PREFETCH
/*
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index 61ea3722ae2..cdf21847d7e 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1949,7 +1949,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1982,7 +1982,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2005,7 +2005,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2028,7 +2028,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 1149d89d7a1..13fb8c31702 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3555,7 +3555,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 12192445218..bab1c5d08f6 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index 1233e07d7da..ce9f258100d 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 951451a9765..3e380f29e5a 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,12 +81,12 @@ extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
extern bool check_maintenance_io_concurrency(int *newval, void **extra,
GucSource source);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -141,13 +141,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -163,7 +163,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--q7xzg7duksj2kgko
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v2-0005-Allow-to-resize-shared-memory-without-restart.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v2 4/6] Introduce pending flag for GUC assign hooks
@ 2025-02-19 16:45 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-02-19 16:45 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 2 +-
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 16 ++++----
8 files changed, 57 insertions(+), 36 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index f9bf5ba7509..ff82ba0a53d 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2188,7 +2188,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 4ad6e236d69..f24c2a0d252 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
#ifdef USE_PREFETCH
/*
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index 61ea3722ae2..cdf21847d7e 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1949,7 +1949,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1982,7 +1982,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2005,7 +2005,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2028,7 +2028,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 1149d89d7a1..13fb8c31702 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3555,7 +3555,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 12192445218..bab1c5d08f6 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index 1233e07d7da..ce9f258100d 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 951451a9765..3e380f29e5a 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,12 +81,12 @@ extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
extern bool check_maintenance_io_concurrency(int *newval, void **extra,
GucSource source);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -141,13 +141,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -163,7 +163,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--q7xzg7duksj2kgko
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v2-0005-Allow-to-resize-shared-memory-without-restart.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v2 4/6] Introduce pending flag for GUC assign hooks
@ 2025-02-19 16:45 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-02-19 16:45 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 2 +-
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 16 ++++----
8 files changed, 57 insertions(+), 36 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index f9bf5ba7509..ff82ba0a53d 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2188,7 +2188,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 4ad6e236d69..f24c2a0d252 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
#ifdef USE_PREFETCH
/*
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index 61ea3722ae2..cdf21847d7e 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1949,7 +1949,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1982,7 +1982,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2005,7 +2005,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2028,7 +2028,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 1149d89d7a1..13fb8c31702 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3555,7 +3555,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 12192445218..bab1c5d08f6 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index 1233e07d7da..ce9f258100d 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 951451a9765..3e380f29e5a 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,12 +81,12 @@ extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
extern bool check_maintenance_io_concurrency(int *newval, void **extra,
GucSource source);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -141,13 +141,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -163,7 +163,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--q7xzg7duksj2kgko
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v2-0005-Allow-to-resize-shared-memory-without-restart.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v2 4/6] Introduce pending flag for GUC assign hooks
@ 2025-02-19 16:45 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-02-19 16:45 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 2 +-
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 16 ++++----
8 files changed, 57 insertions(+), 36 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index f9bf5ba7509..ff82ba0a53d 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2188,7 +2188,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 4ad6e236d69..f24c2a0d252 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
#ifdef USE_PREFETCH
/*
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index 61ea3722ae2..cdf21847d7e 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1949,7 +1949,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1982,7 +1982,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2005,7 +2005,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2028,7 +2028,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 1149d89d7a1..13fb8c31702 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3555,7 +3555,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 12192445218..bab1c5d08f6 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index 1233e07d7da..ce9f258100d 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 951451a9765..3e380f29e5a 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,12 +81,12 @@ extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
extern bool check_maintenance_io_concurrency(int *newval, void **extra,
GucSource source);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -141,13 +141,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -163,7 +163,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--q7xzg7duksj2kgko
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v2-0005-Allow-to-resize-shared-memory-without-restart.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v2 4/6] Introduce pending flag for GUC assign hooks
@ 2025-02-19 16:45 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-02-19 16:45 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 2 +-
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 16 ++++----
8 files changed, 57 insertions(+), 36 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index f9bf5ba7509..ff82ba0a53d 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2188,7 +2188,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 4ad6e236d69..f24c2a0d252 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
#ifdef USE_PREFETCH
/*
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index 61ea3722ae2..cdf21847d7e 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1949,7 +1949,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1982,7 +1982,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2005,7 +2005,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2028,7 +2028,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 1149d89d7a1..13fb8c31702 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3555,7 +3555,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 12192445218..bab1c5d08f6 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index 1233e07d7da..ce9f258100d 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 951451a9765..3e380f29e5a 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,12 +81,12 @@ extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
extern bool check_maintenance_io_concurrency(int *newval, void **extra,
GucSource source);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -141,13 +141,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -163,7 +163,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--q7xzg7duksj2kgko
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v2-0005-Allow-to-resize-shared-memory-without-restart.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v2 4/6] Introduce pending flag for GUC assign hooks
@ 2025-02-19 16:45 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-02-19 16:45 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 2 +-
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 16 ++++----
8 files changed, 57 insertions(+), 36 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index f9bf5ba7509..ff82ba0a53d 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2188,7 +2188,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 4ad6e236d69..f24c2a0d252 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
#ifdef USE_PREFETCH
/*
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index 61ea3722ae2..cdf21847d7e 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1949,7 +1949,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1982,7 +1982,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2005,7 +2005,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2028,7 +2028,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 1149d89d7a1..13fb8c31702 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3555,7 +3555,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 12192445218..bab1c5d08f6 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index 1233e07d7da..ce9f258100d 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 951451a9765..3e380f29e5a 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,12 +81,12 @@ extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
extern bool check_maintenance_io_concurrency(int *newval, void **extra,
GucSource source);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -141,13 +141,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -163,7 +163,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--q7xzg7duksj2kgko
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v2-0005-Allow-to-resize-shared-memory-without-restart.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v2 4/6] Introduce pending flag for GUC assign hooks
@ 2025-02-19 16:45 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-02-19 16:45 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 2 +-
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 16 ++++----
8 files changed, 57 insertions(+), 36 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index f9bf5ba7509..ff82ba0a53d 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2188,7 +2188,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 4ad6e236d69..f24c2a0d252 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
#ifdef USE_PREFETCH
/*
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index 61ea3722ae2..cdf21847d7e 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1949,7 +1949,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1982,7 +1982,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2005,7 +2005,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2028,7 +2028,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 1149d89d7a1..13fb8c31702 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3555,7 +3555,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 12192445218..bab1c5d08f6 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index 1233e07d7da..ce9f258100d 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 951451a9765..3e380f29e5a 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,12 +81,12 @@ extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
extern bool check_maintenance_io_concurrency(int *newval, void **extra,
GucSource source);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -141,13 +141,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -163,7 +163,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--q7xzg7duksj2kgko
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v2-0005-Allow-to-resize-shared-memory-without-restart.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v2 4/6] Introduce pending flag for GUC assign hooks
@ 2025-02-19 16:45 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-02-19 16:45 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 2 +-
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 16 ++++----
8 files changed, 57 insertions(+), 36 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index f9bf5ba7509..ff82ba0a53d 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2188,7 +2188,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 4ad6e236d69..f24c2a0d252 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
#ifdef USE_PREFETCH
/*
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index 61ea3722ae2..cdf21847d7e 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1949,7 +1949,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1982,7 +1982,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2005,7 +2005,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2028,7 +2028,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 1149d89d7a1..13fb8c31702 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3555,7 +3555,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 12192445218..bab1c5d08f6 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index 1233e07d7da..ce9f258100d 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 951451a9765..3e380f29e5a 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,12 +81,12 @@ extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
extern bool check_maintenance_io_concurrency(int *newval, void **extra,
GucSource source);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -141,13 +141,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -163,7 +163,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--q7xzg7duksj2kgko
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v2-0005-Allow-to-resize-shared-memory-without-restart.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v2 4/6] Introduce pending flag for GUC assign hooks
@ 2025-02-19 16:45 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-02-19 16:45 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 2 +-
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 16 ++++----
8 files changed, 57 insertions(+), 36 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index f9bf5ba7509..ff82ba0a53d 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2188,7 +2188,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 4ad6e236d69..f24c2a0d252 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
#ifdef USE_PREFETCH
/*
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index 61ea3722ae2..cdf21847d7e 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1949,7 +1949,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1982,7 +1982,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2005,7 +2005,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2028,7 +2028,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 1149d89d7a1..13fb8c31702 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3555,7 +3555,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 12192445218..bab1c5d08f6 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index 1233e07d7da..ce9f258100d 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 951451a9765..3e380f29e5a 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,12 +81,12 @@ extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
extern bool check_maintenance_io_concurrency(int *newval, void **extra,
GucSource source);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -141,13 +141,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -163,7 +163,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--q7xzg7duksj2kgko
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v2-0005-Allow-to-resize-shared-memory-without-restart.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v2 4/6] Introduce pending flag for GUC assign hooks
@ 2025-02-19 16:45 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-02-19 16:45 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 2 +-
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 16 ++++----
8 files changed, 57 insertions(+), 36 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index f9bf5ba7509..ff82ba0a53d 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2188,7 +2188,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 4ad6e236d69..f24c2a0d252 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
#ifdef USE_PREFETCH
/*
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index 61ea3722ae2..cdf21847d7e 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1949,7 +1949,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1982,7 +1982,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2005,7 +2005,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2028,7 +2028,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 1149d89d7a1..13fb8c31702 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3555,7 +3555,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 12192445218..bab1c5d08f6 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index 1233e07d7da..ce9f258100d 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 951451a9765..3e380f29e5a 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,12 +81,12 @@ extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
extern bool check_maintenance_io_concurrency(int *newval, void **extra,
GucSource source);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -141,13 +141,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -163,7 +163,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--q7xzg7duksj2kgko
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v2-0005-Allow-to-resize-shared-memory-without-restart.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v2 4/6] Introduce pending flag for GUC assign hooks
@ 2025-02-19 16:45 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-02-19 16:45 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 2 +-
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 16 ++++----
8 files changed, 57 insertions(+), 36 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index f9bf5ba7509..ff82ba0a53d 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2188,7 +2188,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 4ad6e236d69..f24c2a0d252 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
#ifdef USE_PREFETCH
/*
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index 61ea3722ae2..cdf21847d7e 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1949,7 +1949,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1982,7 +1982,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2005,7 +2005,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2028,7 +2028,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 1149d89d7a1..13fb8c31702 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3555,7 +3555,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 12192445218..bab1c5d08f6 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index 1233e07d7da..ce9f258100d 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 951451a9765..3e380f29e5a 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,12 +81,12 @@ extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
extern bool check_maintenance_io_concurrency(int *newval, void **extra,
GucSource source);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -141,13 +141,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -163,7 +163,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--q7xzg7duksj2kgko
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v2-0005-Allow-to-resize-shared-memory-without-restart.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v2 4/6] Introduce pending flag for GUC assign hooks
@ 2025-02-19 16:45 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-02-19 16:45 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 2 +-
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 16 ++++----
8 files changed, 57 insertions(+), 36 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index f9bf5ba7509..ff82ba0a53d 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2188,7 +2188,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 4ad6e236d69..f24c2a0d252 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
#ifdef USE_PREFETCH
/*
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index 61ea3722ae2..cdf21847d7e 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1949,7 +1949,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1982,7 +1982,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2005,7 +2005,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2028,7 +2028,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 1149d89d7a1..13fb8c31702 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3555,7 +3555,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 12192445218..bab1c5d08f6 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index 1233e07d7da..ce9f258100d 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 951451a9765..3e380f29e5a 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,12 +81,12 @@ extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
extern bool check_maintenance_io_concurrency(int *newval, void **extra,
GucSource source);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -141,13 +141,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -163,7 +163,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--q7xzg7duksj2kgko
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v2-0005-Allow-to-resize-shared-memory-without-restart.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v2 4/6] Introduce pending flag for GUC assign hooks
@ 2025-02-19 16:45 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-02-19 16:45 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 2 +-
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 16 ++++----
8 files changed, 57 insertions(+), 36 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index f9bf5ba7509..ff82ba0a53d 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2188,7 +2188,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 4ad6e236d69..f24c2a0d252 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
#ifdef USE_PREFETCH
/*
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index 61ea3722ae2..cdf21847d7e 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1949,7 +1949,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1982,7 +1982,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2005,7 +2005,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2028,7 +2028,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 1149d89d7a1..13fb8c31702 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3555,7 +3555,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 12192445218..bab1c5d08f6 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index 1233e07d7da..ce9f258100d 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 951451a9765..3e380f29e5a 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,12 +81,12 @@ extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
extern bool check_maintenance_io_concurrency(int *newval, void **extra,
GucSource source);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -141,13 +141,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -163,7 +163,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--q7xzg7duksj2kgko
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v2-0005-Allow-to-resize-shared-memory-without-restart.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v2 4/6] Introduce pending flag for GUC assign hooks
@ 2025-02-19 16:45 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-02-19 16:45 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 2 +-
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 16 ++++----
8 files changed, 57 insertions(+), 36 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index f9bf5ba7509..ff82ba0a53d 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2188,7 +2188,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 4ad6e236d69..f24c2a0d252 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
#ifdef USE_PREFETCH
/*
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index 61ea3722ae2..cdf21847d7e 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1949,7 +1949,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1982,7 +1982,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2005,7 +2005,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2028,7 +2028,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 1149d89d7a1..13fb8c31702 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3555,7 +3555,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 12192445218..bab1c5d08f6 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index 1233e07d7da..ce9f258100d 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 951451a9765..3e380f29e5a 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,12 +81,12 @@ extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
extern bool check_maintenance_io_concurrency(int *newval, void **extra,
GucSource source);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -141,13 +141,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -163,7 +163,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--q7xzg7duksj2kgko
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v2-0005-Allow-to-resize-shared-memory-without-restart.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v2 4/6] Introduce pending flag for GUC assign hooks
@ 2025-02-19 16:45 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-02-19 16:45 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 2 +-
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 16 ++++----
8 files changed, 57 insertions(+), 36 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index f9bf5ba7509..ff82ba0a53d 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2188,7 +2188,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 4ad6e236d69..f24c2a0d252 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
#ifdef USE_PREFETCH
/*
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index 61ea3722ae2..cdf21847d7e 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1949,7 +1949,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1982,7 +1982,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2005,7 +2005,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2028,7 +2028,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 1149d89d7a1..13fb8c31702 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3555,7 +3555,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 12192445218..bab1c5d08f6 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index 1233e07d7da..ce9f258100d 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 951451a9765..3e380f29e5a 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,12 +81,12 @@ extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
extern bool check_maintenance_io_concurrency(int *newval, void **extra,
GucSource source);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -141,13 +141,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -163,7 +163,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--q7xzg7duksj2kgko
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v2-0005-Allow-to-resize-shared-memory-without-restart.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v2 4/6] Introduce pending flag for GUC assign hooks
@ 2025-02-19 16:45 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-02-19 16:45 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 2 +-
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 16 ++++----
8 files changed, 57 insertions(+), 36 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index f9bf5ba7509..ff82ba0a53d 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2188,7 +2188,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 4ad6e236d69..f24c2a0d252 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
#ifdef USE_PREFETCH
/*
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index 61ea3722ae2..cdf21847d7e 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1949,7 +1949,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1982,7 +1982,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2005,7 +2005,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2028,7 +2028,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 1149d89d7a1..13fb8c31702 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3555,7 +3555,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 12192445218..bab1c5d08f6 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index 1233e07d7da..ce9f258100d 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 951451a9765..3e380f29e5a 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,12 +81,12 @@ extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
extern bool check_maintenance_io_concurrency(int *newval, void **extra,
GucSource source);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -141,13 +141,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -163,7 +163,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--q7xzg7duksj2kgko
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v2-0005-Allow-to-resize-shared-memory-without-restart.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v2 4/6] Introduce pending flag for GUC assign hooks
@ 2025-02-19 16:45 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-02-19 16:45 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 2 +-
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 16 ++++----
8 files changed, 57 insertions(+), 36 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index f9bf5ba7509..ff82ba0a53d 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2188,7 +2188,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 4ad6e236d69..f24c2a0d252 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
#ifdef USE_PREFETCH
/*
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index 61ea3722ae2..cdf21847d7e 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1949,7 +1949,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1982,7 +1982,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2005,7 +2005,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2028,7 +2028,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 1149d89d7a1..13fb8c31702 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3555,7 +3555,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 12192445218..bab1c5d08f6 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index 1233e07d7da..ce9f258100d 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 951451a9765..3e380f29e5a 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,12 +81,12 @@ extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
extern bool check_maintenance_io_concurrency(int *newval, void **extra,
GucSource source);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -141,13 +141,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -163,7 +163,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--q7xzg7duksj2kgko
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v2-0005-Allow-to-resize-shared-memory-without-restart.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v2 4/6] Introduce pending flag for GUC assign hooks
@ 2025-02-19 16:45 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-02-19 16:45 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 2 +-
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 16 ++++----
8 files changed, 57 insertions(+), 36 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index f9bf5ba7509..ff82ba0a53d 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2188,7 +2188,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 4ad6e236d69..f24c2a0d252 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
#ifdef USE_PREFETCH
/*
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index 61ea3722ae2..cdf21847d7e 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1949,7 +1949,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1982,7 +1982,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2005,7 +2005,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2028,7 +2028,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 1149d89d7a1..13fb8c31702 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3555,7 +3555,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 12192445218..bab1c5d08f6 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index 1233e07d7da..ce9f258100d 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 951451a9765..3e380f29e5a 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,12 +81,12 @@ extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
extern bool check_maintenance_io_concurrency(int *newval, void **extra,
GucSource source);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -141,13 +141,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -163,7 +163,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--q7xzg7duksj2kgko
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v2-0005-Allow-to-resize-shared-memory-without-restart.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v2 4/6] Introduce pending flag for GUC assign hooks
@ 2025-02-19 16:45 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-02-19 16:45 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 2 +-
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 16 ++++----
8 files changed, 57 insertions(+), 36 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index f9bf5ba7509..ff82ba0a53d 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2188,7 +2188,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 4ad6e236d69..f24c2a0d252 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
#ifdef USE_PREFETCH
/*
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index 61ea3722ae2..cdf21847d7e 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1949,7 +1949,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1982,7 +1982,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2005,7 +2005,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2028,7 +2028,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 1149d89d7a1..13fb8c31702 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3555,7 +3555,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 12192445218..bab1c5d08f6 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index 1233e07d7da..ce9f258100d 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 951451a9765..3e380f29e5a 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,12 +81,12 @@ extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
extern bool check_maintenance_io_concurrency(int *newval, void **extra,
GucSource source);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -141,13 +141,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -163,7 +163,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--q7xzg7duksj2kgko
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v2-0005-Allow-to-resize-shared-memory-without-restart.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v2 4/6] Introduce pending flag for GUC assign hooks
@ 2025-02-19 16:45 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-02-19 16:45 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 2 +-
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 16 ++++----
8 files changed, 57 insertions(+), 36 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index f9bf5ba7509..ff82ba0a53d 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2188,7 +2188,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 4ad6e236d69..f24c2a0d252 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
#ifdef USE_PREFETCH
/*
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index 61ea3722ae2..cdf21847d7e 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1949,7 +1949,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1982,7 +1982,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2005,7 +2005,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2028,7 +2028,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 1149d89d7a1..13fb8c31702 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3555,7 +3555,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 12192445218..bab1c5d08f6 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index 1233e07d7da..ce9f258100d 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 951451a9765..3e380f29e5a 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,12 +81,12 @@ extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
extern bool check_maintenance_io_concurrency(int *newval, void **extra,
GucSource source);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -141,13 +141,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -163,7 +163,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--q7xzg7duksj2kgko
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v2-0005-Allow-to-resize-shared-memory-without-restart.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v2 4/6] Introduce pending flag for GUC assign hooks
@ 2025-02-19 16:45 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-02-19 16:45 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 2 +-
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 16 ++++----
8 files changed, 57 insertions(+), 36 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index f9bf5ba7509..ff82ba0a53d 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2188,7 +2188,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 4ad6e236d69..f24c2a0d252 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
#ifdef USE_PREFETCH
/*
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index 61ea3722ae2..cdf21847d7e 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1949,7 +1949,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1982,7 +1982,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2005,7 +2005,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2028,7 +2028,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 1149d89d7a1..13fb8c31702 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3555,7 +3555,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 12192445218..bab1c5d08f6 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index 1233e07d7da..ce9f258100d 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 951451a9765..3e380f29e5a 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,12 +81,12 @@ extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
extern bool check_maintenance_io_concurrency(int *newval, void **extra,
GucSource source);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -141,13 +141,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -163,7 +163,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--q7xzg7duksj2kgko
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v2-0005-Allow-to-resize-shared-memory-without-restart.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v2 4/6] Introduce pending flag for GUC assign hooks
@ 2025-02-19 16:45 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-02-19 16:45 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 2 +-
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 16 ++++----
8 files changed, 57 insertions(+), 36 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index f9bf5ba7509..ff82ba0a53d 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2188,7 +2188,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 4ad6e236d69..f24c2a0d252 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
#ifdef USE_PREFETCH
/*
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index 61ea3722ae2..cdf21847d7e 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1949,7 +1949,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1982,7 +1982,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2005,7 +2005,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2028,7 +2028,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 1149d89d7a1..13fb8c31702 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3555,7 +3555,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 12192445218..bab1c5d08f6 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index 1233e07d7da..ce9f258100d 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 951451a9765..3e380f29e5a 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,12 +81,12 @@ extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
extern bool check_maintenance_io_concurrency(int *newval, void **extra,
GucSource source);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -141,13 +141,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -163,7 +163,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--q7xzg7duksj2kgko
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v2-0005-Allow-to-resize-shared-memory-without-restart.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v2 4/6] Introduce pending flag for GUC assign hooks
@ 2025-02-19 16:45 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-02-19 16:45 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 2 +-
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 16 ++++----
8 files changed, 57 insertions(+), 36 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index f9bf5ba7509..ff82ba0a53d 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2188,7 +2188,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 4ad6e236d69..f24c2a0d252 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
#ifdef USE_PREFETCH
/*
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index 61ea3722ae2..cdf21847d7e 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1949,7 +1949,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1982,7 +1982,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2005,7 +2005,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2028,7 +2028,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 1149d89d7a1..13fb8c31702 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3555,7 +3555,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 12192445218..bab1c5d08f6 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index 1233e07d7da..ce9f258100d 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 951451a9765..3e380f29e5a 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,12 +81,12 @@ extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
extern bool check_maintenance_io_concurrency(int *newval, void **extra,
GucSource source);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -141,13 +141,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -163,7 +163,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--q7xzg7duksj2kgko
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v2-0005-Allow-to-resize-shared-memory-without-restart.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v2 4/6] Introduce pending flag for GUC assign hooks
@ 2025-02-19 16:45 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-02-19 16:45 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 2 +-
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 16 ++++----
8 files changed, 57 insertions(+), 36 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index f9bf5ba7509..ff82ba0a53d 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2188,7 +2188,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 4ad6e236d69..f24c2a0d252 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
#ifdef USE_PREFETCH
/*
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index 61ea3722ae2..cdf21847d7e 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1949,7 +1949,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1982,7 +1982,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2005,7 +2005,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2028,7 +2028,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 1149d89d7a1..13fb8c31702 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3555,7 +3555,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 12192445218..bab1c5d08f6 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index 1233e07d7da..ce9f258100d 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 951451a9765..3e380f29e5a 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,12 +81,12 @@ extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
extern bool check_maintenance_io_concurrency(int *newval, void **extra,
GucSource source);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -141,13 +141,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -163,7 +163,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--q7xzg7duksj2kgko
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v2-0005-Allow-to-resize-shared-memory-without-restart.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v2 4/6] Introduce pending flag for GUC assign hooks
@ 2025-02-19 16:45 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-02-19 16:45 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 2 +-
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 16 ++++----
8 files changed, 57 insertions(+), 36 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index f9bf5ba7509..ff82ba0a53d 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2188,7 +2188,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 4ad6e236d69..f24c2a0d252 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
#ifdef USE_PREFETCH
/*
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index 61ea3722ae2..cdf21847d7e 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1949,7 +1949,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1982,7 +1982,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2005,7 +2005,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2028,7 +2028,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 1149d89d7a1..13fb8c31702 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3555,7 +3555,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 12192445218..bab1c5d08f6 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index 1233e07d7da..ce9f258100d 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 951451a9765..3e380f29e5a 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,12 +81,12 @@ extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
extern bool check_maintenance_io_concurrency(int *newval, void **extra,
GucSource source);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -141,13 +141,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -163,7 +163,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--q7xzg7duksj2kgko
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v2-0005-Allow-to-resize-shared-memory-without-restart.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v2 4/6] Introduce pending flag for GUC assign hooks
@ 2025-02-19 16:45 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-02-19 16:45 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 2 +-
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 16 ++++----
8 files changed, 57 insertions(+), 36 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index f9bf5ba7509..ff82ba0a53d 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2188,7 +2188,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 4ad6e236d69..f24c2a0d252 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
#ifdef USE_PREFETCH
/*
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index 61ea3722ae2..cdf21847d7e 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1949,7 +1949,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1982,7 +1982,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2005,7 +2005,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2028,7 +2028,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 1149d89d7a1..13fb8c31702 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3555,7 +3555,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 12192445218..bab1c5d08f6 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index 1233e07d7da..ce9f258100d 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 951451a9765..3e380f29e5a 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,12 +81,12 @@ extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
extern bool check_maintenance_io_concurrency(int *newval, void **extra,
GucSource source);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -141,13 +141,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -163,7 +163,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--q7xzg7duksj2kgko
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v2-0005-Allow-to-resize-shared-memory-without-restart.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v2 4/6] Introduce pending flag for GUC assign hooks
@ 2025-02-19 16:45 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-02-19 16:45 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 2 +-
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 16 ++++----
8 files changed, 57 insertions(+), 36 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index f9bf5ba7509..ff82ba0a53d 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2188,7 +2188,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 4ad6e236d69..f24c2a0d252 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
#ifdef USE_PREFETCH
/*
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index 61ea3722ae2..cdf21847d7e 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1949,7 +1949,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1982,7 +1982,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2005,7 +2005,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2028,7 +2028,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 1149d89d7a1..13fb8c31702 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3555,7 +3555,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 12192445218..bab1c5d08f6 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index 1233e07d7da..ce9f258100d 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 951451a9765..3e380f29e5a 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,12 +81,12 @@ extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
extern bool check_maintenance_io_concurrency(int *newval, void **extra,
GucSource source);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -141,13 +141,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -163,7 +163,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--q7xzg7duksj2kgko
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v2-0005-Allow-to-resize-shared-memory-without-restart.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v2 4/6] Introduce pending flag for GUC assign hooks
@ 2025-02-19 16:45 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-02-19 16:45 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 2 +-
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 16 ++++----
8 files changed, 57 insertions(+), 36 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index f9bf5ba7509..ff82ba0a53d 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2188,7 +2188,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 4ad6e236d69..f24c2a0d252 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
#ifdef USE_PREFETCH
/*
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index 61ea3722ae2..cdf21847d7e 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1949,7 +1949,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1982,7 +1982,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2005,7 +2005,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2028,7 +2028,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 1149d89d7a1..13fb8c31702 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3555,7 +3555,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 12192445218..bab1c5d08f6 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index 1233e07d7da..ce9f258100d 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 951451a9765..3e380f29e5a 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,12 +81,12 @@ extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
extern bool check_maintenance_io_concurrency(int *newval, void **extra,
GucSource source);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -141,13 +141,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -163,7 +163,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--q7xzg7duksj2kgko
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v2-0005-Allow-to-resize-shared-memory-without-restart.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v2 4/6] Introduce pending flag for GUC assign hooks
@ 2025-02-19 16:45 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-02-19 16:45 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 2 +-
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 16 ++++----
8 files changed, 57 insertions(+), 36 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index f9bf5ba7509..ff82ba0a53d 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2188,7 +2188,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 4ad6e236d69..f24c2a0d252 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
#ifdef USE_PREFETCH
/*
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index 61ea3722ae2..cdf21847d7e 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1949,7 +1949,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1982,7 +1982,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2005,7 +2005,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2028,7 +2028,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 1149d89d7a1..13fb8c31702 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3555,7 +3555,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 12192445218..bab1c5d08f6 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index 1233e07d7da..ce9f258100d 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 951451a9765..3e380f29e5a 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,12 +81,12 @@ extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
extern bool check_maintenance_io_concurrency(int *newval, void **extra,
GucSource source);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -141,13 +141,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -163,7 +163,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--q7xzg7duksj2kgko
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v2-0005-Allow-to-resize-shared-memory-without-restart.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v2 4/6] Introduce pending flag for GUC assign hooks
@ 2025-02-19 16:45 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-02-19 16:45 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 2 +-
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 16 ++++----
8 files changed, 57 insertions(+), 36 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index f9bf5ba7509..ff82ba0a53d 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2188,7 +2188,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 4ad6e236d69..f24c2a0d252 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
#ifdef USE_PREFETCH
/*
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index 61ea3722ae2..cdf21847d7e 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1949,7 +1949,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1982,7 +1982,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2005,7 +2005,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2028,7 +2028,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 1149d89d7a1..13fb8c31702 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3555,7 +3555,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 12192445218..bab1c5d08f6 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index 1233e07d7da..ce9f258100d 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 951451a9765..3e380f29e5a 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,12 +81,12 @@ extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
extern bool check_maintenance_io_concurrency(int *newval, void **extra,
GucSource source);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -141,13 +141,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -163,7 +163,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--q7xzg7duksj2kgko
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v2-0005-Allow-to-resize-shared-memory-without-restart.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v2 4/6] Introduce pending flag for GUC assign hooks
@ 2025-02-19 16:45 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-02-19 16:45 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 2 +-
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 16 ++++----
8 files changed, 57 insertions(+), 36 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index f9bf5ba7509..ff82ba0a53d 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2188,7 +2188,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 4ad6e236d69..f24c2a0d252 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
#ifdef USE_PREFETCH
/*
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index 61ea3722ae2..cdf21847d7e 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1949,7 +1949,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1982,7 +1982,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2005,7 +2005,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2028,7 +2028,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 1149d89d7a1..13fb8c31702 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3555,7 +3555,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 12192445218..bab1c5d08f6 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index 1233e07d7da..ce9f258100d 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 951451a9765..3e380f29e5a 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,12 +81,12 @@ extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
extern bool check_maintenance_io_concurrency(int *newval, void **extra,
GucSource source);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -141,13 +141,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -163,7 +163,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--q7xzg7duksj2kgko
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v2-0005-Allow-to-resize-shared-memory-without-restart.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v2 4/6] Introduce pending flag for GUC assign hooks
@ 2025-02-19 16:45 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-02-19 16:45 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 2 +-
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 16 ++++----
8 files changed, 57 insertions(+), 36 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index f9bf5ba7509..ff82ba0a53d 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2188,7 +2188,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 4ad6e236d69..f24c2a0d252 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
#ifdef USE_PREFETCH
/*
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index 61ea3722ae2..cdf21847d7e 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1949,7 +1949,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1982,7 +1982,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2005,7 +2005,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2028,7 +2028,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 1149d89d7a1..13fb8c31702 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3555,7 +3555,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 12192445218..bab1c5d08f6 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index 1233e07d7da..ce9f258100d 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 951451a9765..3e380f29e5a 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,12 +81,12 @@ extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
extern bool check_maintenance_io_concurrency(int *newval, void **extra,
GucSource source);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -141,13 +141,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -163,7 +163,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--q7xzg7duksj2kgko
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v2-0005-Allow-to-resize-shared-memory-without-restart.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v2 4/6] Introduce pending flag for GUC assign hooks
@ 2025-02-19 16:45 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-02-19 16:45 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 2 +-
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 16 ++++----
8 files changed, 57 insertions(+), 36 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index f9bf5ba7509..ff82ba0a53d 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2188,7 +2188,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 4ad6e236d69..f24c2a0d252 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
#ifdef USE_PREFETCH
/*
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index 61ea3722ae2..cdf21847d7e 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1949,7 +1949,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1982,7 +1982,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2005,7 +2005,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2028,7 +2028,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 1149d89d7a1..13fb8c31702 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3555,7 +3555,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 12192445218..bab1c5d08f6 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index 1233e07d7da..ce9f258100d 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 951451a9765..3e380f29e5a 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,12 +81,12 @@ extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
extern bool check_maintenance_io_concurrency(int *newval, void **extra,
GucSource source);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -141,13 +141,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -163,7 +163,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--q7xzg7duksj2kgko
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v2-0005-Allow-to-resize-shared-memory-without-restart.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v2 4/6] Introduce pending flag for GUC assign hooks
@ 2025-02-19 16:45 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-02-19 16:45 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 2 +-
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 16 ++++----
8 files changed, 57 insertions(+), 36 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index f9bf5ba7509..ff82ba0a53d 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2188,7 +2188,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 4ad6e236d69..f24c2a0d252 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
#ifdef USE_PREFETCH
/*
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index 61ea3722ae2..cdf21847d7e 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1949,7 +1949,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1982,7 +1982,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2005,7 +2005,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2028,7 +2028,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 1149d89d7a1..13fb8c31702 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3555,7 +3555,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 12192445218..bab1c5d08f6 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index 1233e07d7da..ce9f258100d 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 951451a9765..3e380f29e5a 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,12 +81,12 @@ extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
extern bool check_maintenance_io_concurrency(int *newval, void **extra,
GucSource source);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -141,13 +141,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -163,7 +163,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--q7xzg7duksj2kgko
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v2-0005-Allow-to-resize-shared-memory-without-restart.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v4 4/8] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index ec40c0b7c42..9aa426992a2 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index a9f2a3a3062..e715a6f01c2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,13 +1161,13 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_max_combine_limit = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit_guc = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 6ae9f38f0c8..b1fba850f02 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3593,7 +3593,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--vninua6xybvzgrci
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v4-0005-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v5 02/10] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 47ffc0a2307..d1be780683b 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 608f10d9412..e40dae2ddf2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,12 +1161,12 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(newval, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(io_max_combine_limit, newval);
}
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 2f8c3d5f918..0d1b6466d1e 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3591,7 +3591,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.49.0
--bwrlgp6w2ubxykjq
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v5-0003-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v4 4/8] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index ec40c0b7c42..9aa426992a2 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index a9f2a3a3062..e715a6f01c2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,13 +1161,13 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_max_combine_limit = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit_guc = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 6ae9f38f0c8..b1fba850f02 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3593,7 +3593,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--vninua6xybvzgrci
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v4-0005-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v4 4/8] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index ec40c0b7c42..9aa426992a2 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index a9f2a3a3062..e715a6f01c2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,13 +1161,13 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_max_combine_limit = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit_guc = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 6ae9f38f0c8..b1fba850f02 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3593,7 +3593,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--vninua6xybvzgrci
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v4-0005-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v4 4/8] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index ec40c0b7c42..9aa426992a2 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index a9f2a3a3062..e715a6f01c2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,13 +1161,13 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_max_combine_limit = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit_guc = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 6ae9f38f0c8..b1fba850f02 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3593,7 +3593,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--vninua6xybvzgrci
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v4-0005-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v4 4/8] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index ec40c0b7c42..9aa426992a2 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index a9f2a3a3062..e715a6f01c2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,13 +1161,13 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_max_combine_limit = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit_guc = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 6ae9f38f0c8..b1fba850f02 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3593,7 +3593,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--vninua6xybvzgrci
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v4-0005-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v4 4/8] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index ec40c0b7c42..9aa426992a2 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index a9f2a3a3062..e715a6f01c2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,13 +1161,13 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_max_combine_limit = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit_guc = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 6ae9f38f0c8..b1fba850f02 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3593,7 +3593,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--vninua6xybvzgrci
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v4-0005-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v4 4/8] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index ec40c0b7c42..9aa426992a2 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index a9f2a3a3062..e715a6f01c2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,13 +1161,13 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_max_combine_limit = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit_guc = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 6ae9f38f0c8..b1fba850f02 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3593,7 +3593,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--vninua6xybvzgrci
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v4-0005-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v4 4/8] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index ec40c0b7c42..9aa426992a2 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index a9f2a3a3062..e715a6f01c2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,13 +1161,13 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_max_combine_limit = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit_guc = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 6ae9f38f0c8..b1fba850f02 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3593,7 +3593,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--vninua6xybvzgrci
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v4-0005-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v5 02/10] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 47ffc0a2307..d1be780683b 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 608f10d9412..e40dae2ddf2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,12 +1161,12 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(newval, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(io_max_combine_limit, newval);
}
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 2f8c3d5f918..0d1b6466d1e 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3591,7 +3591,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.49.0
--bwrlgp6w2ubxykjq
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v5-0003-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v5 02/10] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 47ffc0a2307..d1be780683b 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 608f10d9412..e40dae2ddf2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,12 +1161,12 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(newval, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(io_max_combine_limit, newval);
}
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 2f8c3d5f918..0d1b6466d1e 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3591,7 +3591,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.49.0
--bwrlgp6w2ubxykjq
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v5-0003-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v5 02/10] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 47ffc0a2307..d1be780683b 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 608f10d9412..e40dae2ddf2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,12 +1161,12 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(newval, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(io_max_combine_limit, newval);
}
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 2f8c3d5f918..0d1b6466d1e 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3591,7 +3591,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.49.0
--bwrlgp6w2ubxykjq
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v5-0003-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v4 4/8] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index ec40c0b7c42..9aa426992a2 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index a9f2a3a3062..e715a6f01c2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,13 +1161,13 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_max_combine_limit = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit_guc = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 6ae9f38f0c8..b1fba850f02 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3593,7 +3593,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--vninua6xybvzgrci
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v4-0005-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v4 4/8] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index ec40c0b7c42..9aa426992a2 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index a9f2a3a3062..e715a6f01c2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,13 +1161,13 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_max_combine_limit = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit_guc = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 6ae9f38f0c8..b1fba850f02 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3593,7 +3593,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--vninua6xybvzgrci
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v4-0005-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v4 4/8] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index ec40c0b7c42..9aa426992a2 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index a9f2a3a3062..e715a6f01c2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,13 +1161,13 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_max_combine_limit = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit_guc = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 6ae9f38f0c8..b1fba850f02 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3593,7 +3593,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--vninua6xybvzgrci
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v4-0005-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v5 02/10] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 47ffc0a2307..d1be780683b 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 608f10d9412..e40dae2ddf2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,12 +1161,12 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(newval, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(io_max_combine_limit, newval);
}
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 2f8c3d5f918..0d1b6466d1e 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3591,7 +3591,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.49.0
--bwrlgp6w2ubxykjq
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v5-0003-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v4 4/8] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index ec40c0b7c42..9aa426992a2 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index a9f2a3a3062..e715a6f01c2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,13 +1161,13 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_max_combine_limit = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit_guc = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 6ae9f38f0c8..b1fba850f02 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3593,7 +3593,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--vninua6xybvzgrci
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v4-0005-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v4 4/8] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index ec40c0b7c42..9aa426992a2 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index a9f2a3a3062..e715a6f01c2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,13 +1161,13 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_max_combine_limit = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit_guc = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 6ae9f38f0c8..b1fba850f02 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3593,7 +3593,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--vninua6xybvzgrci
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v4-0005-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v5 02/10] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 47ffc0a2307..d1be780683b 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 608f10d9412..e40dae2ddf2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,12 +1161,12 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(newval, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(io_max_combine_limit, newval);
}
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 2f8c3d5f918..0d1b6466d1e 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3591,7 +3591,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.49.0
--bwrlgp6w2ubxykjq
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v5-0003-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v4 4/8] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index ec40c0b7c42..9aa426992a2 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index a9f2a3a3062..e715a6f01c2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,13 +1161,13 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_max_combine_limit = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit_guc = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 6ae9f38f0c8..b1fba850f02 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3593,7 +3593,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--vninua6xybvzgrci
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v4-0005-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v5 02/10] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 47ffc0a2307..d1be780683b 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 608f10d9412..e40dae2ddf2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,12 +1161,12 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(newval, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(io_max_combine_limit, newval);
}
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 2f8c3d5f918..0d1b6466d1e 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3591,7 +3591,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.49.0
--bwrlgp6w2ubxykjq
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v5-0003-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v5 02/10] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 47ffc0a2307..d1be780683b 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 608f10d9412..e40dae2ddf2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,12 +1161,12 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(newval, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(io_max_combine_limit, newval);
}
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 2f8c3d5f918..0d1b6466d1e 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3591,7 +3591,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.49.0
--bwrlgp6w2ubxykjq
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v5-0003-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v5 02/10] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 47ffc0a2307..d1be780683b 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 608f10d9412..e40dae2ddf2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,12 +1161,12 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(newval, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(io_max_combine_limit, newval);
}
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 2f8c3d5f918..0d1b6466d1e 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3591,7 +3591,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.49.0
--bwrlgp6w2ubxykjq
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v5-0003-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v4 4/8] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index ec40c0b7c42..9aa426992a2 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index a9f2a3a3062..e715a6f01c2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,13 +1161,13 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_max_combine_limit = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit_guc = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 6ae9f38f0c8..b1fba850f02 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3593,7 +3593,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--vninua6xybvzgrci
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v4-0005-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v5 02/10] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 47ffc0a2307..d1be780683b 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 608f10d9412..e40dae2ddf2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,12 +1161,12 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(newval, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(io_max_combine_limit, newval);
}
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 2f8c3d5f918..0d1b6466d1e 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3591,7 +3591,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.49.0
--bwrlgp6w2ubxykjq
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v5-0003-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v4 4/8] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index ec40c0b7c42..9aa426992a2 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index a9f2a3a3062..e715a6f01c2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,13 +1161,13 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_max_combine_limit = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit_guc = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 6ae9f38f0c8..b1fba850f02 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3593,7 +3593,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--vninua6xybvzgrci
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v4-0005-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v5 02/10] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 47ffc0a2307..d1be780683b 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 608f10d9412..e40dae2ddf2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,12 +1161,12 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(newval, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(io_max_combine_limit, newval);
}
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 2f8c3d5f918..0d1b6466d1e 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3591,7 +3591,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.49.0
--bwrlgp6w2ubxykjq
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v5-0003-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v4 4/8] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index ec40c0b7c42..9aa426992a2 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index a9f2a3a3062..e715a6f01c2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,13 +1161,13 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_max_combine_limit = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit_guc = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 6ae9f38f0c8..b1fba850f02 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3593,7 +3593,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--vninua6xybvzgrci
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v4-0005-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v5 02/10] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 47ffc0a2307..d1be780683b 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 608f10d9412..e40dae2ddf2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,12 +1161,12 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(newval, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(io_max_combine_limit, newval);
}
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 2f8c3d5f918..0d1b6466d1e 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3591,7 +3591,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.49.0
--bwrlgp6w2ubxykjq
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v5-0003-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v4 4/8] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index ec40c0b7c42..9aa426992a2 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index a9f2a3a3062..e715a6f01c2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,13 +1161,13 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_max_combine_limit = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit_guc = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 6ae9f38f0c8..b1fba850f02 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3593,7 +3593,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--vninua6xybvzgrci
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v4-0005-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v5 02/10] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 47ffc0a2307..d1be780683b 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 608f10d9412..e40dae2ddf2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,12 +1161,12 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(newval, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(io_max_combine_limit, newval);
}
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 2f8c3d5f918..0d1b6466d1e 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3591,7 +3591,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.49.0
--bwrlgp6w2ubxykjq
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v5-0003-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v4 4/8] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index ec40c0b7c42..9aa426992a2 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index a9f2a3a3062..e715a6f01c2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,13 +1161,13 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_max_combine_limit = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit_guc = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 6ae9f38f0c8..b1fba850f02 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3593,7 +3593,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--vninua6xybvzgrci
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v4-0005-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v4 4/8] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index ec40c0b7c42..9aa426992a2 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index a9f2a3a3062..e715a6f01c2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,13 +1161,13 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_max_combine_limit = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit_guc = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 6ae9f38f0c8..b1fba850f02 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3593,7 +3593,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--vninua6xybvzgrci
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v4-0005-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v5 02/10] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 47ffc0a2307..d1be780683b 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 608f10d9412..e40dae2ddf2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,12 +1161,12 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(newval, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(io_max_combine_limit, newval);
}
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 2f8c3d5f918..0d1b6466d1e 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3591,7 +3591,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.49.0
--bwrlgp6w2ubxykjq
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v5-0003-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v4 4/8] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index ec40c0b7c42..9aa426992a2 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index a9f2a3a3062..e715a6f01c2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,13 +1161,13 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_max_combine_limit = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit_guc = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 6ae9f38f0c8..b1fba850f02 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3593,7 +3593,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--vninua6xybvzgrci
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v4-0005-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v5 02/10] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 47ffc0a2307..d1be780683b 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 608f10d9412..e40dae2ddf2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,12 +1161,12 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(newval, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(io_max_combine_limit, newval);
}
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 2f8c3d5f918..0d1b6466d1e 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3591,7 +3591,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.49.0
--bwrlgp6w2ubxykjq
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v5-0003-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v4 4/8] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index ec40c0b7c42..9aa426992a2 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index a9f2a3a3062..e715a6f01c2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,13 +1161,13 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_max_combine_limit = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit_guc = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 6ae9f38f0c8..b1fba850f02 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3593,7 +3593,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--vninua6xybvzgrci
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v4-0005-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v5 02/10] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 47ffc0a2307..d1be780683b 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 608f10d9412..e40dae2ddf2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,12 +1161,12 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(newval, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(io_max_combine_limit, newval);
}
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 2f8c3d5f918..0d1b6466d1e 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3591,7 +3591,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.49.0
--bwrlgp6w2ubxykjq
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v5-0003-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v4 4/8] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index ec40c0b7c42..9aa426992a2 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index a9f2a3a3062..e715a6f01c2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,13 +1161,13 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_max_combine_limit = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit_guc = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 6ae9f38f0c8..b1fba850f02 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3593,7 +3593,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--vninua6xybvzgrci
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v4-0005-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v4 4/8] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index ec40c0b7c42..9aa426992a2 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index a9f2a3a3062..e715a6f01c2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,13 +1161,13 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_max_combine_limit = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit_guc = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 6ae9f38f0c8..b1fba850f02 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3593,7 +3593,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--vninua6xybvzgrci
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v4-0005-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v5 02/10] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 47ffc0a2307..d1be780683b 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 608f10d9412..e40dae2ddf2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,12 +1161,12 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(newval, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(io_max_combine_limit, newval);
}
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 2f8c3d5f918..0d1b6466d1e 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3591,7 +3591,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.49.0
--bwrlgp6w2ubxykjq
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v5-0003-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v4 4/8] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index ec40c0b7c42..9aa426992a2 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index a9f2a3a3062..e715a6f01c2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,13 +1161,13 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_max_combine_limit = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit_guc = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 6ae9f38f0c8..b1fba850f02 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3593,7 +3593,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--vninua6xybvzgrci
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v4-0005-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v5 02/10] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 47ffc0a2307..d1be780683b 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 608f10d9412..e40dae2ddf2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,12 +1161,12 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(newval, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(io_max_combine_limit, newval);
}
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 2f8c3d5f918..0d1b6466d1e 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3591,7 +3591,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.49.0
--bwrlgp6w2ubxykjq
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v5-0003-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v4 4/8] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index ec40c0b7c42..9aa426992a2 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index a9f2a3a3062..e715a6f01c2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,13 +1161,13 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_max_combine_limit = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit_guc = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 6ae9f38f0c8..b1fba850f02 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3593,7 +3593,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--vninua6xybvzgrci
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v4-0005-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v5 02/10] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 47ffc0a2307..d1be780683b 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 608f10d9412..e40dae2ddf2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,12 +1161,12 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(newval, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(io_max_combine_limit, newval);
}
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 2f8c3d5f918..0d1b6466d1e 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3591,7 +3591,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.49.0
--bwrlgp6w2ubxykjq
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v5-0003-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v5 02/10] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 47ffc0a2307..d1be780683b 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 608f10d9412..e40dae2ddf2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,12 +1161,12 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(newval, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(io_max_combine_limit, newval);
}
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 2f8c3d5f918..0d1b6466d1e 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3591,7 +3591,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.49.0
--bwrlgp6w2ubxykjq
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v5-0003-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v5 02/10] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 47ffc0a2307..d1be780683b 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 608f10d9412..e40dae2ddf2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,12 +1161,12 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(newval, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(io_max_combine_limit, newval);
}
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 2f8c3d5f918..0d1b6466d1e 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3591,7 +3591,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.49.0
--bwrlgp6w2ubxykjq
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v5-0003-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v4 4/8] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index ec40c0b7c42..9aa426992a2 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index a9f2a3a3062..e715a6f01c2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,13 +1161,13 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_max_combine_limit = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit_guc = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 6ae9f38f0c8..b1fba850f02 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3593,7 +3593,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--vninua6xybvzgrci
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v4-0005-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v4 4/8] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index ec40c0b7c42..9aa426992a2 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index a9f2a3a3062..e715a6f01c2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,13 +1161,13 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_max_combine_limit = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit_guc = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 6ae9f38f0c8..b1fba850f02 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3593,7 +3593,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--vninua6xybvzgrci
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v4-0005-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v4 4/8] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index ec40c0b7c42..9aa426992a2 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index a9f2a3a3062..e715a6f01c2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,13 +1161,13 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_max_combine_limit = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit_guc = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 6ae9f38f0c8..b1fba850f02 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3593,7 +3593,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--vninua6xybvzgrci
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v4-0005-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v5 02/10] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 47ffc0a2307..d1be780683b 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 608f10d9412..e40dae2ddf2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,12 +1161,12 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(newval, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(io_max_combine_limit, newval);
}
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 2f8c3d5f918..0d1b6466d1e 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3591,7 +3591,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.49.0
--bwrlgp6w2ubxykjq
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v5-0003-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v4 4/8] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index ec40c0b7c42..9aa426992a2 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index a9f2a3a3062..e715a6f01c2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,13 +1161,13 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_max_combine_limit = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit_guc = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 6ae9f38f0c8..b1fba850f02 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3593,7 +3593,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--vninua6xybvzgrci
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v4-0005-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v4 4/8] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index ec40c0b7c42..9aa426992a2 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index a9f2a3a3062..e715a6f01c2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,13 +1161,13 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_max_combine_limit = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit_guc = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 6ae9f38f0c8..b1fba850f02 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3593,7 +3593,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--vninua6xybvzgrci
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v4-0005-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v5 02/10] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 47ffc0a2307..d1be780683b 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 608f10d9412..e40dae2ddf2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,12 +1161,12 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(newval, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(io_max_combine_limit, newval);
}
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 2f8c3d5f918..0d1b6466d1e 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3591,7 +3591,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.49.0
--bwrlgp6w2ubxykjq
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v5-0003-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v4 4/8] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index ec40c0b7c42..9aa426992a2 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index a9f2a3a3062..e715a6f01c2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,13 +1161,13 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_max_combine_limit = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit_guc = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 6ae9f38f0c8..b1fba850f02 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3593,7 +3593,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--vninua6xybvzgrci
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v4-0005-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v4 4/8] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index ec40c0b7c42..9aa426992a2 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index a9f2a3a3062..e715a6f01c2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,13 +1161,13 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_max_combine_limit = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit_guc = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 6ae9f38f0c8..b1fba850f02 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3593,7 +3593,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--vninua6xybvzgrci
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v4-0005-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v4 4/8] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index ec40c0b7c42..9aa426992a2 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index a9f2a3a3062..e715a6f01c2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,13 +1161,13 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_max_combine_limit = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit_guc = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 6ae9f38f0c8..b1fba850f02 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3593,7 +3593,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--vninua6xybvzgrci
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v4-0005-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v5 02/10] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 47ffc0a2307..d1be780683b 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 608f10d9412..e40dae2ddf2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,12 +1161,12 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(newval, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(io_max_combine_limit, newval);
}
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 2f8c3d5f918..0d1b6466d1e 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3591,7 +3591,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.49.0
--bwrlgp6w2ubxykjq
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v5-0003-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v4 4/8] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index ec40c0b7c42..9aa426992a2 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index a9f2a3a3062..e715a6f01c2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,13 +1161,13 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_max_combine_limit = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit_guc = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 6ae9f38f0c8..b1fba850f02 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3593,7 +3593,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--vninua6xybvzgrci
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v4-0005-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v5 02/10] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 47ffc0a2307..d1be780683b 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 608f10d9412..e40dae2ddf2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,12 +1161,12 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(newval, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(io_max_combine_limit, newval);
}
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 2f8c3d5f918..0d1b6466d1e 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3591,7 +3591,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.49.0
--bwrlgp6w2ubxykjq
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v5-0003-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v5 02/10] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 47ffc0a2307..d1be780683b 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 608f10d9412..e40dae2ddf2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,12 +1161,12 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(newval, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(io_max_combine_limit, newval);
}
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 2f8c3d5f918..0d1b6466d1e 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3591,7 +3591,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.49.0
--bwrlgp6w2ubxykjq
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v5-0003-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v5 02/10] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 47ffc0a2307..d1be780683b 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 608f10d9412..e40dae2ddf2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,12 +1161,12 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(newval, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(io_max_combine_limit, newval);
}
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 2f8c3d5f918..0d1b6466d1e 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3591,7 +3591,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.49.0
--bwrlgp6w2ubxykjq
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v5-0003-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v4 4/8] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index ec40c0b7c42..9aa426992a2 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index a9f2a3a3062..e715a6f01c2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,13 +1161,13 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_max_combine_limit = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit_guc = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 6ae9f38f0c8..b1fba850f02 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3593,7 +3593,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--vninua6xybvzgrci
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v4-0005-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v5 02/10] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 47ffc0a2307..d1be780683b 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 608f10d9412..e40dae2ddf2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,12 +1161,12 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(newval, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(io_max_combine_limit, newval);
}
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 2f8c3d5f918..0d1b6466d1e 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3591,7 +3591,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.49.0
--bwrlgp6w2ubxykjq
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v5-0003-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v4 4/8] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index ec40c0b7c42..9aa426992a2 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index a9f2a3a3062..e715a6f01c2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,13 +1161,13 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_max_combine_limit = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit_guc = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 6ae9f38f0c8..b1fba850f02 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3593,7 +3593,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--vninua6xybvzgrci
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v4-0005-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v5 02/10] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 47ffc0a2307..d1be780683b 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 608f10d9412..e40dae2ddf2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,12 +1161,12 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(newval, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(io_max_combine_limit, newval);
}
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 2f8c3d5f918..0d1b6466d1e 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3591,7 +3591,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.49.0
--bwrlgp6w2ubxykjq
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v5-0003-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v4 4/8] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index ec40c0b7c42..9aa426992a2 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index a9f2a3a3062..e715a6f01c2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,13 +1161,13 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_max_combine_limit = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit_guc = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 6ae9f38f0c8..b1fba850f02 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3593,7 +3593,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--vninua6xybvzgrci
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v4-0005-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v5 02/10] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 47ffc0a2307..d1be780683b 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 608f10d9412..e40dae2ddf2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,12 +1161,12 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(newval, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(io_max_combine_limit, newval);
}
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 2f8c3d5f918..0d1b6466d1e 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3591,7 +3591,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.49.0
--bwrlgp6w2ubxykjq
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v5-0003-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v5 02/10] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 47ffc0a2307..d1be780683b 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 608f10d9412..e40dae2ddf2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,12 +1161,12 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(newval, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(io_max_combine_limit, newval);
}
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 2f8c3d5f918..0d1b6466d1e 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3591,7 +3591,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.49.0
--bwrlgp6w2ubxykjq
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v5-0003-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v5 02/10] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 47ffc0a2307..d1be780683b 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 608f10d9412..e40dae2ddf2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,12 +1161,12 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(newval, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(io_max_combine_limit, newval);
}
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 2f8c3d5f918..0d1b6466d1e 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3591,7 +3591,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.49.0
--bwrlgp6w2ubxykjq
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v5-0003-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v5 02/10] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 47ffc0a2307..d1be780683b 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 608f10d9412..e40dae2ddf2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,12 +1161,12 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(newval, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(io_max_combine_limit, newval);
}
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 2f8c3d5f918..0d1b6466d1e 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3591,7 +3591,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.49.0
--bwrlgp6w2ubxykjq
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v5-0003-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v5 02/10] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 47ffc0a2307..d1be780683b 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 608f10d9412..e40dae2ddf2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,12 +1161,12 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(newval, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(io_max_combine_limit, newval);
}
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 2f8c3d5f918..0d1b6466d1e 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3591,7 +3591,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.49.0
--bwrlgp6w2ubxykjq
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v5-0003-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v5 02/10] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 47ffc0a2307..d1be780683b 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 608f10d9412..e40dae2ddf2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,12 +1161,12 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(newval, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(io_max_combine_limit, newval);
}
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 2f8c3d5f918..0d1b6466d1e 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3591,7 +3591,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.49.0
--bwrlgp6w2ubxykjq
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v5-0003-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v4 4/8] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index ec40c0b7c42..9aa426992a2 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index a9f2a3a3062..e715a6f01c2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,13 +1161,13 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_max_combine_limit = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit_guc = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 6ae9f38f0c8..b1fba850f02 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3593,7 +3593,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--vninua6xybvzgrci
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v4-0005-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v4 4/8] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index ec40c0b7c42..9aa426992a2 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index a9f2a3a3062..e715a6f01c2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,13 +1161,13 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_max_combine_limit = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit_guc = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 6ae9f38f0c8..b1fba850f02 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3593,7 +3593,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--vninua6xybvzgrci
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v4-0005-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v5 02/10] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 47ffc0a2307..d1be780683b 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 608f10d9412..e40dae2ddf2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,12 +1161,12 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(newval, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(io_max_combine_limit, newval);
}
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 2f8c3d5f918..0d1b6466d1e 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3591,7 +3591,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.49.0
--bwrlgp6w2ubxykjq
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v5-0003-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v4 4/8] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index ec40c0b7c42..9aa426992a2 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index a9f2a3a3062..e715a6f01c2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,13 +1161,13 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_max_combine_limit = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit_guc = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 6ae9f38f0c8..b1fba850f02 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3593,7 +3593,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--vninua6xybvzgrci
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v4-0005-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v5 02/10] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 47ffc0a2307..d1be780683b 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 608f10d9412..e40dae2ddf2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,12 +1161,12 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(newval, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(io_max_combine_limit, newval);
}
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 2f8c3d5f918..0d1b6466d1e 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3591,7 +3591,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.49.0
--bwrlgp6w2ubxykjq
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v5-0003-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v4 4/8] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index ec40c0b7c42..9aa426992a2 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index a9f2a3a3062..e715a6f01c2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,13 +1161,13 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_max_combine_limit = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit_guc = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 6ae9f38f0c8..b1fba850f02 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3593,7 +3593,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--vninua6xybvzgrci
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v4-0005-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v5 02/10] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 47ffc0a2307..d1be780683b 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 608f10d9412..e40dae2ddf2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,12 +1161,12 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(newval, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(io_max_combine_limit, newval);
}
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 2f8c3d5f918..0d1b6466d1e 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3591,7 +3591,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.49.0
--bwrlgp6w2ubxykjq
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v5-0003-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v5 02/10] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 47ffc0a2307..d1be780683b 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 608f10d9412..e40dae2ddf2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,12 +1161,12 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(newval, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(io_max_combine_limit, newval);
}
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 2f8c3d5f918..0d1b6466d1e 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3591,7 +3591,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.49.0
--bwrlgp6w2ubxykjq
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v5-0003-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v5 02/10] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 47ffc0a2307..d1be780683b 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 608f10d9412..e40dae2ddf2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,12 +1161,12 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(newval, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(io_max_combine_limit, newval);
}
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 2f8c3d5f918..0d1b6466d1e 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3591,7 +3591,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.49.0
--bwrlgp6w2ubxykjq
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v5-0003-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v5 02/10] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 47ffc0a2307..d1be780683b 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 608f10d9412..e40dae2ddf2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,12 +1161,12 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(newval, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(io_max_combine_limit, newval);
}
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 2f8c3d5f918..0d1b6466d1e 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3591,7 +3591,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.49.0
--bwrlgp6w2ubxykjq
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v5-0003-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v5 02/10] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 47ffc0a2307..d1be780683b 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 608f10d9412..e40dae2ddf2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,12 +1161,12 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(newval, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(io_max_combine_limit, newval);
}
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 2f8c3d5f918..0d1b6466d1e 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3591,7 +3591,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.49.0
--bwrlgp6w2ubxykjq
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v5-0003-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v4 4/8] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index ec40c0b7c42..9aa426992a2 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index a9f2a3a3062..e715a6f01c2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,13 +1161,13 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_max_combine_limit = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit_guc = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 6ae9f38f0c8..b1fba850f02 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3593,7 +3593,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--vninua6xybvzgrci
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v4-0005-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v4 4/8] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index ec40c0b7c42..9aa426992a2 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index a9f2a3a3062..e715a6f01c2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,13 +1161,13 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_max_combine_limit = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit_guc = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 6ae9f38f0c8..b1fba850f02 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3593,7 +3593,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--vninua6xybvzgrci
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v4-0005-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v4 4/8] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index ec40c0b7c42..9aa426992a2 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index a9f2a3a3062..e715a6f01c2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,13 +1161,13 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_max_combine_limit = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit_guc = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 6ae9f38f0c8..b1fba850f02 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3593,7 +3593,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--vninua6xybvzgrci
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v4-0005-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v5 02/10] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 47ffc0a2307..d1be780683b 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 608f10d9412..e40dae2ddf2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,12 +1161,12 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(newval, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(io_max_combine_limit, newval);
}
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 2f8c3d5f918..0d1b6466d1e 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3591,7 +3591,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.49.0
--bwrlgp6w2ubxykjq
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v5-0003-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v5 02/10] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 47ffc0a2307..d1be780683b 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 608f10d9412..e40dae2ddf2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,12 +1161,12 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(newval, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(io_max_combine_limit, newval);
}
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 2f8c3d5f918..0d1b6466d1e 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3591,7 +3591,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.49.0
--bwrlgp6w2ubxykjq
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v5-0003-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v4 4/8] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index ec40c0b7c42..9aa426992a2 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index a9f2a3a3062..e715a6f01c2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,13 +1161,13 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_max_combine_limit = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit_guc = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 6ae9f38f0c8..b1fba850f02 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3593,7 +3593,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--vninua6xybvzgrci
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v4-0005-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v5 02/10] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 47ffc0a2307..d1be780683b 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 608f10d9412..e40dae2ddf2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,12 +1161,12 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(newval, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(io_max_combine_limit, newval);
}
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 2f8c3d5f918..0d1b6466d1e 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3591,7 +3591,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.49.0
--bwrlgp6w2ubxykjq
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v5-0003-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v5 02/10] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 47ffc0a2307..d1be780683b 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 608f10d9412..e40dae2ddf2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,12 +1161,12 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(newval, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(io_max_combine_limit, newval);
}
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 2f8c3d5f918..0d1b6466d1e 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3591,7 +3591,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.49.0
--bwrlgp6w2ubxykjq
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v5-0003-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v4 4/8] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index ec40c0b7c42..9aa426992a2 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index a9f2a3a3062..e715a6f01c2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,13 +1161,13 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_max_combine_limit = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit_guc = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 6ae9f38f0c8..b1fba850f02 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3593,7 +3593,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--vninua6xybvzgrci
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v4-0005-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v5 02/10] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 47ffc0a2307..d1be780683b 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 608f10d9412..e40dae2ddf2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,12 +1161,12 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(newval, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(io_max_combine_limit, newval);
}
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 2f8c3d5f918..0d1b6466d1e 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3591,7 +3591,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.49.0
--bwrlgp6w2ubxykjq
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v5-0003-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v5 02/10] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 47ffc0a2307..d1be780683b 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 608f10d9412..e40dae2ddf2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,12 +1161,12 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(newval, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(io_max_combine_limit, newval);
}
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 2f8c3d5f918..0d1b6466d1e 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3591,7 +3591,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.49.0
--bwrlgp6w2ubxykjq
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v5-0003-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v4 4/8] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index ec40c0b7c42..9aa426992a2 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index a9f2a3a3062..e715a6f01c2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,13 +1161,13 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_max_combine_limit = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit_guc = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 6ae9f38f0c8..b1fba850f02 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3593,7 +3593,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--vninua6xybvzgrci
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v4-0005-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v4 4/8] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index ec40c0b7c42..9aa426992a2 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index a9f2a3a3062..e715a6f01c2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,13 +1161,13 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_max_combine_limit = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit_guc = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 6ae9f38f0c8..b1fba850f02 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3593,7 +3593,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--vninua6xybvzgrci
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v4-0005-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v5 02/10] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 47ffc0a2307..d1be780683b 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 608f10d9412..e40dae2ddf2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,12 +1161,12 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(newval, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(io_max_combine_limit, newval);
}
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 2f8c3d5f918..0d1b6466d1e 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3591,7 +3591,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.49.0
--bwrlgp6w2ubxykjq
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v5-0003-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v4 4/8] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index ec40c0b7c42..9aa426992a2 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index a9f2a3a3062..e715a6f01c2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,13 +1161,13 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_max_combine_limit = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit_guc = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 6ae9f38f0c8..b1fba850f02 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3593,7 +3593,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--vninua6xybvzgrci
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v4-0005-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v5 02/10] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 47ffc0a2307..d1be780683b 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 608f10d9412..e40dae2ddf2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,12 +1161,12 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(newval, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(io_max_combine_limit, newval);
}
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 2f8c3d5f918..0d1b6466d1e 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3591,7 +3591,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.49.0
--bwrlgp6w2ubxykjq
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v5-0003-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v4 4/8] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index ec40c0b7c42..9aa426992a2 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index a9f2a3a3062..e715a6f01c2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,13 +1161,13 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_max_combine_limit = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit_guc = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 6ae9f38f0c8..b1fba850f02 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3593,7 +3593,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--vninua6xybvzgrci
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v4-0005-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v5 02/10] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 47ffc0a2307..d1be780683b 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 608f10d9412..e40dae2ddf2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,12 +1161,12 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(newval, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(io_max_combine_limit, newval);
}
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 2f8c3d5f918..0d1b6466d1e 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3591,7 +3591,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.49.0
--bwrlgp6w2ubxykjq
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v5-0003-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v4 4/8] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index ec40c0b7c42..9aa426992a2 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index a9f2a3a3062..e715a6f01c2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,13 +1161,13 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_max_combine_limit = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit_guc = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 6ae9f38f0c8..b1fba850f02 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3593,7 +3593,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--vninua6xybvzgrci
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v4-0005-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v4 4/8] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index ec40c0b7c42..9aa426992a2 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index a9f2a3a3062..e715a6f01c2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,13 +1161,13 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_max_combine_limit = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit_guc = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 6ae9f38f0c8..b1fba850f02 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3593,7 +3593,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--vninua6xybvzgrci
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v4-0005-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v4 4/8] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index ec40c0b7c42..9aa426992a2 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index a9f2a3a3062..e715a6f01c2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,13 +1161,13 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_max_combine_limit = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit_guc = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 6ae9f38f0c8..b1fba850f02 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3593,7 +3593,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--vninua6xybvzgrci
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v4-0005-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v4 4/8] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index ec40c0b7c42..9aa426992a2 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index a9f2a3a3062..e715a6f01c2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,13 +1161,13 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_max_combine_limit = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit_guc = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 6ae9f38f0c8..b1fba850f02 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3593,7 +3593,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--vninua6xybvzgrci
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v4-0005-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v4 4/8] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index ec40c0b7c42..9aa426992a2 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index a9f2a3a3062..e715a6f01c2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,13 +1161,13 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_max_combine_limit = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit_guc = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 6ae9f38f0c8..b1fba850f02 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3593,7 +3593,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--vninua6xybvzgrci
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v4-0005-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v5 02/10] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 47ffc0a2307..d1be780683b 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 608f10d9412..e40dae2ddf2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,12 +1161,12 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(newval, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(io_max_combine_limit, newval);
}
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 2f8c3d5f918..0d1b6466d1e 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3591,7 +3591,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.49.0
--bwrlgp6w2ubxykjq
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v5-0003-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v4 4/8] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index ec40c0b7c42..9aa426992a2 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index a9f2a3a3062..e715a6f01c2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,13 +1161,13 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_max_combine_limit = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit_guc = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 6ae9f38f0c8..b1fba850f02 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3593,7 +3593,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--vninua6xybvzgrci
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v4-0005-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v5 02/10] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 47ffc0a2307..d1be780683b 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 608f10d9412..e40dae2ddf2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,12 +1161,12 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(newval, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(io_max_combine_limit, newval);
}
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 2f8c3d5f918..0d1b6466d1e 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3591,7 +3591,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.49.0
--bwrlgp6w2ubxykjq
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v5-0003-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v5 02/10] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 47ffc0a2307..d1be780683b 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 608f10d9412..e40dae2ddf2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,12 +1161,12 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(newval, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(io_max_combine_limit, newval);
}
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 2f8c3d5f918..0d1b6466d1e 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3591,7 +3591,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.49.0
--bwrlgp6w2ubxykjq
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v5-0003-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v4 4/8] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index ec40c0b7c42..9aa426992a2 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index a9f2a3a3062..e715a6f01c2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,13 +1161,13 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_max_combine_limit = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit_guc = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 6ae9f38f0c8..b1fba850f02 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3593,7 +3593,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--vninua6xybvzgrci
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v4-0005-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v4 4/8] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index ec40c0b7c42..9aa426992a2 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index a9f2a3a3062..e715a6f01c2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,13 +1161,13 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_max_combine_limit = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit_guc = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 6ae9f38f0c8..b1fba850f02 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3593,7 +3593,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--vninua6xybvzgrci
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v4-0005-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v4 4/8] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index ec40c0b7c42..9aa426992a2 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index a9f2a3a3062..e715a6f01c2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,13 +1161,13 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_max_combine_limit = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit_guc = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 6ae9f38f0c8..b1fba850f02 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3593,7 +3593,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--vninua6xybvzgrci
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v4-0005-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v4 4/8] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index ec40c0b7c42..9aa426992a2 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index a9f2a3a3062..e715a6f01c2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,13 +1161,13 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_max_combine_limit = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit_guc = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 6ae9f38f0c8..b1fba850f02 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3593,7 +3593,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--vninua6xybvzgrci
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v4-0005-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v5 02/10] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 47ffc0a2307..d1be780683b 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 608f10d9412..e40dae2ddf2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,12 +1161,12 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(newval, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(io_max_combine_limit, newval);
}
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 2f8c3d5f918..0d1b6466d1e 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3591,7 +3591,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.49.0
--bwrlgp6w2ubxykjq
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v5-0003-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v5 02/10] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 47ffc0a2307..d1be780683b 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 608f10d9412..e40dae2ddf2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,12 +1161,12 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(newval, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(io_max_combine_limit, newval);
}
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 2f8c3d5f918..0d1b6466d1e 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3591,7 +3591,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.49.0
--bwrlgp6w2ubxykjq
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v5-0003-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v4 4/8] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index ec40c0b7c42..9aa426992a2 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index a9f2a3a3062..e715a6f01c2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,13 +1161,13 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_max_combine_limit = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit_guc = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 6ae9f38f0c8..b1fba850f02 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3593,7 +3593,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--vninua6xybvzgrci
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v4-0005-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v5 02/10] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 47ffc0a2307..d1be780683b 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 608f10d9412..e40dae2ddf2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,12 +1161,12 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(newval, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(io_max_combine_limit, newval);
}
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 2f8c3d5f918..0d1b6466d1e 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3591,7 +3591,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.49.0
--bwrlgp6w2ubxykjq
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v5-0003-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v4 4/8] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index ec40c0b7c42..9aa426992a2 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index a9f2a3a3062..e715a6f01c2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,13 +1161,13 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_max_combine_limit = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit_guc = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 6ae9f38f0c8..b1fba850f02 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3593,7 +3593,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--vninua6xybvzgrci
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v4-0005-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v5 02/10] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 47ffc0a2307..d1be780683b 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 608f10d9412..e40dae2ddf2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,12 +1161,12 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(newval, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(io_max_combine_limit, newval);
}
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 2f8c3d5f918..0d1b6466d1e 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3591,7 +3591,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.49.0
--bwrlgp6w2ubxykjq
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v5-0003-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v5 02/10] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 47ffc0a2307..d1be780683b 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 608f10d9412..e40dae2ddf2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,12 +1161,12 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(newval, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(io_max_combine_limit, newval);
}
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 2f8c3d5f918..0d1b6466d1e 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3591,7 +3591,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.49.0
--bwrlgp6w2ubxykjq
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v5-0003-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v5 02/10] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 47ffc0a2307..d1be780683b 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 608f10d9412..e40dae2ddf2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,12 +1161,12 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(newval, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(io_max_combine_limit, newval);
}
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 2f8c3d5f918..0d1b6466d1e 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3591,7 +3591,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.49.0
--bwrlgp6w2ubxykjq
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v5-0003-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v4 4/8] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index ec40c0b7c42..9aa426992a2 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index a9f2a3a3062..e715a6f01c2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,13 +1161,13 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_max_combine_limit = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit_guc = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 6ae9f38f0c8..b1fba850f02 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3593,7 +3593,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--vninua6xybvzgrci
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v4-0005-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v5 02/10] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 47ffc0a2307..d1be780683b 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 608f10d9412..e40dae2ddf2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,12 +1161,12 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(newval, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(io_max_combine_limit, newval);
}
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 2f8c3d5f918..0d1b6466d1e 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3591,7 +3591,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.49.0
--bwrlgp6w2ubxykjq
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v5-0003-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v4 4/8] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index ec40c0b7c42..9aa426992a2 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index a9f2a3a3062..e715a6f01c2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,13 +1161,13 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_max_combine_limit = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit_guc = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 6ae9f38f0c8..b1fba850f02 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3593,7 +3593,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--vninua6xybvzgrci
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v4-0005-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v4 4/8] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index ec40c0b7c42..9aa426992a2 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index a9f2a3a3062..e715a6f01c2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,13 +1161,13 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_max_combine_limit = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit_guc = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 6ae9f38f0c8..b1fba850f02 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3593,7 +3593,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--vninua6xybvzgrci
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v4-0005-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v4 4/8] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index ec40c0b7c42..9aa426992a2 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index a9f2a3a3062..e715a6f01c2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,13 +1161,13 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_max_combine_limit = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit_guc = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 6ae9f38f0c8..b1fba850f02 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3593,7 +3593,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--vninua6xybvzgrci
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v4-0005-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v4 4/8] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index ec40c0b7c42..9aa426992a2 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index a9f2a3a3062..e715a6f01c2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,13 +1161,13 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_max_combine_limit = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit_guc = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 6ae9f38f0c8..b1fba850f02 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3593,7 +3593,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--vninua6xybvzgrci
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v4-0005-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v4 4/8] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index ec40c0b7c42..9aa426992a2 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index a9f2a3a3062..e715a6f01c2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,13 +1161,13 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_max_combine_limit = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit_guc = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 6ae9f38f0c8..b1fba850f02 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3593,7 +3593,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--vninua6xybvzgrci
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v4-0005-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v4 4/8] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index ec40c0b7c42..9aa426992a2 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index a9f2a3a3062..e715a6f01c2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,13 +1161,13 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_max_combine_limit = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit_guc = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 6ae9f38f0c8..b1fba850f02 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3593,7 +3593,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--vninua6xybvzgrci
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v4-0005-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v5 02/10] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 47ffc0a2307..d1be780683b 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 608f10d9412..e40dae2ddf2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,12 +1161,12 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(newval, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(io_max_combine_limit, newval);
}
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 2f8c3d5f918..0d1b6466d1e 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3591,7 +3591,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.49.0
--bwrlgp6w2ubxykjq
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v5-0003-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v4 4/8] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index ec40c0b7c42..9aa426992a2 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index a9f2a3a3062..e715a6f01c2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,13 +1161,13 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_max_combine_limit = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit_guc = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 6ae9f38f0c8..b1fba850f02 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3593,7 +3593,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--vninua6xybvzgrci
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v4-0005-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v5 02/10] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 47ffc0a2307..d1be780683b 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 608f10d9412..e40dae2ddf2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,12 +1161,12 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(newval, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(io_max_combine_limit, newval);
}
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 2f8c3d5f918..0d1b6466d1e 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3591,7 +3591,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.49.0
--bwrlgp6w2ubxykjq
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v5-0003-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v5 02/10] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 47ffc0a2307..d1be780683b 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 608f10d9412..e40dae2ddf2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,12 +1161,12 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(newval, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(io_max_combine_limit, newval);
}
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 2f8c3d5f918..0d1b6466d1e 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3591,7 +3591,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.49.0
--bwrlgp6w2ubxykjq
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v5-0003-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v4 4/8] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index ec40c0b7c42..9aa426992a2 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index a9f2a3a3062..e715a6f01c2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,13 +1161,13 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_max_combine_limit = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit_guc = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 6ae9f38f0c8..b1fba850f02 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3593,7 +3593,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--vninua6xybvzgrci
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v4-0005-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v5 02/10] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 47ffc0a2307..d1be780683b 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 608f10d9412..e40dae2ddf2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,12 +1161,12 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(newval, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(io_max_combine_limit, newval);
}
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 2f8c3d5f918..0d1b6466d1e 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3591,7 +3591,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.49.0
--bwrlgp6w2ubxykjq
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v5-0003-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v4 4/8] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index ec40c0b7c42..9aa426992a2 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index a9f2a3a3062..e715a6f01c2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,13 +1161,13 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_max_combine_limit = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit_guc = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 6ae9f38f0c8..b1fba850f02 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3593,7 +3593,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--vninua6xybvzgrci
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v4-0005-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v5 02/10] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 47ffc0a2307..d1be780683b 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 608f10d9412..e40dae2ddf2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,12 +1161,12 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(newval, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(io_max_combine_limit, newval);
}
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 2f8c3d5f918..0d1b6466d1e 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3591,7 +3591,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.49.0
--bwrlgp6w2ubxykjq
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v5-0003-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v5 02/10] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 47ffc0a2307..d1be780683b 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 608f10d9412..e40dae2ddf2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,12 +1161,12 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(newval, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(io_max_combine_limit, newval);
}
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 2f8c3d5f918..0d1b6466d1e 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3591,7 +3591,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.49.0
--bwrlgp6w2ubxykjq
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v5-0003-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v5 02/10] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 47ffc0a2307..d1be780683b 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 608f10d9412..e40dae2ddf2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,12 +1161,12 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(newval, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(io_max_combine_limit, newval);
}
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 2f8c3d5f918..0d1b6466d1e 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3591,7 +3591,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.49.0
--bwrlgp6w2ubxykjq
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v5-0003-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v5 02/10] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 47ffc0a2307..d1be780683b 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 608f10d9412..e40dae2ddf2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,12 +1161,12 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(newval, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(io_max_combine_limit, newval);
}
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 2f8c3d5f918..0d1b6466d1e 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3591,7 +3591,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.49.0
--bwrlgp6w2ubxykjq
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v5-0003-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v4 4/8] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index ec40c0b7c42..9aa426992a2 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index a9f2a3a3062..e715a6f01c2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,13 +1161,13 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_max_combine_limit = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit_guc = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 6ae9f38f0c8..b1fba850f02 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3593,7 +3593,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--vninua6xybvzgrci
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v4-0005-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v5 02/10] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 47ffc0a2307..d1be780683b 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 608f10d9412..e40dae2ddf2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,12 +1161,12 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(newval, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(io_max_combine_limit, newval);
}
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 2f8c3d5f918..0d1b6466d1e 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3591,7 +3591,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.49.0
--bwrlgp6w2ubxykjq
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v5-0003-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v5 02/10] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 47ffc0a2307..d1be780683b 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 608f10d9412..e40dae2ddf2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,12 +1161,12 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(newval, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(io_max_combine_limit, newval);
}
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 2f8c3d5f918..0d1b6466d1e 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3591,7 +3591,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.49.0
--bwrlgp6w2ubxykjq
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v5-0003-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v5 02/10] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 47ffc0a2307..d1be780683b 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 608f10d9412..e40dae2ddf2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,12 +1161,12 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(newval, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(io_max_combine_limit, newval);
}
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 2f8c3d5f918..0d1b6466d1e 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3591,7 +3591,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.49.0
--bwrlgp6w2ubxykjq
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v5-0003-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v5 02/10] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 47ffc0a2307..d1be780683b 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 608f10d9412..e40dae2ddf2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,12 +1161,12 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(newval, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(io_max_combine_limit, newval);
}
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 2f8c3d5f918..0d1b6466d1e 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3591,7 +3591,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.49.0
--bwrlgp6w2ubxykjq
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v5-0003-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v5 02/10] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 47ffc0a2307..d1be780683b 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 608f10d9412..e40dae2ddf2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,12 +1161,12 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(newval, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(io_max_combine_limit, newval);
}
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 2f8c3d5f918..0d1b6466d1e 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3591,7 +3591,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.49.0
--bwrlgp6w2ubxykjq
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v5-0003-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v4 4/8] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index ec40c0b7c42..9aa426992a2 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index a9f2a3a3062..e715a6f01c2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,13 +1161,13 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_max_combine_limit = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit_guc = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 6ae9f38f0c8..b1fba850f02 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3593,7 +3593,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--vninua6xybvzgrci
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v4-0005-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v5 02/10] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 47ffc0a2307..d1be780683b 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 608f10d9412..e40dae2ddf2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,12 +1161,12 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(newval, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(io_max_combine_limit, newval);
}
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 2f8c3d5f918..0d1b6466d1e 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3591,7 +3591,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.49.0
--bwrlgp6w2ubxykjq
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v5-0003-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v4 4/8] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index ec40c0b7c42..9aa426992a2 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index a9f2a3a3062..e715a6f01c2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,13 +1161,13 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_max_combine_limit = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit_guc = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 6ae9f38f0c8..b1fba850f02 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3593,7 +3593,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--vninua6xybvzgrci
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v4-0005-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v4 4/8] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index ec40c0b7c42..9aa426992a2 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index a9f2a3a3062..e715a6f01c2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,13 +1161,13 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_max_combine_limit = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit_guc = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 6ae9f38f0c8..b1fba850f02 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3593,7 +3593,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--vninua6xybvzgrci
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v4-0005-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v5 02/10] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 47ffc0a2307..d1be780683b 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 608f10d9412..e40dae2ddf2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,12 +1161,12 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(newval, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(io_max_combine_limit, newval);
}
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 2f8c3d5f918..0d1b6466d1e 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3591,7 +3591,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.49.0
--bwrlgp6w2ubxykjq
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v5-0003-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v4 4/8] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index ec40c0b7c42..9aa426992a2 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index a9f2a3a3062..e715a6f01c2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,13 +1161,13 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_max_combine_limit = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit_guc = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 6ae9f38f0c8..b1fba850f02 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3593,7 +3593,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--vninua6xybvzgrci
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v4-0005-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v4 4/8] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index ec40c0b7c42..9aa426992a2 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index a9f2a3a3062..e715a6f01c2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,13 +1161,13 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_max_combine_limit = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit_guc = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 6ae9f38f0c8..b1fba850f02 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3593,7 +3593,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--vninua6xybvzgrci
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v4-0005-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v5 02/10] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 47ffc0a2307..d1be780683b 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 608f10d9412..e40dae2ddf2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,12 +1161,12 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(newval, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(io_max_combine_limit, newval);
}
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 2f8c3d5f918..0d1b6466d1e 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3591,7 +3591,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.49.0
--bwrlgp6w2ubxykjq
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v5-0003-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v5 02/10] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 47ffc0a2307..d1be780683b 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 608f10d9412..e40dae2ddf2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,12 +1161,12 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(newval, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(io_max_combine_limit, newval);
}
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 2f8c3d5f918..0d1b6466d1e 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3591,7 +3591,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.49.0
--bwrlgp6w2ubxykjq
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v5-0003-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v4 4/8] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index ec40c0b7c42..9aa426992a2 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index a9f2a3a3062..e715a6f01c2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,13 +1161,13 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_max_combine_limit = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit_guc = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 6ae9f38f0c8..b1fba850f02 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3593,7 +3593,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--vninua6xybvzgrci
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v4-0005-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v5 02/10] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 47ffc0a2307..d1be780683b 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 608f10d9412..e40dae2ddf2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,12 +1161,12 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(newval, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(io_max_combine_limit, newval);
}
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 2f8c3d5f918..0d1b6466d1e 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3591,7 +3591,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.49.0
--bwrlgp6w2ubxykjq
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v5-0003-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v5 02/10] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 47ffc0a2307..d1be780683b 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 608f10d9412..e40dae2ddf2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,12 +1161,12 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(newval, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(io_max_combine_limit, newval);
}
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 2f8c3d5f918..0d1b6466d1e 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3591,7 +3591,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.49.0
--bwrlgp6w2ubxykjq
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v5-0003-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v4 4/8] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index ec40c0b7c42..9aa426992a2 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index a9f2a3a3062..e715a6f01c2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,13 +1161,13 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_max_combine_limit = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit_guc = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 6ae9f38f0c8..b1fba850f02 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3593,7 +3593,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--vninua6xybvzgrci
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v4-0005-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v5 02/10] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 47ffc0a2307..d1be780683b 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 608f10d9412..e40dae2ddf2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,12 +1161,12 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(newval, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(io_max_combine_limit, newval);
}
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 2f8c3d5f918..0d1b6466d1e 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3591,7 +3591,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.49.0
--bwrlgp6w2ubxykjq
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v5-0003-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v5 02/10] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 47ffc0a2307..d1be780683b 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 608f10d9412..e40dae2ddf2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,12 +1161,12 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(newval, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(io_max_combine_limit, newval);
}
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 2f8c3d5f918..0d1b6466d1e 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3591,7 +3591,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.49.0
--bwrlgp6w2ubxykjq
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v5-0003-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v4 4/8] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index ec40c0b7c42..9aa426992a2 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index a9f2a3a3062..e715a6f01c2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,13 +1161,13 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_max_combine_limit = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit_guc = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 6ae9f38f0c8..b1fba850f02 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3593,7 +3593,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--vninua6xybvzgrci
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v4-0005-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v5 02/10] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 47ffc0a2307..d1be780683b 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 608f10d9412..e40dae2ddf2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,12 +1161,12 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(newval, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(io_max_combine_limit, newval);
}
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 2f8c3d5f918..0d1b6466d1e 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3591,7 +3591,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.49.0
--bwrlgp6w2ubxykjq
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v5-0003-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v4 4/8] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index ec40c0b7c42..9aa426992a2 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index a9f2a3a3062..e715a6f01c2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,13 +1161,13 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_max_combine_limit = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit_guc = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 6ae9f38f0c8..b1fba850f02 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3593,7 +3593,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--vninua6xybvzgrci
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v4-0005-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v5 02/10] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 47ffc0a2307..d1be780683b 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 608f10d9412..e40dae2ddf2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,12 +1161,12 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(newval, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(io_max_combine_limit, newval);
}
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 2f8c3d5f918..0d1b6466d1e 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3591,7 +3591,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.49.0
--bwrlgp6w2ubxykjq
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v5-0003-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v4 4/8] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index ec40c0b7c42..9aa426992a2 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index a9f2a3a3062..e715a6f01c2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,13 +1161,13 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_max_combine_limit = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit_guc = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 6ae9f38f0c8..b1fba850f02 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3593,7 +3593,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--vninua6xybvzgrci
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v4-0005-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v5 02/10] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 47ffc0a2307..d1be780683b 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 608f10d9412..e40dae2ddf2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,12 +1161,12 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(newval, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(io_max_combine_limit, newval);
}
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 2f8c3d5f918..0d1b6466d1e 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3591,7 +3591,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.49.0
--bwrlgp6w2ubxykjq
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v5-0003-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v4 4/8] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index ec40c0b7c42..9aa426992a2 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index a9f2a3a3062..e715a6f01c2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,13 +1161,13 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_max_combine_limit = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit_guc = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 6ae9f38f0c8..b1fba850f02 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3593,7 +3593,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--vninua6xybvzgrci
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v4-0005-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v5 02/10] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 47ffc0a2307..d1be780683b 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 608f10d9412..e40dae2ddf2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,12 +1161,12 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(newval, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(io_max_combine_limit, newval);
}
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 2f8c3d5f918..0d1b6466d1e 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3591,7 +3591,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.49.0
--bwrlgp6w2ubxykjq
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v5-0003-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v4 4/8] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index ec40c0b7c42..9aa426992a2 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index a9f2a3a3062..e715a6f01c2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,13 +1161,13 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_max_combine_limit = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit_guc = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 6ae9f38f0c8..b1fba850f02 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3593,7 +3593,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--vninua6xybvzgrci
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v4-0005-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v4 4/8] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index ec40c0b7c42..9aa426992a2 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index a9f2a3a3062..e715a6f01c2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,13 +1161,13 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_max_combine_limit = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit_guc = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 6ae9f38f0c8..b1fba850f02 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3593,7 +3593,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--vninua6xybvzgrci
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v4-0005-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v4 4/8] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index ec40c0b7c42..9aa426992a2 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index a9f2a3a3062..e715a6f01c2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,13 +1161,13 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_max_combine_limit = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit_guc = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 6ae9f38f0c8..b1fba850f02 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3593,7 +3593,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--vninua6xybvzgrci
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v4-0005-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v5 02/10] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 47ffc0a2307..d1be780683b 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 608f10d9412..e40dae2ddf2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,12 +1161,12 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(newval, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(io_max_combine_limit, newval);
}
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 2f8c3d5f918..0d1b6466d1e 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3591,7 +3591,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.49.0
--bwrlgp6w2ubxykjq
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v5-0003-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v4 4/8] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index ec40c0b7c42..9aa426992a2 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index a9f2a3a3062..e715a6f01c2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,13 +1161,13 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_max_combine_limit = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit_guc = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 6ae9f38f0c8..b1fba850f02 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3593,7 +3593,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--vninua6xybvzgrci
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v4-0005-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v5 02/10] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 47ffc0a2307..d1be780683b 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 608f10d9412..e40dae2ddf2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,12 +1161,12 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(newval, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(io_max_combine_limit, newval);
}
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 2f8c3d5f918..0d1b6466d1e 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3591,7 +3591,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.49.0
--bwrlgp6w2ubxykjq
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v5-0003-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v4 4/8] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index ec40c0b7c42..9aa426992a2 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index a9f2a3a3062..e715a6f01c2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,13 +1161,13 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_max_combine_limit = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit_guc = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 6ae9f38f0c8..b1fba850f02 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3593,7 +3593,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--vninua6xybvzgrci
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v4-0005-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v4 4/8] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index ec40c0b7c42..9aa426992a2 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index a9f2a3a3062..e715a6f01c2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,13 +1161,13 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_max_combine_limit = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit_guc = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 6ae9f38f0c8..b1fba850f02 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3593,7 +3593,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--vninua6xybvzgrci
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v4-0005-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v5 02/10] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 47ffc0a2307..d1be780683b 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 608f10d9412..e40dae2ddf2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,12 +1161,12 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(newval, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(io_max_combine_limit, newval);
}
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 2f8c3d5f918..0d1b6466d1e 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3591,7 +3591,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.49.0
--bwrlgp6w2ubxykjq
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v5-0003-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v4 4/8] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index ec40c0b7c42..9aa426992a2 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index a9f2a3a3062..e715a6f01c2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,13 +1161,13 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_max_combine_limit = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit_guc = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 6ae9f38f0c8..b1fba850f02 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3593,7 +3593,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--vninua6xybvzgrci
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v4-0005-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v4 4/8] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index ec40c0b7c42..9aa426992a2 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index a9f2a3a3062..e715a6f01c2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,13 +1161,13 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_max_combine_limit = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit_guc = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 6ae9f38f0c8..b1fba850f02 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3593,7 +3593,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--vninua6xybvzgrci
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v4-0005-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v5 02/10] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 47ffc0a2307..d1be780683b 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 608f10d9412..e40dae2ddf2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,12 +1161,12 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(newval, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(io_max_combine_limit, newval);
}
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 2f8c3d5f918..0d1b6466d1e 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3591,7 +3591,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.49.0
--bwrlgp6w2ubxykjq
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v5-0003-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v5 02/10] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 47ffc0a2307..d1be780683b 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 608f10d9412..e40dae2ddf2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,12 +1161,12 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(newval, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(io_max_combine_limit, newval);
}
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 2f8c3d5f918..0d1b6466d1e 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3591,7 +3591,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.49.0
--bwrlgp6w2ubxykjq
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v5-0003-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v4 4/8] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index ec40c0b7c42..9aa426992a2 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index a9f2a3a3062..e715a6f01c2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,13 +1161,13 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_max_combine_limit = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit_guc = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 6ae9f38f0c8..b1fba850f02 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3593,7 +3593,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--vninua6xybvzgrci
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v4-0005-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v4 4/8] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index ec40c0b7c42..9aa426992a2 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index a9f2a3a3062..e715a6f01c2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,13 +1161,13 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_max_combine_limit = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit_guc = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 6ae9f38f0c8..b1fba850f02 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3593,7 +3593,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--vninua6xybvzgrci
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v4-0005-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v5 02/10] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 47ffc0a2307..d1be780683b 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 608f10d9412..e40dae2ddf2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,12 +1161,12 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(newval, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(io_max_combine_limit, newval);
}
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 2f8c3d5f918..0d1b6466d1e 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3591,7 +3591,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.49.0
--bwrlgp6w2ubxykjq
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v5-0003-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v4 4/8] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index ec40c0b7c42..9aa426992a2 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index a9f2a3a3062..e715a6f01c2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,13 +1161,13 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_max_combine_limit = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit_guc = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 6ae9f38f0c8..b1fba850f02 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3593,7 +3593,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--vninua6xybvzgrci
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v4-0005-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v5 02/10] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 47ffc0a2307..d1be780683b 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 608f10d9412..e40dae2ddf2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,12 +1161,12 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(newval, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(io_max_combine_limit, newval);
}
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 2f8c3d5f918..0d1b6466d1e 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3591,7 +3591,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.49.0
--bwrlgp6w2ubxykjq
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v5-0003-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v5 02/10] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 47ffc0a2307..d1be780683b 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 608f10d9412..e40dae2ddf2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,12 +1161,12 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(newval, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(io_max_combine_limit, newval);
}
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 2f8c3d5f918..0d1b6466d1e 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3591,7 +3591,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.49.0
--bwrlgp6w2ubxykjq
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v5-0003-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v4 4/8] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index ec40c0b7c42..9aa426992a2 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index a9f2a3a3062..e715a6f01c2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,13 +1161,13 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_max_combine_limit = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit_guc = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 6ae9f38f0c8..b1fba850f02 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3593,7 +3593,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--vninua6xybvzgrci
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v4-0005-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v4 4/8] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index ec40c0b7c42..9aa426992a2 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index a9f2a3a3062..e715a6f01c2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,13 +1161,13 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_max_combine_limit = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit_guc = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 6ae9f38f0c8..b1fba850f02 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3593,7 +3593,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--vninua6xybvzgrci
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v4-0005-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v4 4/8] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index ec40c0b7c42..9aa426992a2 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index a9f2a3a3062..e715a6f01c2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,13 +1161,13 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_max_combine_limit = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit_guc = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 6ae9f38f0c8..b1fba850f02 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3593,7 +3593,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--vninua6xybvzgrci
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v4-0005-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v5 02/10] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 47ffc0a2307..d1be780683b 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 608f10d9412..e40dae2ddf2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,12 +1161,12 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(newval, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(io_max_combine_limit, newval);
}
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 2f8c3d5f918..0d1b6466d1e 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3591,7 +3591,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.49.0
--bwrlgp6w2ubxykjq
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v5-0003-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v4 4/8] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index ec40c0b7c42..9aa426992a2 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index a9f2a3a3062..e715a6f01c2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,13 +1161,13 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_max_combine_limit = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit_guc = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 6ae9f38f0c8..b1fba850f02 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3593,7 +3593,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--vninua6xybvzgrci
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v4-0005-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v5 02/10] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 47ffc0a2307..d1be780683b 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 608f10d9412..e40dae2ddf2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,12 +1161,12 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(newval, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(io_max_combine_limit, newval);
}
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 2f8c3d5f918..0d1b6466d1e 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3591,7 +3591,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.49.0
--bwrlgp6w2ubxykjq
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v5-0003-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v4 4/8] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index ec40c0b7c42..9aa426992a2 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index a9f2a3a3062..e715a6f01c2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,13 +1161,13 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_max_combine_limit = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit_guc = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 6ae9f38f0c8..b1fba850f02 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3593,7 +3593,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--vninua6xybvzgrci
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v4-0005-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v5 02/10] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 47ffc0a2307..d1be780683b 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 608f10d9412..e40dae2ddf2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,12 +1161,12 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(newval, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(io_max_combine_limit, newval);
}
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 2f8c3d5f918..0d1b6466d1e 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3591,7 +3591,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.49.0
--bwrlgp6w2ubxykjq
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v5-0003-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v5 02/10] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 47ffc0a2307..d1be780683b 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 608f10d9412..e40dae2ddf2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,12 +1161,12 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(newval, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(io_max_combine_limit, newval);
}
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 2f8c3d5f918..0d1b6466d1e 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3591,7 +3591,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.49.0
--bwrlgp6w2ubxykjq
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v5-0003-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v4 4/8] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index ec40c0b7c42..9aa426992a2 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index a9f2a3a3062..e715a6f01c2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,13 +1161,13 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_max_combine_limit = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit_guc = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 6ae9f38f0c8..b1fba850f02 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3593,7 +3593,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--vninua6xybvzgrci
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v4-0005-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v5 02/10] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 47ffc0a2307..d1be780683b 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 608f10d9412..e40dae2ddf2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,12 +1161,12 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(newval, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(io_max_combine_limit, newval);
}
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 2f8c3d5f918..0d1b6466d1e 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3591,7 +3591,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.49.0
--bwrlgp6w2ubxykjq
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v5-0003-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v4 4/8] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index ec40c0b7c42..9aa426992a2 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index a9f2a3a3062..e715a6f01c2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,13 +1161,13 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_max_combine_limit = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit_guc = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 6ae9f38f0c8..b1fba850f02 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3593,7 +3593,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--vninua6xybvzgrci
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v4-0005-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v5 02/10] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 47ffc0a2307..d1be780683b 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 608f10d9412..e40dae2ddf2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,12 +1161,12 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(newval, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(io_max_combine_limit, newval);
}
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 2f8c3d5f918..0d1b6466d1e 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3591,7 +3591,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.49.0
--bwrlgp6w2ubxykjq
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v5-0003-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v5 02/10] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 47ffc0a2307..d1be780683b 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 608f10d9412..e40dae2ddf2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,12 +1161,12 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(newval, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(io_max_combine_limit, newval);
}
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 2f8c3d5f918..0d1b6466d1e 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3591,7 +3591,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.49.0
--bwrlgp6w2ubxykjq
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v5-0003-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v5 02/10] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 47ffc0a2307..d1be780683b 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 608f10d9412..e40dae2ddf2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,12 +1161,12 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(newval, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(io_max_combine_limit, newval);
}
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 2f8c3d5f918..0d1b6466d1e 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3591,7 +3591,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.49.0
--bwrlgp6w2ubxykjq
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v5-0003-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v5 02/10] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 47ffc0a2307..d1be780683b 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 608f10d9412..e40dae2ddf2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,12 +1161,12 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(newval, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(io_max_combine_limit, newval);
}
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 2f8c3d5f918..0d1b6466d1e 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3591,7 +3591,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.49.0
--bwrlgp6w2ubxykjq
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v5-0003-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v4 4/8] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index ec40c0b7c42..9aa426992a2 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index a9f2a3a3062..e715a6f01c2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,13 +1161,13 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_max_combine_limit = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit_guc = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 6ae9f38f0c8..b1fba850f02 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3593,7 +3593,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--vninua6xybvzgrci
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v4-0005-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v5 02/10] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 47ffc0a2307..d1be780683b 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 608f10d9412..e40dae2ddf2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,12 +1161,12 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(newval, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(io_max_combine_limit, newval);
}
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 2f8c3d5f918..0d1b6466d1e 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3591,7 +3591,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.49.0
--bwrlgp6w2ubxykjq
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v5-0003-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v4 4/8] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index ec40c0b7c42..9aa426992a2 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index a9f2a3a3062..e715a6f01c2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,13 +1161,13 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_max_combine_limit = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit_guc = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 6ae9f38f0c8..b1fba850f02 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3593,7 +3593,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--vninua6xybvzgrci
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v4-0005-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v4 4/8] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index ec40c0b7c42..9aa426992a2 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index a9f2a3a3062..e715a6f01c2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,13 +1161,13 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_max_combine_limit = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit_guc = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 6ae9f38f0c8..b1fba850f02 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3593,7 +3593,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.45.1
--vninua6xybvzgrci
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v4-0005-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v5 02/10] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 47ffc0a2307..d1be780683b 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 608f10d9412..e40dae2ddf2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,12 +1161,12 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(newval, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(io_max_combine_limit, newval);
}
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 2f8c3d5f918..0d1b6466d1e 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3591,7 +3591,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.49.0
--bwrlgp6w2ubxykjq
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v5-0003-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v5 02/10] Introduce pending flag for GUC assign hooks
@ 2025-04-06 14:40 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-04-06 14:40 UTC (permalink / raw)
Currently an assing hook can perform some preprocessing of a new value,
but it cannot change the behavior, which dictates that the new value
will be applied immediately after the hook. Certain GUC options (like
shared_buffers, coming in subsequent patches) may need coordinating work
between backends to change, meaning we cannot apply it right away.
Add a new flag "pending" for an assign hook to allow the hook indicate
exactly that. If the pending flag is set after the hook, the new value
will not be applied and it's handling becomes the hook's implementation
responsibility.
Note, that this also requires changes in the way how GUCs are getting
reported, but the patch does not cover that yet.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/commands/variable.c | 6 +--
src/backend/libpq/pqcomm.c | 8 ++--
src/backend/tcop/postgres.c | 2 +-
src/backend/utils/misc/guc.c | 59 +++++++++++++++++++---------
src/backend/utils/misc/stack_depth.c | 2 +-
src/include/utils/guc.h | 2 +-
src/include/utils/guc_hooks.h | 20 +++++-----
8 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 47ffc0a2307..d1be780683b 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2321,7 +2321,7 @@ CalculateCheckpointSegments(void)
}
void
-assign_max_wal_size(int newval, void *extra)
+assign_max_wal_size(int newval, void *extra, bool *pending)
{
max_wal_size_mb = newval;
CalculateCheckpointSegments();
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 608f10d9412..e40dae2ddf2 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -1143,7 +1143,7 @@ check_cluster_name(char **newval, void **extra, GucSource source)
* GUC assign_hook for maintenance_io_concurrency
*/
void
-assign_maintenance_io_concurrency(int newval, void *extra)
+assign_maintenance_io_concurrency(int newval, void *extra, bool *pending)
{
/*
* Reconfigure recovery prefetching, because a setting it depends on
@@ -1161,12 +1161,12 @@ assign_maintenance_io_concurrency(int newval, void *extra)
* they may be assigned in either order.
*/
void
-assign_io_max_combine_limit(int newval, void *extra)
+assign_io_max_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(newval, io_combine_limit_guc);
}
void
-assign_io_combine_limit(int newval, void *extra)
+assign_io_combine_limit(int newval, void *extra, bool *pending)
{
io_combine_limit = Min(io_max_combine_limit, newval);
}
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..2a6a587ef76 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1952,7 +1952,7 @@ pq_settcpusertimeout(int timeout, Port *port)
* GUC assign_hook for tcp_keepalives_idle
*/
void
-assign_tcp_keepalives_idle(int newval, void *extra)
+assign_tcp_keepalives_idle(int newval, void *extra, bool *pending)
{
/*
* The kernel API provides no way to test a value without setting it; and
@@ -1985,7 +1985,7 @@ show_tcp_keepalives_idle(void)
* GUC assign_hook for tcp_keepalives_interval
*/
void
-assign_tcp_keepalives_interval(int newval, void *extra)
+assign_tcp_keepalives_interval(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivesinterval(newval, MyProcPort);
@@ -2008,7 +2008,7 @@ show_tcp_keepalives_interval(void)
* GUC assign_hook for tcp_keepalives_count
*/
void
-assign_tcp_keepalives_count(int newval, void *extra)
+assign_tcp_keepalives_count(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_setkeepalivescount(newval, MyProcPort);
@@ -2031,7 +2031,7 @@ show_tcp_keepalives_count(void)
* GUC assign_hook for tcp_user_timeout
*/
void
-assign_tcp_user_timeout(int newval, void *extra)
+assign_tcp_user_timeout(int newval, void *extra, bool *pending)
{
/* See comments in assign_tcp_keepalives_idle */
(void) pq_settcpusertimeout(newval, MyProcPort);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 2f8c3d5f918..0d1b6466d1e 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3591,7 +3591,7 @@ check_log_stats(bool *newval, void **extra, GucSource source)
/* GUC assign hook for transaction_timeout */
void
-assign_transaction_timeout(int newval, void *extra)
+assign_transaction_timeout(int newval, void *extra, bool *pending)
{
if (IsTransactionState())
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..bb681f5bc60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1679,6 +1679,7 @@ InitializeOneGUCOption(struct config_generic *gconf)
struct config_int *conf = (struct config_int *) gconf;
int newval = conf->boot_val;
void *extra = NULL;
+ bool pending = false;
Assert(newval >= conf->min);
Assert(newval <= conf->max);
@@ -1687,9 +1688,13 @@ InitializeOneGUCOption(struct config_generic *gconf)
elog(FATAL, "failed to initialize %s to %d",
conf->gen.name, newval);
if (conf->assign_hook)
- conf->assign_hook(newval, extra);
- *conf->variable = conf->reset_val = newval;
- conf->gen.extra = conf->reset_extra = extra;
+ conf->assign_hook(newval, extra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val = newval;
+ conf->gen.extra = conf->reset_extra = extra;
+ }
break;
}
case PGC_REAL:
@@ -2041,13 +2046,18 @@ ResetAllOptions(void)
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
+ bool pending = false;
if (conf->assign_hook)
conf->assign_hook(conf->reset_val,
- conf->reset_extra);
- *conf->variable = conf->reset_val;
- set_extra_field(&conf->gen, &conf->gen.extra,
- conf->reset_extra);
+ conf->reset_extra,
+ &pending);
+ if (!pending)
+ {
+ *conf->variable = conf->reset_val;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ conf->reset_extra);
+ }
break;
}
case PGC_REAL:
@@ -2424,16 +2434,21 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
struct config_int *conf = (struct config_int *) gconf;
int newval = newvalue.val.intval;
void *newextra = newvalue.extra;
+ bool pending = false;
if (*conf->variable != newval ||
conf->gen.extra != newextra)
{
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- changed = true;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ changed = true;
+ }
}
break;
}
@@ -3850,18 +3865,24 @@ set_config_with_handle(const char *name, config_handle *handle,
if (changeVal)
{
+ bool pending = false;
+
/* Save old value to support transaction abort */
if (!makeDefault)
push_old_value(&conf->gen, action);
if (conf->assign_hook)
- conf->assign_hook(newval, newextra);
- *conf->variable = newval;
- set_extra_field(&conf->gen, &conf->gen.extra,
- newextra);
- set_guc_source(&conf->gen, source);
- conf->gen.scontext = context;
- conf->gen.srole = srole;
+ conf->assign_hook(newval, newextra, &pending);
+
+ if (!pending)
+ {
+ *conf->variable = newval;
+ set_extra_field(&conf->gen, &conf->gen.extra,
+ newextra);
+ set_guc_source(&conf->gen, source);
+ conf->gen.scontext = context;
+ conf->gen.srole = srole;
+ }
}
if (makeDefault)
{
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 8f7cf531fbc..ef59ae62008 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -156,7 +156,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
/* GUC assign hook for max_stack_depth */
void
-assign_max_stack_depth(int newval, void *extra)
+assign_max_stack_depth(int newval, void *extra, bool *pending)
{
ssize_t newval_bytes = newval * (ssize_t) 1024;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..8802ad8a3cb 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -187,7 +187,7 @@ typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource sourc
typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
typedef void (*GucBoolAssignHook) (bool newval, void *extra);
-typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra, bool *pending);
typedef void (*GucRealAssignHook) (double newval, void *extra);
typedef void (*GucStringAssignHook) (const char *newval, void *extra);
typedef void (*GucEnumAssignHook) (int newval, void *extra);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..c8300cffa8e 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -81,14 +81,14 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source);
extern bool check_log_timezone(char **newval, void **extra, GucSource source);
extern void assign_log_timezone(const char *newval, void *extra);
extern const char *show_log_timezone(void);
-extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern void assign_io_max_combine_limit(int newval, void *extra);
-extern void assign_io_combine_limit(int newval, void *extra);
+extern void assign_maintenance_io_concurrency(int newval, void *extra, bool *pending);
+extern void assign_io_max_combine_limit(int newval, void *extra, bool *pending);
+extern void assign_io_combine_limit(int newval, void *extra, bool *pending);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
-extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_max_wal_size(int newval, void *extra, bool *pending);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
-extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_max_stack_depth(int newval, void *extra, bool *pending);
extern bool check_multixact_member_buffers(int *newval, void **extra,
GucSource source);
extern bool check_multixact_offset_buffers(int *newval, void **extra,
@@ -143,13 +143,13 @@ extern void assign_synchronous_standby_names(const char *newval, void *extra);
extern void assign_synchronous_commit(int newval, void *extra);
extern void assign_syslog_facility(int newval, void *extra);
extern void assign_syslog_ident(const char *newval, void *extra);
-extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_count(void);
-extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern void assign_tcp_keepalives_idle(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_idle(void);
-extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern void assign_tcp_keepalives_interval(int newval, void *extra, bool *pending);
extern const char *show_tcp_keepalives_interval(void);
-extern void assign_tcp_user_timeout(int newval, void *extra);
+extern void assign_tcp_user_timeout(int newval, void *extra, bool *pending);
extern const char *show_tcp_user_timeout(void);
extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
extern bool check_temp_tablespaces(char **newval, void **extra,
@@ -165,7 +165,7 @@ extern bool check_transaction_buffers(int *newval, void **extra, GucSource sourc
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
-extern void assign_transaction_timeout(int newval, void *extra);
+extern void assign_transaction_timeout(int newval, void *extra, bool *pending);
extern const char *show_unix_socket_permissions(void);
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
extern bool check_wal_consistency_checking(char **newval, void **extra,
--
2.49.0
--bwrlgp6w2ubxykjq
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
filename="v5-0003-Introduce-pss_barrierReceivedGeneration.patch"
^ permalink raw reply [nested|flat] 319+ messages in thread
* [PATCH v2] Use open file description locks for data directory lockfile
@ 2025-12-18 17:21 Dmitrii Dolgov <9erthalion6@gmail.com>
0 siblings, 0 replies; 319+ messages in thread
From: Dmitrii Dolgov @ 2025-12-18 17:21 UTC (permalink / raw)
When starting up, postmaster checks for an existing data directory lockfile. If
this file contains current process PID, it's assumed to be stale. Turns out
there is another possibility: we might be running in a PID namespace, and there
is another postgres running inside another PID namespace using the same data
directory. The result is that we don't see another process due to namespace
isolation and start concurrently with the other.
To prevent such situations, at startup use fcntl to get an exclusive open file
description lock for data directory lockfile. Since such locks are associated
with open file descriptors, meaning they're not affected by PID namespace
isolation. It's a "best effort" locking, intended to work with already existing
mechanism, not replace it.
This approach was discussed multiple times in the past, and usually was
rejected as the main work horse for the data directory lockfile due to:
* Portability issues. Open file description lock was a non-POSIX extension in
Linux and similar flock is from BSD standard. But looks like everybody agrees
that such locks make more sense than a typical advisory locks, and
F_OFD_SETLK made its way into POSIX.1 2024 [1].
* Issues with NFS. The current state of things here looks like this:
- NFSv3 doesn't implement open file description locks, they're converted to
advisory locks instead. Advisory locks are subject to namespace isolation,
meaning that processes in different PID namespaces will not see each other
advisory lock, and it's still possible to run multiple postgres
instances on the same data directory.
- NFSv4 uses a lease system for locking, I haven't found any mention of
conversion to advisory locks neither in the man page nor in RFC [2].
To summarize, the approach is now considered POSIX and should fix the described
problem everywhere, except NFSv3.
[1]: https://pubs.opengroup.org/onlinepubs/9799919799/functions/fcntl.html
[2]: https://www.rfc-editor.org/rfc/rfc7530
---
configure | 14 ++++
configure.ac | 3 +
meson.build | 1 +
src/backend/utils/init/miscinit.c | 107 +++++++++++++++++++++++++-----
src/include/pg_config.h.in | 4 ++
5 files changed, 111 insertions(+), 18 deletions(-)
diff --git a/configure b/configure
index fb6a4914b06..1da073f0aaa 100755
--- a/configure
+++ b/configure
@@ -16177,6 +16177,20 @@ cat >>confdefs.h <<_ACEOF
_ACEOF
+# Linux open file descriptor locks
+ac_fn_c_check_decl "$LINENO" "F_OFD_SETLK" "ac_cv_have_decl_F_OFD_SETLK" "#include <fcntl.h>
+"
+if test "x$ac_cv_have_decl_F_OFD_SETLK" = xyes; then :
+ ac_have_decl=1
+else
+ ac_have_decl=0
+fi
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_DECL_F_OFD_SETLK $ac_have_decl
+_ACEOF
+
+
ac_fn_c_check_func "$LINENO" "explicit_bzero" "ac_cv_func_explicit_bzero"
if test "x$ac_cv_func_explicit_bzero" = xyes; then :
$as_echo "#define HAVE_EXPLICIT_BZERO 1" >>confdefs.h
diff --git a/configure.ac b/configure.ac
index d3febfe58f1..075194a8af8 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1844,6 +1844,9 @@ AC_CHECK_DECLS([memset_s], [], [], [#define __STDC_WANT_LIB_EXT1__ 1
# This is probably only present on macOS, but may as well check always
AC_CHECK_DECLS(F_FULLFSYNC, [], [], [#include <fcntl.h>])
+# Linux open file descriptor locks
+AC_CHECK_DECLS([F_OFD_SETLK], [], [], [#include <fcntl.h>])
+
AC_REPLACE_FUNCS(m4_normalize([
explicit_bzero
getopt
diff --git a/meson.build b/meson.build
index 6d304f32fb0..d346aefe9b6 100644
--- a/meson.build
+++ b/meson.build
@@ -2694,6 +2694,7 @@ decl_checks = [
['strlcpy', 'string.h'],
['strsep', 'string.h'],
['timingsafe_bcmp', 'string.h'],
+ ['F_OFD_SETLK', 'fcntl.h'],
]
# Need to check for function declarations for these functions, because
diff --git a/src/backend/utils/init/miscinit.c b/src/backend/utils/init/miscinit.c
index 563f20374ff..b41a5f9dcca 100644
--- a/src/backend/utils/init/miscinit.c
+++ b/src/backend/utils/init/miscinit.c
@@ -68,6 +68,11 @@ static List *lock_files = NIL;
static Latch LocalLatchData;
+#if HAVE_DECL_F_OFD_SETLK
+/* File descriptor for data directory lock file. */
+static int DataDirLockFD;
+#endif
+
/* ----------------------------------------------------------------
* ignoring system indexes support stuff
*
@@ -1117,6 +1122,45 @@ RestoreClientConnectionInfo(char *conninfo)
*-------------------------------------------------------------------------
*/
+/*
+ * Flock the data directory lockfile.
+ *
+ * Lock the data directory lockfile with an open file description lock. If the
+ * lock is already taken, it's a hard stop. It's only a best effort test, and
+ * any other errors are ignored. On succes the file descriptor is duplicated,
+ * to make sure there will be at least one open copy of it to keep the lock.
+ *
+ * filename is used only for reporting purposes.
+ */
+static void
+FlockDataDirLockFile(int fd, const char *filename)
+{
+
+#if HAVE_DECL_F_OFD_SETLK
+ struct flock lock;
+
+ lock.l_type = F_WRLCK;
+ lock.l_whence = SEEK_SET;
+ lock.l_start = 0;
+ lock.l_len = 0;
+ lock.l_pid = 0;
+
+ if (fcntl(fd, F_OFD_SETLK, &lock) == -1)
+ {
+ if (errno == EAGAIN)
+ ereport(FATAL,
+ (errcode(ERRCODE_LOCK_FILE_EXISTS),
+ errmsg("cannot lock the lock file \"%s\"", filename),
+ errhint("Another server is starting.")));
+ else
+ elog(WARNING, "Failed locking file \"%s\", %m", filename);
+ }
+ else
+ DataDirLockFD = dup(fd);
+#endif
+
+}
+
/*
* proc_exit callback to remove lockfiles.
*/
@@ -1125,6 +1169,11 @@ UnlinkLockFiles(int status, Datum arg)
{
ListCell *l;
+#if HAVE_DECL_F_OFD_SETLK
+ /* Close the file descriptor, which keeps the open file description lock */
+ close(DataDirLockFD);
+#endif
+
foreach(l, lock_files)
{
char *curfile = (char *) lfirst(l);
@@ -1171,22 +1220,32 @@ CreateLockFile(const char *filename, bool amPostmaster,
const char *envvar;
/*
- * If the PID in the lockfile is our own PID or our parent's or
- * grandparent's PID, then the file must be stale (probably left over from
- * a previous system boot cycle). We need to check this because of the
- * likelihood that a reboot will assign exactly the same PID as we had in
- * the previous reboot, or one that's only one or two counts larger and
- * hence the lockfile's PID now refers to an ancestor shell process. We
- * allow pg_ctl to pass down its parent shell PID (our grandparent PID)
- * via the environment variable PG_GRANDPARENT_PID; this is so that
- * launching the postmaster via pg_ctl can be just as reliable as
- * launching it directly. There is no provision for detecting
- * further-removed ancestor processes, but if the init script is written
- * carefully then all but the immediate parent shell will be root-owned
- * processes and so the kill test will fail with EPERM. Note that we
- * cannot get a false negative this way, because an existing postmaster
- * would surely never launch a competing postmaster or pg_ctl process
- * directly.
+ * If we find an already existing lockfile containing our own PID,
+ * there are few options:
+ *
+ * - There is another process, that we don't see due to PID namespace
+ * isolation, which is already running in this data directory.
+ *
+ * To prevent two concurrent processes working with the same data
+ * directory, we first try to lock the lockfile exclusively.
+ *
+ * - The file must be stale, probably left over from a previous system boot
+ * cycle. The same if the lockfile contains our parent's or grandparent's
+ * PID.
+ *
+ * We need to check this because of the likelihood that a reboot will
+ * assign exactly the same PID as we had in the previous reboot, or one
+ * that's only one or two counts larger and hence the lockfile's PID now
+ * refers to an ancestor shell process. We allow pg_ctl to pass down its
+ * parent shell PID (our grandparent PID) via the environment variable
+ * PG_GRANDPARENT_PID; this is so that launching the postmaster via
+ * pg_ctl can be just as reliable as launching it directly. There is no
+ * provision for detecting further-removed ancestor processes, but if the
+ * init script is written carefully then all but the immediate parent
+ * shell will be root-owned processes and so the kill test will fail with
+ * EPERM. Note that we cannot get a false negative this way, because an
+ * existing postmaster would surely never launch a competing postmaster
+ * or pg_ctl process directly.
*/
my_pid = getpid();
@@ -1222,7 +1281,11 @@ CreateLockFile(const char *filename, bool amPostmaster,
*/
fd = open(filename, O_RDWR | O_CREAT | O_EXCL, pg_file_create_mode);
if (fd >= 0)
- break; /* Success; exit the retry loop */
+ {
+ /* Success; lock and exit the retry loop */
+ FlockDataDirLockFile(fd, filename);
+ break;
+ }
/*
* Couldn't create the pid file. Probably it already exists.
@@ -1236,8 +1299,12 @@ CreateLockFile(const char *filename, bool amPostmaster,
/*
* Read the file to get the old owner's PID. Note race condition
* here: file might have been deleted since we tried to create it.
+ *
+ * We're going to use the same fd for flock, and want to create a write
+ * lock for the latter one. Since both fd and the lock have to be of
+ * the same type, open the file for read and write.
*/
- fd = open(filename, O_RDONLY, pg_file_create_mode);
+ fd = open(filename, O_RDWR, pg_file_create_mode);
if (fd < 0)
{
if (errno == ENOENT)
@@ -1247,6 +1314,10 @@ CreateLockFile(const char *filename, bool amPostmaster,
errmsg("could not open lock file \"%s\": %m",
filename)));
}
+
+ /* Try to lock the file. We stop here, if it's already locked. */
+ FlockDataDirLockFile(fd, filename);
+
pgstat_report_wait_start(WAIT_EVENT_LOCK_FILE_CREATE_READ);
if ((len = read(fd, buffer, sizeof(buffer) - 1)) < 0)
ereport(FATAL,
diff --git a/src/include/pg_config.h.in b/src/include/pg_config.h.in
index 339268dc8ef..e7b8e023829 100644
--- a/src/include/pg_config.h.in
+++ b/src/include/pg_config.h.in
@@ -80,6 +80,10 @@
don't. */
#undef HAVE_DECL_F_FULLFSYNC
+/* Define to 1 if you have the declaration of `F_OFD_SETLK', and to 0 if you
+ don't. */
+#undef HAVE_DECL_F_OFD_SETLK
+
/* Define to 1 if you have the declaration of `memset_s', and to 0 if you
don't. */
#undef HAVE_DECL_MEMSET_S
base-commit: 6831cd9e3b082d7b830c3196742dd49e3540c49b
--
2.49.0
--7u2oub7w3nl66bkx--
^ permalink raw reply [nested|flat] 319+ messages in thread
end of thread, other threads:[~2025-12-18 17:21 UTC | newest]
Thread overview: 319+ messages (download: mbox mbox.gz follow: Atom feed)
-- links below jump to the message on this page --
2025-02-19 16:45 [PATCH v2 4/6] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-19 16:45 [PATCH v2 4/6] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-19 16:45 [PATCH v2 4/6] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-19 16:45 [PATCH v2 4/6] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-19 16:45 [PATCH v2 4/6] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-19 16:45 [PATCH v2 4/6] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-19 16:45 [PATCH v2 4/6] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-19 16:45 [PATCH v2 4/6] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-19 16:45 [PATCH v2 4/6] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-19 16:45 [PATCH v2 4/6] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-19 16:45 [PATCH v2 4/6] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-19 16:45 [PATCH v2 4/6] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-19 16:45 [PATCH v2 4/6] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-19 16:45 [PATCH v2 4/6] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-19 16:45 [PATCH v2 4/6] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-19 16:45 [PATCH v2 4/6] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-19 16:45 [PATCH v2 4/6] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-19 16:45 [PATCH v2 4/6] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-19 16:45 [PATCH v2 4/6] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-19 16:45 [PATCH v2 4/6] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-19 16:45 [PATCH v2 4/6] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-19 16:45 [PATCH v2 4/6] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-19 16:45 [PATCH v2 4/6] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-19 16:45 [PATCH v2 4/6] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-19 16:45 [PATCH v2 4/6] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-19 16:45 [PATCH v2 4/6] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-19 16:45 [PATCH v2 4/6] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-19 16:45 [PATCH v2 4/6] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-19 16:45 [PATCH v2 4/6] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-19 16:45 [PATCH v2 4/6] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-19 16:45 [PATCH v2 4/6] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-19 16:45 [PATCH v2 4/6] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-19 16:45 [PATCH v2 4/6] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-19 16:45 [PATCH v2 4/6] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-19 16:45 [PATCH v2 4/6] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-19 16:45 [PATCH v2 4/6] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-19 16:45 [PATCH v2 4/6] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-19 16:45 [PATCH v2 4/6] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-19 16:45 [PATCH v2 4/6] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-19 16:45 [PATCH v2 4/6] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-19 16:45 [PATCH v2 4/6] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-19 16:45 [PATCH v2 4/6] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-19 16:45 [PATCH v2 4/6] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-19 16:45 [PATCH v2 4/6] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-19 16:45 [PATCH v2 4/6] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-19 16:45 [PATCH v2 4/6] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-19 16:45 [PATCH v2 4/6] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-19 16:45 [PATCH v2 4/6] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-19 16:45 [PATCH v2 4/6] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-19 16:45 [PATCH v2 4/6] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-19 16:45 [PATCH v2 4/6] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-19 16:45 [PATCH v2 4/6] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-19 16:45 [PATCH v2 4/6] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-19 16:45 [PATCH v2 4/6] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-19 16:45 [PATCH v2 4/6] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-19 16:45 [PATCH v2 4/6] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-19 16:45 [PATCH v2 4/6] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-19 16:45 [PATCH v2 4/6] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-19 16:45 [PATCH v2 4/6] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-19 16:45 [PATCH v2 4/6] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-19 16:45 [PATCH v2 4/6] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-19 16:45 [PATCH v2 4/6] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-19 16:45 [PATCH v2 4/6] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-19 16:45 [PATCH v2 4/6] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-19 16:45 [PATCH v2 4/6] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-19 16:45 [PATCH v2 4/6] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-19 16:45 [PATCH v2 4/6] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-19 16:45 [PATCH v2 4/6] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-19 16:45 [PATCH v2 4/6] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-19 16:45 [PATCH v2 4/6] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-19 16:45 [PATCH v2 4/6] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-19 16:45 [PATCH v2 4/6] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-19 16:45 [PATCH v2 4/6] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-19 16:45 [PATCH v2 4/6] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-19 16:45 [PATCH v2 4/6] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-19 16:45 [PATCH v2 4/6] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-19 16:45 [PATCH v2 4/6] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-19 16:45 [PATCH v2 4/6] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-19 16:45 [PATCH v2 4/6] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-19 16:45 [PATCH v2 4/6] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-19 16:45 [PATCH v2 4/6] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-19 16:45 [PATCH v2 4/6] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-19 16:45 [PATCH v2 4/6] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-19 16:45 [PATCH v2 4/6] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-19 16:45 [PATCH v2 4/6] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-19 16:45 [PATCH v2 4/6] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-19 16:45 [PATCH v2 4/6] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-19 16:45 [PATCH v2 4/6] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-19 16:45 [PATCH v2 4/6] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-19 16:45 [PATCH v2 4/6] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-19 16:45 [PATCH v2 4/6] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-19 16:45 [PATCH v2 4/6] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-19 16:45 [PATCH v2 4/6] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-19 16:45 [PATCH v2 4/6] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-19 16:45 [PATCH v2 4/6] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-19 16:45 [PATCH v2 4/6] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-19 16:45 [PATCH v2 4/6] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-19 16:45 [PATCH v2 4/6] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-19 16:45 [PATCH v2 4/6] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-19 16:45 [PATCH v2 4/6] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-19 16:45 [PATCH v2 4/6] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-19 16:45 [PATCH v2 4/6] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-19 16:45 [PATCH v2 4/6] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-19 16:45 [PATCH v2 4/6] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-19 16:45 [PATCH v2 4/6] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-19 16:45 [PATCH v2 4/6] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v4 4/8] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v5 02/10] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v4 4/8] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v4 4/8] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v4 4/8] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v4 4/8] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v4 4/8] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v4 4/8] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v4 4/8] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v5 02/10] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v5 02/10] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v5 02/10] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v4 4/8] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v4 4/8] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v4 4/8] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v5 02/10] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v4 4/8] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v4 4/8] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v5 02/10] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v4 4/8] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v5 02/10] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v5 02/10] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v5 02/10] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v4 4/8] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v5 02/10] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v4 4/8] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v5 02/10] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v4 4/8] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v5 02/10] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v4 4/8] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v5 02/10] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v4 4/8] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v4 4/8] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v5 02/10] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v4 4/8] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v5 02/10] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v4 4/8] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v5 02/10] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v4 4/8] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v4 4/8] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v5 02/10] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v4 4/8] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v5 02/10] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v4 4/8] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v5 02/10] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v5 02/10] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v5 02/10] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v4 4/8] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v4 4/8] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v4 4/8] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v5 02/10] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v4 4/8] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v4 4/8] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v5 02/10] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v4 4/8] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v4 4/8] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v4 4/8] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v5 02/10] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v4 4/8] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v5 02/10] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v5 02/10] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v5 02/10] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v4 4/8] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v5 02/10] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v4 4/8] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v5 02/10] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v4 4/8] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v5 02/10] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v5 02/10] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v5 02/10] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v5 02/10] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v5 02/10] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v5 02/10] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v4 4/8] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v4 4/8] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v5 02/10] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v4 4/8] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v5 02/10] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v4 4/8] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v5 02/10] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v5 02/10] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v5 02/10] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v5 02/10] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v5 02/10] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v4 4/8] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v4 4/8] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v4 4/8] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v5 02/10] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v5 02/10] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v4 4/8] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v5 02/10] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v5 02/10] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v4 4/8] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v5 02/10] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v5 02/10] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v4 4/8] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v4 4/8] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v5 02/10] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v4 4/8] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v5 02/10] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v4 4/8] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v5 02/10] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v4 4/8] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v4 4/8] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v4 4/8] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v4 4/8] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v4 4/8] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v5 02/10] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v4 4/8] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v5 02/10] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v5 02/10] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v4 4/8] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v4 4/8] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v4 4/8] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v4 4/8] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v5 02/10] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v5 02/10] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v4 4/8] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v5 02/10] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v4 4/8] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v5 02/10] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v5 02/10] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v5 02/10] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v4 4/8] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v5 02/10] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v4 4/8] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v4 4/8] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v4 4/8] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v4 4/8] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v4 4/8] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v4 4/8] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v5 02/10] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v4 4/8] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v5 02/10] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v5 02/10] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v4 4/8] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v5 02/10] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v4 4/8] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v5 02/10] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v5 02/10] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v5 02/10] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v5 02/10] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v4 4/8] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v5 02/10] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v5 02/10] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v5 02/10] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v5 02/10] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v5 02/10] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v4 4/8] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v5 02/10] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v4 4/8] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v4 4/8] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v5 02/10] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v4 4/8] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v4 4/8] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v5 02/10] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v5 02/10] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v4 4/8] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v5 02/10] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v5 02/10] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v4 4/8] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v5 02/10] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v5 02/10] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v4 4/8] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v5 02/10] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v4 4/8] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v5 02/10] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v4 4/8] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v5 02/10] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v4 4/8] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v5 02/10] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v4 4/8] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v4 4/8] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v4 4/8] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v5 02/10] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v4 4/8] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v5 02/10] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v4 4/8] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v4 4/8] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v5 02/10] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v4 4/8] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v4 4/8] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v5 02/10] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v5 02/10] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v4 4/8] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v4 4/8] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v5 02/10] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v4 4/8] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v5 02/10] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v5 02/10] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v4 4/8] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v4 4/8] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v4 4/8] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v5 02/10] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v4 4/8] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v5 02/10] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v4 4/8] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v5 02/10] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v5 02/10] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v4 4/8] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v5 02/10] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v4 4/8] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v5 02/10] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v5 02/10] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v5 02/10] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v5 02/10] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v4 4/8] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v5 02/10] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v4 4/8] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v4 4/8] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v5 02/10] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:40 [PATCH v5 02/10] Introduce pending flag for GUC assign hooks Dmitrii Dolgov <9erthalion6@gmail.com>
2025-12-18 17:21 [PATCH v2] Use open file description locks for data directory lockfile Dmitrii Dolgov <9erthalion6@gmail.com>
This inbox is served by agora; see mirroring instructions
for how to clone and mirror all data and code used for this inbox