aboutsummaryrefslogtreecommitdiff
path: root/src/backend/access/transam/xlog.c
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2012-05-08 23:05:58 -0400
committerTom Lane <tgl@sss.pgh.pa.us>2012-05-08 23:06:40 -0400
commitacd4c7d58baf09fc278a0f8c1170fba2d56ccdd5 (patch)
tree67a9b17ba1bfa2b5414460287b6928b77d78f5d8 /src/backend/access/transam/xlog.c
parent8b77e226fbf4834a03fcef2fa31aa85dac40c941 (diff)
downloadpostgresql-acd4c7d58baf09fc278a0f8c1170fba2d56ccdd5.tar.gz
postgresql-acd4c7d58baf09fc278a0f8c1170fba2d56ccdd5.zip
Fix an issue in recent walwriter hibernation patch.
Users of asynchronous-commit mode expect there to be a guaranteed maximum delay before an async commit's WAL records get flushed to disk. The original version of the walwriter hibernation patch broke that. Add an extra shared-memory flag to allow async commits to kick the walwriter out of hibernation mode, without adding any noticeable overhead in cases where no action is needed.
Diffstat (limited to 'src/backend/access/transam/xlog.c')
-rw-r--r--src/backend/access/transam/xlog.c48
1 files changed, 41 insertions, 7 deletions
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 6d3a4cd3dfe..d3650bdf051 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -427,6 +427,13 @@ typedef struct XLogCtlData
bool SharedHotStandbyActive;
/*
+ * WalWriterSleeping indicates whether the WAL writer is currently in
+ * low-power mode (and hence should be nudged if an async commit occurs).
+ * Protected by info_lck.
+ */
+ bool WalWriterSleeping;
+
+ /*
* 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.
@@ -1903,32 +1910,44 @@ XLogWrite(XLogwrtRqst WriteRqst, bool flexible, bool xlog_switch)
/*
* Record the LSN for an asynchronous transaction commit/abort
- * and nudge the WALWriter if there is a complete page to write.
+ * and nudge the WALWriter if there is work for it to do.
* (This should not be called for synchronous commits.)
*/
void
XLogSetAsyncXactLSN(XLogRecPtr asyncXactLSN)
{
XLogRecPtr WriteRqstPtr = asyncXactLSN;
+ bool sleeping;
/* use volatile pointer to prevent code rearrangement */
volatile XLogCtlData *xlogctl = XLogCtl;
SpinLockAcquire(&xlogctl->info_lck);
LogwrtResult = xlogctl->LogwrtResult;
+ sleeping = xlogctl->WalWriterSleeping;
if (XLByteLT(xlogctl->asyncXactLSN, asyncXactLSN))
xlogctl->asyncXactLSN = asyncXactLSN;
SpinLockRelease(&xlogctl->info_lck);
- /* back off to last completed page boundary */
- WriteRqstPtr.xrecoff -= WriteRqstPtr.xrecoff % XLOG_BLCKSZ;
+ /*
+ * If the WALWriter is sleeping, we should kick it to make it come out of
+ * low-power mode. Otherwise, determine whether there's a full page of
+ * WAL available to write.
+ */
+ if (!sleeping)
+ {
+ /* back off to last completed page boundary */
+ WriteRqstPtr.xrecoff -= WriteRqstPtr.xrecoff % XLOG_BLCKSZ;
- /* if we have already flushed that far, we're done */
- if (XLByteLE(WriteRqstPtr, LogwrtResult.Flush))
- return;
+ /* if we have already flushed that far, we're done */
+ if (XLByteLE(WriteRqstPtr, LogwrtResult.Flush))
+ return;
+ }
/*
- * Nudge the WALWriter if we have a full page of WAL to write.
+ * Nudge the WALWriter: it has a full page of WAL to write, or we want
+ * it to come out of low-power mode so that this async commit will reach
+ * disk within the expected amount of time.
*/
if (ProcGlobal->walwriterLatch)
SetLatch(ProcGlobal->walwriterLatch);
@@ -5100,6 +5119,7 @@ XLOGShmemInit(void)
XLogCtl->XLogCacheBlck = XLOGbuffers - 1;
XLogCtl->SharedRecoveryInProgress = true;
XLogCtl->SharedHotStandbyActive = false;
+ XLogCtl->WalWriterSleeping = false;
XLogCtl->Insert.currpage = (XLogPageHeader) (XLogCtl->pages);
SpinLockInit(&XLogCtl->info_lck);
InitSharedLatch(&XLogCtl->recoveryWakeupLatch);
@@ -10479,3 +10499,17 @@ WakeupRecovery(void)
{
SetLatch(&XLogCtl->recoveryWakeupLatch);
}
+
+/*
+ * Update the WalWriterSleeping flag.
+ */
+void
+SetWalWriterSleeping(bool sleeping)
+{
+ /* use volatile pointer to prevent code rearrangement */
+ volatile XLogCtlData *xlogctl = XLogCtl;
+
+ SpinLockAcquire(&xlogctl->info_lck);
+ xlogctl->WalWriterSleeping = sleeping;
+ SpinLockRelease(&xlogctl->info_lck);
+}