/* We don't need to consider any further sources. */ break;
}
/* *Sincewefoundanotherincrementalfile,sourceallblocksfromit *thatweneedbutdon'tyethave.
*/ for (i = 0; i < s->num_blocks; ++i)
{
BlockNumber b = s->relative_block_numbers[i];
if (b < latest_source->truncation_block_length &&
sourcemap[b] == NULL)
{
sourcemap[b] = s;
offsetmap[b] = s->header_length + (i * BLCKSZ);
/* Save results of checksum calculation. */ if (checksum_type != CHECKSUM_TYPE_NONE)
{
*checksum_payload = pg_malloc(PG_CHECKSUM_MAX_LENGTH);
*checksum_length = pg_checksum_final(&checksum_ctx,
*checksum_payload);
}
/* *Closefilesandreleasememory.
*/ for (i = 0; i <= n_prior_backups; ++i)
{
rfile *s = source[i];
if (s == NULL) continue; if (close(s->fd) != 0)
pg_fatal("could not close file \"%s\": %m", s->filename); if (s->relative_block_numbers != NULL)
pfree(s->relative_block_numbers);
pg_free(s->filename);
pg_free(s);
}
pfree(sourcemap);
pfree(offsetmap);
pfree(source);
}
for (i = 0; i < n_source; ++i)
{
rfile *s = sources[i];
/* Ignore source if not used. */ if (s == NULL) continue;
/* If no data is needed from this file, we can ignore it. */ if (s->num_blocks_read == 0) continue;
/* Debug logging. */ if (dry_run)
pg_log_debug("would have read %u blocks from \"%s\"",
s->num_blocks_read, s->filename); else
pg_log_debug("read %u blocks from \"%s\"",
s->num_blocks_read, s->filename);
/* *Indry-runmode,wedon'tactuallytrytoreaddatafromthefile, *butwedotrytoverifythatthefileislongenoughthatwecould *havereadthedataifwe'dtried. * *Ifthisfails,thenitmeansthatanon-dry-runattemptwouldfail, *complainingofnotbeingabletoreadtherequiredbytesfromthe *file.
*/ if (dry_run)
{ struct stat sb;
if (fstat(s->fd, &sb) < 0)
pg_fatal("could not stat file \"%s\": %m", s->filename); if (sb.st_size < s->highest_offset_read)
pg_fatal("file \"%s\" is too short: expected %llu, found %llu",
s->filename,
(unsignedlonglong) s->highest_offset_read,
(unsignedlonglong) sb.st_size);
}
}
}
/* Basic information about the output file to be produced. */ if (dry_run)
pg_log_debug("would reconstruct \"%s\" (%u blocks, checksum %s)",
output_filename, block_length,
pg_checksum_type_name(checksum_ctx->type)); else
pg_log_debug("reconstructing \"%s\" (%u blocks, checksum %s)",
output_filename, block_length,
pg_checksum_type_name(checksum_ctx->type));
/* Print out the plan for reconstructing this file. */
initStringInfo(&debug_buf); while (current_block < block_length)
{
rfile *s = sourcemap[current_block];
/* Extend range, if possible. */ if (current_block + 1 < block_length &&
s == sourcemap[current_block + 1])
{
++current_block; continue;
}
/* Add details about this range. */ if (s == NULL)
{ if (current_block == start_of_range)
appendStringInfo(&debug_buf, " %u:zero", current_block); else
appendStringInfo(&debug_buf, " %u-%u:zero",
start_of_range, current_block);
} else
{ if (current_block == start_of_range)
appendStringInfo(&debug_buf, " %u:%s@" UINT64_FORMAT,
current_block, s->filename,
(uint64) offsetmap[current_block]); else
appendStringInfo(&debug_buf, " %u-%u:%s@" UINT64_FORMAT,
start_of_range, current_block,
s->filename,
(uint64) offsetmap[current_block]);
}
/* Begin new range. */
start_of_range = ++current_block;
/* If the output is very long or we are done, dump it now. */ if (current_block == block_length || debug_buf.len > 1024)
{
pg_log_debug("reconstruction plan:%s", debug_buf.data);
resetStringInfo(&debug_buf);
}
}
/* Free memory. */
pfree(debug_buf.data);
}
/* Open the output file, except in dry_run mode. */ if (!dry_run &&
(wfd = open(output_filename,
O_RDWR | PG_BINARY | O_CREAT | O_EXCL,
pg_file_create_mode)) < 0)
pg_fatal("could not open file \"%s\": %m", output_filename);
/* Read and write the blocks as required. */ for (i = 0; i < block_length; ++i)
{
uint8 buffer[BLCKSZ];
rfile *s = sourcemap[i];
/* Update accounting information. */ if (s == NULL)
++zero_blocks; else
{
s->num_blocks_read++;
s->highest_offset_read = Max(s->highest_offset_read,
offsetmap[i] + BLCKSZ);
}
/* Skip the rest of this in dry-run mode. */ if (dry_run) continue;
/* Read or zero-fill the block as appropriate. */ if (s == NULL)
{ /* *NewblocknotmentionedintheWALsummary.Shouldhavebeenan *uninitializedblock,sojustzero-fillit.
*/
memset(buffer, 0, BLCKSZ);
/* Write out the block, update the checksum if needed. */
write_block(wfd, output_filename, buffer, checksum_ctx);
/* Nothing else to do for zero-filled blocks. */ continue;
}
/* Copy the block using the appropriate copy method. */ if (copy_method != COPY_METHOD_COPY_FILE_RANGE)
{ /* *Readtheblockfromthecorrectsourcefile,andthenwriteit *out,possiblywithachecksumupdate.
*/
read_block(s, offsetmap[i], buffer);
write_block(wfd, output_filename, buffer, checksum_ctx);
} else/* use copy_file_range */
{ #ifdefined(HAVE_COPY_FILE_RANGE) /* copy_file_range modifies the offset, so use a local copy */
off_t off = offsetmap[i];
size_t nwritten = 0;
/* *Retryuntilwe'vewrittenallthebytes(theoffsetisupdated *bycopy_file_range,andsoisthewfdfileoffset).
*/ do
{ int wb;
if (wb < 0)
pg_fatal("error while copying file range from \"%s\" to \"%s\": %m",
input_filename, output_filename);
nwritten += wb;
} while (BLCKSZ > nwritten);
/* *Whenchecksumcalculationnotneeded,we'redone,otherwise *readtheblockandpassittothechecksumcalculation.
*/ if (checksum_ctx->type == CHECKSUM_TYPE_NONE) continue;
read_block(s, offsetmap[i], buffer);
if (pg_checksum_update(checksum_ctx, buffer, BLCKSZ) < 0)
pg_fatal("could not update checksum of file \"%s\"",
output_filename); #else
pg_fatal("copy_file_range not supported on this platform"); #endif
}
}
/* Debugging output. */ if (zero_blocks > 0)
{ if (dry_run)
pg_log_debug("would have zero-filled %u blocks", zero_blocks); else
pg_log_debug("zero-filled %u blocks", zero_blocks);
}
/* Close the output file. */ if (wfd >= 0 && close(wfd) != 0)
pg_fatal("could not close file \"%s\": %m", output_filename);
}
/* Read the block from the correct source, except if dry-run. */
rb = pg_pread(s->fd, buffer, BLCKSZ, off); if (rb != BLCKSZ)
{ if (rb < 0)
pg_fatal("could not read from file \"%s\": %m", s->filename); else
pg_fatal("could not read from file \"%s\", offset %llu: read %d of %d",
s->filename, (unsignedlonglong) off, rb, BLCKSZ);
}
}
Messung V0.5 in Prozent
¤ Dauer der Verarbeitung: 0.16 Sekunden
(vorverarbeitet am 2026-08-07)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.