10
10
#include "pg_probackup.h"
11
11
12
12
#include <sys/stat.h>
13
+ #include <pthread.h>
13
14
14
- static bool pgBackupValidateFiles (parray * files , const char * root , bool size_only );
15
+ static void pgBackupValidateFiles (void * arg );
16
+
17
+ typedef struct
18
+ {
19
+ parray * files ;
20
+ const char * root ;
21
+ bool size_only ;
22
+ bool corrupted ;
23
+ } validate_files_args ;
15
24
16
25
/*
17
26
* Validate files in the backup and update its status to OK.
@@ -85,6 +94,8 @@ pgBackupValidate(pgBackup *backup,
85
94
char path [MAXPGPATH ];
86
95
parray * files ;
87
96
bool corrupted = false;
97
+ pthread_t validate_threads [num_threads ];
98
+ validate_files_args * validate_threads_args [num_threads ];
88
99
89
100
time2iso (timestamp , lengthof (timestamp ), backup -> recovery_time );
90
101
if (!for_get_timeline )
@@ -102,13 +113,41 @@ pgBackupValidate(pgBackup *backup,
102
113
backup -> backup_mode == BACKUP_MODE_DIFF_PAGE ||
103
114
backup -> backup_mode == BACKUP_MODE_DIFF_PTRACK )
104
115
{
116
+ int i ;
105
117
elog (LOG , "database files..." );
106
118
pgBackupGetPath (backup , base_path , lengthof (base_path ), DATABASE_DIR );
107
119
pgBackupGetPath (backup , path , lengthof (path ),
108
120
DATABASE_FILE_LIST );
109
121
files = dir_read_file_list (base_path , path );
110
- if (!pgBackupValidateFiles (files , base_path , size_only ))
111
- corrupted = true;
122
+
123
+ /* setup threads */
124
+ for (i = 0 ; i < parray_num (files ); i ++ )
125
+ {
126
+ pgFile * file = (pgFile * ) parray_get (files , i );
127
+ __sync_lock_release (& file -> lock );
128
+ }
129
+
130
+ /* restore files into $PGDATA */
131
+ for (i = 0 ; i < num_threads ; i ++ )
132
+ {
133
+ validate_files_args * arg = pg_malloc (sizeof (validate_files_args ));
134
+ arg -> files = files ;
135
+ arg -> root = base_path ;
136
+ arg -> size_only = size_only ;
137
+ arg -> corrupted = false;
138
+
139
+ validate_threads_args [i ] = arg ;
140
+ pthread_create (& validate_threads [i ], NULL , (void * (* )(void * )) pgBackupValidateFiles , arg );
141
+ }
142
+
143
+ /* Wait theads */
144
+ for (i = 0 ; i < num_threads ; i ++ )
145
+ {
146
+ pthread_join (validate_threads [i ], NULL );
147
+ if (validate_threads_args [i ]-> corrupted )
148
+ corrupted = true;
149
+ pg_free (validate_threads_args [i ]);
150
+ }
112
151
parray_walk (files , pgFileFree );
113
152
parray_free (files );
114
153
}
@@ -140,16 +179,21 @@ get_relative_path(const char *path, const char *root)
140
179
/*
141
180
* Validate files in the backup with size or CRC.
142
181
*/
143
- static bool
144
- pgBackupValidateFiles (parray * files , const char * root , bool size_only )
182
+ static void
183
+ pgBackupValidateFiles (void * arg )
145
184
{
146
185
int i ;
147
186
148
- for (i = 0 ; i < parray_num (files ); i ++ )
187
+ validate_files_args * arguments = (validate_files_args * )arg ;
188
+
189
+
190
+ for (i = 0 ; i < parray_num (arguments -> files ); i ++ )
149
191
{
150
192
struct stat st ;
151
193
152
- pgFile * file = (pgFile * ) parray_get (files , i );
194
+ pgFile * file = (pgFile * ) parray_get (arguments -> files , i );
195
+ if (__sync_lock_test_and_set (& file -> lock , 1 ) != 0 )
196
+ continue ;
153
197
154
198
if (interrupted )
155
199
elog (ERROR , "interrupted during validate" );
@@ -159,8 +203,8 @@ pgBackupValidateFiles(parray *files, const char *root, bool size_only)
159
203
continue ;
160
204
161
205
/* print progress */
162
- elog (LOG , "(%d/%lu) %s" , i + 1 , (unsigned long ) parray_num (files ),
163
- get_relative_path (file -> path , root ));
206
+ elog (LOG , "(%d/%lu) %s" , i + 1 , (unsigned long ) parray_num (arguments -> files ),
207
+ get_relative_path (file -> path , arguments -> root ));
164
208
165
209
/* always validate file size */
166
210
if (stat (file -> path , & st ) == -1 )
@@ -169,32 +213,33 @@ pgBackupValidateFiles(parray *files, const char *root, bool size_only)
169
213
elog (WARNING , "backup file \"%s\" vanished" , file -> path );
170
214
else
171
215
elog (ERROR , "cannot stat backup file \"%s\": %s" ,
172
- get_relative_path (file -> path , root ), strerror (errno ));
173
- return false;
216
+ get_relative_path (file -> path , arguments -> root ), strerror (errno ));
217
+ arguments -> corrupted = true;
218
+ return ;
174
219
}
175
220
if (file -> write_size != st .st_size )
176
221
{
177
222
elog (WARNING , "size of backup file \"%s\" must be %lu but %lu" ,
178
- get_relative_path (file -> path , root ),
223
+ get_relative_path (file -> path , arguments -> root ),
179
224
(unsigned long ) file -> write_size ,
180
225
(unsigned long ) st .st_size );
181
- return false;
226
+ arguments -> corrupted = true;
227
+ return ;
182
228
}
183
229
184
230
/* validate CRC too */
185
- if (!size_only )
231
+ if (!arguments -> size_only )
186
232
{
187
233
pg_crc32 crc ;
188
234
189
235
crc = pgFileGetCRC (file );
190
236
if (crc != file -> crc )
191
237
{
192
238
elog (WARNING , "CRC of backup file \"%s\" must be %X but %X" ,
193
- get_relative_path (file -> path , root ), file -> crc , crc );
194
- return false;
239
+ get_relative_path (file -> path , arguments -> root ), file -> crc , crc );
240
+ arguments -> corrupted = true;
241
+ return ;
195
242
}
196
243
}
197
244
}
198
-
199
- return true;
200
245
}
0 commit comments