*** a/src/backend/access/transam/xlog.c --- b/src/backend/access/transam/xlog.c *************** *** 427,432 **** typedef struct XLogCtlData --- 427,443 ---- bool SharedHotStandbyActive; /* + * standbyMode is read from recovery.conf but needs to be in shared + * memory so that the checkpointer process can access it. Note that + * this is not the shared copy of StandbyMode. StandbyMode is forcibly + * turned off at the end of recovery, but this doesn't change accordingly + * because the checkpointer doesn't need to see the change of the mode + * for the current use. Which means that this doesn't change after + * startup so we need no lock to access this. + */ + bool standbyMode; + + /* * 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. *************** *** 5446,5451 **** readRecoveryCommandFile(void) --- 5457,5463 ---- "standby_mode"))); ereport(DEBUG2, (errmsg_internal("standby_mode = '%s'", item->value))); + } else if (strcmp(item->name, "primary_conninfo") == 0) { *************** *** 6075,6085 **** StartupXLOG(void) ControlFile->checkPointCopy.ThisTimeLineID))); /* ! * Save the selected recovery target timeline ID and * archive_cleanup_command in shared memory so that other processes can * see them */ XLogCtl->RecoveryTargetTLI = recoveryTargetTLI; strncpy(XLogCtl->archiveCleanupCommand, archiveCleanupCommand ? archiveCleanupCommand : "", sizeof(XLogCtl->archiveCleanupCommand)); --- 6087,6098 ---- ControlFile->checkPointCopy.ThisTimeLineID))); /* ! * Save the selected recovery target timeline ID, standby_mode and * archive_cleanup_command in shared memory so that other processes can * see them */ XLogCtl->RecoveryTargetTLI = recoveryTargetTLI; + XLogCtl->standbyMode = StandbyMode; strncpy(XLogCtl->archiveCleanupCommand, archiveCleanupCommand ? archiveCleanupCommand : "", sizeof(XLogCtl->archiveCleanupCommand)); *************** *** 7096,7102 **** RecoveryInProgress(void) * 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 --- 7109,7115 ---- * 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 InRecovery, this works in any process that's connected to * shared memory. */ bool *************** *** 7124,7129 **** HotStandbyActive(void) --- 7137,7152 ---- } /* + * Is the system in standby mode? + */ + bool + IsStandbyMode(void) + { + /* XLogCtl->standbyMode doesn't change so we need no lock to copy it */ + return XLogCtl->standbyMode; + } + + /* * Is this process allowed to insert new WAL records? * * Ordinarily this is essentially equivalent to !RecoveryInProgress(). *** a/src/backend/postmaster/checkpointer.c --- b/src/backend/postmaster/checkpointer.c *************** *** 491,498 **** CheckpointerMain(void) * Initialize checkpointer-private variables used during checkpoint. */ ckpt_active = true; ! if (!do_restartpoint) ! ckpt_start_recptr = GetInsertRecPtr(); ckpt_start_time = now; ckpt_cached_elapsed = 0; --- 491,498 ---- * Initialize checkpointer-private variables used during checkpoint. */ ckpt_active = true; ! ckpt_start_recptr = ! do_restartpoint ? GetXLogReplayRecPtr(NULL) : GetInsertRecPtr(); ckpt_start_time = now; ckpt_cached_elapsed = 0; *************** *** 715,720 **** IsCheckpointOnSchedule(double progress) --- 715,721 ---- struct timeval now; double elapsed_xlogs, elapsed_time; + bool recovery_in_progress; Assert(ckpt_active); *************** *** 731,748 **** IsCheckpointOnSchedule(double progress) return false; /* ! * Check progress against WAL segments written and checkpoint_segments. * * We compare the current WAL insert location against the location ! * computed before calling CreateCheckPoint. The code in XLogInsert that ! * actually triggers a checkpoint when checkpoint_segments is exceeded ! * compares against RedoRecptr, so this is not completely accurate. ! * However, it's good enough for our purposes, we're only calculating an ! * estimate anyway. */ ! if (!RecoveryInProgress()) { ! recptr = GetInsertRecPtr(); elapsed_xlogs = (((double) (int32) (recptr.xlogid - ckpt_start_recptr.xlogid)) * XLogSegsPerFile + ((double) recptr.xrecoff - (double) ckpt_start_recptr.xrecoff) / XLogSegSize) / --- 732,758 ---- return false; /* ! * Check progress against WAL segments written, or replayed for ! * hot standby, and checkpoint_segments. * * We compare the current WAL insert location against the location ! * computed before calling CreateCheckPoint. The code in ! * XLogInsert that actually triggers a checkpoint when ! * checkpoint_segments is exceeded compares against RedoRecPtr. ! * Similarly, we consult WAL replay location instead on hot ! * standbys and XLogPageRead compares it aganst RedoRecPtr, too. ! * Altough these are not completely accurate, it's good enough for ! * our purposes, we're only calculating an estimate anyway. ! */ ! ! /* ! * Inhibit governing progress by segments in archive recovery. */ ! recovery_in_progress = RecoveryInProgress(); ! if (!recovery_in_progress || IsStandbyMode()) { ! recptr = recovery_in_progress ? GetXLogReplayRecPtr(NULL) : ! GetInsertRecPtr(); elapsed_xlogs = (((double) (int32) (recptr.xlogid - ckpt_start_recptr.xlogid)) * XLogSegsPerFile + ((double) recptr.xrecoff - (double) ckpt_start_recptr.xrecoff) / XLogSegSize) / *** a/src/include/access/xlog.h --- b/src/include/access/xlog.h *************** *** 285,290 **** extern void issue_xlog_fsync(int fd, uint32 log, uint32 seg); --- 285,291 ---- extern bool RecoveryInProgress(void); extern bool HotStandbyActive(void); + extern bool IsStandbyMode(void); extern bool XLogInsertAllowed(void); extern void GetXLogReceiptTime(TimestampTz *rtime, bool *fromStream); extern XLogRecPtr GetXLogReplayRecPtr(XLogRecPtr *restoreLastRecPtr);