@ -110,6 +110,8 @@ int wal_retrieve_retry_interval = 5000;
bool XLOG_DEBUG = false ;
# endif
int wal_segment_size = DEFAULT_XLOG_SEG_SIZE ;
/*
* Number of WAL insertion locks to use . A higher value allows more insertions
* to happen concurrently , but adds some CPU overhead to flushing the WAL ,
@ -731,14 +733,16 @@ static ControlFileData *ControlFile = NULL;
( ( ( recptr ) / XLOG_BLCKSZ ) % ( XLogCtl - > XLogCacheBlck + 1 ) )
/*
* These are the number of bytes in a WAL page and segment usable for WAL data .
* These are the number of bytes in a WAL page usable for WAL data .
*/
# define UsableBytesInPage (XLOG_BLCKSZ - SizeOfXLogShortPHD)
# define UsableBytesInSegment ((XLOG_SEG_SIZE / XLOG_BLCKSZ) * UsableBytesInPage - (SizeOfXLogLongPHD - SizeOfXLogShortPHD))
/* Convert min_wal_size_mb and max wal_size_mb to equivalent segment count */
# define ConvertToXSegs(x) \
( x / ( XLOG_SEG_SIZE / ( 1024 * 1024 ) ) )
# define ConvertToXSegs(x, segsize) \
( x / ( ( segsize ) / ( 1024 * 1024 ) ) )
/* The number of bytes in a WAL segment usable for WAL data. */
static int UsableBytesInSegment ;
/*
* Private , possibly out - of - date copy of shared LogwrtResult .
@ -1137,7 +1141,9 @@ XLogInsertRecord(XLogRecData *rdata,
EndPos = StartPos + SizeOfXLogRecord ;
if ( StartPos / XLOG_BLCKSZ ! = EndPos / XLOG_BLCKSZ )
{
if ( EndPos % XLOG_SEG_SIZE = = EndPos % XLOG_BLCKSZ )
uint64 offset = XLogSegmentOffset ( EndPos , wal_segment_size ) ;
if ( offset = = EndPos % XLOG_BLCKSZ )
EndPos + = SizeOfXLogLongPHD ;
else
EndPos + = SizeOfXLogShortPHD ;
@ -1170,7 +1176,7 @@ XLogInsertRecord(XLogRecData *rdata,
appendBinaryStringInfo ( & recordBuf , rdata - > data , rdata - > len ) ;
if ( ! debug_reader )
debug_reader = XLogReaderAllocate ( NULL , NULL ) ;
debug_reader = XLogReaderAllocate ( wal_segment_size , NULL , NULL ) ;
if ( ! debug_reader )
{
@ -1296,7 +1302,7 @@ ReserveXLogSwitch(XLogRecPtr *StartPos, XLogRecPtr *EndPos, XLogRecPtr *PrevPtr)
startbytepos = Insert - > CurrBytePos ;
ptr = XLogBytePosToEndRecPtr ( startbytepos ) ;
if ( ptr % XLOG_SEG_SIZE = = 0 )
if ( XLogSegmentOffset ( ptr , wal_segment_size ) = = 0 )
{
SpinLockRelease ( & Insert - > insertpos_lck ) ;
* EndPos = * StartPos = ptr ;
@ -1309,8 +1315,8 @@ ReserveXLogSwitch(XLogRecPtr *StartPos, XLogRecPtr *EndPos, XLogRecPtr *PrevPtr)
* StartPos = XLogBytePosToRecPtr ( startbytepos ) ;
* EndPos = XLogBytePosToEndRecPtr ( endbytepos ) ;
segleft = XLOG_SEG_SIZE - ( ( * EndPos ) % XLOG_SEG_SIZE ) ;
if ( segleft ! = XLOG_SEG_SIZE )
segleft = wal_segment_size - XLogSegmentOffset ( * EndPos , wal_segment_size ) ;
if ( segleft ! = wal_segment_size )
{
/* consume the rest of the segment */
* EndPos + = segleft ;
@ -1323,7 +1329,7 @@ ReserveXLogSwitch(XLogRecPtr *StartPos, XLogRecPtr *EndPos, XLogRecPtr *PrevPtr)
* PrevPtr = XLogBytePosToRecPtr ( prevbytepos ) ;
Assert ( ( * EndPos ) % XLOG_SEG_SIZE = = 0 ) ;
Assert ( XLogSegmentOffset ( * EndPos , wal_segment_size ) = = 0 ) ;
Assert ( XLogRecPtrToBytePos ( * EndPos ) = = endbytepos ) ;
Assert ( XLogRecPtrToBytePos ( * StartPos ) = = startbytepos ) ;
Assert ( XLogRecPtrToBytePos ( * PrevPtr ) = = prevbytepos ) ;
@ -1501,7 +1507,7 @@ CopyXLogRecordToWAL(int write_len, bool isLogSwitch, XLogRecData *rdata,
pagehdr - > xlp_info | = XLP_FIRST_IS_CONTRECORD ;
/* skip over the page header */
if ( CurrPos % XLogSegSize = = 0 )
if ( XLogSegmentOffset ( CurrPos , wal_segment_size ) = = 0 )
{
CurrPos + = SizeOfXLogLongPHD ;
currpos + = SizeOfXLogLongPHD ;
@ -1532,16 +1538,16 @@ CopyXLogRecordToWAL(int write_len, bool isLogSwitch, XLogRecData *rdata,
* allocated and zeroed in the WAL buffers so that when the caller ( or
* someone else ) does XLogWrite ( ) , it can really write out all the zeros .
*/
if ( isLogSwitch & & CurrPos % XLOG_SEG_SIZE ! = 0 )
if ( isLogSwitch & & XLogSegmentOffset ( CurrPos , wal_segment_size ) ! = 0 )
{
/* An xlog-switch record doesn't contain any data besides the header */
Assert ( write_len = = SizeOfXLogRecord ) ;
/*
* We do this one page at a time , to make sure we don ' t deadlock
* against ourselves if wal_buffers < XLOG_SEG_SIZE .
* against ourselves if wal_buffers < wal_segment_size .
*/
Assert ( EndPos % XLogSegSize = = 0 ) ;
Assert ( XLogSegmentOffset ( EndPos , wal_segment_size ) = = 0 ) ;
/* Use up all the remaining space on the first page */
CurrPos + = freespace ;
@ -1866,10 +1872,10 @@ GetXLogBuffer(XLogRecPtr ptr)
* the page header .
*/
if ( ptr % XLOG_BLCKSZ = = SizeOfXLogShortPHD & &
ptr % XLOG_SEG_SIZE > XLOG_BLCKSZ )
XLogSegmentOffset ( ptr , wal_segment_size ) > XLOG_BLCKSZ )
initializedUpto = ptr - SizeOfXLogShortPHD ;
else if ( ptr % XLOG_BLCKSZ = = SizeOfXLogLongPHD & &
ptr % XLOG_SEG_SIZE < XLOG_BLCKSZ )
XLogSegmentOffset ( ptr , wal_segment_size ) < XLOG_BLCKSZ )
initializedUpto = ptr - SizeOfXLogLongPHD ;
else
initializedUpto = ptr ;
@ -1939,7 +1945,7 @@ XLogBytePosToRecPtr(uint64 bytepos)
seg_offset + = fullpages * XLOG_BLCKSZ + bytesleft + SizeOfXLogShortPHD ;
}
XLogSegNoOffsetToRecPtr ( fullsegs , seg_offset , result ) ;
XLogSegNoOffsetToRecPtr ( fullsegs , seg_offset , result , wal_segment_size ) ;
return result ;
}
@ -1985,7 +1991,7 @@ XLogBytePosToEndRecPtr(uint64 bytepos)
seg_offset + = fullpages * XLOG_BLCKSZ + bytesleft + SizeOfXLogShortPHD ;
}
XLogSegNoOffsetToRecPtr ( fullsegs , seg_offset , result ) ;
XLogSegNoOffsetToRecPtr ( fullsegs , seg_offset , result , wal_segment_size ) ;
return result ;
}
@ -2001,9 +2007,9 @@ XLogRecPtrToBytePos(XLogRecPtr ptr)
uint32 offset ;
uint64 result ;
XLByteToSeg ( ptr , fullsegs ) ;
XLByteToSeg ( ptr , fullsegs , wal_segment_size ) ;
fullpages = ( ptr % XLOG_SEG_SIZE ) / XLOG_BLCKSZ ;
fullpages = ( XLogSegmentOffset ( ptr , wal_segment_size ) ) / XLOG_BLCKSZ ;
offset = ptr % XLOG_BLCKSZ ;
if ( fullpages = = 0 )
@ -2168,12 +2174,12 @@ AdvanceXLInsertBuffer(XLogRecPtr upto, bool opportunistic)
/*
* If first page of an XLOG segment file , make it a long header .
*/
if ( ( NewPage - > xlp_pageaddr % XLogSegSize ) = = 0 )
if ( ( XLogSegmentOffset ( NewPage - > xlp_pageaddr , wal_segment_size ) ) = = 0 )
{
XLogLongPageHeader NewLongPage = ( XLogLongPageHeader ) NewPage ;
NewLongPage - > xlp_sysid = ControlFile - > system_identifier ;
NewLongPage - > xlp_seg_size = XLogSegS ize;
NewLongPage - > xlp_seg_size = wal_segment_s ize;
NewLongPage - > xlp_xlog_blcksz = XLOG_BLCKSZ ;
NewPage - > xlp_info | = XLP_LONG_HEADER ;
}
@ -2220,7 +2226,8 @@ CalculateCheckpointSegments(void)
* number of segments consumed between checkpoints .
* - - - - - - -
*/
target = ( double ) ConvertToXSegs ( max_wal_size_mb ) / ( 2.0 + CheckPointCompletionTarget ) ;
target = ( double ) ConvertToXSegs ( max_wal_size_mb , wal_segment_size ) /
( 2.0 + CheckPointCompletionTarget ) ;
/* round down */
CheckPointSegments = ( int ) target ;
@ -2260,8 +2267,10 @@ XLOGfileslop(XLogRecPtr PriorRedoPtr)
* correspond to . Always recycle enough segments to meet the minimum , and
* remove enough segments to stay below the maximum .
*/
minSegNo = PriorRedoPtr / XLOG_SEG_SIZE + ConvertToXSegs ( min_wal_size_mb ) - 1 ;
maxSegNo = PriorRedoPtr / XLOG_SEG_SIZE + ConvertToXSegs ( max_wal_size_mb ) - 1 ;
minSegNo = PriorRedoPtr / wal_segment_size +
ConvertToXSegs ( min_wal_size_mb , wal_segment_size ) - 1 ;
maxSegNo = PriorRedoPtr / wal_segment_size +
ConvertToXSegs ( max_wal_size_mb , wal_segment_size ) - 1 ;
/*
* Between those limits , recycle enough segments to get us through to the
@ -2290,7 +2299,8 @@ XLOGfileslop(XLogRecPtr PriorRedoPtr)
/* add 10% for good measure. */
distance * = 1.10 ;
recycleSegNo = ( XLogSegNo ) ceil ( ( ( double ) PriorRedoPtr + distance ) / XLOG_SEG_SIZE ) ;
recycleSegNo = ( XLogSegNo ) ceil ( ( ( double ) PriorRedoPtr + distance ) /
wal_segment_size ) ;
if ( recycleSegNo < minSegNo )
recycleSegNo = minSegNo ;
@ -2314,7 +2324,7 @@ XLogCheckpointNeeded(XLogSegNo new_segno)
{
XLogSegNo old_segno ;
XLByteToSeg ( RedoRecPtr , old_segno ) ;
XLByteToSeg ( RedoRecPtr , old_segno , wal_segment_size ) ;
if ( new_segno > = old_segno + ( uint64 ) ( CheckPointSegments - 1 ) )
return true ;
@ -2392,7 +2402,8 @@ XLogWrite(XLogwrtRqst WriteRqst, bool flexible)
LogwrtResult . Write = EndPtr ;
ispartialpage = WriteRqst . Write < LogwrtResult . Write ;
if ( ! XLByteInPrevSeg ( LogwrtResult . Write , openLogSegNo ) )
if ( ! XLByteInPrevSeg ( LogwrtResult . Write , openLogSegNo ,
wal_segment_size ) )
{
/*
* Switch to new logfile segment . We cannot have any pending
@ -2401,7 +2412,8 @@ XLogWrite(XLogwrtRqst WriteRqst, bool flexible)
Assert ( npages = = 0 ) ;
if ( openLogFile > = 0 )
XLogFileClose ( ) ;
XLByteToPrevSeg ( LogwrtResult . Write , openLogSegNo ) ;
XLByteToPrevSeg ( LogwrtResult . Write , openLogSegNo ,
wal_segment_size ) ;
/* create/use new log file */
use_existent = true ;
@ -2412,7 +2424,8 @@ XLogWrite(XLogwrtRqst WriteRqst, bool flexible)
/* Make sure we have the current logfile open */
if ( openLogFile < 0 )
{
XLByteToPrevSeg ( LogwrtResult . Write , openLogSegNo ) ;
XLByteToPrevSeg ( LogwrtResult . Write , openLogSegNo ,
wal_segment_size ) ;
openLogFile = XLogFileOpen ( openLogSegNo ) ;
openLogOff = 0 ;
}
@ -2422,7 +2435,8 @@ XLogWrite(XLogwrtRqst WriteRqst, bool flexible)
{
/* first of group */
startidx = curridx ;
startoffset = ( LogwrtResult . Write - XLOG_BLCKSZ ) % XLogSegSize ;
startoffset = XLogSegmentOffset ( LogwrtResult . Write - XLOG_BLCKSZ ,
wal_segment_size ) ;
}
npages + + ;
@ -2435,7 +2449,7 @@ XLogWrite(XLogwrtRqst WriteRqst, bool flexible)
last_iteration = WriteRqst . Write < = LogwrtResult . Write ;
finishing_seg = ! ispartialpage & &
( startoffset + npages * XLOG_BLCKSZ ) > = XLogSegS ize;
( startoffset + npages * XLOG_BLCKSZ ) > = wal_segment_s ize;
if ( last_iteration | |
curridx = = XLogCtl - > XLogCacheBlck | |
@ -2562,11 +2576,13 @@ XLogWrite(XLogwrtRqst WriteRqst, bool flexible)
sync_method ! = SYNC_METHOD_OPEN_DSYNC )
{
if ( openLogFile > = 0 & &
! XLByteInPrevSeg ( LogwrtResult . Write , openLogSegNo ) )
! XLByteInPrevSeg ( LogwrtResult . Write , openLogSegNo ,
wal_segment_size ) )
XLogFileClose ( ) ;
if ( openLogFile < 0 )
{
XLByteToPrevSeg ( LogwrtResult . Write , openLogSegNo ) ;
XLByteToPrevSeg ( LogwrtResult . Write , openLogSegNo ,
wal_segment_size ) ;
openLogFile = XLogFileOpen ( openLogSegNo ) ;
openLogOff = 0 ;
}
@ -2982,7 +2998,8 @@ XLogBackgroundFlush(void)
{
if ( openLogFile > = 0 )
{
if ( ! XLByteInPrevSeg ( LogwrtResult . Write , openLogSegNo ) )
if ( ! XLByteInPrevSeg ( LogwrtResult . Write , openLogSegNo ,
wal_segment_size ) )
{
XLogFileClose ( ) ;
}
@ -3161,7 +3178,7 @@ XLogFileInit(XLogSegNo logsegno, bool *use_existent, bool use_lock)
int fd ;
int nbytes ;
XLogFilePath ( path , ThisTimeLineID , logsegno ) ;
XLogFilePath ( path , ThisTimeLineID , logsegno , wal_segment_size ) ;
/*
* Try to use existent file ( checkpoint maker may have created it already )
@ -3215,7 +3232,7 @@ XLogFileInit(XLogSegNo logsegno, bool *use_existent, bool use_lock)
*/
zbuffer = ( char * ) MAXALIGN ( zbuffer_raw ) ;
memset ( zbuffer , 0 , XLOG_BLCKSZ ) ;
for ( nbytes = 0 ; nbytes < XLogSegS ize; nbytes + = XLOG_BLCKSZ )
for ( nbytes = 0 ; nbytes < wal_segment_s ize; nbytes + = XLOG_BLCKSZ )
{
errno = 0 ;
pgstat_report_wait_start ( WAIT_EVENT_WAL_INIT_WRITE ) ;
@ -3332,7 +3349,7 @@ XLogFileCopy(XLogSegNo destsegno, TimeLineID srcTLI, XLogSegNo srcsegno,
/*
* Open the source file
*/
XLogFilePath ( path , srcTLI , srcsegno ) ;
XLogFilePath ( path , srcTLI , srcsegno , wal_segment_size ) ;
srcfd = OpenTransientFile ( path , O_RDONLY | PG_BINARY , 0 ) ;
if ( srcfd < 0 )
ereport ( ERROR ,
@ -3357,7 +3374,7 @@ XLogFileCopy(XLogSegNo destsegno, TimeLineID srcTLI, XLogSegNo srcsegno,
/*
* Do the data copying .
*/
for ( nbytes = 0 ; nbytes < XLogSegS ize; nbytes + = sizeof ( buffer ) )
for ( nbytes = 0 ; nbytes < wal_segment_s ize; nbytes + = sizeof ( buffer ) )
{
int nread ;
@ -3467,7 +3484,7 @@ InstallXLogFileSegment(XLogSegNo *segno, char *tmppath,
char path [ MAXPGPATH ] ;
struct stat stat_buf ;
XLogFilePath ( path , ThisTimeLineID , * segno ) ;
XLogFilePath ( path , ThisTimeLineID , * segno , wal_segment_size ) ;
/*
* We want to be sure that only one process does this at a time .
@ -3493,7 +3510,7 @@ InstallXLogFileSegment(XLogSegNo *segno, char *tmppath,
return false ;
}
( * segno ) + + ;
XLogFilePath ( path , ThisTimeLineID , * segno ) ;
XLogFilePath ( path , ThisTimeLineID , * segno , wal_segment_size ) ;
}
}
@ -3524,7 +3541,7 @@ XLogFileOpen(XLogSegNo segno)
char path [ MAXPGPATH ] ;
int fd ;
XLogFilePath ( path , ThisTimeLineID , segno ) ;
XLogFilePath ( path , ThisTimeLineID , segno , wal_segment_size ) ;
fd = BasicOpenFile ( path , O_RDWR | PG_BINARY | get_sync_bit ( sync_method ) ,
S_IRUSR | S_IWUSR ) ;
@ -3551,7 +3568,7 @@ XLogFileRead(XLogSegNo segno, int emode, TimeLineID tli,
char path [ MAXPGPATH ] ;
int fd ;
XLogFileName ( xlogfname , tli , segno ) ;
XLogFileName ( xlogfname , tli , segno , wal_segment_size ) ;
switch ( source )
{
@ -3563,7 +3580,7 @@ XLogFileRead(XLogSegNo segno, int emode, TimeLineID tli,
restoredFromArchive = RestoreArchivedFile ( path , xlogfname ,
" RECOVERYXLOG " ,
XLogSegS ize,
wal_segment_s ize,
InRedo ) ;
if ( ! restoredFromArchive )
return - 1 ;
@ -3571,7 +3588,7 @@ XLogFileRead(XLogSegNo segno, int emode, TimeLineID tli,
case XLOG_FROM_PG_WAL :
case XLOG_FROM_STREAM :
XLogFilePath ( path , tli , segno ) ;
XLogFilePath ( path , tli , segno , wal_segment_size ) ;
restoredFromArchive = false ;
break ;
@ -3690,7 +3707,7 @@ XLogFileReadAnyTLI(XLogSegNo segno, int emode, int source)
}
/* Couldn't find it. For simplicity, complain about front timeline */
XLogFilePath ( path , recoveryTargetTLI , segno ) ;
XLogFilePath ( path , recoveryTargetTLI , segno , wal_segment_size ) ;
errno = ENOENT ;
ereport ( emode ,
( errcode_for_file_access ( ) ,
@ -3741,9 +3758,11 @@ PreallocXlogFiles(XLogRecPtr endptr)
XLogSegNo _logSegNo ;
int lf ;
bool use_existent ;
uint64 offset ;
XLByteToPrevSeg ( endptr , _logSegNo ) ;
if ( ( endptr - 1 ) % XLogSegSize > = ( uint32 ) ( 0.75 * XLogSegSize ) )
XLByteToPrevSeg ( endptr , _logSegNo , wal_segment_size ) ;
offset = XLogSegmentOffset ( endptr - 1 , wal_segment_size ) ;
if ( offset > = ( uint32 ) ( 0.75 * wal_segment_size ) )
{
_logSegNo + + ;
use_existent = true ;
@ -3774,7 +3793,7 @@ CheckXLogRemoved(XLogSegNo segno, TimeLineID tli)
{
char filename [ MAXFNAMELEN ] ;
XLogFileName ( filename , tli , segno ) ;
XLogFileName ( filename , tli , segno , wal_segment_size ) ;
ereport ( ERROR ,
( errcode_for_file_access ( ) ,
errmsg ( " requested WAL segment %s has already been removed " ,
@ -3811,7 +3830,7 @@ UpdateLastRemovedPtr(char *filename)
uint32 tli ;
XLogSegNo segno ;
XLogFromFileName ( filename , & tli , & segno ) ;
XLogFromFileName ( filename , & tli , & segno , wal_segment_size ) ;
SpinLockAcquire ( & XLogCtl - > info_lck ) ;
if ( segno > XLogCtl - > lastRemovedSegNo )
@ -3845,7 +3864,7 @@ RemoveOldXlogFiles(XLogSegNo segno, XLogRecPtr PriorRedoPtr, XLogRecPtr endptr)
* doesn ' t matter , we ignore that in the comparison . ( During recovery ,
* ThisTimeLineID isn ' t set , so we can ' t use that . )
*/
XLogFileName ( lastoff , 0 , segno ) ;
XLogFileName ( lastoff , 0 , segno , wal_segment_size ) ;
elog ( DEBUG2 , " attempting to remove WAL segments older than log file %s " ,
lastoff ) ;
@ -3906,7 +3925,7 @@ RemoveNonParentXlogFiles(XLogRecPtr switchpoint, TimeLineID newTLI)
char switchseg [ MAXFNAMELEN ] ;
XLogSegNo endLogSegNo ;
XLByteToPrevSeg ( switchpoint , endLogSegNo ) ;
XLByteToPrevSeg ( switchpoint , endLogSegNo , wal_segment_size ) ;
xldir = AllocateDir ( XLOGDIR ) ;
if ( xldir = = NULL )
@ -3918,7 +3937,7 @@ RemoveNonParentXlogFiles(XLogRecPtr switchpoint, TimeLineID newTLI)
/*
* Construct a filename of the last segment to be kept .
*/
XLogFileName ( switchseg , newTLI , endLogSegNo ) ;
XLogFileName ( switchseg , newTLI , endLogSegNo , wal_segment_size ) ;
elog ( DEBUG2 , " attempting to remove WAL segments newer than log file %s " ,
switchseg ) ;
@ -3974,7 +3993,7 @@ RemoveXlogFile(const char *segname, XLogRecPtr PriorRedoPtr, XLogRecPtr endptr)
/*
* Initialize info about where to try to recycle to .
*/
XLByteToSeg ( endptr , endlogSegNo ) ;
XLByteToSeg ( endptr , endlogSegNo , wal_segment_size ) ;
if ( PriorRedoPtr = = InvalidXLogRecPtr )
recycleSegNo = endlogSegNo + 10 ;
else
@ -4192,9 +4211,11 @@ ReadRecord(XLogReaderState *xlogreader, XLogRecPtr RecPtr, int emode,
XLogSegNo segno ;
int32 offset ;
XLByteToSeg ( xlogreader - > latestPagePtr , segno ) ;
offset = xlogreader - > latestPagePtr % XLogSegSize ;
XLogFileName ( fname , xlogreader - > readPageTLI , segno ) ;
XLByteToSeg ( xlogreader - > latestPagePtr , segno , wal_segment_size ) ;
offset = XLogSegmentOffset ( xlogreader - > latestPagePtr ,
wal_segment_size ) ;
XLogFileName ( fname , xlogreader - > readPageTLI , segno ,
wal_segment_size ) ;
ereport ( emode_for_corrupt_record ( emode ,
RecPtr ? RecPtr : EndRecPtr ) ,
( errmsg ( " unexpected timeline ID %u in log segment %s, offset %u " ,
@ -4399,7 +4420,7 @@ WriteControlFile(void)
ControlFile - > blcksz = BLCKSZ ;
ControlFile - > relseg_size = RELSEG_SIZE ;
ControlFile - > xlog_blcksz = XLOG_BLCKSZ ;
ControlFile - > xlog_seg_size = XLOG_SEG_SIZE ;
ControlFile - > xlog_seg_size = wal_segment_size ;
ControlFile - > nameDataLen = NAMEDATALEN ;
ControlFile - > indexMaxKeys = INDEX_MAX_KEYS ;
@ -4467,6 +4488,7 @@ ReadControlFile(void)
{
pg_crc32c crc ;
int fd ;
static char wal_segsz_str [ 20 ] ;
/*
* Read data . . .
@ -4569,13 +4591,6 @@ ReadControlFile(void)
" but the server was compiled with XLOG_BLCKSZ %d. " ,
ControlFile - > xlog_blcksz , XLOG_BLCKSZ ) ,
errhint ( " It looks like you need to recompile or initdb. " ) ) ) ;
if ( ControlFile - > xlog_seg_size ! = XLOG_SEG_SIZE )
ereport ( FATAL ,
( errmsg ( " database files are incompatible with server " ) ,
errdetail ( " The database cluster was initialized with XLOG_SEG_SIZE %d, "
" but the server was compiled with XLOG_SEG_SIZE %d. " ,
ControlFile - > xlog_seg_size , XLOG_SEG_SIZE ) ,
errhint ( " It looks like you need to recompile or initdb. " ) ) ) ;
if ( ControlFile - > nameDataLen ! = NAMEDATALEN )
ereport ( FATAL ,
( errmsg ( " database files are incompatible with server " ) ,
@ -4637,6 +4652,32 @@ ReadControlFile(void)
errhint ( " It looks like you need to recompile or initdb. " ) ) ) ;
# endif
wal_segment_size = ControlFile - > xlog_seg_size ;
if ( ! IsValidWalSegSize ( wal_segment_size ) )
ereport ( ERROR , ( errcode ( ERRCODE_INVALID_PARAMETER_VALUE ) ,
errmsg ( " WAL segment size must be a power of two between 1MB and 1GB, but the control file specifies %d bytes " ,
wal_segment_size ) ) ) ;
snprintf ( wal_segsz_str , sizeof ( wal_segsz_str ) , " %d " , wal_segment_size ) ;
SetConfigOption ( " wal_segment_size " , wal_segsz_str , PGC_INTERNAL ,
PGC_S_OVERRIDE ) ;
/* check and update variables dependent on wal_segment_size */
if ( ConvertToXSegs ( min_wal_size_mb , wal_segment_size ) < 2 )
ereport ( ERROR , ( errcode ( ERRCODE_INVALID_PARAMETER_VALUE ) ,
errmsg ( " \" min_wal_size \" must be at least twice \" wal_segment_size \" . " ) ) ) ;
if ( ConvertToXSegs ( max_wal_size_mb , wal_segment_size ) < 2 )
ereport ( ERROR , ( errcode ( ERRCODE_INVALID_PARAMETER_VALUE ) ,
errmsg ( " \" max_wal_size \" must be at least twice \" wal_segment_size \" . " ) ) ) ;
UsableBytesInSegment =
( wal_segment_size / XLOG_BLCKSZ * UsableBytesInPage ) -
( SizeOfXLogLongPHD - SizeOfXLogShortPHD ) ;
CalculateCheckpointSegments ( ) ;
/* Make the initdb settings visible as GUC variables, too */
SetConfigOption ( " data_checksums " , DataChecksumsEnabled ( ) ? " yes " : " no " ,
PGC_INTERNAL , PGC_S_OVERRIDE ) ;
@ -4757,8 +4798,8 @@ XLOGChooseNumBuffers(void)
int xbuffers ;
xbuffers = NBuffers / 32 ;
if ( xbuffers > XLOG_SEG_SIZE / XLOG_BLCKSZ )
xbuffers = XLOG_SEG_SIZE / XLOG_BLCKSZ ;
if ( xbuffers > ( wal_segment_size / XLOG_BLCKSZ ) )
xbuffers = ( wal_segment_size / XLOG_BLCKSZ ) ;
if ( xbuffers < 8 )
xbuffers = 8 ;
return xbuffers ;
@ -5034,7 +5075,7 @@ BootStrapXLOG(void)
* segment with logid = 0 logseg = 1. The very first WAL segment , 0 / 0 , is not
* used , so that we can use 0 / 0 to mean " before any valid WAL segment " .
*/
checkPoint . redo = XLogSegS ize + SizeOfXLogLongPHD ;
checkPoint . redo = wal_segment_s ize + SizeOfXLogLongPHD ;
checkPoint . ThisTimeLineID = ThisTimeLineID ;
checkPoint . PrevTimeLineID = ThisTimeLineID ;
checkPoint . fullPageWrites = fullPageWrites ;
@ -5065,10 +5106,10 @@ BootStrapXLOG(void)
page - > xlp_magic = XLOG_PAGE_MAGIC ;
page - > xlp_info = XLP_LONG_HEADER ;
page - > xlp_tli = ThisTimeLineID ;
page - > xlp_pageaddr = XLogSegS ize;
page - > xlp_pageaddr = wal_segment_s ize;
longpage = ( XLogLongPageHeader ) page ;
longpage - > xlp_sysid = sysidentifier ;
longpage - > xlp_seg_size = XLogSegS ize;
longpage - > xlp_seg_size = wal_segment_s ize;
longpage - > xlp_xlog_blcksz = XLOG_BLCKSZ ;
/* Insert the initial checkpoint record */
@ -5550,8 +5591,8 @@ exitArchiveRecovery(TimeLineID endTLI, XLogRecPtr endOfLog)
* they are the same , but if the switch happens exactly at a segment
* boundary , startLogSegNo will be endLogSegNo + 1.
*/
XLByteToPrevSeg ( endOfLog , endLogSegNo ) ;
XLByteToSeg ( endOfLog , startLogSegNo ) ;
XLByteToPrevSeg ( endOfLog , endLogSegNo , wal_segment_size ) ;
XLByteToSeg ( endOfLog , startLogSegNo , wal_segment_size ) ;
/*
* Initialize the starting WAL segment for the new timeline . If the switch
@ -5569,7 +5610,7 @@ exitArchiveRecovery(TimeLineID endTLI, XLogRecPtr endOfLog)
* avoid emplacing a bogus file .
*/
XLogFileCopy ( endLogSegNo , endTLI , endLogSegNo ,
endOfLog % XLOG_SEG_SIZE ) ;
XLogSegmentOffset ( endOfLog , wal_segment_size ) ) ;
}
else
{
@ -5593,7 +5634,7 @@ exitArchiveRecovery(TimeLineID endTLI, XLogRecPtr endOfLog)
* Let ' s just make real sure there are not . ready or . done flags posted
* for the new segment .
*/
XLogFileName ( xlogfname , ThisTimeLineID , startLogSegNo ) ;
XLogFileName ( xlogfname , ThisTimeLineID , startLogSegNo , wal_segment_size ) ;
XLogArchiveCleanup ( xlogfname ) ;
/*
@ -6390,7 +6431,7 @@ StartupXLOG(void)
/* Set up XLOG reader facility */
MemSet ( & private , 0 , sizeof ( XLogPageReadPrivate ) ) ;
xlogreader = XLogReaderAllocate ( & XLogPageRead , & private ) ;
xlogreader = XLogReaderAllocate ( wal_segment_size , & XLogPageRead , & private ) ;
if ( ! xlogreader )
ereport ( ERROR ,
( errcode ( ERRCODE_OUT_OF_MEMORY ) ,
@ -7523,7 +7564,7 @@ StartupXLOG(void)
XLogRecPtr pageBeginPtr ;
pageBeginPtr = EndOfLog - ( EndOfLog % XLOG_BLCKSZ ) ;
Assert ( readOff = = pageBeginPtr % XLogSegSize ) ;
Assert ( readOff = = XLogSegmentOffset ( pageBeginPtr , wal_segment_size ) ) ;
firstIdx = XLogRecPtrToBufIdx ( EndOfLog ) ;
@ -7672,13 +7713,14 @@ StartupXLOG(void)
* restored from the archive to begin with , it ' s expected to have a
* . done file ) .
*/
if ( EndOfLog % XLOG_SEG_SIZE ! = 0 & & XLogArchivingActive ( ) )
if ( XLogSegmentOffset ( EndOfLog , wal_segment_size ) ! = 0 & &
XLogArchivingActive ( ) )
{
char origfname [ MAXFNAMELEN ] ;
XLogSegNo endLogSegNo ;
XLByteToPrevSeg ( EndOfLog , endLogSegNo ) ;
XLogFileName ( origfname , EndOfLogTLI , endLogSegNo ) ;
XLByteToPrevSeg ( EndOfLog , endLogSegNo , wal_segment_size ) ;
XLogFileName ( origfname , EndOfLogTLI , endLogSegNo , wal_segment_size ) ;
if ( ! XLogArchiveIsReadyOrDone ( origfname ) )
{
@ -7686,7 +7728,7 @@ StartupXLOG(void)
char partialfname [ MAXFNAMELEN ] ;
char partialpath [ MAXPGPATH ] ;
XLogFilePath ( origpath , EndOfLogTLI , endLogSegNo ) ;
XLogFilePath ( origpath , EndOfLogTLI , endLogSegNo , wal_segment_size ) ;
snprintf ( partialfname , MAXFNAMELEN , " %s.partial " , origfname ) ;
snprintf ( partialpath , MAXPGPATH , " %s.partial " , origpath ) ;
@ -8192,6 +8234,9 @@ InitXLOGAccess(void)
ThisTimeLineID = XLogCtl - > ThisTimeLineID ;
Assert ( ThisTimeLineID ! = 0 | | IsBootstrapProcessingMode ( ) ) ;
/* set wal_segment_size */
wal_segment_size = ControlFile - > xlog_seg_size ;
/* Use GetRedoRecPtr to copy the RedoRecPtr safely */
( void ) GetRedoRecPtr ( ) ;
/* Also update our copy of doPageWrites. */
@ -8522,7 +8567,7 @@ UpdateCheckPointDistanceEstimate(uint64 nbytes)
* more .
*
* When checkpoints are triggered by max_wal_size , this should converge to
* CheckpointSegments * XLOG_SEG_SIZE ,
* CheckpointSegments * wal_segment_size ,
*
* Note : This doesn ' t pay any attention to what caused the checkpoint .
* Checkpoints triggered manually with CHECKPOINT command , or by e . g .
@ -8721,7 +8766,7 @@ CreateCheckPoint(int flags)
freespace = INSERT_FREESPACE ( curInsert ) ;
if ( freespace = = 0 )
{
if ( curInsert % XLogSegSize = = 0 )
if ( XLogSegmentOffset ( curInsert , wal_segment_size ) = = 0 )
curInsert + = SizeOfXLogLongPHD ;
else
curInsert + = SizeOfXLogShortPHD ;
@ -8955,7 +9000,7 @@ CreateCheckPoint(int flags)
/* Update the average distance between checkpoints. */
UpdateCheckPointDistanceEstimate ( RedoRecPtr - PriorRedoPtr ) ;
XLByteToSeg ( PriorRedoPtr , _logSegNo ) ;
XLByteToSeg ( PriorRedoPtr , _logSegNo , wal_segment_size ) ;
KeepLogSeg ( recptr , & _logSegNo ) ;
_logSegNo - - ;
RemoveOldXlogFiles ( _logSegNo , PriorRedoPtr , recptr ) ;
@ -9283,7 +9328,7 @@ CreateRestartPoint(int flags)
/* Update the average distance between checkpoints/restartpoints. */
UpdateCheckPointDistanceEstimate ( RedoRecPtr - PriorRedoPtr ) ;
XLByteToSeg ( PriorRedoPtr , _logSegNo ) ;
XLByteToSeg ( PriorRedoPtr , _logSegNo , wal_segment_size ) ;
/*
* Get the current end of xlog replayed or received , whichever is
@ -9378,7 +9423,7 @@ KeepLogSeg(XLogRecPtr recptr, XLogSegNo *logSegNo)
XLogSegNo segno ;
XLogRecPtr keep ;
XLByteToSeg ( recptr , segno ) ;
XLByteToSeg ( recptr , segno , wal_segment_size ) ;
keep = XLogGetReplicationSlotMinimumLSN ( ) ;
/* compute limit for wal_keep_segments first */
@ -9396,7 +9441,7 @@ KeepLogSeg(XLogRecPtr recptr, XLogSegNo *logSegNo)
{
XLogSegNo slotSegNo ;
XLByteToSeg ( keep , slotSegNo ) ;
XLByteToSeg ( keep , slotSegNo , wal_segment_size ) ;
if ( slotSegNo < = 0 )
segno = 1 ;
@ -10179,7 +10224,7 @@ XLogFileNameP(TimeLineID tli, XLogSegNo segno)
{
char * result = palloc ( MAXFNAMELEN ) ;
XLogFileName ( result , tli , segno ) ;
XLogFileName ( result , tli , segno , wal_segment_size ) ;
return result ;
}
@ -10433,8 +10478,8 @@ do_pg_start_backup(const char *backupidstr, bool fast, TimeLineID *starttli_p,
WALInsertLockRelease ( ) ;
} while ( ! gotUniqueStartpoint ) ;
XLByteToSeg ( startpoint , _logSegNo ) ;
XLogFileName ( xlogfilename , starttli , _logSegNo ) ;
XLByteToSeg ( startpoint , _logSegNo , wal_segment_size ) ;
XLogFileName ( xlogfilename , starttli , _logSegNo , wal_segment_size ) ;
/*
* Construct tablespace_map file
@ -10985,8 +11030,8 @@ do_pg_stop_backup(char *labelfile, bool waitforarchive, TimeLineID *stoptli_p)
*/
RequestXLogSwitch ( false ) ;
XLByteToPrevSeg ( stoppoint , _logSegNo ) ;
XLogFileName ( stopxlogfilename , stoptli , _logSegNo ) ;
XLByteToPrevSeg ( stoppoint , _logSegNo , wal_segment_size ) ;
XLogFileName ( stopxlogfilename , stoptli , _logSegNo , wal_segment_size ) ;
/* Use the log timezone here, not the session timezone */
stamp_time = ( pg_time_t ) time ( NULL ) ;
@ -10997,9 +11042,9 @@ do_pg_stop_backup(char *labelfile, bool waitforarchive, TimeLineID *stoptli_p)
/*
* Write the backup history file
*/
XLByteToSeg ( startpoint , _logSegNo ) ;
XLByteToSeg ( startpoint , _logSegNo , wal_segment_size ) ;
BackupHistoryFilePath ( histfilepath , stoptli , _logSegNo ,
( uint32 ) ( startpoint % XLogSegSize ) ) ;
startpoint , wal_segment_size ) ;
fp = AllocateFile ( histfilepath , " w " ) ;
if ( ! fp )
ereport ( ERROR ,
@ -11053,12 +11098,12 @@ do_pg_stop_backup(char *labelfile, bool waitforarchive, TimeLineID *stoptli_p)
( ( ! backup_started_in_recovery & & XLogArchivingActive ( ) ) | |
( backup_started_in_recovery & & XLogArchivingAlways ( ) ) ) )
{
XLByteToPrevSeg ( stoppoint , _logSegNo ) ;
XLogFileName ( lastxlogfilename , stoptli , _logSegNo ) ;
XLByteToPrevSeg ( stoppoint , _logSegNo , wal_segment_size ) ;
XLogFileName ( lastxlogfilename , stoptli , _logSegNo , wal_segment_size ) ;
XLByteToSeg ( startpoint , _logSegNo ) ;
XLByteToSeg ( startpoint , _logSegNo , wal_segment_size ) ;
BackupHistoryFileName ( histfilename , stoptli , _logSegNo ,
( uint32 ) ( startpoint % XLogSegSize ) ) ;
startpoint , wal_segment_size ) ;
seconds_before_warning = 60 ;
waits = 0 ;
@ -11501,14 +11546,15 @@ XLogPageRead(XLogReaderState *xlogreader, XLogRecPtr targetPagePtr, int reqLen,
uint32 targetPageOff ;
XLogSegNo targetSegNo PG_USED_FOR_ASSERTS_ONLY ;
XLByteToSeg ( targetPagePtr , targetSegNo ) ;
targetPageOff = targetPagePtr % XLogSegSize ;
XLByteToSeg ( targetPagePtr , targetSegNo , wal_segment_size ) ;
targetPageOff = XLogSegmentOffset ( targetPagePtr , wal_segment_size ) ;
/*
* See if we need to switch to a new segment because the requested record
* is not in the currently open one .
*/
if ( readFile > = 0 & & ! XLByteInSeg ( targetPagePtr , readSegNo ) )
if ( readFile > = 0 & &
! XLByteInSeg ( targetPagePtr , readSegNo , wal_segment_size ) )
{
/*
* Request a restartpoint if we ' ve replayed too much xlog since the
@ -11529,7 +11575,7 @@ XLogPageRead(XLogReaderState *xlogreader, XLogRecPtr targetPagePtr, int reqLen,
readSource = 0 ;
}
XLByteToSeg ( targetPagePtr , readSegNo ) ;
XLByteToSeg ( targetPagePtr , readSegNo , wal_segment_size ) ;
retry :
/* See if we need to retrieve more data */
@ -11569,7 +11615,8 @@ retry:
if ( ( ( targetPagePtr ) / XLOG_BLCKSZ ) ! = ( receivedUpto / XLOG_BLCKSZ ) )
readLen = XLOG_BLCKSZ ;
else
readLen = receivedUpto % XLogSegSize - targetPageOff ;
readLen = XLogSegmentOffset ( receivedUpto , wal_segment_size ) -
targetPageOff ;
}
else
readLen = XLOG_BLCKSZ ;
@ -11580,7 +11627,7 @@ retry:
{
char fname [ MAXFNAMELEN ] ;
XLogFileName ( fname , curFileTLI , readSegNo ) ;
XLogFileName ( fname , curFileTLI , readSegNo , wal_segment_size ) ;
ereport ( emode_for_corrupt_record ( emode , targetPagePtr + reqLen ) ,
( errcode_for_file_access ( ) ,
errmsg ( " could not seek in log segment %s to offset %u: %m " ,
@ -11594,7 +11641,7 @@ retry:
char fname [ MAXFNAMELEN ] ;
pgstat_report_wait_end ( ) ;
XLogFileName ( fname , curFileTLI , readSegNo ) ;
XLogFileName ( fname , curFileTLI , readSegNo , wal_segment_size ) ;
ereport ( emode_for_corrupt_record ( emode , targetPagePtr + reqLen ) ,
( errcode_for_file_access ( ) ,
errmsg ( " could not read from log segment %s, offset %u: %m " ,