1010#include "pg_probackup.h"
1111
1212#include <sys/stat.h>
13+ #include <pthread.h>
1314
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 ;
1524
1625/*
1726 * Validate files in the backup and update its status to OK.
@@ -85,6 +94,8 @@ pgBackupValidate(pgBackup *backup,
8594char path [MAXPGPATH ];
8695parray * files ;
8796bool corrupted = false;
97+ pthread_t validate_threads [num_threads ];
98+ validate_files_args * validate_threads_args [num_threads ];
8899
89100time2iso (timestamp ,lengthof (timestamp ),backup -> recovery_time );
90101if (!for_get_timeline )
@@ -102,13 +113,41 @@ pgBackupValidate(pgBackup *backup,
102113backup -> backup_mode == BACKUP_MODE_DIFF_PAGE ||
103114backup -> backup_mode == BACKUP_MODE_DIFF_PTRACK )
104115{
116+ int i ;
105117elog (LOG ,"database files..." );
106118pgBackupGetPath (backup ,base_path ,lengthof (base_path ),DATABASE_DIR );
107119pgBackupGetPath (backup ,path ,lengthof (path ),
108120DATABASE_FILE_LIST );
109121files = 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+ }
112151parray_walk (files ,pgFileFree );
113152parray_free (files );
114153}
@@ -140,16 +179,21 @@ get_relative_path(const char *path, const char *root)
140179/*
141180 * Validate files in the backup with size or CRC.
142181 */
143- static bool
144- pgBackupValidateFiles (parray * files , const char * root , bool size_only )
182+ static void
183+ pgBackupValidateFiles (void * arg )
145184{
146185int i ;
147186
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 ++ )
149191{
150192struct stat st ;
151193
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 ;
153197
154198if (interrupted )
155199elog (ERROR ,"interrupted during validate" );
@@ -159,8 +203,8 @@ pgBackupValidateFiles(parray *files, const char *root, bool size_only)
159203continue ;
160204
161205/* 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 ));
164208
165209/* always validate file size */
166210if (stat (file -> path ,& st )== -1 )
@@ -169,32 +213,33 @@ pgBackupValidateFiles(parray *files, const char *root, bool size_only)
169213elog (WARNING ,"backup file \"%s\" vanished" ,file -> path );
170214else
171215elog (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 ;
174219}
175220if (file -> write_size != st .st_size )
176221{
177222elog (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 ),
179224(unsigned long )file -> write_size ,
180225(unsigned long )st .st_size );
181- return false;
226+ arguments -> corrupted = true;
227+ return ;
182228}
183229
184230/* validate CRC too */
185- if (!size_only )
231+ if (!arguments -> size_only )
186232{
187233pg_crc32 crc ;
188234
189235crc = pgFileGetCRC (file );
190236if (crc != file -> crc )
191237{
192238elog (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 ;
195242}
196243}
197244}
198-
199- return true;
200245}