57 unsigned block_length,
92 char **prior_backup_dirs,
97 uint8 **checksum_payload,
103 rfile *latest_source = NULL;
106 unsigned block_length;
108 unsigned sidx = n_prior_backups;
109 bool full_copy_possible =
true;
110 int copy_source_index = -1;
111 rfile *copy_source = NULL;
125 source[n_prior_backups] = latest_source;
134 offsetmap =
pg_malloc0(
sizeof(off_t) * block_length);
150 sourcemap[
b] = latest_source;
157 full_copy_possible =
false;
178 prior_backup_dirs[sidx], relative_path, bare_file_name);
179 if ((s =
make_rfile(source_filename,
true)) == NULL)
182 prior_backup_dirs[sidx], relative_path, bare_file_name);
222 blocklength = sb.
st_size / BLCKSZ;
225 if (sourcemap[
b] == NULL &&
b < blocklength)
228 offsetmap[
b] =
b * BLCKSZ;
237 if (full_copy_possible)
239 uint64 expected_length;
243 expected_length *= BLCKSZ;
247 copy_source_index = sidx;
263 if (b < latest_source->truncation_block_length &&
264 sourcemap[
b] == NULL)
274 full_copy_possible =
false;
284 if (copy_source_index >= 0 && manifests[copy_source_index] != NULL &&
289 mfile = manifest_files_lookup(manifests[copy_source_index]->files,
293 char *path =
psprintf(
"%s/backup_manifest",
294 prior_backup_dirs[copy_source_index]);
300 pg_log_warning(
"manifest file \"%s\" contains no entry for file \"%s\"",
308 *checksum_payload =
pg_malloc(*checksum_length);
326 if (copy_source != NULL)
328 &checksum_ctx, copy_method,
dry_run);
332 block_length, sourcemap, offsetmap,
333 &checksum_ctx, copy_method,
349 for (
i = 0;
i <= n_prior_backups; ++
i)
374 for (
i = 0;
i < n_source; ++
i)
410 pg_fatal(
"file \"%s\" is too short: expected %llu, found %llu",
413 (
unsigned long long) sb.
st_size);
452 pg_fatal(
"file \"%s\" has bad incremental magic number (0x%x, expected 0x%x)",
458 pg_fatal(
"file \"%s\" has block count %u in excess of segment size %u",
465 pg_fatal(
"file \"%s\" has truncation block length %u in excess of segment size %u",
505 if (missing_ok && errno == ENOENT)
522 int rb =
read(rf->
fd, buffer, length);
529 pg_fatal(
"could not read file \"%s\": read %d of %u",
540 unsigned block_length,
550 unsigned zero_blocks = 0;
556 unsigned start_of_range = 0;
557 unsigned current_block = 0;
561 pg_log_debug(
"would reconstruct \"%s\" (%u blocks, checksum %s)",
565 pg_log_debug(
"reconstructing \"%s\" (%u blocks, checksum %s)",
571 while (current_block < block_length)
573 rfile *s = sourcemap[current_block];
576 if (current_block + 1 < block_length &&
577 s == sourcemap[current_block + 1])
586 if (current_block == start_of_range)
590 start_of_range, current_block);
594 if (current_block == start_of_range)
597 (uint64) offsetmap[current_block]);
600 start_of_range, current_block,
602 (uint64) offsetmap[current_block]);
606 start_of_range = ++current_block;
609 if (current_block == block_length || debug_buf.
len > 1024)
628 for (
i = 0;
i < block_length; ++
i)
630 uint8 buffer[BLCKSZ];
640 offsetmap[
i] + BLCKSZ);
654 memset(buffer, 0, BLCKSZ);
675 #if defined(HAVE_COPY_FILE_RANGE)
677 off_t off = offsetmap[
i];
688 wb = copy_file_range(s->
fd, &off, wfd, NULL, BLCKSZ - nwritten, 0);
691 pg_fatal(
"error while copying file range from \"%s\" to \"%s\": %m",
696 }
while (BLCKSZ > nwritten);
708 pg_fatal(
"could not update checksum of file \"%s\"",
711 pg_fatal(
"copy_file_range not supported on this platform");
720 pg_log_debug(
"would have zero-filled %u blocks", zero_blocks);
726 if (wfd >= 0 &&
close(wfd) != 0)
743 if ((wb =
write(
fd, buffer, BLCKSZ)) != BLCKSZ)
748 pg_fatal(
"could not write file \"%s\": wrote %d of %d",
754 pg_fatal(
"could not update checksum of file \"%s\"",
773 pg_fatal(
"could not read from file \"%s\", offset %llu: read %d of %d",
774 s->
filename, (
unsigned long long) off, rb, BLCKSZ);
#define INCREMENTAL_MAGIC
#define Assert(condition)
char * pg_checksum_type_name(pg_checksum_type type)
int pg_checksum_final(pg_checksum_context *context, uint8 *output)
int pg_checksum_update(pg_checksum_context *context, const uint8 *input, size_t len)
int pg_checksum_init(pg_checksum_context *context, pg_checksum_type type)
#define PG_CHECKSUM_MAX_LENGTH
@ COPY_METHOD_COPY_FILE_RANGE
void copy_file(const char *fromfile, const char *tofile)
void * pg_malloc0(size_t size)
void * pg_malloc(size_t size)
if(TABLE==NULL||TABLE_index==NULL)
#define pg_log_debug(...)
char * pstrdup(const char *in)
void pfree(void *pointer)
static rewind_source * source
#define pg_log_warning(...)
static int fd(const char *x, int i)
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)
void reconstruct_from_incremental_file(char *input_filename, char *output_filename, char *relative_path, char *bare_file_name, int n_prior_backups, char **prior_backup_dirs, manifest_data **manifests, char *manifest_path, pg_checksum_type checksum_type, int *checksum_length, uint8 **checksum_payload, CopyMethod copy_method, bool debug, bool dry_run)
static void read_block(rfile *s, off_t off, uint8 *buffer)
static void read_bytes(rfile *rf, void *buffer, unsigned length)
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)
static void write_block(int fd, char *output_filename, uint8 *buffer, pg_checksum_context *checksum_ctx)
void resetStringInfo(StringInfo str)
void appendStringInfo(StringInfo str, const char *fmt,...)
void initStringInfo(StringInfo str)
pg_checksum_type checksum_type
off_t highest_offset_read
BlockNumber * relative_block_numbers
unsigned truncation_block_length