@@ -24,7 +24,8 @@ typedef struct
2424}restore_files_args ;
2525
2626static 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 ,
2829const char * target_xid ,
2930const char * target_inclusive ,
3031TimeLineID target_tli );
@@ -43,6 +44,9 @@ static void search_next_wal(const char *path,
4344parray * timelines );
4445static void restore_files (void * arg );
4546
47+ TimeLineID findNewestTimeLine (TimeLineID startTLI );
48+ bool existsTimeLineHistory (TimeLineID probeTLI );
49+
4650
4751int
4852do_restore (time_t backup_id ,
@@ -57,6 +61,7 @@ do_restore(time_t backup_id,
5761int ret ;
5862TimeLineID cur_tli ;
5963TimeLineID backup_tli ;
64+ TimeLineID newest_tli ;
6065parray * backups ;
6166pgBackup * base_backup = NULL ;
6267parray * files ;
@@ -95,13 +100,15 @@ do_restore(time_t backup_id,
95100elog (ERROR ,"cannot process any more." );
96101
97102cur_tli = get_current_timeline (true);
103+ newest_tli = findNewestTimeLine (1 );
98104backup_tli = get_fullbackup_timeline (backups ,rt );
99105
100106/* determine target timeline */
101107if (target_tli == 0 )
102- target_tli = cur_tli != 0 ?cur_tli :backup_tli ;
108+ target_tli = newest_tli != 1 ?newest_tli :backup_tli ;
103109
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 );
105112elog (LOG ,"latest full backup timeline ID = %u" ,backup_tli );
106113elog (LOG ,"target timeline ID = %u" ,target_tli );
107114
@@ -216,7 +223,7 @@ do_restore(time_t backup_id,
216223
217224/* create recovery.conf */
218225if (!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 );
220227
221228/* release catalog lock */
222229catalog_unlock ();
@@ -454,7 +461,8 @@ restore_files(void *arg)
454461}
455462
456463static void
457- create_recovery_conf (const char * target_time ,
464+ create_recovery_conf (time_t backup_id ,
465+ const char * target_time ,
458466const char * target_xid ,
459467const char * target_inclusive ,
460468TimeLineID target_tli )
@@ -484,8 +492,11 @@ create_recovery_conf(const char *target_time,
484492fprintf (fp ,"recovery_target_time = '%s'\n" ,target_time );
485493else if (target_xid )
486494fprintf (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+ }
489500
490501if (target_inclusive )
491502fprintf (fp ,"recovery_target_inclusive = '%s'\n" ,target_inclusive );
@@ -797,3 +808,67 @@ checkIfCreateRecoveryConf(const char *target_time,
797808return rt ;
798809
799810}
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+ }