aboutsummaryrefslogtreecommitdiff
path: root/src/backend/access/transam/xlog.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/access/transam/xlog.c')
-rw-r--r--src/backend/access/transam/xlog.c58
1 files changed, 54 insertions, 4 deletions
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 6fdaaff9140..3ba1f29197f 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -158,6 +158,11 @@ static XLogRecPtr LastRec;
* known, need to check the shared state".
*/
static bool LocalRecoveryInProgress = true;
+/*
+ * Local copy of SharedHotStandbyActive variable. False actually means "not
+ * known, need to check the shared state".
+ */
+static bool LocalHotStandbyActive = false;
/*
* Local state for XLogInsertAllowed():
@@ -406,6 +411,12 @@ typedef struct XLogCtlData
bool SharedRecoveryInProgress;
/*
+ * SharedHotStandbyActive indicates if we're still in crash or archive
+ * recovery. Protected by info_lck.
+ */
+ bool SharedHotStandbyActive;
+
+ /*
* recoveryWakeupLatch is used to wake up the startup process to
* continue WAL replay, if it is waiting for WAL to arrive or failover
* trigger file to appear.
@@ -4917,6 +4928,7 @@ XLOGShmemInit(void)
*/
XLogCtl->XLogCacheBlck = XLOGbuffers - 1;
XLogCtl->SharedRecoveryInProgress = true;
+ XLogCtl->SharedHotStandbyActive = false;
XLogCtl->Insert.currpage = (XLogPageHeader) (XLogCtl->pages);
SpinLockInit(&XLogCtl->info_lck);
InitSharedLatch(&XLogCtl->recoveryWakeupLatch);
@@ -6790,8 +6802,6 @@ StartupXLOG(void)
static void
CheckRecoveryConsistency(void)
{
- static bool backendsAllowed = false;
-
/*
* Have we passed our safe starting point?
*/
@@ -6811,11 +6821,19 @@ CheckRecoveryConsistency(void)
* enabling connections.
*/
if (standbyState == STANDBY_SNAPSHOT_READY &&
- !backendsAllowed &&
+ !LocalHotStandbyActive &&
reachedMinRecoveryPoint &&
IsUnderPostmaster)
{
- backendsAllowed = true;
+ /* use volatile pointer to prevent code rearrangement */
+ volatile XLogCtlData *xlogctl = XLogCtl;
+
+ SpinLockAcquire(&xlogctl->info_lck);
+ xlogctl->SharedHotStandbyActive = true;
+ SpinLockRelease(&xlogctl->info_lck);
+
+ LocalHotStandbyActive = true;
+
SendPostmasterSignal(PMSIGNAL_BEGIN_HOT_STANDBY);
}
}
@@ -6863,6 +6881,38 @@ RecoveryInProgress(void)
}
/*
+ * Is HotStandby active yet? This is only important in special backends
+ * since normal backends won't ever be able to connect until this returns
+ * true. Postmaster knows this by way of signal, not via shared memory.
+ *
+ * Unlike testing standbyState, this works in any process that's connected to
+ * shared memory.
+ */
+bool
+HotStandbyActive(void)
+{
+ /*
+ * We check shared state each time only until Hot Standby is active. We
+ * 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)
+ return true;
+ else
+ {
+ /* use volatile pointer to prevent code rearrangement */
+ volatile XLogCtlData *xlogctl = XLogCtl;
+
+ /* spinlock is essential on machines with weak memory ordering! */
+ SpinLockAcquire(&xlogctl->info_lck);
+ LocalHotStandbyActive = xlogctl->SharedHotStandbyActive;
+ SpinLockRelease(&xlogctl->info_lck);
+
+ return LocalHotStandbyActive;
+ }
+}
+
+/*
* Is this process allowed to insert new WAL records?
*
* Ordinarily this is essentially equivalent to !RecoveryInProgress().