22 *
33 * backup.c: backup DB cluster, archived WAL, serverlog.
44 *
5- * Copyright (c) 2009-2010 , NIPPON TELEGRAPH AND TELEPHONE CORPORATION
5+ * Copyright (c) 2009-2011 , NIPPON TELEGRAPH AND TELEPHONE CORPORATION
66 *
77 *-------------------------------------------------------------------------
88 */
@@ -41,6 +41,7 @@ static void pg_start_backup(const char *label, bool smooth, pgBackup *backup);
4141static void pg_stop_backup (pgBackup * backup );
4242static void pg_switch_xlog (pgBackup * backup );
4343static void get_lsn (PGresult * res ,TimeLineID * timeline ,XLogRecPtr * lsn );
44+ static void get_xid (PGresult * res ,uint32 * xid );
4445
4546static void delete_arclog_link (void );
4647static void delete_online_wal_backup (void );
@@ -75,8 +76,26 @@ do_backup_database(parray *backup_list, bool smooth_checkpoint)
7576XLogRecPtr * lsn = NULL ;
7677char prev_file_txt [MAXPGPATH ];/* path of the previous backup list file */
7778
78- if (!HAVE_DATABASE (& current ))
79- return NULL ;
79+ if (!HAVE_DATABASE (& current )) {
80+ /* check if arclog backup. if arclog backup and no suitable full backup, */
81+ /* take full backup instead. */
82+ if (HAVE_ARCLOG (& current )) {
83+ pgBackup * prev_backup ;
84+
85+ /* find last completed database backup */
86+ prev_backup = catalog_get_last_data_backup (backup_list );
87+ if (prev_backup == NULL )
88+ {
89+ elog (ERROR_SYSTEM ,_ ("There is indeed a full backup but it is not validated."
90+ "So I can't take any arclog backup."
91+ "Please validate it and retry." ));
92+ ///elog(INFO, _("no previous full backup, performing a full backup instead"));
93+ ///current.backup_mode = BACKUP_MODE_FULL;
94+ }
95+ }
96+ else
97+ return NULL ;
98+ }
8099
81100elog (INFO ,_ ("database backup start" ));
82101
@@ -89,6 +108,16 @@ do_backup_database(parray *backup_list, bool smooth_checkpoint)
89108strncat (label ," with pg_rman" ,lengthof (label ));
90109pg_start_backup (label ,smooth_checkpoint ,& current );
91110
111+ /* If backup_label does not exist in $PGDATA, stop taking backup */
112+ snprintf (path ,lengthof (path ),"%s/backup_label" ,pgdata );
113+ make_native_path (path );
114+ if (!fileExists (path )) {
115+ if (verbose )
116+ printf (_ ("backup_label does not exist, stop backup\n" ));
117+ pg_stop_backup (NULL );
118+ elog (ERROR_SYSTEM ,_ ("backup_label does not exist in PGDATA." ));
119+ }
120+
92121/*
93122 * list directories and symbolic links with the physical path to make
94123 * mkdirs.sh
@@ -127,10 +156,13 @@ do_backup_database(parray *backup_list, bool smooth_checkpoint)
127156
128157/* find last completed database backup */
129158prev_backup = catalog_get_last_data_backup (backup_list );
130- if (prev_backup == NULL )
159+ if (prev_backup == NULL || prev_backup -> tli != current . tli )
131160{
132- elog (INFO ,_ ("no previous full backup, do a full backup instead" ));
133- current .backup_mode = BACKUP_MODE_FULL ;
161+ elog (ERROR_SYSTEM ,_ ("There is indeed a full backup but it is not validated."
162+ "So I can't take any incremental backup."
163+ "Please validate it and retry." ));
164+ ///elog(INFO, _("no previous full backup, performing a full backup instead"));
165+ ///current.backup_mode = BACKUP_MODE_FULL;
134166}
135167else
136168{
@@ -440,7 +472,7 @@ do_backup_arclog(parray *backup_list)
440472 */
441473prev_backup = catalog_get_last_arclog_backup (backup_list );
442474if (verbose && prev_backup == NULL )
443- printf (_ ("no previous full backup,do a full backup instead\n" ));
475+ printf (_ ("no previous full backup,performing a full backup instead\n" ));
444476
445477if (prev_backup )
446478{
@@ -564,7 +596,7 @@ do_backup_srvlog(parray *backup_list)
564596 */
565597prev_backup = catalog_get_last_srvlog_backup (backup_list );
566598if (verbose && prev_backup == NULL )
567- printf (_ ("no previous full backup,do a full backup instead\n" ));
599+ printf (_ ("no previous full backup,performing a full backup instead\n" ));
568600
569601if (prev_backup )
570602{
@@ -695,6 +727,8 @@ do_backup(bool smooth_checkpoint,
695727current .write_bytes = 0 ;/* write_bytes is valid always */
696728current .block_size = BLCKSZ ;
697729current .wal_block_size = XLOG_BLCKSZ ;
730+ current .recovery_xid = 0 ;
731+ current .recovery_time = (time_t )0 ;
698732
699733/* create backup directory and backup.ini */
700734if (!check )
@@ -708,6 +742,9 @@ do_backup(bool smooth_checkpoint,
708742
709743/* get list of backups already taken */
710744backup_list = catalog_get_backup_list (NULL );
745+ if (!backup_list ){
746+ elog (ERROR_SYSTEM ,_ ("can't process any more." ));
747+ }
711748
712749/* set the error processing function for the backup process */
713750pgut_atexit_push (backup_cleanup ,NULL );
@@ -893,6 +930,12 @@ wait_for_archive(pgBackup *backup, const char *sql)
893930elog (LOG ,"%s() wait for %s" ,__FUNCTION__ ,ready_path );
894931
895932PQclear (res );
933+
934+ res = execute (TXID_CURRENT_SQL ,0 ,NULL );
935+ if (backup != NULL ){
936+ get_xid (res ,& backup -> recovery_xid );
937+ backup -> recovery_time = time (NULL );
938+ }
896939disconnect ();
897940
898941/* wait until switched WAL is archived */
@@ -960,6 +1003,26 @@ get_lsn(PGresult *res, TimeLineID *timeline, XLogRecPtr *lsn)
9601003lsn -> xrecoff += off_upper <<24 ;
9611004}
9621005
1006+ /*
1007+ * Get XID from result of txid_current() after pg_stop_backup().
1008+ */
1009+ static void
1010+ get_xid (PGresult * res ,uint32 * xid )
1011+ {
1012+ if (res == NULL || PQntuples (res )!= 1 || PQnfields (res )!= 1 )
1013+ elog (ERROR_PG_COMMAND ,
1014+ _ ("result of txid_current() is invalid: %s" ),
1015+ PQerrorMessage (connection ));
1016+
1017+ if (sscanf (PQgetvalue (res ,0 ,0 ),"%u" ,xid )!= 1 )
1018+ {
1019+ elog (ERROR_PG_COMMAND ,
1020+ _ ("result of txid_current() is invalid: %s" ),
1021+ PQerrorMessage (connection ));
1022+ }
1023+ elog (LOG ,"%s():%s" ,__FUNCTION__ ,PQgetvalue (res ,0 ,0 ));
1024+ }
1025+
9631026/*
9641027 * Return true if the path is a existing regular file.
9651028 */
@@ -1055,6 +1118,11 @@ backup_files(const char *from_root,
10551118
10561119pgFile * file = (pgFile * )parray_get (files ,i );
10571120
1121+ /* If current time is rewinded, abort this backup. */
1122+ if (tv .tv_sec < file -> mtime ){
1123+ elog (ERROR_SYSTEM ,_ ("current time may be rewound. Please retry with full backup mode." ));
1124+ }
1125+
10581126/* check for interrupt */
10591127if (interrupted )
10601128elog (ERROR_INTERRUPTED ,_ ("interrupted during backup" ));
@@ -1101,8 +1169,9 @@ backup_files(const char *from_root,
11011169char dirpath [MAXPGPATH ];
11021170
11031171join_path_components (dirpath ,to_root ,JoinPathEnd (file -> path ,from_root ));
1104- if (!check )
1172+ if (!check ){
11051173dir_create_dir (dirpath ,DIR_PERMISSION );
1174+ }
11061175if (verbose )
11071176printf (_ ("directory\n" ));
11081177}
@@ -1143,7 +1212,7 @@ backup_files(const char *from_root,
11431212prev_file = * p ;
11441213}
11451214
1146- if (prev_file && prev_file -> mtime > =file -> mtime )
1215+ if (prev_file && prev_file -> mtime = =file -> mtime )
11471216{
11481217/* record as skipped file in file_xxx.txt */
11491218file -> write_size = BYTES_INVALID ;
@@ -1158,7 +1227,8 @@ backup_files(const char *from_root,
11581227 * file should contain all modifications at the clock of mtime.
11591228 * timer resolution of ext3 file system is one second.
11601229 */
1161- if (tv .tv_sec <=file -> mtime )
1230+
1231+ if (tv .tv_sec == file -> mtime )
11621232{
11631233/* update time and recheck */
11641234gettimeofday (& tv ,NULL );