@@ -31,8 +31,8 @@ typedef struct DataPage
31
31
char data [BLCKSZ ];
32
32
} DataPage ;
33
33
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 );
36
36
static bool get_compressed_page_meta (FILE * in , const char * fullpath , BackupPageHeader * bph ,
37
37
pg_crc32 * crc , bool use_crc32c );
38
38
@@ -537,7 +537,8 @@ backup_data_file(ConnectionArgs* conn_arg, pgFile *file,
537
537
const char * from_fullpath , const char * to_fullpath ,
538
538
XLogRecPtr prev_backup_start_lsn , BackupMode backup_mode ,
539
539
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 )
541
542
{
542
543
int rc ;
543
544
bool use_pagemap ;
@@ -684,7 +685,7 @@ backup_data_file(ConnectionArgs* conn_arg, pgFile *file,
684
685
FIN_FILE_CRC32 (true, file -> crc );
685
686
686
687
/* dump page headers */
687
- write_page_headers (headers , file , to_fullpath );
688
+ write_page_headers (headers , file , hdr_map );
688
689
689
690
pg_free (errmsg );
690
691
pg_free (file -> pagemap .bitmap );
@@ -740,7 +741,7 @@ backup_non_data_file(pgFile *file, pgFile *prev_file,
740
741
size_t
741
742
restore_data_file (parray * parent_chain , pgFile * dest_file , FILE * out ,
742
743
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 )
744
745
{
745
746
size_t total_write_len = 0 ;
746
747
char * in_buf = pgut_malloc (STDIO_BUFSIZE );
@@ -818,10 +819,11 @@ restore_data_file(parray *parent_chain, pgFile *dest_file, FILE *out,
818
819
setvbuf (in , in_buf , _IOFBF , STDIO_BUFSIZE );
819
820
820
821
/* 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 ));
823
825
824
- if (! is_merge && !headers && tmp_file -> n_headers > 0 )
826
+ if (use_headers && !headers && tmp_file -> n_headers > 0 )
825
827
elog (ERROR , "Failed to get headers for file \"%s\"" , from_fullpath );
826
828
827
829
/*
@@ -1574,7 +1576,7 @@ check_data_file(ConnectionArgs *arguments, pgFile *file,
1574
1576
/* Valiate pages of datafile in backup one by one */
1575
1577
bool
1576
1578
validate_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 )
1578
1580
{
1579
1581
size_t read_len = 0 ;
1580
1582
bool is_valid = true;
@@ -1595,7 +1597,7 @@ validate_file_pages(pgFile *file, const char *fullpath, XLogRecPtr stop_lsn,
1595
1597
elog (ERROR , "Cannot open file \"%s\": %s" ,
1596
1598
fullpath , strerror (errno ));
1597
1599
1598
- headers = get_data_file_headers (fullpath , file , backup_version );
1600
+ headers = get_data_file_headers (hdr_map , file , backup_version );
1599
1601
1600
1602
if (!headers && file -> n_headers > 0 )
1601
1603
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
2120
2122
* array of headers.
2121
2123
*/
2122
2124
BackupPageHeader2 *
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 )
2124
2126
{
2125
- int len ;
2126
- FILE * in = NULL ;
2127
+ size_t read_len = 0 ;
2128
+ FILE * in = NULL ;
2127
2129
pg_crc32 hdr_crc ;
2128
- char fullpath_hdr [MAXPGPATH ];
2129
2130
BackupPageHeader2 * headers = NULL ;
2130
2131
2131
2132
if (backup_version < 20400 )
@@ -2134,70 +2135,83 @@ get_data_file_headers(const char *fullpath, pgFile *file, uint32 backup_version)
2134
2135
if (file -> n_headers <= 0 )
2135
2136
return NULL ;
2136
2137
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 );
2140
2139
2141
2140
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 ));
2143
2149
2144
2150
/*
2145
2151
* the actual number of headers in header file is n+1, last one is a dummy header,
2146
2152
* used for calculation of compressed_size for actual last header.
2147
2153
*/
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 );
2150
2156
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 ));
2153
2159
2154
2160
/* validate checksum */
2155
2161
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 );
2157
2163
FIN_FILE_CRC32 (true, hdr_crc );
2158
2164
2159
2165
if (hdr_crc != file -> hdr_crc )
2160
2166
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 );
2162
2168
2163
2169
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 ));
2165
2171
2166
2172
return headers ;
2167
2173
}
2168
2174
2169
2175
void
2170
- write_page_headers (BackupPageHeader2 * headers , pgFile * file , const char * to_fullpath )
2176
+ write_page_headers (BackupPageHeader2 * headers , pgFile * file , HeaderMap * hdr_map )
2171
2177
{
2172
- FILE * out = NULL ;
2173
- size_t hdr_size = 0 ;
2174
- char to_fullpath_hdr [MAXPGPATH ];
2178
+ size_t read_len = 0 ;
2175
2179
2176
2180
if (file -> n_headers <= 0 )
2177
2181
return ;
2178
2182
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? */
2180
2185
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 */
2190
2205
2191
- hdr_size = (file -> n_headers + 1 ) * sizeof (BackupPageHeader2 );
2206
+ read_len = (file -> n_headers + 1 ) * sizeof (BackupPageHeader2 );
2192
2207
2193
2208
/* calculate checksums */
2194
2209
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 );
2196
2211
FIN_FILE_CRC32 (true, file -> hdr_crc );
2197
2212
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 ));
2200
2215
2201
- if (fclose (out ))
2202
- elog (ERROR , "Cannot close file \"%s\": %s" , to_fullpath_hdr , strerror (errno ));
2216
+ pthread_mutex_unlock (& (hdr_map -> mutex ));
2203
2217
}
0 commit comments