12
12
13
13
#include <sys/stat.h>
14
14
#include <pthread.h>
15
+ #include <dirent.h>
15
16
16
17
static void pgBackupValidateFiles (void * arg );
18
+ static void do_validate_instance (void );
19
+
20
+ static bool corrupted_backup_found = false;
17
21
18
22
typedef struct
19
23
{
@@ -38,6 +42,14 @@ pgBackupValidate(pgBackup *backup)
38
42
39
43
backup_id_string = base36enc (backup -> start_time );
40
44
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
+
41
53
elog (LOG , "Validate backup %s" , backup_id_string );
42
54
43
55
if (backup -> backup_mode != BACKUP_MODE_FULL &&
@@ -161,3 +173,119 @@ pgBackupValidateFiles(void *arg)
161
173
}
162
174
}
163
175
}
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