22 *
33 * backup.c: backup DB cluster, archived WAL, serverlog.
44 *
5- * Copyright (c) 2009-2011 , NIPPON TELEGRAPH AND TELEPHONE CORPORATION
5+ * Copyright (c) 2009-2013 , NIPPON TELEGRAPH AND TELEPHONE CORPORATION
66 *
77 *-------------------------------------------------------------------------
88 */
@@ -33,20 +33,22 @@ static void delete_old_files(const char *root, parray *files, int keep_files,
3333int keep_days ,int server_version ,bool is_arclog );
3434static void backup_files (const char * from_root ,const char * to_root ,
3535parray * files ,parray * prev_files ,const XLogRecPtr * lsn ,bool compress ,const char * prefix );
36- static parray * do_backup_database (parray * backup_list ,bool smooth_checkpoint );
36+ static parray * do_backup_database (parray * backup_list ,pgBackupOption bkupopt );
3737static parray * do_backup_arclog (parray * backup_list );
3838static parray * do_backup_srvlog (parray * backup_list );
39+ static void remove_stopinfo_from_backup_label (char * history_file ,char * bkup_label );
40+ static void make_backup_label (parray * backup_list );
3941static void confirm_block_size (const char * name ,int blcksz );
4042static void pg_start_backup (const char * label ,bool smooth ,pgBackup * backup );
4143static void pg_stop_backup (pgBackup * backup );
4244static void pg_switch_xlog (pgBackup * backup );
4345static void get_lsn (PGresult * res ,TimeLineID * timeline ,XLogRecPtr * lsn );
4446static void get_xid (PGresult * res ,uint32 * xid );
47+ static bool execute_restartpoint (pgBackupOption bkupopt );
4548
4649static void delete_arclog_link (void );
4750static void delete_online_wal_backup (void );
4851
49- static bool fileExists (const char * path );
5052static bool dirExists (const char * path );
5153
5254static void execute_freeze (void );
@@ -65,7 +67,7 @@ static void create_file_list(parray *files, const char *root, const char *prefix
6567 * Take a backup of database.
6668 */
6769static parray *
68- do_backup_database (parray * backup_list ,bool smooth_checkpoint )
70+ do_backup_database (parray * backup_list ,pgBackupOption bkupopt )
6971{
7072int i ;
7173parray * files ;/* backup file list from non-snapshot */
@@ -75,6 +77,11 @@ do_backup_database(parray *backup_list, bool smooth_checkpoint)
7577char label [1024 ];
7678XLogRecPtr * lsn = NULL ;
7779char prev_file_txt [MAXPGPATH ];/* path of the previous backup list file */
80+ bool has_backup_label = true;/* flag if backup_label is there */
81+ bool has_recovery_conf = false;/* flag if recovery.conf is there */
82+
83+ /* repack the options */
84+ bool smooth_checkpoint = bkupopt .smooth_checkpoint ;
7885
7986if (!HAVE_DATABASE (& current )) {
8087/* check if arclog backup. if arclog backup and no suitable full backup, */
@@ -112,14 +119,34 @@ do_backup_database(parray *backup_list, bool smooth_checkpoint)
112119snprintf (path ,lengthof (path ),"%s/backup_label" ,pgdata );
113120make_native_path (path );
114121if (!fileExists (path )) {
115- snprintf (path ,lengthof (path ),"%s/recovery.conf" ,pgdata );
116- make_native_path (path );
117- if (!fileExists (path )) {
118- if (verbose )
119- printf (_ ("backup_label does not exist, stop backup\n" ));
122+ has_backup_label = false;
123+ }
124+ snprintf (path ,lengthof (path ),"%s/recovery.conf" ,pgdata );
125+ make_native_path (path );
126+ if (fileExists (path )) {
127+ has_recovery_conf = true;
128+ }
129+ if (!has_backup_label && !has_recovery_conf )
130+ {
131+ if (verbose )
132+ printf (_ ("backup_label does not exist, stop backup\n" ));
133+ pg_stop_backup (NULL );
134+ elog (ERROR_SYSTEM ,_ ("backup_label does not exist in PGDATA." ));
135+ }
136+ else if (has_recovery_conf )
137+ {
138+
139+ if (!bkupopt .standby_host || !bkupopt .standby_port )
140+ {
120141pg_stop_backup (NULL );
121- elog (ERROR_SYSTEM ,_ ("backup_label does notexist in PGDATA ." ));
142+ elog (ERROR_SYSTEM ,_ ("could notspecified standby host or port ." ));
122143}
144+ if (!execute_restartpoint (bkupopt ))
145+ {
146+ pg_stop_backup (NULL );
147+ elog (ERROR_SYSTEM ,_ ("could not execute restartpoint." ));
148+ }
149+ current .is_from_standby = true;
123150}
124151
125152/*
@@ -411,6 +438,11 @@ do_backup_database(parray *backup_list, bool smooth_checkpoint)
411438/* notify end of backup */
412439pg_stop_backup (& current );
413440
441+ /* if backup is from standby, making backup_label from*/
442+ /* backup.history file.*/
443+ if (current .is_from_standby )
444+ make_backup_label (files );
445+
414446/* create file list */
415447create_file_list (files ,pgdata ,NULL , false);
416448}
@@ -437,6 +469,25 @@ do_backup_database(parray *backup_list, bool smooth_checkpoint)
437469return files ;
438470}
439471
472+ static bool
473+ execute_restartpoint (pgBackupOption bkupopt )
474+ {
475+ PGconn * sby_conn = NULL ;
476+ const char * tmp_host ;
477+ const char * tmp_port ;
478+ tmp_host = pgut_get_host ();
479+ tmp_port = pgut_get_port ();
480+ pgut_set_host (bkupopt .standby_host );
481+ pgut_set_port (bkupopt .standby_port );
482+ sby_conn = reconnect_elevel (ERROR_PG_CONNECT );
483+ if (!sby_conn )
484+ return false;
485+ command ("CHECKPOINT" ,0 ,NULL );
486+ pgut_set_host (tmp_host );
487+ pgut_set_port (tmp_port );
488+ return true;
489+ }
490+
440491/*
441492 * backup archived WAL incrementally.
442493 */
@@ -653,13 +704,7 @@ do_backup_srvlog(parray *backup_list)
653704}
654705
655706int
656- do_backup (bool smooth_checkpoint ,
657- int keep_arclog_files ,
658- int keep_arclog_days ,
659- int keep_srvlog_files ,
660- int keep_srvlog_days ,
661- int keep_data_generations ,
662- int keep_data_days )
707+ do_backup (pgBackupOption bkupopt )
663708{
664709parray * backup_list ;
665710parray * files_database ;
@@ -668,6 +713,14 @@ do_backup(bool smooth_checkpoint,
668713int server_version ;
669714int ret ;
670715
716+ /* repack the necesary options */
717+ int keep_arclog_files = bkupopt .keep_arclog_files ;
718+ int keep_arclog_days = bkupopt .keep_arclog_days ;
719+ int keep_srvlog_files = bkupopt .keep_srvlog_files ;
720+ int keep_srvlog_days = bkupopt .keep_srvlog_days ;
721+ int keep_data_generations = bkupopt .keep_data_generations ;
722+ int keep_data_days = bkupopt .keep_data_days ;
723+
671724/* PGDATA and BACKUP_MODE are always required */
672725if (pgdata == NULL )
673726elog (ERROR_ARGS ,_ ("required parameter not specified: PGDATA (-D, --pgdata)" ));
@@ -731,8 +784,9 @@ do_backup(bool smooth_checkpoint,
731784current .write_bytes = 0 ;/* write_bytes is valid always */
732785current .block_size = BLCKSZ ;
733786current .wal_block_size = XLOG_BLCKSZ ;
734- current .recovery_xid = 0 ;
735- current .recovery_time = (time_t )0 ;
787+ current .recovery_xid = 0 ;
788+ current .recovery_time = (time_t )0 ;
789+ current .is_from_standby = false;
736790
737791/* create backup directory and backup.ini */
738792if (!check )
@@ -754,7 +808,7 @@ current.recovery_time = (time_t) 0;
754808pgut_atexit_push (backup_cleanup ,NULL );
755809
756810/* backup data */
757- files_database = do_backup_database (backup_list ,smooth_checkpoint );
811+ files_database = do_backup_database (backup_list ,bkupopt );
758812
759813/* backup archived WAL */
760814files_arclog = do_backup_arclog (backup_list );
@@ -822,6 +876,80 @@ current.recovery_time = (time_t) 0;
822876return 0 ;
823877}
824878
879+ void
880+ remove_stopinfo_from_backup_label (char * history_file ,char * bkup_label )
881+ {
882+ FILE * read ;
883+ FILE * write ;
884+ char buf [MAXPGPATH * 2 ];
885+
886+ if ((read = fopen (history_file ,"r" ))== NULL )
887+ elog (ERROR_SYSTEM ,
888+ _ ("can't open backup history file for standby backup." ));
889+ if ((write = fopen (bkup_label ,"w" ))== NULL )
890+ elog (ERROR_SYSTEM ,
891+ _ ("can't open backup_label file for standby backup." ));
892+ while (fgets (buf ,lengthof (buf ),read )!= NULL )
893+ {
894+ if (strstr (buf ,"STOP" )- buf == 0 )
895+ continue ;
896+ fputs (buf ,write );
897+ }
898+ fclose (write );
899+ fclose (read );
900+ }
901+
902+ /*
903+ * creating backup_label from backup.history for standby backup.
904+ */
905+ void
906+ make_backup_label (parray * backup_list )
907+ {
908+ char dest_path [MAXPGPATH ];
909+ char src_bkup_history_file [MAXPGPATH ];
910+ char dst_bkup_label_file [MAXPGPATH ];
911+ char original_bkup_label_file [MAXPGPATH ];
912+ parray * bkuped_arc_files = NULL ;
913+ int i ;
914+
915+ pgBackupGetPath (& current ,dest_path ,lengthof (dest_path ),DATABASE_DIR );
916+ bkuped_arc_files = parray_new ();
917+ dir_list_file (bkuped_arc_files ,arclog_path ,NULL , true, false);
918+
919+ for (i = parray_num (bkuped_arc_files )- 1 ;i >=0 ;i -- )
920+ {
921+ char * current_arc_fname ;
922+ pgFile * current_arc_file ;
923+
924+ current_arc_file = (pgFile * )parray_get (bkuped_arc_files ,i );
925+ current_arc_fname = last_dir_separator (current_arc_file -> path )+ 1 ;
926+
927+ if (strlen (current_arc_fname ) <=24 )continue ;
928+
929+ copy_file (arclog_path ,dest_path ,current_arc_file ,NO_COMPRESSION );
930+ join_path_components (src_bkup_history_file ,dest_path ,current_arc_fname );
931+ join_path_components (dst_bkup_label_file ,dest_path ,PG_BACKUP_LABEL_FILE );
932+ join_path_components (original_bkup_label_file ,pgdata ,PG_BACKUP_LABEL_FILE );
933+ remove_stopinfo_from_backup_label (src_bkup_history_file ,dst_bkup_label_file );
934+
935+ dir_list_file (backup_list ,dst_bkup_label_file ,NULL , false, true);
936+ for (i = 0 ;i < parray_num (backup_list );i ++ )
937+ {
938+ pgFile * file = (pgFile * )parray_get (backup_list ,i );
939+ if (strcmp (file -> path ,dst_bkup_label_file )== 0 )
940+ {
941+ struct stat st ;
942+ stat (dst_bkup_label_file ,& st );
943+ file -> write_size = st .st_size ;
944+ file -> crc = pgFileGetCRC (file );
945+ strcpy (file -> path ,original_bkup_label_file );
946+ }
947+ }
948+ parray_qsort (backup_list ,pgFileComparePath );
949+ break ;
950+ }
951+ }
952+
825953/*
826954 * get server version and confirm block sizes.
827955 */
@@ -1030,7 +1158,7 @@ get_xid(PGresult *res, uint32 *xid)
10301158/*
10311159 * Return true if the path is a existing regular file.
10321160 */
1033- static bool
1161+ bool
10341162fileExists (const char * path )
10351163{
10361164struct stat buf ;