* XLogCtl->Insert.RedoRecPtr, whenever we can safely do so (ie, when we
* hold an insertion lock). See XLogInsertRecord for details. We are also
* allowed to update from XLogCtl->RedoRecPtr if we hold the info_lck;
- * see GetRedoRecPtr. A freshly spawned backend obtains the value during
- * InitXLOGAccess.
+ * see GetRedoRecPtr.
+ *
+ * NB: Code that uses this variable must be prepared not only for the
+ * possibility that it may be arbitrarily out of date, but also for the
+ * possibility that it might be set to InvalidXLogRecPtr. We used to
+ * initialize it as a side effect of the first call to RecoveryInProgress(),
+ * which meant that most code that might use it could assume that it had a
+ * real if perhaps stale value. That's no longer the case.
*/
static XLogRecPtr RedoRecPtr;
* doPageWrites is this backend's local copy of (forcePageWrites ||
* fullPageWrites). It is used together with RedoRecPtr to decide whether
* a full-page image of a page need to be taken.
+ *
+ * NB: Initially this is false, and there's no guarantee that it will be
+ * initialized to any other value before it is first used. Any code that
+ * makes use of it must recheck the value after obtaining a WALInsertLock,
+ * and respond appropriately if it turns out that the previous value wasn't
+ * accurate.
*/
static bool doPageWrites;
*
* Unlike testing InRecovery, this works in any process that's connected to
* shared memory.
- *
- * As a side-effect, we initialize the local RedoRecPtr variable the first
- * time we see that recovery is finished.
*/
bool
RecoveryInProgress(void)
LocalRecoveryInProgress = (xlogctl->SharedRecoveryState != RECOVERY_STATE_DONE);
- /*
- * Initialize TimeLineID and RedoRecPtr when we discover that recovery
- * is finished. InitPostgres() relies upon this behaviour to ensure
- * that InitXLOGAccess() is called at backend startup. (If you change
- * this, see also LocalSetXLogInsertAllowed.)
- */
- if (!LocalRecoveryInProgress)
- {
- /*
- * If we just exited recovery, make sure we read TimeLineID and
- * RedoRecPtr after SharedRecoveryState (for machines with weak
- * memory ordering).
- */
- pg_memory_barrier();
- InitXLOGAccess();
- }
-
/*
* Note: We don't need a memory barrier when we're still in recovery.
* We might exit recovery immediately after return, so the caller
LocalXLogInsertAllowed = 1;
- /* Initialize as RecoveryInProgress() would do when switching state */
- InitXLOGAccess();
-
return oldXLogAllowed;
}
return record;
}
-/*
- * This must be called in a backend process before creating WAL records
- * (except in a standalone backend, which does StartupXLOG instead). We need
- * to initialize the local copy of RedoRecPtr.
- */
-void
-InitXLOGAccess(void)
-{
- XLogCtlInsert *Insert = &XLogCtl->Insert;
-
- /* set wal_segment_size */
- wal_segment_size = ControlFile->xlog_seg_size;
-
- /* Use GetRedoRecPtr to copy the RedoRecPtr safely */
- (void) GetRedoRecPtr();
- /* Also update our copy of doPageWrites. */
- doPageWrites = (Insert->fullPageWrites || Insert->forcePageWrites);
-}
-
/*
* Return the current Redo pointer from shared memory.
*
* full-page image to be included in the WAL record.
*
* The returned values are cached copies from backend-private memory, and
- * possibly out-of-date. XLogInsertRecord will re-check them against
- * up-to-date values, while holding the WAL insert lock.
+ * possibly out-of-date or, indeed, uninitalized, in which case they will
+ * be InvalidXLogRecPtr and false, respectively. XLogInsertRecord will
+ * re-check them against up-to-date values, while holding the WAL insert lock.
*/
void
GetFullPageWriteInfo(XLogRecPtr *RedoRecPtr_p, bool *doPageWrites_p)
}
/*
- * Initialize local process's access to XLOG.
+ * If this is either a bootstrap process nor a standalone backend, start
+ * up the XLOG machinery, and register to have it closed down at exit.
+ * In other cases, the startup process is responsible for starting up
+ * the XLOG machinery, and the checkpointer for closing it down.
*/
- if (IsUnderPostmaster)
- {
- /*
- * The postmaster already started the XLOG machinery, but we need to
- * call InitXLOGAccess(), if the system isn't in hot-standby mode.
- * This is handled by calling RecoveryInProgress and ignoring the
- * result.
- */
- (void) RecoveryInProgress();
- }
- else
+ if (!IsUnderPostmaster)
{
/*
- * We are either a bootstrap process or a standalone backend. Either
- * way, start up the XLOG machinery, and register to have it closed
- * down at exit.
- *
* We don't yet have an aux-process resource owner, but StartupXLOG
* and ShutdownXLOG will need one. Hence, create said resource owner
* (and register a callback to clean it up after ShutdownXLOG runs).