@@ -2904,12 +2904,15 @@ XLogFileInit(XLogSegNo logsegno, bool *use_existent, bool use_lock)
29042904 * srcTLI, srclog, srcseg: identify segment to be copied (could be from
29052905 * a different timeline)
29062906 *
2907+ * upto: how much of the source file to copy? (the rest is filled with zeros)
2908+ *
29072909 * Currently this is only used during recovery, and so there are no locking
29082910 * considerations. But we should be just as tense as XLogFileInit to avoid
29092911 * emplacing a bogus file.
29102912 */
29112913static void
2912- XLogFileCopy (XLogSegNo destsegno , TimeLineID srcTLI , XLogSegNo srcsegno )
2914+ XLogFileCopy (XLogSegNo destsegno , TimeLineID srcTLI , XLogSegNo srcsegno ,
2915+ int upto )
29132916{
29142917 char path [MAXPGPATH ];
29152918 char tmppath [MAXPGPATH ];
@@ -2948,16 +2951,31 @@ XLogFileCopy(XLogSegNo destsegno, TimeLineID srcTLI, XLogSegNo srcsegno)
29482951 */
29492952 for (nbytes = 0 ; nbytes < XLogSegSize ; nbytes += sizeof (buffer ))
29502953 {
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 )
29532965 {
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+ }
29612979 }
29622980 errno = 0 ;
29632981 if ((int ) write (fd , buffer , sizeof (buffer )) != (int ) sizeof (buffer ))
@@ -4960,10 +4978,15 @@ readRecoveryCommandFile(void)
49604978 * Exit archive-recovery state
49614979 */
49624980static void
4963- exitArchiveRecovery (TimeLineID endTLI , XLogSegNo endLogSegNo )
4981+ exitArchiveRecovery (TimeLineID endTLI , XLogRecPtr endOfLog )
49644982{
49654983 char recoveryPath [MAXPGPATH ];
49664984 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 );
49674990
49684991 /*
49694992 * We are no longer in archive recovery state.
@@ -4986,18 +5009,29 @@ exitArchiveRecovery(TimeLineID endTLI, XLogSegNo endLogSegNo)
49865009 }
49875010
49885011 /*
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.
49925025 *
49935026 * Notify the archiver that the last WAL segment of the old timeline is
49945027 * ready to copy to archival storage if its .done file doesn't exist
49955028 * (e.g., if it's the restored WAL file, it's expected to have .done file).
49965029 * Otherwise, it is not archived for a while.
49975030 */
4998- if (endTLI != ThisTimeLineID )
5031+ if (endLogSegNo == startLogSegNo )
49995032 {
5000- XLogFileCopy (endLogSegNo , endTLI , endLogSegNo );
5033+ XLogFileCopy (startLogSegNo , endTLI , endLogSegNo ,
5034+ endOfLog % XLOG_SEG_SIZE );
50015035
50025036 /* Create .ready file only when neither .ready nor .done files exist */
50035037 if (XLogArchivingActive ())
@@ -5006,12 +5040,18 @@ exitArchiveRecovery(TimeLineID endTLI, XLogSegNo endLogSegNo)
50065040 XLogArchiveCheckDone (xlogfname );
50075041 }
50085042 }
5043+ else
5044+ {
5045+ bool use_existent = true;
5046+
5047+ XLogFileInit (startLogSegNo , & use_existent , true);
5048+ }
50095049
50105050 /*
50115051 * Let's just make real sure there are not .ready or .done flags posted
50125052 * for the new segment.
50135053 */
5014- XLogFileName (xlogfname , ThisTimeLineID , endLogSegNo );
5054+ XLogFileName (xlogfname , ThisTimeLineID , startLogSegNo );
50155055 XLogArchiveCleanup (xlogfname );
50165056
50175057 /*
@@ -5599,7 +5639,7 @@ StartupXLOG(void)
55995639 XLogRecPtr RecPtr ,
56005640 checkPointLoc ,
56015641 EndOfLog ;
5602- XLogSegNo endLogSegNo ;
5642+ XLogSegNo startLogSegNo ;
56035643 TimeLineID PrevTimeLineID ;
56045644 XLogRecord * record ;
56055645 TransactionId oldestActiveXID ;
@@ -6586,7 +6626,7 @@ StartupXLOG(void)
65866626 */
65876627 record = ReadRecord (xlogreader , LastRec , PANIC , false);
65886628 EndOfLog = EndRecPtr ;
6589- XLByteToPrevSeg (EndOfLog , endLogSegNo );
6629+ XLByteToSeg (EndOfLog , startLogSegNo );
65906630
65916631 /*
65926632 * Complain if we did not roll forward far enough to render the backup
@@ -6687,14 +6727,14 @@ StartupXLOG(void)
66876727 * we will use that below.)
66886728 */
66896729 if (ArchiveRecoveryRequested )
6690- exitArchiveRecovery (xlogreader -> readPageTLI , endLogSegNo );
6730+ exitArchiveRecovery (xlogreader -> readPageTLI , EndOfLog );
66916731
66926732 /*
66936733 * Prepare to write WAL starting at EndOfLog position, and init xlog
66946734 * buffer cache using the block containing the last record from the
66956735 * previous incarnation.
66966736 */
6697- openLogSegNo = endLogSegNo ;
6737+ openLogSegNo = startLogSegNo ;
66986738 openLogFile = XLogFileOpen (openLogSegNo );
66996739 openLogOff = 0 ;
67006740 Insert = & XLogCtl -> Insert ;
0 commit comments