@@ -2904,12 +2904,15 @@ XLogFileInit(XLogSegNo logsegno, bool *use_existent, bool use_lock)
2904
2904
* srcTLI, srclog, srcseg: identify segment to be copied (could be from
2905
2905
* a different timeline)
2906
2906
*
2907
+ * upto: how much of the source file to copy? (the rest is filled with zeros)
2908
+ *
2907
2909
* Currently this is only used during recovery, and so there are no locking
2908
2910
* considerations. But we should be just as tense as XLogFileInit to avoid
2909
2911
* emplacing a bogus file.
2910
2912
*/
2911
2913
static void
2912
- XLogFileCopy (XLogSegNo destsegno , TimeLineID srcTLI , XLogSegNo srcsegno )
2914
+ XLogFileCopy (XLogSegNo destsegno , TimeLineID srcTLI , XLogSegNo srcsegno ,
2915
+ int upto )
2913
2916
{
2914
2917
char path [MAXPGPATH ];
2915
2918
char tmppath [MAXPGPATH ];
@@ -2948,16 +2951,31 @@ XLogFileCopy(XLogSegNo destsegno, TimeLineID srcTLI, XLogSegNo srcsegno)
2948
2951
*/
2949
2952
for (nbytes = 0 ; nbytes < XLogSegSize ; nbytes += sizeof (buffer ))
2950
2953
{
2951
- errno = 0 ;
2952
- if ((int ) read (srcfd , buffer , sizeof (buffer )) != (int ) sizeof (buffer ))
2954
+ int nread ;
2955
+
2956
+ nread = upto - nbytes ;
2957
+
2958
+ /*
2959
+ * The part that is not read from the source file is filled with zeros.
2960
+ */
2961
+ if (nread < sizeof (buffer ))
2962
+ memset (buffer , 0 , sizeof (buffer ));
2963
+
2964
+ if (nread > 0 )
2953
2965
{
2954
- if (errno != 0 )
2955
- ereport (ERROR ,
2956
- (errcode_for_file_access (),
2957
- errmsg ("could not read file \"%s\": %m" , path )));
2958
- else
2959
- ereport (ERROR ,
2960
- (errmsg ("not enough data in file \"%s\"" , path )));
2966
+ if (nread > sizeof (buffer ))
2967
+ nread = sizeof (buffer );
2968
+ errno = 0 ;
2969
+ if (read (srcfd , buffer , nread ) != nread )
2970
+ {
2971
+ if (errno != 0 )
2972
+ ereport (ERROR ,
2973
+ (errcode_for_file_access (),
2974
+ errmsg ("could not read file \"%s\": %m" , path )));
2975
+ else
2976
+ ereport (ERROR ,
2977
+ (errmsg ("not enough data in file \"%s\"" , path )));
2978
+ }
2961
2979
}
2962
2980
errno = 0 ;
2963
2981
if ((int ) write (fd , buffer , sizeof (buffer )) != (int ) sizeof (buffer ))
@@ -4960,10 +4978,15 @@ readRecoveryCommandFile(void)
4960
4978
* Exit archive-recovery state
4961
4979
*/
4962
4980
static void
4963
- exitArchiveRecovery (TimeLineID endTLI , XLogSegNo endLogSegNo )
4981
+ exitArchiveRecovery (TimeLineID endTLI , XLogRecPtr endOfLog )
4964
4982
{
4965
4983
char recoveryPath [MAXPGPATH ];
4966
4984
char xlogfname [MAXFNAMELEN ];
4985
+ XLogSegNo endLogSegNo ;
4986
+ XLogSegNo startLogSegNo ;
4987
+
4988
+ /* we always switch to a new timeline after archive recovery */
4989
+ Assert (endTLI != ThisTimeLineID );
4967
4990
4968
4991
/*
4969
4992
* We are no longer in archive recovery state.
@@ -4986,18 +5009,29 @@ exitArchiveRecovery(TimeLineID endTLI, XLogSegNo endLogSegNo)
4986
5009
}
4987
5010
4988
5011
/*
4989
- * If we are establishing a new timeline, we have to copy data from the
4990
- * last WAL segment of the old timeline to create a starting WAL segment
4991
- * for the new timeline.
5012
+ * Calculate the last segment on the old timeline, and the first segment
5013
+ * on the new timeline. If the switch happens in the middle of a segment,
5014
+ * they are the same, but if the switch happens exactly at a segment
5015
+ * boundary, startLogSegNo will be endLogSegNo + 1.
5016
+ */
5017
+ XLByteToPrevSeg (endOfLog , endLogSegNo );
5018
+ XLByteToSeg (endOfLog , startLogSegNo );
5019
+
5020
+ /*
5021
+ * Initialize the starting WAL segment for the new timeline. If the switch
5022
+ * happens in the middle of a segment, copy data from the last WAL segment
5023
+ * of the old timeline up to the switch point, to the starting WAL segment
5024
+ * on the new timeline.
4992
5025
*
4993
5026
* Notify the archiver that the last WAL segment of the old timeline is
4994
5027
* ready to copy to archival storage if its .done file doesn't exist
4995
5028
* (e.g., if it's the restored WAL file, it's expected to have .done file).
4996
5029
* Otherwise, it is not archived for a while.
4997
5030
*/
4998
- if (endTLI != ThisTimeLineID )
5031
+ if (endLogSegNo == startLogSegNo )
4999
5032
{
5000
- XLogFileCopy (endLogSegNo , endTLI , endLogSegNo );
5033
+ XLogFileCopy (startLogSegNo , endTLI , endLogSegNo ,
5034
+ endOfLog % XLOG_SEG_SIZE );
5001
5035
5002
5036
/* Create .ready file only when neither .ready nor .done files exist */
5003
5037
if (XLogArchivingActive ())
@@ -5006,12 +5040,18 @@ exitArchiveRecovery(TimeLineID endTLI, XLogSegNo endLogSegNo)
5006
5040
XLogArchiveCheckDone (xlogfname );
5007
5041
}
5008
5042
}
5043
+ else
5044
+ {
5045
+ bool use_existent = true;
5046
+
5047
+ XLogFileInit (startLogSegNo , & use_existent , true);
5048
+ }
5009
5049
5010
5050
/*
5011
5051
* Let's just make real sure there are not .ready or .done flags posted
5012
5052
* for the new segment.
5013
5053
*/
5014
- XLogFileName (xlogfname , ThisTimeLineID , endLogSegNo );
5054
+ XLogFileName (xlogfname , ThisTimeLineID , startLogSegNo );
5015
5055
XLogArchiveCleanup (xlogfname );
5016
5056
5017
5057
/*
@@ -5599,7 +5639,7 @@ StartupXLOG(void)
5599
5639
XLogRecPtr RecPtr ,
5600
5640
checkPointLoc ,
5601
5641
EndOfLog ;
5602
- XLogSegNo endLogSegNo ;
5642
+ XLogSegNo startLogSegNo ;
5603
5643
TimeLineID PrevTimeLineID ;
5604
5644
XLogRecord * record ;
5605
5645
TransactionId oldestActiveXID ;
@@ -6586,7 +6626,7 @@ StartupXLOG(void)
6586
6626
*/
6587
6627
record = ReadRecord (xlogreader , LastRec , PANIC , false);
6588
6628
EndOfLog = EndRecPtr ;
6589
- XLByteToPrevSeg (EndOfLog , endLogSegNo );
6629
+ XLByteToSeg (EndOfLog , startLogSegNo );
6590
6630
6591
6631
/*
6592
6632
* Complain if we did not roll forward far enough to render the backup
@@ -6687,14 +6727,14 @@ StartupXLOG(void)
6687
6727
* we will use that below.)
6688
6728
*/
6689
6729
if (ArchiveRecoveryRequested )
6690
- exitArchiveRecovery (xlogreader -> readPageTLI , endLogSegNo );
6730
+ exitArchiveRecovery (xlogreader -> readPageTLI , EndOfLog );
6691
6731
6692
6732
/*
6693
6733
* Prepare to write WAL starting at EndOfLog position, and init xlog
6694
6734
* buffer cache using the block containing the last record from the
6695
6735
* previous incarnation.
6696
6736
*/
6697
- openLogSegNo = endLogSegNo ;
6737
+ openLogSegNo = startLogSegNo ;
6698
6738
openLogFile = XLogFileOpen (openLogSegNo );
6699
6739
openLogOff = 0 ;
6700
6740
Insert = & XLogCtl -> Insert ;
0 commit comments