102{
104 rfile *latest_source = NULL;
106 off_t *offsetmap;
107 unsigned block_length;
109 unsigned sidx = n_prior_backups;
110 bool full_copy_possible = true;
111 int copy_source_index = -1;
112 rfile *copy_source = NULL;
114
115
116 Assert(relative_path[0] !=
'\0');
117 Assert(relative_path[strlen(relative_path) - 1] ==
'/');
118
119
120
121
122
124
125
126
127
128
130 source[n_prior_backups] = latest_source;
132
133
134
135
136
137
139 offsetmap =
pg_malloc0(
sizeof(off_t) * block_length);
140
141
142
143
144
145
146
147
148
149
151 {
153
155 sourcemap[
b] = latest_source;
157
158
159
160
161
162 full_copy_possible = false;
163 }
164
165 while (1)
166 {
169
170
171
172
173
174 if (sidx == 0)
175 break;
176 --sidx;
177
178
179
180
181
183 prior_backup_dirs[sidx], relative_path, bare_file_name);
184 if ((s =
make_rfile(source_filename,
true)) == NULL)
185 {
187 prior_backup_dirs[sidx], relative_path, bare_file_name);
189 }
191
192
193
194
195
197 {
201
202
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227 blocklength = sb.st_size / BLCKSZ;
229 {
230 if (sourcemap[
b] == NULL &&
b < blocklength)
231 {
233 offsetmap[
b] =
b * BLCKSZ;
234 }
235 }
236
237
238
239
240
241
242 if (full_copy_possible)
243 {
245
246 expected_length =
248 expected_length *= BLCKSZ;
249 if (expected_length == sb.st_size)
250 {
251 copy_source = s;
252 copy_source_index = sidx;
253 }
254 }
255
256
257 break;
258 }
259
260
261
262
263
265 {
267
268 if (b < latest_source->truncation_block_length &&
269 sourcemap[
b] == NULL)
270 {
273
274
275
276
277
278
279 full_copy_possible = false;
280 }
281 }
282 }
283
284
285
286
287
288
289 if (copy_source_index >= 0 && manifests[copy_source_index] != NULL &&
291 {
293
294 mfile = manifest_files_lookup(manifests[copy_source_index]->files,
295 manifest_path);
296 if (mfile == NULL)
297 {
298 char *path =
psprintf(
"%s/backup_manifest",
299 prior_backup_dirs[copy_source_index]);
300
301
302
303
304
305 pg_log_warning(
"manifest file \"%s\" contains no entry for file \"%s\"",
306 path,
307 manifest_path);
309 }
311 {
313 *checksum_payload =
pg_malloc(*checksum_length);
315 *checksum_length);
317 }
318 }
319
320
322
323
324
325
326
327
328
329
330
331
332
333
334 if (copy_source != NULL)
336 &checksum_ctx, copy_method,
dry_run);
337 else if (sidx == 0 &&
source[0]->header_length != 0)
338 {
339 pg_fatal(
"full backup contains unexpected incremental file \"%s\"",
341 }
342 else
343 {
345 block_length, sourcemap, offsetmap,
346 &checksum_ctx, copy_method,
349 }
350
351
353 {
356 *checksum_payload);
357 }
358
359
360
361
362 for (
i = 0;
i <= n_prior_backups; ++
i)
363 {
365
366 if (s == NULL)
367 continue;
373 }
377}
#define Assert(condition)
int pg_checksum_final(pg_checksum_context *context, uint8 *output)
int pg_checksum_init(pg_checksum_context *context, pg_checksum_type type)
#define PG_CHECKSUM_MAX_LENGTH
void copy_file(const char *fromfile, const char *tofile)
void * pg_malloc(size_t size)
void * pg_malloc0(size_t size)
if(TABLE==NULL||TABLE_index==NULL)
void pfree(void *pointer)
static rewind_source * source
#define pg_log_warning(...)
char * psprintf(const char *fmt,...)
static rfile * make_rfile(char *filename, bool missing_ok)
static rfile * make_incremental_rfile(char *filename)
static void debug_reconstruction(int n_source, rfile **sources, bool dry_run)
static void write_reconstructed_file(char *input_filename, char *output_filename, unsigned block_length, rfile **sourcemap, off_t *offsetmap, pg_checksum_context *checksum_ctx, CopyMethod copy_method, bool debug, bool dry_run)
static unsigned find_reconstructed_block_length(rfile *s)
pg_checksum_type checksum_type
BlockNumber * relative_block_numbers
unsigned truncation_block_length