@@ -80,7 +80,7 @@ static void backup_cleanup(bool fatal, void *userdata);
80
80
81
81
static void * backup_files (void * arg );
82
82
83
- static void do_backup_instance (PGconn * backup_conn , PGNodeInfo * nodeInfo );
83
+ static void do_backup_instance (PGconn * backup_conn , PGNodeInfo * nodeInfo , bool no_sync );
84
84
85
85
static void pg_start_backup (const char * label , bool smooth , pgBackup * backup ,
86
86
PGNodeInfo * nodeInfo , PGconn * backup_conn , PGconn * master_conn );
@@ -129,7 +129,7 @@ backup_stopbackup_callback(bool fatal, void *userdata)
129
129
* Move files from 'pgdata' to a subdirectory in 'backup_path'.
130
130
*/
131
131
static void
132
- do_backup_instance (PGconn * backup_conn , PGNodeInfo * nodeInfo )
132
+ do_backup_instance (PGconn * backup_conn , PGNodeInfo * nodeInfo , bool no_sync )
133
133
{
134
134
int i ;
135
135
char database_path [MAXPGPATH ];
@@ -155,6 +155,7 @@ do_backup_instance(PGconn *backup_conn, PGNodeInfo *nodeInfo)
155
155
156
156
/* for fancy reporting */
157
157
time_t start_time , end_time ;
158
+ char pretty_time [20 ];
158
159
char pretty_bytes [20 ];
159
160
160
161
elog (LOG , "Database backup start" );
@@ -452,7 +453,7 @@ do_backup_instance(PGconn *backup_conn, PGNodeInfo *nodeInfo)
452
453
parray_qsort (backup_files_list , pgFileCompareSize );
453
454
/* Sort the array for binary search */
454
455
if (prev_backup_filelist )
455
- parray_qsort (prev_backup_filelist , pgFileComparePathWithExternal );
456
+ parray_qsort (prev_backup_filelist , pgFileCompareRelPathWithExternal );
456
457
457
458
/* write initial backup_content.control file and update backup.control */
458
459
write_backup_filelist (& current , backup_files_list ,
@@ -485,6 +486,7 @@ do_backup_instance(PGconn *backup_conn, PGNodeInfo *nodeInfo)
485
486
/* Run threads */
486
487
thread_interrupted = false;
487
488
elog (INFO , "Start transferring data files" );
489
+ time (& start_time );
488
490
for (i = 0 ; i < num_threads ; i ++ )
489
491
{
490
492
backup_files_arg * arg = & (threads_args [i ]);
@@ -500,10 +502,16 @@ do_backup_instance(PGconn *backup_conn, PGNodeInfo *nodeInfo)
500
502
if (threads_args [i ].ret == 1 )
501
503
backup_isok = false;
502
504
}
505
+
506
+ time (& end_time );
507
+ pretty_time_interval (difftime (end_time , start_time ),
508
+ pretty_time , lengthof (pretty_time ));
503
509
if (backup_isok )
504
- elog (INFO , "Data files are transferred" );
510
+ elog (INFO , "Data files are transferred, time elapsed: %s" ,
511
+ pretty_time );
505
512
else
506
- elog (ERROR , "Data files transferring failed" );
513
+ elog (ERROR , "Data files transferring failed, time elapsed: %s" ,
514
+ pretty_time );
507
515
508
516
/* Remove disappeared during backup files from backup_list */
509
517
for (i = 0 ; i < parray_num (backup_files_list ); i ++ )
@@ -589,7 +597,8 @@ do_backup_instance(PGconn *backup_conn, PGNodeInfo *nodeInfo)
589
597
{
590
598
char * ptr = file -> path ;
591
599
592
- file -> path = pstrdup (GetRelativePath (ptr , database_path ));
600
+ file -> path = pgut_strdup (GetRelativePath (ptr , database_path ));
601
+ file -> rel_path = pgut_strdup (file -> path );
593
602
free (ptr );
594
603
}
595
604
}
@@ -613,6 +622,48 @@ do_backup_instance(PGconn *backup_conn, PGNodeInfo *nodeInfo)
613
622
/* update backup control file to update size info */
614
623
write_backup (& current );
615
624
625
+ /* Sync all copied files unless '--no-sync' flag is used */
626
+ if (no_sync )
627
+ elog (WARNING , "Backup files are not synced to disk" );
628
+ else
629
+ {
630
+ elog (INFO , "Syncing backup files to disk" );
631
+ time (& start_time );
632
+
633
+ for (i = 0 ; i < parray_num (backup_files_list ); i ++ )
634
+ {
635
+ char to_fullpath [MAXPGPATH ];
636
+ pgFile * file = (pgFile * ) parray_get (backup_files_list , i );
637
+
638
+ /* TODO: sync directory ? */
639
+ if (S_ISDIR (file -> mode ))
640
+ continue ;
641
+
642
+ if (file -> write_size <= 0 )
643
+ continue ;
644
+
645
+ /* construct fullpath */
646
+ if (file -> external_dir_num == 0 )
647
+ join_path_components (to_fullpath , database_path , file -> rel_path );
648
+ else
649
+ {
650
+ char external_dst [MAXPGPATH ];
651
+
652
+ makeExternalDirPathByNum (external_dst , external_prefix ,
653
+ file -> external_dir_num );
654
+ join_path_components (to_fullpath , external_dst , file -> rel_path );
655
+ }
656
+
657
+ if (fio_sync (to_fullpath , FIO_BACKUP_HOST ) != 0 )
658
+ elog (ERROR , "Failed to sync file \"%s\": %s" , to_fullpath , strerror (errno ));
659
+ }
660
+
661
+ time (& end_time );
662
+ pretty_time_interval (difftime (end_time , start_time ),
663
+ pretty_time , lengthof (pretty_time ));
664
+ elog (INFO , "Backup files are synced, time elapsed: %s" , pretty_time );
665
+ }
666
+
616
667
/* clean external directories list */
617
668
if (external_dirs )
618
669
free_dir_list (external_dirs );
@@ -696,7 +747,7 @@ pgdata_basic_setup(ConnectionOptions conn_opt, PGNodeInfo *nodeInfo)
696
747
*/
697
748
int
698
749
do_backup (time_t start_time , bool no_validate ,
699
- pgSetBackupParams * set_backup_params )
750
+ pgSetBackupParams * set_backup_params , bool no_sync )
700
751
{
701
752
PGconn * backup_conn = NULL ;
702
753
PGNodeInfo nodeInfo ;
@@ -795,7 +846,7 @@ do_backup(time_t start_time, bool no_validate,
795
846
elog (ERROR , "Options for connection to master must be provided to perform backup from replica" );
796
847
797
848
/* backup data */
798
- do_backup_instance (backup_conn , & nodeInfo );
849
+ do_backup_instance (backup_conn , & nodeInfo , no_sync );
799
850
pgut_atexit_pop (backup_cleanup , NULL );
800
851
801
852
/* compute size of wal files of this backup stored in the archive */
@@ -1928,18 +1979,24 @@ static void *
1928
1979
backup_files (void * arg )
1929
1980
{
1930
1981
int i ;
1931
- backup_files_arg * arguments = ( backup_files_arg * ) arg ;
1932
- int n_backup_files_list = parray_num ( arguments -> files_list ) ;
1982
+ char from_fullpath [ MAXPGPATH ] ;
1983
+ char to_fullpath [ MAXPGPATH ] ;
1933
1984
static time_t prev_time ;
1934
1985
1986
+ backup_files_arg * arguments = (backup_files_arg * ) arg ;
1987
+ int n_backup_files_list = parray_num (arguments -> files_list );
1988
+
1935
1989
prev_time = current .start_time ;
1936
1990
1937
1991
/* backup a file */
1938
1992
for (i = 0 ; i < n_backup_files_list ; i ++ )
1939
1993
{
1940
- int ret ;
1941
- struct stat buf ;
1942
- pgFile * file = (pgFile * ) parray_get (arguments -> files_list , i );
1994
+ pgFile * file = (pgFile * ) parray_get (arguments -> files_list , i );
1995
+ pgFile * prev_file = NULL ;
1996
+
1997
+ /* We have already copied all directories */
1998
+ if (S_ISDIR (file -> mode ))
1999
+ continue ;
1943
2000
1944
2001
if (arguments -> thread_num == 1 )
1945
2002
{
@@ -1957,147 +2014,91 @@ backup_files(void *arg)
1957
2014
1958
2015
if (!pg_atomic_test_set_flag (& file -> lock ))
1959
2016
continue ;
1960
- elog (VERBOSE , "Copying file: \"%s\"" , file -> path );
1961
2017
1962
2018
/* check for interrupt */
1963
2019
if (interrupted || thread_interrupted )
1964
2020
elog (ERROR , "interrupted during backup" );
1965
2021
1966
2022
if (progress )
1967
2023
elog (INFO , "Progress: (%d/%d). Process file \"%s\"" ,
1968
- i + 1 , n_backup_files_list , file -> path );
2024
+ i + 1 , n_backup_files_list , file -> rel_path );
1969
2025
1970
- /* stat file to check its current state */
1971
- ret = fio_stat (file -> path , & buf , true, FIO_DB_HOST );
1972
- if (ret == -1 )
2026
+ /* Handle zero sized files */
2027
+ if (file -> size == 0 )
1973
2028
{
1974
- if (errno == ENOENT )
1975
- {
1976
- /*
1977
- * If file is not found, this is not en error.
1978
- * It could have been deleted by concurrent postgres transaction.
1979
- */
1980
- file -> write_size = FILE_NOT_FOUND ;
1981
- elog (LOG , "File \"%s\" is not found" , file -> path );
1982
- continue ;
1983
- }
1984
- else
1985
- {
1986
- elog (ERROR ,
1987
- "can't stat file to backup \"%s\": %s" ,
1988
- file -> path , strerror (errno ));
1989
- }
1990
- }
1991
-
1992
- /* We have already copied all directories */
1993
- if (S_ISDIR (buf .st_mode ))
2029
+ file -> write_size = 0 ;
1994
2030
continue ;
2031
+ }
1995
2032
1996
- if (S_ISREG (buf .st_mode ))
2033
+ /* construct destination filepath */
2034
+ if (file -> external_dir_num == 0 )
2035
+ {
2036
+ join_path_components (from_fullpath , arguments -> from_root , file -> rel_path );
2037
+ join_path_components (to_fullpath , arguments -> to_root , file -> rel_path );
2038
+ }
2039
+ else
1997
2040
{
1998
- pgFile * * prev_file = NULL ;
1999
- char * external_path = NULL ;
2041
+ char external_dst [MAXPGPATH ];
2042
+ char * external_path = parray_get (arguments -> external_dirs ,
2043
+ file -> external_dir_num - 1 );
2000
2044
2001
- if ( file -> external_dir_num )
2002
- external_path = parray_get ( arguments -> external_dirs ,
2003
- file -> external_dir_num - 1 );
2045
+ makeExternalDirPathByNum ( external_dst ,
2046
+ arguments -> external_prefix ,
2047
+ file -> external_dir_num );
2004
2048
2005
- /* Check that file exist in previous backup */
2006
- if (current .backup_mode != BACKUP_MODE_FULL )
2007
- {
2008
- char * relative ;
2009
- pgFile key ;
2010
-
2011
- relative = GetRelativePath (file -> path , file -> external_dir_num ?
2012
- external_path : arguments -> from_root );
2013
- key .path = relative ;
2014
- key .external_dir_num = file -> external_dir_num ;
2015
-
2016
- prev_file = (pgFile * * ) parray_bsearch (arguments -> prev_filelist ,
2017
- & key , pgFileComparePathWithExternal );
2018
- if (prev_file )
2019
- /* File exists in previous backup */
2020
- file -> exists_in_prev = true;
2021
- }
2049
+ join_path_components (to_fullpath , external_dst , file -> rel_path );
2050
+ join_path_components (from_fullpath , external_path , file -> rel_path );
2051
+ }
2022
2052
2023
- /* copy the file into backup */
2024
- if (file -> is_datafile && !file -> is_cfs )
2025
- {
2026
- char to_path [MAXPGPATH ];
2027
-
2028
- join_path_components (to_path , arguments -> to_root ,
2029
- file -> path + strlen (arguments -> from_root ) + 1 );
2030
-
2031
- if (current .backup_mode != BACKUP_MODE_FULL )
2032
- file -> n_blocks = file -> size /BLCKSZ ;
2033
-
2034
- /* backup block by block if datafile AND not compressed by cfs*/
2035
- if (!backup_data_file (arguments , to_path , file ,
2036
- arguments -> prev_start_lsn ,
2037
- current .backup_mode ,
2038
- instance_config .compress_alg ,
2039
- instance_config .compress_level ,
2040
- arguments -> nodeInfo -> checksum_version ,
2041
- arguments -> nodeInfo -> ptrack_version_num ,
2042
- arguments -> nodeInfo -> ptrack_schema ,
2043
- true))
2044
- {
2045
- /* disappeared file not to be confused with 'not changed' */
2046
- if (file -> write_size != FILE_NOT_FOUND )
2047
- file -> write_size = BYTES_INVALID ;
2048
- elog (VERBOSE , "File \"%s\" was not copied to backup" , file -> path );
2049
- continue ;
2050
- }
2051
- }
2052
- else if (!file -> external_dir_num &&
2053
- strcmp (file -> name , "pg_control" ) == 0 )
2054
- copy_pgcontrol_file (arguments -> from_root , FIO_DB_HOST ,
2055
- arguments -> to_root , FIO_BACKUP_HOST ,
2056
- file );
2057
- else
2058
- {
2059
- const char * dst ;
2060
- bool skip = false;
2061
- char external_dst [MAXPGPATH ];
2053
+ /* Encountered some strange beast */
2054
+ if (!S_ISREG (file -> mode ))
2055
+ elog (WARNING , "Unexpected type %d of file \"%s\", skipping" ,
2056
+ file -> mode , from_fullpath );
2062
2057
2063
- /* If non-data file has not changed since last backup... */
2064
- if (prev_file && file -> exists_in_prev &&
2065
- buf .st_mtime < current .parent_backup )
2066
- {
2067
- file -> crc = pgFileGetCRC (file -> path , true, false,
2068
- & file -> read_size , FIO_DB_HOST );
2069
- file -> write_size = file -> read_size ;
2070
- /* ...and checksum is the same... */
2071
- if (EQ_TRADITIONAL_CRC32 (file -> crc , (* prev_file )-> crc ))
2072
- skip = true; /* ...skip copying file. */
2073
- }
2074
- /* Set file paths */
2075
- if (file -> external_dir_num )
2076
- {
2077
- makeExternalDirPathByNum (external_dst ,
2078
- arguments -> external_prefix ,
2079
- file -> external_dir_num );
2080
- dst = external_dst ;
2081
- }
2082
- else
2083
- dst = arguments -> to_root ;
2084
- if (skip ||
2085
- !copy_file (FIO_DB_HOST , dst , FIO_BACKUP_HOST , file , true))
2086
- {
2087
- /* disappeared file not to be confused with 'not changed' */
2088
- if (file -> write_size != FILE_NOT_FOUND )
2089
- file -> write_size = BYTES_INVALID ;
2090
- elog (VERBOSE , "File \"%s\" was not copied to backup" ,
2091
- file -> path );
2092
- continue ;
2093
- }
2058
+ /* Check that file exist in previous backup */
2059
+ if (current .backup_mode != BACKUP_MODE_FULL )
2060
+ {
2061
+ pgFile * * prev_file_tmp = NULL ;
2062
+ prev_file_tmp = (pgFile * * ) parray_bsearch (arguments -> prev_filelist ,
2063
+ file , pgFileCompareRelPathWithExternal );
2064
+ if (prev_file_tmp )
2065
+ {
2066
+ /* File exists in previous backup */
2067
+ file -> exists_in_prev = true;
2068
+ prev_file = * prev_file_tmp ;
2094
2069
}
2070
+ }
2095
2071
2096
- elog (VERBOSE , "File \"%s\". Copied " INT64_FORMAT " bytes" ,
2097
- file -> path , file -> write_size );
2072
+ /* backup file */
2073
+ if (file -> is_datafile && !file -> is_cfs )
2074
+ {
2075
+ backup_data_file (& (arguments -> conn_arg ), file , from_fullpath , to_fullpath ,
2076
+ arguments -> prev_start_lsn ,
2077
+ current .backup_mode ,
2078
+ instance_config .compress_alg ,
2079
+ instance_config .compress_level ,
2080
+ arguments -> nodeInfo -> checksum_version ,
2081
+ arguments -> nodeInfo -> ptrack_version_num ,
2082
+ arguments -> nodeInfo -> ptrack_schema ,
2083
+ true);
2098
2084
}
2099
2085
else
2100
- elog (WARNING , "unexpected file type %d" , buf .st_mode );
2086
+ {
2087
+ backup_non_data_file (file , prev_file , from_fullpath , to_fullpath ,
2088
+ current .backup_mode , current .parent_backup , true);
2089
+ }
2090
+
2091
+ if (file -> write_size == FILE_NOT_FOUND )
2092
+ continue ;
2093
+
2094
+ if (file -> write_size == BYTES_INVALID )
2095
+ {
2096
+ elog (VERBOSE , "Skipping the unchanged file: \"%s\"" , from_fullpath );
2097
+ continue ;
2098
+ }
2099
+
2100
+ elog (VERBOSE , "File \"%s\". Copied " INT64_FORMAT " bytes" ,
2101
+ from_fullpath , file -> write_size );
2101
2102
}
2102
2103
2103
2104
/* ssh connection to longer needed */
0 commit comments