chkpt_segs_for_standby_20120608_1.patch

text/x-patch

Filename: chkpt_segs_for_standby_20120608_1.patch
Type: text/x-patch
Part: 0
Message: Checkpointer on hot standby runs without looking checkpoint_segments

Patch

Same data as JSON: GET /api/v1/attachments/:id/patch the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes. API reference →
Format: unified
File+
src/backend/postmaster/checkpointer.c 18 8
src/backend/replication/walreceiver.c 1 0
src/backend/replication/walreceiverfuncs.c 20 0
src/include/replication/walreceiver.h 2 0
diff --git a/src/backend/postmaster/checkpointer.c b/src/backend/postmaster/checkpointer.c
index 6aeade9..cb2509a 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"
@@ -493,8 +494,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;
 
@@ -747,6 +748,7 @@ IsCheckpointOnSchedule(double progress)
 	struct timeval now;
 	double		elapsed_xlogs,
 				elapsed_time;
+	bool        recovery_in_progress;
 
 	Assert(ckpt_active);
 
@@ -763,18 +765,26 @@ 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.
+	 * 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) /
diff --git a/src/backend/replication/walreceiver.c b/src/backend/replication/walreceiver.c
index d63ff29..7d57ad7 100644
--- a/src/backend/replication/walreceiver.c
+++ b/src/backend/replication/walreceiver.c
@@ -215,6 +215,7 @@ WalReceiverMain(void)
 	/* Advertise our PID so that the startup process can kill us */
 	walrcv->pid = MyProcPid;
 	walrcv->walRcvState = WALRCV_RUNNING;
+	walrcv->started = true;
 
 	/* Fetch information required to start streaming */
 	strlcpy(conninfo, (char *) walrcv->conninfo, MAXCONNINFO);
diff --git a/src/backend/replication/walreceiverfuncs.c b/src/backend/replication/walreceiverfuncs.c
index f8dd523..c3b26e9 100644
--- a/src/backend/replication/walreceiverfuncs.c
+++ b/src/backend/replication/walreceiverfuncs.c
@@ -31,6 +31,7 @@
 #include "utils/timestamp.h"
 
 WalRcvData *WalRcv = NULL;
+static bool localWalRcvStarted = false;
 
 /*
  * How long to wait for walreceiver to start up after requesting
@@ -167,6 +168,25 @@ ShutdownWalRcv(void)
 }
 
 /*
+ * Returns true if WAL receiver has been launced so far regardless of current
+ * state.
+ */
+bool
+WalRcvStarted(void)
+{
+	/* WalRcv->started changes one way throughout the server life */
+	if (!localWalRcvStarted)
+	{
+		volatile WalRcvData *walrcv = WalRcv;
+
+		SpinLockAcquire(&walrcv->mutex);
+		localWalRcvStarted = walrcv->started;
+		SpinLockRelease(&walrcv->mutex);
+	}
+	return localWalRcvStarted;
+}
+
+/*
  * Request postmaster to start walreceiver.
  *
  * recptr indicates the position where streaming should begin, and conninfo
diff --git a/src/include/replication/walreceiver.h b/src/include/replication/walreceiver.h
index 68c8647..24901be 100644
--- a/src/include/replication/walreceiver.h
+++ b/src/include/replication/walreceiver.h
@@ -53,6 +53,7 @@ typedef struct
 	 */
 	pid_t		pid;
 	WalRcvState walRcvState;
+	bool        started;
 	pg_time_t	startTime;
 
 	/*
@@ -116,6 +117,7 @@ extern Size WalRcvShmemSize(void);
 extern void WalRcvShmemInit(void);
 extern void ShutdownWalRcv(void);
 extern bool WalRcvInProgress(void);
+extern bool WalRcvStarted(void);
 extern void RequestXLogStreaming(XLogRecPtr recptr, const char *conninfo);
 extern XLogRecPtr GetWalRcvWriteRecPtr(XLogRecPtr *latestChunkStart);
 extern int GetReplicationApplyDelay(void);