@@ -457,15 +457,6 @@ typedef struct XLogCtlInsert
457
457
XLogRecPtr lastBackupStart ;
458
458
} XLogCtlInsert ;
459
459
460
- /*
461
- * Shared state data for XLogWrite/XLogFlush.
462
- */
463
- typedef struct XLogCtlWrite
464
- {
465
- int curridx ; /* cache index of next block to write */
466
- pg_time_t lastSegSwitchTime ; /* time of last xlog segment switch */
467
- } XLogCtlWrite ;
468
-
469
460
/*
470
461
* Total shared-memory state for XLOG.
471
462
*/
@@ -482,12 +473,12 @@ typedef struct XLogCtlData
482
473
XLogSegNo lastRemovedSegNo ; /* latest removed/recycled XLOG
483
474
* segment */
484
475
485
- /* Fake LSN counter, for unlogged relations. Protected by ulsn_lck */
476
+ /* Fake LSN counter, for unlogged relations. Protected by ulsn_lck. */
486
477
XLogRecPtr unloggedLSN ;
487
478
slock_t ulsn_lck ;
488
479
489
- /* Protected by WALWriteLock: */
490
- XLogCtlWrite Write ;
480
+ /* Time of last xlog segment switch. Protected by WALWriteLock. */
481
+ pg_time_t lastSegSwitchTime ;
491
482
492
483
/*
493
484
* Protected by info_lck and WALWriteLock (you must hold either lock to
@@ -496,15 +487,15 @@ typedef struct XLogCtlData
496
487
XLogwrtResult LogwrtResult ;
497
488
498
489
/*
499
- * Latest initialized block index in cache.
490
+ * Latest initialized page in the cache (last byte position + 1) .
500
491
*
501
- * To change curridx and the identity of a buffer, you need to hold
502
- * WALBufMappingLock. To change the identity of a buffer that's still
492
+ * To change the identity of a buffer (and InitializedUpTo) , you need to
493
+ * hold WALBufMappingLock. To change the identity of a buffer that's still
503
494
* dirty, the old page needs to be written out first, and for that you
504
495
* need WALWriteLock, and you need to ensure that there are no in-progress
505
496
* insertions to the page by calling WaitXLogInsertionsToFinish().
506
497
*/
507
- int curridx ;
498
+ XLogRecPtr InitializedUpTo ;
508
499
509
500
/*
510
501
* These values do not change after startup, although the pointed-to pages
@@ -618,16 +609,10 @@ static ControlFileData *ControlFile = NULL;
618
609
/*
619
610
* XLogRecPtrToBufIdx returns the index of the WAL buffer that holds, or
620
611
* would hold if it was in cache, the page containing 'recptr'.
621
- *
622
- * XLogRecEndPtrToBufIdx is the same, but a pointer to the first byte of a
623
- * page is taken to mean the previous page.
624
612
*/
625
613
#define XLogRecPtrToBufIdx (recptr ) \
626
614
(((recptr) / XLOG_BLCKSZ) % (XLogCtl->XLogCacheBlck + 1))
627
615
628
- #define XLogRecEndPtrToBufIdx (recptr ) \
629
- ((((recptr) - 1) / XLOG_BLCKSZ) % (XLogCtl->XLogCacheBlck + 1))
630
-
631
616
/*
632
617
* These are the number of bytes in a WAL page and segment usable for WAL data.
633
618
*/
@@ -2409,9 +2394,9 @@ AdvanceXLInsertBuffer(XLogRecPtr upto, bool opportunistic)
2409
2394
* Now that we have the lock, check if someone initialized the page
2410
2395
* already.
2411
2396
*/
2412
- while (upto >= XLogCtl -> xlblocks [ XLogCtl -> curridx ] || opportunistic )
2397
+ while (upto >= XLogCtl -> InitializedUpTo || opportunistic )
2413
2398
{
2414
- nextidx = NextBufIdx (XLogCtl -> curridx );
2399
+ nextidx = XLogRecPtrToBufIdx (XLogCtl -> InitializedUpTo );
2415
2400
2416
2401
/*
2417
2402
* Get ending-offset of the buffer page we need to replace (this may
@@ -2484,11 +2469,9 @@ AdvanceXLInsertBuffer(XLogRecPtr upto, bool opportunistic)
2484
2469
* Now the next buffer slot is free and we can set it up to be the next
2485
2470
* output page.
2486
2471
*/
2487
- NewPageBeginPtr = XLogCtl -> xlblocks [ XLogCtl -> curridx ] ;
2472
+ NewPageBeginPtr = XLogCtl -> InitializedUpTo ;
2488
2473
NewPageEndPtr = NewPageBeginPtr + XLOG_BLCKSZ ;
2489
2474
2490
- Assert (NewPageEndPtr % XLOG_BLCKSZ == 0 );
2491
- Assert (XLogRecEndPtrToBufIdx (NewPageEndPtr ) == nextidx );
2492
2475
Assert (XLogRecPtrToBufIdx (NewPageBeginPtr ) == nextidx );
2493
2476
2494
2477
NewPage = (XLogPageHeader ) (XLogCtl -> pages + nextidx * (Size ) XLOG_BLCKSZ );
@@ -2547,7 +2530,7 @@ AdvanceXLInsertBuffer(XLogRecPtr upto, bool opportunistic)
2547
2530
2548
2531
* ((volatile XLogRecPtr * ) & XLogCtl -> xlblocks [nextidx ]) = NewPageEndPtr ;
2549
2532
2550
- XLogCtl -> curridx = nextidx ;
2533
+ XLogCtl -> InitializedUpTo = NewPageEndPtr ;
2551
2534
2552
2535
npages ++ ;
2553
2536
}
@@ -2598,7 +2581,6 @@ XLogCheckpointNeeded(XLogSegNo new_segno)
2598
2581
static void
2599
2582
XLogWrite (XLogwrtRqst WriteRqst , bool flexible )
2600
2583
{
2601
- XLogCtlWrite * Write = & XLogCtl -> Write ;
2602
2584
bool ispartialpage ;
2603
2585
bool last_iteration ;
2604
2586
bool finishing_seg ;
@@ -2631,12 +2613,10 @@ XLogWrite(XLogwrtRqst WriteRqst, bool flexible)
2631
2613
2632
2614
/*
2633
2615
* Within the loop, curridx is the cache block index of the page to
2634
- * consider writing. We advance Write->curridx only after successfully
2635
- * writing pages. (Right now, this refinement is useless since we are
2636
- * going to PANIC if any error occurs anyway; but someday it may come in
2637
- * useful.)
2616
+ * consider writing. Begin at the buffer containing the next unwritten
2617
+ * page, or last partially written page.
2638
2618
*/
2639
- curridx = Write -> curridx ;
2619
+ curridx = XLogRecPtrToBufIdx ( LogwrtResult . Write ) ;
2640
2620
2641
2621
while (LogwrtResult .Write < WriteRqst .Write )
2642
2622
{
@@ -2747,7 +2727,6 @@ XLogWrite(XLogwrtRqst WriteRqst, bool flexible)
2747
2727
2748
2728
/* Update state for write */
2749
2729
openLogOff += nbytes ;
2750
- Write -> curridx = ispartialpage ? curridx : NextBufIdx (curridx );
2751
2730
npages = 0 ;
2752
2731
2753
2732
/*
@@ -2775,7 +2754,7 @@ XLogWrite(XLogwrtRqst WriteRqst, bool flexible)
2775
2754
if (XLogArchivingActive ())
2776
2755
XLogArchiveNotifySeg (openLogSegNo );
2777
2756
2778
- Write -> lastSegSwitchTime = (pg_time_t ) time (NULL );
2757
+ XLogCtl -> lastSegSwitchTime = (pg_time_t ) time (NULL );
2779
2758
2780
2759
/*
2781
2760
* Request a checkpoint if we've consumed too much xlog since
@@ -2807,7 +2786,6 @@ XLogWrite(XLogwrtRqst WriteRqst, bool flexible)
2807
2786
}
2808
2787
2809
2788
Assert (npages == 0 );
2810
- Assert (curridx == Write -> curridx );
2811
2789
2812
2790
/*
2813
2791
* If asked to flush, do so
@@ -6021,12 +5999,10 @@ StartupXLOG(void)
6021
5999
XLogSegNo endLogSegNo ;
6022
6000
TimeLineID PrevTimeLineID ;
6023
6001
XLogRecord * record ;
6024
- uint32 freespace ;
6025
6002
TransactionId oldestActiveXID ;
6026
6003
bool backupEndRequired = false;
6027
6004
bool backupFromStandby = false;
6028
6005
DBState dbstate_at_startup ;
6029
- int firstIdx ;
6030
6006
XLogReaderState * xlogreader ;
6031
6007
XLogPageReadPrivate private ;
6032
6008
bool fast_promoted = false;
@@ -7034,48 +7010,51 @@ StartupXLOG(void)
7034
7010
openLogOff = 0 ;
7035
7011
Insert = & XLogCtl -> Insert ;
7036
7012
Insert -> PrevBytePos = XLogRecPtrToBytePos (LastRec );
7037
-
7038
- firstIdx = XLogRecEndPtrToBufIdx (EndOfLog );
7039
- XLogCtl -> curridx = firstIdx ;
7040
-
7041
- XLogCtl -> xlblocks [firstIdx ] = ((EndOfLog - 1 ) / XLOG_BLCKSZ + 1 ) * XLOG_BLCKSZ ;
7013
+ Insert -> CurrBytePos = XLogRecPtrToBytePos (EndOfLog );
7042
7014
7043
7015
/*
7044
7016
* Tricky point here: readBuf contains the *last* block that the LastRec
7045
7017
* record spans, not the one it starts in. The last block is indeed the
7046
7018
* one we want to use.
7047
7019
*/
7048
- Assert (readOff == (XLogCtl -> xlblocks [firstIdx ] - XLOG_BLCKSZ ) % XLogSegSize );
7049
- memcpy ((char * ) & XLogCtl -> pages [firstIdx * XLOG_BLCKSZ ], xlogreader -> readBuf , XLOG_BLCKSZ );
7050
- Insert -> CurrBytePos = XLogRecPtrToBytePos (EndOfLog );
7020
+ if (EndOfLog % XLOG_BLCKSZ != 0 )
7021
+ {
7022
+ char * page ;
7023
+ int len ;
7024
+ int firstIdx ;
7025
+ XLogRecPtr pageBeginPtr ;
7051
7026
7052
- LogwrtResult .Write = LogwrtResult .Flush = EndOfLog ;
7027
+ pageBeginPtr = EndOfLog - (EndOfLog % XLOG_BLCKSZ );
7028
+ Assert (readOff == pageBeginPtr % XLogSegSize );
7053
7029
7054
- XLogCtl -> LogwrtResult = LogwrtResult ;
7030
+ firstIdx = XLogRecPtrToBufIdx ( EndOfLog ) ;
7055
7031
7056
- XLogCtl -> LogwrtRqst .Write = EndOfLog ;
7057
- XLogCtl -> LogwrtRqst .Flush = EndOfLog ;
7032
+ /* Copy the valid part of the last block, and zero the rest */
7033
+ page = & XLogCtl -> pages [firstIdx * XLOG_BLCKSZ ];
7034
+ len = EndOfLog % XLOG_BLCKSZ ;
7035
+ memcpy (page , xlogreader -> readBuf , len );
7036
+ memset (page + len , 0 , XLOG_BLCKSZ - len );
7058
7037
7059
- freespace = INSERT_FREESPACE (EndOfLog );
7060
- if (freespace > 0 )
7061
- {
7062
- /* Make sure rest of page is zero */
7063
- MemSet (& XLogCtl -> pages [firstIdx * XLOG_BLCKSZ ] + EndOfLog % XLOG_BLCKSZ , 0 , freespace );
7064
- XLogCtl -> Write .curridx = firstIdx ;
7038
+ XLogCtl -> xlblocks [firstIdx ] = pageBeginPtr + XLOG_BLCKSZ ;
7039
+ XLogCtl -> InitializedUpTo = pageBeginPtr + XLOG_BLCKSZ ;
7065
7040
}
7066
7041
else
7067
7042
{
7068
7043
/*
7069
- * Whenever LogwrtResult points to exactly the end of a page,
7070
- * Write.curridx must point to the *next* page (see XLogWrite()).
7071
- *
7072
- * Note: it might seem we should do AdvanceXLInsertBuffer() here, but
7073
- * this is sufficient. The first actual attempt to insert a log
7074
- * record will advance the insert state.
7044
+ * There is no partial block to copy. Just set InitializedUpTo,
7045
+ * and let the first attempt to insert a log record to initialize
7046
+ * the next buffer.
7075
7047
*/
7076
- XLogCtl -> Write . curridx = NextBufIdx ( firstIdx ) ;
7048
+ XLogCtl -> InitializedUpTo = EndOfLog ;
7077
7049
}
7078
7050
7051
+ LogwrtResult .Write = LogwrtResult .Flush = EndOfLog ;
7052
+
7053
+ XLogCtl -> LogwrtResult = LogwrtResult ;
7054
+
7055
+ XLogCtl -> LogwrtRqst .Write = EndOfLog ;
7056
+ XLogCtl -> LogwrtRqst .Flush = EndOfLog ;
7057
+
7079
7058
/* Pre-scan prepared transactions to find out the range of XIDs present */
7080
7059
oldestActiveXID = PrescanPreparedTransactions (NULL , NULL );
7081
7060
@@ -7199,7 +7178,7 @@ StartupXLOG(void)
7199
7178
LWLockRelease (ControlFileLock );
7200
7179
7201
7180
/* start the archive_timeout timer running */
7202
- XLogCtl -> Write . lastSegSwitchTime = (pg_time_t ) time (NULL );
7181
+ XLogCtl -> lastSegSwitchTime = (pg_time_t ) time (NULL );
7203
7182
7204
7183
/* also initialize latestCompletedXid, to nextXid - 1 */
7205
7184
LWLockAcquire (ProcArrayLock , LW_EXCLUSIVE );
@@ -7710,7 +7689,7 @@ GetLastSegSwitchTime(void)
7710
7689
7711
7690
/* Need WALWriteLock, but shared lock is sufficient */
7712
7691
LWLockAcquire (WALWriteLock , LW_SHARED );
7713
- result = XLogCtl -> Write . lastSegSwitchTime ;
7692
+ result = XLogCtl -> lastSegSwitchTime ;
7714
7693
LWLockRelease (WALWriteLock );
7715
7694
7716
7695
return result ;
0 commit comments