@@ -289,35 +289,16 @@ static XLogRecPtr RedoStartLSN = {0, 0};
289
289
* These structs are identical but are declared separately to indicate their
290
290
* slightly different functions.
291
291
*
292
- * We do a lot of pushups to minimize the amount of access to lockable
293
- * shared memory values. There are actually three shared-memory copies of
294
- * LogwrtResult, plus one unshared copy in each backend. Here's how it works:
295
- * XLogCtl->LogwrtResult is protected by info_lck
296
- * XLogCtl->Write.LogwrtResult is protected by WALWriteLock
297
- * XLogCtl->Insert.LogwrtResult is protected by WALInsertLock
298
- * One must hold the associated lock to read or write any of these, but
299
- * of course no lock is needed to read/write the unshared LogwrtResult.
300
- *
301
- * XLogCtl->LogwrtResult and XLogCtl->Write.LogwrtResult are both "always
302
- * right", since both are updated by a write or flush operation before
303
- * it releases WALWriteLock. The point of keeping XLogCtl->Write.LogwrtResult
304
- * is that it can be examined/modified by code that already holds WALWriteLock
305
- * without needing to grab info_lck as well.
306
- *
307
- * XLogCtl->Insert.LogwrtResult may lag behind the reality of the other two,
308
- * but is updated when convenient. Again, it exists for the convenience of
309
- * code that is already holding WALInsertLock but not the other locks.
310
- *
311
- * The unshared LogwrtResult may lag behind any or all of these, and again
312
- * is updated when convenient.
292
+ * To read XLogCtl->LogwrtResult, you must hold either info_lck or
293
+ * WALWriteLock. To update it, you need to hold both locks. The point of
294
+ * this arrangement is that the value can be examined by code that already
295
+ * holds WALWriteLock without needing to grab info_lck as well. In addition
296
+ * to the shared variable, each backend has a private copy of LogwrtResult,
297
+ * which is updated when convenient.
313
298
*
314
299
* The request bookkeeping is simpler: there is a shared XLogCtl->LogwrtRqst
315
300
* (protected by info_lck), but we don't need to cache any copies of it.
316
301
*
317
- * Note that this all works because the request and result positions can only
318
- * advance forward, never back up, and so we can easily determine which of two
319
- * values is "more up to date".
320
- *
321
302
* info_lck is only held long enough to read/update the protected variables,
322
303
* so it's a plain spinlock. The other locks are held longer (potentially
323
304
* over I/O operations), so we use LWLocks for them. These locks are:
@@ -354,7 +335,6 @@ typedef struct XLogwrtResult
354
335
*/
355
336
typedef struct XLogCtlInsert
356
337
{
357
- XLogwrtResult LogwrtResult ; /* a recent value of LogwrtResult */
358
338
XLogRecPtr PrevRecord ; /* start of previously-inserted record */
359
339
int curridx ; /* current block index in cache */
360
340
XLogPageHeader currpage ; /* points to header of block in cache */
@@ -388,7 +368,6 @@ typedef struct XLogCtlInsert
388
368
*/
389
369
typedef struct XLogCtlWrite
390
370
{
391
- XLogwrtResult LogwrtResult ; /* current value of LogwrtResult */
392
371
int curridx ; /* cache index of next block to write */
393
372
pg_time_t lastSegSwitchTime ; /* time of last xlog segment switch */
394
373
} XLogCtlWrite ;
@@ -403,7 +382,6 @@ typedef struct XLogCtlData
403
382
404
383
/* Protected by info_lck: */
405
384
XLogwrtRqst LogwrtRqst ;
406
- XLogwrtResult LogwrtResult ;
407
385
uint32 ckptXidEpoch ; /* nextXID & epoch of latest checkpoint */
408
386
TransactionId ckptXid ;
409
387
XLogRecPtr asyncXactLSN ; /* LSN of newest async commit/abort */
@@ -413,6 +391,12 @@ typedef struct XLogCtlData
413
391
/* Protected by WALWriteLock: */
414
392
XLogCtlWrite Write ;
415
393
394
+ /*
395
+ * Protected by info_lck and WALWriteLock (you must hold either lock to
396
+ * read it, but both to update)
397
+ */
398
+ XLogwrtResult LogwrtResult ;
399
+
416
400
/*
417
401
* These values do not change after startup, although the pointed-to pages
418
402
* and xlblocks values certainly do. Permission to read/write the pages
@@ -1015,7 +999,7 @@ begin:;
1015
999
}
1016
1000
1017
1001
LWLockAcquire (WALWriteLock , LW_EXCLUSIVE );
1018
- LogwrtResult = XLogCtl -> Write . LogwrtResult ;
1002
+ LogwrtResult = XLogCtl -> LogwrtResult ;
1019
1003
if (!XLByteLE (RecPtr , LogwrtResult .Flush ))
1020
1004
{
1021
1005
XLogwrtRqst FlushRqst ;
@@ -1188,8 +1172,6 @@ begin:;
1188
1172
SpinLockRelease (& xlogctl -> info_lck );
1189
1173
}
1190
1174
1191
- Write -> LogwrtResult = LogwrtResult ;
1192
-
1193
1175
LWLockRelease (WALWriteLock );
1194
1176
1195
1177
updrqst = false; /* done already */
@@ -1477,18 +1459,13 @@ static bool
1477
1459
AdvanceXLInsertBuffer (bool new_segment )
1478
1460
{
1479
1461
XLogCtlInsert * Insert = & XLogCtl -> Insert ;
1480
- XLogCtlWrite * Write = & XLogCtl -> Write ;
1481
1462
int nextidx = NextBufIdx (Insert -> curridx );
1482
1463
bool update_needed = true;
1483
1464
XLogRecPtr OldPageRqstPtr ;
1484
1465
XLogwrtRqst WriteRqst ;
1485
1466
XLogRecPtr NewPageEndPtr ;
1486
1467
XLogPageHeader NewPage ;
1487
1468
1488
- /* Use Insert->LogwrtResult copy if it's more fresh */
1489
- if (XLByteLT (LogwrtResult .Write , Insert -> LogwrtResult .Write ))
1490
- LogwrtResult = Insert -> LogwrtResult ;
1491
-
1492
1469
/*
1493
1470
* Get ending-offset of the buffer page we need to replace (this may be
1494
1471
* zero if the buffer hasn't been used yet). Fall through if it's already
@@ -1516,21 +1493,19 @@ AdvanceXLInsertBuffer(bool new_segment)
1516
1493
1517
1494
update_needed = false; /* Did the shared-request update */
1518
1495
1519
- if (XLByteLE (OldPageRqstPtr , LogwrtResult .Write ))
1520
- {
1521
- /* OK, someone wrote it already */
1522
- Insert -> LogwrtResult = LogwrtResult ;
1523
- }
1524
- else
1496
+ /*
1497
+ * Now that we have an up-to-date LogwrtResult value, see if we still
1498
+ * need to write it or if someone else already did.
1499
+ */
1500
+ if (!XLByteLE (OldPageRqstPtr , LogwrtResult .Write ))
1525
1501
{
1526
1502
/* Must acquire write lock */
1527
1503
LWLockAcquire (WALWriteLock , LW_EXCLUSIVE );
1528
- LogwrtResult = Write -> LogwrtResult ;
1504
+ LogwrtResult = XLogCtl -> LogwrtResult ;
1529
1505
if (XLByteLE (OldPageRqstPtr , LogwrtResult .Write ))
1530
1506
{
1531
1507
/* OK, someone wrote it already */
1532
1508
LWLockRelease (WALWriteLock );
1533
- Insert -> LogwrtResult = LogwrtResult ;
1534
1509
}
1535
1510
else
1536
1511
{
@@ -1544,7 +1519,6 @@ AdvanceXLInsertBuffer(bool new_segment)
1544
1519
WriteRqst .Flush .xrecoff = 0 ;
1545
1520
XLogWrite (WriteRqst , false, false);
1546
1521
LWLockRelease (WALWriteLock );
1547
- Insert -> LogwrtResult = LogwrtResult ;
1548
1522
TRACE_POSTGRESQL_WAL_BUFFER_WRITE_DIRTY_DONE ();
1549
1523
}
1550
1524
}
@@ -1697,7 +1671,7 @@ XLogWrite(XLogwrtRqst WriteRqst, bool flexible, bool xlog_switch)
1697
1671
/*
1698
1672
* Update local LogwrtResult (caller probably did this already, but...)
1699
1673
*/
1700
- LogwrtResult = Write -> LogwrtResult ;
1674
+ LogwrtResult = XLogCtl -> LogwrtResult ;
1701
1675
1702
1676
/*
1703
1677
* Since successive pages in the xlog cache are consecutively allocated,
@@ -1931,8 +1905,6 @@ XLogWrite(XLogwrtRqst WriteRqst, bool flexible, bool xlog_switch)
1931
1905
xlogctl -> LogwrtRqst .Flush = LogwrtResult .Flush ;
1932
1906
SpinLockRelease (& xlogctl -> info_lck );
1933
1907
}
1934
-
1935
- Write -> LogwrtResult = LogwrtResult ;
1936
1908
}
1937
1909
1938
1910
/*
@@ -2126,7 +2098,7 @@ XLogFlush(XLogRecPtr record)
2126
2098
continue ;
2127
2099
}
2128
2100
/* Got the lock */
2129
- LogwrtResult = XLogCtl -> Write . LogwrtResult ;
2101
+ LogwrtResult = XLogCtl -> LogwrtResult ;
2130
2102
if (!XLByteLE (record , LogwrtResult .Flush ))
2131
2103
{
2132
2104
/* try to write/flush later additions to XLOG as well */
@@ -2268,7 +2240,7 @@ XLogBackgroundFlush(void)
2268
2240
2269
2241
/* now wait for the write lock */
2270
2242
LWLockAcquire (WALWriteLock , LW_EXCLUSIVE );
2271
- LogwrtResult = XLogCtl -> Write . LogwrtResult ;
2243
+ LogwrtResult = XLogCtl -> LogwrtResult ;
2272
2244
if (!XLByteLE (WriteRqstPtr , LogwrtResult .Flush ))
2273
2245
{
2274
2246
XLogwrtRqst WriteRqst ;
@@ -6831,8 +6803,6 @@ StartupXLOG(void)
6831
6803
6832
6804
LogwrtResult .Write = LogwrtResult .Flush = EndOfLog ;
6833
6805
6834
- XLogCtl -> Write .LogwrtResult = LogwrtResult ;
6835
- Insert -> LogwrtResult = LogwrtResult ;
6836
6806
XLogCtl -> LogwrtResult = LogwrtResult ;
6837
6807
6838
6808
XLogCtl -> LogwrtRqst .Write = EndOfLog ;
0 commit comments