@@ -757,7 +757,7 @@ restore_data_file(const char *to_path, pgFile *file, bool allow_truncate,
757
757
}
758
758
759
759
/*
760
- * Open backup file for write. We use "r+" at first to overwrite only
760
+ * Open backup file for write. We use "r+" at first to overwrite only
761
761
* modified pages for differential restore. If the file does not exist,
762
762
* re-open it with "w" to create an empty file.
763
763
*/
@@ -961,6 +961,193 @@ restore_data_file(const char *to_path, pgFile *file, bool allow_truncate,
961
961
fclose (in );
962
962
}
963
963
964
+ /*
965
+ * Restore files in the from_root directory to the to_root directory with
966
+ * same relative path.
967
+ *
968
+ * If write_header is true then we add header to each restored block, currently
969
+ * it is used for MERGE command.
970
+ *
971
+ * to_fullpath and from_fullpath are provided strictly for ERROR reporting
972
+ */
973
+ void
974
+ restore_data_file_new (FILE * in , FILE * out , pgFile * file , uint32 backup_version ,
975
+ const char * from_fullpath , const char * to_fullpath , int nblocks )
976
+ {
977
+ BackupPageHeader header ;
978
+ BlockNumber blknum = 0 ;
979
+ size_t write_len = 0 ;
980
+
981
+ while (true)
982
+ {
983
+ off_t write_pos ;
984
+ size_t read_len ;
985
+ DataPage compressed_page ; /* used as read buffer */
986
+ DataPage page ;
987
+ int32 uncompressed_size = 0 ;
988
+
989
+ /* read BackupPageHeader */
990
+ read_len = fread (& header , 1 , sizeof (header ), in );
991
+
992
+ if (read_len != sizeof (header ))
993
+ {
994
+ int errno_tmp = errno ;
995
+ if (read_len == 0 && feof (in ))
996
+ break ; /* EOF found */
997
+ else if (read_len != 0 && feof (in ))
998
+ elog (ERROR , "Odd size page found at block %u of \"%s\"" ,
999
+ blknum , from_fullpath );
1000
+ else
1001
+ elog (ERROR , "Cannot read header of block %u of \"%s\": %s" ,
1002
+ blknum , from_fullpath , strerror (errno_tmp ));
1003
+ }
1004
+
1005
+ /* Consider empty block */
1006
+ if (header .block == 0 && header .compressed_size == 0 )
1007
+ {
1008
+ elog (VERBOSE , "Skip empty block of \"%s\"" , from_fullpath );
1009
+ continue ;
1010
+ }
1011
+
1012
+ /* sanity? */
1013
+ if (header .block < blknum )
1014
+ elog (ERROR , "Backup is broken at block %u of \"%s\"" ,
1015
+ blknum , from_fullpath );
1016
+
1017
+ blknum = header .block ;
1018
+
1019
+ /* no point in writing redundant data */
1020
+ if (nblocks > 0 && blknum >= nblocks )
1021
+ return ;
1022
+
1023
+ if (header .compressed_size > BLCKSZ )
1024
+ elog (ERROR , "Size of a blknum %i exceed BLCKSZ" , blknum );
1025
+
1026
+ /* read a page from file */
1027
+ read_len = fread (compressed_page .data , 1 ,
1028
+ MAXALIGN (header .compressed_size ), in );
1029
+
1030
+ if (read_len != MAXALIGN (header .compressed_size ))
1031
+ elog (ERROR , "Cannot read block %u of \"%s\", read %zu of %d" ,
1032
+ blknum , from_fullpath , read_len , header .compressed_size );
1033
+
1034
+ /*
1035
+ * if page size is smaller than BLCKSZ, decompress the page.
1036
+ * BUGFIX for versions < 2.0.23: if page size is equal to BLCKSZ.
1037
+ * we have to check, whether it is compressed or not using
1038
+ * page_may_be_compressed() function.
1039
+ */
1040
+ if (header .compressed_size != BLCKSZ
1041
+ || page_may_be_compressed (compressed_page .data , file -> compress_alg ,
1042
+ backup_version ))
1043
+ {
1044
+ const char * errormsg = NULL ;
1045
+
1046
+ uncompressed_size = do_decompress (page .data , BLCKSZ ,
1047
+ compressed_page .data ,
1048
+ header .compressed_size ,
1049
+ file -> compress_alg , & errormsg );
1050
+
1051
+ if (uncompressed_size < 0 && errormsg != NULL )
1052
+ elog (WARNING , "An error occured during decompressing block %u of file \"%s\": %s" ,
1053
+ blknum , from_fullpath , errormsg );
1054
+
1055
+ if (uncompressed_size != BLCKSZ )
1056
+ elog (ERROR , "Page of file \"%s\" uncompressed to %d bytes. != BLCKSZ" ,
1057
+ from_fullpath , uncompressed_size );
1058
+ }
1059
+
1060
+ write_pos = blknum * BLCKSZ ;
1061
+
1062
+ /*
1063
+ * Seek and write the restored page.
1064
+ * TODO: invent fio_pwrite().
1065
+ */
1066
+ if (fio_fseek (out , write_pos ) < 0 )
1067
+ elog (ERROR , "Cannot seek block %u of \"%s\": %s" ,
1068
+ blknum , to_fullpath , strerror (errno ));
1069
+
1070
+ /* if we uncompressed the page - write page.data,
1071
+ * if page wasn't compressed -
1072
+ * write what we've read - compressed_page.data
1073
+ */
1074
+ if (uncompressed_size == BLCKSZ )
1075
+ {
1076
+ if (fio_fwrite (out , page .data , BLCKSZ ) != BLCKSZ )
1077
+ elog (ERROR , "Cannot write block %u of \"%s\": %s" ,
1078
+ blknum , to_fullpath , strerror (errno ));
1079
+ }
1080
+ else
1081
+ {
1082
+ if (fio_fwrite (out , compressed_page .data , BLCKSZ ) != BLCKSZ )
1083
+ elog (ERROR , "Cannot write block %u of \"%s\": %s" ,
1084
+ blknum , to_fullpath , strerror (errno ));
1085
+ }
1086
+
1087
+ write_len += BLCKSZ ;
1088
+ }
1089
+
1090
+ elog (VERBOSE , "Copied file \"%s\": %lu bytes" , from_fullpath , write_len );
1091
+ }
1092
+
1093
+ /*
1094
+ * Copy file to backup.
1095
+ * We do not apply compression to these files, because
1096
+ * it is either small control file or already compressed cfs file.
1097
+ */
1098
+ void
1099
+ restore_non_data_file (FILE * in , FILE * out , pgFile * file ,
1100
+ const char * from_fullpath , const char * to_fullpath )
1101
+ {
1102
+ size_t read_len = 0 ;
1103
+ int errno_tmp ;
1104
+ char buf [BLCKSZ ];
1105
+
1106
+ /* copy content */
1107
+ for (;;)
1108
+ {
1109
+ read_len = 0 ;
1110
+
1111
+ if ((read_len = fio_fread (in , buf , sizeof (buf ))) != sizeof (buf ))
1112
+ break ;
1113
+
1114
+ if (fio_fwrite (out , buf , read_len ) != read_len )
1115
+ {
1116
+ errno_tmp = errno ;
1117
+ /* oops */
1118
+ fio_fclose (in );
1119
+ fio_fclose (out );
1120
+ elog (ERROR , "Cannot write to \"%s\": %s" , to_fullpath ,
1121
+ strerror (errno_tmp ));
1122
+ }
1123
+ }
1124
+
1125
+ errno_tmp = errno ;
1126
+ if (read_len < 0 )
1127
+ {
1128
+ fio_fclose (in );
1129
+ fio_fclose (out );
1130
+ elog (ERROR , "Cannot read backup mode file \"%s\": %s" ,
1131
+ from_fullpath , strerror (errno_tmp ));
1132
+ }
1133
+
1134
+ /* copy odd part. */
1135
+ if (read_len > 0 )
1136
+ {
1137
+ if (fio_fwrite (out , buf , read_len ) != read_len )
1138
+ {
1139
+ errno_tmp = errno ;
1140
+ /* oops */
1141
+ fio_fclose (in );
1142
+ fio_fclose (out );
1143
+ elog (ERROR , "Cannot write to \"%s\": %s" , to_fullpath ,
1144
+ strerror (errno_tmp ));
1145
+ }
1146
+ }
1147
+
1148
+ elog (VERBOSE , "Copied file \"%s\": %lu bytes" , from_fullpath , file -> write_size );
1149
+ }
1150
+
964
1151
/*
965
1152
* Copy file to backup.
966
1153
* We do not apply compression to these files, because
0 commit comments