2
2
*
3
3
* backup.c: backup DB cluster, archived WAL, serverlog.
4
4
*
5
- * Copyright (c) 2009-2011 , NIPPON TELEGRAPH AND TELEPHONE CORPORATION
5
+ * Copyright (c) 2009-2013 , NIPPON TELEGRAPH AND TELEPHONE CORPORATION
6
6
*
7
7
*-------------------------------------------------------------------------
8
8
*/
@@ -33,20 +33,22 @@ static void delete_old_files(const char *root, parray *files, int keep_files,
33
33
int keep_days ,int server_version ,bool is_arclog );
34
34
static void backup_files (const char * from_root ,const char * to_root ,
35
35
parray * 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 );
37
37
static parray * do_backup_arclog (parray * backup_list );
38
38
static 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 );
39
41
static void confirm_block_size (const char * name ,int blcksz );
40
42
static void pg_start_backup (const char * label ,bool smooth ,pgBackup * backup );
41
43
static void pg_stop_backup (pgBackup * backup );
42
44
static void pg_switch_xlog (pgBackup * backup );
43
45
static void get_lsn (PGresult * res ,TimeLineID * timeline ,XLogRecPtr * lsn );
44
46
static void get_xid (PGresult * res ,uint32 * xid );
47
+ static bool execute_restartpoint (pgBackupOption bkupopt );
45
48
46
49
static void delete_arclog_link (void );
47
50
static void delete_online_wal_backup (void );
48
51
49
- static bool fileExists (const char * path );
50
52
static bool dirExists (const char * path );
51
53
52
54
static void execute_freeze (void );
@@ -65,7 +67,7 @@ static void create_file_list(parray *files, const char *root, const char *prefix
65
67
* Take a backup of database.
66
68
*/
67
69
static parray *
68
- do_backup_database (parray * backup_list ,bool smooth_checkpoint )
70
+ do_backup_database (parray * backup_list ,pgBackupOption bkupopt )
69
71
{
70
72
int i ;
71
73
parray * files ;/* backup file list from non-snapshot */
@@ -75,6 +77,11 @@ do_backup_database(parray *backup_list, bool smooth_checkpoint)
75
77
char label [1024 ];
76
78
XLogRecPtr * lsn = NULL ;
77
79
char 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 ;
78
85
79
86
if (!HAVE_DATABASE (& current )) {
80
87
/* 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)
112
119
snprintf (path ,lengthof (path ),"%s/backup_label" ,pgdata );
113
120
make_native_path (path );
114
121
if (!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
+ {
120
141
pg_stop_backup (NULL );
121
- elog (ERROR_SYSTEM ,_ ("backup_label does notexist in PGDATA ." ));
142
+ elog (ERROR_SYSTEM ,_ ("could notspecified standby host or port ." ));
122
143
}
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;
123
150
}
124
151
125
152
/*
@@ -411,6 +438,11 @@ do_backup_database(parray *backup_list, bool smooth_checkpoint)
411
438
/* notify end of backup */
412
439
pg_stop_backup (& current );
413
440
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
+
414
446
/* create file list */
415
447
create_file_list (files ,pgdata ,NULL , false);
416
448
}
@@ -437,6 +469,25 @@ do_backup_database(parray *backup_list, bool smooth_checkpoint)
437
469
return files ;
438
470
}
439
471
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
+
440
491
/*
441
492
* backup archived WAL incrementally.
442
493
*/
@@ -653,13 +704,7 @@ do_backup_srvlog(parray *backup_list)
653
704
}
654
705
655
706
int
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 )
663
708
{
664
709
parray * backup_list ;
665
710
parray * files_database ;
@@ -668,6 +713,14 @@ do_backup(bool smooth_checkpoint,
668
713
int server_version ;
669
714
int ret ;
670
715
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
+
671
724
/* PGDATA and BACKUP_MODE are always required */
672
725
if (pgdata == NULL )
673
726
elog (ERROR_ARGS ,_ ("required parameter not specified: PGDATA (-D, --pgdata)" ));
@@ -731,8 +784,9 @@ do_backup(bool smooth_checkpoint,
731
784
current .write_bytes = 0 ;/* write_bytes is valid always */
732
785
current .block_size = BLCKSZ ;
733
786
current .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;
736
790
737
791
/* create backup directory and backup.ini */
738
792
if (!check )
@@ -754,7 +808,7 @@ current.recovery_time = (time_t) 0;
754
808
pgut_atexit_push (backup_cleanup ,NULL );
755
809
756
810
/* backup data */
757
- files_database = do_backup_database (backup_list ,smooth_checkpoint );
811
+ files_database = do_backup_database (backup_list ,bkupopt );
758
812
759
813
/* backup archived WAL */
760
814
files_arclog = do_backup_arclog (backup_list );
@@ -822,6 +876,80 @@ current.recovery_time = (time_t) 0;
822
876
return 0 ;
823
877
}
824
878
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
+
825
953
/*
826
954
* get server version and confirm block sizes.
827
955
*/
@@ -1030,7 +1158,7 @@ get_xid(PGresult *res, uint32 *xid)
1030
1158
/*
1031
1159
* Return true if the path is a existing regular file.
1032
1160
*/
1033
- static bool
1161
+ bool
1034
1162
fileExists (const char * path )
1035
1163
{
1036
1164
struct stat buf ;