77 * Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
88 * Portions Copyright (c) 1994, Regents of the University of California
99 *
10- * $PostgreSQL: pgsql/src/backend/access/transam/xlog.c,v 1.418 2010/06/09 10:54:45 mha Exp $
10+ * $PostgreSQL: pgsql/src/backend/access/transam/xlog.c,v 1.419 2010/06/09 15:04:06 heikki Exp $
1111 *
1212 *-------------------------------------------------------------------------
1313 */
@@ -508,6 +508,9 @@ static bool reachedMinRecoveryPoint = false;
508508
509509static bool InRedo = false;
510510
511+ /* Have we launched bgwriter during recovery? */
512+ static bool bgwriterLaunched = false;
513+
511514/*
512515 * Information logged when we detect a change in one of the parameters
513516 * important for Hot Standby.
@@ -550,6 +553,7 @@ static void CheckPointGuts(XLogRecPtr checkPointRedo, int flags);
550553static bool XLogCheckBuffer (XLogRecData * rdata , bool doPageWrites ,
551554 XLogRecPtr * lsn , BkpBlock * bkpb );
552555static bool AdvanceXLInsertBuffer (bool new_segment );
556+ static bool XLogCheckpointNeeded (uint32 logid , uint32 logseg );
553557static void XLogWrite (XLogwrtRqst WriteRqst , bool flexible , bool xlog_switch );
554558static bool InstallXLogFileSegment (uint32 * log , uint32 * seg , char * tmppath ,
555559 bool find_free , int * max_advance ,
@@ -1554,14 +1558,14 @@ AdvanceXLInsertBuffer(bool new_segment)
15541558/*
15551559 * Check whether we've consumed enough xlog space that a checkpoint is needed.
15561560 *
1557- * Caller must have just finished filling the open log file (so that
1558- * openLogId/openLogSeg are valid ). We measure the distance from RedoRecPtr
1559- * to the open log file and see if that exceeds CheckPointSegments.
1561+ * logid/logseg indicate a log file that has just been filled up (or read
1562+ * during recovery ). We measure the distance from RedoRecPtr to logid/logseg
1563+ * and see if that exceeds CheckPointSegments.
15601564 *
15611565 * Note: it is caller's responsibility that RedoRecPtr is up-to-date.
15621566 */
15631567static bool
1564- XLogCheckpointNeeded (void )
1568+ XLogCheckpointNeeded (uint32 logid , uint32 logseg )
15651569{
15661570 /*
15671571 * A straight computation of segment number could overflow 32 bits. Rather
@@ -1577,8 +1581,8 @@ XLogCheckpointNeeded(void)
15771581 old_segno = (RedoRecPtr .xlogid % XLogSegSize ) * XLogSegsPerFile +
15781582 (RedoRecPtr .xrecoff / XLogSegSize );
15791583 old_highbits = RedoRecPtr .xlogid / XLogSegSize ;
1580- new_segno = (openLogId % XLogSegSize ) * XLogSegsPerFile + openLogSeg ;
1581- new_highbits = openLogId / XLogSegSize ;
1584+ new_segno = (logid % XLogSegSize ) * XLogSegsPerFile + logseg ;
1585+ new_highbits = logid / XLogSegSize ;
15821586 if (new_highbits != old_highbits ||
15831587 new_segno >= old_segno + (uint32 ) (CheckPointSegments - 1 ))
15841588 return true;
@@ -1782,10 +1786,10 @@ XLogWrite(XLogwrtRqst WriteRqst, bool flexible, bool xlog_switch)
17821786 * update RedoRecPtr and recheck.
17831787 */
17841788 if (IsUnderPostmaster &&
1785- XLogCheckpointNeeded ())
1789+ XLogCheckpointNeeded (openLogId , openLogSeg ))
17861790 {
17871791 (void ) GetRedoRecPtr ();
1788- if (XLogCheckpointNeeded ())
1792+ if (XLogCheckpointNeeded (openLogId , openLogSeg ))
17891793 RequestCheckpoint (CHECKPOINT_CAUSE_XLOG );
17901794 }
17911795 }
@@ -5653,7 +5657,6 @@ StartupXLOG(void)
56535657 XLogRecord * record ;
56545658 uint32 freespace ;
56555659 TransactionId oldestActiveXID ;
5656- bool bgwriterLaunched = false;
56575660
56585661 /*
56595662 * Read control file and check XLOG status looks valid.
@@ -7576,6 +7579,21 @@ CreateRestartPoint(int flags)
75767579 return false;
75777580 }
75787581
7582+ /*
7583+ * Update the shared RedoRecPtr so that the startup process can
7584+ * calculate the number of segments replayed since last restartpoint,
7585+ * and request a restartpoint if it exceeds checkpoint_segments.
7586+ *
7587+ * You need to hold WALInsertLock and info_lck to update it, although
7588+ * during recovery acquiring WALInsertLock is just pro forma, because
7589+ * there is no other processes updating Insert.RedoRecPtr.
7590+ */
7591+ LWLockAcquire (WALInsertLock , LW_EXCLUSIVE );
7592+ SpinLockAcquire (& xlogctl -> info_lck );
7593+ xlogctl -> Insert .RedoRecPtr = lastCheckPoint .redo ;
7594+ SpinLockRelease (& xlogctl -> info_lck );
7595+ LWLockRelease (WALInsertLock );
7596+
75797597 if (log_checkpoints )
75807598 {
75817599 /*
@@ -9209,6 +9227,20 @@ XLogPageRead(XLogRecPtr *RecPtr, int emode, bool fetching_ckpt,
92099227 */
92109228 if (readFile >= 0 && !XLByteInSeg (* RecPtr , readId , readSeg ))
92119229 {
9230+ /*
9231+ * Signal bgwriter to start a restartpoint if we've replayed too
9232+ * much xlog since the last one.
9233+ */
9234+ if (StandbyMode && bgwriterLaunched )
9235+ {
9236+ if (XLogCheckpointNeeded (readId , readSeg ))
9237+ {
9238+ (void ) GetRedoRecPtr ();
9239+ if (XLogCheckpointNeeded (readId , readSeg ))
9240+ RequestCheckpoint (CHECKPOINT_CAUSE_XLOG );
9241+ }
9242+ }
9243+
92129244 close (readFile );
92139245 readFile = -1 ;
92149246 readSource = 0 ;
0 commit comments