@@ -31,8 +31,8 @@ typedef struct DataPage
3131char data [BLCKSZ ];
3232}DataPage ;
3333
34- static bool get_compressed_page_meta (FILE * in ,const char * fullpath ,BackupPageHeader * bph ,
35- pg_crc32 * crc ,bool use_crc32c );
34+ static bool get_page_header (FILE * in ,const char * fullpath ,BackupPageHeader * bph ,
35+ pg_crc32 * crc ,bool use_crc32c );
3636
3737#ifdef HAVE_LIBZ
3838/* Implementation of zlib compression method */
@@ -861,6 +861,10 @@ restore_data_file(parray *parent_chain, pgFile *dest_file, FILE *out,
861861 * If "nblocks" is greater than zero, then skip restoring blocks,
862862 * whose position if greater than "nblocks".
863863 * If map is NULL, then page bitmap cannot be used for restore optimization
864+ * Page bitmap optimize restore of incremental chains, consisting of more than one
865+ * backup. We restoring from newest to oldest and page, once restored, marked in map.
866+ * When the same page, but in older backup, encountered, we check the map, if it is
867+ * marked as already restored, then page is skipped.
864868 */
865869size_t
866870restore_data_file_internal (FILE * in ,FILE * out ,pgFile * file ,uint32 backup_version ,
@@ -930,39 +934,37 @@ restore_data_file_internal(FILE *in, FILE *out, pgFile *file, uint32 backup_vers
930934else
931935{
932936/* We get into this function either when restoring old backup
933- * or when merging something.Aligh read_len only in restoring
934- * or merging oldbackup .
937+ * or when merging something.Align read_len only in restoring
938+ * or merging oldbackups .
935939 */
936- if (get_compressed_page_meta (in ,from_fullpath ,& (page ).bph ,NULL , false))
940+ if (get_page_header (in ,from_fullpath ,& (page ).bph ,NULL , false))
937941{
938942cur_pos_in += sizeof (BackupPageHeader );
939943
940944/* backward compatibility kludge TODO: remove in 3.0 */
941945blknum = page .bph .block ;
942946compressed_size = page .bph .compressed_size ;
943947
944- /* this will backfire when retrying merge of old backups,
945- * just pray that this will never happen.
948+ /* this has a potential to backfire when retrying merge of old backups,
949+ * so we just forbid the retrying of failed merges between versions >= 2.4.0 and
950+ * version < 2.4.0
946951 */
947952if (backup_version >=20400 )
948953read_len = compressed_size ;
949954else
955+ /* For some unknown and possibly dump reason I/O operations
956+ * in versions < 2.4.0 were always aligned to 8 bytes.
957+ * Now we have to deal with backward compatibility.
958+ */
950959read_len = MAXALIGN (compressed_size );
951960
952- //elog(INFO, "FILE: %s", from_fullpath);
953- //elog(INFO, "blknum: %i", blknum);
954- //
955- //elog(INFO, "POS: %u", cur_pos_in);
956- //elog(INFO, "SIZE: %i", compressed_size);
957- //elog(INFO, "ASIZE: %i", read_len);
958-
959961}
960962else
961963break ;
962964}
963965
964966/*
965- *Backupward compatibility kludge: in the good old days
967+ *Backward compatibility kludge: in the good old days
966968 * n_blocks attribute was available only in DELTA backups.
967969 * File truncate in PAGE and PTRACK happened on the fly when
968970 * special value PageIsTruncated is encountered.
@@ -1006,13 +1008,13 @@ restore_data_file_internal(FILE *in, FILE *out, pgFile *file, uint32 backup_vers
10061008if (compressed_size > BLCKSZ )
10071009elog (ERROR ,"Size of a blknum %i exceed BLCKSZ: %i" ,blknum ,compressed_size );
10081010
1009- /*incremental restore in LSN mode */
1011+ /*Incremental restore in LSN mode */
10101012if (map && lsn_map && datapagemap_is_set (lsn_map ,blknum ))
10111013datapagemap_add (map ,blknum );
10121014
10131015if (map && checksum_map && checksum_map [blknum ].checksum != 0 )
10141016{
1015- // elog(INFO, "HDR CRC: %u, MAP CRC: %u", page_crc, checksum_map[blknum].checksum);
1017+ // elog(INFO, "HDR CRC: %u, MAP CRC: %u", page_crc, checksum_map[blknum].checksum);
10161018/*
10171019 * The heart of incremental restore in CHECKSUM mode
10181020 * If page in backup has the same checksum and lsn as
@@ -1110,7 +1112,7 @@ restore_data_file_internal(FILE *in, FILE *out, pgFile *file, uint32 backup_vers
11101112write_len += BLCKSZ ;
11111113cur_pos_out += BLCKSZ ;/* update current write position */
11121114
1113- /* Mark page as restored, to avoid reading this page when restoring parent backups */
1115+ /* Mark page as restored to avoid reading this page when restoring parent backups */
11141116if (map )
11151117datapagemap_add (map ,blknum );
11161118}
@@ -1238,7 +1240,7 @@ restore_non_data_file(parray *parent_chain, pgBackup *dest_backup,
12381240/* incremental restore */
12391241if (already_exists )
12401242{
1241- /* comparechecksumms ofremote andlocal files */
1243+ /* comparechecksums ofalready existing file andbackup file */
12421244pg_crc32 file_crc = fio_get_crc32 (to_fullpath ,FIO_DB_HOST , false);
12431245
12441246if (file_crc == tmp_file -> crc )
@@ -1625,7 +1627,7 @@ validate_file_pages(pgFile *file, const char *fullpath, XLogRecPtr stop_lsn,
16251627if (interrupted || thread_interrupted )
16261628elog (ERROR ,"Interrupted during data file validation" );
16271629
1628- /* newer backups have headers in separate storage */
1630+ /* newer backups havepage headers in separate storage */
16291631if (headers )
16301632{
16311633n_hdr ++ ;
@@ -1657,7 +1659,7 @@ validate_file_pages(pgFile *file, const char *fullpath, XLogRecPtr stop_lsn,
16571659/* old backups rely on header located directly in data file */
16581660else
16591661{
1660- if (get_compressed_page_meta (in ,fullpath ,& (compressed_page ).bph ,& crc ,use_crc32c ))
1662+ if (get_page_header (in ,fullpath ,& (compressed_page ).bph ,& crc ,use_crc32c ))
16611663{
16621664/* Backward compatibility kludge, TODO: remove in 3.0
16631665 * for some reason we padded compressed pages in old versions
@@ -1686,11 +1688,6 @@ validate_file_pages(pgFile *file, const char *fullpath, XLogRecPtr stop_lsn,
16861688else
16871689len = fread (compressed_page .data ,1 ,read_len ,in );
16881690
1689- //elog(INFO, "POS: %u", cur_pos_in);
1690- //
1691- //elog(INFO, "LEN: %i", len);
1692- //elog(INFO, "READ_LEN: %i", read_len);
1693-
16941691if (len != read_len )
16951692{
16961693elog (WARNING ,"Cannot read block %u file \"%s\": %s" ,
@@ -1886,11 +1883,8 @@ get_lsn_map(const char *fullpath, uint32 checksum_version,
18861883for (blknum = 0 ;blknum < n_blocks ;blknum ++ )
18871884{
18881885size_t read_len = fread (read_buffer ,1 ,BLCKSZ ,in );
1889- //page_lsn = InvalidXLogRecPtr;
18901886PageState page_st ;
18911887
1892- //page_st.lsn = InvalidXLogRecPtr
1893-
18941888/* report error */
18951889if (ferror (in ))
18961890elog (ERROR ,"Cannot read block %u of \"%s\": %s" ,
@@ -1905,7 +1899,8 @@ get_lsn_map(const char *fullpath, uint32 checksum_version,
19051899datapagemap_add (lsn_map ,blknum );
19061900}
19071901else
1908- elog (ERROR ,"Failed to read blknum %u from file \"%s\"" ,blknum ,fullpath );
1902+ elog (ERROR ,"Cannot read block %u from file \"%s\": %s" ,
1903+ blknum ,fullpath ,strerror (errno ));
19091904
19101905if (feof (in ))
19111906break ;
@@ -1926,10 +1921,10 @@ get_lsn_map(const char *fullpath, uint32 checksum_version,
19261921return lsn_map ;
19271922}
19281923
1929- /* */
1924+ /*Every page in data file contains BackupPageHeader, extract it */
19301925bool
1931- get_compressed_page_meta (FILE * in ,const char * fullpath ,BackupPageHeader * bph ,
1932- pg_crc32 * crc ,bool use_crc32c )
1926+ get_page_header (FILE * in ,const char * fullpath ,BackupPageHeader * bph ,
1927+ pg_crc32 * crc ,bool use_crc32c )
19331928{
19341929
19351930/* read BackupPageHeader */
@@ -1952,26 +1947,18 @@ get_compressed_page_meta(FILE *in, const char *fullpath, BackupPageHeader* bph,
19521947ftell (in ),fullpath ,strerror (errno ));
19531948}
19541949
1950+ /* In older versions < 2.4.0, when crc for file was calculated, header was
1951+ * not included in crc calculations. Now it is. And now we have
1952+ * the problem of backward compatibility for backups of old versions
1953+ */
19551954if (crc )
19561955COMP_FILE_CRC32 (use_crc32c ,* crc ,bph ,read_len );
19571956
19581957if (bph -> block == 0 && bph -> compressed_size == 0 )
19591958elog (ERROR ,"Empty block in file \"%s\"" ,fullpath );
19601959
1961-
1962- //*blknum = header.block;
1963- //*compressed_size = header.compressed_size;
1964-
1965- //elog(INFO, "blknum: %i", header.block);
1966- //elog(INFO, "size: %i", header.compressed_size);
1967- //elog(INFO, "size2: %i", *compressed_size);
1968- //
1969- //elog(INFO, "BLKNUM: %i", *blknum);
1970- //elog(INFO, "File: %s", fullpath);
1971-
19721960Assert (bph -> compressed_size != 0 );
19731961return true;
1974-
19751962}
19761963
19771964/* Open local backup file for writing, set permissions and buffering */
@@ -2099,7 +2086,10 @@ send_pages(ConnectionArgs* conn_arg, const char *to_fullpath, const char *from_f
20992086blknum ++ ;
21002087}
21012088
2102- /* add one additional header */
2089+ /*
2090+ * Add dummy header, so we can later extract the length of last header
2091+ * as difference between their offsets.
2092+ */
21032093if (* headers )
21042094{
21052095file -> n_headers = hdr_num + 1 ;
@@ -2124,8 +2114,11 @@ send_pages(ConnectionArgs* conn_arg, const char *to_fullpath, const char *from_f
21242114return n_blocks_read ;
21252115}
21262116
2127- /* attempt to open header file, read content and return as
2117+ /*
2118+ * Attempt to open header file, read content and return as
21282119 * array of headers.
2120+ * TODO: some access optimizations would be great here:
2121+ * less fseeks, buffering, descriptor sharing, etc.
21292122 */
21302123BackupPageHeader2 *
21312124get_data_file_headers (HeaderMap * hdr_map ,pgFile * file ,uint32 backup_version ,bool strict )
@@ -2181,8 +2174,6 @@ get_data_file_headers(HeaderMap *hdr_map, pgFile *file, uint32 backup_version, b
21812174gotocleanup ;
21822175}
21832176
2184- //elog(INFO, "zsize: %i, size: %i", file->hdr_size, read_len);
2185-
21862177/* allocate memory for uncompressed headers */
21872178headers = pgut_malloc (read_len );
21882179memset (headers ,0 ,read_len );
@@ -2244,7 +2235,7 @@ write_page_headers(BackupPageHeader2 *headers, pgFile *file, HeaderMap *hdr_map,
22442235if (file -> n_headers <=0 )
22452236return ;
22462237
2247- /* when running merge we mustsave headers into the temp map */
2238+ /* when running merge we mustwrite headers into temp map */
22482239map_path = (is_merge ) ?hdr_map -> path_tmp :hdr_map -> path ;
22492240read_len = (file -> n_headers + 1 )* sizeof (BackupPageHeader2 );
22502241