Skip to content

Commit 0220ae5

Browse files
committed
Merge branch 'master' into pgpro_2370
2 parents 5c247d0 + 04a7d45 commit 0220ae5

File tree

8 files changed

+379
-43
lines changed

8 files changed

+379
-43
lines changed

src/backup.c

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -763,6 +763,19 @@ do_backup_instance(void)
763763
else
764764
elog(ERROR, "Data files transferring failed");
765765

766+
/* Remove disappeared during backup files from backup_list */
767+
for (i = 0; i < parray_num(backup_files_list); i++)
768+
{
769+
pgFile *tmp_file = (pgFile *) parray_get(backup_files_list, i);
770+
771+
if (tmp_file->write_size == FILE_NOT_FOUND)
772+
{
773+
pg_atomic_clear_flag(&tmp_file->lock);
774+
pgFileFree(tmp_file);
775+
parray_remove(backup_files_list, i);
776+
}
777+
}
778+
766779
/* clean previous backup file list */
767780
if (prev_backup_filelist)
768781
{
@@ -2241,7 +2254,7 @@ backup_files(void *arg)
22412254
* If file is not found, this is not en error.
22422255
* It could have been deleted by concurrent postgres transaction.
22432256
*/
2244-
file->write_size = BYTES_INVALID;
2257+
file->write_size = FILE_NOT_FOUND;
22452258
elog(LOG, "File \"%s\" is not found", file->path);
22462259
continue;
22472260
}
@@ -2291,7 +2304,9 @@ backup_files(void *arg)
22912304
instance_config.compress_alg,
22922305
instance_config.compress_level))
22932306
{
2294-
file->write_size = BYTES_INVALID;
2307+
/* disappeared file not to be confused with 'not changed' */
2308+
if (file->write_size != FILE_NOT_FOUND)
2309+
file->write_size = BYTES_INVALID;
22952310
elog(VERBOSE, "File \"%s\" was not copied to backup", file->path);
22962311
continue;
22972312
}
@@ -2315,7 +2330,9 @@ backup_files(void *arg)
23152330
if (skip ||
23162331
!copy_file(arguments->from_root, arguments->to_root, file))
23172332
{
2318-
file->write_size = BYTES_INVALID;
2333+
/* disappeared file not to be confused with 'not changed' */
2334+
if (file->write_size != FILE_NOT_FOUND)
2335+
file->write_size = BYTES_INVALID;
23192336
elog(VERBOSE, "File \"%s\" was not copied to backup",
23202337
file->path);
23212338
continue;

src/catalog.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -981,6 +981,9 @@ is_parent(time_t parent_backup_time, pgBackup *child_backup, bool inclusive)
981981
if (!child_backup)
982982
elog(ERROR, "Target backup cannot be NULL");
983983

984+
if (inclusive && child_backup->start_time == parent_backup_time)
985+
return true;
986+
984987
while (child_backup->parent_backup_link &&
985988
child_backup->parent_backup != parent_backup_time)
986989
{
@@ -990,8 +993,8 @@ is_parent(time_t parent_backup_time, pgBackup *child_backup, bool inclusive)
990993
if (child_backup->parent_backup == parent_backup_time)
991994
return true;
992995

993-
if (inclusive && child_backup->start_time == parent_backup_time)
994-
return true;
996+
//if (inclusive && child_backup->start_time == parent_backup_time)
997+
// return true;
995998

996999
return false;
9971000
}

src/data.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -564,6 +564,7 @@ backup_data_file(backup_files_arg* arguments,
564564
if (errno == ENOENT)
565565
{
566566
elog(LOG, "File \"%s\" is not found", file->path);
567+
file->write_size = FILE_NOT_FOUND;
567568
return false;
568569
}
569570

@@ -946,7 +947,11 @@ copy_file(const char *from_root, const char *to_root, pgFile *file)
946947

947948
/* maybe deleted, it's not error */
948949
if (errno == ENOENT)
950+
{
951+
elog(LOG, "File \"%s\" is not found", file->path);
952+
file->write_size = FILE_NOT_FOUND;
949953
return false;
954+
}
950955

951956
elog(ERROR, "cannot open source file \"%s\": %s", file->path,
952957
strerror(errno));

src/dir.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1055,11 +1055,11 @@ create_data_directories(const char *data_dir, const char *backup_dir,
10551055
}
10561056

10571057
if (link_sep)
1058-
elog(LOG, "create directory \"%s\" and symbolic link \"%.*s\"",
1058+
elog(VERBOSE, "create directory \"%s\" and symbolic link \"%.*s\"",
10591059
linked_path,
10601060
(int) (link_sep - relative_ptr), relative_ptr);
10611061
else
1062-
elog(LOG, "create directory \"%s\" and symbolic link \"%s\"",
1062+
elog(VERBOSE, "create directory \"%s\" and symbolic link \"%s\"",
10631063
linked_path, relative_ptr);
10641064

10651065
/* Firstly, create linked directory */
@@ -1090,7 +1090,7 @@ create_data_directories(const char *data_dir, const char *backup_dir,
10901090
}
10911091

10921092
create_directory:
1093-
elog(LOG, "create directory \"%s\"", relative_ptr);
1093+
elog(VERBOSE, "create directory \"%s\"", relative_ptr);
10941094

10951095
/* This is not symlink, create directory */
10961096
join_path_components(to_path, data_dir, relative_ptr);

src/parsexlog.c

Lines changed: 26 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,9 @@ typedef struct XLogPageReadPrivate
104104
#ifdef HAVE_LIBZ
105105
gzFile gz_xlogfile;
106106
char gz_xlogpath[MAXPGPATH];
107+
108+
char gz_buf[XLOG_BLCKSZ];
109+
uint32 gz_prev_off;
107110
#endif
108111
} XLogPageReadPrivate;
109112

@@ -1057,22 +1060,30 @@ SimpleXLogPageRead(XLogReaderState *xlogreader, XLogRecPtr targetPagePtr,
10571060
#ifdef HAVE_LIBZ
10581061
else
10591062
{
1060-
if (gzseek(private_data->gz_xlogfile, (z_off_t) targetPageOff, SEEK_SET) == -1)
1063+
if (private_data->gz_prev_off != 0 &&
1064+
private_data->gz_prev_off == targetPageOff)
1065+
memcpy(readBuf, private_data->gz_buf, XLOG_BLCKSZ);
1066+
else
10611067
{
1062-
elog(WARNING, "Thread [%d]: Could not seek in compressed WAL segment \"%s\": %s",
1063-
private_data->thread_num,
1064-
private_data->gz_xlogpath,
1065-
get_gz_error(private_data->gz_xlogfile));
1066-
return -1;
1067-
}
1068+
if (gzseek(private_data->gz_xlogfile, (z_off_t) targetPageOff, SEEK_SET) == -1)
1069+
{
1070+
elog(WARNING, "Thread [%d]: Could not seek in compressed WAL segment \"%s\": %s",
1071+
private_data->thread_num,
1072+
private_data->gz_xlogpath,
1073+
get_gz_error(private_data->gz_xlogfile));
1074+
return -1;
1075+
}
10681076

1069-
if (gzread(private_data->gz_xlogfile, readBuf, XLOG_BLCKSZ) != XLOG_BLCKSZ)
1070-
{
1071-
elog(WARNING, "Thread [%d]: Could not read from compressed WAL segment \"%s\": %s",
1072-
private_data->thread_num,
1073-
private_data->gz_xlogpath,
1074-
get_gz_error(private_data->gz_xlogfile));
1075-
return -1;
1077+
if (gzread(private_data->gz_xlogfile, readBuf, XLOG_BLCKSZ) != XLOG_BLCKSZ)
1078+
{
1079+
elog(WARNING, "Thread [%d]: Could not read from compressed WAL segment \"%s\": %s",
1080+
private_data->thread_num,
1081+
private_data->gz_xlogpath,
1082+
get_gz_error(private_data->gz_xlogfile));
1083+
return -1;
1084+
}
1085+
private_data->gz_prev_off = targetPageOff;
1086+
memcpy(private_data->gz_buf, readBuf, XLOG_BLCKSZ);
10761087
}
10771088
}
10781089
#endif
@@ -1131,6 +1142,7 @@ CleanupXLogPageRead(XLogReaderState *xlogreader)
11311142
{
11321143
gzclose(private_data->gz_xlogfile);
11331144
private_data->gz_xlogfile = NULL;
1145+
private_data->gz_prev_off = 0;
11341146
}
11351147
#endif
11361148
private_data->xlogexists = false;

src/pg_probackup.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,8 @@ typedef enum ShowFormat
165165

166166
/* special values of pgBackup fields */
167167
#define INVALID_BACKUP_ID 0 /* backup ID is not provided by user */
168-
#define BYTES_INVALID (-1)
168+
#define BYTES_INVALID (-1) /* file didn`t changed since previous backup, DELTA backup do not rely on it */
169+
#define FILE_NOT_FOUND (-2) /* file disappeared during backup */
169170
#define BLOCKNUM_INVALID (-1)
170171

171172
/*

src/restore.c

Lines changed: 39 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ do_restore_or_validate(time_t target_backup_id, pgRecoveryTarget *rt,
5757
int base_full_backup_index = 0;
5858
int corrupted_backup_index = 0;
5959
char *action = is_restore ? "Restore":"Validate";
60+
parray *parent_chain = NULL;
6061

6162
if (is_restore)
6263
{
@@ -285,34 +286,53 @@ do_restore_or_validate(time_t target_backup_id, pgRecoveryTarget *rt,
285286
if (is_restore)
286287
check_tablespace_mapping(dest_backup);
287288

289+
/* At this point we are sure that parent chain is whole
290+
* so we can build separate array, containing all needed backups,
291+
* to simplify validation and restore
292+
*/
293+
parent_chain = parray_new();
294+
295+
/* Take every backup that is a child of base_backup AND parent of dest_backup
296+
* including base_backup and dest_backup
297+
*/
298+
for (i = base_full_backup_index; i >= dest_backup_index; i--)
299+
{
300+
tmp_backup = (pgBackup *) parray_get(backups, i);
301+
302+
if (is_parent(base_full_backup->start_time, tmp_backup, true) &&
303+
is_parent(tmp_backup->start_time, dest_backup, true))
304+
{
305+
parray_append(parent_chain, tmp_backup);
306+
}
307+
}
308+
309+
/* for validation or restore with enabled validation */
288310
if (!is_restore || !rt->restore_no_validate)
289311
{
290312
if (dest_backup->backup_mode != BACKUP_MODE_FULL)
291313
elog(INFO, "Validating parents for backup %s", base36enc(dest_backup->start_time));
292314

293315
/*
294316
* Validate backups from base_full_backup to dest_backup.
295-
* At this point we are sure that parent chain is intact.
296317
*/
297-
for (i = base_full_backup_index; i >= dest_backup_index; i--)
318+
for (i = 0; i < parray_num(parent_chain); i++)
298319
{
299-
tmp_backup = (pgBackup *) parray_get(backups, i);
320+
tmp_backup = (pgBackup *) parray_get(parent_chain, i);
300321

301-
if (is_parent(base_full_backup->start_time, tmp_backup, true))
322+
pgBackupValidate(tmp_backup);
323+
/* Maybe we should be more paranoid and check for !BACKUP_STATUS_OK? */
324+
if (tmp_backup->status == BACKUP_STATUS_CORRUPT)
302325
{
303-
304-
pgBackupValidate(tmp_backup);
305-
/* Maybe we should be more paranoid and check for !BACKUP_STATUS_OK? */
306-
if (tmp_backup->status == BACKUP_STATUS_CORRUPT)
307-
{
308-
corrupted_backup = tmp_backup;
309-
corrupted_backup_index = i;
310-
break;
311-
}
312-
/* We do not validate WAL files of intermediate backups
313-
* It`s done to speed up restore
326+
corrupted_backup = tmp_backup;
327+
/* we need corrupted backup index from 'backups' not parent_chain
328+
* so we can properly orphanize all its descendants
314329
*/
330+
corrupted_backup_index = get_backup_index_number(backups, corrupted_backup);
331+
break;
315332
}
333+
/* We do not validate WAL files of intermediate backups
334+
* It`s done to speed up restore
335+
*/
316336
}
317337

318338
/* There is no point in wal validation of corrupted backups */
@@ -355,7 +375,6 @@ do_restore_or_validate(time_t target_backup_id, pgRecoveryTarget *rt,
355375
}
356376
}
357377

358-
// TODO: rewrite restore to use parent_chain
359378
/*
360379
* If dest backup is corrupted or was orphaned in previous check
361380
* produce corresponding error message
@@ -376,13 +395,12 @@ do_restore_or_validate(time_t target_backup_id, pgRecoveryTarget *rt,
376395
base36enc(dest_backup->start_time), status2str(dest_backup->status));
377396

378397
/* We ensured that all backups are valid, now restore if required
379-
* TODO: use parent_link
380398
*/
381399
if (is_restore)
382400
{
383-
for (i = base_full_backup_index; i >= dest_backup_index; i--)
401+
for (i = 0; i < parray_num(parent_chain); i++)
384402
{
385-
pgBackup *backup = (pgBackup *) parray_get(backups, i);
403+
pgBackup *backup = (pgBackup *) parray_get(parent_chain, i);
386404

387405
if (rt->lsn_specified && parse_server_version(backup->server_version) < 100000)
388406
elog(ERROR, "Backup %s was created for version %s which doesn't support recovery_target_lsn",
@@ -405,6 +423,7 @@ do_restore_or_validate(time_t target_backup_id, pgRecoveryTarget *rt,
405423
/* cleanup */
406424
parray_walk(backups, pgBackupFree);
407425
parray_free(backups);
426+
parray_free(parent_chain);
408427

409428
elog(INFO, "%s of backup %s completed.",
410429
action, base36enc(dest_backup->start_time));
@@ -480,6 +499,7 @@ restore_backup(pgBackup *backup)
480499
/* By default there are some error */
481500
threads_args[i].ret = 1;
482501

502+
/* Useless message TODO: rewrite */
483503
elog(LOG, "Start thread for num:%zu", parray_num(files));
484504

485505
pthread_create(&threads[i], NULL, restore_files, arg);

0 commit comments

Comments
 (0)