diff options
Diffstat (limited to 'src/backend/access/transam/xlog.c')
-rw-r--r-- | src/backend/access/transam/xlog.c | 58 |
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(). |