@@ -764,15 +764,14 @@ logical_read_xlog_page(XLogReaderState *state, XLogRecPtr targetPagePtr, int req
764
764
/* make sure we have enough WAL available */
765
765
flushptr = WalSndWaitForWal (targetPagePtr + reqLen );
766
766
767
- /* more than one block available */
768
- if (targetPagePtr + XLOG_BLCKSZ <= flushptr )
769
- count = XLOG_BLCKSZ ;
770
- /* not enough WAL synced, that can happen during shutdown */
771
- else if (targetPagePtr + reqLen > flushptr )
767
+ /* fail if not (implies we are going to shut down) */
768
+ if (flushptr < targetPagePtr + reqLen )
772
769
return -1 ;
773
- /* part of the page available */
770
+
771
+ if (targetPagePtr + XLOG_BLCKSZ <= flushptr )
772
+ count = XLOG_BLCKSZ ; /* more than one block available */
774
773
else
775
- count = flushptr - targetPagePtr ;
774
+ count = flushptr - targetPagePtr ; /* part of the page available */
776
775
777
776
/* now actually read the data, we know it's there */
778
777
XLogRead (cur_page , targetPagePtr , XLOG_BLCKSZ );
@@ -1266,7 +1265,11 @@ WalSndUpdateProgress(LogicalDecodingContext *ctx, XLogRecPtr lsn, TransactionId
1266
1265
}
1267
1266
1268
1267
/*
1269
- * Wait till WAL < loc is flushed to disk so it can be safely read.
1268
+ * Wait till WAL < loc is flushed to disk so it can be safely sent to client.
1269
+ *
1270
+ * Returns end LSN of flushed WAL. Normally this will be >= loc, but
1271
+ * if we detect a shutdown request (either from postmaster or client)
1272
+ * we will return early, so caller must always check.
1270
1273
*/
1271
1274
static XLogRecPtr
1272
1275
WalSndWaitForWal (XLogRecPtr loc )
@@ -1333,9 +1336,7 @@ WalSndWaitForWal(XLogRecPtr loc)
1333
1336
RecentFlushPtr = GetXLogReplayRecPtr (NULL );
1334
1337
1335
1338
/*
1336
- * If postmaster asked us to stop, don't wait here anymore. This will
1337
- * cause the xlogreader to return without reading a full record, which
1338
- * is the fastest way to reach the mainloop which then can quit.
1339
+ * If postmaster asked us to stop, don't wait anymore.
1339
1340
*
1340
1341
* It's important to do this check after the recomputation of
1341
1342
* RecentFlushPtr, so we can send all remaining data before shutting
@@ -1366,14 +1367,20 @@ WalSndWaitForWal(XLogRecPtr loc)
1366
1367
WalSndCaughtUp = true;
1367
1368
1368
1369
/*
1369
- * Try to flush pending output to the client. Also wait for the socket
1370
- * becoming writable, if there's still pending output after an attempt
1371
- * to flush. Otherwise we might just sit on output data while waiting
1372
- * for new WAL being generated.
1370
+ * Try to flush any pending output to the client.
1373
1371
*/
1374
1372
if (pq_flush_if_writable () != 0 )
1375
1373
WalSndShutdown ();
1376
1374
1375
+ /*
1376
+ * If we have received CopyDone from the client, sent CopyDone
1377
+ * ourselves, and the output buffer is empty, it's time to exit
1378
+ * streaming, so fail the current WAL fetch request.
1379
+ */
1380
+ if (streamingDoneReceiving && streamingDoneSending &&
1381
+ !pq_is_send_pending ())
1382
+ break ;
1383
+
1377
1384
now = GetCurrentTimestamp ();
1378
1385
1379
1386
/* die if timeout was reached */
@@ -1382,6 +1389,13 @@ WalSndWaitForWal(XLogRecPtr loc)
1382
1389
/* Send keepalive if the time has come */
1383
1390
WalSndKeepaliveIfNecessary (now );
1384
1391
1392
+ /*
1393
+ * Sleep until something happens or we time out. Also wait for the
1394
+ * socket becoming writable, if there's still pending output.
1395
+ * Otherwise we might sit on sendable output data while waiting for
1396
+ * new WAL to be generated. (But if we have nothing to send, we don't
1397
+ * want to wake on socket-writable.)
1398
+ */
1385
1399
sleeptime = WalSndComputeSleeptime (now );
1386
1400
1387
1401
wakeEvents = WL_LATCH_SET | WL_POSTMASTER_DEATH |
@@ -1390,7 +1404,6 @@ WalSndWaitForWal(XLogRecPtr loc)
1390
1404
if (pq_is_send_pending ())
1391
1405
wakeEvents |= WL_SOCKET_WRITEABLE ;
1392
1406
1393
- /* Sleep until something happens or we time out */
1394
1407
WaitLatchOrSocket (MyLatch , wakeEvents ,
1395
1408
MyProcPort -> sock , sleeptime ,
1396
1409
WAIT_EVENT_WAL_SENDER_WAIT_WAL );
@@ -2115,7 +2128,8 @@ WalSndLoop(WalSndSendDataCallback send_data)
2115
2128
* ourselves, and the output buffer is empty, it's time to exit
2116
2129
* streaming.
2117
2130
*/
2118
- if (!pq_is_send_pending () && streamingDoneSending && streamingDoneReceiving )
2131
+ if (streamingDoneReceiving && streamingDoneSending &&
2132
+ !pq_is_send_pending ())
2119
2133
break ;
2120
2134
2121
2135
/*
0 commit comments