Skip to content

Commit 644c4bd

Browse files
committed
Merge remote-tracking branch 'origin/pgpro-1892-2'
2 parents 8e71679 + ee6bab4 commit 644c4bd

File tree

8 files changed

+239
-93
lines changed

8 files changed

+239
-93
lines changed

Diff for: src/backup.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -817,7 +817,7 @@ do_backup_instance(void)
817817
}
818818

819819
/* Print the list of files to backup catalog */
820-
pgBackupWriteFileList(&current, backup_files_list, pgdata);
820+
write_backup_filelist(&current, backup_files_list, pgdata);
821821

822822
/* Compute summary of size of regular files in the backup */
823823
for (i = 0; i < parray_num(backup_files_list); i++)

Diff for: src/catalog.c

+9-5
Original file line numberDiff line numberDiff line change
@@ -509,18 +509,22 @@ write_backup(pgBackup *backup)
509509
fp = fopen(conf_path, "wt");
510510
if (fp == NULL)
511511
elog(ERROR, "Cannot open configuration file \"%s\": %s", conf_path,
512-
strerror(errno));
512+
strerror(errno));
513513

514514
pgBackupWriteControl(fp, backup);
515515

516-
fclose(fp);
516+
if (fflush(fp) != 0 ||
517+
fsync(fileno(fp)) != 0 ||
518+
fclose(fp))
519+
elog(ERROR, "Cannot write configuration file \"%s\": %s",
520+
conf_path, strerror(errno));
517521
}
518522

519523
/*
520524
* Output the list of files to backup catalog DATABASE_FILE_LIST
521525
*/
522526
void
523-
pgBackupWriteFileList(pgBackup *backup, parray *files, const char *root)
527+
write_backup_filelist(pgBackup *backup, parray *files, const char *root)
524528
{
525529
FILE *fp;
526530
char path[MAXPGPATH];
@@ -529,15 +533,15 @@ pgBackupWriteFileList(pgBackup *backup, parray *files, const char *root)
529533

530534
fp = fopen(path, "wt");
531535
if (fp == NULL)
532-
elog(ERROR, "cannot open file list \"%s\": %s", path,
536+
elog(ERROR, "Cannot open file list \"%s\": %s", path,
533537
strerror(errno));
534538

535539
print_file_list(fp, files, root);
536540

537541
if (fflush(fp) != 0 ||
538542
fsync(fileno(fp)) != 0 ||
539543
fclose(fp))
540-
elog(ERROR, "cannot write file list \"%s\": %s", path, strerror(errno));
544+
elog(ERROR, "Cannot write file list \"%s\": %s", path, strerror(errno));
541545
}
542546

543547
/*

Diff for: src/data.c

-16
Original file line numberDiff line numberDiff line change
@@ -1037,22 +1037,6 @@ copy_file(const char *from_root, const char *to_root, pgFile *file)
10371037
return true;
10381038
}
10391039

1040-
/*
1041-
* Move file from one backup to another.
1042-
* We do not apply compression to these files, because
1043-
* it is either small control file or already compressed cfs file.
1044-
*/
1045-
void
1046-
move_file(const char *from_root, const char *to_root, pgFile *file)
1047-
{
1048-
char to_path[MAXPGPATH];
1049-
1050-
join_path_components(to_path, to_root, file->path + strlen(from_root) + 1);
1051-
if (rename(file->path, to_path) == -1)
1052-
elog(ERROR, "Cannot move file \"%s\" to path \"%s\": %s",
1053-
file->path, to_path, strerror(errno));
1054-
}
1055-
10561040
#ifdef HAVE_LIBZ
10571041
/*
10581042
* Show error during work with compressed file

Diff for: src/delete.c

+15-12
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414
#include <time.h>
1515
#include <unistd.h>
1616

17-
static int delete_backup_files(pgBackup *backup);
1817
static void delete_walfiles(XLogRecPtr oldest_lsn, TimeLineID oldest_tli,
1918
uint32 xlog_seg_size);
2019

@@ -245,7 +244,7 @@ do_retention_purge(void)
245244
* Delete backup files of the backup and update the status of the backup to
246245
* BACKUP_STATUS_DELETED.
247246
*/
248-
static int
247+
void
249248
delete_backup_files(pgBackup *backup)
250249
{
251250
size_t i;
@@ -257,11 +256,15 @@ delete_backup_files(pgBackup *backup)
257256
* If the backup was deleted already, there is nothing to do.
258257
*/
259258
if (backup->status == BACKUP_STATUS_DELETED)
260-
return 0;
259+
{
260+
elog(WARNING, "Backup %s already deleted",
261+
base36enc(backup->start_time));
262+
return;
263+
}
261264

262265
time2iso(timestamp, lengthof(timestamp), backup->recovery_time);
263266

264-
elog(INFO, "delete: %s %s",
267+
elog(INFO, "Delete: %s %s",
265268
base36enc(backup->start_time), timestamp);
266269

267270
/*
@@ -283,25 +286,25 @@ delete_backup_files(pgBackup *backup)
283286
pgFile *file = (pgFile *) parray_get(files, i);
284287

285288
/* print progress */
286-
elog(VERBOSE, "delete file(%zd/%lu) \"%s\"", i + 1,
289+
elog(VERBOSE, "Delete file(%zd/%lu) \"%s\"", i + 1,
287290
(unsigned long) parray_num(files), file->path);
288291

289292
if (remove(file->path))
290293
{
291-
elog(WARNING, "can't remove \"%s\": %s", file->path,
292-
strerror(errno));
293-
parray_walk(files, pgFileFree);
294-
parray_free(files);
295-
296-
return 1;
294+
if (errno == ENOENT)
295+
elog(VERBOSE, "File \"%s\" is absent", file->path);
296+
else
297+
elog(ERROR, "Cannot remove \"%s\": %s", file->path,
298+
strerror(errno));
299+
return;
297300
}
298301
}
299302

300303
parray_walk(files, pgFileFree);
301304
parray_free(files);
302305
backup->status = BACKUP_STATUS_DELETED;
303306

304-
return 0;
307+
return;
305308
}
306309

307310
/*

Diff for: src/merge.c

+68-54
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ do_merge(time_t backup_id)
5959
if (instance_name == NULL)
6060
elog(ERROR, "required parameter is not specified: --instance");
6161

62-
elog(LOG, "Merge started");
62+
elog(INFO, "Merge started");
6363

6464
catalog_lock();
6565

@@ -77,7 +77,8 @@ do_merge(time_t backup_id)
7777
{
7878
if (backup->status != BACKUP_STATUS_OK &&
7979
/* It is possible that previous merging was interrupted */
80-
backup->status != BACKUP_STATUS_MERGING)
80+
backup->status != BACKUP_STATUS_MERGING &&
81+
backup->status != BACKUP_STATUS_DELETING)
8182
elog(ERROR, "Backup %s has status: %s",
8283
base36enc(backup->start_time), status2str(backup->status));
8384

@@ -128,17 +129,21 @@ do_merge(time_t backup_id)
128129
*/
129130
for (i = full_backup_idx; i > dest_backup_idx; i--)
130131
{
131-
pgBackup *to_backup = (pgBackup *) parray_get(backups, i);
132132
pgBackup *from_backup = (pgBackup *) parray_get(backups, i - 1);
133133

134-
merge_backups(to_backup, from_backup);
134+
full_backup = (pgBackup *) parray_get(backups, i);
135+
merge_backups(full_backup, from_backup);
135136
}
136137

138+
pgBackupValidate(full_backup);
139+
if (full_backup->status == BACKUP_STATUS_CORRUPT)
140+
elog(ERROR, "Merging of backup %s failed", base36enc(backup_id));
141+
137142
/* cleanup */
138143
parray_walk(backups, pgBackupFree);
139144
parray_free(backups);
140145

141-
elog(LOG, "Merge completed");
146+
elog(INFO, "Merge of backup %s completed", base36enc(backup_id));
142147
}
143148

144149
/*
@@ -164,7 +169,36 @@ merge_backups(pgBackup *to_backup, pgBackup *from_backup)
164169
int i;
165170
bool merge_isok = true;
166171

167-
elog(LOG, "Merging backup %s with backup %s", from_backup_id, to_backup_id);
172+
elog(INFO, "Merging backup %s with backup %s", from_backup_id, to_backup_id);
173+
174+
/*
175+
* Validate to_backup only if it is BACKUP_STATUS_OK. If it has
176+
* BACKUP_STATUS_MERGING status then it isn't valid backup until merging
177+
* finished.
178+
*/
179+
if (to_backup->status == BACKUP_STATUS_OK)
180+
{
181+
pgBackupValidate(to_backup);
182+
if (to_backup->status == BACKUP_STATUS_CORRUPT)
183+
elog(ERROR, "Interrupt merging");
184+
}
185+
186+
/*
187+
* It is OK to validate from_backup if it has BACKUP_STATUS_OK or
188+
* BACKUP_STATUS_MERGING status.
189+
*/
190+
Assert(from_backup->status == BACKUP_STATUS_OK ||
191+
from_backup->status == BACKUP_STATUS_MERGING);
192+
pgBackupValidate(from_backup);
193+
if (from_backup->status == BACKUP_STATUS_CORRUPT)
194+
elog(ERROR, "Interrupt merging");
195+
196+
/*
197+
* Previous merging was interrupted during deleting source backup. It is
198+
* safe just to delete it again.
199+
*/
200+
if (from_backup->status == BACKUP_STATUS_DELETING)
201+
goto delete_source_backup;
168202

169203
to_backup->status = BACKUP_STATUS_MERGING;
170204
write_backup_status(to_backup);
@@ -244,37 +278,38 @@ merge_backups(pgBackup *to_backup, pgBackup *from_backup)
244278
elog(ERROR, "Data files merging failed");
245279

246280
/*
247-
* Files were copied into to_backup and deleted from from_backup. Remove
248-
* remaining directories from from_backup.
281+
* Update to_backup metadata.
249282
*/
250-
parray_qsort(files, pgFileComparePathDesc);
283+
to_backup->status = BACKUP_STATUS_OK;
284+
/* Compute summary of size of regular files in the backup */
285+
to_backup->data_bytes = 0;
251286
for (i = 0; i < parray_num(files); i++)
252287
{
253288
pgFile *file = (pgFile *) parray_get(files, i);
254289

255-
if (!S_ISDIR(file->mode))
256-
continue;
257-
258-
if (rmdir(file->path))
259-
elog(ERROR, "Could not remove directory \"%s\": %s",
260-
file->path, strerror(errno));
290+
if (S_ISDIR(file->mode))
291+
to_backup->data_bytes += 4096;
292+
/* Count the amount of the data actually copied */
293+
else if (S_ISREG(file->mode))
294+
to_backup->data_bytes += file->write_size;
261295
}
262-
if (rmdir(from_database_path))
263-
elog(ERROR, "Could not remove directory \"%s\": %s",
264-
from_database_path, strerror(errno));
265-
if (unlink(control_file))
266-
elog(ERROR, "Could not remove file \"%s\": %s",
267-
control_file, strerror(errno));
296+
/* compute size of wal files of this backup stored in the archive */
297+
if (!to_backup->stream)
298+
to_backup->wal_bytes = xlog_seg_size *
299+
(to_backup->stop_lsn / xlog_seg_size -
300+
to_backup->start_lsn / xlog_seg_size + 1);
301+
else
302+
to_backup->wal_bytes = BYTES_INVALID;
268303

269-
pgBackupGetPath(from_backup, control_file, lengthof(control_file),
270-
BACKUP_CONTROL_FILE);
271-
if (unlink(control_file))
272-
elog(ERROR, "Could not remove file \"%s\": %s",
273-
control_file, strerror(errno));
304+
write_backup_filelist(to_backup, files, from_database_path);
305+
write_backup(to_backup);
274306

275-
if (rmdir(from_backup_path))
276-
elog(ERROR, "Could not remove directory \"%s\": %s",
277-
from_backup_path, strerror(errno));
307+
delete_source_backup:
308+
/*
309+
* Files were copied into to_backup. It is time to remove source backup
310+
* entirely.
311+
*/
312+
delete_backup_files(from_backup);
278313

279314
/*
280315
* Delete files which are not in from_backup file list.
@@ -286,46 +321,26 @@ merge_backups(pgBackup *to_backup, pgBackup *from_backup)
286321
if (parray_bsearch(files, file, pgFileComparePathDesc) == NULL)
287322
{
288323
pgFileDelete(file);
289-
elog(LOG, "Deleted \"%s\"", file->path);
324+
elog(VERBOSE, "Deleted \"%s\"", file->path);
290325
}
291326
}
292327

293328
/*
294329
* Rename FULL backup directory.
295330
*/
331+
elog(INFO, "Rename %s to %s", to_backup_id, from_backup_id);
296332
if (rename(to_backup_path, from_backup_path) == -1)
297333
elog(ERROR, "Could not rename directory \"%s\" to \"%s\": %s",
298334
to_backup_path, from_backup_path, strerror(errno));
299335

300336
/*
301-
* Update to_backup metadata.
337+
* Merging finished, now we can safely update ID of the destination backup.
302338
*/
303339
pgBackupCopy(to_backup, from_backup);
304340
/* Correct metadata */
305341
to_backup->backup_mode = BACKUP_MODE_FULL;
306342
to_backup->status = BACKUP_STATUS_OK;
307343
to_backup->parent_backup = INVALID_BACKUP_ID;
308-
/* Compute summary of size of regular files in the backup */
309-
to_backup->data_bytes = 0;
310-
for (i = 0; i < parray_num(files); i++)
311-
{
312-
pgFile *file = (pgFile *) parray_get(files, i);
313-
314-
if (S_ISDIR(file->mode))
315-
to_backup->data_bytes += 4096;
316-
/* Count the amount of the data actually copied */
317-
else if (S_ISREG(file->mode))
318-
to_backup->data_bytes += file->write_size;
319-
}
320-
/* compute size of wal files of this backup stored in the archive */
321-
if (!to_backup->stream)
322-
to_backup->wal_bytes = xlog_seg_size *
323-
(to_backup->stop_lsn / xlog_seg_size -
324-
to_backup->start_lsn / xlog_seg_size + 1);
325-
else
326-
to_backup->wal_bytes = BYTES_INVALID;
327-
328-
pgBackupWriteFileList(to_backup, files, from_database_path);
329344
write_backup(to_backup);
330345

331346
/* Cleanup */
@@ -508,10 +523,9 @@ merge_files(void *arg)
508523
file->write_size = pgFileSize(to_path_tmp);
509524
file->crc = pgFileGetCRC(to_path_tmp, false);
510525
}
511-
pgFileDelete(file);
512526
}
513527
else
514-
move_file(argument->from_root, argument->to_root, file);
528+
copy_file(argument->from_root, argument->to_root, file);
515529

516530
if (file->write_size != BYTES_INVALID)
517531
elog(LOG, "Moved file \"%s\": " INT64_FORMAT " bytes",

Diff for: src/pg_probackup.h

+4-3
Original file line numberDiff line numberDiff line change
@@ -452,6 +452,7 @@ extern int do_show(time_t requested_backup_id);
452452

453453
/* in delete.c */
454454
extern void do_delete(time_t backup_id);
455+
extern void delete_backup_files(pgBackup *backup);
455456
extern int do_retention_purge(void);
456457
extern int do_delete_instance(void);
457458

@@ -482,10 +483,11 @@ extern pgBackup *catalog_get_last_data_backup(parray *backup_list,
482483
TimeLineID tli);
483484
extern void catalog_lock(void);
484485
extern void pgBackupWriteControl(FILE *out, pgBackup *backup);
485-
extern void pgBackupWriteFileList(pgBackup *backup, parray *files,
486+
extern void write_backup_filelist(pgBackup *backup, parray *files,
486487
const char *root);
487488

488-
extern void pgBackupGetPath(const pgBackup *backup, char *path, size_t len, const char *subdir);
489+
extern void pgBackupGetPath(const pgBackup *backup, char *path, size_t len,
490+
const char *subdir);
489491
extern void pgBackupGetPath2(const pgBackup *backup, char *path, size_t len,
490492
const char *subdir1, const char *subdir2);
491493
extern int pgBackupCreateDir(pgBackup *backup);
@@ -547,7 +549,6 @@ extern void restore_data_file(const char *to_path,
547549
bool write_header,
548550
uint32 backup_version);
549551
extern bool copy_file(const char *from_root, const char *to_root, pgFile *file);
550-
extern void move_file(const char *from_root, const char *to_root, pgFile *file);
551552
extern void push_wal_file(const char *from_path, const char *to_path,
552553
bool is_compress, bool overwrite);
553554
extern void get_wal_file(const char *from_path, const char *to_path);

0 commit comments

Comments
 (0)