public inbox for [email protected]
help / color / mirror / Atom feed[PATCH v7 7/9] Default to LZ4..
6+ messages / 3 participants
[nested] [flat]
* [PATCH v7 7/9] Default to LZ4..
@ 2021-03-12 21:35 Justin Pryzby <[email protected]>
0 siblings, 0 replies; 6+ messages in thread
From: Justin Pryzby @ 2021-03-12 21:35 UTC (permalink / raw)
this is meant to exercise in the CIs, and not meant to be merged
---
configure | 6 ++++--
configure.ac | 4 ++--
src/backend/access/transam/xlog.c | 2 +-
src/backend/utils/misc/guc.c | 2 +-
4 files changed, 8 insertions(+), 6 deletions(-)
diff --git a/configure b/configure
index 9d44f6acc7..72bbd719dc 100755
--- a/configure
+++ b/configure
@@ -1581,7 +1581,7 @@ Optional Packages:
--with-system-tzdata=DIR
use system time zone data in DIR
--without-zlib do not use Zlib
- --with-lz4 build with LZ4 support
+ --without-lz4 build without LZ4 support
--with-zstd build with Zstd compression library
--with-gnu-ld assume the C compiler uses GNU ld [default=no]
--with-ssl=LIB use LIB for SSL/TLS support (openssl)
@@ -8607,7 +8607,9 @@ $as_echo "#define USE_LZ4 1" >>confdefs.h
esac
else
- with_lz4=no
+ with_lz4=yes
+
+$as_echo "#define USE_LZ4 1" >>confdefs.h
fi
diff --git a/configure.ac b/configure.ac
index f10c33785e..c348a3ee91 100644
--- a/configure.ac
+++ b/configure.ac
@@ -990,8 +990,8 @@ AC_SUBST(with_zlib)
# LZ4
#
AC_MSG_CHECKING([whether to build with LZ4 support])
-PGAC_ARG_BOOL(with, lz4, no, [build with LZ4 support],
- [AC_DEFINE([USE_LZ4], 1, [Define to 1 to build with LZ4 support. (--with-lz4)])])
+PGAC_ARG_BOOL(with, lz4, yes, [build without LZ4 support],
+ [AC_DEFINE([USE_LZ4], 1, [Define to 1 to build without LZ4 support. (--without-lz4)])])
AC_MSG_RESULT([$with_lz4])
AC_SUBST(with_lz4)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index e31ce1c2a6..3ddfa8c0ee 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -99,7 +99,7 @@ bool EnableHotStandby = false;
bool fullPageWrites = true;
bool wal_log_hints = false;
bool wal_compression = false;
-int wal_compression_method = WAL_COMPRESSION_ZLIB;
+int wal_compression_method = WAL_COMPRESSION_LZ4;
char *wal_consistency_checking_string = NULL;
bool *wal_consistency_checking = NULL;
bool wal_init_zero = true;
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index a448267ee9..da1ed32943 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -4832,7 +4832,7 @@ static struct config_enum ConfigureNamesEnum[] =
NULL
},
&wal_compression_method,
- WAL_COMPRESSION_ZLIB, wal_compression_options,
+ WAL_COMPRESSION_LZ4, wal_compression_options,
NULL, NULL, NULL
},
--
2.17.0
--JYK4vJDZwFMowpUq
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment; filename="v7-0008-Default-to-zstd.patch"
^ permalink raw reply [nested|flat] 6+ messages in thread
* Re: SQL function which allows to distinguish a server being in point in time recovery mode and an ordinary replica
@ 2024-05-08 04:24 Michael Paquier <[email protected]>
2024-06-13 18:07 ` Re: SQL function which allows to distinguish a server being in point in time recovery mode and an ordinary replica [email protected]
0 siblings, 1 reply; 6+ messages in thread
From: Michael Paquier @ 2024-05-08 04:24 UTC (permalink / raw)
To: [email protected]; +Cc: Tristan Partin <[email protected]>; [email protected]
On Mon, May 06, 2024 at 06:55:46PM +0300, [email protected] wrote:
> as a first step I have introduced the `SharedRecoveryDataFlags` bitmask
> instead of three boolean SharedHotStandbyActive, SharedPromoteIsTriggered
> and SharedStandbyModeRequested flags (the last one from my previous patch)
> and made minimal updates in corresponding code based on that change.
Thanks for the patch.
/*
- * Local copy of SharedHotStandbyActive variable. False actually means "not
+ * Local copy of XLR_HOT_STANDBY_ACTIVE flag. False actually means "not
* known, need to check the shared state".
*/
static bool LocalHotStandbyActive = false;
/*
- * Local copy of SharedPromoteIsTriggered variable. False actually means "not
+ * Local copy of XLR_PROMOTE_IS_TRIGGERED flag. False actually means "not
* known, need to check the shared state".
*/
static bool LocalPromoteIsTriggered = false;
It's a bit strange to have a bitwise set of flags in shmem while we
keep these local copies as booleans. Perhaps it would be cleaner to
merge both local variables into a single bits32 store?
+ uint32 SharedRecoveryDataFlags;
I'd switch to bits32 for flags here.
+bool
+StandbyModeIsRequested(void)
+{
+ /*
+ * Spinlock is not needed here because XLR_STANDBY_MODE_REQUESTED flag
+ * can only be read after startup process is done.
+ */
+ return (XLogRecoveryCtl->SharedRecoveryDataFlags & XLR_STANDBY_MODE_REQUESTED) != 0;
+}
How about introducing a single wrapper function that returns the whole
value SharedRecoveryDataFlags, with the flags published in a header?
Sure, XLR_HOT_STANDBY_ACTIVE is not really exciting because being able
to query a standby implies it, but XLR_PROMOTE_IS_TRIGGERED could be
interesting? Then this could be used with a function that returns a
text[] array with all the states retrieved?
The refactoring pieces and the function pieces should be split, for
clarity.
--
Michael
Attachments:
[application/pgp-signature] signature.asc (833B, ../../[email protected]/2-signature.asc)
download
^ permalink raw reply [nested|flat] 6+ messages in thread
* Re: SQL function which allows to distinguish a server being in point in time recovery mode and an ordinary replica
2024-05-08 04:24 Re: SQL function which allows to distinguish a server being in point in time recovery mode and an ordinary replica Michael Paquier <[email protected]>
@ 2024-06-13 18:07 ` [email protected]
2024-06-14 04:51 ` Re: SQL function which allows to distinguish a server being in point in time recovery mode and an ordinary replica Michael Paquier <[email protected]>
0 siblings, 1 reply; 6+ messages in thread
From: [email protected] @ 2024-06-13 18:07 UTC (permalink / raw)
To: Michael Paquier <[email protected]>; +Cc: [email protected]
Hi!
Michael,
I have fixed the patches according to your comments.
> merge both local variables into a single bits32 store?
This is done in v3-0001-Standby-mode-requested.patch
> Then this could be used with a function that returns a
> text[] array with all the states retrieved?
Placed this in the v3-0002-Text-array-sql-wrapper.patch
> The refactoring pieces and the function pieces should be split, for
> clarity.
Sure. I also added the third patch with some tests. Perhaps it would be
usefull.
Respectfully,
Mikhail Litsarev
Postgres Professional: https://postgrespro.com
Attachments:
[text/x-diff] v3-0003-Test-standby-is-requested.patch (2.9K, ../../[email protected]/2-v3-0003-Test-standby-is-requested.patch)
download | inline diff:
From cd32de9ec14dba0011f8c05e6a8ab7e4f7be045c Mon Sep 17 00:00:00 2001
From: Mikhail Litsarev <[email protected]>
Date: Thu, 13 Jun 2024 18:47:47 +0300
Subject: [PATCH] Tests for standby-is-requested mode.
Add tiny tests in src/test/recovery/t/004_timeline_switch.pl
They validate:
- master is not a replica
- standby_1 is a replica
- promoted replica in master mode
- standby_2 remains a replica after switch to promoted master
---
src/test/recovery/t/004_timeline_switch.pl | 25 ++++++++++++++++++++++
1 file changed, 25 insertions(+)
diff --git a/src/test/recovery/t/004_timeline_switch.pl b/src/test/recovery/t/004_timeline_switch.pl
index 684838cbab7..11f0b22ae90 100644
--- a/src/test/recovery/t/004_timeline_switch.pl
+++ b/src/test/recovery/t/004_timeline_switch.pl
@@ -16,6 +16,11 @@ my $node_primary = PostgreSQL::Test::Cluster->new('primary');
$node_primary->init(allows_streaming => 1);
$node_primary->start;
+# Validate pg_get_recovery_flags() for master
+my $ret_mode_primary = $node_primary->safe_psql('postgres',
+ 'SELECT pg_get_recovery_flags()');
+is($ret_mode_primary, '{}', "master is not a replica");
+
# Take backup
my $backup_name = 'my_backup';
$node_primary->backup($backup_name);
@@ -30,6 +35,12 @@ $node_standby_2->init_from_backup($node_primary, $backup_name,
has_streaming => 1);
$node_standby_2->start;
+# Validate standby-mode-requested state for replica node
+my $ret_mode_standby_1 = $node_standby_1->safe_psql('postgres',
+ 'SELECT pg_get_recovery_flags()');
+is($ret_mode_standby_1, '{STANDBY_MODE_REQUESTED}', "node_standby_1 is a replica");
+print($ret_mode_standby_1);
+
# Create some content on primary
$node_primary->safe_psql('postgres',
"CREATE TABLE tab_int AS SELECT generate_series(1,1000) AS a");
@@ -48,6 +59,15 @@ $node_standby_1->psql(
stdout => \$psql_out);
is($psql_out, 't', "promotion of standby with pg_promote");
+# Validate pg_get_recovery_flags() for master promoted from standby node.
+# STANDBY_MODE_REQUESTED is returned because standby.signal file
+# was found while being a replica.
+# Use it with pg_is_in_recovery() (will return false), for such use-cases.
+my $ret_mode_1 = $node_standby_1->safe_psql('postgres',
+ 'SELECT pg_get_recovery_flags()');
+is($ret_mode_1, '{PROMOTE_IS_TRIGGERED,STANDBY_MODE_REQUESTED}',
+ "node_standby_1 becomes a master");
+
# Switch standby 2 to replay from standby 1
my $connstr_1 = $node_standby_1->connstr;
$node_standby_2->append_conf(
@@ -56,6 +76,11 @@ primary_conninfo='$connstr_1'
));
$node_standby_2->restart;
+# Validate STANDBY_MODE_REQUESTED for second replica after restart
+my $ret_mode_standby_2 = $node_standby_2->safe_psql('postgres',
+ 'SELECT pg_get_recovery_flags()');
+is($ret_mode_standby_2, '{STANDBY_MODE_REQUESTED}', "node_standby_2 remains a replica");
+
# Insert some data in standby 1 and check its presence in standby 2
# to ensure that the timeline switch has been done.
$node_standby_1->safe_psql('postgres',
--
2.34.1
[text/x-diff] v3-0002-Text-array-sql-wrapper.patch (4.0K, ../../[email protected]/3-v3-0002-Text-array-sql-wrapper.patch)
download | inline diff:
From ac304f75d5f6f9bb9712ef4113da035ad74b7344 Mon Sep 17 00:00:00 2001
From: Mikhail Litsarev <[email protected]>
Date: Thu, 13 Jun 2024 18:37:13 +0300
Subject: [PATCH] Wrapper function to extract whole text array from the
SharedRecoveryDataFlags.
---
src/backend/access/transam/xlogfuncs.c | 31 +++++++++++++++++++++++
src/backend/access/transam/xlogrecovery.c | 17 +++++++++++++
src/include/access/xlogrecovery.h | 1 +
src/include/catalog/pg_proc.dat | 4 +++
4 files changed, 53 insertions(+)
diff --git a/src/backend/access/transam/xlogfuncs.c b/src/backend/access/transam/xlogfuncs.c
index 4e46baaebdf..9e752639aa4 100644
--- a/src/backend/access/transam/xlogfuncs.c
+++ b/src/backend/access/transam/xlogfuncs.c
@@ -29,6 +29,7 @@
#include "replication/walreceiver.h"
#include "storage/fd.h"
#include "storage/standby.h"
+#include "utils/array.h"
#include "utils/builtins.h"
#include "utils/memutils.h"
#include "utils/pg_lsn.h"
@@ -747,3 +748,33 @@ pg_promote(PG_FUNCTION_ARGS)
wait_seconds)));
PG_RETURN_BOOL(false);
}
+
+Datum
+pg_get_recovery_flags(PG_FUNCTION_ARGS)
+{
+/*
+ * Currently supported number of recovery flags is equal to 2:
+ * {XLR_PROMOTE_IS_TRIGGERED, XLR_STANDBY_MODE_REQUESTED}.
+ * It can be extended in future.
+ */
+#define MAX_RECOVERY_FLAGS 2
+
+ bits32 recovery_flags;
+ int cnt = 0;
+ Datum flags[MAX_RECOVERY_FLAGS];
+ ArrayType *txt_arr;
+
+ recovery_flags = GetXLogRecoveryFlags();
+
+ if (recovery_flags & XLR_PROMOTE_IS_TRIGGERED)
+ flags[cnt++] = CStringGetTextDatum("PROMOTE_IS_TRIGGERED");
+
+ if (recovery_flags & XLR_STANDBY_MODE_REQUESTED)
+ flags[cnt++] = CStringGetTextDatum("STANDBY_MODE_REQUESTED");
+
+ Assert(cnt <= MAX_RECOVERY_FLAGS);
+
+ /* Returns bit array as Datum */
+ txt_arr = construct_array_builtin(flags, cnt, TEXTOID);
+ PG_RETURN_ARRAYTYPE_P(txt_arr);
+}
diff --git a/src/backend/access/transam/xlogrecovery.c b/src/backend/access/transam/xlogrecovery.c
index de92f48e4ae..bd919732a56 100644
--- a/src/backend/access/transam/xlogrecovery.c
+++ b/src/backend/access/transam/xlogrecovery.c
@@ -4399,6 +4399,22 @@ StartupRequestWalReceiverRestart(void)
}
}
+/*
+ * Return flags for recovery states.
+ *
+ * Please, see description of
+ * XLR_PROMOTE_IS_TRIGGERED and XLR_STANDBY_MODE_REQUESTED.
+ */
+bits32 GetXLogRecoveryFlags(void)
+{
+ bits32 flags;
+
+ SpinLockAcquire(&XLogRecoveryCtl->info_lck);
+ flags = XLogRecoveryCtl->SharedRecoveryDataFlags;
+ SpinLockRelease(&XLogRecoveryCtl->info_lck);
+
+ return flags;
+}
/*
* Has a standby promotion already been triggered?
@@ -4551,6 +4567,7 @@ HotStandbyActiveInReplay(void)
return (LocalRecoveryDataFlags & XLR_HOT_STANDBY_ACTIVE);
}
+
/*
* Get latest redo apply position.
*
diff --git a/src/include/access/xlogrecovery.h b/src/include/access/xlogrecovery.h
index 2cb56fc365f..40487de1846 100644
--- a/src/include/access/xlogrecovery.h
+++ b/src/include/access/xlogrecovery.h
@@ -165,6 +165,7 @@ extern TimestampTz GetLatestXTime(void);
extern TimestampTz GetCurrentChunkReplayStartTime(void);
extern XLogRecPtr GetCurrentReplayRecPtr(TimeLineID *replayEndTLI);
+extern bits32 GetXLogRecoveryFlags(void);
extern bool PromoteIsTriggered(void);
extern bool CheckPromoteSignal(void);
extern void WakeupRecovery(void);
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index 6a5476d3c4c..7b199780c01 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -6520,6 +6520,10 @@
{ oid => '3810', descr => 'true if server is in recovery',
proname => 'pg_is_in_recovery', provolatile => 'v', prorettype => 'bool',
proargtypes => '', prosrc => 'pg_is_in_recovery' },
+{ oid => '8439',
+ descr => 'return flags for recovery states',
+ proname => 'pg_get_recovery_flags', provolatile => 'v', prorettype => '_text',
+ proargtypes => '', prosrc => 'pg_get_recovery_flags' },
{ oid => '3820', descr => 'current wal flush location',
proname => 'pg_last_wal_receive_lsn', provolatile => 'v',
--
2.34.1
[text/x-diff] v3-0001-Standby-mode-requested.patch (8.2K, ../../[email protected]/4-v3-0001-Standby-mode-requested.patch)
download | inline diff:
From 23e23dd4c0b1c4c69021a4f2bf95586f39d8bd1f Mon Sep 17 00:00:00 2001
From: Mikhail Litsarev <[email protected]>
Date: Mon, 6 May 2024 15:23:52 +0300
Subject: [PATCH] Replace recovery boolean flags with a bits32 set.
Replace local and shared-memory flags (Local/Shared)HotStandbyActive,
(Local/Shared)PromoteIsTriggered with corresponding
(Local/Shared)RecoveryDataFlags.
Introduce XLR_STANDBY_MODE_REQUESTED state which indicates
that a node is in a standby mode at start, while recovery mode is on
(standby.signal file was found at start up).
---
src/backend/access/transam/xlogrecovery.c | 89 ++++++++++++++---------
src/include/access/xlogrecovery.h | 21 ++++++
2 files changed, 76 insertions(+), 34 deletions(-)
diff --git a/src/backend/access/transam/xlogrecovery.c b/src/backend/access/transam/xlogrecovery.c
index b45b8331720..de92f48e4ae 100644
--- a/src/backend/access/transam/xlogrecovery.c
+++ b/src/backend/access/transam/xlogrecovery.c
@@ -170,16 +170,22 @@ static XLogRecPtr RedoStartLSN = InvalidXLogRecPtr;
static TimeLineID RedoStartTLI = 0;
/*
- * Local copy of SharedHotStandbyActive variable. False actually means "not
- * known, need to check the shared state".
- */
-static bool LocalHotStandbyActive = false;
-
-/*
- * Local copy of SharedPromoteIsTriggered variable. False actually means "not
- * known, need to check the shared state".
+ * This bit array is introduced to keep the local copies of RecoveryDataFlags
+ * in corresponding SharedRecoveryDataFlags bitset.
+ *
+ * Currently it provides the following states:
+ *
+ * -- Local copy of XLR_HOT_STANDBY_ACTIVE flag. False actually means "not
+ * known, need to check the shared state.
+ *
+ * -- Local copy of XLR_PROMOTE_IS_TRIGGERED flag. False actually means "not
+ * known, need to check the shared state".
+ *
+ * -- XLR_STANDBY_MODE_REQUESTED is not mirrored here.
+ *
+ * This bitset can be extended in future.
*/
-static bool LocalPromoteIsTriggered = false;
+static bits32 LocalRecoveryDataFlags;
/* Has the recovery code requested a walreceiver wakeup? */
static bool doRequestWalReceiverReply;
@@ -297,23 +303,26 @@ bool reachedConsistency = false;
static char *replay_image_masked = NULL;
static char *primary_image_masked = NULL;
-
/*
* Shared-memory state for WAL recovery.
*/
typedef struct XLogRecoveryCtlData
{
/*
- * SharedHotStandbyActive indicates if we allow hot standby queries to be
- * run. Protected by info_lck.
- */
- bool SharedHotStandbyActive;
-
- /*
- * SharedPromoteIsTriggered indicates if a standby promotion has been
- * triggered. Protected by info_lck.
+ * This bit array is introduced to keep the following states:
+ *
+ * -- XLR_HOT_STANDBY_ACTIVE indicates if we allow hot standby queries
+ * to be run. Protected by info_lck.
+ *
+ * -- XLR_PROMOTE_IS_TRIGGERED indicates if a standby promotion
+ * has been triggered. Protected by info_lck.
+ *
+ * -- XLR_STANDBY_MODE_REQUESTED indicates if we're in a standby mode
+ * at start, while recovery mode is on. No info_lck protection.
+ *
+ * and can be extended in future.
*/
- bool SharedPromoteIsTriggered;
+ bits32 SharedRecoveryDataFlags;
/*
* recoveryWakeupLatch is used to wake up the startup process to continue
@@ -1082,10 +1091,17 @@ readRecoverySignalFile(void)
StandbyModeRequested = false;
ArchiveRecoveryRequested = false;
+ /*
+ * There is no need to use Spinlock here because only the startup
+ * process modifies the SharedRecoveryDataFlags bit here and
+ * no other processes are reading it at that time.
+ */
+ XLogRecoveryCtl->SharedRecoveryDataFlags &= ~XLR_STANDBY_MODE_REQUESTED;
if (standby_signal_file_found)
{
StandbyModeRequested = true;
ArchiveRecoveryRequested = true;
+ XLogRecoveryCtl->SharedRecoveryDataFlags |= XLR_STANDBY_MODE_REQUESTED;
}
else if (recovery_signal_file_found)
{
@@ -2254,15 +2270,15 @@ CheckRecoveryConsistency(void)
* enabling connections.
*/
if (standbyState == STANDBY_SNAPSHOT_READY &&
- !LocalHotStandbyActive &&
+ !(LocalRecoveryDataFlags & XLR_HOT_STANDBY_ACTIVE) &&
reachedConsistency &&
IsUnderPostmaster)
{
SpinLockAcquire(&XLogRecoveryCtl->info_lck);
- XLogRecoveryCtl->SharedHotStandbyActive = true;
+ XLogRecoveryCtl->SharedRecoveryDataFlags |= XLR_HOT_STANDBY_ACTIVE;
SpinLockRelease(&XLogRecoveryCtl->info_lck);
- LocalHotStandbyActive = true;
+ LocalRecoveryDataFlags |= XLR_HOT_STANDBY_ACTIVE;
SendPostmasterSignal(PMSIGNAL_BEGIN_HOT_STANDBY);
}
@@ -2925,11 +2941,11 @@ static void
recoveryPausesHere(bool endOfRecovery)
{
/* Don't pause unless users can connect! */
- if (!LocalHotStandbyActive)
+ if (!(LocalRecoveryDataFlags & XLR_HOT_STANDBY_ACTIVE))
return;
/* Don't pause after standby promotion has been triggered */
- if (LocalPromoteIsTriggered)
+ if (LocalRecoveryDataFlags & XLR_PROMOTE_IS_TRIGGERED)
return;
if (endOfRecovery)
@@ -4398,21 +4414,23 @@ PromoteIsTriggered(void)
* triggered. We can't trigger a promotion again, so there's no need to
* keep checking after the shared variable has once been seen true.
*/
- if (LocalPromoteIsTriggered)
+ if (LocalRecoveryDataFlags & XLR_PROMOTE_IS_TRIGGERED)
return true;
SpinLockAcquire(&XLogRecoveryCtl->info_lck);
- LocalPromoteIsTriggered = XLogRecoveryCtl->SharedPromoteIsTriggered;
+ LocalRecoveryDataFlags &= ~XLR_PROMOTE_IS_TRIGGERED;
+ LocalRecoveryDataFlags |=
+ (XLogRecoveryCtl->SharedRecoveryDataFlags & XLR_PROMOTE_IS_TRIGGERED);
SpinLockRelease(&XLogRecoveryCtl->info_lck);
- return LocalPromoteIsTriggered;
+ return (LocalRecoveryDataFlags & XLR_PROMOTE_IS_TRIGGERED);
}
static void
SetPromoteIsTriggered(void)
{
SpinLockAcquire(&XLogRecoveryCtl->info_lck);
- XLogRecoveryCtl->SharedPromoteIsTriggered = true;
+ XLogRecoveryCtl->SharedRecoveryDataFlags |= XLR_PROMOTE_IS_TRIGGERED;
SpinLockRelease(&XLogRecoveryCtl->info_lck);
/*
@@ -4423,7 +4441,7 @@ SetPromoteIsTriggered(void)
*/
SetRecoveryPause(false);
- LocalPromoteIsTriggered = true;
+ LocalRecoveryDataFlags |= XLR_PROMOTE_IS_TRIGGERED;
}
/*
@@ -4432,7 +4450,7 @@ SetPromoteIsTriggered(void)
static bool
CheckForStandbyTrigger(void)
{
- if (LocalPromoteIsTriggered)
+ if (LocalRecoveryDataFlags & XLR_PROMOTE_IS_TRIGGERED)
return true;
if (IsPromoteSignaled() && CheckPromoteSignal())
@@ -4506,16 +4524,18 @@ HotStandbyActive(void)
* can't de-activate Hot Standby, so there's no need to keep checking
* after the shared variable has once been seen true.
*/
- if (LocalHotStandbyActive)
+ if (LocalRecoveryDataFlags & XLR_HOT_STANDBY_ACTIVE)
return true;
else
{
/* spinlock is essential on machines with weak memory ordering! */
SpinLockAcquire(&XLogRecoveryCtl->info_lck);
- LocalHotStandbyActive = XLogRecoveryCtl->SharedHotStandbyActive;
+ LocalRecoveryDataFlags &= ~XLR_HOT_STANDBY_ACTIVE;
+ LocalRecoveryDataFlags |=
+ (XLogRecoveryCtl->SharedRecoveryDataFlags & XLR_HOT_STANDBY_ACTIVE);
SpinLockRelease(&XLogRecoveryCtl->info_lck);
- return LocalHotStandbyActive;
+ return LocalRecoveryDataFlags & XLR_HOT_STANDBY_ACTIVE;
}
}
@@ -4527,7 +4547,8 @@ static bool
HotStandbyActiveInReplay(void)
{
Assert(AmStartupProcess() || !IsPostmasterEnvironment);
- return LocalHotStandbyActive;
+
+ return (LocalRecoveryDataFlags & XLR_HOT_STANDBY_ACTIVE);
}
/*
diff --git a/src/include/access/xlogrecovery.h b/src/include/access/xlogrecovery.h
index c423464e8bc..2cb56fc365f 100644
--- a/src/include/access/xlogrecovery.h
+++ b/src/include/access/xlogrecovery.h
@@ -16,6 +16,27 @@
#include "lib/stringinfo.h"
#include "utils/timestamp.h"
+/*
+ * The flag indicates if we allow hot standby queries to be run.
+ * Protected by info_lck.
+ */
+#define XLR_HOT_STANDBY_ACTIVE 0x01
+/*
+ * The flag indicates if a standby promotion has been triggered.
+ * Protected by info_lck.
+ */
+#define XLR_PROMOTE_IS_TRIGGERED 0x02
+/*
+ * The flag indicates if we're in a standby mode at start,
+ * while recovery mode is on.
+ * It is introduced to distinguish a replica from a regular instance
+ * in a Point In Time Recovery (PITR) mode.
+ *
+ * It is selected if standby.signal file is found at startup process
+ * It is skipped otherwise.
+ */
+#define XLR_STANDBY_MODE_REQUESTED 0x04
+
/*
* Recovery target type.
* Only set during a Point in Time recovery, not when in standby mode.
--
2.34.1
^ permalink raw reply [nested|flat] 6+ messages in thread
* Re: SQL function which allows to distinguish a server being in point in time recovery mode and an ordinary replica
2024-05-08 04:24 Re: SQL function which allows to distinguish a server being in point in time recovery mode and an ordinary replica Michael Paquier <[email protected]>
2024-06-13 18:07 ` Re: SQL function which allows to distinguish a server being in point in time recovery mode and an ordinary replica [email protected]
@ 2024-06-14 04:51 ` Michael Paquier <[email protected]>
2025-01-10 20:39 ` Re: SQL function which allows to distinguish a server being in point in time recovery mode and an ordinary replica [email protected]
0 siblings, 1 reply; 6+ messages in thread
From: Michael Paquier @ 2024-06-14 04:51 UTC (permalink / raw)
To: [email protected]; +Cc: [email protected]
On Thu, Jun 13, 2024 at 09:07:42PM +0300, [email protected] wrote:
> Hi!
>
> Michael,
> I have fixed the patches according to your comments.
>
> > merge both local variables into a single bits32 store?
> This is done in v3-0001-Standby-mode-requested.patch
>
> > Then this could be used with a function that returns a
> > text[] array with all the states retrieved?
> Placed this in the v3-0002-Text-array-sql-wrapper.patch
>
> > The refactoring pieces and the function pieces should be split, for
> > clarity.
> Sure. I also added the third patch with some tests. Perhaps it would be
> usefull.
+ * -- XLR_PROMOTE_IS_TRIGGERED indicates if a standby promotion
+ * has been triggered. Protected by info_lck.
+ *
+ * -- XLR_STANDBY_MODE_REQUESTED indicates if we're in a standby mode
+ * at start, while recovery mode is on. No info_lck protection.
+ *
+ * and can be extended in future.
This comment is incorrect for XLR_STANDBY_MODE_REQUESTED? A startup
we would unlikely be in standby mode, most likely in crash recovery,
then switch to standby mode.
- LocalPromoteIsTriggered = XLogRecoveryCtl->SharedPromoteIsTriggered;
+ LocalRecoveryDataFlags &= ~XLR_PROMOTE_IS_TRIGGERED;
+ LocalRecoveryDataFlags |=
+ (XLogRecoveryCtl->SharedRecoveryDataFlags & XLR_PROMOTE_IS_TRIGGERED)
Are these complications really needed? All these flags are false,
then switched to true. true -> false is not possible.
StandbyModeRequested = true;
ArchiveRecoveryRequested = true;
+ XLogRecoveryCtl->SharedRecoveryDataFlags |= XLR_STANDBY_MODE_REQUESTED;
Shouldn't STANDBY_MODE be only used in the local flag, as well as an
ARCHIVE_RECOVERY_REQUESTED? It looks like this could push a bit more
forward the removal of more of these booleans, with a bit more work..
return (LocalRecoveryDataFlags & XLR_HOT_STANDBY_ACTIVE);
}
+
/*
Some noise lying around.
+ /* Returns bit array as Datum */
+ txt_arr = construct_array_builtin(flags, cnt, TEXTOID);
Yep, that's the correct way to do it.
+is($ret_mode_primary, '{}', "master is not a replica");
The test additions are welcome. Note that we avoid the word "master",
see 229f8c219f8f.
--
Michael
Attachments:
[application/pgp-signature] signature.asc (833B, ../../[email protected]/2-signature.asc)
download
^ permalink raw reply [nested|flat] 6+ messages in thread
* Re: SQL function which allows to distinguish a server being in point in time recovery mode and an ordinary replica
2024-05-08 04:24 Re: SQL function which allows to distinguish a server being in point in time recovery mode and an ordinary replica Michael Paquier <[email protected]>
2024-06-13 18:07 ` Re: SQL function which allows to distinguish a server being in point in time recovery mode and an ordinary replica [email protected]
2024-06-14 04:51 ` Re: SQL function which allows to distinguish a server being in point in time recovery mode and an ordinary replica Michael Paquier <[email protected]>
@ 2025-01-10 20:39 ` [email protected]
2025-02-28 13:41 ` Re: SQL function which allows to distinguish a server being in point in time recovery mode and an ordinary replica [email protected]
0 siblings, 1 reply; 6+ messages in thread
From: [email protected] @ 2025-01-10 20:39 UTC (permalink / raw)
To: Michael Paquier <[email protected]>; +Cc: [email protected]
Hi!
Michael, sorry for such a long time to deliver next version of the patch
from my side.
In this version I have fixed all your propositions, hopefully correct.
There is one point that I would like to emphasize, namely
> Shouldn't STANDBY_MODE be only used in the local flag, as well as an
> ARCHIVE_RECOVERY_REQUESTED? It looks like this could push a bit more
> forward the removal of more of these booleans, with a bit more work..
I made corresponding changes, but given that these three variables
bool ArchiveRecoveryRequested;
bool InArchiveRecovery;
bool StandbyMode;
are used in other units, and (if I understand correctly) we decided to
move them in one localRecoveryFlags bitset too,
I changed their extern calls to boolean functions calls instead of
extern variables.
> The test additions are welcome.
My test additions were based on copy of StandbyModeRequested placed in
shared memory
even the startup process is done. With current implementation they seems
to be not very usefull now.
Respectfully,
Mikhail Litsarev,
Postgres Professional: https://postgrespro.com
Attachments:
[text/x-diff] v4-0001-Standby-mode-requested.patch (31.7K, ../../[email protected]/2-v4-0001-Standby-mode-requested.patch)
download | inline diff:
From eaf661c022f82217d33cfdb3776c69675f82ac67 Mon Sep 17 00:00:00 2001
From: Mikhail Litsarev <[email protected]>
Date: Fri, 10 Jan 2025 21:23:02 +0300
Subject: [PATCH] Replace recovery boolean flags with a bits32 set.
Move local booleans ArchiveRecoveryRequested, InArchiveRecovery,
StandbyModeRequested, StandbyMode, LocalHotStandbyActive,
LocalPromoteIsTriggered into localRecoveryFlags bitset.
Move SharedHotStandbyActive, SharedPromoteIsTriggered members of
XLogRecoveryCtlData into sharedRecoveryFlags bitset.
Refactor code according to the changes.
---
src/backend/access/transam/timeline.c | 6 +-
src/backend/access/transam/xlog.c | 26 +--
src/backend/access/transam/xlogarchive.c | 4 +-
src/backend/access/transam/xlogrecovery.c | 221 ++++++++++-----------
src/backend/replication/logical/slotsync.c | 2 +-
src/include/access/xlog_internal.h | 7 +-
src/include/access/xlogrecovery.h | 34 +++-
7 files changed, 161 insertions(+), 139 deletions(-)
diff --git a/src/backend/access/transam/timeline.c b/src/backend/access/transam/timeline.c
index a27f27cc037..c9f53c4b667 100644
--- a/src/backend/access/transam/timeline.c
+++ b/src/backend/access/transam/timeline.c
@@ -93,7 +93,7 @@ readTimeLineHistory(TimeLineID targetTLI)
return list_make1(entry);
}
- if (ArchiveRecoveryRequested)
+ if (ArchiveRecoveryRequested())
{
TLHistoryFileName(histfname, targetTLI);
fromArchive =
@@ -229,7 +229,7 @@ existsTimeLineHistory(TimeLineID probeTLI)
if (probeTLI == 1)
return false;
- if (ArchiveRecoveryRequested)
+ if (ArchiveRecoveryRequested())
{
TLHistoryFileName(histfname, probeTLI);
RestoreArchivedFile(path, histfname, "RECOVERYHISTORY", 0, false);
@@ -331,7 +331,7 @@ writeTimeLineHistory(TimeLineID newTLI, TimeLineID parentTLI,
/*
* If a history file exists for the parent, copy it verbatim
*/
- if (ArchiveRecoveryRequested)
+ if (ArchiveRecoveryRequested())
{
TLHistoryFileName(histfname, parentTLI);
RestoreArchivedFile(path, histfname, "RECOVERYHISTORY", 0, false);
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index bf3dbda901d..2d6615d94d0 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -5388,7 +5388,7 @@ CheckRequiredParameterValues(void)
* For archive recovery, the WAL must be generated with at least 'replica'
* wal_level.
*/
- if (ArchiveRecoveryRequested && ControlFile->wal_level == WAL_LEVEL_MINIMAL)
+ if (ArchiveRecoveryRequested() && ControlFile->wal_level == WAL_LEVEL_MINIMAL)
{
ereport(FATAL,
(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
@@ -5401,7 +5401,7 @@ CheckRequiredParameterValues(void)
* For Hot Standby, the WAL must be generated with 'replica' mode, and we
* must have at least as many backend slots as the primary.
*/
- if (ArchiveRecoveryRequested && EnableHotStandby)
+ if (ArchiveRecoveryRequested() && EnableHotStandby)
{
/* We ignore autovacuum_worker_slots when we make this test. */
RecoveryRequiresIntParameter("max_connections",
@@ -5561,8 +5561,8 @@ StartupXLOG(void)
*
* InitWalRecovery analyzes the control file and the backup label file, if
* any. It updates the in-memory ControlFile buffer according to the
- * starting checkpoint, and sets InRecovery and ArchiveRecoveryRequested.
- * It also applies the tablespace map file, if any.
+ * starting checkpoint, and sets SX_ARCHIVE_RECOVERY_REQUESTED and
+ * InRecovery. It also applies the tablespace map file, if any.
*/
InitWalRecovery(ControlFile, &wasShutdown,
&haveBackupLabel, &haveTblspcMap);
@@ -5694,7 +5694,7 @@ StartupXLOG(void)
{
/* Initialize state for RecoveryInProgress() */
SpinLockAcquire(&XLogCtl->info_lck);
- if (InArchiveRecovery)
+ if (InArchiveRecovery())
XLogCtl->SharedRecoveryState = RECOVERY_STATE_ARCHIVE;
else
XLogCtl->SharedRecoveryState = RECOVERY_STATE_CRASH;
@@ -5747,7 +5747,7 @@ StartupXLOG(void)
* startup process to think that there are still invalid page
* references when checking for data consistency.
*/
- if (InArchiveRecovery)
+ if (InArchiveRecovery())
{
LocalMinRecoveryPoint = ControlFile->minRecoveryPoint;
LocalMinRecoveryPointTLI = ControlFile->minRecoveryPointTLI;
@@ -5781,7 +5781,7 @@ StartupXLOG(void)
* control file and we've established a recovery snapshot from a
* running-xacts WAL record.
*/
- if (ArchiveRecoveryRequested && EnableHotStandby)
+ if (ArchiveRecoveryRequested() && EnableHotStandby)
{
TransactionId *xids;
int nxids;
@@ -5894,7 +5894,7 @@ StartupXLOG(void)
* recover from an online backup but never called pg_backup_stop(), or
* you didn't archive all the WAL needed.
*/
- if (ArchiveRecoveryRequested || ControlFile->backupEndRequired)
+ if (ArchiveRecoveryRequested() || ControlFile->backupEndRequired)
{
if (!XLogRecPtrIsInvalid(ControlFile->backupStartPoint) || ControlFile->backupEndRequired)
ereport(FATAL,
@@ -5946,7 +5946,7 @@ StartupXLOG(void)
* In a normal crash recovery, we can just extend the timeline we were in.
*/
newTLI = endOfRecoveryInfo->lastRecTLI;
- if (ArchiveRecoveryRequested)
+ if (ArchiveRecoveryRequested())
{
newTLI = findNewestTimeLine(recoveryTargetTLI) + 1;
ereport(LOG,
@@ -6139,7 +6139,7 @@ StartupXLOG(void)
XLogReportParameters();
/* If this is archive recovery, perform post-recovery cleanup actions. */
- if (ArchiveRecoveryRequested)
+ if (ArchiveRecoveryRequested())
CleanupAfterArchiveRecovery(EndOfLogTLI, EndOfLog, newTLI);
/*
@@ -6298,7 +6298,7 @@ PerformRecoveryXLogAction(void)
* of a full checkpoint. A checkpoint is requested later, after we're
* fully out of recovery mode and already accepting queries.
*/
- if (ArchiveRecoveryRequested && IsUnderPostmaster &&
+ if (ArchiveRecoveryRequested() && IsUnderPostmaster &&
PromoteIsTriggered())
{
promoted = true;
@@ -8292,7 +8292,7 @@ xlog_redo(XLogReaderState *record)
* record, the backup was canceled and the end-of-backup record will
* never arrive.
*/
- if (ArchiveRecoveryRequested &&
+ if (ArchiveRecoveryRequested() &&
!XLogRecPtrIsInvalid(ControlFile->backupStartPoint) &&
XLogRecPtrIsInvalid(ControlFile->backupEndPoint))
ereport(PANIC,
@@ -8533,7 +8533,7 @@ xlog_redo(XLogReaderState *record)
* local copies cannot be updated as long as crash recovery is
* happening and we expect all the WAL to be replayed.
*/
- if (InArchiveRecovery)
+ if (InArchiveRecovery())
{
LocalMinRecoveryPoint = ControlFile->minRecoveryPoint;
LocalMinRecoveryPointTLI = ControlFile->minRecoveryPointTLI;
diff --git a/src/backend/access/transam/xlogarchive.c b/src/backend/access/transam/xlogarchive.c
index 1ef1713c91a..ad379acc30a 100644
--- a/src/backend/access/transam/xlogarchive.c
+++ b/src/backend/access/transam/xlogarchive.c
@@ -68,7 +68,7 @@ RestoreArchivedFile(char *path, const char *xlogfname,
* Ignore restore_command when not in archive recovery (meaning we are in
* crash recovery).
*/
- if (!ArchiveRecoveryRequested)
+ if (!ArchiveRecoveryRequested())
goto not_available;
/* In standby mode, restore_command might not be supplied */
@@ -205,7 +205,7 @@ RestoreArchivedFile(char *path, const char *xlogfname,
* incorrectly conclude we've reached the end of WAL and we're
* done recovering ...
*/
- if (StandbyMode && stat_buf.st_size < expectedSize)
+ if (InStandbyMode() && stat_buf.st_size < expectedSize)
elevel = DEBUG1;
else
elevel = FATAL;
diff --git a/src/backend/access/transam/xlogrecovery.c b/src/backend/access/transam/xlogrecovery.c
index 0bbe2eea206..e75c7891fd5 100644
--- a/src/backend/access/transam/xlogrecovery.c
+++ b/src/backend/access/transam/xlogrecovery.c
@@ -123,30 +123,7 @@ TimeLineID recoveryTargetTLI = 0;
static List *expectedTLEs;
static TimeLineID curFileTLI;
-/*
- * When ArchiveRecoveryRequested is set, archive recovery was requested,
- * ie. signal files were present. When InArchiveRecovery is set, we are
- * currently recovering using offline XLOG archives. These variables are only
- * valid in the startup process.
- *
- * When ArchiveRecoveryRequested is true, but InArchiveRecovery is false, we're
- * currently performing crash recovery using only XLOG files in pg_wal, but
- * will switch to using offline XLOG archives as soon as we reach the end of
- * WAL in pg_wal.
- */
-bool ArchiveRecoveryRequested = false;
-bool InArchiveRecovery = false;
-
-/*
- * When StandbyModeRequested is set, standby mode was requested, i.e.
- * standby.signal file was present. When StandbyMode is set, we are currently
- * in standby mode. These variables are only valid in the startup process.
- * They work similarly to ArchiveRecoveryRequested and InArchiveRecovery.
- */
-static bool StandbyModeRequested = false;
-bool StandbyMode = false;
-
-/* was a signal file present at startup? */
+/* Was a signal file present at startup? */
static bool standby_signal_file_found = false;
static bool recovery_signal_file_found = false;
@@ -170,16 +147,19 @@ static XLogRecPtr RedoStartLSN = InvalidXLogRecPtr;
static TimeLineID RedoStartTLI = 0;
/*
- * Local copy of SharedHotStandbyActive variable. False actually means "not
- * known, need to check the shared state".
- */
-static bool LocalHotStandbyActive = false;
-
-/*
- * Local copy of SharedPromoteIsTriggered variable. False actually means "not
- * known, need to check the shared state".
+ * Local flags:
+ * SX_ARCHIVE_RECOVERY_REQUESTED
+ * SX_IN_ARCHIVE_RECOVERY
+ * SX_STANDBY_MODE_REQUESTED
+ * SX_IN_STANDBY_MODE
+ *
+ * and local copies of sharedRecoveryFlags:
+ * SX_HOT_STANDBY_ACTIVE,
+ * SX_PROMOTE_IS_TRIGGERED.
+ * If some flag is not set, that actually means "not known, need to check
+ * the shared state".
*/
-static bool LocalPromoteIsTriggered = false;
+static bits32 localRecoveryFlags = 0;
/* Has the recovery code requested a walreceiver wakeup? */
static bool doRequestWalReceiverReply;
@@ -297,23 +277,16 @@ bool reachedConsistency = false;
static char *replay_image_masked = NULL;
static char *primary_image_masked = NULL;
-
/*
* Shared-memory state for WAL recovery.
*/
typedef struct XLogRecoveryCtlData
{
/*
- * SharedHotStandbyActive indicates if we allow hot standby queries to be
- * run. Protected by info_lck.
+ * The bit array stores the following states
+ * SX_HOT_STANDBY_ACTIVE, SX_PROMOTE_IS_TRIGGERED. Protected by info_lck.
*/
- bool SharedHotStandbyActive;
-
- /*
- * SharedPromoteIsTriggered indicates if a standby promotion has been
- * triggered. Protected by info_lck.
- */
- bool SharedPromoteIsTriggered;
+ bits32 sharedRecoveryFlags;
/*
* recoveryWakeupLatch is used to wake up the startup process to continue
@@ -440,6 +413,7 @@ static bool HotStandbyActiveInReplay(void);
static void SetCurrentChunkStartTime(TimestampTz xtime);
static void SetLatestXTime(TimestampTz xtime);
+static bool StandbyModeRequested(void);
/*
* Initialization of shared memory for WAL recovery
*/
@@ -477,7 +451,7 @@ XLogRecoveryShmemInit(void)
static void
EnableStandbyMode(void)
{
- StandbyMode = true;
+ localRecoveryFlags |= SX_IN_STANDBY_MODE;
/*
* To avoid server log bloat, we don't report recovery progress in a
@@ -505,8 +479,8 @@ EnableStandbyMode(void)
* disk does after initializing other subsystems, but before calling
* PerformWalRecovery().
*
- * This initializes some global variables like ArchiveRecoveryRequested, and
- * StandbyModeRequested and InRecovery.
+ * This initializes some flags like SX_ARCHIVE_RECOVERY_REQUESTED and
+ * SX_STABDBY_MODE_REQUESTED and global variable InRecovery.
*/
void
InitWalRecovery(ControlFileData *ControlFile, bool *wasShutdown_ptr,
@@ -544,7 +518,7 @@ InitWalRecovery(ControlFileData *ControlFile, bool *wasShutdown_ptr,
* Take ownership of the wakeup latch if we're going to sleep during
* recovery, if required.
*/
- if (ArchiveRecoveryRequested)
+ if (ArchiveRecoveryRequested())
OwnLatch(&XLogRecoveryCtl->recoveryWakeupLatch);
/*
@@ -599,8 +573,8 @@ InitWalRecovery(ControlFileData *ControlFile, bool *wasShutdown_ptr,
* file, we know how far we need to replay to reach consistency. Enter
* archive recovery directly.
*/
- InArchiveRecovery = true;
- if (StandbyModeRequested)
+ localRecoveryFlags |= SX_IN_ARCHIVE_RECOVERY;
+ if (StandbyModeRequested())
EnableStandbyMode();
/*
@@ -749,14 +723,14 @@ InitWalRecovery(ControlFileData *ControlFile, bool *wasShutdown_ptr,
* to minRecoveryPoint, up to backupEndPoint, or until we see an
* end-of-backup record), and we can enter archive recovery directly.
*/
- if (ArchiveRecoveryRequested &&
+ if (ArchiveRecoveryRequested() &&
(ControlFile->minRecoveryPoint != InvalidXLogRecPtr ||
ControlFile->backupEndRequired ||
ControlFile->backupEndPoint != InvalidXLogRecPtr ||
ControlFile->state == DB_SHUTDOWNED))
{
- InArchiveRecovery = true;
- if (StandbyModeRequested)
+ localRecoveryFlags |= SX_IN_ARCHIVE_RECOVERY;
+ if (StandbyModeRequested())
EnableStandbyMode();
}
@@ -799,9 +773,9 @@ InitWalRecovery(ControlFileData *ControlFile, bool *wasShutdown_ptr,
wasShutdown = ((record->xl_info & ~XLR_INFO_MASK) == XLOG_CHECKPOINT_SHUTDOWN);
}
- if (ArchiveRecoveryRequested)
+ if (ArchiveRecoveryRequested())
{
- if (StandbyModeRequested)
+ if (StandbyModeRequested())
ereport(LOG,
(errmsg("entering standby mode")));
else if (recoveryTarget == RECOVERY_TARGET_XID)
@@ -911,7 +885,7 @@ InitWalRecovery(ControlFileData *ControlFile, bool *wasShutdown_ptr,
}
else if (ControlFile->state != DB_SHUTDOWNED)
InRecovery = true;
- else if (ArchiveRecoveryRequested)
+ else if (ArchiveRecoveryRequested())
{
/* force recovery due to presence of recovery signal file */
InRecovery = true;
@@ -928,7 +902,7 @@ InitWalRecovery(ControlFileData *ControlFile, bool *wasShutdown_ptr,
*/
if (InRecovery)
{
- if (InArchiveRecovery)
+ if (InArchiveRecovery())
{
ControlFile->state = DB_IN_ARCHIVE_RECOVERY;
}
@@ -947,7 +921,7 @@ InitWalRecovery(ControlFileData *ControlFile, bool *wasShutdown_ptr,
}
ControlFile->checkPoint = CheckPointLoc;
ControlFile->checkPointCopy = checkPoint;
- if (InArchiveRecovery)
+ if (InArchiveRecovery())
{
/* initialize minRecoveryPoint if not set yet */
if (ControlFile->minRecoveryPoint < checkPoint.redo)
@@ -994,7 +968,7 @@ InitWalRecovery(ControlFileData *ControlFile, bool *wasShutdown_ptr,
backupStartPoint = ControlFile->backupStartPoint;
backupEndRequired = ControlFile->backupEndRequired;
backupEndPoint = ControlFile->backupEndPoint;
- if (InArchiveRecovery)
+ if (InArchiveRecovery())
{
minRecoveryPoint = ControlFile->minRecoveryPoint;
minRecoveryPointTLI = ControlFile->minRecoveryPointTLI;
@@ -1080,17 +1054,16 @@ readRecoverySignalFile(void)
recovery_signal_file_found = true;
}
- StandbyModeRequested = false;
- ArchiveRecoveryRequested = false;
+ localRecoveryFlags &= ~SX_STANDBY_MODE_REQUESTED;
+ localRecoveryFlags &= ~SX_ARCHIVE_RECOVERY_REQUESTED;
if (standby_signal_file_found)
{
- StandbyModeRequested = true;
- ArchiveRecoveryRequested = true;
+ localRecoveryFlags |= SX_STANDBY_MODE_REQUESTED;
+ localRecoveryFlags |= SX_ARCHIVE_RECOVERY_REQUESTED;
}
else if (recovery_signal_file_found)
{
- StandbyModeRequested = false;
- ArchiveRecoveryRequested = true;
+ localRecoveryFlags |= SX_ARCHIVE_RECOVERY_REQUESTED;
}
else
return;
@@ -1099,7 +1072,7 @@ readRecoverySignalFile(void)
* We don't support standby mode in standalone backends; that requires
* other processes such as the WAL receiver to be alive.
*/
- if (StandbyModeRequested && !IsUnderPostmaster)
+ if (StandbyModeRequested() && !IsUnderPostmaster)
ereport(FATAL,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("standby mode is not supported by single-user servers")));
@@ -1108,13 +1081,13 @@ readRecoverySignalFile(void)
static void
validateRecoveryParameters(void)
{
- if (!ArchiveRecoveryRequested)
+ if (!ArchiveRecoveryRequested())
return;
/*
* Check for compulsory parameters
*/
- if (StandbyModeRequested)
+ if (StandbyModeRequested())
{
if ((PrimaryConnInfo == NULL || strcmp(PrimaryConnInfo, "") == 0) &&
(recoveryRestoreCommand == NULL || strcmp(recoveryRestoreCommand, "") == 0))
@@ -1155,8 +1128,8 @@ validateRecoveryParameters(void)
/*
* If user specified recovery_target_timeline, validate it or compute the
* "latest" value. We can't do this until after we've gotten the restore
- * command and set InArchiveRecovery, because we need to fetch timeline
- * history files from the archive.
+ * command and set SX_IN_ARCHIVE_RECOVERY, because we need to fetch
+ * timeline history files from the archive.
*/
if (recoveryTargetTimeLineGoal == RECOVERY_TARGET_TIMELINE_NUMERIC)
{
@@ -1494,7 +1467,7 @@ FinishWalRecovery(void)
* i.e., calling XLogShutdownWalRcv().
*/
Assert(!WalRcvStreaming());
- StandbyMode = false;
+ localRecoveryFlags &= ~SX_IN_STANDBY_MODE;
/*
* Determine where to start writing WAL next.
@@ -1532,7 +1505,7 @@ FinishWalRecovery(void)
*/
result->endOfLogTLI = xlogreader->seg.ws_tli;
- if (ArchiveRecoveryRequested)
+ if (ArchiveRecoveryRequested())
{
/*
* We are no longer in archive recovery state.
@@ -1540,8 +1513,8 @@ FinishWalRecovery(void)
* We are now done reading the old WAL. Turn off archive fetching if
* it was active.
*/
- Assert(InArchiveRecovery);
- InArchiveRecovery = false;
+ Assert(InArchiveRecovery());
+ localRecoveryFlags &= ~SX_IN_ARCHIVE_RECOVERY;
/*
* If the ending log segment is still open, close it (to avoid
@@ -1621,7 +1594,7 @@ ShutdownWalRecovery(void)
XLogReaderFree(xlogreader);
XLogPrefetcherFree(xlogprefetcher);
- if (ArchiveRecoveryRequested)
+ if (ArchiveRecoveryRequested())
{
/*
* Since there might be a partial WAL segment named RECOVERYXLOG, get
@@ -1639,7 +1612,7 @@ ShutdownWalRecovery(void)
* We don't need the latch anymore. It's not strictly necessary to disown
* it, but let's do it for the sake of tidiness.
*/
- if (ArchiveRecoveryRequested)
+ if (ArchiveRecoveryRequested())
DisownLatch(&XLogRecoveryCtl->recoveryWakeupLatch);
}
@@ -1741,7 +1714,7 @@ PerformWalRecovery(void)
LSN_FORMAT_ARGS(xlogreader->ReadRecPtr))));
/* Prepare to report progress of the redo phase. */
- if (!StandbyMode)
+ if (!InStandbyMode())
begin_startup_progress_phase();
/*
@@ -1749,7 +1722,7 @@ PerformWalRecovery(void)
*/
do
{
- if (!StandbyMode)
+ if (!InStandbyMode())
ereport_startup_progress("redo in progress, elapsed time: %ld.%02d s, current LSN: %X/%X",
LSN_FORMAT_ARGS(xlogreader->ReadRecPtr));
@@ -1894,7 +1867,7 @@ PerformWalRecovery(void)
* This check is intentionally after the above log messages that indicate
* how far recovery went.
*/
- if (ArchiveRecoveryRequested &&
+ if (ArchiveRecoveryRequested() &&
recoveryTarget != RECOVERY_TARGET_UNSET &&
!reachedRecoveryTarget)
ereport(FATAL,
@@ -2186,7 +2159,7 @@ CheckRecoveryConsistency(void)
if (XLogRecPtrIsInvalid(minRecoveryPoint))
return;
- Assert(InArchiveRecovery);
+ Assert(InArchiveRecovery());
/*
* assume that we are called in the startup process, and hence don't need
@@ -2256,15 +2229,15 @@ CheckRecoveryConsistency(void)
* enabling connections.
*/
if (standbyState == STANDBY_SNAPSHOT_READY &&
- !LocalHotStandbyActive &&
+ !(localRecoveryFlags & SX_HOT_STANDBY_ACTIVE) &&
reachedConsistency &&
IsUnderPostmaster)
{
SpinLockAcquire(&XLogRecoveryCtl->info_lck);
- XLogRecoveryCtl->SharedHotStandbyActive = true;
+ XLogRecoveryCtl->sharedRecoveryFlags |= SX_HOT_STANDBY_ACTIVE;
SpinLockRelease(&XLogRecoveryCtl->info_lck);
- LocalHotStandbyActive = true;
+ localRecoveryFlags |= SX_HOT_STANDBY_ACTIVE;
SendPostmasterSignal(PMSIGNAL_BEGIN_HOT_STANDBY);
}
@@ -2584,7 +2557,7 @@ recoveryStopsBefore(XLogReaderState *record)
* Ignore recovery target settings when not in archive recovery (meaning
* we are in crash recovery).
*/
- if (!ArchiveRecoveryRequested)
+ if (!ArchiveRecoveryRequested())
return false;
/* Check if we should stop as soon as reaching consistency */
@@ -2736,7 +2709,7 @@ recoveryStopsAfter(XLogReaderState *record)
* Ignore recovery target settings when not in archive recovery (meaning
* we are in crash recovery).
*/
- if (!ArchiveRecoveryRequested)
+ if (!ArchiveRecoveryRequested())
return false;
info = XLogRecGetInfo(record) & ~XLR_INFO_MASK;
@@ -2927,11 +2900,11 @@ static void
recoveryPausesHere(bool endOfRecovery)
{
/* Don't pause unless users can connect! */
- if (!LocalHotStandbyActive)
+ if (!(localRecoveryFlags & SX_HOT_STANDBY_ACTIVE))
return;
/* Don't pause after standby promotion has been triggered */
- if (LocalPromoteIsTriggered)
+ if (localRecoveryFlags & SX_PROMOTE_IS_TRIGGERED)
return;
if (endOfRecovery)
@@ -2997,7 +2970,7 @@ recoveryApplyDelay(XLogReaderState *record)
return false;
/* nothing to do if crash recovery is requested */
- if (!ArchiveRecoveryRequested)
+ if (!ArchiveRecoveryRequested())
return false;
/*
@@ -3159,13 +3132,13 @@ ReadRecord(XLogPrefetcher *xlogprefetcher, int emode,
* to indicate to downstream WAL readers that that portion is to
* be ignored.
*
- * However, when ArchiveRecoveryRequested = true, we're going to
+ * However, when ArchiveRecoveryRequested() = true, we're going to
* switch to a new timeline at the end of recovery. We will only
* copy WAL over to the new timeline up to the end of the last
* complete record, so if we did this, we would later create an
* overwrite contrecord in the wrong place, breaking everything.
*/
- if (!ArchiveRecoveryRequested &&
+ if (!ArchiveRecoveryRequested() &&
!XLogRecPtrIsInvalid(xlogreader->abortedRecPtr))
{
abortedRecPtr = xlogreader->abortedRecPtr;
@@ -3234,13 +3207,13 @@ ReadRecord(XLogPrefetcher *xlogprefetcher, int emode,
* we'd have no idea how far we'd have to replay to reach
* consistency. So err on the safe side and give up.
*/
- if (!InArchiveRecovery && ArchiveRecoveryRequested &&
+ if (!InArchiveRecovery() && ArchiveRecoveryRequested() &&
!fetching_ckpt)
{
ereport(DEBUG1,
(errmsg_internal("reached end of WAL in pg_wal, entering archive recovery")));
- InArchiveRecovery = true;
- if (StandbyModeRequested)
+ localRecoveryFlags |= SX_IN_ARCHIVE_RECOVERY;
+ if (StandbyModeRequested())
EnableStandbyMode();
SwitchIntoArchiveRecovery(xlogreader->EndRecPtr, replayTLI);
@@ -3260,7 +3233,7 @@ ReadRecord(XLogPrefetcher *xlogprefetcher, int emode,
}
/* In standby mode, loop back to retry. Otherwise, give up. */
- if (StandbyMode && !CheckForStandbyTrigger())
+ if (InStandbyMode() && !CheckForStandbyTrigger())
continue;
else
return NULL;
@@ -3321,7 +3294,7 @@ XLogPageRead(XLogReaderState *xlogreader, XLogRecPtr targetPagePtr, int reqLen,
* Request a restartpoint if we've replayed too much xlog since the
* last one.
*/
- if (ArchiveRecoveryRequested && IsUnderPostmaster)
+ if (ArchiveRecoveryRequested() && IsUnderPostmaster)
{
if (XLogCheckpointNeeded(readSegNo))
{
@@ -3464,7 +3437,7 @@ retry:
* page header here for the retry. Instead, ReadPageInternal() is
* responsible for the validation.
*/
- if (StandbyMode &&
+ if (InStandbyMode() &&
!XLogReaderValidatePageHeader(xlogreader, targetPagePtr, readBuf))
{
/*
@@ -3500,7 +3473,7 @@ next_record_is_invalid:
readSource = XLOG_FROM_ANY;
/* In standby-mode, keep trying */
- if (StandbyMode)
+ if (InStandbyMode())
goto retry;
else
return XLREAD_FAIL;
@@ -3575,10 +3548,10 @@ WaitForWALToBecomeAvailable(XLogRecPtr RecPtr, bool randAccess,
* the end of recovery.
*-------
*/
- if (!InArchiveRecovery)
+ if (!InArchiveRecovery())
currentSource = XLOG_FROM_PG_WAL;
else if (currentSource == XLOG_FROM_ANY ||
- (!StandbyMode && currentSource == XLOG_FROM_STREAM))
+ (!InStandbyMode() && currentSource == XLOG_FROM_STREAM))
{
lastSourceFailed = false;
currentSource = XLOG_FROM_ARCHIVE;
@@ -3616,7 +3589,7 @@ WaitForWALToBecomeAvailable(XLogRecPtr RecPtr, bool randAccess,
* finish replaying as much as we can from archive and
* pg_wal before failover.
*/
- if (StandbyMode && CheckForStandbyTrigger())
+ if (InStandbyMode() && CheckForStandbyTrigger())
{
XLogShutdownWalRcv();
return XLREAD_FAIL;
@@ -3626,7 +3599,7 @@ WaitForWALToBecomeAvailable(XLogRecPtr RecPtr, bool randAccess,
* Not in standby mode, and we've now tried the archive
* and pg_wal.
*/
- if (!StandbyMode)
+ if (!InStandbyMode())
return XLREAD_FAIL;
/*
@@ -3658,7 +3631,7 @@ WaitForWALToBecomeAvailable(XLogRecPtr RecPtr, bool randAccess,
* We should be able to move to XLOG_FROM_STREAM only in
* standby mode.
*/
- Assert(StandbyMode);
+ Assert(InStandbyMode());
/*
* Before we leave XLOG_FROM_STREAM state, make sure that
@@ -3729,7 +3702,7 @@ WaitForWALToBecomeAvailable(XLogRecPtr RecPtr, bool randAccess,
* the archive over ones in pg_wal, so try the next file again
* from the archive first.
*/
- if (InArchiveRecovery)
+ if (InArchiveRecovery())
currentSource = XLOG_FROM_ARCHIVE;
}
@@ -3789,7 +3762,7 @@ WaitForWALToBecomeAvailable(XLogRecPtr RecPtr, bool randAccess,
* We should be able to move to XLOG_FROM_STREAM only in
* standby mode.
*/
- Assert(StandbyMode);
+ Assert(InStandbyMode());
/*
* First, shutdown walreceiver if its restart has been
@@ -4397,21 +4370,22 @@ PromoteIsTriggered(void)
* triggered. We can't trigger a promotion again, so there's no need to
* keep checking after the shared variable has once been seen true.
*/
- if (LocalPromoteIsTriggered)
+ if (localRecoveryFlags & SX_PROMOTE_IS_TRIGGERED)
return true;
SpinLockAcquire(&XLogRecoveryCtl->info_lck);
- LocalPromoteIsTriggered = XLogRecoveryCtl->SharedPromoteIsTriggered;
+ localRecoveryFlags |=
+ (XLogRecoveryCtl->sharedRecoveryFlags & SX_PROMOTE_IS_TRIGGERED);
SpinLockRelease(&XLogRecoveryCtl->info_lck);
- return LocalPromoteIsTriggered;
+ return localRecoveryFlags & SX_PROMOTE_IS_TRIGGERED;
}
static void
SetPromoteIsTriggered(void)
{
SpinLockAcquire(&XLogRecoveryCtl->info_lck);
- XLogRecoveryCtl->SharedPromoteIsTriggered = true;
+ XLogRecoveryCtl->sharedRecoveryFlags |= SX_PROMOTE_IS_TRIGGERED;
SpinLockRelease(&XLogRecoveryCtl->info_lck);
/*
@@ -4422,7 +4396,7 @@ SetPromoteIsTriggered(void)
*/
SetRecoveryPause(false);
- LocalPromoteIsTriggered = true;
+ localRecoveryFlags |= SX_PROMOTE_IS_TRIGGERED;
}
/*
@@ -4431,7 +4405,7 @@ SetPromoteIsTriggered(void)
static bool
CheckForStandbyTrigger(void)
{
- if (LocalPromoteIsTriggered)
+ if (localRecoveryFlags & SX_PROMOTE_IS_TRIGGERED)
return true;
if (IsPromoteSignaled() && CheckPromoteSignal())
@@ -4505,16 +4479,17 @@ HotStandbyActive(void)
* can't de-activate Hot Standby, so there's no need to keep checking
* after the shared variable has once been seen true.
*/
- if (LocalHotStandbyActive)
+ if (localRecoveryFlags & SX_HOT_STANDBY_ACTIVE)
return true;
else
{
/* spinlock is essential on machines with weak memory ordering! */
SpinLockAcquire(&XLogRecoveryCtl->info_lck);
- LocalHotStandbyActive = XLogRecoveryCtl->SharedHotStandbyActive;
+ localRecoveryFlags |=
+ (XLogRecoveryCtl->sharedRecoveryFlags & SX_HOT_STANDBY_ACTIVE);
SpinLockRelease(&XLogRecoveryCtl->info_lck);
- return LocalHotStandbyActive;
+ return localRecoveryFlags & SX_HOT_STANDBY_ACTIVE;
}
}
@@ -4526,7 +4501,7 @@ static bool
HotStandbyActiveInReplay(void)
{
Assert(AmStartupProcess() || !IsPostmasterEnvironment);
- return LocalHotStandbyActive;
+ return localRecoveryFlags & SX_HOT_STANDBY_ACTIVE;
}
/*
@@ -5044,3 +5019,23 @@ assign_recovery_target_xid(const char *newval, void *extra)
else
recoveryTarget = RECOVERY_TARGET_UNSET;
}
+
+bool StandbyModeRequested(void)
+{
+ return localRecoveryFlags & SX_STANDBY_MODE_REQUESTED;
+}
+
+bool ArchiveRecoveryRequested(void)
+{
+ return localRecoveryFlags & SX_ARCHIVE_RECOVERY_REQUESTED;
+}
+
+bool InArchiveRecovery(void)
+{
+ return localRecoveryFlags & SX_IN_ARCHIVE_RECOVERY;
+}
+
+bool InStandbyMode(void)
+{
+ return localRecoveryFlags & SX_IN_STANDBY_MODE;
+}
diff --git a/src/backend/replication/logical/slotsync.c b/src/backend/replication/logical/slotsync.c
index f6945af1d43..b8ac4c6c5df 100644
--- a/src/backend/replication/logical/slotsync.c
+++ b/src/backend/replication/logical/slotsync.c
@@ -1517,7 +1517,7 @@ update_synced_slots_inactive_since(void)
* long time after promotion if they haven't been synchronized recently.
* Whoever acquires the slot, i.e., makes the slot active, will reset it.
*/
- if (!StandbyMode)
+ if (!InStandbyMode())
return;
/* The slot sync worker or SQL function mustn't be running by now */
diff --git a/src/include/access/xlog_internal.h b/src/include/access/xlog_internal.h
index 0b7c56332b5..ff5e4fce305 100644
--- a/src/include/access/xlog_internal.h
+++ b/src/include/access/xlog_internal.h
@@ -392,14 +392,13 @@ extern void GetOldestRestartPoint(XLogRecPtr *oldrecptr, TimeLineID *oldtli);
extern void XLogRecGetBlockRefInfo(XLogReaderState *record, bool pretty,
bool detailed_format, StringInfo buf,
uint32 *fpi_len);
-
/*
* Exported for the functions in timeline.c and xlogarchive.c. Only valid
* in the startup process.
*/
-extern PGDLLIMPORT bool ArchiveRecoveryRequested;
-extern PGDLLIMPORT bool InArchiveRecovery;
-extern PGDLLIMPORT bool StandbyMode;
+extern PGDLLIMPORT bool ArchiveRecoveryRequested(void);
+extern PGDLLIMPORT bool InArchiveRecovery(void);
+extern PGDLLIMPORT bool InStandbyMode(void);
extern PGDLLIMPORT char *recoveryRestoreCommand;
#endif /* XLOG_INTERNAL_H */
diff --git a/src/include/access/xlogrecovery.h b/src/include/access/xlogrecovery.h
index 91446303024..2d44905ea36 100644
--- a/src/include/access/xlogrecovery.h
+++ b/src/include/access/xlogrecovery.h
@@ -16,6 +16,37 @@
#include "lib/stringinfo.h"
#include "utils/timestamp.h"
+/*
+ * The flag indicates if we allow hot standby queries to be run.
+ */
+#define SX_HOT_STANDBY_ACTIVE 0x01 /* SX: Startup Xlog */
+/*
+ * The flag indicates if a standby promotion has been triggered.
+ */
+#define SX_PROMOTE_IS_TRIGGERED 0x02
+/*
+ * When SX_ARCHIVE_RECOVERY_REQUESTED is set, archive recovery was requested,
+ * i.e. signal files were present. When SX_IN_ARCHIVE_RECOVERY is set, we are
+ * currently recovering using offline XLOG archives. These variables are only
+ * valid in the startup process.
+ *
+ * When SX_ARCHIVE_RECOVERY_REQUESTED is set, but SX_IN_ARCHIVE_RECOVERY is
+ * not, we're currently performing crash recovery using only XLOG files in
+ * pg_wal, but will switch to using offline XLOG archives as soon as we reach
+ * the end of WAL in pg_wal.
+ */
+#define SX_ARCHIVE_RECOVERY_REQUESTED 0x04
+#define SX_IN_ARCHIVE_RECOVERY 0x08
+/*
+ * When SX_STANDBY_MODE_REQUESTED is set, standby mode was requested, i.e.
+ * standby.signal file was present. When SX_IN_STANDBY_MODE is set, we are
+ * currently in standby mode. These variables are only valid in the startup
+ * process. They work similarly to SX_ARCHIVE_RECOVERY_REQUESTED and
+ * SX_IN_ARCHIVE_RECOVERY.
+ */
+#define SX_STANDBY_MODE_REQUESTED 0x10
+#define SX_IN_STANDBY_MODE 0x20
+
/*
* Recovery target type.
* Only set during a Point in Time recovery, not when in standby mode.
@@ -73,9 +104,6 @@ extern PGDLLIMPORT TimeLineID recoveryTargetTLI;
/* Have we already reached a consistent database state? */
extern PGDLLIMPORT bool reachedConsistency;
-/* Are we currently in standby mode? */
-extern PGDLLIMPORT bool StandbyMode;
-
extern Size XLogRecoveryShmemSize(void);
extern void XLogRecoveryShmemInit(void);
--
2.34.1
[text/x-diff] v4-0002-Text-array-sql-wrapper.patch (3.9K, ../../[email protected]/3-v4-0002-Text-array-sql-wrapper.patch)
download | inline diff:
From 39c42bdcaa371ea356ff2db8944d4cf8535d23ba Mon Sep 17 00:00:00 2001
From: Mikhail Litsarev <[email protected]>
Date: Fri, 10 Jan 2025 22:31:34 +0300
Subject: [PATCH] Wrapper function to extract whole text array from recovery
flags bitset.
It returns SX_PROMOTE_IS_TRIGGERED, SX_STANDBY_MODE_REQUESTED flags for
recovery states.
---
src/backend/access/transam/xlogfuncs.c | 31 +++++++++++++++++++++++
src/backend/access/transam/xlogrecovery.c | 16 ++++++++++++
src/include/access/xlogrecovery.h | 1 +
src/include/catalog/pg_proc.dat | 5 ++++
4 files changed, 53 insertions(+)
diff --git a/src/backend/access/transam/xlogfuncs.c b/src/backend/access/transam/xlogfuncs.c
index 8c3090165f0..9b71ff7583c 100644
--- a/src/backend/access/transam/xlogfuncs.c
+++ b/src/backend/access/transam/xlogfuncs.c
@@ -30,6 +30,7 @@
#include "storage/fd.h"
#include "storage/latch.h"
#include "storage/standby.h"
+#include "utils/array.h"
#include "utils/builtins.h"
#include "utils/memutils.h"
#include "utils/pg_lsn.h"
@@ -748,3 +749,33 @@ pg_promote(PG_FUNCTION_ARGS)
wait_seconds)));
PG_RETURN_BOOL(false);
}
+
+Datum
+pg_get_recovery_flags(PG_FUNCTION_ARGS)
+{
+/*
+ * Currently supported number of recovery flags is equal to two:
+ * {SX_PROMOTE_IS_TRIGGERED, SX_STANDBY_MODE_REQUESTED}.
+ * The SX_STANDBY_MODE_REQUESTED is valid only in the startup process.
+ */
+#define MAX_RECOVERY_FLAGS 2
+
+ bits32 recovery_flags;
+ int cnt = 0;
+ Datum flags[MAX_RECOVERY_FLAGS];
+ ArrayType *txt_arr;
+
+ recovery_flags = GetXLogRecoveryFlags();
+
+ if (recovery_flags & SX_PROMOTE_IS_TRIGGERED)
+ flags[cnt++] = CStringGetTextDatum("PROMOTE_IS_TRIGGERED");
+
+ if (recovery_flags & SX_STANDBY_MODE_REQUESTED)
+ flags[cnt++] = CStringGetTextDatum("STANDBY_MODE_REQUESTED");
+
+ Assert(cnt <= MAX_RECOVERY_FLAGS);
+
+ /* Returns bit array as Datum */
+ txt_arr = construct_array_builtin(flags, cnt, TEXTOID);
+ PG_RETURN_ARRAYTYPE_P(txt_arr);
+}
diff --git a/src/backend/access/transam/xlogrecovery.c b/src/backend/access/transam/xlogrecovery.c
index e75c7891fd5..d675b46c592 100644
--- a/src/backend/access/transam/xlogrecovery.c
+++ b/src/backend/access/transam/xlogrecovery.c
@@ -4355,6 +4355,22 @@ StartupRequestWalReceiverRestart(void)
}
}
+/*
+ * Return SX_PROMOTE_IS_TRIGGERED, SX_STANDBY_MODE_REQUESTED flags for
+ * recovery states.
+ */
+bits32 GetXLogRecoveryFlags(void)
+{
+ bits32 flags = 0;
+
+ SpinLockAcquire(&XLogRecoveryCtl->info_lck);
+ flags = XLogRecoveryCtl->sharedRecoveryFlags;
+ SpinLockRelease(&XLogRecoveryCtl->info_lck);
+
+ flags |= (localRecoveryFlags & SX_STANDBY_MODE_REQUESTED);
+
+ return flags;
+}
/*
* Has a standby promotion already been triggered?
diff --git a/src/include/access/xlogrecovery.h b/src/include/access/xlogrecovery.h
index 2d44905ea36..faa6c666ede 100644
--- a/src/include/access/xlogrecovery.h
+++ b/src/include/access/xlogrecovery.h
@@ -172,6 +172,7 @@ extern TimestampTz GetLatestXTime(void);
extern TimestampTz GetCurrentChunkReplayStartTime(void);
extern XLogRecPtr GetCurrentReplayRecPtr(TimeLineID *replayEndTLI);
+extern bits32 GetXLogRecoveryFlags(void);
extern bool PromoteIsTriggered(void);
extern bool CheckPromoteSignal(void);
extern void WakeupRecovery(void);
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index b37e8a6f882..e1e10f6a5d6 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -6660,6 +6660,11 @@
proname => 'pg_is_in_recovery', provolatile => 'v', prorettype => 'bool',
proargtypes => '', prosrc => 'pg_is_in_recovery' },
+{ oid => '8439',
+ descr => 'return flags for recovery states',
+ proname => 'pg_get_recovery_flags', provolatile => 'v', prorettype => '_text',
+ proargtypes => '', prosrc => 'pg_get_recovery_flags' },
+
{ oid => '3820', descr => 'current wal flush location',
proname => 'pg_last_wal_receive_lsn', provolatile => 'v',
prorettype => 'pg_lsn', proargtypes => '',
--
2.34.1
^ permalink raw reply [nested|flat] 6+ messages in thread
* Re: SQL function which allows to distinguish a server being in point in time recovery mode and an ordinary replica
2024-05-08 04:24 Re: SQL function which allows to distinguish a server being in point in time recovery mode and an ordinary replica Michael Paquier <[email protected]>
2024-06-13 18:07 ` Re: SQL function which allows to distinguish a server being in point in time recovery mode and an ordinary replica [email protected]
2024-06-14 04:51 ` Re: SQL function which allows to distinguish a server being in point in time recovery mode and an ordinary replica Michael Paquier <[email protected]>
2025-01-10 20:39 ` Re: SQL function which allows to distinguish a server being in point in time recovery mode and an ordinary replica [email protected]
@ 2025-02-28 13:41 ` [email protected]
0 siblings, 0 replies; 6+ messages in thread
From: [email protected] @ 2025-02-28 13:41 UTC (permalink / raw)
To: Michael Paquier <[email protected]>; +Cc: [email protected]
Hi!
Rebased the patch.
Respectfully,
Mikhail Litsarev,
Postgres Professional: https://postgrespro.com
Attachments:
[text/x-diff] v5-0001-Replace-recovery-boolean-flags-with-a-bits32-set.patch (31.7K, ../../[email protected]/2-v5-0001-Replace-recovery-boolean-flags-with-a-bits32-set.patch)
download | inline diff:
From 67b190ce15f8ba7480ba1691b804b27f96fd5540 Mon Sep 17 00:00:00 2001
From: Mikhail Litsarev <[email protected]>
Date: Fri, 10 Jan 2025 21:23:02 +0300
Subject: [PATCH v5 1/2] Replace recovery boolean flags with a bits32 set.
Move local booleans ArchiveRecoveryRequested, InArchiveRecovery,
StandbyModeRequested, StandbyMode, LocalHotStandbyActive,
LocalPromoteIsTriggered into localRecoveryFlags bitset.
Move SharedHotStandbyActive, SharedPromoteIsTriggered members of
XLogRecoveryCtlData into sharedRecoveryFlags bitset.
Refactor the code according to the changes.
---
src/backend/access/transam/timeline.c | 6 +-
src/backend/access/transam/xlog.c | 26 +--
src/backend/access/transam/xlogarchive.c | 4 +-
src/backend/access/transam/xlogrecovery.c | 221 ++++++++++-----------
src/backend/replication/logical/slotsync.c | 2 +-
src/include/access/xlog_internal.h | 7 +-
src/include/access/xlogrecovery.h | 34 +++-
7 files changed, 161 insertions(+), 139 deletions(-)
diff --git a/src/backend/access/transam/timeline.c b/src/backend/access/transam/timeline.c
index a27f27cc037..c9f53c4b667 100644
--- a/src/backend/access/transam/timeline.c
+++ b/src/backend/access/transam/timeline.c
@@ -93,7 +93,7 @@ readTimeLineHistory(TimeLineID targetTLI)
return list_make1(entry);
}
- if (ArchiveRecoveryRequested)
+ if (ArchiveRecoveryRequested())
{
TLHistoryFileName(histfname, targetTLI);
fromArchive =
@@ -229,7 +229,7 @@ existsTimeLineHistory(TimeLineID probeTLI)
if (probeTLI == 1)
return false;
- if (ArchiveRecoveryRequested)
+ if (ArchiveRecoveryRequested())
{
TLHistoryFileName(histfname, probeTLI);
RestoreArchivedFile(path, histfname, "RECOVERYHISTORY", 0, false);
@@ -331,7 +331,7 @@ writeTimeLineHistory(TimeLineID newTLI, TimeLineID parentTLI,
/*
* If a history file exists for the parent, copy it verbatim
*/
- if (ArchiveRecoveryRequested)
+ if (ArchiveRecoveryRequested())
{
TLHistoryFileName(histfname, parentTLI);
RestoreArchivedFile(path, histfname, "RECOVERYHISTORY", 0, false);
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 799fc739e18..f3af732b229 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -5434,7 +5434,7 @@ CheckRequiredParameterValues(void)
* For archive recovery, the WAL must be generated with at least 'replica'
* wal_level.
*/
- if (ArchiveRecoveryRequested && ControlFile->wal_level == WAL_LEVEL_MINIMAL)
+ if (ArchiveRecoveryRequested() && ControlFile->wal_level == WAL_LEVEL_MINIMAL)
{
ereport(FATAL,
(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
@@ -5447,7 +5447,7 @@ CheckRequiredParameterValues(void)
* For Hot Standby, the WAL must be generated with 'replica' mode, and we
* must have at least as many backend slots as the primary.
*/
- if (ArchiveRecoveryRequested && EnableHotStandby)
+ if (ArchiveRecoveryRequested() && EnableHotStandby)
{
/* We ignore autovacuum_worker_slots when we make this test. */
RecoveryRequiresIntParameter("max_connections",
@@ -5607,8 +5607,8 @@ StartupXLOG(void)
*
* InitWalRecovery analyzes the control file and the backup label file, if
* any. It updates the in-memory ControlFile buffer according to the
- * starting checkpoint, and sets InRecovery and ArchiveRecoveryRequested.
- * It also applies the tablespace map file, if any.
+ * starting checkpoint, and sets SX_ARCHIVE_RECOVERY_REQUESTED and
+ * InRecovery. It also applies the tablespace map file, if any.
*/
InitWalRecovery(ControlFile, &wasShutdown,
&haveBackupLabel, &haveTblspcMap);
@@ -5740,7 +5740,7 @@ StartupXLOG(void)
{
/* Initialize state for RecoveryInProgress() */
SpinLockAcquire(&XLogCtl->info_lck);
- if (InArchiveRecovery)
+ if (InArchiveRecovery())
XLogCtl->SharedRecoveryState = RECOVERY_STATE_ARCHIVE;
else
XLogCtl->SharedRecoveryState = RECOVERY_STATE_CRASH;
@@ -5793,7 +5793,7 @@ StartupXLOG(void)
* startup process to think that there are still invalid page
* references when checking for data consistency.
*/
- if (InArchiveRecovery)
+ if (InArchiveRecovery())
{
LocalMinRecoveryPoint = ControlFile->minRecoveryPoint;
LocalMinRecoveryPointTLI = ControlFile->minRecoveryPointTLI;
@@ -5827,7 +5827,7 @@ StartupXLOG(void)
* control file and we've established a recovery snapshot from a
* running-xacts WAL record.
*/
- if (ArchiveRecoveryRequested && EnableHotStandby)
+ if (ArchiveRecoveryRequested() && EnableHotStandby)
{
TransactionId *xids;
int nxids;
@@ -5940,7 +5940,7 @@ StartupXLOG(void)
* recover from an online backup but never called pg_backup_stop(), or
* you didn't archive all the WAL needed.
*/
- if (ArchiveRecoveryRequested || ControlFile->backupEndRequired)
+ if (ArchiveRecoveryRequested() || ControlFile->backupEndRequired)
{
if (!XLogRecPtrIsInvalid(ControlFile->backupStartPoint) || ControlFile->backupEndRequired)
ereport(FATAL,
@@ -5992,7 +5992,7 @@ StartupXLOG(void)
* In a normal crash recovery, we can just extend the timeline we were in.
*/
newTLI = endOfRecoveryInfo->lastRecTLI;
- if (ArchiveRecoveryRequested)
+ if (ArchiveRecoveryRequested())
{
newTLI = findNewestTimeLine(recoveryTargetTLI) + 1;
ereport(LOG,
@@ -6185,7 +6185,7 @@ StartupXLOG(void)
XLogReportParameters();
/* If this is archive recovery, perform post-recovery cleanup actions. */
- if (ArchiveRecoveryRequested)
+ if (ArchiveRecoveryRequested())
CleanupAfterArchiveRecovery(EndOfLogTLI, EndOfLog, newTLI);
/*
@@ -6344,7 +6344,7 @@ PerformRecoveryXLogAction(void)
* of a full checkpoint. A checkpoint is requested later, after we're
* fully out of recovery mode and already accepting queries.
*/
- if (ArchiveRecoveryRequested && IsUnderPostmaster &&
+ if (ArchiveRecoveryRequested() && IsUnderPostmaster &&
PromoteIsTriggered())
{
promoted = true;
@@ -8338,7 +8338,7 @@ xlog_redo(XLogReaderState *record)
* record, the backup was canceled and the end-of-backup record will
* never arrive.
*/
- if (ArchiveRecoveryRequested &&
+ if (ArchiveRecoveryRequested() &&
!XLogRecPtrIsInvalid(ControlFile->backupStartPoint) &&
XLogRecPtrIsInvalid(ControlFile->backupEndPoint))
ereport(PANIC,
@@ -8579,7 +8579,7 @@ xlog_redo(XLogReaderState *record)
* local copies cannot be updated as long as crash recovery is
* happening and we expect all the WAL to be replayed.
*/
- if (InArchiveRecovery)
+ if (InArchiveRecovery())
{
LocalMinRecoveryPoint = ControlFile->minRecoveryPoint;
LocalMinRecoveryPointTLI = ControlFile->minRecoveryPointTLI;
diff --git a/src/backend/access/transam/xlogarchive.c b/src/backend/access/transam/xlogarchive.c
index 1ef1713c91a..ad379acc30a 100644
--- a/src/backend/access/transam/xlogarchive.c
+++ b/src/backend/access/transam/xlogarchive.c
@@ -68,7 +68,7 @@ RestoreArchivedFile(char *path, const char *xlogfname,
* Ignore restore_command when not in archive recovery (meaning we are in
* crash recovery).
*/
- if (!ArchiveRecoveryRequested)
+ if (!ArchiveRecoveryRequested())
goto not_available;
/* In standby mode, restore_command might not be supplied */
@@ -205,7 +205,7 @@ RestoreArchivedFile(char *path, const char *xlogfname,
* incorrectly conclude we've reached the end of WAL and we're
* done recovering ...
*/
- if (StandbyMode && stat_buf.st_size < expectedSize)
+ if (InStandbyMode() && stat_buf.st_size < expectedSize)
elevel = DEBUG1;
else
elevel = FATAL;
diff --git a/src/backend/access/transam/xlogrecovery.c b/src/backend/access/transam/xlogrecovery.c
index 52f53fa12e0..3d1fe965a45 100644
--- a/src/backend/access/transam/xlogrecovery.c
+++ b/src/backend/access/transam/xlogrecovery.c
@@ -124,30 +124,7 @@ TimeLineID recoveryTargetTLI = 0;
static List *expectedTLEs;
static TimeLineID curFileTLI;
-/*
- * When ArchiveRecoveryRequested is set, archive recovery was requested,
- * ie. signal files were present. When InArchiveRecovery is set, we are
- * currently recovering using offline XLOG archives. These variables are only
- * valid in the startup process.
- *
- * When ArchiveRecoveryRequested is true, but InArchiveRecovery is false, we're
- * currently performing crash recovery using only XLOG files in pg_wal, but
- * will switch to using offline XLOG archives as soon as we reach the end of
- * WAL in pg_wal.
- */
-bool ArchiveRecoveryRequested = false;
-bool InArchiveRecovery = false;
-
-/*
- * When StandbyModeRequested is set, standby mode was requested, i.e.
- * standby.signal file was present. When StandbyMode is set, we are currently
- * in standby mode. These variables are only valid in the startup process.
- * They work similarly to ArchiveRecoveryRequested and InArchiveRecovery.
- */
-static bool StandbyModeRequested = false;
-bool StandbyMode = false;
-
-/* was a signal file present at startup? */
+/* Was a signal file present at startup? */
static bool standby_signal_file_found = false;
static bool recovery_signal_file_found = false;
@@ -171,16 +148,19 @@ static XLogRecPtr RedoStartLSN = InvalidXLogRecPtr;
static TimeLineID RedoStartTLI = 0;
/*
- * Local copy of SharedHotStandbyActive variable. False actually means "not
- * known, need to check the shared state".
- */
-static bool LocalHotStandbyActive = false;
-
-/*
- * Local copy of SharedPromoteIsTriggered variable. False actually means "not
- * known, need to check the shared state".
+ * Local flags:
+ * SX_ARCHIVE_RECOVERY_REQUESTED
+ * SX_IN_ARCHIVE_RECOVERY
+ * SX_STANDBY_MODE_REQUESTED
+ * SX_IN_STANDBY_MODE
+ *
+ * and local copies of sharedRecoveryFlags:
+ * SX_HOT_STANDBY_ACTIVE,
+ * SX_PROMOTE_IS_TRIGGERED.
+ * If some flag is not set, that actually means "not known, need to check
+ * the shared state".
*/
-static bool LocalPromoteIsTriggered = false;
+static bits32 localRecoveryFlags = 0;
/* Has the recovery code requested a walreceiver wakeup? */
static bool doRequestWalReceiverReply;
@@ -298,23 +278,16 @@ bool reachedConsistency = false;
static char *replay_image_masked = NULL;
static char *primary_image_masked = NULL;
-
/*
* Shared-memory state for WAL recovery.
*/
typedef struct XLogRecoveryCtlData
{
/*
- * SharedHotStandbyActive indicates if we allow hot standby queries to be
- * run. Protected by info_lck.
+ * The bit array stores the following states
+ * SX_HOT_STANDBY_ACTIVE, SX_PROMOTE_IS_TRIGGERED. Protected by info_lck.
*/
- bool SharedHotStandbyActive;
-
- /*
- * SharedPromoteIsTriggered indicates if a standby promotion has been
- * triggered. Protected by info_lck.
- */
- bool SharedPromoteIsTriggered;
+ bits32 sharedRecoveryFlags;
/*
* recoveryWakeupLatch is used to wake up the startup process to continue
@@ -441,6 +414,7 @@ static bool HotStandbyActiveInReplay(void);
static void SetCurrentChunkStartTime(TimestampTz xtime);
static void SetLatestXTime(TimestampTz xtime);
+static bool StandbyModeRequested(void);
/*
* Initialization of shared memory for WAL recovery
*/
@@ -478,7 +452,7 @@ XLogRecoveryShmemInit(void)
static void
EnableStandbyMode(void)
{
- StandbyMode = true;
+ localRecoveryFlags |= SX_IN_STANDBY_MODE;
/*
* To avoid server log bloat, we don't report recovery progress in a
@@ -506,8 +480,8 @@ EnableStandbyMode(void)
* disk does after initializing other subsystems, but before calling
* PerformWalRecovery().
*
- * This initializes some global variables like ArchiveRecoveryRequested, and
- * StandbyModeRequested and InRecovery.
+ * This initializes some flags like SX_ARCHIVE_RECOVERY_REQUESTED and
+ * SX_STABDBY_MODE_REQUESTED and global variable InRecovery.
*/
void
InitWalRecovery(ControlFileData *ControlFile, bool *wasShutdown_ptr,
@@ -545,7 +519,7 @@ InitWalRecovery(ControlFileData *ControlFile, bool *wasShutdown_ptr,
* Take ownership of the wakeup latch if we're going to sleep during
* recovery, if required.
*/
- if (ArchiveRecoveryRequested)
+ if (ArchiveRecoveryRequested())
OwnLatch(&XLogRecoveryCtl->recoveryWakeupLatch);
/*
@@ -600,8 +574,8 @@ InitWalRecovery(ControlFileData *ControlFile, bool *wasShutdown_ptr,
* file, we know how far we need to replay to reach consistency. Enter
* archive recovery directly.
*/
- InArchiveRecovery = true;
- if (StandbyModeRequested)
+ localRecoveryFlags |= SX_IN_ARCHIVE_RECOVERY;
+ if (StandbyModeRequested())
EnableStandbyMode();
/*
@@ -750,14 +724,14 @@ InitWalRecovery(ControlFileData *ControlFile, bool *wasShutdown_ptr,
* to minRecoveryPoint, up to backupEndPoint, or until we see an
* end-of-backup record), and we can enter archive recovery directly.
*/
- if (ArchiveRecoveryRequested &&
+ if (ArchiveRecoveryRequested() &&
(ControlFile->minRecoveryPoint != InvalidXLogRecPtr ||
ControlFile->backupEndRequired ||
ControlFile->backupEndPoint != InvalidXLogRecPtr ||
ControlFile->state == DB_SHUTDOWNED))
{
- InArchiveRecovery = true;
- if (StandbyModeRequested)
+ localRecoveryFlags |= SX_IN_ARCHIVE_RECOVERY;
+ if (StandbyModeRequested())
EnableStandbyMode();
}
@@ -800,9 +774,9 @@ InitWalRecovery(ControlFileData *ControlFile, bool *wasShutdown_ptr,
wasShutdown = ((record->xl_info & ~XLR_INFO_MASK) == XLOG_CHECKPOINT_SHUTDOWN);
}
- if (ArchiveRecoveryRequested)
+ if (ArchiveRecoveryRequested())
{
- if (StandbyModeRequested)
+ if (StandbyModeRequested())
ereport(LOG,
(errmsg("entering standby mode")));
else if (recoveryTarget == RECOVERY_TARGET_XID)
@@ -914,7 +888,7 @@ InitWalRecovery(ControlFileData *ControlFile, bool *wasShutdown_ptr,
}
else if (ControlFile->state != DB_SHUTDOWNED)
InRecovery = true;
- else if (ArchiveRecoveryRequested)
+ else if (ArchiveRecoveryRequested())
{
/* force recovery due to presence of recovery signal file */
InRecovery = true;
@@ -931,7 +905,7 @@ InitWalRecovery(ControlFileData *ControlFile, bool *wasShutdown_ptr,
*/
if (InRecovery)
{
- if (InArchiveRecovery)
+ if (InArchiveRecovery())
{
ControlFile->state = DB_IN_ARCHIVE_RECOVERY;
}
@@ -950,7 +924,7 @@ InitWalRecovery(ControlFileData *ControlFile, bool *wasShutdown_ptr,
}
ControlFile->checkPoint = CheckPointLoc;
ControlFile->checkPointCopy = checkPoint;
- if (InArchiveRecovery)
+ if (InArchiveRecovery())
{
/* initialize minRecoveryPoint if not set yet */
if (ControlFile->minRecoveryPoint < checkPoint.redo)
@@ -997,7 +971,7 @@ InitWalRecovery(ControlFileData *ControlFile, bool *wasShutdown_ptr,
backupStartPoint = ControlFile->backupStartPoint;
backupEndRequired = ControlFile->backupEndRequired;
backupEndPoint = ControlFile->backupEndPoint;
- if (InArchiveRecovery)
+ if (InArchiveRecovery())
{
minRecoveryPoint = ControlFile->minRecoveryPoint;
minRecoveryPointTLI = ControlFile->minRecoveryPointTLI;
@@ -1083,17 +1057,16 @@ readRecoverySignalFile(void)
recovery_signal_file_found = true;
}
- StandbyModeRequested = false;
- ArchiveRecoveryRequested = false;
+ localRecoveryFlags &= ~SX_STANDBY_MODE_REQUESTED;
+ localRecoveryFlags &= ~SX_ARCHIVE_RECOVERY_REQUESTED;
if (standby_signal_file_found)
{
- StandbyModeRequested = true;
- ArchiveRecoveryRequested = true;
+ localRecoveryFlags |= SX_STANDBY_MODE_REQUESTED;
+ localRecoveryFlags |= SX_ARCHIVE_RECOVERY_REQUESTED;
}
else if (recovery_signal_file_found)
{
- StandbyModeRequested = false;
- ArchiveRecoveryRequested = true;
+ localRecoveryFlags |= SX_ARCHIVE_RECOVERY_REQUESTED;
}
else
return;
@@ -1102,7 +1075,7 @@ readRecoverySignalFile(void)
* We don't support standby mode in standalone backends; that requires
* other processes such as the WAL receiver to be alive.
*/
- if (StandbyModeRequested && !IsUnderPostmaster)
+ if (StandbyModeRequested() && !IsUnderPostmaster)
ereport(FATAL,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("standby mode is not supported by single-user servers")));
@@ -1111,13 +1084,13 @@ readRecoverySignalFile(void)
static void
validateRecoveryParameters(void)
{
- if (!ArchiveRecoveryRequested)
+ if (!ArchiveRecoveryRequested())
return;
/*
* Check for compulsory parameters
*/
- if (StandbyModeRequested)
+ if (StandbyModeRequested())
{
if ((PrimaryConnInfo == NULL || strcmp(PrimaryConnInfo, "") == 0) &&
(recoveryRestoreCommand == NULL || strcmp(recoveryRestoreCommand, "") == 0))
@@ -1158,8 +1131,8 @@ validateRecoveryParameters(void)
/*
* If user specified recovery_target_timeline, validate it or compute the
* "latest" value. We can't do this until after we've gotten the restore
- * command and set InArchiveRecovery, because we need to fetch timeline
- * history files from the archive.
+ * command and set SX_IN_ARCHIVE_RECOVERY, because we need to fetch
+ * timeline history files from the archive.
*/
if (recoveryTargetTimeLineGoal == RECOVERY_TARGET_TIMELINE_NUMERIC)
{
@@ -1497,7 +1470,7 @@ FinishWalRecovery(void)
* i.e., calling XLogShutdownWalRcv().
*/
Assert(!WalRcvStreaming());
- StandbyMode = false;
+ localRecoveryFlags &= ~SX_IN_STANDBY_MODE;
/*
* Determine where to start writing WAL next.
@@ -1535,7 +1508,7 @@ FinishWalRecovery(void)
*/
result->endOfLogTLI = xlogreader->seg.ws_tli;
- if (ArchiveRecoveryRequested)
+ if (ArchiveRecoveryRequested())
{
/*
* We are no longer in archive recovery state.
@@ -1543,8 +1516,8 @@ FinishWalRecovery(void)
* We are now done reading the old WAL. Turn off archive fetching if
* it was active.
*/
- Assert(InArchiveRecovery);
- InArchiveRecovery = false;
+ Assert(InArchiveRecovery());
+ localRecoveryFlags &= ~SX_IN_ARCHIVE_RECOVERY;
/*
* If the ending log segment is still open, close it (to avoid
@@ -1624,7 +1597,7 @@ ShutdownWalRecovery(void)
XLogReaderFree(xlogreader);
XLogPrefetcherFree(xlogprefetcher);
- if (ArchiveRecoveryRequested)
+ if (ArchiveRecoveryRequested())
{
/*
* Since there might be a partial WAL segment named RECOVERYXLOG, get
@@ -1642,7 +1615,7 @@ ShutdownWalRecovery(void)
* We don't need the latch anymore. It's not strictly necessary to disown
* it, but let's do it for the sake of tidiness.
*/
- if (ArchiveRecoveryRequested)
+ if (ArchiveRecoveryRequested())
DisownLatch(&XLogRecoveryCtl->recoveryWakeupLatch);
}
@@ -1744,7 +1717,7 @@ PerformWalRecovery(void)
LSN_FORMAT_ARGS(xlogreader->ReadRecPtr))));
/* Prepare to report progress of the redo phase. */
- if (!StandbyMode)
+ if (!InStandbyMode())
begin_startup_progress_phase();
/*
@@ -1752,7 +1725,7 @@ PerformWalRecovery(void)
*/
do
{
- if (!StandbyMode)
+ if (!InStandbyMode())
ereport_startup_progress("redo in progress, elapsed time: %ld.%02d s, current LSN: %X/%X",
LSN_FORMAT_ARGS(xlogreader->ReadRecPtr));
@@ -1897,7 +1870,7 @@ PerformWalRecovery(void)
* This check is intentionally after the above log messages that indicate
* how far recovery went.
*/
- if (ArchiveRecoveryRequested &&
+ if (ArchiveRecoveryRequested() &&
recoveryTarget != RECOVERY_TARGET_UNSET &&
!reachedRecoveryTarget)
ereport(FATAL,
@@ -2189,7 +2162,7 @@ CheckRecoveryConsistency(void)
if (XLogRecPtrIsInvalid(minRecoveryPoint))
return;
- Assert(InArchiveRecovery);
+ Assert(InArchiveRecovery());
/*
* assume that we are called in the startup process, and hence don't need
@@ -2259,15 +2232,15 @@ CheckRecoveryConsistency(void)
* enabling connections.
*/
if (standbyState == STANDBY_SNAPSHOT_READY &&
- !LocalHotStandbyActive &&
+ !(localRecoveryFlags & SX_HOT_STANDBY_ACTIVE) &&
reachedConsistency &&
IsUnderPostmaster)
{
SpinLockAcquire(&XLogRecoveryCtl->info_lck);
- XLogRecoveryCtl->SharedHotStandbyActive = true;
+ XLogRecoveryCtl->sharedRecoveryFlags |= SX_HOT_STANDBY_ACTIVE;
SpinLockRelease(&XLogRecoveryCtl->info_lck);
- LocalHotStandbyActive = true;
+ localRecoveryFlags |= SX_HOT_STANDBY_ACTIVE;
SendPostmasterSignal(PMSIGNAL_BEGIN_HOT_STANDBY);
}
@@ -2587,7 +2560,7 @@ recoveryStopsBefore(XLogReaderState *record)
* Ignore recovery target settings when not in archive recovery (meaning
* we are in crash recovery).
*/
- if (!ArchiveRecoveryRequested)
+ if (!ArchiveRecoveryRequested())
return false;
/* Check if we should stop as soon as reaching consistency */
@@ -2739,7 +2712,7 @@ recoveryStopsAfter(XLogReaderState *record)
* Ignore recovery target settings when not in archive recovery (meaning
* we are in crash recovery).
*/
- if (!ArchiveRecoveryRequested)
+ if (!ArchiveRecoveryRequested())
return false;
info = XLogRecGetInfo(record) & ~XLR_INFO_MASK;
@@ -2930,11 +2903,11 @@ static void
recoveryPausesHere(bool endOfRecovery)
{
/* Don't pause unless users can connect! */
- if (!LocalHotStandbyActive)
+ if (!(localRecoveryFlags & SX_HOT_STANDBY_ACTIVE))
return;
/* Don't pause after standby promotion has been triggered */
- if (LocalPromoteIsTriggered)
+ if (localRecoveryFlags & SX_PROMOTE_IS_TRIGGERED)
return;
if (endOfRecovery)
@@ -3000,7 +2973,7 @@ recoveryApplyDelay(XLogReaderState *record)
return false;
/* nothing to do if crash recovery is requested */
- if (!ArchiveRecoveryRequested)
+ if (!ArchiveRecoveryRequested())
return false;
/*
@@ -3162,13 +3135,13 @@ ReadRecord(XLogPrefetcher *xlogprefetcher, int emode,
* to indicate to downstream WAL readers that that portion is to
* be ignored.
*
- * However, when ArchiveRecoveryRequested = true, we're going to
+ * However, when ArchiveRecoveryRequested() = true, we're going to
* switch to a new timeline at the end of recovery. We will only
* copy WAL over to the new timeline up to the end of the last
* complete record, so if we did this, we would later create an
* overwrite contrecord in the wrong place, breaking everything.
*/
- if (!ArchiveRecoveryRequested &&
+ if (!ArchiveRecoveryRequested() &&
!XLogRecPtrIsInvalid(xlogreader->abortedRecPtr))
{
abortedRecPtr = xlogreader->abortedRecPtr;
@@ -3237,13 +3210,13 @@ ReadRecord(XLogPrefetcher *xlogprefetcher, int emode,
* we'd have no idea how far we'd have to replay to reach
* consistency. So err on the safe side and give up.
*/
- if (!InArchiveRecovery && ArchiveRecoveryRequested &&
+ if (!InArchiveRecovery() && ArchiveRecoveryRequested() &&
!fetching_ckpt)
{
ereport(DEBUG1,
(errmsg_internal("reached end of WAL in pg_wal, entering archive recovery")));
- InArchiveRecovery = true;
- if (StandbyModeRequested)
+ localRecoveryFlags |= SX_IN_ARCHIVE_RECOVERY;
+ if (StandbyModeRequested())
EnableStandbyMode();
SwitchIntoArchiveRecovery(xlogreader->EndRecPtr, replayTLI);
@@ -3263,7 +3236,7 @@ ReadRecord(XLogPrefetcher *xlogprefetcher, int emode,
}
/* In standby mode, loop back to retry. Otherwise, give up. */
- if (StandbyMode && !CheckForStandbyTrigger())
+ if (InStandbyMode() && !CheckForStandbyTrigger())
continue;
else
return NULL;
@@ -3325,7 +3298,7 @@ XLogPageRead(XLogReaderState *xlogreader, XLogRecPtr targetPagePtr, int reqLen,
* Request a restartpoint if we've replayed too much xlog since the
* last one.
*/
- if (ArchiveRecoveryRequested && IsUnderPostmaster)
+ if (ArchiveRecoveryRequested() && IsUnderPostmaster)
{
if (XLogCheckpointNeeded(readSegNo))
{
@@ -3478,7 +3451,7 @@ retry:
* page header here for the retry. Instead, ReadPageInternal() is
* responsible for the validation.
*/
- if (StandbyMode &&
+ if (InStandbyMode() &&
(targetPagePtr % wal_segment_size) == 0 &&
!XLogReaderValidatePageHeader(xlogreader, targetPagePtr, readBuf))
{
@@ -3515,7 +3488,7 @@ next_record_is_invalid:
readSource = XLOG_FROM_ANY;
/* In standby-mode, keep trying */
- if (StandbyMode)
+ if (InStandbyMode())
goto retry;
else
return XLREAD_FAIL;
@@ -3590,10 +3563,10 @@ WaitForWALToBecomeAvailable(XLogRecPtr RecPtr, bool randAccess,
* the end of recovery.
*-------
*/
- if (!InArchiveRecovery)
+ if (!InArchiveRecovery())
currentSource = XLOG_FROM_PG_WAL;
else if (currentSource == XLOG_FROM_ANY ||
- (!StandbyMode && currentSource == XLOG_FROM_STREAM))
+ (!InStandbyMode() && currentSource == XLOG_FROM_STREAM))
{
lastSourceFailed = false;
currentSource = XLOG_FROM_ARCHIVE;
@@ -3631,7 +3604,7 @@ WaitForWALToBecomeAvailable(XLogRecPtr RecPtr, bool randAccess,
* finish replaying as much as we can from archive and
* pg_wal before failover.
*/
- if (StandbyMode && CheckForStandbyTrigger())
+ if (InStandbyMode() && CheckForStandbyTrigger())
{
XLogShutdownWalRcv();
return XLREAD_FAIL;
@@ -3641,7 +3614,7 @@ WaitForWALToBecomeAvailable(XLogRecPtr RecPtr, bool randAccess,
* Not in standby mode, and we've now tried the archive
* and pg_wal.
*/
- if (!StandbyMode)
+ if (!InStandbyMode())
return XLREAD_FAIL;
/*
@@ -3673,7 +3646,7 @@ WaitForWALToBecomeAvailable(XLogRecPtr RecPtr, bool randAccess,
* We should be able to move to XLOG_FROM_STREAM only in
* standby mode.
*/
- Assert(StandbyMode);
+ Assert(InStandbyMode());
/*
* Before we leave XLOG_FROM_STREAM state, make sure that
@@ -3744,7 +3717,7 @@ WaitForWALToBecomeAvailable(XLogRecPtr RecPtr, bool randAccess,
* the archive over ones in pg_wal, so try the next file again
* from the archive first.
*/
- if (InArchiveRecovery)
+ if (InArchiveRecovery())
currentSource = XLOG_FROM_ARCHIVE;
}
@@ -3804,7 +3777,7 @@ WaitForWALToBecomeAvailable(XLogRecPtr RecPtr, bool randAccess,
* We should be able to move to XLOG_FROM_STREAM only in
* standby mode.
*/
- Assert(StandbyMode);
+ Assert(InStandbyMode());
/*
* First, shutdown walreceiver if its restart has been
@@ -4412,21 +4385,22 @@ PromoteIsTriggered(void)
* triggered. We can't trigger a promotion again, so there's no need to
* keep checking after the shared variable has once been seen true.
*/
- if (LocalPromoteIsTriggered)
+ if (localRecoveryFlags & SX_PROMOTE_IS_TRIGGERED)
return true;
SpinLockAcquire(&XLogRecoveryCtl->info_lck);
- LocalPromoteIsTriggered = XLogRecoveryCtl->SharedPromoteIsTriggered;
+ localRecoveryFlags |=
+ (XLogRecoveryCtl->sharedRecoveryFlags & SX_PROMOTE_IS_TRIGGERED);
SpinLockRelease(&XLogRecoveryCtl->info_lck);
- return LocalPromoteIsTriggered;
+ return localRecoveryFlags & SX_PROMOTE_IS_TRIGGERED;
}
static void
SetPromoteIsTriggered(void)
{
SpinLockAcquire(&XLogRecoveryCtl->info_lck);
- XLogRecoveryCtl->SharedPromoteIsTriggered = true;
+ XLogRecoveryCtl->sharedRecoveryFlags |= SX_PROMOTE_IS_TRIGGERED;
SpinLockRelease(&XLogRecoveryCtl->info_lck);
/*
@@ -4437,7 +4411,7 @@ SetPromoteIsTriggered(void)
*/
SetRecoveryPause(false);
- LocalPromoteIsTriggered = true;
+ localRecoveryFlags |= SX_PROMOTE_IS_TRIGGERED;
}
/*
@@ -4446,7 +4420,7 @@ SetPromoteIsTriggered(void)
static bool
CheckForStandbyTrigger(void)
{
- if (LocalPromoteIsTriggered)
+ if (localRecoveryFlags & SX_PROMOTE_IS_TRIGGERED)
return true;
if (IsPromoteSignaled() && CheckPromoteSignal())
@@ -4520,16 +4494,17 @@ HotStandbyActive(void)
* can't de-activate Hot Standby, so there's no need to keep checking
* after the shared variable has once been seen true.
*/
- if (LocalHotStandbyActive)
+ if (localRecoveryFlags & SX_HOT_STANDBY_ACTIVE)
return true;
else
{
/* spinlock is essential on machines with weak memory ordering! */
SpinLockAcquire(&XLogRecoveryCtl->info_lck);
- LocalHotStandbyActive = XLogRecoveryCtl->SharedHotStandbyActive;
+ localRecoveryFlags |=
+ (XLogRecoveryCtl->sharedRecoveryFlags & SX_HOT_STANDBY_ACTIVE);
SpinLockRelease(&XLogRecoveryCtl->info_lck);
- return LocalHotStandbyActive;
+ return localRecoveryFlags & SX_HOT_STANDBY_ACTIVE;
}
}
@@ -4541,7 +4516,7 @@ static bool
HotStandbyActiveInReplay(void)
{
Assert(AmStartupProcess() || !IsPostmasterEnvironment);
- return LocalHotStandbyActive;
+ return localRecoveryFlags & SX_HOT_STANDBY_ACTIVE;
}
/*
@@ -5059,3 +5034,23 @@ assign_recovery_target_xid(const char *newval, void *extra)
else
recoveryTarget = RECOVERY_TARGET_UNSET;
}
+
+bool StandbyModeRequested(void)
+{
+ return localRecoveryFlags & SX_STANDBY_MODE_REQUESTED;
+}
+
+bool ArchiveRecoveryRequested(void)
+{
+ return localRecoveryFlags & SX_ARCHIVE_RECOVERY_REQUESTED;
+}
+
+bool InArchiveRecovery(void)
+{
+ return localRecoveryFlags & SX_IN_ARCHIVE_RECOVERY;
+}
+
+bool InStandbyMode(void)
+{
+ return localRecoveryFlags & SX_IN_STANDBY_MODE;
+}
diff --git a/src/backend/replication/logical/slotsync.c b/src/backend/replication/logical/slotsync.c
index 2c0a7439be4..920040f3bcd 100644
--- a/src/backend/replication/logical/slotsync.c
+++ b/src/backend/replication/logical/slotsync.c
@@ -1517,7 +1517,7 @@ update_synced_slots_inactive_since(void)
* long time after promotion if they haven't been synchronized recently.
* Whoever acquires the slot, i.e., makes the slot active, will reset it.
*/
- if (!StandbyMode)
+ if (!InStandbyMode())
return;
/* The slot sync worker or SQL function mustn't be running by now */
diff --git a/src/include/access/xlog_internal.h b/src/include/access/xlog_internal.h
index 2cf8d55d706..48c8cb85271 100644
--- a/src/include/access/xlog_internal.h
+++ b/src/include/access/xlog_internal.h
@@ -392,14 +392,13 @@ extern void GetOldestRestartPoint(XLogRecPtr *oldrecptr, TimeLineID *oldtli);
extern void XLogRecGetBlockRefInfo(XLogReaderState *record, bool pretty,
bool detailed_format, StringInfo buf,
uint32 *fpi_len);
-
/*
* Exported for the functions in timeline.c and xlogarchive.c. Only valid
* in the startup process.
*/
-extern PGDLLIMPORT bool ArchiveRecoveryRequested;
-extern PGDLLIMPORT bool InArchiveRecovery;
-extern PGDLLIMPORT bool StandbyMode;
+extern PGDLLIMPORT bool ArchiveRecoveryRequested(void);
+extern PGDLLIMPORT bool InArchiveRecovery(void);
+extern PGDLLIMPORT bool InStandbyMode(void);
extern PGDLLIMPORT char *recoveryRestoreCommand;
#endif /* XLOG_INTERNAL_H */
diff --git a/src/include/access/xlogrecovery.h b/src/include/access/xlogrecovery.h
index 91446303024..2d44905ea36 100644
--- a/src/include/access/xlogrecovery.h
+++ b/src/include/access/xlogrecovery.h
@@ -16,6 +16,37 @@
#include "lib/stringinfo.h"
#include "utils/timestamp.h"
+/*
+ * The flag indicates if we allow hot standby queries to be run.
+ */
+#define SX_HOT_STANDBY_ACTIVE 0x01 /* SX: Startup Xlog */
+/*
+ * The flag indicates if a standby promotion has been triggered.
+ */
+#define SX_PROMOTE_IS_TRIGGERED 0x02
+/*
+ * When SX_ARCHIVE_RECOVERY_REQUESTED is set, archive recovery was requested,
+ * i.e. signal files were present. When SX_IN_ARCHIVE_RECOVERY is set, we are
+ * currently recovering using offline XLOG archives. These variables are only
+ * valid in the startup process.
+ *
+ * When SX_ARCHIVE_RECOVERY_REQUESTED is set, but SX_IN_ARCHIVE_RECOVERY is
+ * not, we're currently performing crash recovery using only XLOG files in
+ * pg_wal, but will switch to using offline XLOG archives as soon as we reach
+ * the end of WAL in pg_wal.
+ */
+#define SX_ARCHIVE_RECOVERY_REQUESTED 0x04
+#define SX_IN_ARCHIVE_RECOVERY 0x08
+/*
+ * When SX_STANDBY_MODE_REQUESTED is set, standby mode was requested, i.e.
+ * standby.signal file was present. When SX_IN_STANDBY_MODE is set, we are
+ * currently in standby mode. These variables are only valid in the startup
+ * process. They work similarly to SX_ARCHIVE_RECOVERY_REQUESTED and
+ * SX_IN_ARCHIVE_RECOVERY.
+ */
+#define SX_STANDBY_MODE_REQUESTED 0x10
+#define SX_IN_STANDBY_MODE 0x20
+
/*
* Recovery target type.
* Only set during a Point in Time recovery, not when in standby mode.
@@ -73,9 +104,6 @@ extern PGDLLIMPORT TimeLineID recoveryTargetTLI;
/* Have we already reached a consistent database state? */
extern PGDLLIMPORT bool reachedConsistency;
-/* Are we currently in standby mode? */
-extern PGDLLIMPORT bool StandbyMode;
-
extern Size XLogRecoveryShmemSize(void);
extern void XLogRecoveryShmemInit(void);
--
2.34.1
[text/x-diff] v5-0002-Wrapper-function-to-extract-whole-text-array-from.patch (3.9K, ../../[email protected]/3-v5-0002-Wrapper-function-to-extract-whole-text-array-from.patch)
download | inline diff:
From 33dbaa6cde687c97373959695c84c5eee72192a7 Mon Sep 17 00:00:00 2001
From: Mikhail Litsarev <[email protected]>
Date: Fri, 10 Jan 2025 22:31:34 +0300
Subject: [PATCH v5 2/2] Wrapper function to extract whole text array from
recovery flags bitset.
It returns SX_PROMOTE_IS_TRIGGERED, SX_STANDBY_MODE_REQUESTED flags for
recovery states.
---
src/backend/access/transam/xlogfuncs.c | 31 +++++++++++++++++++++++
src/backend/access/transam/xlogrecovery.c | 16 ++++++++++++
src/include/access/xlogrecovery.h | 1 +
src/include/catalog/pg_proc.dat | 5 ++++
4 files changed, 53 insertions(+)
diff --git a/src/backend/access/transam/xlogfuncs.c b/src/backend/access/transam/xlogfuncs.c
index 8c3090165f0..9b71ff7583c 100644
--- a/src/backend/access/transam/xlogfuncs.c
+++ b/src/backend/access/transam/xlogfuncs.c
@@ -30,6 +30,7 @@
#include "storage/fd.h"
#include "storage/latch.h"
#include "storage/standby.h"
+#include "utils/array.h"
#include "utils/builtins.h"
#include "utils/memutils.h"
#include "utils/pg_lsn.h"
@@ -748,3 +749,33 @@ pg_promote(PG_FUNCTION_ARGS)
wait_seconds)));
PG_RETURN_BOOL(false);
}
+
+Datum
+pg_get_recovery_flags(PG_FUNCTION_ARGS)
+{
+/*
+ * Currently supported number of recovery flags is equal to two:
+ * {SX_PROMOTE_IS_TRIGGERED, SX_STANDBY_MODE_REQUESTED}.
+ * The SX_STANDBY_MODE_REQUESTED is valid only in the startup process.
+ */
+#define MAX_RECOVERY_FLAGS 2
+
+ bits32 recovery_flags;
+ int cnt = 0;
+ Datum flags[MAX_RECOVERY_FLAGS];
+ ArrayType *txt_arr;
+
+ recovery_flags = GetXLogRecoveryFlags();
+
+ if (recovery_flags & SX_PROMOTE_IS_TRIGGERED)
+ flags[cnt++] = CStringGetTextDatum("PROMOTE_IS_TRIGGERED");
+
+ if (recovery_flags & SX_STANDBY_MODE_REQUESTED)
+ flags[cnt++] = CStringGetTextDatum("STANDBY_MODE_REQUESTED");
+
+ Assert(cnt <= MAX_RECOVERY_FLAGS);
+
+ /* Returns bit array as Datum */
+ txt_arr = construct_array_builtin(flags, cnt, TEXTOID);
+ PG_RETURN_ARRAYTYPE_P(txt_arr);
+}
diff --git a/src/backend/access/transam/xlogrecovery.c b/src/backend/access/transam/xlogrecovery.c
index 3d1fe965a45..fb2c31616aa 100644
--- a/src/backend/access/transam/xlogrecovery.c
+++ b/src/backend/access/transam/xlogrecovery.c
@@ -4370,6 +4370,22 @@ StartupRequestWalReceiverRestart(void)
}
}
+/*
+ * Return SX_PROMOTE_IS_TRIGGERED, SX_STANDBY_MODE_REQUESTED flags for
+ * recovery states.
+ */
+bits32 GetXLogRecoveryFlags(void)
+{
+ bits32 flags = 0;
+
+ SpinLockAcquire(&XLogRecoveryCtl->info_lck);
+ flags = XLogRecoveryCtl->sharedRecoveryFlags;
+ SpinLockRelease(&XLogRecoveryCtl->info_lck);
+
+ flags |= (localRecoveryFlags & SX_STANDBY_MODE_REQUESTED);
+
+ return flags;
+}
/*
* Has a standby promotion already been triggered?
diff --git a/src/include/access/xlogrecovery.h b/src/include/access/xlogrecovery.h
index 2d44905ea36..faa6c666ede 100644
--- a/src/include/access/xlogrecovery.h
+++ b/src/include/access/xlogrecovery.h
@@ -172,6 +172,7 @@ extern TimestampTz GetLatestXTime(void);
extern TimestampTz GetCurrentChunkReplayStartTime(void);
extern XLogRecPtr GetCurrentReplayRecPtr(TimeLineID *replayEndTLI);
+extern bits32 GetXLogRecoveryFlags(void);
extern bool PromoteIsTriggered(void);
extern bool CheckPromoteSignal(void);
extern void WakeupRecovery(void);
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index cd9422d0bac..d8c5ec9d98a 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -6685,6 +6685,11 @@
proname => 'pg_is_in_recovery', provolatile => 'v', prorettype => 'bool',
proargtypes => '', prosrc => 'pg_is_in_recovery' },
+{ oid => '8439',
+ descr => 'return flags for recovery states',
+ proname => 'pg_get_recovery_flags', provolatile => 'v', prorettype => '_text',
+ proargtypes => '', prosrc => 'pg_get_recovery_flags' },
+
{ oid => '3820', descr => 'current wal flush location',
proname => 'pg_last_wal_receive_lsn', provolatile => 'v',
prorettype => 'pg_lsn', proargtypes => '',
--
2.34.1
^ permalink raw reply [nested|flat] 6+ messages in thread
end of thread, other threads:[~2025-02-28 13:41 UTC | newest]
Thread overview: 6+ messages (download: mbox mbox.gz follow: Atom feed)
-- links below jump to the message on this page --
2021-03-12 21:35 [PATCH v7 7/9] Default to LZ4.. Justin Pryzby <[email protected]>
2024-05-08 04:24 Re: SQL function which allows to distinguish a server being in point in time recovery mode and an ordinary replica Michael Paquier <[email protected]>
2024-06-13 18:07 ` Re: SQL function which allows to distinguish a server being in point in time recovery mode and an ordinary replica [email protected]
2024-06-14 04:51 ` Re: SQL function which allows to distinguish a server being in point in time recovery mode and an ordinary replica Michael Paquier <[email protected]>
2025-01-10 20:39 ` Re: SQL function which allows to distinguish a server being in point in time recovery mode and an ordinary replica [email protected]
2025-02-28 13:41 ` Re: SQL function which allows to distinguish a server being in point in time recovery mode and an ordinary replica [email protected]
This inbox is served by agora; see mirroring instructions
for how to clone and mirror all data and code used for this inbox