@@ -18,20 +18,15 @@ static void pgBackupValidateFiles(void *arg);
18
18
typedef struct
19
19
{
20
20
parray * files ;
21
- const char * root ;
22
- bool size_only ;
21
+ bool validate_crc ;
23
22
bool corrupted ;
24
23
} validate_files_args ;
25
24
26
25
/*
27
- * Validate each files in the backup with its size.
28
- * TODO: change from bool to void
29
- * TODO: understand and probably fix second argument
26
+ * Validate backup files.
30
27
*/
31
- bool
32
- pgBackupValidate (pgBackup * backup ,
33
- bool size_only ,
34
- bool for_get_timeline )
28
+ void
29
+ pgBackupValidate (pgBackup * backup )
35
30
{
36
31
char * backup_id_string ;
37
32
char base_path [MAXPGPATH ];
@@ -40,96 +35,79 @@ pgBackupValidate(pgBackup *backup,
40
35
bool corrupted = false;
41
36
pthread_t validate_threads [num_threads ];
42
37
validate_files_args * validate_threads_args [num_threads ];
38
+ int i ;
43
39
44
40
backup_id_string = base36enc (backup -> start_time );
45
- if (!for_get_timeline )
41
+
42
+ elog (LOG , "Validate backup %s" , backup_id_string );
43
+
44
+ if (backup -> backup_mode != BACKUP_MODE_FULL &&
45
+ backup -> backup_mode != BACKUP_MODE_DIFF_PAGE &&
46
+ backup -> backup_mode != BACKUP_MODE_DIFF_PTRACK )
47
+ elog (LOG , "Invalid backup_mode of backup %s" , backup_id_string );
48
+
49
+ pgBackupGetPath (backup , base_path , lengthof (base_path ), DATABASE_DIR );
50
+ pgBackupGetPath (backup , path , lengthof (path ), DATABASE_FILE_LIST );
51
+ files = dir_read_file_list (base_path , path );
52
+
53
+ /* setup threads */
54
+ for (i = 0 ; i < parray_num (files ); i ++ )
46
55
{
47
- if (backup -> backup_mode == BACKUP_MODE_FULL ||
48
- backup -> backup_mode == BACKUP_MODE_DIFF_PAGE ||
49
- backup -> backup_mode == BACKUP_MODE_DIFF_PTRACK )
50
- elog (INFO , "validate: %s backup and archive log files by %s" ,
51
- backup_id_string , (size_only ? "SIZE" : "CRC" ));
56
+ pgFile * file = (pgFile * ) parray_get (files , i );
57
+ __sync_lock_release (& file -> lock );
52
58
}
53
59
54
- if (backup -> backup_mode == BACKUP_MODE_FULL ||
55
- backup -> backup_mode == BACKUP_MODE_DIFF_PAGE ||
56
- backup -> backup_mode == BACKUP_MODE_DIFF_PTRACK )
60
+ /* Validate files */
61
+ for (i = 0 ; i < num_threads ; i ++ )
57
62
{
58
- int i ;
59
- elog (LOG , "database files..." );
60
- pgBackupGetPath (backup , base_path , lengthof (base_path ), DATABASE_DIR );
61
- pgBackupGetPath (backup , path , lengthof (path ),
62
- DATABASE_FILE_LIST );
63
- files = dir_read_file_list (base_path , path );
64
-
65
- /* setup threads */
66
- for (i = 0 ; i < parray_num (files ); i ++ )
67
- {
68
- pgFile * file = (pgFile * ) parray_get (files , i );
69
- __sync_lock_release (& file -> lock );
70
- }
63
+ validate_files_args * arg = pg_malloc (sizeof (validate_files_args ));
64
+ arg -> files = files ;
65
+ arg -> validate_crc = true;
71
66
72
- /* restore files into $PGDATA */
73
- for (i = 0 ; i < num_threads ; i ++ )
74
- {
75
- validate_files_args * arg = pg_malloc (sizeof (validate_files_args ));
76
- arg -> files = files ;
77
- arg -> root = base_path ;
78
- arg -> size_only = size_only ;
79
- arg -> corrupted = false;
80
-
81
- validate_threads_args [i ] = arg ;
82
- pthread_create (& validate_threads [i ], NULL , (void * (* )(void * )) pgBackupValidateFiles , arg );
83
- }
67
+ /* TODO Why didn't we validate checksums on restore before? */
68
+ // if (backup_subcmd == RESTORE)
69
+ // arg->validate_crc = false;
84
70
85
- /* Wait theads */
86
- for (i = 0 ; i < num_threads ; i ++ )
87
- {
88
- pthread_join (validate_threads [i ], NULL );
89
- if (validate_threads_args [i ]-> corrupted )
90
- corrupted = true;
91
- pg_free (validate_threads_args [i ]);
92
- }
93
- parray_walk (files , pgFileFree );
94
- parray_free (files );
71
+ arg -> corrupted = false;
72
+ validate_threads_args [i ] = arg ;
73
+ pthread_create (& validate_threads [i ], NULL , (void * (* )(void * )) pgBackupValidateFiles , arg );
95
74
}
96
75
97
- /* update status to OK */
98
- if (corrupted )
99
- backup -> status = BACKUP_STATUS_CORRUPT ;
100
- else
101
- backup -> status = BACKUP_STATUS_OK ;
102
- pgBackupWriteConf (backup );
76
+ /* Wait theads */
77
+ for (i = 0 ; i < num_threads ; i ++ )
78
+ {
79
+ pthread_join (validate_threads [i ], NULL );
80
+ if (validate_threads_args [i ]-> corrupted )
81
+ corrupted = true;
82
+ pg_free (validate_threads_args [i ]);
83
+ }
103
84
104
- if (corrupted )
105
- elog (WARNING , "backup %s is corrupted" , backup_id_string );
106
- else
107
- elog (LOG , "backup %s is valid" , backup_id_string );
85
+ /* cleanup */
86
+ parray_walk (files , pgFileFree );
87
+ parray_free (files );
108
88
109
- return !corrupted ;
110
- }
89
+ /* Update backup status */
90
+ backup -> status = corrupted ? BACKUP_STATUS_CORRUPT : BACKUP_STATUS_OK ;
91
+ pgBackupWriteConf (backup );
111
92
112
- static const char *
113
- get_relative_path (const char * path , const char * root )
114
- {
115
- size_t rootlen = strlen (root );
116
- if (strncmp (path , root , rootlen ) == 0 && path [rootlen ] == '/' )
117
- return path + rootlen + 1 ;
93
+ if (corrupted )
94
+ elog (WARNING , "Backup %s is corrupted" , backup_id_string );
118
95
else
119
- return path ;
96
+ elog ( LOG , "Backup %s is valid" , backup_id_string ) ;
120
97
}
121
98
122
99
/*
123
100
* Validate files in the backup with size or CRC.
101
+ * NOTE: If file is not valid, do not use ERROR log message,
102
+ * rather throw a WARNING and set arguments->corrupted = true.
103
+ * This is necessary to update backup status.
124
104
*/
125
105
static void
126
106
pgBackupValidateFiles (void * arg )
127
107
{
128
108
int i ;
129
-
130
109
validate_files_args * arguments = (validate_files_args * )arg ;
131
110
132
-
133
111
for (i = 0 ; i < parray_num (arguments -> files ); i ++ )
134
112
{
135
113
struct stat st ;
@@ -139,51 +117,56 @@ pgBackupValidateFiles(void *arg)
139
117
continue ;
140
118
141
119
if (interrupted )
142
- elog (ERROR , "interrupted during validate" );
143
-
144
- /* skipped backup while differential backup */
145
- /* NOTE We don't compute checksums for compressed data,
146
- * so skip it too */
147
- if (file -> write_size == BYTES_INVALID
148
- || !S_ISREG (file -> mode )
149
- || file -> generation != -1 )
120
+ elog (ERROR , "Interrupted during validate" );
121
+
122
+ /* Validate only regular files */
123
+ if (!S_ISREG (file -> mode ))
124
+ continue ;
125
+ /*
126
+ * Skip files which has no data, because they
127
+ * haven't changed between backups.
128
+ */
129
+ if (file -> write_size == BYTES_INVALID )
130
+ continue ;
131
+ /* We don't compute checksums for compressed data, so skip them
132
+ * TODO Add checksums to compressed files.
133
+ */
134
+ if (file -> generation != -1 )
150
135
continue ;
151
136
152
137
/* print progress */
153
- elog (LOG , "(%d/%lu) %s" , i + 1 , ( unsigned long ) parray_num ( arguments -> files ) ,
154
- get_relative_path ( file -> path , arguments -> root ) );
138
+ elog (LOG , "Validate files: (%d/%lu) %s" ,
139
+ i + 1 , ( unsigned long ) parray_num ( arguments -> files ), file -> path );
155
140
156
- /* always validate file size */
157
141
if (stat (file -> path , & st ) == -1 )
158
142
{
159
143
if (errno == ENOENT )
160
- elog (WARNING , "backup file \"%s\" vanished " , file -> path );
144
+ elog (WARNING , "Backup file \"%s\" is not found " , file -> path );
161
145
else
162
- elog (ERROR , "cannot stat backup file \"%s\": %s" ,
163
- get_relative_path ( file -> path , arguments -> root ) , strerror (errno ));
146
+ elog (WARNING , "Cannot stat backup file \"%s\": %s" ,
147
+ file -> path , strerror (errno ));
164
148
arguments -> corrupted = true;
165
149
return ;
166
150
}
151
+
167
152
if (file -> write_size != st .st_size )
168
153
{
169
- elog (WARNING , "size of backup file \"%s\" must be %lu but %lu" ,
170
- get_relative_path (file -> path , arguments -> root ),
171
- (unsigned long ) file -> write_size ,
172
- (unsigned long ) st .st_size );
154
+ elog (WARNING , "Invalid size of backup file \"%s\" : %lu. Expected %lu" ,
155
+ file -> path , (unsigned long ) file -> write_size ,
156
+ (unsigned long ) st .st_size );
173
157
arguments -> corrupted = true;
174
158
return ;
175
159
}
176
160
177
- /* validate CRC too */
178
- if (!arguments -> size_only )
161
+ if (arguments -> validate_crc )
179
162
{
180
163
pg_crc32 crc ;
181
164
182
165
crc = pgFileGetCRC (file );
183
166
if (crc != file -> crc )
184
167
{
185
- elog (WARNING , "CRC of backup file \"%s\" must be %X but %X" ,
186
- get_relative_path ( file -> path , arguments -> root ) , file -> crc , crc );
168
+ elog (WARNING , "Invalid CRC of backup file \"%s\" : %X. Expected %X" ,
169
+ file -> path , file -> crc , crc );
187
170
arguments -> corrupted = true;
188
171
return ;
189
172
}
0 commit comments