@@ -24,7 +24,8 @@ typedef struct
24
24
} restore_files_args ;
25
25
26
26
static void restore_database (pgBackup * backup );
27
- static void create_recovery_conf (const char * target_time ,
27
+ static void create_recovery_conf (time_t backup_id ,
28
+ const char * target_time ,
28
29
const char * target_xid ,
29
30
const char * target_inclusive ,
30
31
TimeLineID target_tli );
@@ -43,6 +44,9 @@ static void search_next_wal(const char *path,
43
44
parray * timelines );
44
45
static void restore_files (void * arg );
45
46
47
+ TimeLineID findNewestTimeLine (TimeLineID startTLI );
48
+ bool existsTimeLineHistory (TimeLineID probeTLI );
49
+
46
50
47
51
int
48
52
do_restore (time_t backup_id ,
@@ -57,6 +61,7 @@ do_restore(time_t backup_id,
57
61
int ret ;
58
62
TimeLineID cur_tli ;
59
63
TimeLineID backup_tli ;
64
+ TimeLineID newest_tli ;
60
65
parray * backups ;
61
66
pgBackup * base_backup = NULL ;
62
67
parray * files ;
@@ -95,13 +100,15 @@ do_restore(time_t backup_id,
95
100
elog (ERROR , "cannot process any more." );
96
101
97
102
cur_tli = get_current_timeline (true);
103
+ newest_tli = findNewestTimeLine (1 );
98
104
backup_tli = get_fullbackup_timeline (backups , rt );
99
105
100
106
/* determine target timeline */
101
107
if (target_tli == 0 )
102
- target_tli = cur_tli != 0 ? cur_tli : backup_tli ;
108
+ target_tli = newest_tli != 1 ? newest_tli : backup_tli ;
103
109
104
- elog (LOG , "current timeline ID = %u" , cur_tli );
110
+ elog (LOG , "current instance timeline ID = %u" , cur_tli );
111
+ elog (LOG , "newest timeline ID for wal dir = %u" , newest_tli );
105
112
elog (LOG , "latest full backup timeline ID = %u" , backup_tli );
106
113
elog (LOG , "target timeline ID = %u" , target_tli );
107
114
@@ -216,7 +223,7 @@ do_restore(time_t backup_id,
216
223
217
224
/* create recovery.conf */
218
225
if (!stream_wal || target_time != NULL || target_xid != NULL )
219
- create_recovery_conf (target_time , target_xid , target_inclusive , target_tli );
226
+ create_recovery_conf (backup_id , target_time , target_xid , target_inclusive , target_tli );
220
227
221
228
/* release catalog lock */
222
229
catalog_unlock ();
@@ -454,7 +461,8 @@ restore_files(void *arg)
454
461
}
455
462
456
463
static void
457
- create_recovery_conf (const char * target_time ,
464
+ create_recovery_conf (time_t backup_id ,
465
+ const char * target_time ,
458
466
const char * target_xid ,
459
467
const char * target_inclusive ,
460
468
TimeLineID target_tli )
@@ -484,8 +492,11 @@ create_recovery_conf(const char *target_time,
484
492
fprintf (fp , "recovery_target_time = '%s'\n" , target_time );
485
493
else if (target_xid )
486
494
fprintf (fp , "recovery_target_xid = '%s'\n" , target_xid );
487
- /*else
488
- fprintf(fp, "recovery_target = 'immediate'\n");*/
495
+ else if (backup_id != 0 )
496
+ {
497
+ fprintf (fp , "recovery_target = 'immediate'\n" );
498
+ fprintf (fp , "recovery_target_action = 'promote'\n" );
499
+ }
489
500
490
501
if (target_inclusive )
491
502
fprintf (fp , "recovery_target_inclusive = '%s'\n" , target_inclusive );
@@ -797,3 +808,67 @@ checkIfCreateRecoveryConf(const char *target_time,
797
808
return rt ;
798
809
799
810
}
811
+
812
+
813
+ /*
814
+ * Probe whether a timeline history file exists for the given timeline ID
815
+ */
816
+ bool
817
+ existsTimeLineHistory (TimeLineID probeTLI )
818
+ {
819
+ char path [MAXPGPATH ];
820
+ FILE * fd ;
821
+
822
+ /* Timeline 1 does not have a history file, so no need to check */
823
+ if (probeTLI == 1 )
824
+ return false;
825
+
826
+ snprintf (path , lengthof (path ), "%s/%08X.history" , arclog_path , probeTLI );
827
+ fd = fopen (path , "r" );
828
+ if (fd != NULL )
829
+ {
830
+ fclose (fd );
831
+ return true;
832
+ }
833
+ else
834
+ {
835
+ if (errno != ENOENT )
836
+ elog (ERROR , "Failed directory for path: %s" , path );
837
+ return false;
838
+ }
839
+ }
840
+
841
+ /*
842
+ * Find the newest existing timeline, assuming that startTLI exists.
843
+ *
844
+ * Note: while this is somewhat heuristic, it does positively guarantee
845
+ * that (result + 1) is not a known timeline, and therefore it should
846
+ * be safe to assign that ID to a new timeline.
847
+ */
848
+ TimeLineID
849
+ findNewestTimeLine (TimeLineID startTLI )
850
+ {
851
+ TimeLineID newestTLI ;
852
+ TimeLineID probeTLI ;
853
+
854
+ /*
855
+ * The algorithm is just to probe for the existence of timeline history
856
+ * files. XXX is it useful to allow gaps in the sequence?
857
+ */
858
+ newestTLI = startTLI ;
859
+
860
+ for (probeTLI = startTLI + 1 ;; probeTLI ++ )
861
+ {
862
+ if (existsTimeLineHistory (probeTLI ))
863
+ {
864
+ newestTLI = probeTLI ; /* probeTLI exists */
865
+ }
866
+ else
867
+ {
868
+ /* doesn't exist, assume we're done */
869
+ break ;
870
+ }
871
+ }
872
+
873
+ return newestTLI ;
874
+ }
0 commit comments