Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit49163b3

Browse files
committed
[Issue#83] data corruption as a result of failed merge
1 parente495a9a commit49163b3

File tree

1 file changed

+40
-21
lines changed

1 file changed

+40
-21
lines changed

‎src/merge.c‎

Lines changed: 40 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -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-
elseif (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
charto_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+
charmerge_to_file_path[MAXPGPATH];
563572
chartmp_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 filein FULL backupif 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->pathpoints to the file in from_root directory. But we
589-
*need the file in directory to_root.
598+
* file->pathis 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

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp