aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/backend/access/transam/xlog.c33
-rw-r--r--src/backend/postmaster/walwriter.c27
-rw-r--r--src/include/access/xlog.h2
3 files changed, 44 insertions, 18 deletions
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 0d494e2e3bf..20c04240b70 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -433,6 +433,11 @@ typedef struct XLogCtlData
Latch recoveryWakeupLatch;
/*
+ * WALWriterLatch is used to wake up the WALWriter to write some WAL.
+ */
+ Latch WALWriterLatch;
+
+ /*
* During recovery, we keep a copy of the latest checkpoint record here.
* Used by the background writer when it wants to create a restartpoint.
*
@@ -1916,19 +1921,35 @@ XLogWrite(XLogwrtRqst WriteRqst, bool flexible, bool xlog_switch)
}
/*
- * Record the LSN for an asynchronous transaction commit/abort.
+ * Record the LSN for an asynchronous transaction commit/abort
+ * and nudge the WALWriter if there is a complete page to write.
* (This should not be called for for synchronous commits.)
*/
void
XLogSetAsyncXactLSN(XLogRecPtr asyncXactLSN)
{
+ XLogRecPtr WriteRqstPtr = asyncXactLSN;
+
/* use volatile pointer to prevent code rearrangement */
volatile XLogCtlData *xlogctl = XLogCtl;
SpinLockAcquire(&xlogctl->info_lck);
+ LogwrtResult = xlogctl->LogwrtResult;
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 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.
+ */
+ SetLatch(&XLogCtl->WALWriterLatch);
}
/*
@@ -5072,6 +5093,7 @@ XLOGShmemInit(void)
XLogCtl->Insert.currpage = (XLogPageHeader) (XLogCtl->pages);
SpinLockInit(&XLogCtl->info_lck);
InitSharedLatch(&XLogCtl->recoveryWakeupLatch);
+ InitSharedLatch(&XLogCtl->WALWriterLatch);
/*
* If we are not in bootstrap mode, pg_control should already exist. Read
@@ -10013,3 +10035,12 @@ WakeupRecovery(void)
{
SetLatch(&XLogCtl->recoveryWakeupLatch);
}
+
+/*
+ * Manage the WALWriterLatch
+ */
+Latch *
+WALWriterLatch(void)
+{
+ return &XLogCtl->WALWriterLatch;
+}
diff --git a/src/backend/postmaster/walwriter.c b/src/backend/postmaster/walwriter.c
index 23c4aacd7da..157728e20e7 100644
--- a/src/backend/postmaster/walwriter.c
+++ b/src/backend/postmaster/walwriter.c
@@ -11,7 +11,8 @@
*
* Note that as with the bgwriter for shared buffers, regular backends are
* still empowered to issue WAL writes and fsyncs when the walwriter doesn't
- * keep up.
+ * keep up. This means that the WALWriter is not an essential process and
+ * can shutdown quickly when requested.
*
* Because the walwriter's cycle is directly linked to the maximum delay
* before async-commit transactions are guaranteed committed, it's probably
@@ -76,7 +77,6 @@ static void wal_quickdie(SIGNAL_ARGS);
static void WalSigHupHandler(SIGNAL_ARGS);
static void WalShutdownHandler(SIGNAL_ARGS);
-
/*
* Main entry point for walwriter process
*
@@ -89,6 +89,8 @@ WalWriterMain(void)
sigjmp_buf local_sigjmp_buf;
MemoryContext walwriter_context;
+ InitLatch(WALWriterLatch()); /* initialize latch used in main loop */
+
/*
* If possible, make this process a group leader, so that the postmaster
* can signal any child processes too. (walwriter probably never has any
@@ -220,7 +222,7 @@ WalWriterMain(void)
*/
for (;;)
{
- long udelay;
+ ResetLatch(WALWriterLatch());
/*
* Emergency bailout if postmaster has died. This is to avoid the
@@ -248,20 +250,9 @@ WalWriterMain(void)
*/
XLogBackgroundFlush();
- /*
- * Delay until time to do something more, but fall out of delay
- * reasonably quickly if signaled.
- */
- udelay = WalWriterDelay * 1000L;
- while (udelay > 999999L)
- {
- if (got_SIGHUP || shutdown_requested)
- break;
- pg_usleep(1000000L);
- udelay -= 1000000L;
- }
- if (!(got_SIGHUP || shutdown_requested))
- pg_usleep(udelay);
+ (void) WaitLatch(WALWriterLatch(),
+ WL_LATCH_SET | WL_TIMEOUT | WL_POSTMASTER_DEATH,
+ WalWriterDelay /* ms */);
}
}
@@ -308,6 +299,7 @@ static void
WalSigHupHandler(SIGNAL_ARGS)
{
got_SIGHUP = true;
+ SetLatch(WALWriterLatch());
}
/* SIGTERM: set flag to exit normally */
@@ -315,4 +307,5 @@ static void
WalShutdownHandler(SIGNAL_ARGS)
{
shutdown_requested = true;
+ SetLatch(WALWriterLatch());
}
diff --git a/src/include/access/xlog.h b/src/include/access/xlog.h
index 83106b80e4e..6344a850dcd 100644
--- a/src/include/access/xlog.h
+++ b/src/include/access/xlog.h
@@ -16,6 +16,7 @@
#include "datatype/timestamp.h"
#include "lib/stringinfo.h"
#include "storage/buf.h"
+#include "storage/latch.h"
#include "utils/pg_crc.h"
/*
@@ -319,6 +320,7 @@ extern TimeLineID GetRecoveryTargetTLI(void);
extern bool CheckPromoteSignal(void);
extern void WakeupRecovery(void);
+extern Latch *WALWriterLatch(void);
/*
* Starting/stopping a base backup