@@ -782,6 +782,8 @@ static intemode_for_corrupt_record(int emode, XLogRecPtr RecPtr);
782782static void XLogFileClose (void );
783783static void PreallocXlogFiles (XLogRecPtr endptr );
784784static void RemoveOldXlogFiles (XLogSegNo segno ,XLogRecPtr endptr );
785+ static void RemoveXlogFile (const char * segname ,XLogRecPtr endptr );
786+ static void RemoveNonParentXlogFiles (XLogRecPtr switchpoint ,TimeLineID newTLI );
785787static void UpdateLastRemovedPtr (char * filename );
786788static void ValidateXLOGDirectoryStructure (void );
787789static void CleanupBackupHistory (void );
@@ -3743,32 +3745,17 @@ UpdateLastRemovedPtr(char *filename)
37433745}
37443746
37453747/*
3746- * Recycle or remove all log files older or equal to passed segno
3748+ * Recycle or remove all log files older or equal to passed segno.
37473749 *
37483750 * endptr is current (or recent) end of xlog; this is used to determine
37493751 * whether we want to recycle rather than delete no-longer-wanted log files.
37503752 */
37513753static void
37523754RemoveOldXlogFiles (XLogSegNo segno ,XLogRecPtr endptr )
37533755{
3754- XLogSegNo endlogSegNo ;
3755- int max_advance ;
37563756DIR * xldir ;
37573757struct dirent * xlde ;
37583758char lastoff [MAXFNAMELEN ];
3759- char path [MAXPGPATH ];
3760-
3761- #ifdef WIN32
3762- char newpath [MAXPGPATH ];
3763- #endif
3764- struct stat statbuf ;
3765-
3766- /*
3767- * Initialize info about where to try to recycle to. We allow recycling
3768- * segments up to XLOGfileslop segments beyond the current XLOG location.
3769- */
3770- XLByteToPrevSeg (endptr ,endlogSegNo );
3771- max_advance = XLOGfileslop ;
37723759
37733760xldir = AllocateDir (XLOGDIR );
37743761if (xldir == NULL )
@@ -3789,6 +3776,11 @@ RemoveOldXlogFiles(XLogSegNo segno, XLogRecPtr endptr)
37893776
37903777while ((xlde = ReadDir (xldir ,XLOGDIR ))!= NULL )
37913778{
3779+ /* Ignore files that are not XLOG segments */
3780+ if (strlen (xlde -> d_name )!= 24 ||
3781+ strspn (xlde -> d_name ,"0123456789ABCDEF" )!= 24 )
3782+ continue ;
3783+
37923784/*
37933785 * We ignore the timeline part of the XLOG segment identifiers in
37943786 * deciding whether a segment is still needed. This ensures that we
@@ -3800,92 +3792,110 @@ RemoveOldXlogFiles(XLogSegNo segno, XLogRecPtr endptr)
38003792 * We use the alphanumeric sorting property of the filenames to decide
38013793 * which ones are earlier than the lastoff segment.
38023794 */
3803- if (strlen (xlde -> d_name )== 24 &&
3804- strspn (xlde -> d_name ,"0123456789ABCDEF" )== 24 &&
3805- strcmp (xlde -> d_name + 8 ,lastoff + 8 ) <=0 )
3795+ if (strcmp (xlde -> d_name + 8 ,lastoff + 8 ) <=0 )
38063796{
38073797if (XLogArchiveCheckDone (xlde -> d_name ))
38083798{
3809- snprintf (path ,MAXPGPATH ,XLOGDIR "/%s" ,xlde -> d_name );
3810-
38113799/* Update the last removed location in shared memory first */
38123800UpdateLastRemovedPtr (xlde -> d_name );
38133801
3814- /*
3815- * Before deleting the file, see if it can be recycled as a
3816- * future log segment. Only recycle normal files, pg_standby
3817- * for example can create symbolic links pointing to a
3818- * separate archive directory.
3819- */
3820- if (lstat (path ,& statbuf )== 0 && S_ISREG (statbuf .st_mode )&&
3821- InstallXLogFileSegment (& endlogSegNo ,path ,
3822- true,& max_advance , true))
3823- {
3824- ereport (DEBUG2 ,
3825- (errmsg ("recycled transaction log file \"%s\"" ,
3826- xlde -> d_name )));
3827- CheckpointStats .ckpt_segs_recycled ++ ;
3828- /* Needn't recheck that slot on future iterations */
3829- if (max_advance > 0 )
3830- {
3831- endlogSegNo ++ ;
3832- max_advance -- ;
3833- }
3834- }
3835- else
3836- {
3837- /* No need for any more future segments... */
3838- int rc ;
3802+ RemoveXlogFile (xlde -> d_name ,endptr );
3803+ }
3804+ }
3805+ }
38393806
3840- ereport (DEBUG2 ,
3841- (errmsg ("removing transaction log file \"%s\"" ,
3842- xlde -> d_name )));
3807+ FreeDir (xldir );
3808+ }
38433809
3810+ /*
3811+ * Recycle or remove a log file that's no longer needed.
3812+ *
3813+ * endptr is current (or recent) end of xlog; this is used to determine
3814+ * whether we want to recycle rather than delete no-longer-wanted log files.
3815+ */
3816+ static void
3817+ RemoveXlogFile (const char * segname ,XLogRecPtr endptr )
3818+ {
3819+ char path [MAXPGPATH ];
38443820#ifdef WIN32
3821+ char newpath [MAXPGPATH ];
3822+ #endif
3823+ struct stat statbuf ;
3824+ XLogSegNo endlogSegNo ;
3825+ int max_advance ;
38453826
3846- /*
3847- * On Windows, if another process (e.g another backend)
3848- * holds the file open in FILE_SHARE_DELETE mode, unlink
3849- * will succeed, but the file will still show up in
3850- * directory listing until the last handle is closed. To
3851- * avoid confusing the lingering deleted file for a live
3852- * WAL file that needs to be archived, rename it before
3853- * deleting it.
3854- *
3855- * If another process holds the file open without
3856- * FILE_SHARE_DELETE flag, rename will fail. We'll try
3857- * again at the next checkpoint.
3858- */
3859- snprintf (newpath ,MAXPGPATH ,"%s.deleted" ,path );
3860- if (rename (path ,newpath )!= 0 )
3861- {
3862- ereport (LOG ,
3863- (errcode_for_file_access (),
3864- errmsg ("could not rename old transaction log file \"%s\": %m" ,
3865- path )));
3866- continue ;
3867- }
3868- rc = unlink (newpath );
3827+ /*
3828+ * Initialize info about where to try to recycle to. We allow recycling
3829+ * segments up to XLOGfileslop segments beyond the current XLOG location.
3830+ */
3831+ XLByteToPrevSeg (endptr ,endlogSegNo );
3832+ max_advance = XLOGfileslop ;
3833+
3834+ snprintf (path ,MAXPGPATH ,XLOGDIR "/%s" ,segname );
3835+
3836+ /*
3837+ * Before deleting the file, see if it can be recycled as a future log
3838+ * segment. Only recycle normal files, pg_standby for example can create
3839+ * symbolic links pointing to a separate archive directory.
3840+ */
3841+ if (lstat (path ,& statbuf )== 0 && S_ISREG (statbuf .st_mode )&&
3842+ InstallXLogFileSegment (& endlogSegNo ,path ,
3843+ true,& max_advance , true))
3844+ {
3845+ ereport (DEBUG2 ,
3846+ (errmsg ("recycled transaction log file \"%s\"" ,segname )));
3847+ CheckpointStats .ckpt_segs_recycled ++ ;
3848+ /* Needn't recheck that slot on future iterations */
3849+ if (max_advance > 0 )
3850+ {
3851+ endlogSegNo ++ ;
3852+ max_advance -- ;
3853+ }
3854+ }
3855+ else
3856+ {
3857+ /* No need for any more future segments... */
3858+ int rc ;
3859+
3860+ ereport (DEBUG2 ,
3861+ (errmsg ("removing transaction log file \"%s\"" ,segname )));
3862+
3863+ #ifdef WIN32
3864+ /*
3865+ * On Windows, if another process (e.g another backend) holds the file
3866+ * open in FILE_SHARE_DELETE mode, unlink will succeed, but the file
3867+ * will still show up in directory listing until the last handle is
3868+ * closed. To avoid confusing the lingering deleted file for a live
3869+ * WAL file that needs to be archived, rename it before deleting it.
3870+ *
3871+ * If another process holds the file open without FILE_SHARE_DELETE
3872+ * flag, rename will fail. We'll try again at the next checkpoint.
3873+ */
3874+ snprintf (newpath ,MAXPGPATH ,"%s.deleted" ,path );
3875+ if (rename (path ,newpath )!= 0 )
3876+ {
3877+ ereport (LOG ,
3878+ (errcode_for_file_access (),
3879+ errmsg ("could not rename old transaction log file \"%s\": %m" ,
3880+ path )));
3881+ return ;
3882+ }
3883+ rc = unlink (newpath );
38693884#else
3870- rc = unlink (path );
3885+ rc = unlink (path );
38713886#endif
3872- if (rc != 0 )
3873- {
3874- ereport (LOG ,
3875- (errcode_for_file_access (),
3876- errmsg ("could not remove old transaction log file \"%s\": %m" ,
3877- path )));
3878- continue ;
3879- }
3880- CheckpointStats .ckpt_segs_removed ++ ;
3881- }
3882-
3883- XLogArchiveCleanup (xlde -> d_name );
3884- }
3887+ if (rc != 0 )
3888+ {
3889+ ereport (LOG ,
3890+ (errcode_for_file_access (),
3891+ errmsg ("could not remove old transaction log file \"%s\": %m" ,
3892+ path )));
3893+ return ;
38853894}
3895+ CheckpointStats .ckpt_segs_removed ++ ;
38863896}
38873897
3888- FreeDir ( xldir );
3898+ XLogArchiveCleanup ( segname );
38893899}
38903900
38913901/*
@@ -5407,6 +5417,76 @@ exitArchiveRecovery(TimeLineID endTLI, XLogSegNo endLogSegNo)
54075417(errmsg ("archive recovery complete" )));
54085418}
54095419
5420+ /*
5421+ * Remove WAL files that are not part of the given timeline's history.
5422+ *
5423+ * This is called during recovery, whenever we switch to follow a new
5424+ * timeline, and at the end of recovery when we create a new timeline. We
5425+ * wouldn't otherwise care about extra WAL files lying in pg_xlog, but they
5426+ * can be pre-allocated or recycled WAL segments on the old timeline that we
5427+ * haven't used yet, and contain garbage. If we just leave them in pg_xlog,
5428+ * they will eventually be archived, and we can't let that happen. Files that
5429+ * belong to our timeline history are valid, because we have successfully
5430+ * replayed them, but from others we can't be sure.
5431+ *
5432+ * 'switchpoint' is the current point in WAL where we switch to new timeline,
5433+ * and 'newTLI' is the new timeline we switch to.
5434+ */
5435+ static void
5436+ RemoveNonParentXlogFiles (XLogRecPtr switchpoint ,TimeLineID newTLI )
5437+ {
5438+ DIR * xldir ;
5439+ struct dirent * xlde ;
5440+ char switchseg [MAXFNAMELEN ];
5441+ XLogSegNo endLogSegNo ;
5442+
5443+ XLByteToPrevSeg (switchpoint ,endLogSegNo );
5444+
5445+ xldir = AllocateDir (XLOGDIR );
5446+ if (xldir == NULL )
5447+ ereport (ERROR ,
5448+ (errcode_for_file_access (),
5449+ errmsg ("could not open transaction log directory \"%s\": %m" ,
5450+ XLOGDIR )));
5451+
5452+ /*
5453+ * Construct a filename of the last segment to be kept.
5454+ */
5455+ XLogFileName (switchseg ,newTLI ,endLogSegNo );
5456+
5457+ elog (DEBUG2 ,"attempting to remove WAL segments newer than log file %s" ,
5458+ switchseg );
5459+
5460+ while ((xlde = ReadDir (xldir ,XLOGDIR ))!= NULL )
5461+ {
5462+ /* Ignore files that are not XLOG segments */
5463+ if (strlen (xlde -> d_name )!= 24 ||
5464+ strspn (xlde -> d_name ,"0123456789ABCDEF" )!= 24 )
5465+ continue ;
5466+
5467+ /*
5468+ * Remove files that are on a timeline older than the new one we're
5469+ * switching to, but with a segment number >= the first segment on
5470+ * the new timeline.
5471+ */
5472+ if (strncmp (xlde -> d_name ,switchseg ,8 )< 0 &&
5473+ strcmp (xlde -> d_name + 8 ,switchseg + 8 )> 0 )
5474+ {
5475+ /*
5476+ * If the file has already been marked as .ready, however, don't
5477+ * remove it yet. It should be OK to remove it - files that are
5478+ * not part of our timeline history are not required for recovery
5479+ * - but seems safer to let them be archived and removed later.
5480+ */
5481+ if (!XLogArchiveIsReady (xlde -> d_name ))
5482+ RemoveXlogFile (xlde -> d_name ,switchpoint );
5483+ }
5484+ }
5485+
5486+ FreeDir (xldir );
5487+ }
5488+
5489+
54105490/*
54115491 * Extract timestamp from WAL record.
54125492 *
@@ -6775,9 +6855,9 @@ StartupXLOG(void)
67756855 */
67766856if (record -> xl_rmid == RM_XLOG_ID )
67776857{
6858+ uint8 info = record -> xl_info & ~XLR_INFO_MASK ;
67786859TimeLineID newTLI = ThisTimeLineID ;
67796860TimeLineID prevTLI = ThisTimeLineID ;
6780- uint8 info = record -> xl_info & ~XLR_INFO_MASK ;
67816861
67826862if (info == XLOG_CHECKPOINT_SHUTDOWN )
67836863{
@@ -6845,12 +6925,21 @@ StartupXLOG(void)
68456925/* Allow read-only connections if we're consistent now */
68466926CheckRecoveryConsistency ();
68476927
6848- /*
6849- * If this record was a timeline switch, wake up any
6850- * walsenders to notice that we are on a new timeline.
6851- */
6852- if (switchedTLI && AllowCascadeReplication ())
6853- WalSndWakeup ();
6928+ if (switchedTLI )
6929+ {
6930+ /*
6931+ * Before we go further on the new timeline, clean up any
6932+ * (possibly bogus) future WAL segments on the old one.
6933+ */
6934+ RemoveNonParentXlogFiles (EndRecPtr ,ThisTimeLineID );
6935+
6936+ /*
6937+ * Wake up any walsenders to notice that we are on a new
6938+ * timeline.
6939+ */
6940+ if (AllowCascadeReplication ())
6941+ WalSndWakeup ();
6942+ }
68546943
68556944/* Exit loop if we reached inclusive recovery target */
68566945if (recoveryStopsAfter (record ))
@@ -7177,6 +7266,12 @@ StartupXLOG(void)
71777266 true);
71787267}
71797268
7269+ /*
7270+ * Clean up any (possibly bogus) future WAL segments on the old timeline.
7271+ */
7272+ if (ArchiveRecoveryRequested )
7273+ RemoveNonParentXlogFiles (EndOfLog ,ThisTimeLineID );
7274+
71807275/*
71817276 * Preallocate additional log files, if wanted.
71827277 */