1
0
mirror of https://github.com/postgrespro/pg_probackup.git synced 2026-06-21 01:34:15 +02:00

Add muti-thread validation.

This commit is contained in:
stalkerg
2016-11-25 14:26:58 +03:00
parent 2eb6d92ee1
commit b127345cd5
3 changed files with 66 additions and 21 deletions
+3
View File
@@ -178,6 +178,9 @@ main(int argc, char *argv[])
if (target_time != NULL && target_xid != NULL) if (target_time != NULL && target_xid != NULL)
elog(ERROR, "You can't specify recovery-target-time and recovery-target-xid at the same time"); elog(ERROR, "You can't specify recovery-target-time and recovery-target-xid at the same time");
if (num_threads < 1)
num_threads = 1;
/* do actual operation */ /* do actual operation */
if (pg_strcasecmp(cmd, "init") == 0) if (pg_strcasecmp(cmd, "init") == 0)
return do_init(); return do_init();
-3
View File
@@ -335,9 +335,6 @@ restore_database(pgBackup *backup)
pgFileFree(parray_remove(files, i)); pgFileFree(parray_remove(files, i));
} }
if (num_threads < 1)
num_threads = 1;
for (i = 0; i < parray_num(files); i++) for (i = 0; i < parray_num(files); i++)
{ {
pgFile *file = (pgFile *) parray_get(files, i); pgFile *file = (pgFile *) parray_get(files, i);
+63 -18
View File
@@ -10,8 +10,17 @@
#include "pg_probackup.h" #include "pg_probackup.h"
#include <sys/stat.h> #include <sys/stat.h>
#include <pthread.h>
static bool pgBackupValidateFiles(parray *files, const char *root, bool size_only); static void pgBackupValidateFiles(void *arg);
typedef struct
{
parray *files;
const char *root;
bool size_only;
bool corrupted;
} validate_files_args;
/* /*
* Validate files in the backup and update its status to OK. * Validate files in the backup and update its status to OK.
@@ -85,6 +94,8 @@ pgBackupValidate(pgBackup *backup,
char path[MAXPGPATH]; char path[MAXPGPATH];
parray *files; parray *files;
bool corrupted = false; bool corrupted = false;
pthread_t validate_threads[num_threads];
validate_files_args *validate_threads_args[num_threads];
time2iso(timestamp, lengthof(timestamp), backup->recovery_time); time2iso(timestamp, lengthof(timestamp), backup->recovery_time);
if (!for_get_timeline) if (!for_get_timeline)
@@ -102,13 +113,41 @@ pgBackupValidate(pgBackup *backup,
backup->backup_mode == BACKUP_MODE_DIFF_PAGE || backup->backup_mode == BACKUP_MODE_DIFF_PAGE ||
backup->backup_mode == BACKUP_MODE_DIFF_PTRACK) backup->backup_mode == BACKUP_MODE_DIFF_PTRACK)
{ {
int i;
elog(LOG, "database files..."); elog(LOG, "database files...");
pgBackupGetPath(backup, base_path, lengthof(base_path), DATABASE_DIR); pgBackupGetPath(backup, base_path, lengthof(base_path), DATABASE_DIR);
pgBackupGetPath(backup, path, lengthof(path), pgBackupGetPath(backup, path, lengthof(path),
DATABASE_FILE_LIST); DATABASE_FILE_LIST);
files = dir_read_file_list(base_path, path); files = dir_read_file_list(base_path, path);
if (!pgBackupValidateFiles(files, base_path, size_only))
corrupted = true; /* setup threads */
for (i = 0; i < parray_num(files); i++)
{
pgFile *file = (pgFile *) parray_get(files, i);
__sync_lock_release(&file->lock);
}
/* restore files into $PGDATA */
for (i = 0; i < num_threads; i++)
{
validate_files_args *arg = pg_malloc(sizeof(validate_files_args));
arg->files = files;
arg->root = base_path;
arg->size_only = size_only;
arg->corrupted = false;
validate_threads_args[i] = arg;
pthread_create(&validate_threads[i], NULL, (void *(*)(void *)) pgBackupValidateFiles, arg);
}
/* Wait theads */
for (i = 0; i < num_threads; i++)
{
pthread_join(validate_threads[i], NULL);
if (validate_threads_args[i]->corrupted)
corrupted = true;
pg_free(validate_threads_args[i]);
}
parray_walk(files, pgFileFree); parray_walk(files, pgFileFree);
parray_free(files); parray_free(files);
} }
@@ -140,16 +179,21 @@ get_relative_path(const char *path, const char *root)
/* /*
* Validate files in the backup with size or CRC. * Validate files in the backup with size or CRC.
*/ */
static bool static void
pgBackupValidateFiles(parray *files, const char *root, bool size_only) pgBackupValidateFiles(void *arg)
{ {
int i; int i;
for (i = 0; i < parray_num(files); i++) validate_files_args *arguments = (validate_files_args *)arg;
for (i = 0; i < parray_num(arguments->files); i++)
{ {
struct stat st; struct stat st;
pgFile *file = (pgFile *) parray_get(files, i); pgFile *file = (pgFile *) parray_get(arguments->files, i);
if (__sync_lock_test_and_set(&file->lock, 1) != 0)
continue;
if (interrupted) if (interrupted)
elog(ERROR, "interrupted during validate"); elog(ERROR, "interrupted during validate");
@@ -159,8 +203,8 @@ pgBackupValidateFiles(parray *files, const char *root, bool size_only)
continue; continue;
/* print progress */ /* print progress */
elog(LOG, "(%d/%lu) %s", i + 1, (unsigned long) parray_num(files), elog(LOG, "(%d/%lu) %s", i + 1, (unsigned long) parray_num(arguments->files),
get_relative_path(file->path, root)); get_relative_path(file->path, arguments->root));
/* always validate file size */ /* always validate file size */
if (stat(file->path, &st) == -1) if (stat(file->path, &st) == -1)
@@ -169,20 +213,22 @@ pgBackupValidateFiles(parray *files, const char *root, bool size_only)
elog(WARNING, "backup file \"%s\" vanished", file->path); elog(WARNING, "backup file \"%s\" vanished", file->path);
else else
elog(ERROR, "cannot stat backup file \"%s\": %s", elog(ERROR, "cannot stat backup file \"%s\": %s",
get_relative_path(file->path, root), strerror(errno)); get_relative_path(file->path, arguments->root), strerror(errno));
return false; arguments->corrupted = true;
return;
} }
if (file->write_size != st.st_size) if (file->write_size != st.st_size)
{ {
elog(WARNING, "size of backup file \"%s\" must be %lu but %lu", elog(WARNING, "size of backup file \"%s\" must be %lu but %lu",
get_relative_path(file->path, root), get_relative_path(file->path, arguments->root),
(unsigned long) file->write_size, (unsigned long) file->write_size,
(unsigned long) st.st_size); (unsigned long) st.st_size);
return false; arguments->corrupted = true;
return;
} }
/* validate CRC too */ /* validate CRC too */
if (!size_only) if (!arguments->size_only)
{ {
pg_crc32 crc; pg_crc32 crc;
@@ -190,11 +236,10 @@ pgBackupValidateFiles(parray *files, const char *root, bool size_only)
if (crc != file->crc) if (crc != file->crc)
{ {
elog(WARNING, "CRC of backup file \"%s\" must be %X but %X", elog(WARNING, "CRC of backup file \"%s\" must be %X but %X",
get_relative_path(file->path, root), file->crc, crc); get_relative_path(file->path, arguments->root), file->crc, crc);
return false; arguments->corrupted = true;
return;
} }
} }
} }
return true;
} }