@@ -45,7 +45,13 @@ static void digestControlFile(ControlFileData *ControlFile,
45
45
const char * content , size_t size );
46
46
static void getRestoreCommand (const char * argv0 );
47
47
static void sanityChecks (void );
48
- static void findCommonAncestorTimeline (XLogRecPtr * recptr , int * tliIndex );
48
+ static TimeLineHistoryEntry * getTimelineHistory (TimeLineID tli , bool is_source ,
49
+ int * nentries );
50
+ static void findCommonAncestorTimeline (TimeLineHistoryEntry * a_history ,
51
+ int a_nentries ,
52
+ TimeLineHistoryEntry * b_history ,
53
+ int b_nentries ,
54
+ XLogRecPtr * recptr , int * tliIndex );
49
55
static void ensureCleanShutdown (const char * argv0 );
50
56
static void disconnect_atexit (void );
51
57
@@ -134,6 +140,8 @@ main(int argc, char **argv)
134
140
XLogRecPtr chkptrec ;
135
141
TimeLineID chkpttli ;
136
142
XLogRecPtr chkptredo ;
143
+ TimeLineID source_tli ;
144
+ TimeLineID target_tli ;
137
145
XLogRecPtr target_wal_endrec ;
138
146
size_t size ;
139
147
char * buffer ;
@@ -332,14 +340,28 @@ main(int argc, char **argv)
332
340
333
341
sanityChecks ();
334
342
343
+ /*
344
+ * Usually, the TLI can be found in the latest checkpoint record. But if
345
+ * the source server is just being promoted (or it's a standby that's
346
+ * following a primary that's just being promoted), and the checkpoint
347
+ * requested by the promotion hasn't completed yet, the latest timeline is
348
+ * in minRecoveryPoint. So we check which is later, the TLI of the
349
+ * minRecoveryPoint or the latest checkpoint.
350
+ */
351
+ source_tli = Max (ControlFile_source .minRecoveryPointTLI ,
352
+ ControlFile_source .checkPointCopy .ThisTimeLineID );
353
+
354
+ /* Similarly for the target. */
355
+ target_tli = Max (ControlFile_target .minRecoveryPointTLI ,
356
+ ControlFile_target .checkPointCopy .ThisTimeLineID );
357
+
335
358
/*
336
359
* Find the common ancestor timeline between the clusters.
337
360
*
338
361
* If both clusters are already on the same timeline, there's nothing to
339
362
* do.
340
363
*/
341
- if (ControlFile_target .checkPointCopy .ThisTimeLineID ==
342
- ControlFile_source .checkPointCopy .ThisTimeLineID )
364
+ if (target_tli == source_tli )
343
365
{
344
366
pg_log_info ("source and target cluster are on the same timeline" );
345
367
rewind_needed = false;
@@ -348,12 +370,31 @@ main(int argc, char **argv)
348
370
else
349
371
{
350
372
XLogRecPtr chkptendrec ;
373
+ TimeLineHistoryEntry * sourceHistory ;
374
+ int sourceNentries ;
375
+
376
+ /*
377
+ * Retrieve timelines for both source and target, and find the point
378
+ * where they diverged.
379
+ */
380
+ sourceHistory = getTimelineHistory (source_tli , true, & sourceNentries );
381
+ targetHistory = getTimelineHistory (target_tli , false, & targetNentries );
382
+
383
+ findCommonAncestorTimeline (sourceHistory , sourceNentries ,
384
+ targetHistory , targetNentries ,
385
+ & divergerec , & lastcommontliIndex );
351
386
352
- findCommonAncestorTimeline (& divergerec , & lastcommontliIndex );
353
387
pg_log_info ("servers diverged at WAL location %X/%X on timeline %u" ,
354
388
LSN_FORMAT_ARGS (divergerec ),
355
389
targetHistory [lastcommontliIndex ].tli );
356
390
391
+ /*
392
+ * Don't need the source history anymore. The target history is still
393
+ * needed by the routines in parsexlog.c, when we read the target WAL.
394
+ */
395
+ pfree (sourceHistory );
396
+
397
+
357
398
/*
358
399
* Determine the end-of-WAL on the target.
359
400
*
@@ -654,7 +695,8 @@ perform_rewind(filemap_t *filemap, rewind_source *source,
654
695
pg_fatal ("source system was in unexpected state at end of rewind" );
655
696
656
697
endrec = source -> get_current_wal_insert_lsn (source );
657
- endtli = ControlFile_source_after .checkPointCopy .ThisTimeLineID ;
698
+ endtli = Max (ControlFile_source_after .checkPointCopy .ThisTimeLineID ,
699
+ ControlFile_source_after .minRecoveryPointTLI );
658
700
}
659
701
}
660
702
else
@@ -796,16 +838,12 @@ MinXLogRecPtr(XLogRecPtr a, XLogRecPtr b)
796
838
}
797
839
798
840
/*
799
- * Retrieve timeline history for given control file which should behold
800
- * either source or target.
841
+ * Retrieve timeline history for the source or target system.
801
842
*/
802
843
static TimeLineHistoryEntry *
803
- getTimelineHistory (ControlFileData * controlFile , int * nentries )
844
+ getTimelineHistory (TimeLineID tli , bool is_source , int * nentries )
804
845
{
805
846
TimeLineHistoryEntry * history ;
806
- TimeLineID tli ;
807
-
808
- tli = controlFile -> checkPointCopy .ThisTimeLineID ;
809
847
810
848
/*
811
849
* Timeline 1 does not have a history file, so there is no need to check
@@ -826,12 +864,10 @@ getTimelineHistory(ControlFileData *controlFile, int *nentries)
826
864
TLHistoryFilePath (path , tli );
827
865
828
866
/* Get history file from appropriate source */
829
- if (controlFile == & ControlFile_source )
867
+ if (is_source )
830
868
histfile = source -> fetch_file (source , path , NULL );
831
- else if (controlFile == & ControlFile_target )
832
- histfile = slurpFile (datadir_target , path , NULL );
833
869
else
834
- pg_fatal ( "invalid control file" );
870
+ histfile = slurpFile ( datadir_target , path , NULL );
835
871
836
872
history = rewind_parseTimeLineHistory (histfile , tli , nentries );
837
873
pg_free (histfile );
@@ -841,12 +877,10 @@ getTimelineHistory(ControlFileData *controlFile, int *nentries)
841
877
{
842
878
int i ;
843
879
844
- if (controlFile == & ControlFile_source )
880
+ if (is_source )
845
881
pg_log_debug ("Source timeline history:" );
846
- else if (controlFile == & ControlFile_target )
847
- pg_log_debug ("Target timeline history:" );
848
882
else
849
- Assert (false );
883
+ pg_log_debug ( "Target timeline history:" );
850
884
851
885
/*
852
886
* Print the target timeline history.
@@ -866,28 +900,19 @@ getTimelineHistory(ControlFileData *controlFile, int *nentries)
866
900
}
867
901
868
902
/*
869
- * Determine the TLI of the last common timeline in the timeline history of the
870
- * two clusters. targetHistory is filled with target timeline history and
871
- * targetNentries is number of items in targetHistory. *tliIndex is set to the
872
- * index of last common timeline in targetHistory array, and *recptr is set to
873
- * the position where the timeline history diverged (ie. the first WAL record
874
- * that's not the same in both clusters).
875
- *
876
- * Control files of both clusters must be read into ControlFile_target/source
877
- * before calling this routine.
903
+ * Determine the TLI of the last common timeline in the timeline history of
904
+ * two clusters. *tliIndex is set to the index of last common timeline in
905
+ * the arrays, and *recptr is set to the position where the timeline history
906
+ * diverged (ie. the first WAL record that's not the same in both clusters).
878
907
*/
879
908
static void
880
- findCommonAncestorTimeline (XLogRecPtr * recptr , int * tliIndex )
909
+ findCommonAncestorTimeline (TimeLineHistoryEntry * a_history , int a_nentries ,
910
+ TimeLineHistoryEntry * b_history , int b_nentries ,
911
+ XLogRecPtr * recptr , int * tliIndex )
881
912
{
882
- TimeLineHistoryEntry * sourceHistory ;
883
- int sourceNentries ;
884
913
int i ,
885
914
n ;
886
915
887
- /* Retrieve timelines for both source and target */
888
- sourceHistory = getTimelineHistory (& ControlFile_source , & sourceNentries );
889
- targetHistory = getTimelineHistory (& ControlFile_target , & targetNentries );
890
-
891
916
/*
892
917
* Trace the history forward, until we hit the timeline diverge. It may
893
918
* still be possible that the source and target nodes used the same
@@ -896,21 +921,19 @@ findCommonAncestorTimeline(XLogRecPtr *recptr, int *tliIndex)
896
921
* recovery processes. Hence check the start position of the new timeline
897
922
* as well and move down by one extra timeline entry if they do not match.
898
923
*/
899
- n = Min (sourceNentries , targetNentries );
924
+ n = Min (a_nentries , b_nentries );
900
925
for (i = 0 ; i < n ; i ++ )
901
926
{
902
- if (sourceHistory [i ].tli != targetHistory [i ].tli ||
903
- sourceHistory [i ].begin != targetHistory [i ].begin )
927
+ if (a_history [i ].tli != b_history [i ].tli ||
928
+ a_history [i ].begin != b_history [i ].begin )
904
929
break ;
905
930
}
906
931
907
932
if (i > 0 )
908
933
{
909
934
i -- ;
910
- * recptr = MinXLogRecPtr (sourceHistory [i ].end , targetHistory [i ].end );
935
+ * recptr = MinXLogRecPtr (a_history [i ].end , b_history [i ].end );
911
936
* tliIndex = i ;
912
-
913
- pg_free (sourceHistory );
914
937
return ;
915
938
}
916
939
else
0 commit comments