v3-0001-Use-WALReadFromBuffers-in-more-places.patch
application/octet-stream
Filename: v3-0001-Use-WALReadFromBuffers-in-more-places.patch
Type: application/octet-stream
Part: 0
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: format-patch
Series: patch v3-0001
Subject: Use WALReadFromBuffers in more places
| File | + | − |
|---|---|---|
| src/backend/access/transam/xlogutils.c | 20 | 3 |
| src/backend/replication/walsender.c | 50 | 27 |
From 60aa2e18df060fcc341847585aa8cd4dcddea5ed Mon Sep 17 00:00:00 2001
From: Bharath Rupireddy <rupiredd@amazon.com>
Date: Sun, 14 Sep 2025 04:54:12 +0000
Subject: [PATCH v3] Use WALReadFromBuffers in more places
Commit 91f2cae introduced WALReadFromBuffers but used it only for
physical replication walsenders. There are several other callers
that use the read_local_xlog_page page_read callback, and logical
replication walsenders can also benefit from reading WAL from WAL
buffers using the new function. This commit extends the use of
WALReadFromBuffers to these callers.
Author: Bharath Rupireddy
Reviewed-by: Jingtang Zhang, Nitin Jadhav
Discussion: https://www.postgresql.org/message-id/CALj2ACVfF2Uj9NoFy-5m98HNtjHpuD17EDE9twVeJng-jTAe7A%40mail.gmail.com
---
src/backend/access/transam/xlogutils.c | 23 +++++++-
src/backend/replication/walsender.c | 77 +++++++++++++++++---------
2 files changed, 70 insertions(+), 30 deletions(-)
diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 38176d9688e..3e5b4f75feb 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -876,6 +876,7 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
int count;
WALReadError errinfo;
TimeLineID currTLI;
+ Size bytesRead;
loc = targetPagePtr + reqLen;
@@ -995,9 +996,25 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
count = read_upto - targetPagePtr;
}
- if (!WALRead(state, cur_page, targetPagePtr, count, tli,
- &errinfo))
- WALReadRaiseError(&errinfo);
+ /* First attempt to read from WAL buffers */
+ bytesRead = WALReadFromBuffers(cur_page, targetPagePtr, count, currTLI);
+
+ /* If we still have bytes to read, get them from WAL file */
+ if (bytesRead < count)
+ {
+ if (!WALRead(state,
+ cur_page + bytesRead,
+ targetPagePtr + bytesRead,
+ count - bytesRead,
+ tli,
+ &errinfo))
+ {
+ WALReadRaiseError(&errinfo);
+ }
+ bytesRead = count; /* All requested bytes read */
+ }
+
+ Assert(bytesRead == count);
/* number of valid bytes in the buffer */
return count;
diff --git a/src/backend/replication/walsender.c b/src/backend/replication/walsender.c
index 59822f22b8d..937936c3550 100644
--- a/src/backend/replication/walsender.c
+++ b/src/backend/replication/walsender.c
@@ -1036,6 +1036,7 @@ logical_read_xlog_page(XLogReaderState *state, XLogRecPtr targetPagePtr, int req
WALReadError errinfo;
XLogSegNo segno;
TimeLineID currTLI;
+ Size bytesRead;
/*
* Make sure we have enough WAL available before retrieving the current
@@ -1073,16 +1074,29 @@ logical_read_xlog_page(XLogReaderState *state, XLogRecPtr targetPagePtr, int req
else
count = flushptr - targetPagePtr; /* part of the page available */
- /* now actually read the data, we know it's there */
- if (!WALRead(state,
- cur_page,
- targetPagePtr,
- count,
- currTLI, /* Pass the current TLI because only
+ /* First attempt to read from WAL buffers */
+ bytesRead = WALReadFromBuffers(cur_page, targetPagePtr, count, currTLI);
+
+ targetPagePtr += bytesRead;
+
+ /* If we still have bytes to read, get them from WAL file */
+ if (bytesRead < count)
+ {
+ if (!WALRead(state,
+ cur_page + bytesRead,
+ targetPagePtr,
+ count - bytesRead,
+ currTLI, /* Pass the current TLI because only
* WalSndSegmentOpen controls whether new TLI
* is needed. */
- &errinfo))
- WALReadRaiseError(&errinfo);
+ &errinfo))
+ {
+ WALReadRaiseError(&errinfo);
+ }
+ bytesRead = count; /* All requested bytes read */
+ }
+
+ Assert(bytesRead == count);
/*
* After reading into the buffer, check that what we read was valid. We do
@@ -3176,7 +3190,7 @@ XLogSendPhysical(void)
Size nbytes;
XLogSegNo segno;
WALReadError errinfo;
- Size rbytes;
+ Size bytesRead;
/* If requested switch the WAL sender to the stopping state. */
if (got_STOPPING)
@@ -3392,24 +3406,33 @@ XLogSendPhysical(void)
enlargeStringInfo(&output_message, nbytes);
retry:
- /* attempt to read WAL from WAL buffers first */
- rbytes = WALReadFromBuffers(&output_message.data[output_message.len],
- startptr, nbytes, xlogreader->seg.ws_tli);
- output_message.len += rbytes;
- startptr += rbytes;
- nbytes -= rbytes;
-
- /* now read the remaining WAL from WAL file */
- if (nbytes > 0 &&
- !WALRead(xlogreader,
- &output_message.data[output_message.len],
- startptr,
- nbytes,
- xlogreader->seg.ws_tli, /* Pass the current TLI because
- * only WalSndSegmentOpen controls
- * whether new TLI is needed. */
- &errinfo))
- WALReadRaiseError(&errinfo);
+ /* First attempt to read from WAL buffers */
+ bytesRead = WALReadFromBuffers(&output_message.data[output_message.len],
+ startptr,
+ nbytes,
+ xlogreader->seg.ws_tli);
+
+ startptr += bytesRead;
+
+ /* If we still have bytes to read, get them from WAL file */
+ if (bytesRead < nbytes)
+ {
+ if (!WALRead(xlogreader,
+ &output_message.data[output_message.len + bytesRead],
+ startptr,
+ nbytes - bytesRead,
+ xlogreader->seg.ws_tli, /* Pass the current TLI
+ * because only
+ * WalSndSegmentOpen controls
+ * whether new TLI is needed. */
+ &errinfo))
+ {
+ WALReadRaiseError(&errinfo);
+ }
+ bytesRead = nbytes; /* All requested bytes read */
+ }
+
+ Assert(bytesRead == nbytes);
/* See logical_read_xlog_page(). */
XLByteToSeg(startptr, segno, xlogreader->segcxt.ws_segsize);
--
2.47.3