standby_checkpoint_segments_9.2dev_fix_20120423.patch

application/octet-stream

Filename: standby_checkpoint_segments_9.2dev_fix_20120423.patch
Type: application/octet-stream
Part: 0
Message: Re: [BUG] 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: context
File+
src/backend/access/transam/xlog.c 25 0
src/backend/postmaster/checkpointer.c 20 0
src/include/access/xlog.h 1 0
*** 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);