diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c index 19f812456e..4718b538e8 100644 --- a/src/backend/access/transam/xlog.c +++ b/src/backend/access/transam/xlog.c @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/backend/access/transam/xlog.c,v 1.418 2010/06/09 10:54:45 mha Exp $ + * $PostgreSQL: pgsql/src/backend/access/transam/xlog.c,v 1.419 2010/06/09 15:04:06 heikki Exp $ * *------------------------------------------------------------------------- */ @@ -508,6 +508,9 @@ static bool reachedMinRecoveryPoint = false; static bool InRedo = false; +/* Have we launched bgwriter during recovery? */ +static bool bgwriterLaunched = false; + /* * Information logged when we detect a change in one of the parameters * important for Hot Standby. @@ -550,6 +553,7 @@ static void CheckPointGuts(XLogRecPtr checkPointRedo, int flags); static bool XLogCheckBuffer(XLogRecData *rdata, bool doPageWrites, XLogRecPtr *lsn, BkpBlock *bkpb); static bool AdvanceXLInsertBuffer(bool new_segment); +static bool XLogCheckpointNeeded(uint32 logid, uint32 logseg); static void XLogWrite(XLogwrtRqst WriteRqst, bool flexible, bool xlog_switch); static bool InstallXLogFileSegment(uint32 *log, uint32 *seg, char *tmppath, bool find_free, int *max_advance, @@ -1554,14 +1558,14 @@ AdvanceXLInsertBuffer(bool new_segment) /* * Check whether we've consumed enough xlog space that a checkpoint is needed. * - * Caller must have just finished filling the open log file (so that - * openLogId/openLogSeg are valid). We measure the distance from RedoRecPtr - * to the open log file and see if that exceeds CheckPointSegments. + * logid/logseg indicate a log file that has just been filled up (or read + * during recovery). We measure the distance from RedoRecPtr to logid/logseg + * and see if that exceeds CheckPointSegments. * * Note: it is caller's responsibility that RedoRecPtr is up-to-date. */ static bool -XLogCheckpointNeeded(void) +XLogCheckpointNeeded(uint32 logid, uint32 logseg) { /* * A straight computation of segment number could overflow 32 bits. Rather @@ -1577,8 +1581,8 @@ XLogCheckpointNeeded(void) old_segno = (RedoRecPtr.xlogid % XLogSegSize) * XLogSegsPerFile + (RedoRecPtr.xrecoff / XLogSegSize); old_highbits = RedoRecPtr.xlogid / XLogSegSize; - new_segno = (openLogId % XLogSegSize) * XLogSegsPerFile + openLogSeg; - new_highbits = openLogId / XLogSegSize; + new_segno = (logid % XLogSegSize) * XLogSegsPerFile + logseg; + new_highbits = logid / XLogSegSize; if (new_highbits != old_highbits || new_segno >= old_segno + (uint32) (CheckPointSegments - 1)) return true; @@ -1782,10 +1786,10 @@ XLogWrite(XLogwrtRqst WriteRqst, bool flexible, bool xlog_switch) * update RedoRecPtr and recheck. */ if (IsUnderPostmaster && - XLogCheckpointNeeded()) + XLogCheckpointNeeded(openLogId, openLogSeg)) { (void) GetRedoRecPtr(); - if (XLogCheckpointNeeded()) + if (XLogCheckpointNeeded(openLogId, openLogSeg)) RequestCheckpoint(CHECKPOINT_CAUSE_XLOG); } } @@ -5653,7 +5657,6 @@ StartupXLOG(void) XLogRecord *record; uint32 freespace; TransactionId oldestActiveXID; - bool bgwriterLaunched = false; /* * Read control file and check XLOG status looks valid. @@ -7576,6 +7579,21 @@ CreateRestartPoint(int flags) return false; } + /* + * Update the shared RedoRecPtr so that the startup process can + * calculate the number of segments replayed since last restartpoint, + * and request a restartpoint if it exceeds checkpoint_segments. + * + * You need to hold WALInsertLock and info_lck to update it, although + * during recovery acquiring WALInsertLock is just pro forma, because + * there is no other processes updating Insert.RedoRecPtr. + */ + LWLockAcquire(WALInsertLock, LW_EXCLUSIVE); + SpinLockAcquire(&xlogctl->info_lck); + xlogctl->Insert.RedoRecPtr = lastCheckPoint.redo; + SpinLockRelease(&xlogctl->info_lck); + LWLockRelease(WALInsertLock); + if (log_checkpoints) { /* @@ -9209,6 +9227,20 @@ XLogPageRead(XLogRecPtr *RecPtr, int emode, bool fetching_ckpt, */ if (readFile >= 0 && !XLByteInSeg(*RecPtr, readId, readSeg)) { + /* + * Signal bgwriter to start a restartpoint if we've replayed too + * much xlog since the last one. + */ + if (StandbyMode && bgwriterLaunched) + { + if (XLogCheckpointNeeded(readId, readSeg)) + { + (void) GetRedoRecPtr(); + if (XLogCheckpointNeeded(readId, readSeg)) + RequestCheckpoint(CHECKPOINT_CAUSE_XLOG); + } + } + close(readFile); readFile = -1; readSource = 0; diff --git a/src/backend/replication/walreceiver.c b/src/backend/replication/walreceiver.c index 11abe6eb8b..c5a6b315eb 100644 --- a/src/backend/replication/walreceiver.c +++ b/src/backend/replication/walreceiver.c @@ -29,7 +29,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/replication/walreceiver.c,v 1.13 2010/06/09 00:54:39 ishii Exp $ + * $PostgreSQL: pgsql/src/backend/replication/walreceiver.c,v 1.14 2010/06/09 15:04:07 heikki Exp $ * *------------------------------------------------------------------------- */ @@ -506,13 +506,6 @@ XLogWalRcvWrite(char *buf, Size nbytes, XLogRecPtr recptr) buf += byteswritten; LogstreamResult.Write = recptr; - - /* - * XXX: Should we signal bgwriter to start a restartpoint if we've - * consumed too much xlog since the last one, like in normal - * processing? But this is not worth doing unless a restartpoint can - * be created independently from a checkpoint record. - */ } }