@ -83,7 +83,8 @@ static SlruCtlData ClogCtlData;
static int ZeroCLOGPage ( int pageno , bool writeXlog ) ;
static bool CLOGPagePrecedes ( int page1 , int page2 ) ;
static void WriteZeroPageXlogRec ( int pageno ) ;
static void WriteTruncateXlogRec ( int pageno ) ;
static void WriteTruncateXlogRec ( int pageno , TransactionId oldestXact ,
Oid oldestXidDb ) ;
static void TransactionIdSetPageStatus ( TransactionId xid , int nsubxids ,
TransactionId * subxids , XidStatus status ,
XLogRecPtr lsn , int pageno ) ;
@ -640,7 +641,7 @@ ExtendCLOG(TransactionId newestXact)
* the XLOG flush unless we have confirmed that there is a removable segment .
*/
void
TruncateCLOG ( TransactionId oldestXact )
TruncateCLOG ( TransactionId oldestXact , Oid oldestxid_datoid )
{
int cutoffPage ;
@ -654,8 +655,26 @@ TruncateCLOG(TransactionId oldestXact)
if ( ! SlruScanDirectory ( ClogCtl , SlruScanDirCbReportPresence , & cutoffPage ) )
return ; /* nothing to remove */
/* Write XLOG record and flush XLOG to disk */
WriteTruncateXlogRec ( cutoffPage ) ;
/*
* Advance oldestClogXid before truncating clog , so concurrent xact status
* lookups can ensure they don ' t attempt to access truncated - away clog .
*
* It ' s only necessary to do this if we will actually truncate away clog
* pages .
*/
AdvanceOldestClogXid ( oldestXact ) ;
/* vac_truncate_clog already advanced oldestXid */
Assert ( TransactionIdPrecedesOrEquals ( oldestXact ,
ShmemVariableCache - > oldestXid ) ) ;
/*
* Write XLOG record and flush XLOG to disk . We record the oldest xid we ' re
* keeping information about here so we can ensure that it ' s always ahead
* of clog truncation in case we crash , and so a standby finds out the new
* valid xid before the next checkpoint .
*/
WriteTruncateXlogRec ( cutoffPage , oldestXact , oldestxid_datoid ) ;
/* Now we can remove the old CLOG segment(s) */
SimpleLruTruncate ( ClogCtl , cutoffPage ) ;
@ -704,12 +723,17 @@ WriteZeroPageXlogRec(int pageno)
* in TruncateCLOG ( ) .
*/
static void
WriteTruncateXlogRec ( int pageno )
WriteTruncateXlogRec ( int pageno , TransactionId oldestXact , Oid oldestXactDb )
{
XLogRecPtr recptr ;
xl_clog_truncate xlrec ;
xlrec . pageno = pageno ;
xlrec . oldestXact = oldestXact ;
xlrec . oldestXactDb = oldestXactDb ;
XLogBeginInsert ( ) ;
XLogRegisterData ( ( char * ) ( & pageno ) , sizeof ( int ) ) ;
XLogRegisterData ( ( char * ) ( & xlrec ) , sizeof ( xl_clog_truncate ) ) ;
recptr = XLogInsert ( RM_CLOG_ID , CLOG_TRUNCATE ) ;
XLogFlush ( recptr ) ;
}
@ -742,17 +766,19 @@ clog_redo(XLogReaderState *record)
}
else if ( info = = CLOG_TRUNCATE )
{
int pageno ;
xl_clog_truncate xlrec ;
memcpy ( & pageno , XLogRecGetData ( record ) , sizeof ( int ) ) ;
memcpy ( & xlrec , XLogRecGetData ( record ) , sizeof ( xl_clog_truncate ) ) ;
/*
* During XLOG replay , latest_page_number isn ' t set up yet ; insert a
* suitable value to bypass the sanity test in SimpleLruTruncate .
*/
ClogCtl - > shared - > latest_page_number = pageno ;
ClogCtl - > shared - > latest_page_number = xlrec . pageno ;
AdvanceOldestClogXid ( xlrec . oldestXact ) ;
SimpleLruTruncate ( ClogCtl , pageno ) ;
SimpleLruTruncate ( ClogCtl , xlrec . pageno ) ;
}
else
elog ( PANIC , " clog_redo: unknown op code %u " , info ) ;