1717#include <dirent.h>
1818#include <time.h>
1919
20+ #include "catalog/pg_control.h"
2021#include "libpq/pqsignal.h"
2122#include "pgut/pgut-port.h"
2223
@@ -48,7 +49,7 @@ static void confirm_block_size(const char *name, int blcksz);
4849static void pg_start_backup (const char * label ,bool smooth ,pgBackup * backup );
4950static void pg_stop_backup (pgBackup * backup );
5051static void pg_switch_xlog (pgBackup * backup );
51- static void get_lsn (PGresult * res ,TimeLineID * timeline , XLogRecPtr * lsn );
52+ static void get_lsn (PGresult * res ,XLogRecPtr * lsn );
5253static void get_xid (PGresult * res ,uint32 * xid );
5354static bool execute_restartpoint (pgBackupOption bkupopt );
5455
@@ -60,6 +61,7 @@ static bool dirExists(const char *path);
6061static void add_files (parray * files ,const char * root ,bool add_root ,bool is_pgdata );
6162static int strCompare (const void * str1 ,const void * str2 );
6263static void create_file_list (parray * files ,const char * root ,const char * prefix ,bool is_append );
64+ static TimeLineID get_current_timeline (void );
6365
6466/*
6567 * Take a backup of database.
@@ -108,6 +110,13 @@ do_backup_database(parray *backup_list, pgBackupOption bkupopt)
108110current .total_data_bytes = 0 ;
109111current .read_data_bytes = 0 ;
110112
113+ /*
114+ * Obtain current timeline by scanning control file, theh LSN
115+ * obtained at output of pg_start_backup or pg_stop_backup does
116+ * not contain this information.
117+ */
118+ current .tli = get_current_timeline ();
119+
111120/* notify start of backup to PostgreSQL server */
112121time2iso (label ,lengthof (label ),current .start_time );
113122strncat (label ," with pg_rman" ,lengthof (label ));
@@ -492,8 +501,8 @@ do_backup_arclog(parray *backup_list)
492501pg_switch_xlog (& current );
493502
494503/*
495- * To take incremental backup, the file list of the last completed database
496- * backup is needed.
504+ * To take incremental backup, the file list of the last completed
505+ *database backup is needed.
497506 */
498507prev_backup = catalog_get_last_arclog_backup (backup_list );
499508if (verbose && prev_backup == NULL )
@@ -985,10 +994,10 @@ pg_start_backup(const char *label, bool smooth, pgBackup *backup)
985994
986995/* 2nd argument is 'fast'*/
987996params [1 ]= smooth ?"false" :"true" ;
988- res = execute ("SELECT* from pg_xlogfile_name_offset( pg_start_backup($1, $2) )" ,2 ,params );
997+ res = execute ("SELECT pg_start_backup($1, $2)" ,2 ,params );
989998
990999if (backup != NULL )
991- get_lsn (res ,& backup -> tli , & backup -> start_lsn );
1000+ get_lsn (res ,& backup -> start_lsn );
9921001PQclear (res );
9931002disconnect ();
9941003}
@@ -998,22 +1007,42 @@ wait_for_archive(pgBackup *backup, const char *sql)
9981007{
9991008PGresult * res ;
10001009char ready_path [MAXPGPATH ];
1010+ char file_name [MAXFNAMELEN ];
10011011int try_count ;
1012+ XLogRecPtr lsn ;
1013+ TimeLineID tli ;
10021014
10031015reconnect ();
10041016res = execute (sql ,0 ,NULL );
1017+
1018+ /* Get LSN from execution result */
1019+ get_lsn (res ,& lsn );
1020+
1021+ /*
1022+ * Enforce TLI obtention if backup is not present as this code
1023+ * path can be taken as a callback at exit.
1024+ */
1025+ if (backup != NULL )
1026+ tli = backup -> tli ;
1027+ else
1028+ tli = get_current_timeline ();
1029+
1030+ /* Fill in fields if backup exists */
10051031if (backup != NULL )
10061032{
1007- get_lsn ( res , & backup -> tli , & backup -> stop_lsn ) ;
1033+ backup -> stop_lsn = lsn ;
10081034elog (LOG ,_ ("%s(): tli=%X lsn=%X/%08X" ),
10091035__FUNCTION__ ,backup -> tli ,
10101036 (uint32 ) (backup -> stop_lsn >>32 ),
10111037 (uint32 )backup -> stop_lsn );
10121038}
10131039
1014- /* get filename from the result of pg_xlogfile_name_offset() */
1040+ /* As well as WAL file name */
1041+ XLogFileName (file_name ,tli ,lsn );
1042+
10151043snprintf (ready_path ,lengthof (ready_path ),
1016- "%s/pg_xlog/archive_status/%s.ready" ,pgdata ,PQgetvalue (res ,0 ,0 ));
1044+ "%s/pg_xlog/archive_status/%s.ready" ,pgdata ,
1045+ file_name );
10171046elog (LOG ,"%s() wait for %s" ,__FUNCTION__ ,ready_path );
10181047
10191048PQclear (res );
@@ -1049,32 +1078,41 @@ static void
10491078pg_stop_backup (pgBackup * backup )
10501079{
10511080wait_for_archive (backup ,
1052- "SELECT * FROMpg_xlogfile_name_offset( pg_stop_backup() )" );
1081+ "SELECT * FROM pg_stop_backup()" );
10531082}
10541083
10551084/*
1056- * Force switch to a new transaction log file and update backup->tli.
1085+ * Force switch to a new transaction log file
10571086 */
10581087static void
10591088pg_switch_xlog (pgBackup * backup )
10601089{
10611090wait_for_archive (backup ,
1062- "SELECT * FROMpg_xlogfile_name_offset( pg_switch_xlog())" );
1091+ "SELECT * FROM pg_switch_xlog())" );
10631092}
10641093
10651094/*
1066- * GetTimeLineID and LSN from result ofpg_xlogfile_name_offset ().
1095+ * Get LSN from result ofpg_start_backup() or pg_stop_backup ().
10671096 */
10681097static void
1069- get_lsn (PGresult * res ,TimeLineID * timeline , XLogRecPtr * lsn )
1098+ get_lsn (PGresult * res ,XLogRecPtr * lsn )
10701099{
1071- if (res == NULL || PQntuples (res )!= 1 || PQnfields (res )!= 2 )
1100+ uint32 xlogid ;
1101+ uint32 xrecoff ;
1102+
1103+ if (res == NULL || PQntuples (res )!= 1 || PQnfields (res )!= 1 )
10721104elog (ERROR_PG_COMMAND ,
1073- _ ("result ofpg_xlogfile_name_offset() is invalid: %s" ),
1105+ _ ("result ofbackup command is invalid: %s" ),
10741106PQerrorMessage (connection ));
10751107
1076- /* Extract timeline and LSN from result of pg_stop_backup() */
1077- XLogFromFileName (PQgetvalue (res ,0 ,0 ),timeline ,lsn );
1108+ /*
1109+ * Extract timeline and LSN from results of pg_stop_backup()
1110+ * and friends.
1111+ */
1112+ XLogDataFromLSN (PQgetvalue (res ,0 ,0 ),& xlogid ,& xrecoff );
1113+
1114+ /* Calculate LSN */
1115+ * lsn = (XLogRecPtr ) ((uint64 )xlogid <<32 ) |xrecoff ;
10781116}
10791117
10801118/*
@@ -1598,3 +1636,27 @@ create_file_list(parray *files, const char *root, const char *prefix, bool is_ap
15981636fclose (fp );
15991637}
16001638}
1639+
1640+ /*
1641+ * Scan control file of given cluster at obtain the current timeline
1642+ * since last checkpoint that occurred on it.
1643+ */
1644+ static TimeLineID
1645+ get_current_timeline (void )
1646+ {
1647+ char * buffer ;
1648+ size_t size ;
1649+ ControlFileData control_file ;
1650+
1651+ /* First fetch file... */
1652+ buffer = slurpFile (pgdata ,"global/pg_control" ,& size );
1653+
1654+ /* .. Then interpret it */
1655+ if (size != PG_CONTROL_SIZE )
1656+ elog (ERROR_CORRUPTED ,"unexpected control file size %d, expected %d\n" ,
1657+ (int )size ,PG_CONTROL_SIZE );
1658+ memcpy (& control_file ,buffer ,sizeof (ControlFileData ));
1659+
1660+ /* Finally return the timeline wanted */
1661+ return control_file .checkPointCopy .ThisTimeLineID ;
1662+ }