@@ -31,8 +31,8 @@ typedef struct DataPage
3131 char data [BLCKSZ ];
3232} DataPage ;
3333
34- static BackupPageHeader2 * get_data_file_headers (const char * fullpath , pgFile * file , uint32 backup_version );
35- static void write_page_headers (BackupPageHeader2 * headers , pgFile * file , const char * to_fullpath );
34+ static BackupPageHeader2 * get_data_file_headers (HeaderMap * hdr_map , pgFile * file , uint32 backup_version );
35+ static void write_page_headers (BackupPageHeader2 * headers , pgFile * file , HeaderMap * hdr_map );
3636static bool get_compressed_page_meta (FILE * in , const char * fullpath , BackupPageHeader * bph ,
3737 pg_crc32 * crc , bool use_crc32c );
3838
@@ -537,7 +537,8 @@ backup_data_file(ConnectionArgs* conn_arg, pgFile *file,
537537 const char * from_fullpath , const char * to_fullpath ,
538538 XLogRecPtr prev_backup_start_lsn , BackupMode backup_mode ,
539539 CompressAlg calg , int clevel , uint32 checksum_version ,
540- int ptrack_version_num , const char * ptrack_schema , bool missing_ok )
540+ int ptrack_version_num , const char * ptrack_schema ,
541+ HeaderMap * hdr_map , bool missing_ok )
541542{
542543 int rc ;
543544 bool use_pagemap ;
@@ -684,7 +685,7 @@ backup_data_file(ConnectionArgs* conn_arg, pgFile *file,
684685 FIN_FILE_CRC32 (true, file -> crc );
685686
686687 /* dump page headers */
687- write_page_headers (headers , file , to_fullpath );
688+ write_page_headers (headers , file , hdr_map );
688689
689690 pg_free (errmsg );
690691 pg_free (file -> pagemap .bitmap );
@@ -740,7 +741,7 @@ backup_non_data_file(pgFile *file, pgFile *prev_file,
740741size_t
741742restore_data_file (parray * parent_chain , pgFile * dest_file , FILE * out ,
742743 const char * to_fullpath , bool use_bitmap , PageState * checksum_map ,
743- XLogRecPtr shift_lsn , datapagemap_t * lsn_map , bool is_merge )
744+ XLogRecPtr shift_lsn , datapagemap_t * lsn_map , bool use_headers )
744745{
745746 size_t total_write_len = 0 ;
746747 char * in_buf = pgut_malloc (STDIO_BUFSIZE );
@@ -818,10 +819,11 @@ restore_data_file(parray *parent_chain, pgFile *dest_file, FILE *out,
818819 setvbuf (in , in_buf , _IOFBF , STDIO_BUFSIZE );
819820
820821 /* get headers for this file */
821- if (!is_merge )
822- headers = get_data_file_headers (from_fullpath , tmp_file , parse_program_version (backup -> program_version ));
822+ if (use_headers )
823+ headers = get_data_file_headers (& (backup -> hdr_map ), tmp_file ,
824+ parse_program_version (backup -> program_version ));
823825
824- if (! is_merge && !headers && tmp_file -> n_headers > 0 )
826+ if (use_headers && !headers && tmp_file -> n_headers > 0 )
825827 elog (ERROR , "Failed to get headers for file \"%s\"" , from_fullpath );
826828
827829 /*
@@ -1574,7 +1576,7 @@ check_data_file(ConnectionArgs *arguments, pgFile *file,
15741576/* Valiate pages of datafile in backup one by one */
15751577bool
15761578validate_file_pages (pgFile * file , const char * fullpath , XLogRecPtr stop_lsn ,
1577- uint32 checksum_version , uint32 backup_version )
1579+ uint32 checksum_version , uint32 backup_version , HeaderMap * hdr_map )
15781580{
15791581 size_t read_len = 0 ;
15801582 bool is_valid = true;
@@ -1595,7 +1597,7 @@ validate_file_pages(pgFile *file, const char *fullpath, XLogRecPtr stop_lsn,
15951597 elog (ERROR , "Cannot open file \"%s\": %s" ,
15961598 fullpath , strerror (errno ));
15971599
1598- headers = get_data_file_headers (fullpath , file , backup_version );
1600+ headers = get_data_file_headers (hdr_map , file , backup_version );
15991601
16001602 if (!headers && file -> n_headers > 0 )
16011603 elog (ERROR , "Failed to get headers for file \"%s\"" , fullpath );
@@ -2120,12 +2122,11 @@ send_pages(ConnectionArgs* conn_arg, const char *to_fullpath, const char *from_f
21202122 * array of headers.
21212123 */
21222124BackupPageHeader2 *
2123- get_data_file_headers (const char * fullpath , pgFile * file , uint32 backup_version )
2125+ get_data_file_headers (HeaderMap * hdr_map , pgFile * file , uint32 backup_version )
21242126{
2125- int len ;
2126- FILE * in = NULL ;
2127+ size_t read_len = 0 ;
2128+ FILE * in = NULL ;
21272129 pg_crc32 hdr_crc ;
2128- char fullpath_hdr [MAXPGPATH ];
21292130 BackupPageHeader2 * headers = NULL ;
21302131
21312132 if (backup_version < 20400 )
@@ -2134,70 +2135,83 @@ get_data_file_headers(const char *fullpath, pgFile *file, uint32 backup_version)
21342135 if (file -> n_headers <= 0 )
21352136 return NULL ;
21362137
2137- snprintf (fullpath_hdr , MAXPGPATH , "%s_hdr" , fullpath );
2138-
2139- in = fopen (fullpath_hdr , PG_BINARY_R );
2138+ in = fopen (hdr_map -> path , PG_BINARY_R );
21402139
21412140 if (!in )
2142- elog (ERROR , "Cannot open header file \"%s\": %s" , fullpath_hdr , strerror (errno ));
2141+ elog (ERROR , "Cannot open header file \"%s\": %s" , hdr_map -> path , strerror (errno ));
2142+
2143+ /* disable buffering */
2144+ setvbuf (in , NULL , _IONBF , BUFSIZ );
2145+
2146+ if (fseek (in , file -> hdr_off , SEEK_SET ))
2147+ elog (ERROR , "Cannot seek to position %lu in header map \"%s\": %s" ,
2148+ file -> hdr_off , hdr_map -> path , strerror (errno ));
21432149
21442150 /*
21452151 * the actual number of headers in header file is n+1, last one is a dummy header,
21462152 * used for calculation of compressed_size for actual last header.
21472153 */
2148- len = (file -> n_headers + 1 ) * sizeof (BackupPageHeader2 );
2149- headers = pgut_malloc (len );
2154+ read_len = (file -> n_headers + 1 ) * sizeof (BackupPageHeader2 );
2155+ headers = pgut_malloc (read_len );
21502156
2151- if (fread (headers , 1 , len , in ) != len )
2152- elog (ERROR , "Cannot read header file \"%s\": %s" , fullpath_hdr , strerror (errno ));
2157+ if (fread (headers , 1 , read_len , in ) != read_len )
2158+ elog (ERROR , "Cannot read header file \"%s\": %s" , hdr_map -> path , strerror (errno ));
21532159
21542160 /* validate checksum */
21552161 INIT_FILE_CRC32 (true, hdr_crc );
2156- COMP_FILE_CRC32 (true, hdr_crc , headers , len );
2162+ COMP_FILE_CRC32 (true, hdr_crc , headers , read_len );
21572163 FIN_FILE_CRC32 (true, hdr_crc );
21582164
21592165 if (hdr_crc != file -> hdr_crc )
21602166 elog (ERROR , "Header file crc mismatch \"%s\", current: %u, expected: %u" ,
2161- fullpath_hdr , hdr_crc , file -> hdr_crc );
2167+ hdr_map -> path , hdr_crc , file -> hdr_crc );
21622168
21632169 if (fclose (in ))
2164- elog (ERROR , "Cannot close header file \"%s\": %s" , fullpath_hdr , strerror (errno ));
2170+ elog (ERROR , "Cannot close header file \"%s\": %s" , hdr_map -> path , strerror (errno ));
21652171
21662172 return headers ;
21672173}
21682174
21692175void
2170- write_page_headers (BackupPageHeader2 * headers , pgFile * file , const char * to_fullpath )
2176+ write_page_headers (BackupPageHeader2 * headers , pgFile * file , HeaderMap * hdr_map )
21712177{
2172- FILE * out = NULL ;
2173- size_t hdr_size = 0 ;
2174- char to_fullpath_hdr [MAXPGPATH ];
2178+ size_t read_len = 0 ;
21752179
21762180 if (file -> n_headers <= 0 )
21772181 return ;
21782182
2179- snprintf (to_fullpath_hdr , MAXPGPATH , "%s_hdr" , to_fullpath );
2183+ /* writing to header map must be serialized */
2184+ pthread_lock (& (hdr_map -> mutex )); /* what if we crash while trying to obtain mutex? */
21802185
2181- out = fopen (to_fullpath_hdr , PG_BINARY_W );
2182- if (out == NULL )
2183- elog (ERROR , "Cannot open header file \"%s\": %s" ,
2184- to_fullpath , strerror (errno ));
2185-
2186- /* update file permission */
2187- if (chmod (to_fullpath_hdr , FILE_PERMISSION ) == -1 )
2188- elog (ERROR , "Cannot change mode of \"%s\": %s" , to_fullpath ,
2189- strerror (errno ));
2186+ if (!hdr_map -> fp )
2187+ {
2188+ hdr_map -> fp = fopen (hdr_map -> path , PG_BINARY_W );
2189+ if (hdr_map -> fp == NULL )
2190+ elog (ERROR , "Cannot open header file \"%s\": %s" ,
2191+ hdr_map -> path , strerror (errno ));
2192+
2193+ /* disable buffering for header file */
2194+ setvbuf (hdr_map -> fp , NULL , _IONBF , BUFSIZ );
2195+
2196+ /* update file permission */
2197+ if (chmod (hdr_map -> path , FILE_PERMISSION ) == -1 )
2198+ elog (ERROR , "Cannot change mode of \"%s\": %s" , hdr_map -> path ,
2199+ strerror (errno ));
2200+
2201+ file -> hdr_off = 0 ;
2202+ }
2203+ else
2204+ file -> hdr_off = ftell (hdr_map -> fp ); /* TODO: replace by counter */
21902205
2191- hdr_size = (file -> n_headers + 1 ) * sizeof (BackupPageHeader2 );
2206+ read_len = (file -> n_headers + 1 ) * sizeof (BackupPageHeader2 );
21922207
21932208 /* calculate checksums */
21942209 INIT_FILE_CRC32 (true, file -> hdr_crc );
2195- COMP_FILE_CRC32 (true, file -> hdr_crc , headers , hdr_size );
2210+ COMP_FILE_CRC32 (true, file -> hdr_crc , headers , read_len );
21962211 FIN_FILE_CRC32 (true, file -> hdr_crc );
21972212
2198- if (fwrite (headers , 1 , hdr_size , out ) != hdr_size )
2199- elog (ERROR , "Cannot write to file \"%s\": %s" , to_fullpath_hdr , strerror (errno ));
2213+ if (fwrite (headers , 1 , read_len , hdr_map -> fp ) != read_len )
2214+ elog (ERROR , "Cannot write to file \"%s\": %s" , hdr_map -> path , strerror (errno ));
22002215
2201- if (fclose (out ))
2202- elog (ERROR , "Cannot close file \"%s\": %s" , to_fullpath_hdr , strerror (errno ));
2216+ pthread_mutex_unlock (& (hdr_map -> mutex ));
22032217}
0 commit comments