Skip to content

Commit c9920a9

Browse files
committed
Split XLogCtl->LogwrtResult into separate struct members
After this change we have XLogCtl->logWriteResult and ->logFlushResult. There's no functional change, other than the fact that the assignment from shared memory to local is no longer done via struct assignment, but instead using a macro that copies each member separately. The current representation is inconvenient going forward; notably, we would like to add a new member "Copy" (to keep track of the last position copied into WAL buffers), so the symmetry between the values in shared memory vs. those in local would be lost. This also gives us freedom to later change the concurrency model for the values in shared memory: we can make them use atomics instead of relying on the info_lck spinlock. Reviewed-by: Bharath Rupireddy <bharath.rupireddyforpostgres@gmail.com> Discussion: https://postgr.es/m/202404031119.cd2kugjk2vho@alvherre.pgsql
1 parent deb1486 commit c9920a9

File tree

1 file changed

+35
-24
lines changed
  • src/backend/access/transam

1 file changed

+35
-24
lines changed

src/backend/access/transam/xlog.c

Lines changed: 35 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -291,16 +291,15 @@ static bool doPageWrites;
291291
*
292292
* LogwrtRqst indicates a byte position that we need to write and/or fsync
293293
* the log up to (all records before that point must be written or fsynced).
294-
* LogwrtResult indicates the byte positions we have already written/fsynced.
295-
* These structs are identical but are declared separately to indicate their
296-
* slightly different functions.
294+
* The positions already written/fsynced are maintained in logWriteResult
295+
* and logFlushResult.
297296
*
298-
* To read XLogCtl->LogwrtResult, you must hold either info_lck or
299-
* WALWriteLock. To update it, you need to hold both locks. The point of
300-
* this arrangement is that the value can be examined by code that already
301-
* holds WALWriteLock without needing to grab info_lck as well. In addition
302-
* to the shared variable, each backend has a private copy of LogwrtResult,
303-
* which is updated when convenient.
297+
* To read XLogCtl->logWriteResult or ->logFlushResult, you must hold either
298+
* info_lck or WALWriteLock. To update them, you need to hold both locks.
299+
* The point of this arrangement is that the value can be examined by code
300+
* that already holds WALWriteLock without needing to grab info_lck as well.
301+
* In addition to the shared variable, each backend has a private copy of
302+
* both in LogwrtResult, which is updated when convenient.
304303
*
305304
* The request bookkeeping is simpler: there is a shared XLogCtl->LogwrtRqst
306305
* (protected by info_lck), but we don't need to cache any copies of it.
@@ -478,7 +477,8 @@ typedef struct XLogCtlData
478477
* Protected by info_lck and WALWriteLock (you must hold either lock to
479478
* read it, but both to update)
480479
*/
481-
XLogwrtResult LogwrtResult;
480+
XLogRecPtr logWriteResult; /* last byte + 1 written out */
481+
XLogRecPtr logFlushResult; /* last byte + 1 flushed */
482482

483483
/*
484484
* Latest initialized page in the cache (last byte position + 1).
@@ -614,6 +614,15 @@ static int UsableBytesInSegment;
614614
*/
615615
static XLogwrtResult LogwrtResult = {0, 0};
616616

617+
/*
618+
* Update local copy of shared XLogCtl->log{Write,Flush}Result
619+
*/
620+
#define RefreshXLogWriteResult(_target) \
621+
do { \
622+
_target.Write = XLogCtl->logWriteResult; \
623+
_target.Flush = XLogCtl->logFlushResult; \
624+
} while (0)
625+
617626
/*
618627
* openLogFile is -1 or a kernel FD for an open log file segment.
619628
* openLogSegNo identifies the segment, and openLogTLI the corresponding TLI.
@@ -960,7 +969,7 @@ XLogInsertRecord(XLogRecData *rdata,
960969
if (XLogCtl->LogwrtRqst.Write < EndPos)
961970
XLogCtl->LogwrtRqst.Write = EndPos;
962971
/* update local result copy while I have the chance */
963-
LogwrtResult = XLogCtl->LogwrtResult;
972+
RefreshXLogWriteResult(LogwrtResult);
964973
SpinLockRelease(&XLogCtl->info_lck);
965974
}
966975

@@ -1984,7 +1993,7 @@ AdvanceXLInsertBuffer(XLogRecPtr upto, TimeLineID tli, bool opportunistic)
19841993
SpinLockAcquire(&XLogCtl->info_lck);
19851994
if (XLogCtl->LogwrtRqst.Write < OldPageRqstPtr)
19861995
XLogCtl->LogwrtRqst.Write = OldPageRqstPtr;
1987-
LogwrtResult = XLogCtl->LogwrtResult;
1996+
RefreshXLogWriteResult(LogwrtResult);
19881997
SpinLockRelease(&XLogCtl->info_lck);
19891998

19901999
/*
@@ -2005,7 +2014,7 @@ AdvanceXLInsertBuffer(XLogRecPtr upto, TimeLineID tli, bool opportunistic)
20052014

20062015
LWLockAcquire(WALWriteLock, LW_EXCLUSIVE);
20072016

2008-
LogwrtResult = XLogCtl->LogwrtResult;
2017+
RefreshXLogWriteResult(LogwrtResult);
20092018
if (LogwrtResult.Write >= OldPageRqstPtr)
20102019
{
20112020
/* OK, someone wrote it already */
@@ -2289,7 +2298,7 @@ XLogWrite(XLogwrtRqst WriteRqst, TimeLineID tli, bool flexible)
22892298
/*
22902299
* Update local LogwrtResult (caller probably did this already, but...)
22912300
*/
2292-
LogwrtResult = XLogCtl->LogwrtResult;
2301+
RefreshXLogWriteResult(LogwrtResult);
22932302

22942303
/*
22952304
* Since successive pages in the xlog cache are consecutively allocated,
@@ -2549,7 +2558,8 @@ XLogWrite(XLogwrtRqst WriteRqst, TimeLineID tli, bool flexible)
25492558
*/
25502559
{
25512560
SpinLockAcquire(&XLogCtl->info_lck);
2552-
XLogCtl->LogwrtResult = LogwrtResult;
2561+
XLogCtl->logWriteResult = LogwrtResult.Write;
2562+
XLogCtl->logFlushResult = LogwrtResult.Flush;
25532563
if (XLogCtl->LogwrtRqst.Write < LogwrtResult.Write)
25542564
XLogCtl->LogwrtRqst.Write = LogwrtResult.Write;
25552565
if (XLogCtl->LogwrtRqst.Flush < LogwrtResult.Flush)
@@ -2572,7 +2582,7 @@ XLogSetAsyncXactLSN(XLogRecPtr asyncXactLSN)
25722582
XLogRecPtr prevAsyncXactLSN;
25732583

25742584
SpinLockAcquire(&XLogCtl->info_lck);
2575-
LogwrtResult = XLogCtl->LogwrtResult;
2585+
RefreshXLogWriteResult(LogwrtResult);
25762586
sleeping = XLogCtl->WalWriterSleeping;
25772587
prevAsyncXactLSN = XLogCtl->asyncXactLSN;
25782588
if (XLogCtl->asyncXactLSN < asyncXactLSN)
@@ -2784,7 +2794,7 @@ XLogFlush(XLogRecPtr record)
27842794
SpinLockAcquire(&XLogCtl->info_lck);
27852795
if (WriteRqstPtr < XLogCtl->LogwrtRqst.Write)
27862796
WriteRqstPtr = XLogCtl->LogwrtRqst.Write;
2787-
LogwrtResult = XLogCtl->LogwrtResult;
2797+
RefreshXLogWriteResult(LogwrtResult);
27882798
SpinLockRelease(&XLogCtl->info_lck);
27892799

27902800
/* done already? */
@@ -2815,7 +2825,7 @@ XLogFlush(XLogRecPtr record)
28152825
}
28162826

28172827
/* Got the lock; recheck whether request is satisfied */
2818-
LogwrtResult = XLogCtl->LogwrtResult;
2828+
RefreshXLogWriteResult(LogwrtResult);
28192829
if (record <= LogwrtResult.Flush)
28202830
{
28212831
LWLockRelease(WALWriteLock);
@@ -2939,7 +2949,7 @@ XLogBackgroundFlush(void)
29392949

29402950
/* read LogwrtResult and update local state */
29412951
SpinLockAcquire(&XLogCtl->info_lck);
2942-
LogwrtResult = XLogCtl->LogwrtResult;
2952+
RefreshXLogWriteResult(LogwrtResult);
29432953
WriteRqst = XLogCtl->LogwrtRqst;
29442954
SpinLockRelease(&XLogCtl->info_lck);
29452955

@@ -3027,7 +3037,7 @@ XLogBackgroundFlush(void)
30273037
/* now wait for any in-progress insertions to finish and get write lock */
30283038
WaitXLogInsertionsToFinish(WriteRqst.Write);
30293039
LWLockAcquire(WALWriteLock, LW_EXCLUSIVE);
3030-
LogwrtResult = XLogCtl->LogwrtResult;
3040+
RefreshXLogWriteResult(LogwrtResult);
30313041
if (WriteRqst.Write > LogwrtResult.Write ||
30323042
WriteRqst.Flush > LogwrtResult.Flush)
30333043
{
@@ -3116,7 +3126,7 @@ XLogNeedsFlush(XLogRecPtr record)
31163126

31173127
/* read LogwrtResult and update local state */
31183128
SpinLockAcquire(&XLogCtl->info_lck);
3119-
LogwrtResult = XLogCtl->LogwrtResult;
3129+
RefreshXLogWriteResult(LogwrtResult);
31203130
SpinLockRelease(&XLogCtl->info_lck);
31213131

31223132
/* check again */
@@ -5953,7 +5963,8 @@ StartupXLOG(void)
59535963

59545964
LogwrtResult.Write = LogwrtResult.Flush = EndOfLog;
59555965

5956-
XLogCtl->LogwrtResult = LogwrtResult;
5966+
XLogCtl->logWriteResult = LogwrtResult.Write;
5967+
XLogCtl->logFlushResult = LogwrtResult.Flush;
59575968

59585969
XLogCtl->LogwrtRqst.Write = EndOfLog;
59595970
XLogCtl->LogwrtRqst.Flush = EndOfLog;
@@ -6400,7 +6411,7 @@ GetFlushRecPtr(TimeLineID *insertTLI)
64006411
Assert(XLogCtl->SharedRecoveryState == RECOVERY_STATE_DONE);
64016412

64026413
SpinLockAcquire(&XLogCtl->info_lck);
6403-
LogwrtResult = XLogCtl->LogwrtResult;
6414+
RefreshXLogWriteResult(LogwrtResult);
64046415
SpinLockRelease(&XLogCtl->info_lck);
64056416

64066417
/*
@@ -9316,7 +9327,7 @@ XLogRecPtr
93169327
GetXLogWriteRecPtr(void)
93179328
{
93189329
SpinLockAcquire(&XLogCtl->info_lck);
9319-
LogwrtResult = XLogCtl->LogwrtResult;
9330+
RefreshXLogWriteResult(LogwrtResult);
93209331
SpinLockRelease(&XLogCtl->info_lck);
93219332

93229333
return LogwrtResult.Write;

0 commit comments

Comments
 (0)