diff --git a/src/backend/postmaster/checkpointer.c b/src/backend/postmaster/checkpointer.c index c9473f7..babb874 100644 --- a/src/backend/postmaster/checkpointer.c +++ b/src/backend/postmaster/checkpointer.c @@ -46,6 +46,7 @@ #include "miscadmin.h" #include "pgstat.h" #include "postmaster/bgwriter.h" +#include "replication/walreceiver.h" #include "replication/syncrep.h" #include "storage/bufmgr.h" #include "storage/ipc.h" @@ -157,6 +158,8 @@ static bool am_checkpointer = false; static bool ckpt_active = false; +static bool walreceiver_started = false; + /* these values are valid when ckpt_active is true: */ static pg_time_t ckpt_start_time; static XLogRecPtr ckpt_start_recptr; @@ -168,6 +171,7 @@ static pg_time_t last_xlog_switch_time; /* Prototypes for private functions */ static void CheckArchiveTimeout(void); +static bool WalRcvStarted(void); static bool IsCheckpointOnSchedule(double progress); static bool ImmediateCheckpointRequested(void); static bool CompactCheckpointerRequestQueue(void); @@ -491,8 +495,8 @@ CheckpointerMain(void) * Initialize checkpointer-private variables used during checkpoint. */ ckpt_active = true; - if (!do_restartpoint) - ckpt_start_recptr = GetInsertRecPtr(); + ckpt_start_recptr = + do_restartpoint ? GetXLogReplayRecPtr(NULL) : GetInsertRecPtr(); ckpt_start_time = now; ckpt_cached_elapsed = 0; @@ -638,6 +642,25 @@ ImmediateCheckpointRequested(void) } /* + * WalRcvStarted -- Return whether WAL is coming via streaming + * + * WalRcvInProgress() indicates simply whether wal receiver is running or not + * at the moment this function is called. This natuer is not suitable to + * determine current source of WAL. WalRcvStarted() returns false before + * wal receiver is found running and true after that regardless whether wal + * receiver is actually running or not at the moment. + */ +bool +WalRcvStarted() +{ + if (!walreceiver_started && WalRcvInProgress()) + walreceiver_started = true; + + return walreceiver_started; +} + + +/* * CheckpointWriteDelay -- control rate of checkpoint * * This function is called after each page write performed by BufferSync(). @@ -715,6 +738,7 @@ IsCheckpointOnSchedule(double progress) struct timeval now; double elapsed_xlogs, elapsed_time; + bool recovery_in_progress; Assert(ckpt_active); @@ -731,18 +755,27 @@ IsCheckpointOnSchedule(double progress) return false; /* - * Check progress against WAL segments written and checkpoint_segments. + * 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, so this is not completely accurate. - * However, it's good enough for our purposes, we're only calculating an - * estimate anyway. + * 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. */ - if (!RecoveryInProgress()) + recovery_in_progress = RecoveryInProgress(); + if (!recovery_in_progress || WalRcvStarted()) { - recptr = GetInsertRecPtr(); + 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) /