@ -79,7 +79,8 @@ extern uint32 bootstrap_data_checksum_version;
/* User-settable parameters */
/* User-settable parameters */
int CheckPointSegments = 3 ;
int max_wal_size = 8 ; /* 128 MB */
int min_wal_size = 5 ; /* 80 MB */
int wal_keep_segments = 0 ;
int wal_keep_segments = 0 ;
int XLOGbuffers = - 1 ;
int XLOGbuffers = - 1 ;
int XLogArchiveTimeout = 0 ;
int XLogArchiveTimeout = 0 ;
@ -107,18 +108,14 @@ bool XLOG_DEBUG = false;
# define NUM_XLOGINSERT_LOCKS 8
# define NUM_XLOGINSERT_LOCKS 8
/*
/*
* XLOGfileslop is the maximum number of preallocated future XLOG segments .
* Max distance from last checkpoint , before triggering a new xlog - based
* When we are done with an old XLOG segment file , we will recycle it as a
* checkpoint .
* future XLOG segment as long as there aren ' t already XLOGfileslop future
* segments ; else we ' ll delete it . This could be made a separate GUC
* variable , but at present I think it ' s sufficient to hardwire it as
* 2 * CheckPointSegments + 1. Under normal conditions , a checkpoint will free
* no more than 2 * CheckPointSegments log segments , and we want to recycle all
* of them ; the + 1 allows boundary cases to happen without wasting a
* delete / create - segment cycle .
*/
*/
# define XLOGfileslop (2*CheckPointSegments + 1)
int CheckPointSegments ;
/* Estimated distance between checkpoints, in bytes */
static double CheckPointDistanceEstimate = 0 ;
static double PrevCheckPointDistance = 0 ;
/*
/*
* GUC support
* GUC support
@ -779,7 +776,7 @@ static void AdvanceXLInsertBuffer(XLogRecPtr upto, bool opportunistic);
static bool XLogCheckpointNeeded ( XLogSegNo new_segno ) ;
static bool XLogCheckpointNeeded ( XLogSegNo new_segno ) ;
static void XLogWrite ( XLogwrtRqst WriteRqst , bool flexible ) ;
static void XLogWrite ( XLogwrtRqst WriteRqst , bool flexible ) ;
static bool InstallXLogFileSegment ( XLogSegNo * segno , char * tmppath ,
static bool InstallXLogFileSegment ( XLogSegNo * segno , char * tmppath ,
bool find_free , int * max_advance ,
bool find_free , XLogSegNo max_segno ,
bool use_lock ) ;
bool use_lock ) ;
static int XLogFileRead ( XLogSegNo segno , int emode , TimeLineID tli ,
static int XLogFileRead ( XLogSegNo segno , int emode , TimeLineID tli ,
int source , bool notexistOk ) ;
int source , bool notexistOk ) ;
@ -792,7 +789,7 @@ static bool WaitForWALToBecomeAvailable(XLogRecPtr RecPtr, bool randAccess,
static int emode_for_corrupt_record ( int emode , XLogRecPtr RecPtr ) ;
static int emode_for_corrupt_record ( int emode , XLogRecPtr RecPtr ) ;
static void XLogFileClose ( void ) ;
static void XLogFileClose ( void ) ;
static void PreallocXlogFiles ( XLogRecPtr endptr ) ;
static void PreallocXlogFiles ( XLogRecPtr endptr ) ;
static void RemoveOldXlogFiles ( XLogSegNo segno , XLogRecPtr endptr ) ;
static void RemoveOldXlogFiles ( XLogSegNo segno , XLogRecPtr PriorRedoPtr , XLogRecPtr endptr ) ;
static void UpdateLastRemovedPtr ( char * filename ) ;
static void UpdateLastRemovedPtr ( char * filename ) ;
static void ValidateXLOGDirectoryStructure ( void ) ;
static void ValidateXLOGDirectoryStructure ( void ) ;
static void CleanupBackupHistory ( void ) ;
static void CleanupBackupHistory ( void ) ;
@ -1958,6 +1955,104 @@ AdvanceXLInsertBuffer(XLogRecPtr upto, bool opportunistic)
# endif
# endif
}
}
/*
* Calculate CheckPointSegments based on max_wal_size and
* checkpoint_completion_target .
*/
static void
CalculateCheckpointSegments ( void )
{
double target ;
/*-------
* Calculate the distance at which to trigger a checkpoint , to avoid
* exceeding max_wal_size . This is based on two assumptions :
*
* a ) we keep WAL for two checkpoint cycles , back to the " prev " checkpoint .
* b ) during checkpoint , we consume checkpoint_completion_target *
* number of segments consumed between checkpoints .
* - - - - - - -
*/
target = ( double ) max_wal_size / ( 2.0 + CheckPointCompletionTarget ) ;
/* round down */
CheckPointSegments = ( int ) target ;
if ( CheckPointSegments < 1 )
CheckPointSegments = 1 ;
}
void
assign_max_wal_size ( int newval , void * extra )
{
max_wal_size = newval ;
CalculateCheckpointSegments ( ) ;
}
void
assign_checkpoint_completion_target ( double newval , void * extra )
{
CheckPointCompletionTarget = newval ;
CalculateCheckpointSegments ( ) ;
}
/*
* At a checkpoint , how many WAL segments to recycle as preallocated future
* XLOG segments ? Returns the highest segment that should be preallocated .
*/
static XLogSegNo
XLOGfileslop ( XLogRecPtr PriorRedoPtr )
{
XLogSegNo minSegNo ;
XLogSegNo maxSegNo ;
double distance ;
XLogSegNo recycleSegNo ;
/*
* Calculate the segment numbers that min_wal_size and max_wal_size
* correspond to . Always recycle enough segments to meet the minimum , and
* remove enough segments to stay below the maximum .
*/
minSegNo = PriorRedoPtr / XLOG_SEG_SIZE + min_wal_size - 1 ;
maxSegNo = PriorRedoPtr / XLOG_SEG_SIZE + max_wal_size - 1 ;
/*
* Between those limits , recycle enough segments to get us through to the
* estimated end of next checkpoint .
*
* To estimate where the next checkpoint will finish , assume that the
* system runs steadily consuming CheckPointDistanceEstimate
* bytes between every checkpoint .
*
* The reason this calculation is done from the prior checkpoint , not the
* one that just finished , is that this behaves better if some checkpoint
* cycles are abnormally short , like if you perform a manual checkpoint
* right after a timed one . The manual checkpoint will make almost a full
* cycle ' s worth of WAL segments available for recycling , because the
* segments from the prior ' s prior , fully - sized checkpoint cycle are no
* longer needed . However , the next checkpoint will make only few segments
* available for recycling , the ones generated between the timed
* checkpoint and the manual one right after that . If at the manual
* checkpoint we only retained enough segments to get us to the next timed
* one , and removed the rest , then at the next checkpoint we would not
* have enough segments around for recycling , to get us to the checkpoint
* after that . Basing the calculations on the distance from the prior redo
* pointer largely fixes that problem .
*/
distance = ( 2.0 + CheckPointCompletionTarget ) * CheckPointDistanceEstimate ;
/* add 10% for good measure. */
distance * = 1.10 ;
recycleSegNo = ( XLogSegNo ) ceil ( ( ( double ) PriorRedoPtr + distance ) / XLOG_SEG_SIZE ) ;
if ( recycleSegNo < minSegNo )
recycleSegNo = minSegNo ;
if ( recycleSegNo > maxSegNo )
recycleSegNo = maxSegNo ;
return recycleSegNo ;
}
/*
/*
* Check whether we ' ve consumed enough xlog space that a checkpoint is needed .
* Check whether we ' ve consumed enough xlog space that a checkpoint is needed .
*
*
@ -2765,7 +2860,7 @@ XLogFileInit(XLogSegNo logsegno, bool *use_existent, bool use_lock)
char zbuffer_raw [ XLOG_BLCKSZ + MAXIMUM_ALIGNOF ] ;
char zbuffer_raw [ XLOG_BLCKSZ + MAXIMUM_ALIGNOF ] ;
char * zbuffer ;
char * zbuffer ;
XLogSegNo installed_segno ;
XLogSegNo installed_segno ;
int max_advance ;
XLogSegNo max_segno ;
int fd ;
int fd ;
int nbytes ;
int nbytes ;
@ -2868,9 +2963,19 @@ XLogFileInit(XLogSegNo logsegno, bool *use_existent, bool use_lock)
* pre - create a future log segment .
* pre - create a future log segment .
*/
*/
installed_segno = logsegno ;
installed_segno = logsegno ;
max_advance = XLOGfileslop ;
/*
* XXX : What should we use as max_segno ? We used to use XLOGfileslop when
* that was a constant , but that was always a bit dubious : normally , at a
* checkpoint , XLOGfileslop was the offset from the checkpoint record ,
* but here , it was the offset from the insert location . We can ' t do the
* normal XLOGfileslop calculation here because we don ' t have access to
* the prior checkpoint ' s redo location . So somewhat arbitrarily , just
* use CheckPointSegments .
*/
max_segno = logsegno + CheckPointSegments ;
if ( ! InstallXLogFileSegment ( & installed_segno , tmppath ,
if ( ! InstallXLogFileSegment ( & installed_segno , tmppath ,
* use_existent , & max_advance ,
* use_existent , max_segno ,
use_lock ) )
use_lock ) )
{
{
/*
/*
@ -3011,7 +3116,7 @@ XLogFileCopy(XLogSegNo destsegno, TimeLineID srcTLI, XLogSegNo srcsegno,
/*
/*
* Now move the segment into place with its final name .
* Now move the segment into place with its final name .
*/
*/
if ( ! InstallXLogFileSegment ( & destsegno , tmppath , false , NULL , false ) )
if ( ! InstallXLogFileSegment ( & destsegno , tmppath , false , 0 , false ) )
elog ( ERROR , " InstallXLogFileSegment should not have failed " ) ;
elog ( ERROR , " InstallXLogFileSegment should not have failed " ) ;
}
}
@ -3031,22 +3136,21 @@ XLogFileCopy(XLogSegNo destsegno, TimeLineID srcTLI, XLogSegNo srcsegno,
* number at or after the passed numbers . If FALSE , install the new segment
* number at or after the passed numbers . If FALSE , install the new segment
* exactly where specified , deleting any existing segment file there .
* exactly where specified , deleting any existing segment file there .
*
*
* * max_advance : maximum number of segno slots to advance past the starting
* max_segno : maximum segment number to install the new file as . Fail if no
* point . Fail if no free slot is found in this range . On return , reduced
* free slot is found between * segno and max_segno . ( Ignored when find_free
* by the number of slots skipped over . ( Irrelevant , and may be NULL ,
* is FALSE . )
* when find_free is FALSE . )
*
*
* use_lock : if TRUE , acquire ControlFileLock while moving file into
* use_lock : if TRUE , acquire ControlFileLock while moving file into
* place . This should be TRUE except during bootstrap log creation . The
* place . This should be TRUE except during bootstrap log creation . The
* caller must * not * hold the lock at call .
* caller must * not * hold the lock at call .
*
*
* Returns TRUE if the file was installed successfully . FALSE indicates that
* Returns TRUE if the file was installed successfully . FALSE indicates that
* max_advance limit was exceeded , or an error occurred while renaming the
* max_segno limit was exceeded , or an error occurred while renaming the
* file into place .
* file into place .
*/
*/
static bool
static bool
InstallXLogFileSegment ( XLogSegNo * segno , char * tmppath ,
InstallXLogFileSegment ( XLogSegNo * segno , char * tmppath ,
bool find_free , int * max_advance ,
bool find_free , XLogSegNo max_segno ,
bool use_lock )
bool use_lock )
{
{
char path [ MAXPGPATH ] ;
char path [ MAXPGPATH ] ;
@ -3070,7 +3174,7 @@ InstallXLogFileSegment(XLogSegNo *segno, char *tmppath,
/* Find a free slot to put it in */
/* Find a free slot to put it in */
while ( stat ( path , & stat_buf ) = = 0 )
while ( stat ( path , & stat_buf ) = = 0 )
{
{
if ( * max_advance < = 0 )
if ( ( * segno ) > = max_segno )
{
{
/* Failed to find a free slot within specified range */
/* Failed to find a free slot within specified range */
if ( use_lock )
if ( use_lock )
@ -3078,7 +3182,6 @@ InstallXLogFileSegment(XLogSegNo *segno, char *tmppath,
return false ;
return false ;
}
}
( * segno ) + + ;
( * segno ) + + ;
( * max_advance ) - - ;
XLogFilePath ( path , ThisTimeLineID , * segno ) ;
XLogFilePath ( path , ThisTimeLineID , * segno ) ;
}
}
}
}
@ -3426,14 +3529,15 @@ UpdateLastRemovedPtr(char *filename)
/*
/*
* Recycle or remove all log files older or equal to passed segno
* Recycle or remove all log files older or equal to passed segno
*
*
* endptr is current ( or recent ) end of xlog ; this is used to determine
* endptr is current ( or recent ) end of xlog , and PriorRedoRecPtr is the
* redo pointer of the previous checkpoint . These are used to determine
* whether we want to recycle rather than delete no - longer - wanted log files .
* whether we want to recycle rather than delete no - longer - wanted log files .
*/
*/
static void
static void
RemoveOldXlogFiles ( XLogSegNo segno , XLogRecPtr endptr )
RemoveOldXlogFiles ( XLogSegNo segno , XLogRecPtr PriorRedoPtr , XLogRecPtr endptr )
{
{
XLogSegNo endlogSegNo ;
XLogSegNo endlogSegNo ;
int max_advance ;
XLogSegNo recycleSegNo ;
DIR * xldir ;
DIR * xldir ;
struct dirent * xlde ;
struct dirent * xlde ;
char lastoff [ MAXFNAMELEN ] ;
char lastoff [ MAXFNAMELEN ] ;
@ -3445,11 +3549,10 @@ RemoveOldXlogFiles(XLogSegNo segno, XLogRecPtr endptr)
struct stat statbuf ;
struct stat statbuf ;
/*
/*
* Initialize info about where to try to recycle to . We allow recycling
* Initialize info about where to try to recycle to .
* segments up to XLOGfileslop segments beyond the current XLOG location .
*/
*/
XLByteToPrevSeg ( endptr , endlogSegNo ) ;
XLByteToPrevSeg ( endptr , endlogSegNo ) ;
max_advance = XLOGfileslop ;
recycleSegNo = XLOGfileslop ( PriorRedoPtr ) ;
xldir = AllocateDir ( XLOGDIR ) ;
xldir = AllocateDir ( XLOGDIR ) ;
if ( xldir = = NULL )
if ( xldir = = NULL )
@ -3498,20 +3601,17 @@ RemoveOldXlogFiles(XLogSegNo segno, XLogRecPtr endptr)
* for example can create symbolic links pointing to a
* for example can create symbolic links pointing to a
* separate archive directory .
* separate archive directory .
*/
*/
if ( lstat ( path , & statbuf ) = = 0 & & S_ISREG ( statbuf . st_mode ) & &
if ( endlogSegNo < = recycleSegNo & &
lstat ( path , & statbuf ) = = 0 & & S_ISREG ( statbuf . st_mode ) & &
InstallXLogFileSegment ( & endlogSegNo , path ,
InstallXLogFileSegment ( & endlogSegNo , path ,
true , & max_advance , true ) )
true , recycleSegNo , true ) )
{
{
ereport ( DEBUG2 ,
ereport ( DEBUG2 ,
( errmsg ( " recycled transaction log file \" %s \" " ,
( errmsg ( " recycled transaction log file \" %s \" " ,
xlde - > d_name ) ) ) ;
xlde - > d_name ) ) ) ;
CheckpointStats . ckpt_segs_recycled + + ;
CheckpointStats . ckpt_segs_recycled + + ;
/* Needn't recheck that slot on future iterations */
/* Needn't recheck that slot on future iterations */
if ( max_advance > 0 )
{
endlogSegNo + + ;
endlogSegNo + + ;
max_advance - - ;
}
}
}
else
else
{
{
@ -7594,7 +7694,8 @@ LogCheckpointEnd(bool restartpoint)
elog ( LOG , " %s complete: wrote %d buffers (%.1f%%); "
elog ( LOG , " %s complete: wrote %d buffers (%.1f%%); "
" %d transaction log file(s) added, %d removed, %d recycled; "
" %d transaction log file(s) added, %d removed, %d recycled; "
" write=%ld.%03d s, sync=%ld.%03d s, total=%ld.%03d s; "
" write=%ld.%03d s, sync=%ld.%03d s, total=%ld.%03d s; "
" sync files=%d, longest=%ld.%03d s, average=%ld.%03d s " ,
" sync files=%d, longest=%ld.%03d s, average=%ld.%03d s; "
" distance=%d kB, estimate=%d kB " ,
restartpoint ? " restartpoint " : " checkpoint " ,
restartpoint ? " restartpoint " : " checkpoint " ,
CheckpointStats . ckpt_bufs_written ,
CheckpointStats . ckpt_bufs_written ,
( double ) CheckpointStats . ckpt_bufs_written * 100 / NBuffers ,
( double ) CheckpointStats . ckpt_bufs_written * 100 / NBuffers ,
@ -7606,7 +7707,48 @@ LogCheckpointEnd(bool restartpoint)
total_secs , total_usecs / 1000 ,
total_secs , total_usecs / 1000 ,
CheckpointStats . ckpt_sync_rels ,
CheckpointStats . ckpt_sync_rels ,
longest_secs , longest_usecs / 1000 ,
longest_secs , longest_usecs / 1000 ,
average_secs , average_usecs / 1000 ) ;
average_secs , average_usecs / 1000 ,
( int ) ( PrevCheckPointDistance / 1024.0 ) ,
( int ) ( CheckPointDistanceEstimate / 1024.0 ) ) ;
}
/*
* Update the estimate of distance between checkpoints .
*
* The estimate is used to calculate the number of WAL segments to keep
* preallocated , see XLOGFileSlop ( ) .
*/
static void
UpdateCheckPointDistanceEstimate ( uint64 nbytes )
{
/*
* To estimate the number of segments consumed between checkpoints , keep
* a moving average of the amount of WAL generated in previous checkpoint
* cycles . However , if the load is bursty , with quiet periods and busy
* periods , we want to cater for the peak load . So instead of a plain
* moving average , let the average decline slowly if the previous cycle
* used less WAL than estimated , but bump it up immediately if it used
* more .
*
* When checkpoints are triggered by max_wal_size , this should converge to
* CheckpointSegments * XLOG_SEG_SIZE ,
*
* Note : This doesn ' t pay any attention to what caused the checkpoint .
* Checkpoints triggered manually with CHECKPOINT command , or by e . g .
* starting a base backup , are counted the same as those created
* automatically . The slow - decline will largely mask them out , if they are
* not frequent . If they are frequent , it seems reasonable to count them
* in as any others ; if you issue a manual checkpoint every 5 minutes and
* never let a timed checkpoint happen , it makes sense to base the
* preallocation on that 5 minute interval rather than whatever
* checkpoint_timeout is set to .
*/
PrevCheckPointDistance = nbytes ;
if ( CheckPointDistanceEstimate < nbytes )
CheckPointDistanceEstimate = nbytes ;
else
CheckPointDistanceEstimate =
( 0.90 * CheckPointDistanceEstimate + 0.10 * ( double ) nbytes ) ;
}
}
/*
/*
@ -7646,7 +7788,7 @@ CreateCheckPoint(int flags)
XLogRecPtr recptr ;
XLogRecPtr recptr ;
XLogCtlInsert * Insert = & XLogCtl - > Insert ;
XLogCtlInsert * Insert = & XLogCtl - > Insert ;
uint32 freespace ;
uint32 freespace ;
XLogSegNo _logSegNo ;
XLogRecPtr PriorRedoPtr ;
XLogRecPtr curInsert ;
XLogRecPtr curInsert ;
VirtualTransactionId * vxids ;
VirtualTransactionId * vxids ;
int nvxids ;
int nvxids ;
@ -7961,10 +8103,10 @@ CreateCheckPoint(int flags)
( errmsg ( " concurrent transaction log activity while database system is shutting down " ) ) ) ;
( errmsg ( " concurrent transaction log activity while database system is shutting down " ) ) ) ;
/*
/*
* Select point at which we can truncate the log , which we base on th e
* Remember the prior checkpoint ' s redo pointer , used later to determin e
* prior checkpoint ' s earliest info .
* the point where the log can be truncated .
*/
*/
XLByteToSeg ( ControlFile - > checkPointCopy . redo , _logSegNo ) ;
PriorRedoPtr = ControlFile - > checkPointCopy . redo ;
/*
/*
* Update the control file .
* Update the control file .
@ -8019,11 +8161,17 @@ CreateCheckPoint(int flags)
* Delete old log files ( those no longer needed even for previous
* Delete old log files ( those no longer needed even for previous
* checkpoint or the standbys in XLOG streaming ) .
* checkpoint or the standbys in XLOG streaming ) .
*/
*/
if ( _logSegNo )
if ( PriorRedoPtr ! = InvalidXLogRecPtr )
{
{
XLogSegNo _logSegNo ;
/* Update the average distance between checkpoints. */
UpdateCheckPointDistanceEstimate ( RedoRecPtr - PriorRedoPtr ) ;
XLByteToSeg ( PriorRedoPtr , _logSegNo ) ;
KeepLogSeg ( recptr , & _logSegNo ) ;
KeepLogSeg ( recptr , & _logSegNo ) ;
_logSegNo - - ;
_logSegNo - - ;
RemoveOldXlogFiles ( _logSegNo , recptr ) ;
RemoveOldXlogFiles ( _logSegNo , PriorRedoPtr , recptr ) ;
}
}
/*
/*
@ -8191,7 +8339,7 @@ CreateRestartPoint(int flags)
{
{
XLogRecPtr lastCheckPointRecPtr ;
XLogRecPtr lastCheckPointRecPtr ;
CheckPoint lastCheckPoint ;
CheckPoint lastCheckPoint ;
XLogSegNo _logSegNo ;
XLogRecPtr PriorRedoPtr ;
TimestampTz xtime ;
TimestampTz xtime ;
/*
/*
@ -8256,14 +8404,14 @@ CreateRestartPoint(int flags)
/*
/*
* Update the shared RedoRecPtr so that the startup process can calculate
* Update the shared RedoRecPtr so that the startup process can calculate
* the number of segments replayed since last restartpoint , and request a
* the number of segments replayed since last restartpoint , and request a
* restartpoint if it exceeds checkpoint_s egments.
* restartpoint if it exceeds CheckPointS egments.
*
*
* Like in CreateCheckPoint ( ) , hold off insertions to update it , although
* Like in CreateCheckPoint ( ) , hold off insertions to update it , although
* during recovery this is just pro forma , because no WAL insertions are
* during recovery this is just pro forma , because no WAL insertions are
* happening .
* happening .
*/
*/
WALInsertLockAcquireExclusive ( ) ;
WALInsertLockAcquireExclusive ( ) ;
XLogCtl - > Insert . RedoRecPtr = lastCheckPoint . redo ;
RedoRecPtr = XLogCtl - > Insert . RedoRecPtr = lastCheckPoint . redo ;
WALInsertLockRelease ( ) ;
WALInsertLockRelease ( ) ;
/* Also update the info_lck-protected copy */
/* Also update the info_lck-protected copy */
@ -8287,10 +8435,10 @@ CreateRestartPoint(int flags)
CheckPointGuts ( lastCheckPoint . redo , flags ) ;
CheckPointGuts ( lastCheckPoint . redo , flags ) ;
/*
/*
* Select point at which we can truncate the xlog , which we base on th e
* Remember the prior checkpoint ' s redo pointer , used later to determin e
* prior checkpoint ' s earliest info .
* the point at which we can truncate the log .
*/
*/
XLByteToSeg ( ControlFile - > checkPointCopy . redo , _logSegNo ) ;
PriorRedoPtr = ControlFile - > checkPointCopy . redo ;
/*
/*
* Update pg_control , using current time . Check that it still shows
* Update pg_control , using current time . Check that it still shows
@ -8317,12 +8465,18 @@ CreateRestartPoint(int flags)
* checkpoint / restartpoint ) to prevent the disk holding the xlog from
* checkpoint / restartpoint ) to prevent the disk holding the xlog from
* growing full .
* growing full .
*/
*/
if ( _logSegNo )
if ( PriorRedoPtr ! = InvalidXLogRecPtr )
{
{
XLogRecPtr receivePtr ;
XLogRecPtr receivePtr ;
XLogRecPtr replayPtr ;
XLogRecPtr replayPtr ;
TimeLineID replayTLI ;
TimeLineID replayTLI ;
XLogRecPtr endptr ;
XLogRecPtr endptr ;
XLogSegNo _logSegNo ;
/* Update the average distance between checkpoints/restartpoints. */
UpdateCheckPointDistanceEstimate ( RedoRecPtr - PriorRedoPtr ) ;
XLByteToSeg ( PriorRedoPtr , _logSegNo ) ;
/*
/*
* Get the current end of xlog replayed or received , whichever is
* Get the current end of xlog replayed or received , whichever is
@ -8351,7 +8505,7 @@ CreateRestartPoint(int flags)
if ( RecoveryInProgress ( ) )
if ( RecoveryInProgress ( ) )
ThisTimeLineID = replayTLI ;
ThisTimeLineID = replayTLI ;
RemoveOldXlogFiles ( _logSegNo , endptr ) ;
RemoveOldXlogFiles ( _logSegNo , PriorRedoPtr , endptr ) ;
/*
/*
* Make more log segments if needed . ( Do this after recycling old log
* Make more log segments if needed . ( Do this after recycling old log