Skip to content

Commit 9caafbd

Browse files
committed
validate without options checks all backups in the backup catalog. If --instance option is provided, validate only backups of this instance
1 parent bf40f1f commit 9caafbd

File tree

4 files changed

+138
-7
lines changed

4 files changed

+138
-7
lines changed

help.c

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -97,8 +97,8 @@ help_pg_probackup(void)
9797
printf(_(" [--time=time|--xid=xid [--inclusive=boolean]]\n"));
9898
printf(_(" [--timeline=timeline] [-T OLDDIR=NEWDIR]\n"));
9999

100-
printf(_("\n %s validate -B backup-dir --instance=instance_name\n"), PROGRAM_NAME);
101-
printf(_(" [-D pgdata-dir] [-i backup-id] [--progress]\n"));
100+
printf(_("\n %s validate -B backup-dir [--instance=instance_name]\n"), PROGRAM_NAME);
101+
printf(_(" [-i backup-id] [--progress]\n"));
102102
printf(_(" [--time=time|--xid=xid [--inclusive=boolean]]\n"));
103103
printf(_(" [--timeline=timeline]\n"));
104104

@@ -206,14 +206,13 @@ help_restore(void)
206206
static void
207207
help_validate(void)
208208
{
209-
printf(_("%s validate -B backup-dir --instance=instance_name\n"), PROGRAM_NAME);
210-
printf(_(" [-D pgdata-dir] [-i backup-id] [--progress]\n"));
209+
printf(_("%s validate -B backup-dir [--instance=instance_name]\n"), PROGRAM_NAME);
210+
printf(_(" [-i backup-id] [--progress]\n"));
211211
printf(_(" [--time=time|--xid=xid [--inclusive=boolean]]\n"));
212212
printf(_(" [--timeline=timeline]\n\n"));
213213

214214
printf(_(" -B, --backup-path=backup-path location of the backup storage area\n"));
215215
printf(_(" --instance=instance_name name of the instance\n"));
216-
printf(_(" -D, --pgdata=pgdata-dir location of the database storage area\n"));
217216
printf(_(" -i, --backup-id=backup-id backup to validate\n"));
218217

219218
printf(_(" --progress show progress\n"));

pg_probackup.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -253,7 +253,7 @@ main(int argc, char *argv[])
253253
elog(ERROR, "-B, --backup-path must be a path to directory");
254254

255255
/* Option --instance is required for all commands except init and show */
256-
if (backup_subcmd != INIT && backup_subcmd != SHOW)
256+
if (backup_subcmd != INIT && backup_subcmd != SHOW && backup_subcmd != VALIDATE)
257257
{
258258
if (instance_name == NULL)
259259
elog(ERROR, "required parameter not specified: --instance");
@@ -378,7 +378,10 @@ main(int argc, char *argv[])
378378
target_inclusive, target_tli,
379379
true);
380380
case VALIDATE:
381-
return do_restore_or_validate(current.backup_id,
381+
if (current.backup_id == 0 && target_time == 0 && target_xid == 0)
382+
return do_validate_all();
383+
else
384+
return do_restore_or_validate(current.backup_id,
382385
target_time, target_xid,
383386
target_inclusive, target_tli,
384387
false);

pg_probackup.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -368,6 +368,7 @@ extern void help_command(char *command);
368368

369369
/* in validate.c */
370370
extern void pgBackupValidate(pgBackup* backup);
371+
extern int do_validate_all(void);
371372

372373
/* in catalog.c */
373374
extern pgBackup *read_backup(time_t timestamp);

validate.c

Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,12 @@
1212

1313
#include <sys/stat.h>
1414
#include <pthread.h>
15+
#include <dirent.h>
1516

1617
static void pgBackupValidateFiles(void *arg);
18+
static void do_validate_instance(void);
19+
20+
static bool corrupted_backup_found = false;
1721

1822
typedef struct
1923
{
@@ -38,6 +42,14 @@ pgBackupValidate(pgBackup *backup)
3842

3943
backup_id_string = base36enc(backup->start_time);
4044

45+
if (backup->status != BACKUP_STATUS_OK &&
46+
backup->status != BACKUP_STATUS_DONE)
47+
{
48+
elog(INFO, "Backup %s has status %s. Skip validation.",
49+
backup_id_string, status2str(backup->status));
50+
return;
51+
}
52+
4153
elog(LOG, "Validate backup %s", backup_id_string);
4254

4355
if (backup->backup_mode != BACKUP_MODE_FULL &&
@@ -161,3 +173,119 @@ pgBackupValidateFiles(void *arg)
161173
}
162174
}
163175
}
176+
177+
/*
178+
* Validate all backups in the backup catalog.
179+
* If --instance option was provided, validate only backups of this instance.
180+
*/
181+
int
182+
do_validate_all(void)
183+
{
184+
if (instance_name == NULL)
185+
{
186+
/* Show list of instances */
187+
char path[MAXPGPATH];
188+
DIR *dir;
189+
struct dirent *dent;
190+
191+
/* open directory and list contents */
192+
join_path_components(path, backup_path, BACKUPS_DIR);
193+
dir = opendir(path);
194+
if (dir == NULL)
195+
elog(ERROR, "cannot open directory \"%s\": %s", path, strerror(errno));
196+
197+
errno = 0;
198+
while ((dent = readdir(dir)))
199+
{
200+
char child[MAXPGPATH];
201+
struct stat st;
202+
203+
/* skip entries point current dir or parent dir */
204+
if (strcmp(dent->d_name, ".") == 0 ||
205+
strcmp(dent->d_name, "..") == 0)
206+
continue;
207+
208+
join_path_components(child, path, dent->d_name);
209+
210+
if (lstat(child, &st) == -1)
211+
elog(ERROR, "cannot stat file \"%s\": %s", child, strerror(errno));
212+
213+
if (!S_ISDIR(st.st_mode))
214+
continue;
215+
216+
instance_name = dent->d_name;
217+
sprintf(backup_instance_path, "%s/%s/%s", backup_path, BACKUPS_DIR, instance_name);
218+
sprintf(arclog_path, "%s/%s/%s", backup_path, "wal", instance_name);
219+
do_validate_instance();
220+
}
221+
}
222+
else
223+
{
224+
do_validate_instance();
225+
}
226+
227+
if (corrupted_backup_found)
228+
elog(INFO, "Some backups are not valid");
229+
else
230+
elog(INFO, "All backups are valid");
231+
232+
return 0;
233+
}
234+
235+
/*
236+
* Validate all backups in the given instance of the backup catalog.
237+
*/
238+
static void
239+
do_validate_instance(void)
240+
{
241+
int i, j;
242+
parray *backups;
243+
pgBackup *current_backup = NULL;
244+
pgBackup *base_full_backup = NULL;
245+
246+
elog(INFO, "Validate backups of the instance '%s'", instance_name);
247+
248+
/* Get exclusive lock of backup catalog */
249+
catalog_lock();
250+
251+
/* Get list of all backups sorted in order of descending start time */
252+
backups = catalog_get_backup_list(INVALID_BACKUP_ID);
253+
if (backups == NULL)
254+
elog(ERROR, "Failed to get backup list.");
255+
256+
/* Valiate each backup along with its xlog files. */
257+
for (i = 0; i < parray_num(backups); i++)
258+
{
259+
current_backup = (pgBackup *) parray_get(backups, i);
260+
elog(INFO, "Validate backup %s", base36enc(current_backup->start_time));
261+
262+
if (current_backup->backup_mode != BACKUP_MODE_FULL)
263+
{
264+
j = i+1;
265+
do
266+
{
267+
base_full_backup = (pgBackup *) parray_get(backups, j);
268+
j++;
269+
}
270+
while (base_full_backup->backup_mode != BACKUP_MODE_FULL
271+
&& j < parray_num(backups));
272+
}
273+
274+
pgBackupValidate(current_backup);
275+
276+
/* There is no point in wal validation for corrupted backup */
277+
if (current_backup->status == BACKUP_STATUS_OK)
278+
{
279+
/* Validate corresponding WAL files */
280+
validate_wal(current_backup, arclog_path, 0,
281+
0, base_full_backup->tli);
282+
}
283+
284+
if (current_backup->status != BACKUP_STATUS_OK)
285+
corrupted_backup_found = true;
286+
}
287+
288+
/* cleanup */
289+
parray_walk(backups, pgBackupFree);
290+
parray_free(backups);
291+
}

0 commit comments

Comments
 (0)