@@ -1109,9 +1109,7 @@ backup_cleanup(bool fatal, void *userdata)
11091109}
11101110}
11111111
1112- /*
1113- * Count bytes in file
1114- */
1112+ /* Count bytes in file */
11151113static long
11161114file_size (const char * file )
11171115{
@@ -1120,8 +1118,8 @@ file_size(const char *file)
11201118
11211119if (!f )
11221120{
1123- fprintf ( stderr , _ ( "%s : could not open file \"%s\" for reading: %s\n") ,
1124- progname , file ,strerror (errno ));
1121+ elog ( ERROR , "pg_probackup : could not open file \"%s\" for reading: %s\n" ,
1122+ file ,strerror (errno ));
11251123return -1 ;
11261124}
11271125fseek (f ,0 ,SEEK_END );
@@ -1130,6 +1128,55 @@ file_size(const char *file)
11301128return r ;
11311129}
11321130
1131+ bool
1132+ backup_compressed_file_partially (pgFile * file ,void * arg ,size_t * skip_size )
1133+ {
1134+ bool result = false;
1135+ pgFile * prev_file = NULL ;
1136+ size_t current_file_size ;
1137+ backup_files_args * arguments = (backup_files_args * )arg ;
1138+
1139+ if (arguments -> prev_files )
1140+ {
1141+ pgFile * * p = (pgFile * * )parray_bsearch (arguments -> prev_files ,
1142+ file ,pgFileComparePath );
1143+ if (p )
1144+ prev_file = * p ;
1145+
1146+ elog (NOTICE ,"file '%s' generation: prev %d, now %d" ,
1147+ file -> path ,prev_file -> generation ,file -> generation );
1148+
1149+ /* If file's gc generation has changed since last backup, just copy it*/
1150+ if (prev_file
1151+ && prev_file -> generation == file -> generation )
1152+ {
1153+ current_file_size = file_size (file -> path );
1154+
1155+ elog (NOTICE ,"prev->write_size %lu, current_file_size %lu" ,
1156+ prev_file -> write_size ,current_file_size );
1157+
1158+ if (prev_file -> write_size == BYTES_INVALID )
1159+ return false;
1160+
1161+ * skip_size = prev_file -> write_size ;
1162+
1163+ if (current_file_size >=prev_file -> write_size )
1164+ {
1165+ elog (NOTICE ,"Backup part of the file. %s : %lu" ,
1166+ file -> path ,current_file_size - * skip_size );
1167+ result = true;
1168+ }
1169+ else
1170+ elog (ERROR ,"Something went wrong. current_file_size %lu, prev %lu" ,
1171+ current_file_size ,prev_file -> write_size );
1172+ }
1173+ else
1174+ elog (NOTICE ,"Copy full file. Generations are different" );
1175+ }
1176+
1177+ return result ;
1178+ }
1179+
11331180/*
11341181 * Take differential backup at page level.
11351182 */
@@ -1138,6 +1185,7 @@ backup_files(void *arg)
11381185{
11391186int i ;
11401187struct timeval tv ;
1188+
11411189backup_files_args * arguments = (backup_files_args * )arg ;
11421190
11431191gettimeofday (& tv ,NULL );
@@ -1239,52 +1287,15 @@ backup_files(void *arg)
12391287continue ;
12401288}
12411289}
1242- else
1290+ else if ( is_compressed_data_file ( file , arguments -> files ))
12431291{
1244- /* Check first if the file is a cfs relation's segment */
1245- bool is_cfs_relation_segment = false;
1246- pgFile tmp_file ;
1247- pgFile * * pre_search_file ;
1248- pgFile * prev_file = NULL ;
1249-
1250- tmp_file .path = psprintf ("%s.cfm" ,file -> path );
1251- pre_search_file = (pgFile * * )parray_bsearch (arguments -> files ,& tmp_file ,pgFileComparePath );
1252- if (pre_search_file != NULL )
1253- {
1254- /* Now check if it's generation has changed since last backup */
1255- if (arguments -> prev_files )
1256- {
1257- pgFile * * p = (pgFile * * )parray_bsearch (arguments -> prev_files ,file ,pgFileComparePath );
1258- if (p )
1259- prev_file = * p ;
1260- elog (NOTICE ,"file '%s' is a cfs relation's segment generation prev %d, now %d" ,
1261- file -> path ,prev_file -> generation ,file -> generation );
1262-
1263- if (prev_file && prev_file -> generation == file -> generation )
1264- {
1265- elog (NOTICE ,"prev->write_size %lu, file_size %lu" ,prev_file -> write_size ,file_size (file -> path ));
1266- if (prev_file -> write_size == file_size (file -> path ))
1267- {
1268- elog (NOTICE ,"File hasn't changed since last backup. Don't copy at all" );
1269- is_cfs_relation_segment = true;
1270- }
1271- else
1272- {
1273- elog (NOTICE ,"Backup part of the file. %s" ,file -> path );
1274- is_cfs_relation_segment = true;
1275- }
1276- }
1277- }
1278- }
1279- pg_free (tmp_file .path );
1280-
1281-
1282- if (is_cfs_relation_segment )
1292+ size_t skip_size = 0 ;
1293+ if (backup_compressed_file_partially (file ,arguments ,& skip_size ))
12831294{
12841295/* backup cfs segment partly */
12851296if (!copy_file_partly (arguments -> from_root ,
12861297arguments -> to_root ,
1287- file ,prev_file -> write_size ))
1298+ file ,skip_size ))
12881299{
12891300/* record as skipped file in file_xxx.txt */
12901301file -> write_size = BYTES_INVALID ;
@@ -1302,6 +1313,15 @@ backup_files(void *arg)
13021313continue ;
13031314}
13041315}
1316+ else if (!copy_file (arguments -> from_root ,
1317+ arguments -> to_root ,
1318+ file ))
1319+ {
1320+ /* record as skipped file in file_xxx.txt */
1321+ file -> write_size = BYTES_INVALID ;
1322+ elog (LOG ,"skip" );
1323+ continue ;
1324+ }
13051325
13061326elog (LOG ,"copied %lu" , (unsigned long )file -> write_size );
13071327}
@@ -1377,30 +1397,23 @@ add_files(parray *files, const char *root, bool add_root, bool is_pgdata)
13771397tmp_file .path [path_len - 7 ]= '\0' ;
13781398
13791399pre_search_file = (pgFile * * )parray_bsearch (list_file ,& tmp_file ,pgFileComparePath );
1380- /* Use another scheme for compressed files */
1381- pgFile map_file ;
1382- pgFile * * map_search_file ;
1383- map_file .path = pg_strdup (file -> path );
1384- if (segno > 0 )
1385- sprintf (map_file .path + path_len - 7 ,".%d.cfm" ,segno );
1386- else
1387- sprintf (map_file .path + path_len - 7 ,".cfm" );
1388- map_search_file = (pgFile * * )parray_bsearch (list_file ,& map_file ,pgFileComparePath );
13891400
1390- if (pre_search_file != NULL
1391- && map_search_file == NULL )
1401+ if (is_compressed_data_file (& tmp_file ,list_file ))
1402+ {
1403+ elog (NOTICE ,"file %s is compressed, don't remove it from list" ,tmp_file .path );
1404+ pg_free (tmp_file .path );
1405+ break ;
1406+ }
1407+
1408+ if (pre_search_file != NULL )
13921409{
13931410search_file = * pre_search_file ;
13941411search_file -> ptrack_path = pg_strdup (file -> path );
13951412search_file -> segno = segno ;
1396- }
1397- else
1398- {
1413+ }else {
13991414pg_free (tmp_file .path );
1400- pg_free (map_file .path );
14011415break ;
14021416}
1403- pg_free (map_file .path );
14041417pg_free (tmp_file .path );
14051418segno ++ ;
14061419}
@@ -1453,9 +1466,6 @@ add_files(parray *files, const char *root, bool add_root, bool is_pgdata)
14531466}
14541467
14551468/* mark cfs relations as not data */
1456- /* TODO
1457- * Don't mark cfs relations as not_datafile?
1458- * We can use similar code to check if the file is compressed */
14591469for (i = 0 ;i < (int )parray_num (list_file );i ++ )
14601470{
14611471pgFile * file = (pgFile * )parray_get (list_file ,i );
@@ -1467,7 +1477,8 @@ add_files(parray *files, const char *root, bool add_root, bool is_pgdata)
14671477pgFile tmp_file ;
14681478tmp_file .path = pg_strdup (file -> path );
14691479tmp_file .path [path_len - 4 ]= '\0' ;
1470- pre_search_file = (pgFile * * )parray_bsearch (list_file ,& tmp_file ,pgFileComparePath );
1480+ pre_search_file = (pgFile * * )parray_bsearch (list_file ,
1481+ & tmp_file ,pgFileComparePath );
14711482if (pre_search_file != NULL )
14721483{
14731484FileMap * map ;
@@ -1483,13 +1494,9 @@ add_files(parray *files, const char *root, bool add_root, bool is_pgdata)
14831494break ;
14841495}
14851496
1486- (* pre_search_file )-> last_backup_write_size = map -> last_backup_write_size ;
14871497(* pre_search_file )-> generation = map -> generation ;
14881498(* pre_search_file )-> is_datafile = false;
1489- map -> last_backup_write_size = map -> physSize ;
14901499
1491- if (cfs_msync (map )< 0 )
1492- elog (LOG ,"add_files(). CFS failed to sync map %s: %m" ,file -> path );
14931500if (cfs_munmap (map )< 0 )
14941501elog (LOG ,"add_files(). CFS failed to unmap file %s: %m" ,file -> path );
14951502if (close (md )< 0 )
@@ -1799,12 +1806,3 @@ int cfs_munmap(FileMap* map)
17991806return munmap (map ,sizeof (FileMap ));
18001807#endif
18011808}
1802-
1803- int cfs_msync (FileMap * map )
1804- {
1805- #ifdef WIN32
1806- return FlushViewOfFile (map ,sizeof (FileMap )) ?0 :-1 ;
1807- #else
1808- return msync (map ,sizeof (FileMap ),MS_SYNC );
1809- #endif
1810- }