@@ -160,6 +160,7 @@ do_merge(time_t backup_id)
160160
161161/*
162162 * Merge two backups data files using threads.
163+ * - to_backup - FULL, from_backup - incremental.
163164 * - move instance files from from_backup to to_backup
164165 * - remove unnecessary directories and files from to_backup
165166 * - update metadata of from_backup, it becames FULL backup
@@ -355,9 +356,12 @@ merge_backups(pgBackup *to_backup, pgBackup *from_backup)
355356 pgFile * file = (pgFile * ) parray_get (files , i );
356357
357358 if (S_ISDIR (file -> mode ))
359+ {
358360 to_backup -> data_bytes += 4096 ;
361+ continue ;
362+ }
359363 /* Count the amount of the data actually copied */
360- else if (S_ISREG ( file -> mode ) )
364+ if (file -> write_size > 0 )
361365 to_backup -> data_bytes += file -> write_size ;
362366 }
363367 /* compute size of wal files of this backup stored in the archive */
@@ -381,7 +385,7 @@ merge_backups(pgBackup *to_backup, pgBackup *from_backup)
381385 /*
382386 * Delete files which are not in from_backup file list.
383387 */
384- parray_qsort (files , pgFileComparePathDesc );
388+ parray_qsort (files , pgFileComparePathWithExternalDesc );
385389 for (i = 0 ; i < parray_num (to_files ); i ++ )
386390 {
387391 pgFile * file = (pgFile * ) parray_get (to_files , i );
@@ -394,7 +398,7 @@ merge_backups(pgBackup *to_backup, pgBackup *from_backup)
394398 continue ;
395399 }
396400
397- if (parray_bsearch (files , file , pgFileComparePathDesc ) == NULL )
401+ if (parray_bsearch (files , file , pgFileComparePathWithExternalDesc ) == NULL )
398402 {
399403 char to_file_path [MAXPGPATH ];
400404 char * prev_path ;
@@ -507,7 +511,7 @@ merge_files(void *arg)
507511 (!file -> is_datafile || file -> is_cfs ))
508512 {
509513 elog (VERBOSE , "Skip merging file \"%s\", the file didn't change" ,
510- file -> path );
514+ file -> rel_path );
511515
512516 /*
513517 * If the file wasn't changed, retreive its
@@ -529,6 +533,10 @@ merge_files(void *arg)
529533 }
530534 }
531535
536+ /* TODO optimization: file from incremental backup has size 0, then
537+ * just truncate the file from FULL backup
538+ */
539+
532540 /* We need to make full path, file object has relative path */
533541 if (file -> external_dir_num )
534542 {
@@ -560,46 +568,51 @@ merge_files(void *arg)
560568 if (to_backup -> compress_alg == PGLZ_COMPRESS ||
561569 to_backup -> compress_alg == ZLIB_COMPRESS )
562570 {
571+ char merge_to_file_path [MAXPGPATH ];
563572 char tmp_file_path [MAXPGPATH ];
564573 char * prev_path ;
565574
575+ snprintf (merge_to_file_path , MAXPGPATH , "%s_merge" , to_file_path );
566576 snprintf (tmp_file_path , MAXPGPATH , "%s_tmp" , to_file_path );
567577
568578 /* Start the magic */
569579
570580 /*
571581 * Merge files:
572- * - if target file exists restore and decompress it to the temp
573- * path
582+ * - if to_file in FULL backup exists, restore and decompress it to to_file_merge
574583 * - decompress source file if necessary and merge it with the
575- * target decompressed file
576- * - compress result file
584+ * target decompressed file in to_file_merge.
585+ * - compress result file to to_file_tmp
586+ * - rename to_file_tmp to to_file
577587 */
578588
579589 /*
580- * We need to decompress target file if it exists.
590+ * We need to decompress target file in FULL backup if it exists.
581591 */
582592 if (to_file )
583593 {
584594 elog (VERBOSE , "Merge target and source files into the temporary path \"%s\"" ,
585- tmp_file_path );
595+ merge_to_file_path );
586596
587597 /*
588- * file->path points to the file in from_root directory. But we
589- * need the file in directory to_root .
598+ * file->path is relative, to_file_path - is absolute.
599+ * Substitute them .
590600 */
591601 prev_path = to_file -> path ;
592602 to_file -> path = to_file_path ;
593603 /* Decompress target file into temporary one */
594- restore_data_file (tmp_file_path , to_file , false, false,
604+ restore_data_file (merge_to_file_path , to_file , false, false,
595605 parse_program_version (to_backup -> program_version ));
596606 to_file -> path = prev_path ;
597607 }
598608 else
599609 elog (VERBOSE , "Restore source file into the temporary path \"%s\"" ,
600- tmp_file_path );
610+ merge_to_file_path );
611+
612+ /* TODO: Optimize merge of new files */
613+
601614 /* Merge source file with target file */
602- restore_data_file (tmp_file_path , file ,
615+ restore_data_file (merge_to_file_path , file ,
603616 from_backup -> backup_mode == BACKUP_MODE_DIFF_DELTA ,
604617 false,
605618 parse_program_version (from_backup -> program_version ));
@@ -609,12 +622,12 @@ merge_files(void *arg)
609622
610623 /* Again we need to change path */
611624 prev_path = file -> path ;
612- file -> path = tmp_file_path ;
625+ file -> path = merge_to_file_path ;
613626 /* backup_data_file() requires file size to calculate nblocks */
614627 file -> size = pgFileSize (file -> path );
615628 /* Now we can compress the file */
616629 backup_data_file (NULL , /* We shouldn't need 'arguments' here */
617- to_file_path , file ,
630+ tmp_file_path , file ,
618631 to_backup -> start_lsn ,
619632 to_backup -> backup_mode ,
620633 to_backup -> compress_alg ,
@@ -623,10 +636,15 @@ merge_files(void *arg)
623636
624637 file -> path = prev_path ;
625638
626- /* We can remove temporary file now */
627- if (unlink (tmp_file_path ))
639+ /* rename temp file */
640+ if (rename (tmp_file_path , to_file_path ) == -1 )
641+ elog (ERROR , "Could not rename file \"%s\" to \"%s\": %s" ,
642+ file -> path , tmp_file_path , strerror (errno ));
643+
644+ /* We can remove temporary file */
645+ if (unlink (merge_to_file_path ))
628646 elog (ERROR , "Could not remove temporary file \"%s\": %s" ,
629- tmp_file_path , strerror (errno ));
647+ merge_to_file_path , strerror (errno ));
630648 }
631649 /*
632650 * Otherwise merging algorithm is simpler.
@@ -676,7 +694,8 @@ merge_files(void *arg)
676694 elog (VERBOSE , "Merged file \"%s\": " INT64_FORMAT " bytes" ,
677695 file -> path , file -> write_size );
678696 else
679- elog (ERROR , "Merge of file \"%s\" failed. Invalid size: %i" , BYTES_INVALID );
697+ elog (ERROR , "Merge of file \"%s\" failed. Invalid size: %i" ,
698+ file -> path , BYTES_INVALID );
680699
681700 /* Restore relative path */
682701 file -> path = prev_file_path ;
0 commit comments