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
}