PostgreSQL Source Code  git master
basebackup.c File Reference
#include "postgres.h"
#include <sys/stat.h>
#include <unistd.h>
#include <time.h>
#include "access/xlog_internal.h"
#include "catalog/pg_type.h"
#include "common/file_perm.h"
#include "commands/defrem.h"
#include "commands/progress.h"
#include "lib/stringinfo.h"
#include "libpq/libpq.h"
#include "libpq/pqformat.h"
#include "miscadmin.h"
#include "nodes/pg_list.h"
#include "pgstat.h"
#include "pgtar.h"
#include "port.h"
#include "postmaster/syslogger.h"
#include "replication/basebackup.h"
#include "replication/backup_manifest.h"
#include "replication/walsender.h"
#include "replication/walsender_private.h"
#include "storage/bufpage.h"
#include "storage/checksum.h"
#include "storage/dsm_impl.h"
#include "storage/fd.h"
#include "storage/ipc.h"
#include "storage/reinit.h"
#include "utils/builtins.h"
#include "utils/ps_status.h"
#include "utils/relcache.h"
#include "utils/resowner.h"
#include "utils/timestamp.h"
Include dependency graph for basebackup.c:

Go to the source code of this file.

Data Structures

struct  basebackup_options
 
struct  exclude_list_item
 

Macros

#define TAR_SEND_SIZE   32768
 
#define THROTTLING_FREQUENCY   8
 

Functions

static int64 sendTablespace (char *path, char *oid, bool sizeonly, struct backup_manifest_info *manifest)
 
static int64 sendDir (const char *path, int basepathlen, bool sizeonly, List *tablespaces, bool sendtblspclinks, backup_manifest_info *manifest, const char *spcoid)
 
static bool sendFile (const char *readfilename, const char *tarfilename, struct stat *statbuf, bool missing_ok, Oid dboid, backup_manifest_info *manifest, const char *spcoid)
 
static void sendFileWithContent (const char *filename, const char *content, backup_manifest_info *manifest)
 
static int64 _tarWriteHeader (const char *filename, const char *linktarget, struct stat *statbuf, bool sizeonly)
 
static void convert_link_to_directory (const char *pathbuf, struct stat *statbuf)
 
static void send_int8_string (StringInfoData *buf, int64 intval)
 
static void SendBackupHeader (List *tablespaces)
 
static void perform_base_backup (basebackup_options *opt)
 
static void parse_basebackup_options (List *options, basebackup_options *opt)
 
static void SendXlogRecPtrResult (XLogRecPtr ptr, TimeLineID tli)
 
static int compareWalFileNames (const ListCell *a, const ListCell *b)
 
static void throttle (size_t increment)
 
static void update_basebackup_progress (int64 delta)
 
static bool is_checksummed_file (const char *fullpath, const char *filename)
 
static int basebackup_read_file (int fd, char *buf, size_t nbytes, off_t offset, const char *filename, bool partial_read_ok)
 
void SendBaseBackup (BaseBackupCmd *cmd)
 

Variables

static bool backup_started_in_recovery = false
 
static char * statrelpath = NULL
 
static uint64 throttling_sample
 
static int64 throttling_counter
 
static TimeOffset elapsed_min_unit
 
static TimestampTz throttled_last
 
static XLogRecPtr startptr
 
static long long int total_checksum_failures
 
static bool noverify_checksums = false
 
static int64 backup_total = 0
 
static int64 backup_streamed = 0
 
static const char *const excludeDirContents []
 
static const struct exclude_list_item excludeFiles []
 
static const struct exclude_list_item noChecksumFiles []
 

Macro Definition Documentation

◆ TAR_SEND_SIZE

#define TAR_SEND_SIZE   32768

Definition at line 96 of file basebackup.c.

Referenced by perform_base_backup(), and sendFile().

◆ THROTTLING_FREQUENCY

#define THROTTLING_FREQUENCY   8

Definition at line 101 of file basebackup.c.

Referenced by perform_base_backup().

Function Documentation

◆ _tarWriteHeader()

static int64 _tarWriteHeader ( const char *  filename,
const char *  linktarget,
struct stat statbuf,
bool  sizeonly 
)
static

Definition at line 1852 of file basebackup.c.

References elog, ereport, errmsg(), ERROR, pq_putmessage, stat::st_gid, stat::st_mode, stat::st_mtime, stat::st_size, stat::st_uid, TAR_BLOCK_SIZE, TAR_NAME_TOO_LONG, TAR_OK, TAR_SYMLINK_TOO_LONG, tarCreateHeader(), and update_basebackup_progress().

Referenced by perform_base_backup(), sendDir(), sendFile(), sendFileWithContent(), and sendTablespace().

1854 {
1855  char h[TAR_BLOCK_SIZE];
1856  enum tarError rc;
1857 
1858  if (!sizeonly)
1859  {
1860  rc = tarCreateHeader(h, filename, linktarget, statbuf->st_size,
1861  statbuf->st_mode, statbuf->st_uid, statbuf->st_gid,
1862  statbuf->st_mtime);
1863 
1864  switch (rc)
1865  {
1866  case TAR_OK:
1867  break;
1868  case TAR_NAME_TOO_LONG:
1869  ereport(ERROR,
1870  (errmsg("file name too long for tar format: \"%s\"",
1871  filename)));
1872  break;
1873  case TAR_SYMLINK_TOO_LONG:
1874  ereport(ERROR,
1875  (errmsg("symbolic link target too long for tar format: "
1876  "file name \"%s\", target \"%s\"",
1877  filename, linktarget)));
1878  break;
1879  default:
1880  elog(ERROR, "unrecognized tar error: %d", rc);
1881  }
1882 
1883  pq_putmessage('d', h, sizeof(h));
1884  update_basebackup_progress(sizeof(h));
1885  }
1886 
1887  return sizeof(h);
1888 }
Definition: pgtar.h:21
short st_uid
Definition: win32_port.h:270
tarError
Definition: pgtar.h:19
#define ERROR
Definition: elog.h:46
short st_gid
Definition: win32_port.h:271
#define TAR_BLOCK_SIZE
Definition: pgtar.h:17
__int64 st_size
Definition: win32_port.h:273
enum tarError tarCreateHeader(char *h, const char *filename, const char *linktarget, pgoff_t size, mode_t mode, uid_t uid, gid_t gid, time_t mtime)
Definition: tar.c:114
unsigned short st_mode
Definition: win32_port.h:268
#define ereport(elevel,...)
Definition: elog.h:157
static void update_basebackup_progress(int64 delta)
Definition: basebackup.c:1986
static char * filename
Definition: pg_dumpall.c:92
int errmsg(const char *fmt,...)
Definition: elog.c:909
#define elog(elevel,...)
Definition: elog.h:232
__time64_t st_mtime
Definition: win32_port.h:275
#define pq_putmessage(msgtype, s, len)
Definition: libpq.h:49

◆ basebackup_read_file()

static int basebackup_read_file ( int  fd,
char *  buf,
size_t  nbytes,
off_t  offset,
const char *  filename,
bool  partial_read_ok 
)
static

Definition at line 2023 of file basebackup.c.

References ereport, errcode_for_file_access(), errmsg(), ERROR, pg_pread(), pgstat_report_wait_end(), pgstat_report_wait_start(), and WAIT_EVENT_BASEBACKUP_READ.

Referenced by perform_base_backup(), and sendFile().

2025 {
2026  int rc;
2027 
2029  rc = pg_pread(fd, buf, nbytes, offset);
2031 
2032  if (rc < 0)
2033  ereport(ERROR,
2035  errmsg("could not read file \"%s\": %m", filename)));
2036  if (!partial_read_ok && rc > 0 && rc != nbytes)
2037  ereport(ERROR,
2039  errmsg("could not read file \"%s\": read %d of %zu",
2040  filename, rc, nbytes)));
2041 
2042  return rc;
2043 }
static void pgstat_report_wait_end(void)
Definition: wait_event.h:274
static int fd(const char *x, int i)
Definition: preproc-init.c:105
ssize_t pg_pread(int fd, void *buf, size_t nbyte, off_t offset)
Definition: pread.c:27
#define ERROR
Definition: elog.h:46
static char * buf
Definition: pg_test_fsync.c:68
int errcode_for_file_access(void)
Definition: elog.c:721
static void pgstat_report_wait_start(uint32 wait_event_info)
Definition: wait_event.h:258
#define ereport(elevel,...)
Definition: elog.h:157
static char * filename
Definition: pg_dumpall.c:92
int errmsg(const char *fmt,...)
Definition: elog.c:909

◆ compareWalFileNames()

static int compareWalFileNames ( const ListCell a,
const ListCell b 
)
static

Definition at line 750 of file basebackup.c.

References lfirst.

Referenced by perform_base_backup().

751 {
752  char *fna = (char *) lfirst(a);
753  char *fnb = (char *) lfirst(b);
754 
755  return strcmp(fna + 8, fnb + 8);
756 }
#define lfirst(lc)
Definition: pg_list.h:169

◆ convert_link_to_directory()

static void convert_link_to_directory ( const char *  pathbuf,
struct stat statbuf 
)
static

Definition at line 1895 of file basebackup.c.

References pg_dir_create_mode, pgwin32_is_junction(), and stat::st_mode.

Referenced by sendDir().

1896 {
1897  /* If symlink, write it as a directory anyway */
1898 #ifndef WIN32
1899  if (S_ISLNK(statbuf->st_mode))
1900 #else
1901  if (pgwin32_is_junction(pathbuf))
1902 #endif
1903  statbuf->st_mode = S_IFDIR | pg_dir_create_mode;
1904 }
int pg_dir_create_mode
Definition: file_perm.c:18
unsigned short st_mode
Definition: win32_port.h:268
bool pgwin32_is_junction(const char *path)

◆ is_checksummed_file()

static bool is_checksummed_file ( const char *  fullpath,
const char *  filename 
)
static

Definition at line 1550 of file basebackup.c.

References exclude_list_item::match_prefix, and exclude_list_item::name.

Referenced by sendFile().

1551 {
1552  /* Check that the file is in a tablespace */
1553  if (strncmp(fullpath, "./global/", 9) == 0 ||
1554  strncmp(fullpath, "./base/", 7) == 0 ||
1555  strncmp(fullpath, "/", 1) == 0)
1556  {
1557  int excludeIdx;
1558 
1559  /* Compare file against noChecksumFiles skip list */
1560  for (excludeIdx = 0; noChecksumFiles[excludeIdx].name != NULL; excludeIdx++)
1561  {
1562  int cmplen = strlen(noChecksumFiles[excludeIdx].name);
1563 
1564  if (!noChecksumFiles[excludeIdx].match_prefix)
1565  cmplen++;
1566  if (strncmp(filename, noChecksumFiles[excludeIdx].name,
1567  cmplen) == 0)
1568  return false;
1569  }
1570 
1571  return true;
1572  }
1573  else
1574  return false;
1575 }
static const struct exclude_list_item noChecksumFiles[]
Definition: basebackup.c:238
const char * name
Definition: encode.c:561
const char * name
Definition: basebackup.c:141
static char * filename
Definition: pg_dumpall.c:92

◆ parse_basebackup_options()

static void parse_basebackup_options ( List options,
basebackup_options opt 
)
static

Definition at line 762 of file basebackup.c.

References CHECKSUM_TYPE_CRC32C, CHECKSUM_TYPE_NONE, defGetBoolean(), defGetInt64(), defGetString(), DefElem::defname, ereport, errcode(), errmsg(), ERROR, basebackup_options::fastcheckpoint, basebackup_options::includewal, basebackup_options::label, lfirst, basebackup_options::manifest, basebackup_options::manifest_checksum_type, MANIFEST_OPTION_FORCE_ENCODE, MANIFEST_OPTION_NO, MANIFEST_OPTION_YES, MAX_RATE_LOWER, MAX_RATE_UPPER, basebackup_options::maxrate, maxrate, MemSet, noverify_checksums, basebackup_options::nowait, parse_bool(), pg_checksum_parse_type(), pg_strcasecmp(), basebackup_options::progress, and basebackup_options::sendtblspcmapfile.

Referenced by SendBaseBackup().

763 {
764  ListCell *lopt;
765  bool o_label = false;
766  bool o_progress = false;
767  bool o_checkpoint = false;
768  bool o_nowait = false;
769  bool o_wal = false;
770  bool o_maxrate = false;
771  bool o_tablespace_map = false;
772  bool o_noverify_checksums = false;
773  bool o_manifest = false;
774  bool o_manifest_checksums = false;
775 
776  MemSet(opt, 0, sizeof(*opt));
779 
780  foreach(lopt, options)
781  {
782  DefElem *defel = (DefElem *) lfirst(lopt);
783 
784  if (strcmp(defel->defname, "label") == 0)
785  {
786  if (o_label)
787  ereport(ERROR,
788  (errcode(ERRCODE_SYNTAX_ERROR),
789  errmsg("duplicate option \"%s\"", defel->defname)));
790  opt->label = defGetString(defel);
791  o_label = true;
792  }
793  else if (strcmp(defel->defname, "progress") == 0)
794  {
795  if (o_progress)
796  ereport(ERROR,
797  (errcode(ERRCODE_SYNTAX_ERROR),
798  errmsg("duplicate option \"%s\"", defel->defname)));
799  opt->progress = defGetBoolean(defel);
800  o_progress = true;
801  }
802  else if (strcmp(defel->defname, "checkpoint") == 0)
803  {
804  char *optval = defGetString(defel);
805 
806  if (o_checkpoint)
807  ereport(ERROR,
808  (errcode(ERRCODE_SYNTAX_ERROR),
809  errmsg("duplicate option \"%s\"", defel->defname)));
810  if (pg_strcasecmp(optval, "fast") == 0)
811  opt->fastcheckpoint = true;
812  else if (pg_strcasecmp(optval, "spread") == 0)
813  opt->fastcheckpoint = false;
814  else
815  ereport(ERROR,
816  (errcode(ERRCODE_SYNTAX_ERROR),
817  errmsg("unrecognized checkpoint type: \"%s\"",
818  optval)));
819  o_checkpoint = true;
820  }
821  else if (strcmp(defel->defname, "wait") == 0)
822  {
823  if (o_nowait)
824  ereport(ERROR,
825  (errcode(ERRCODE_SYNTAX_ERROR),
826  errmsg("duplicate option \"%s\"", defel->defname)));
827  opt->nowait = !defGetBoolean(defel);
828  o_nowait = true;
829  }
830  else if (strcmp(defel->defname, "wal") == 0)
831  {
832  if (o_wal)
833  ereport(ERROR,
834  (errcode(ERRCODE_SYNTAX_ERROR),
835  errmsg("duplicate option \"%s\"", defel->defname)));
836  opt->includewal = defGetBoolean(defel);
837  o_wal = true;
838  }
839  else if (strcmp(defel->defname, "max_rate") == 0)
840  {
841  int64 maxrate;
842 
843  if (o_maxrate)
844  ereport(ERROR,
845  (errcode(ERRCODE_SYNTAX_ERROR),
846  errmsg("duplicate option \"%s\"", defel->defname)));
847 
848  maxrate = defGetInt64(defel);
849  if (maxrate < MAX_RATE_LOWER || maxrate > MAX_RATE_UPPER)
850  ereport(ERROR,
851  (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
852  errmsg("%d is outside the valid range for parameter \"%s\" (%d .. %d)",
853  (int) maxrate, "MAX_RATE", MAX_RATE_LOWER, MAX_RATE_UPPER)));
854 
855  opt->maxrate = (uint32) maxrate;
856  o_maxrate = true;
857  }
858  else if (strcmp(defel->defname, "tablespace_map") == 0)
859  {
860  if (o_tablespace_map)
861  ereport(ERROR,
862  (errcode(ERRCODE_SYNTAX_ERROR),
863  errmsg("duplicate option \"%s\"", defel->defname)));
864  opt->sendtblspcmapfile = defGetBoolean(defel);
865  o_tablespace_map = true;
866  }
867  else if (strcmp(defel->defname, "verify_checksums") == 0)
868  {
869  if (o_noverify_checksums)
870  ereport(ERROR,
871  (errcode(ERRCODE_SYNTAX_ERROR),
872  errmsg("duplicate option \"%s\"", defel->defname)));
874  o_noverify_checksums = true;
875  }
876  else if (strcmp(defel->defname, "manifest") == 0)
877  {
878  char *optval = defGetString(defel);
879  bool manifest_bool;
880 
881  if (o_manifest)
882  ereport(ERROR,
883  (errcode(ERRCODE_SYNTAX_ERROR),
884  errmsg("duplicate option \"%s\"", defel->defname)));
885  if (parse_bool(optval, &manifest_bool))
886  {
887  if (manifest_bool)
889  else
891  }
892  else if (pg_strcasecmp(optval, "force-encode") == 0)
894  else
895  ereport(ERROR,
896  (errcode(ERRCODE_SYNTAX_ERROR),
897  errmsg("unrecognized manifest option: \"%s\"",
898  optval)));
899  o_manifest = true;
900  }
901  else if (strcmp(defel->defname, "manifest_checksums") == 0)
902  {
903  char *optval = defGetString(defel);
904 
905  if (o_manifest_checksums)
906  ereport(ERROR,
907  (errcode(ERRCODE_SYNTAX_ERROR),
908  errmsg("duplicate option \"%s\"", defel->defname)));
909  if (!pg_checksum_parse_type(optval,
910  &opt->manifest_checksum_type))
911  ereport(ERROR,
912  (errcode(ERRCODE_SYNTAX_ERROR),
913  errmsg("unrecognized checksum algorithm: \"%s\"",
914  optval)));
915  o_manifest_checksums = true;
916  }
917  else
918  ereport(ERROR,
919  errcode(ERRCODE_SYNTAX_ERROR),
920  errmsg("option \"%s\" not recognized",
921  defel->defname));
922  }
923  if (opt->label == NULL)
924  opt->label = "base backup";
925  if (opt->manifest == MANIFEST_OPTION_NO)
926  {
927  if (o_manifest_checksums)
928  ereport(ERROR,
929  (errcode(ERRCODE_SYNTAX_ERROR),
930  errmsg("manifest checksums require a backup manifest")));
932  }
933 }
#define MAX_RATE_LOWER
Definition: basebackup.h:20
int errcode(int sqlerrcode)
Definition: elog.c:698
#define MemSet(start, val, len)
Definition: c.h:1008
bool pg_checksum_parse_type(char *name, pg_checksum_type *type)
int64 defGetInt64(DefElem *def)
Definition: define.c:185
bool parse_bool(const char *value, bool *result)
Definition: bool.c:30
int pg_strcasecmp(const char *s1, const char *s2)
Definition: pgstrcasecmp.c:36
bool defGetBoolean(DefElem *def)
Definition: define.c:106
#define MAX_RATE_UPPER
Definition: basebackup.h:21
#define ERROR
Definition: elog.h:46
backup_manifest_option manifest
Definition: basebackup.c:58
static bool noverify_checksums
Definition: basebackup.c:122
char * defGetString(DefElem *def)
Definition: define.c:49
static int32 maxrate
const char * label
Definition: basebackup.c:51
unsigned int uint32
Definition: c.h:441
#define ereport(elevel,...)
Definition: elog.h:157
#define lfirst(lc)
Definition: pg_list.h:169
int errmsg(const char *fmt,...)
Definition: elog.c:909
char * defname
Definition: parsenodes.h:758
pg_checksum_type manifest_checksum_type
Definition: basebackup.c:59

◆ perform_base_backup()

static void perform_base_backup ( basebackup_options opt)
static

Definition at line 256 of file basebackup.c.

References _tarWriteHeader(), AddWALInfoToBackupManifest(), AllocateDir(), Assert, BACKUP_LABEL_FILE, backup_started_in_recovery, backup_streamed, backup_total, basebackup_read_file(), BoolGetDatum, buf, CheckXLogRemoved(), CloseTransientFile(), compareWalFileNames(), CurrentResourceOwner, dirent::d_name, StringInfoData::data, DataDir, do_pg_abort_backup(), do_pg_start_backup(), do_pg_stop_backup(), elapsed_min_unit, ereport, errcode(), ERRCODE_DATA_CORRUPTED, errcode_for_file_access(), errmsg(), errmsg_plural(), ERROR, basebackup_options::fastcheckpoint, fd(), FreeBackupManifest(), FreeDir(), fstat, GetCurrentTimestamp(), basebackup_options::includewal, InitializeBackupManifest(), InvalidOid, is_absolute_path, IsTLHistoryFileName, IsXLogFileName, basebackup_options::label, lappend(), lfirst, linitial, list_length(), list_sort(), lnext(), lstat, makeStringInfo(), basebackup_options::manifest, manifest, basebackup_options::manifest_checksum_type, MAXFNAMELEN, MAXPGPATH, basebackup_options::maxrate, Min, NIL, basebackup_options::nowait, tablespaceinfo::oid, OpenTransientFile(), palloc0(), tablespaceinfo::path, PG_BINARY, PG_END_ENSURE_ERROR_CLEANUP, PG_ENSURE_ERROR_CLEANUP, pgoff_t, pgstat_progress_end_command(), pgstat_progress_start_command(), pgstat_progress_update_multi_param(), pgstat_progress_update_param(), pgstat_stat_directory, pq_beginmessage(), pq_endmessage(), pq_putemptymessage(), pq_putmessage, pq_sendbyte(), pq_sendint16(), basebackup_options::progress, PROGRESS_BASEBACKUP_BACKUP_TOTAL, PROGRESS_BASEBACKUP_PHASE, PROGRESS_BASEBACKUP_PHASE_ESTIMATE_BACKUP_SIZE, PROGRESS_BASEBACKUP_PHASE_STREAM_BACKUP, PROGRESS_BASEBACKUP_PHASE_TRANSFER_WAL, PROGRESS_BASEBACKUP_PHASE_WAIT_CHECKPOINT, PROGRESS_BASEBACKUP_PHASE_WAIT_WAL_ARCHIVE, PROGRESS_BASEBACKUP_TBLSPC_STREAMED, PROGRESS_BASEBACKUP_TBLSPC_TOTAL, PROGRESS_COMMAND_BASEBACKUP, psprintf(), pstrdup(), ReadDir(), RecoveryInProgress(), ResourceOwnerCreate(), SendBackupHeader(), SendBackupManifest(), sendDir(), sendFile(), sendFileWithContent(), sendTablespace(), basebackup_options::sendtblspcmapfile, SendXlogRecPtrResult(), tablespaceinfo::size, snprintf, stat::st_size, startptr, statrelpath, StatusFilePath, TABLESPACE_MAP, TAR_BLOCK_SIZE, TAR_SEND_SIZE, tblspc_map_file, ThisTimeLineID, throttle(), throttled_last, throttling_counter, THROTTLING_FREQUENCY, throttling_sample, total_checksum_failures, update_basebackup_progress(), USECS_PER_SEC, val, wal_segment_size, WalSndResourceCleanup(), WARNING, XLByteToPrevSeg, XLByteToSeg, XLOG_CONTROL_FILE, XLOGDIR, XLogFileName, and XLogFromFileName.

Referenced by SendBaseBackup().

257 {
258  TimeLineID starttli;
259  XLogRecPtr endptr;
260  TimeLineID endtli;
261  StringInfo labelfile;
264  int datadirpathlen;
265  List *tablespaces = NIL;
266 
267  backup_total = 0;
268  backup_streamed = 0;
270 
271  /*
272  * If the estimation of the total backup size is disabled, make the
273  * backup_total column in the view return NULL by setting the parameter to
274  * -1.
275  */
276  if (!opt->progress)
277  {
278  backup_total = -1;
280  backup_total);
281  }
282 
283  /* we're going to use a BufFile, so we need a ResourceOwner */
284  Assert(CurrentResourceOwner == NULL);
285  CurrentResourceOwner = ResourceOwnerCreate(NULL, "base backup");
286 
287  datadirpathlen = strlen(DataDir);
288 
290 
291  labelfile = makeStringInfo();
292  tblspc_map_file = makeStringInfo();
293  InitializeBackupManifest(&manifest, opt->manifest,
295 
297 
300  startptr = do_pg_start_backup(opt->label, opt->fastcheckpoint, &starttli,
301  labelfile, &tablespaces,
302  tblspc_map_file);
303 
304  /*
305  * Once do_pg_start_backup has been called, ensure that any failure causes
306  * us to abort the backup so we don't "leak" a backup counter. For this
307  * reason, *all* functionality between do_pg_start_backup() and the end of
308  * do_pg_stop_backup() should be inside the error cleanup block!
309  */
310 
312  {
313  ListCell *lc;
314  tablespaceinfo *ti;
315  int tblspc_streamed = 0;
316 
317  /*
318  * Calculate the relative path of temporary statistics directory in
319  * order to skip the files which are located in that directory later.
320  */
322  strncmp(pgstat_stat_directory, DataDir, datadirpathlen) == 0)
323  statrelpath = psprintf("./%s", pgstat_stat_directory + datadirpathlen + 1);
324  else if (strncmp(pgstat_stat_directory, "./", 2) != 0)
326  else
328 
329  /* Add a node for the base directory at the end */
330  ti = palloc0(sizeof(tablespaceinfo));
331  ti->size = -1;
332  tablespaces = lappend(tablespaces, ti);
333 
334  /*
335  * Calculate the total backup size by summing up the size of each
336  * tablespace
337  */
338  if (opt->progress)
339  {
342 
343  foreach(lc, tablespaces)
344  {
345  tablespaceinfo *tmp = (tablespaceinfo *) lfirst(lc);
346 
347  if (tmp->path == NULL)
348  tmp->size = sendDir(".", 1, true, tablespaces, true, NULL,
349  NULL);
350  else
351  tmp->size = sendTablespace(tmp->path, tmp->oid, true,
352  NULL);
353  backup_total += tmp->size;
354  }
355  }
356 
357  /* Report that we are now streaming database files as a base backup */
358  {
359  const int index[] = {
363  };
364  const int64 val[] = {
366  backup_total, list_length(tablespaces)
367  };
368 
369  pgstat_progress_update_multi_param(3, index, val);
370  }
371 
372  /* Send the starting position of the backup */
373  SendXlogRecPtrResult(startptr, starttli);
374 
375  /* Send tablespace header */
376  SendBackupHeader(tablespaces);
377 
378  /* Setup and activate network throttling, if client requested it */
379  if (opt->maxrate > 0)
380  {
382  (int64) opt->maxrate * (int64) 1024 / THROTTLING_FREQUENCY;
383 
384  /*
385  * The minimum amount of time for throttling_sample bytes to be
386  * transferred.
387  */
389 
390  /* Enable throttling. */
391  throttling_counter = 0;
392 
393  /* The 'real data' starts now (header was ignored). */
395  }
396  else
397  {
398  /* Disable throttling. */
399  throttling_counter = -1;
400  }
401 
402  /* Send off our tablespaces one by one */
403  foreach(lc, tablespaces)
404  {
405  tablespaceinfo *ti = (tablespaceinfo *) lfirst(lc);
407 
408  /* Send CopyOutResponse message */
409  pq_beginmessage(&buf, 'H');
410  pq_sendbyte(&buf, 0); /* overall format */
411  pq_sendint16(&buf, 0); /* natts */
412  pq_endmessage(&buf);
413 
414  if (ti->path == NULL)
415  {
416  struct stat statbuf;
417  bool sendtblspclinks = true;
418 
419  /* In the main tar, include the backup_label first... */
421  &manifest);
422 
423  /* Then the tablespace_map file, if required... */
424  if (opt->sendtblspcmapfile)
425  {
426  sendFileWithContent(TABLESPACE_MAP, tblspc_map_file->data,
427  &manifest);
428  sendtblspclinks = false;
429  }
430 
431  /* Then the bulk of the files... */
432  sendDir(".", 1, false, tablespaces, sendtblspclinks,
433  &manifest, NULL);
434 
435  /* ... and pg_control after everything else. */
436  if (lstat(XLOG_CONTROL_FILE, &statbuf) != 0)
437  ereport(ERROR,
439  errmsg("could not stat file \"%s\": %m",
442  false, InvalidOid, &manifest, NULL);
443  }
444  else
445  sendTablespace(ti->path, ti->oid, false, &manifest);
446 
447  /*
448  * If we're including WAL, and this is the main data directory we
449  * don't terminate the tar stream here. Instead, we will append
450  * the xlog files below and terminate it then. This is safe since
451  * the main data directory is always sent *last*.
452  */
453  if (opt->includewal && ti->path == NULL)
454  {
455  Assert(lnext(tablespaces, lc) == NULL);
456  }
457  else
458  pq_putemptymessage('c'); /* CopyDone */
459 
460  tblspc_streamed++;
462  tblspc_streamed);
463  }
464 
467  endptr = do_pg_stop_backup(labelfile->data, !opt->nowait, &endtli);
468  }
470 
471 
472  if (opt->includewal)
473  {
474  /*
475  * We've left the last tar file "open", so we can now append the
476  * required WAL files to it.
477  */
478  char pathbuf[MAXPGPATH];
479  XLogSegNo segno;
480  XLogSegNo startsegno;
481  XLogSegNo endsegno;
482  struct stat statbuf;
483  List *historyFileList = NIL;
484  List *walFileList = NIL;
485  char firstoff[MAXFNAMELEN];
486  char lastoff[MAXFNAMELEN];
487  DIR *dir;
488  struct dirent *de;
489  ListCell *lc;
490  TimeLineID tli;
491 
494 
495  /*
496  * I'd rather not worry about timelines here, so scan pg_wal and
497  * include all WAL files in the range between 'startptr' and 'endptr',
498  * regardless of the timeline the file is stamped with. If there are
499  * some spurious WAL files belonging to timelines that don't belong in
500  * this server's history, they will be included too. Normally there
501  * shouldn't be such files, but if there are, there's little harm in
502  * including them.
503  */
504  XLByteToSeg(startptr, startsegno, wal_segment_size);
505  XLogFileName(firstoff, ThisTimeLineID, startsegno, wal_segment_size);
506  XLByteToPrevSeg(endptr, endsegno, wal_segment_size);
507  XLogFileName(lastoff, ThisTimeLineID, endsegno, wal_segment_size);
508 
509  dir = AllocateDir("pg_wal");
510  while ((de = ReadDir(dir, "pg_wal")) != NULL)
511  {
512  /* Does it look like a WAL segment, and is it in the range? */
513  if (IsXLogFileName(de->d_name) &&
514  strcmp(de->d_name + 8, firstoff + 8) >= 0 &&
515  strcmp(de->d_name + 8, lastoff + 8) <= 0)
516  {
517  walFileList = lappend(walFileList, pstrdup(de->d_name));
518  }
519  /* Does it look like a timeline history file? */
520  else if (IsTLHistoryFileName(de->d_name))
521  {
522  historyFileList = lappend(historyFileList, pstrdup(de->d_name));
523  }
524  }
525  FreeDir(dir);
526 
527  /*
528  * Before we go any further, check that none of the WAL segments we
529  * need were removed.
530  */
531  CheckXLogRemoved(startsegno, ThisTimeLineID);
532 
533  /*
534  * Sort the WAL filenames. We want to send the files in order from
535  * oldest to newest, to reduce the chance that a file is recycled
536  * before we get a chance to send it over.
537  */
538  list_sort(walFileList, compareWalFileNames);
539 
540  /*
541  * There must be at least one xlog file in the pg_wal directory, since
542  * we are doing backup-including-xlog.
543  */
544  if (walFileList == NIL)
545  ereport(ERROR,
546  (errmsg("could not find any WAL files")));
547 
548  /*
549  * Sanity check: the first and last segment should cover startptr and
550  * endptr, with no gaps in between.
551  */
552  XLogFromFileName((char *) linitial(walFileList),
553  &tli, &segno, wal_segment_size);
554  if (segno != startsegno)
555  {
556  char startfname[MAXFNAMELEN];
557 
558  XLogFileName(startfname, ThisTimeLineID, startsegno,
560  ereport(ERROR,
561  (errmsg("could not find WAL file \"%s\"", startfname)));
562  }
563  foreach(lc, walFileList)
564  {
565  char *walFileName = (char *) lfirst(lc);
566  XLogSegNo currsegno = segno;
567  XLogSegNo nextsegno = segno + 1;
568 
569  XLogFromFileName(walFileName, &tli, &segno, wal_segment_size);
570  if (!(nextsegno == segno || currsegno == segno))
571  {
572  char nextfname[MAXFNAMELEN];
573 
574  XLogFileName(nextfname, ThisTimeLineID, nextsegno,
576  ereport(ERROR,
577  (errmsg("could not find WAL file \"%s\"", nextfname)));
578  }
579  }
580  if (segno != endsegno)
581  {
582  char endfname[MAXFNAMELEN];
583 
584  XLogFileName(endfname, ThisTimeLineID, endsegno, wal_segment_size);
585  ereport(ERROR,
586  (errmsg("could not find WAL file \"%s\"", endfname)));
587  }
588 
589  /* Ok, we have everything we need. Send the WAL files. */
590  foreach(lc, walFileList)
591  {
592  char *walFileName = (char *) lfirst(lc);
593  int fd;
594  char buf[TAR_SEND_SIZE];
595  size_t cnt;
596  pgoff_t len = 0;
597 
598  snprintf(pathbuf, MAXPGPATH, XLOGDIR "/%s", walFileName);
599  XLogFromFileName(walFileName, &tli, &segno, wal_segment_size);
600 
601  fd = OpenTransientFile(pathbuf, O_RDONLY | PG_BINARY);
602  if (fd < 0)
603  {
604  int save_errno = errno;
605 
606  /*
607  * Most likely reason for this is that the file was already
608  * removed by a checkpoint, so check for that to get a better
609  * error message.
610  */
611  CheckXLogRemoved(segno, tli);
612 
613  errno = save_errno;
614  ereport(ERROR,
616  errmsg("could not open file \"%s\": %m", pathbuf)));
617  }
618 
619  if (fstat(fd, &statbuf) != 0)
620  ereport(ERROR,
622  errmsg("could not stat file \"%s\": %m",
623  pathbuf)));
624  if (statbuf.st_size != wal_segment_size)
625  {
626  CheckXLogRemoved(segno, tli);
627  ereport(ERROR,
629  errmsg("unexpected WAL file size \"%s\"", walFileName)));
630  }
631 
632  /* send the WAL file itself */
633  _tarWriteHeader(pathbuf, NULL, &statbuf, false);
634 
635  while ((cnt = basebackup_read_file(fd, buf,
636  Min(sizeof(buf),
637  wal_segment_size - len),
638  len, pathbuf, true)) > 0)
639  {
640  CheckXLogRemoved(segno, tli);
641  /* Send the chunk as a CopyData message */
642  if (pq_putmessage('d', buf, cnt))
643  ereport(ERROR,
644  (errmsg("base backup could not send data, aborting backup")));
646 
647  len += cnt;
648  throttle(cnt);
649 
650  if (len == wal_segment_size)
651  break;
652  }
653 
654  if (len != wal_segment_size)
655  {
656  CheckXLogRemoved(segno, tli);
657  ereport(ERROR,
659  errmsg("unexpected WAL file size \"%s\"", walFileName)));
660  }
661 
662  /*
663  * wal_segment_size is a multiple of TAR_BLOCK_SIZE, so no need
664  * for padding.
665  */
667 
668  CloseTransientFile(fd);
669 
670  /*
671  * Mark file as archived, otherwise files can get archived again
672  * after promotion of a new node. This is in line with
673  * walreceiver.c always doing an XLogArchiveForceDone() after a
674  * complete segment.
675  */
676  StatusFilePath(pathbuf, walFileName, ".done");
677  sendFileWithContent(pathbuf, "", &manifest);
678  }
679 
680  /*
681  * Send timeline history files too. Only the latest timeline history
682  * file is required for recovery, and even that only if there happens
683  * to be a timeline switch in the first WAL segment that contains the
684  * checkpoint record, or if we're taking a base backup from a standby
685  * server and the target timeline changes while the backup is taken.
686  * But they are small and highly useful for debugging purposes, so
687  * better include them all, always.
688  */
689  foreach(lc, historyFileList)
690  {
691  char *fname = lfirst(lc);
692 
693  snprintf(pathbuf, MAXPGPATH, XLOGDIR "/%s", fname);
694 
695  if (lstat(pathbuf, &statbuf) != 0)
696  ereport(ERROR,
698  errmsg("could not stat file \"%s\": %m", pathbuf)));
699 
700  sendFile(pathbuf, pathbuf, &statbuf, false, InvalidOid,
701  &manifest, NULL);
702 
703  /* unconditionally mark file as archived */
704  StatusFilePath(pathbuf, fname, ".done");
705  sendFileWithContent(pathbuf, "", &manifest);
706  }
707 
708  /* Send CopyDone message for the last tar file */
709  pq_putemptymessage('c');
710  }
711 
712  AddWALInfoToBackupManifest(&manifest, startptr, starttli, endptr, endtli);
713 
714  SendBackupManifest(&manifest);
715 
716  SendXlogRecPtrResult(endptr, endtli);
717 
719  {
720  if (total_checksum_failures > 1)
722  (errmsg_plural("%lld total checksum verification failure",
723  "%lld total checksum verification failures",
726 
727  ereport(ERROR,
729  errmsg("checksum verification failure during base backup")));
730  }
731 
732  /*
733  * Make sure to free the manifest before the resource owners as manifests
734  * use cryptohash contexts that may depend on resource owners (like
735  * OpenSSL).
736  */
737  FreeBackupManifest(&manifest);
738 
739  /* clean up the resource owner we created */
740  WalSndResourceCleanup(true);
741 
743 }
#define StatusFilePath(path, xlog, suffix)
#define NIL
Definition: pg_list.h:65
static void pq_sendint16(StringInfo buf, uint16 i)
Definition: pqformat.h:137
void InitializeBackupManifest(backup_manifest_info *manifest, backup_manifest_option want_manifest, pg_checksum_type manifest_checksum_type)
static int basebackup_read_file(int fd, char *buf, size_t nbytes, off_t offset, const char *filename, bool partial_read_ok)
Definition: basebackup.c:2023
static void throttle(size_t increment)
Definition: basebackup.c:1912
static int64 backup_total
Definition: basebackup.c:128
uint32 TimeLineID
Definition: xlogdefs.h:59
#define PROGRESS_BASEBACKUP_PHASE
Definition: progress.h:123
void do_pg_abort_backup(int code, Datum arg)
Definition: xlog.c:11894
int wal_segment_size
Definition: xlog.c:120
static ListCell * lnext(const List *l, const ListCell *c)
Definition: pg_list.h:322
#define USECS_PER_SEC
Definition: timestamp.h:94
int errmsg_plural(const char *fmt_singular, const char *fmt_plural, unsigned long n,...)
Definition: elog.c:1019
TimestampTz GetCurrentTimestamp(void)
Definition: timestamp.c:1580
#define XLByteToPrevSeg(xlrp, logSegNo, wal_segsz_bytes)
ResourceOwner CurrentResourceOwner
Definition: resowner.c:146
char * pstrdup(const char *in)
Definition: mcxt.c:1299
char * psprintf(const char *fmt,...)
Definition: psprintf.c:46
StringInfo makeStringInfo(void)
Definition: stringinfo.c:41
#define Min(x, y)
Definition: c.h:986
static void SendBackupHeader(List *tablespaces)
Definition: basebackup.c:975
#define PROGRESS_BASEBACKUP_TBLSPC_STREAMED
Definition: progress.h:127
int errcode(int sqlerrcode)
Definition: elog.c:698
#define PROGRESS_BASEBACKUP_PHASE_WAIT_WAL_ARCHIVE
Definition: progress.h:133
void pq_putemptymessage(char msgtype)
Definition: pqformat.c:390
bool RecoveryInProgress(void)
Definition: xlog.c:8341
static bool backup_started_in_recovery
Definition: basebackup.c:88
Definition: dirent.h:9
static int fd(const char *x, int i)
Definition: preproc-init.c:105
#define PG_BINARY
Definition: c.h:1271
void pgstat_progress_end_command(void)
void pq_beginmessage(StringInfo buf, char msgtype)
Definition: pqformat.c:87
void pgstat_progress_update_multi_param(int nparam, const int *index, const int64 *val)
static void pq_sendbyte(StringInfo buf, uint8 byt)
Definition: pqformat.h:161
Definition: type.h:89
#define PROGRESS_BASEBACKUP_PHASE_WAIT_CHECKPOINT
Definition: progress.h:130
#define pgoff_t
Definition: win32_port.h:208
#define TABLESPACE_MAP
Definition: xlog.h:366
#define PG_ENSURE_ERROR_CLEANUP(cleanup_function, arg)
Definition: ipc.h:47
#define fstat
Definition: win32_port.h:282
static void sendFileWithContent(const char *filename, const char *content, backup_manifest_info *manifest)
Definition: basebackup.c:1108
#define linitial(l)
Definition: pg_list.h:174
Definition: dirent.c:25
#define ERROR
Definition: elog.h:46
#define IsXLogFileName(fname)
backup_manifest_option manifest
Definition: basebackup.c:58
XLogRecPtr do_pg_stop_backup(char *labelfile, bool waitforarchive, TimeLineID *stoptli_p)
Definition: xlog.c:11479
int OpenTransientFile(const char *fileName, int fileFlags)
Definition: fd.c:2510
void CheckXLogRemoved(XLogSegNo segno, TimeLineID tli)
Definition: xlog.c:4000
#define MAXPGPATH
#define XLogFromFileName(fname, tli, logSegNo, wal_segsz_bytes)
#define TAR_BLOCK_SIZE
Definition: pgtar.h:17
void pgstat_progress_start_command(ProgressCommandType cmdtype, Oid relid)
static char * buf
Definition: pg_test_fsync.c:68
uint64 XLogSegNo
Definition: xlogdefs.h:48
void SendBackupManifest(backup_manifest_info *manifest)
static int64 backup_streamed
Definition: basebackup.c:131
int errcode_for_file_access(void)
Definition: elog.c:721
#define is_absolute_path(filename)
Definition: port.h:86
const char * label
Definition: basebackup.c:51
static void SendXlogRecPtrResult(XLogRecPtr ptr, TimeLineID tli)
Definition: basebackup.c:1053
static int64 _tarWriteHeader(const char *filename, const char *linktarget, struct stat *statbuf, bool sizeonly)
Definition: basebackup.c:1852
DIR * AllocateDir(const char *dirname)
Definition: fd.c:2721
void FreeBackupManifest(backup_manifest_info *manifest)
static int64 sendTablespace(char *path, char *oid, bool sizeonly, struct backup_manifest_info *manifest)
Definition: basebackup.c:1170
char * pgstat_stat_directory
Definition: pgstat.c:122
static char * statrelpath
Definition: basebackup.c:91
void AddWALInfoToBackupManifest(backup_manifest_info *manifest, XLogRecPtr startptr, TimeLineID starttli, XLogRecPtr endptr, TimeLineID endtli)
#define ERRCODE_DATA_CORRUPTED
Definition: pg_basebackup.c:47
List * lappend(List *list, void *datum)
Definition: list.c:336
int CloseTransientFile(int fd)
Definition: fd.c:2687
#define WARNING
Definition: elog.h:40
#define MAXFNAMELEN
#define PROGRESS_BASEBACKUP_BACKUP_TOTAL
Definition: progress.h:124
void * palloc0(Size size)
Definition: mcxt.c:1093
#define XLOGDIR
#define PROGRESS_BASEBACKUP_TBLSPC_TOTAL
Definition: progress.h:126
#define PROGRESS_BASEBACKUP_PHASE_TRANSFER_WAL
Definition: progress.h:134
void WalSndResourceCleanup(bool isCommit)
Definition: walsender.c:332
#define BoolGetDatum(X)
Definition: postgres.h:446
#define XLOG_CONTROL_FILE
#define InvalidOid
Definition: postgres_ext.h:36
TimeLineID ThisTimeLineID
Definition: xlog.c:195
static TimestampTz throttled_last
Definition: basebackup.c:113
#define ereport(elevel,...)
Definition: elog.h:157
static StringInfo tblspc_map_file
Definition: xlogfuncs.c:45
static void update_basebackup_progress(int64 delta)
Definition: basebackup.c:1986
uint64 XLogRecPtr
Definition: xlogdefs.h:21
#define Assert(condition)
Definition: c.h:804
#define lfirst(lc)
Definition: pg_list.h:169
void pgstat_progress_update_param(int index, int64 val)
struct dirent * ReadDir(DIR *dir, const char *dirname)
Definition: fd.c:2787
XLogRecPtr do_pg_start_backup(const char *backupidstr, bool fast, TimeLineID *starttli_p, StringInfo labelfile, List **tablespaces, StringInfo tblspcmapfile)
Definition: xlog.c:10961
#define THROTTLING_FREQUENCY
Definition: basebackup.c:101
static bool manifest
#define XLogFileName(fname, tli, logSegNo, wal_segsz_bytes)
static int list_length(const List *l)
Definition: pg_list.h:149
#define PG_END_ENSURE_ERROR_CLEANUP(cleanup_function, arg)
Definition: ipc.h:52
#define PROGRESS_BASEBACKUP_PHASE_ESTIMATE_BACKUP_SIZE
Definition: progress.h:131
#define lstat(path, sb)
Definition: win32_port.h:284
#define PROGRESS_BASEBACKUP_PHASE_STREAM_BACKUP
Definition: progress.h:132
#define IsTLHistoryFileName(fname)
static int compareWalFileNames(const ListCell *a, const ListCell *b)
Definition: basebackup.c:750
static int64 sendDir(const char *path, int basepathlen, bool sizeonly, List *tablespaces, bool sendtblspclinks, backup_manifest_info *manifest, const char *spcoid)
Definition: basebackup.c:1223
void list_sort(List *list, list_sort_comparator cmp)
Definition: list.c:1496
int errmsg(const char *fmt,...)
Definition: elog.c:909
void pq_endmessage(StringInfo buf)
Definition: pqformat.c:298
#define TAR_SEND_SIZE
Definition: basebackup.c:96
static bool sendFile(const char *readfilename, const char *tarfilename, struct stat *statbuf, bool missing_ok, Oid dboid, backup_manifest_info *manifest, const char *spcoid)
Definition: basebackup.c:1596
char * DataDir
Definition: globals.c:65
#define BACKUP_LABEL_FILE
Definition: xlog.h:363
pg_checksum_type manifest_checksum_type
Definition: basebackup.c:59
char d_name[MAX_PATH]
Definition: dirent.h:15
#define pq_putmessage(msgtype, s, len)
Definition: libpq.h:49
static int64 throttling_counter
Definition: basebackup.c:107
Definition: pg_list.h:50
#define snprintf
Definition: port.h:217
static uint64 throttling_sample
Definition: basebackup.c:104
long val
Definition: informix.c:664
int FreeDir(DIR *dir)
Definition: fd.c:2839
static TimeOffset elapsed_min_unit
Definition: basebackup.c:110
static XLogRecPtr startptr
Definition: basebackup.c:116
ResourceOwner ResourceOwnerCreate(ResourceOwner parent, const char *name)
Definition: resowner.c:428
static long long int total_checksum_failures
Definition: basebackup.c:119
#define XLByteToSeg(xlrp, logSegNo, wal_segsz_bytes)

◆ send_int8_string()

static void send_int8_string ( StringInfoData buf,
int64  intval 
)
static

Definition at line 965 of file basebackup.c.

References INT64_FORMAT, pq_sendbytes(), pq_sendint32(), and sprintf.

Referenced by SendBackupHeader().

966 {
967  char is[32];
968 
969  sprintf(is, INT64_FORMAT, intval);
970  pq_sendint32(buf, strlen(is));
971  pq_sendbytes(buf, is, strlen(is));
972 }
static void pq_sendint32(StringInfo buf, uint32 i)
Definition: pqformat.h:145
#define sprintf
Definition: port.h:219
#define INT64_FORMAT
Definition: c.h:483
void pq_sendbytes(StringInfo buf, const char *data, int datalen)
Definition: pqformat.c:125

◆ SendBackupHeader()

static void SendBackupHeader ( List tablespaces)
static

Definition at line 975 of file basebackup.c.

References buf, lfirst, tablespaceinfo::oid, tablespaceinfo::path, pq_beginmessage(), pq_endmessage(), pq_puttextmessage(), pq_sendbytes(), pq_sendint16(), pq_sendint32(), pq_sendstring(), send_int8_string(), and tablespaceinfo::size.

Referenced by perform_base_backup().

976 {
978  ListCell *lc;
979 
980  /* Construct and send the directory information */
981  pq_beginmessage(&buf, 'T'); /* RowDescription */
982  pq_sendint16(&buf, 3); /* 3 fields */
983 
984  /* First field - spcoid */
985  pq_sendstring(&buf, "spcoid");
986  pq_sendint32(&buf, 0); /* table oid */
987  pq_sendint16(&buf, 0); /* attnum */
988  pq_sendint32(&buf, OIDOID); /* type oid */
989  pq_sendint16(&buf, 4); /* typlen */
990  pq_sendint32(&buf, 0); /* typmod */
991  pq_sendint16(&buf, 0); /* format code */
992 
993  /* Second field - spclocation */
994  pq_sendstring(&buf, "spclocation");
995  pq_sendint32(&buf, 0);
996  pq_sendint16(&buf, 0);
997  pq_sendint32(&buf, TEXTOID);
998  pq_sendint16(&buf, -1);
999  pq_sendint32(&buf, 0);
1000  pq_sendint16(&buf, 0);
1001 
1002  /* Third field - size */
1003  pq_sendstring(&buf, "size");
1004  pq_sendint32(&buf, 0);
1005  pq_sendint16(&buf, 0);
1006  pq_sendint32(&buf, INT8OID);
1007  pq_sendint16(&buf, 8);
1008  pq_sendint32(&buf, 0);
1009  pq_sendint16(&buf, 0);
1010  pq_endmessage(&buf);
1011 
1012  foreach(lc, tablespaces)
1013  {
1014  tablespaceinfo *ti = lfirst(lc);
1015 
1016  /* Send one datarow message */
1017  pq_beginmessage(&buf, 'D');
1018  pq_sendint16(&buf, 3); /* number of columns */
1019  if (ti->path == NULL)
1020  {
1021  pq_sendint32(&buf, -1); /* Length = -1 ==> NULL */
1022  pq_sendint32(&buf, -1);
1023  }
1024  else
1025  {
1026  Size len;
1027 
1028  len = strlen(ti->oid);
1029  pq_sendint32(&buf, len);
1030  pq_sendbytes(&buf, ti->oid, len);
1031 
1032  len = strlen(ti->path);
1033  pq_sendint32(&buf, len);
1034  pq_sendbytes(&buf, ti->path, len);
1035  }
1036  if (ti->size >= 0)
1037  send_int8_string(&buf, ti->size / 1024);
1038  else
1039  pq_sendint32(&buf, -1); /* NULL */
1040 
1041  pq_endmessage(&buf);
1042  }
1043 
1044  /* Send a CommandComplete message */
1045  pq_puttextmessage('C', "SELECT");
1046 }
static void pq_sendint16(StringInfo buf, uint16 i)
Definition: pqformat.h:137
void pq_sendstring(StringInfo buf, const char *str)
Definition: pqformat.c:197
static void send_int8_string(StringInfoData *buf, int64 intval)
Definition: basebackup.c:965
void pq_beginmessage(StringInfo buf, char msgtype)
Definition: pqformat.c:87
static void pq_sendint32(StringInfo buf, uint32 i)
Definition: pqformat.h:145
static char * buf
Definition: pg_test_fsync.c:68
#define lfirst(lc)
Definition: pg_list.h:169
size_t Size
Definition: c.h:540
void pq_sendbytes(StringInfo buf, const char *data, int datalen)
Definition: pqformat.c:125
void pq_endmessage(StringInfo buf)
Definition: pqformat.c:298
void pq_puttextmessage(char msgtype, const char *str)
Definition: pqformat.c:369

◆ SendBaseBackup()

void SendBaseBackup ( BaseBackupCmd cmd)

Definition at line 944 of file basebackup.c.

References basebackup_options::label, BaseBackupCmd::options, parse_basebackup_options(), perform_base_backup(), set_ps_display(), snprintf, update_process_title, WalSndSetState(), and WALSNDSTATE_BACKUP.

Referenced by exec_replication_command().

945 {
946  basebackup_options opt;
947 
948  parse_basebackup_options(cmd->options, &opt);
949 
951 
953  {
954  char activitymsg[50];
955 
956  snprintf(activitymsg, sizeof(activitymsg), "sending backup \"%s\"",
957  opt.label);
958  set_ps_display(activitymsg);
959  }
960 
961  perform_base_backup(&opt);
962 }
List * options
Definition: replnodes.h:44
bool update_process_title
Definition: ps_status.c:36
static void parse_basebackup_options(List *options, basebackup_options *opt)
Definition: basebackup.c:762
void set_ps_display(const char *activity)
Definition: ps_status.c:349
const char * label
Definition: basebackup.c:51
static void perform_base_backup(basebackup_options *opt)
Definition: basebackup.c:256
void WalSndSetState(WalSndState state)
Definition: walsender.c:3335
#define snprintf
Definition: port.h:217

◆ sendDir()

static int64 sendDir ( const char *  path,
int  basepathlen,
bool  sizeonly,
List tablespaces,
bool  sendtblspclinks,
backup_manifest_info manifest,
const char *  spcoid 
)
static

Definition at line 1223 of file basebackup.c.

References _tarWriteHeader(), AllocateDir(), atooid, backup_started_in_recovery, CHECK_FOR_INTERRUPTS, convert_link_to_directory(), dirent::d_name, DEBUG1, DEBUG2, elog, ereport, errcode(), errcode_for_file_access(), errhint(), errmsg(), ERROR, excludeDirContents, FreeDir(), INIT_FORKNUM, InvalidOid, last_dir_separator(), lfirst, looks_like_temp_rel_name(), lstat, exclude_list_item::match_prefix, MAXPGPATH, exclude_list_item::name, OIDCHARS, parse_filename_for_nontemp_relation(), PG_TEMP_FILE_PREFIX, pgwin32_is_junction(), ReadDir(), readlink, RecoveryInProgress(), tablespaceinfo::rpath, S_ISDIR, S_ISREG, sendFile(), snprintf, stat::st_mode, stat::st_size, statrelpath, TABLESPACE_VERSION_DIRECTORY, TAR_BLOCK_SIZE, tarPaddingBytesRequired(), and WARNING.

Referenced by perform_base_backup(), and sendTablespace().

1226 {
1227  DIR *dir;
1228  struct dirent *de;
1229  char pathbuf[MAXPGPATH * 2];
1230  struct stat statbuf;
1231  int64 size = 0;
1232  const char *lastDir; /* Split last dir from parent path. */
1233  bool isDbDir = false; /* Does this directory contain relations? */
1234 
1235  /*
1236  * Determine if the current path is a database directory that can contain
1237  * relations.
1238  *
1239  * Start by finding the location of the delimiter between the parent path
1240  * and the current path.
1241  */
1242  lastDir = last_dir_separator(path);
1243 
1244  /* Does this path look like a database path (i.e. all digits)? */
1245  if (lastDir != NULL &&
1246  strspn(lastDir + 1, "0123456789") == strlen(lastDir + 1))
1247  {
1248  /* Part of path that contains the parent directory. */
1249  int parentPathLen = lastDir - path;
1250 
1251  /*
1252  * Mark path as a database directory if the parent path is either
1253  * $PGDATA/base or a tablespace version path.
1254  */
1255  if (strncmp(path, "./base", parentPathLen) == 0 ||
1256  (parentPathLen >= (sizeof(TABLESPACE_VERSION_DIRECTORY) - 1) &&
1257  strncmp(lastDir - (sizeof(TABLESPACE_VERSION_DIRECTORY) - 1),
1259  sizeof(TABLESPACE_VERSION_DIRECTORY) - 1) == 0))
1260  isDbDir = true;
1261  }
1262 
1263  dir = AllocateDir(path);
1264  while ((de = ReadDir(dir, path)) != NULL)
1265  {
1266  int excludeIdx;
1267  bool excludeFound;
1268  ForkNumber relForkNum; /* Type of fork if file is a relation */
1269  int relOidChars; /* Chars in filename that are the rel oid */
1270 
1271  /* Skip special stuff */
1272  if (strcmp(de->d_name, ".") == 0 || strcmp(de->d_name, "..") == 0)
1273  continue;
1274 
1275  /* Skip temporary files */
1276  if (strncmp(de->d_name,
1278  strlen(PG_TEMP_FILE_PREFIX)) == 0)
1279  continue;
1280 
1281  /*
1282  * Check if the postmaster has signaled us to exit, and abort with an
1283  * error in that case. The error handler further up will call
1284  * do_pg_abort_backup() for us. Also check that if the backup was
1285  * started while still in recovery, the server wasn't promoted.
1286  * do_pg_stop_backup() will check that too, but it's better to stop
1287  * the backup early than continue to the end and fail there.
1288  */
1291  ereport(ERROR,
1292  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
1293  errmsg("the standby was promoted during online backup"),
1294  errhint("This means that the backup being taken is corrupt "
1295  "and should not be used. "
1296  "Try taking another online backup.")));
1297 
1298  /* Scan for files that should be excluded */
1299  excludeFound = false;
1300  for (excludeIdx = 0; excludeFiles[excludeIdx].name != NULL; excludeIdx++)
1301  {
1302  int cmplen = strlen(excludeFiles[excludeIdx].name);
1303 
1304  if (!excludeFiles[excludeIdx].match_prefix)
1305  cmplen++;
1306  if (strncmp(de->d_name, excludeFiles[excludeIdx].name, cmplen) == 0)
1307  {
1308  elog(DEBUG1, "file \"%s\" excluded from backup", de->d_name);
1309  excludeFound = true;
1310  break;
1311  }
1312  }
1313 
1314  if (excludeFound)
1315  continue;
1316 
1317  /* Exclude all forks for unlogged tables except the init fork */
1318  if (isDbDir &&
1319  parse_filename_for_nontemp_relation(de->d_name, &relOidChars,
1320  &relForkNum))
1321  {
1322  /* Never exclude init forks */
1323  if (relForkNum != INIT_FORKNUM)
1324  {
1325  char initForkFile[MAXPGPATH];
1326  char relOid[OIDCHARS + 1];
1327 
1328  /*
1329  * If any other type of fork, check if there is an init fork
1330  * with the same OID. If so, the file can be excluded.
1331  */
1332  memcpy(relOid, de->d_name, relOidChars);
1333  relOid[relOidChars] = '\0';
1334  snprintf(initForkFile, sizeof(initForkFile), "%s/%s_init",
1335  path, relOid);
1336 
1337  if (lstat(initForkFile, &statbuf) == 0)
1338  {
1339  elog(DEBUG2,
1340  "unlogged relation file \"%s\" excluded from backup",
1341  de->d_name);
1342 
1343  continue;
1344  }
1345  }
1346  }
1347 
1348  /* Exclude temporary relations */
1349  if (isDbDir && looks_like_temp_rel_name(de->d_name))
1350  {
1351  elog(DEBUG2,
1352  "temporary relation file \"%s\" excluded from backup",
1353  de->d_name);
1354 
1355  continue;
1356  }
1357 
1358  snprintf(pathbuf, sizeof(pathbuf), "%s/%s", path, de->d_name);
1359 
1360  /* Skip pg_control here to back up it last */
1361  if (strcmp(pathbuf, "./global/pg_control") == 0)
1362  continue;
1363 
1364  if (lstat(pathbuf, &statbuf) != 0)
1365  {
1366  if (errno != ENOENT)
1367  ereport(ERROR,
1369  errmsg("could not stat file or directory \"%s\": %m",
1370  pathbuf)));
1371 
1372  /* If the file went away while scanning, it's not an error. */
1373  continue;
1374  }
1375 
1376  /* Scan for directories whose contents should be excluded */
1377  excludeFound = false;
1378  for (excludeIdx = 0; excludeDirContents[excludeIdx] != NULL; excludeIdx++)
1379  {
1380  if (strcmp(de->d_name, excludeDirContents[excludeIdx]) == 0)
1381  {
1382  elog(DEBUG1, "contents of directory \"%s\" excluded from backup", de->d_name);
1383  convert_link_to_directory(pathbuf, &statbuf);
1384  size += _tarWriteHeader(pathbuf + basepathlen + 1, NULL, &statbuf,
1385  sizeonly);
1386  excludeFound = true;
1387  break;
1388  }
1389  }
1390 
1391  if (excludeFound)
1392  continue;
1393 
1394  /*
1395  * Exclude contents of directory specified by statrelpath if not set
1396  * to the default (pg_stat_tmp) which is caught in the loop above.
1397  */
1398  if (statrelpath != NULL && strcmp(pathbuf, statrelpath) == 0)
1399  {
1400  elog(DEBUG1, "contents of directory \"%s\" excluded from backup", statrelpath);
1401  convert_link_to_directory(pathbuf, &statbuf);
1402  size += _tarWriteHeader(pathbuf + basepathlen + 1, NULL, &statbuf,
1403  sizeonly);
1404  continue;
1405  }
1406 
1407  /*
1408  * We can skip pg_wal, the WAL segments need to be fetched from the
1409  * WAL archive anyway. But include it as an empty directory anyway, so
1410  * we get permissions right.
1411  */
1412  if (strcmp(pathbuf, "./pg_wal") == 0)
1413  {
1414  /* If pg_wal is a symlink, write it as a directory anyway */
1415  convert_link_to_directory(pathbuf, &statbuf);
1416  size += _tarWriteHeader(pathbuf + basepathlen + 1, NULL, &statbuf,
1417  sizeonly);
1418 
1419  /*
1420  * Also send archive_status directory (by hackishly reusing
1421  * statbuf from above ...).
1422  */
1423  size += _tarWriteHeader("./pg_wal/archive_status", NULL, &statbuf,
1424  sizeonly);
1425 
1426  continue; /* don't recurse into pg_wal */
1427  }
1428 
1429  /* Allow symbolic links in pg_tblspc only */
1430  if (strcmp(path, "./pg_tblspc") == 0 &&
1431 #ifndef WIN32
1432  S_ISLNK(statbuf.st_mode)
1433 #else
1434  pgwin32_is_junction(pathbuf)
1435 #endif
1436  )
1437  {
1438 #if defined(HAVE_READLINK) || defined(WIN32)
1439  char linkpath[MAXPGPATH];
1440  int rllen;
1441 
1442  rllen = readlink(pathbuf, linkpath, sizeof(linkpath));
1443  if (rllen < 0)
1444  ereport(ERROR,
1446  errmsg("could not read symbolic link \"%s\": %m",
1447  pathbuf)));
1448  if (rllen >= sizeof(linkpath))
1449  ereport(ERROR,
1450  (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
1451  errmsg("symbolic link \"%s\" target is too long",
1452  pathbuf)));
1453  linkpath[rllen] = '\0';
1454 
1455  size += _tarWriteHeader(pathbuf + basepathlen + 1, linkpath,
1456  &statbuf, sizeonly);
1457 #else
1458 
1459  /*
1460  * If the platform does not have symbolic links, it should not be
1461  * possible to have tablespaces - clearly somebody else created
1462  * them. Warn about it and ignore.
1463  */
1464  ereport(WARNING,
1465  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1466  errmsg("tablespaces are not supported on this platform")));
1467  continue;
1468 #endif /* HAVE_READLINK */
1469  }
1470  else if (S_ISDIR(statbuf.st_mode))
1471  {
1472  bool skip_this_dir = false;
1473  ListCell *lc;
1474 
1475  /*
1476  * Store a directory entry in the tar file so we can get the
1477  * permissions right.
1478  */
1479  size += _tarWriteHeader(pathbuf + basepathlen + 1, NULL, &statbuf,
1480  sizeonly);
1481 
1482  /*
1483  * Call ourselves recursively for a directory, unless it happens
1484  * to be a separate tablespace located within PGDATA.
1485  */
1486  foreach(lc, tablespaces)
1487  {
1488  tablespaceinfo *ti = (tablespaceinfo *) lfirst(lc);
1489 
1490  /*
1491  * ti->rpath is the tablespace relative path within PGDATA, or
1492  * NULL if the tablespace has been properly located somewhere
1493  * else.
1494  *
1495  * Skip past the leading "./" in pathbuf when comparing.
1496  */
1497  if (ti->rpath && strcmp(ti->rpath, pathbuf + 2) == 0)
1498  {
1499  skip_this_dir = true;
1500  break;
1501  }
1502  }
1503 
1504  /*
1505  * skip sending directories inside pg_tblspc, if not required.
1506  */
1507  if (strcmp(pathbuf, "./pg_tblspc") == 0 && !sendtblspclinks)
1508  skip_this_dir = true;
1509 
1510  if (!skip_this_dir)
1511  size += sendDir(pathbuf, basepathlen, sizeonly, tablespaces,
1512  sendtblspclinks, manifest, spcoid);
1513  }
1514  else if (S_ISREG(statbuf.st_mode))
1515  {
1516  bool sent = false;
1517 
1518  if (!sizeonly)
1519  sent = sendFile(pathbuf, pathbuf + basepathlen + 1, &statbuf,
1520  true, isDbDir ? atooid(lastDir + 1) : InvalidOid,
1521  manifest, spcoid);
1522 
1523  if (sent || sizeonly)
1524  {
1525  /* Add size. */
1526  size += statbuf.st_size;
1527 
1528  /* Pad to a multiple of the tar block size. */
1529  size += tarPaddingBytesRequired(statbuf.st_size);
1530 
1531  /* Size of the header for the file. */
1532  size += TAR_BLOCK_SIZE;
1533  }
1534  }
1535  else
1536  ereport(WARNING,
1537  (errmsg("skipping special file \"%s\"", pathbuf)));
1538  }
1539  FreeDir(dir);
1540  return size;
1541 }
#define DEBUG1
Definition: elog.h:25
int errhint(const char *fmt,...)
Definition: elog.c:1156
char * rpath
Definition: basebackup.h:32
int errcode(int sqlerrcode)
Definition: elog.c:698
bool RecoveryInProgress(void)
Definition: xlog.c:8341
static bool backup_started_in_recovery
Definition: basebackup.c:88
Definition: dirent.h:9
static const char *const excludeDirContents[]
Definition: basebackup.c:153
Definition: dirent.c:25
#define ERROR
Definition: elog.h:46
#define PG_TEMP_FILE_PREFIX
Definition: pg_checksums.c:63
#define MAXPGPATH
#define DEBUG2
Definition: elog.h:24
#define TAR_BLOCK_SIZE
Definition: pgtar.h:17
#define TABLESPACE_VERSION_DIRECTORY
Definition: relpath.h:26
#define readlink(path, buf, size)
Definition: win32_port.h:236
int errcode_for_file_access(void)
Definition: elog.c:721
static int64 _tarWriteHeader(const char *filename, const char *linktarget, struct stat *statbuf, bool sizeonly)
Definition: basebackup.c:1852
DIR * AllocateDir(const char *dirname)
Definition: fd.c:2721
#define atooid(x)
Definition: postgres_ext.h:42
static char * statrelpath
Definition: basebackup.c:91
ForkNumber
Definition: relpath.h:40
#define S_ISREG(m)
Definition: win32_port.h:327
#define WARNING
Definition: elog.h:40
static size_t tarPaddingBytesRequired(size_t len)
Definition: pgtar.h:40
char * last_dir_separator(const char *filename)
Definition: path.c:138
#define InvalidOid
Definition: postgres_ext.h:36
#define ereport(elevel,...)
Definition: elog.h:157
#define lfirst(lc)
Definition: pg_list.h:169
struct dirent * ReadDir(DIR *dir, const char *dirname)
Definition: fd.c:2787
bool looks_like_temp_rel_name(const char *name)
Definition: fd.c:3332
bool parse_filename_for_nontemp_relation(const char *name, int *oidchars, ForkNumber *fork)
Definition: reinit.c:381
const char * name
Definition: encode.c:561
#define S_ISDIR(m)
Definition: win32_port.h:324
#define lstat(path, sb)
Definition: win32_port.h:284
const char * name
Definition: basebackup.c:141
static int64 sendDir(const char *path, int basepathlen, bool sizeonly, List *tablespaces, bool sendtblspclinks, backup_manifest_info *manifest, const char *spcoid)
Definition: basebackup.c:1223
int errmsg(const char *fmt,...)
Definition: elog.c:909
#define elog(elevel,...)
Definition: elog.h:232
static bool sendFile(const char *readfilename, const char *tarfilename, struct stat *statbuf, bool missing_ok, Oid dboid, backup_manifest_info *manifest, const char *spcoid)
Definition: basebackup.c:1596
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:120
char d_name[MAX_PATH]
Definition: dirent.h:15
static void convert_link_to_directory(const char *pathbuf, struct stat *statbuf)
Definition: basebackup.c:1895
static const struct exclude_list_item excludeFiles[]
Definition: basebackup.c:194
#define snprintf
Definition: port.h:217
#define OIDCHARS
Definition: relpath.h:30
int FreeDir(DIR *dir)
Definition: fd.c:2839
bool pgwin32_is_junction(const char *path)

◆ sendFile()

static bool sendFile ( const char *  readfilename,
const char *  tarfilename,
struct stat statbuf,
bool  missing_ok,
Oid  dboid,
backup_manifest_info manifest,
const char *  spcoid 
)
static

Definition at line 1596 of file basebackup.c.

References _tarWriteHeader(), AddFileToBackupManifest(), Assert, basebackup_read_file(), buf, backup_manifest_info::checksum_type, CloseTransientFile(), DataChecksumsEnabled(), elog, ereport, errcode_for_file_access(), errmsg(), errmsg_plural(), ERROR, fd(), filename, i, is_checksummed_file(), last_dir_separator(), MemSet, Min, noverify_checksums, OpenTransientFile(), PageGetLSN, PageIsNew, PageHeaderData::pd_checksum, PG_BINARY, pg_checksum_init(), pg_checksum_page(), pg_checksum_update(), pgoff_t, pgstat_report_checksum_failures_in_db(), pq_putmessage, stat::st_mtime, stat::st_size, startptr, TAR_SEND_SIZE, tarPaddingBytesRequired(), throttle(), total_checksum_failures, update_basebackup_progress(), and WARNING.

Referenced by perform_base_backup(), and sendDir().

1599 {
1600  int fd;
1601  BlockNumber blkno = 0;
1602  bool block_retry = false;
1603  char buf[TAR_SEND_SIZE];
1604  uint16 checksum;
1605  int checksum_failures = 0;
1606  off_t cnt;
1607  int i;
1608  pgoff_t len = 0;
1609  char *page;
1610  size_t pad;
1611  PageHeader phdr;
1612  int segmentno = 0;
1613  char *segmentpath;
1614  bool verify_checksum = false;
1615  pg_checksum_context checksum_ctx;
1616 
1617  if (pg_checksum_init(&checksum_ctx, manifest->checksum_type) < 0)
1618  elog(ERROR, "could not initialize checksum of file \"%s\"",
1619  readfilename);
1620 
1621  fd = OpenTransientFile(readfilename, O_RDONLY | PG_BINARY);
1622  if (fd < 0)
1623  {
1624  if (errno == ENOENT && missing_ok)
1625  return false;
1626  ereport(ERROR,
1628  errmsg("could not open file \"%s\": %m", readfilename)));
1629  }
1630 
1631  _tarWriteHeader(tarfilename, NULL, statbuf, false);
1632 
1634  {
1635  char *filename;
1636 
1637  /*
1638  * Get the filename (excluding path). As last_dir_separator()
1639  * includes the last directory separator, we chop that off by
1640  * incrementing the pointer.
1641  */
1642  filename = last_dir_separator(readfilename) + 1;
1643 
1644  if (is_checksummed_file(readfilename, filename))
1645  {
1646  verify_checksum = true;
1647 
1648  /*
1649  * Cut off at the segment boundary (".") to get the segment number
1650  * in order to mix it into the checksum.
1651  */
1652  segmentpath = strstr(filename, ".");
1653  if (segmentpath != NULL)
1654  {
1655  segmentno = atoi(segmentpath + 1);
1656  if (segmentno == 0)
1657  ereport(ERROR,
1658  (errmsg("invalid segment number %d in file \"%s\"",
1659  segmentno, filename)));
1660  }
1661  }
1662  }
1663 
1664  /*
1665  * Loop until we read the amount of data the caller told us to expect. The
1666  * file could be longer, if it was extended while we were sending it, but
1667  * for a base backup we can ignore such extended data. It will be restored
1668  * from WAL.
1669  */
1670  while (len < statbuf->st_size)
1671  {
1672  /* Try to read some more data. */
1673  cnt = basebackup_read_file(fd, buf,
1674  Min(sizeof(buf), statbuf->st_size - len),
1675  len, readfilename, true);
1676 
1677  /*
1678  * If we hit end-of-file, a concurrent truncation must have occurred.
1679  * That's not an error condition, because WAL replay will fix things
1680  * up.
1681  */
1682  if (cnt == 0)
1683  break;
1684 
1685  /*
1686  * The checksums are verified at block level, so we iterate over the
1687  * buffer in chunks of BLCKSZ, after making sure that
1688  * TAR_SEND_SIZE/buf is divisible by BLCKSZ and we read a multiple of
1689  * BLCKSZ bytes.
1690  */
1691  Assert(TAR_SEND_SIZE % BLCKSZ == 0);
1692 
1693  if (verify_checksum && (cnt % BLCKSZ != 0))
1694  {
1695  ereport(WARNING,
1696  (errmsg("could not verify checksum in file \"%s\", block "
1697  "%u: read buffer size %d and page size %d "
1698  "differ",
1699  readfilename, blkno, (int) cnt, BLCKSZ)));
1700  verify_checksum = false;
1701  }
1702 
1703  if (verify_checksum)
1704  {
1705  for (i = 0; i < cnt / BLCKSZ; i++)
1706  {
1707  page = buf + BLCKSZ * i;
1708 
1709  /*
1710  * Only check pages which have not been modified since the
1711  * start of the base backup. Otherwise, they might have been
1712  * written only halfway and the checksum would not be valid.
1713  * However, replaying WAL would reinstate the correct page in
1714  * this case. We also skip completely new pages, since they
1715  * don't have a checksum yet.
1716  */
1717  if (!PageIsNew(page) && PageGetLSN(page) < startptr)
1718  {
1719  checksum = pg_checksum_page((char *) page, blkno + segmentno * RELSEG_SIZE);
1720  phdr = (PageHeader) page;
1721  if (phdr->pd_checksum != checksum)
1722  {
1723  /*
1724  * Retry the block on the first failure. It's
1725  * possible that we read the first 4K page of the
1726  * block just before postgres updated the entire block
1727  * so it ends up looking torn to us. We only need to
1728  * retry once because the LSN should be updated to
1729  * something we can ignore on the next pass. If the
1730  * error happens again then it is a true validation
1731  * failure.
1732  */
1733  if (block_retry == false)
1734  {
1735  int reread_cnt;
1736 
1737  /* Reread the failed block */
1738  reread_cnt =
1739  basebackup_read_file(fd, buf + BLCKSZ * i,
1740  BLCKSZ, len + BLCKSZ * i,
1741  readfilename,
1742  false);
1743  if (reread_cnt == 0)
1744  {
1745  /*
1746  * If we hit end-of-file, a concurrent
1747  * truncation must have occurred, so break out
1748  * of this loop just as if the initial fread()
1749  * returned 0. We'll drop through to the same
1750  * code that handles that case. (We must fix
1751  * up cnt first, though.)
1752  */
1753  cnt = BLCKSZ * i;
1754  break;
1755  }
1756 
1757  /* Set flag so we know a retry was attempted */
1758  block_retry = true;
1759 
1760  /* Reset loop to validate the block again */
1761  i--;
1762  continue;
1763  }
1764 
1765  checksum_failures++;
1766 
1767  if (checksum_failures <= 5)
1768  ereport(WARNING,
1769  (errmsg("checksum verification failed in "
1770  "file \"%s\", block %u: calculated "
1771  "%X but expected %X",
1772  readfilename, blkno, checksum,
1773  phdr->pd_checksum)));
1774  if (checksum_failures == 5)
1775  ereport(WARNING,
1776  (errmsg("further checksum verification "
1777  "failures in file \"%s\" will not "
1778  "be reported", readfilename)));
1779  }
1780  }
1781  block_retry = false;
1782  blkno++;
1783  }
1784  }
1785 
1786  /* Send the chunk as a CopyData message */
1787  if (pq_putmessage('d', buf, cnt))
1788  ereport(ERROR,
1789  (errmsg("base backup could not send data, aborting backup")));
1791 
1792  /* Also feed it to the checksum machinery. */
1793  if (pg_checksum_update(&checksum_ctx, (uint8 *) buf, cnt) < 0)
1794  elog(ERROR, "could not update checksum of base backup");
1795 
1796  len += cnt;
1797  throttle(cnt);
1798  }
1799 
1800  /* If the file was truncated while we were sending it, pad it with zeros */
1801  if (len < statbuf->st_size)
1802  {
1803  MemSet(buf, 0, sizeof(buf));
1804  while (len < statbuf->st_size)
1805  {
1806  cnt = Min(sizeof(buf), statbuf->st_size - len);
1807  pq_putmessage('d', buf, cnt);
1808  if (pg_checksum_update(&checksum_ctx, (uint8 *) buf, cnt) < 0)
1809  elog(ERROR, "could not update checksum of base backup");
1811  len += cnt;
1812  throttle(cnt);
1813  }
1814  }
1815 
1816  /*
1817  * Pad to a block boundary, per tar format requirements. (This small piece
1818  * of data is probably not worth throttling, and is not checksummed
1819  * because it's not actually part of the file.)
1820  */
1821  pad = tarPaddingBytesRequired(len);
1822  if (pad > 0)
1823  {
1824  MemSet(buf, 0, pad);
1825  pq_putmessage('d', buf, pad);
1827  }
1828 
1829  CloseTransientFile(fd);
1830 
1831  if (checksum_failures > 1)
1832  {
1833  ereport(WARNING,
1834  (errmsg_plural("file \"%s\" has a total of %d checksum verification failure",
1835  "file \"%s\" has a total of %d checksum verification failures",
1836  checksum_failures,
1837  readfilename, checksum_failures)));
1838 
1839  pgstat_report_checksum_failures_in_db(dboid, checksum_failures);
1840  }
1841 
1842  total_checksum_failures += checksum_failures;
1843 
1844  AddFileToBackupManifest(manifest, spcoid, tarfilename, statbuf->st_size,
1845  (pg_time_t) statbuf->st_mtime, &checksum_ctx);
1846 
1847  return true;
1848 }
static int basebackup_read_file(int fd, char *buf, size_t nbytes, off_t offset, const char *filename, bool partial_read_ok)
Definition: basebackup.c:2023
static void throttle(size_t increment)
Definition: basebackup.c:1912
int64 pg_time_t
Definition: pgtime.h:23
int errmsg_plural(const char *fmt_singular, const char *fmt_plural, unsigned long n,...)
Definition: elog.c:1019
bool DataChecksumsEnabled(void)
Definition: xlog.c:5019
#define Min(x, y)
Definition: c.h:986
unsigned char uint8
Definition: c.h:439
#define MemSet(start, val, len)
Definition: c.h:1008
uint32 BlockNumber
Definition: block.h:31
static int fd(const char *x, int i)
Definition: preproc-init.c:105
#define PG_BINARY
Definition: c.h:1271
void pgstat_report_checksum_failures_in_db(Oid dboid, int failurecount)
Definition: pgstat.c:1703
uint16 pd_checksum
Definition: bufpage.h:156
#define pgoff_t
Definition: win32_port.h:208
unsigned short uint16
Definition: c.h:440
#define ERROR
Definition: elog.h:46
int OpenTransientFile(const char *fileName, int fileFlags)
Definition: fd.c:2510
static bool noverify_checksums
Definition: basebackup.c:122
static char * buf
Definition: pg_test_fsync.c:68
int errcode_for_file_access(void)
Definition: elog.c:721
static int64 _tarWriteHeader(const char *filename, const char *linktarget, struct stat *statbuf, bool sizeonly)
Definition: basebackup.c:1852
__int64 st_size
Definition: win32_port.h:273
int CloseTransientFile(int fd)
Definition: fd.c:2687
#define WARNING
Definition: elog.h:40
pg_checksum_type checksum_type
static size_t tarPaddingBytesRequired(size_t len)
Definition: pgtar.h:40
int pg_checksum_init(pg_checksum_context *context, pg_checksum_type type)
char * last_dir_separator(const char *filename)
Definition: path.c:138
#define ereport(elevel,...)
Definition: elog.h:157
static bool is_checksummed_file(const char *fullpath, const char *filename)
Definition: basebackup.c:1550
PageHeaderData * PageHeader
Definition: bufpage.h:166
static void update_basebackup_progress(int64 delta)
Definition: basebackup.c:1986
#define Assert(condition)
Definition: c.h:804
int pg_checksum_update(pg_checksum_context *context, const uint8 *input, size_t len)
#define PageGetLSN(page)
Definition: bufpage.h:366
static char * filename
Definition: pg_dumpall.c:92
#define PageIsNew(page)
Definition: bufpage.h:229
int errmsg(const char *fmt,...)
Definition: elog.c:909
#define TAR_SEND_SIZE
Definition: basebackup.c:96
#define elog(elevel,...)
Definition: elog.h:232
int i
__time64_t st_mtime
Definition: win32_port.h:275
void AddFileToBackupManifest(backup_manifest_info *manifest, const char *spcoid, const char *pathname, size_t size, pg_time_t mtime, pg_checksum_context *checksum_ctx)
#define pq_putmessage(msgtype, s, len)
Definition: libpq.h:49
uint16 pg_checksum_page(char *page, BlockNumber blkno)
static XLogRecPtr startptr
Definition: basebackup.c:116
static long long int total_checksum_failures
Definition: basebackup.c:119

◆ sendFileWithContent()

static void sendFileWithContent ( const char *  filename,
const char *  content,
backup_manifest_info manifest 
)
static

Definition at line 1108 of file basebackup.c.

References _tarWriteHeader(), AddFileToBackupManifest(), buf, backup_manifest_info::checksum_type, elog, ERROR, MemSet, pg_checksum_init(), pg_checksum_update(), pg_file_create_mode, pq_putmessage, stat::st_gid, stat::st_mode, stat::st_mtime, stat::st_size, stat::st_uid, TAR_BLOCK_SIZE, tarPaddingBytesRequired(), and update_basebackup_progress().

Referenced by perform_base_backup().

1110 {
1111  struct stat statbuf;
1112  int pad,
1113  len;
1114  pg_checksum_context checksum_ctx;
1115 
1116  if (pg_checksum_init(&checksum_ctx, manifest->checksum_type) < 0)
1117  elog(ERROR, "could not initialize checksum of file \"%s\"",
1118  filename);
1119 
1120  len = strlen(content);
1121 
1122  /*
1123  * Construct a stat struct for the backup_label file we're injecting in
1124  * the tar.
1125  */
1126  /* Windows doesn't have the concept of uid and gid */
1127 #ifdef WIN32
1128  statbuf.st_uid = 0;
1129  statbuf.st_gid = 0;
1130 #else
1131  statbuf.st_uid = geteuid();
1132  statbuf.st_gid = getegid();
1133 #endif
1134  statbuf.st_mtime = time(NULL);
1135  statbuf.st_mode = pg_file_create_mode;
1136  statbuf.st_size = len;
1137 
1138  _tarWriteHeader(filename, NULL, &statbuf, false);
1139  /* Send the contents as a CopyData message */
1140  pq_putmessage('d', content, len);
1142 
1143  /* Pad to a multiple of the tar block size. */
1144  pad = tarPaddingBytesRequired(len);
1145  if (pad > 0)
1146  {
1147  char buf[TAR_BLOCK_SIZE];
1148 
1149  MemSet(buf, 0, pad);
1150  pq_putmessage('d', buf, pad);
1152  }
1153 
1154  if (pg_checksum_update(&checksum_ctx, (uint8 *) content, len) < 0)
1155  elog(ERROR, "could not update checksum of file \"%s\"",
1156  filename);
1157 
1158  AddFileToBackupManifest(manifest, NULL, filename, len,
1159  (pg_time_t) statbuf.st_mtime, &checksum_ctx);
1160 }
int pg_file_create_mode
Definition: file_perm.c:19
int64 pg_time_t
Definition: pgtime.h:23
unsigned char uint8
Definition: c.h:439
#define MemSet(start, val, len)
Definition: c.h:1008
#define ERROR
Definition: elog.h:46
#define TAR_BLOCK_SIZE
Definition: pgtar.h:17
static char * buf
Definition: pg_test_fsync.c:68
static int64 _tarWriteHeader(const char *filename, const char *linktarget, struct stat *statbuf, bool sizeonly)
Definition: basebackup.c:1852
pg_checksum_type checksum_type
static size_t tarPaddingBytesRequired(size_t len)
Definition: pgtar.h:40
int pg_checksum_init(pg_checksum_context *context, pg_checksum_type type)
static void update_basebackup_progress(int64 delta)
Definition: basebackup.c:1986
int pg_checksum_update(pg_checksum_context *context, const uint8 *input, size_t len)
static char * filename
Definition: pg_dumpall.c:92
#define elog(elevel,...)
Definition: elog.h:232
void AddFileToBackupManifest(backup_manifest_info *manifest, const char *spcoid, const char *pathname, size_t size, pg_time_t mtime, pg_checksum_context *checksum_ctx)
#define pq_putmessage(msgtype, s, len)
Definition: libpq.h:49

◆ sendTablespace()

static int64 sendTablespace ( char *  path,
char *  oid,
bool  sizeonly,
struct backup_manifest_info manifest 
)
static

Definition at line 1170 of file basebackup.c.

References _tarWriteHeader(), ereport, errcode_for_file_access(), errmsg(), ERROR, lstat, MAXPGPATH, NIL, sendDir(), snprintf, and TABLESPACE_VERSION_DIRECTORY.

Referenced by perform_base_backup().

1172 {
1173  int64 size;
1174  char pathbuf[MAXPGPATH];
1175  struct stat statbuf;
1176 
1177  /*
1178  * 'path' points to the tablespace location, but we only want to include
1179  * the version directory in it that belongs to us.
1180  */
1181  snprintf(pathbuf, sizeof(pathbuf), "%s/%s", path,
1183 
1184  /*
1185  * Store a directory entry in the tar file so we get the permissions
1186  * right.
1187  */
1188  if (lstat(pathbuf, &statbuf) != 0)
1189  {
1190  if (errno != ENOENT)
1191  ereport(ERROR,
1193  errmsg("could not stat file or directory \"%s\": %m",
1194  pathbuf)));
1195 
1196  /* If the tablespace went away while scanning, it's no error. */
1197  return 0;
1198  }
1199 
1200  size = _tarWriteHeader(TABLESPACE_VERSION_DIRECTORY, NULL, &statbuf,
1201  sizeonly);
1202 
1203  /* Send all the files in the tablespace version directory */
1204  size += sendDir(pathbuf, strlen(path), sizeonly, NIL, true, manifest,
1205  spcoid);
1206 
1207  return size;
1208 }
#define NIL
Definition: pg_list.h:65
#define ERROR
Definition: elog.h:46
#define MAXPGPATH
#define TABLESPACE_VERSION_DIRECTORY
Definition: relpath.h:26
int errcode_for_file_access(void)
Definition: elog.c:721
static int64 _tarWriteHeader(const char *filename, const char *linktarget, struct stat *statbuf, bool sizeonly)
Definition: basebackup.c:1852
#define ereport(elevel,...)
Definition: elog.h:157
#define lstat(path, sb)
Definition: win32_port.h:284
static int64 sendDir(const char *path, int basepathlen, bool sizeonly, List *tablespaces, bool sendtblspclinks, backup_manifest_info *manifest, const char *spcoid)
Definition: basebackup.c:1223
int errmsg(const char *fmt,...)
Definition: elog.c:909
#define snprintf
Definition: port.h:217

◆ SendXlogRecPtrResult()

static void SendXlogRecPtrResult ( XLogRecPtr  ptr,
TimeLineID  tli 
)
static

Definition at line 1053 of file basebackup.c.

References buf, LSN_FORMAT_ARGS, MAXFNAMELEN, pq_beginmessage(), pq_endmessage(), pq_puttextmessage(), pq_sendbytes(), pq_sendint16(), pq_sendint32(), pq_sendstring(), snprintf, and generate_unaccent_rules::str.

Referenced by perform_base_backup().

1054 {
1056  char str[MAXFNAMELEN];
1057  Size len;
1058 
1059  pq_beginmessage(&buf, 'T'); /* RowDescription */
1060  pq_sendint16(&buf, 2); /* 2 fields */
1061 
1062  /* Field headers */
1063  pq_sendstring(&buf, "recptr");
1064  pq_sendint32(&buf, 0); /* table oid */
1065  pq_sendint16(&buf, 0); /* attnum */
1066  pq_sendint32(&buf, TEXTOID); /* type oid */
1067  pq_sendint16(&buf, -1);
1068  pq_sendint32(&buf, 0);
1069  pq_sendint16(&buf, 0);
1070 
1071  pq_sendstring(&buf, "tli");
1072  pq_sendint32(&buf, 0); /* table oid */
1073  pq_sendint16(&buf, 0); /* attnum */
1074 
1075  /*
1076  * int8 may seem like a surprising data type for this, but in theory int4
1077  * would not be wide enough for this, as TimeLineID is unsigned.
1078  */
1079  pq_sendint32(&buf, INT8OID); /* type oid */
1080  pq_sendint16(&buf, -1);
1081  pq_sendint32(&buf, 0);
1082  pq_sendint16(&buf, 0);
1083  pq_endmessage(&buf);
1084 
1085  /* Data row */
1086  pq_beginmessage(&buf, 'D');
1087  pq_sendint16(&buf, 2); /* number of columns */
1088 
1089  len = snprintf(str, sizeof(str),
1090  "%X/%X", LSN_FORMAT_ARGS(ptr));
1091  pq_sendint32(&buf, len);
1092  pq_sendbytes(&buf, str, len);
1093 
1094  len = snprintf(str, sizeof(str), "%u", tli);
1095  pq_sendint32(&buf, len);
1096  pq_sendbytes(&buf, str, len);
1097 
1098  pq_endmessage(&buf);
1099 
1100  /* Send a CommandComplete message */
1101  pq_puttextmessage('C', "SELECT");
1102 }
static void pq_sendint16(StringInfo buf, uint16 i)
Definition: pqformat.h:137
void pq_sendstring(StringInfo buf, const char *str)
Definition: pqformat.c:197
void pq_beginmessage(StringInfo buf, char msgtype)
Definition: pqformat.c:87
static void pq_sendint32(StringInfo buf, uint32 i)
Definition: pqformat.h:145
#define LSN_FORMAT_ARGS(lsn)
Definition: xlogdefs.h:43
static char * buf
Definition: pg_test_fsync.c:68
#define MAXFNAMELEN
size_t Size
Definition: c.h:540
void pq_sendbytes(StringInfo buf, const char *data, int datalen)
Definition: pqformat.c:125
void pq_endmessage(StringInfo buf)
Definition: pqformat.c:298
void pq_puttextmessage(char msgtype, const char *str)
Definition: pqformat.c:369
#define snprintf
Definition: port.h:217

◆ throttle()

static void throttle ( size_t  increment)
static

Definition at line 1912 of file basebackup.c.

References CHECK_FOR_INTERRUPTS, elapsed_min_unit, GetCurrentTimestamp(), MyLatch, ResetLatch(), throttled_last, throttling_counter, throttling_sample, WAIT_EVENT_BASE_BACKUP_THROTTLE, WaitLatch(), WL_EXIT_ON_PM_DEATH, WL_LATCH_SET, and WL_TIMEOUT.

Referenced by perform_base_backup(), and sendFile().

1913 {
1914  TimeOffset elapsed_min;
1915 
1916  if (throttling_counter < 0)
1917  return;
1918 
1919  throttling_counter += increment;
1921  return;
1922 
1923  /* How much time should have elapsed at minimum? */
1924  elapsed_min = elapsed_min_unit *
1926 
1927  /*
1928  * Since the latch could be set repeatedly because of concurrently WAL
1929  * activity, sleep in a loop to ensure enough time has passed.
1930  */
1931  for (;;)
1932  {
1933  TimeOffset elapsed,
1934  sleep;
1935  int wait_result;
1936 
1937  /* Time elapsed since the last measurement (and possible wake up). */
1938  elapsed = GetCurrentTimestamp() - throttled_last;
1939 
1940  /* sleep if the transfer is faster than it should be */
1941  sleep = elapsed_min - elapsed;
1942  if (sleep <= 0)
1943  break;
1944 
1946 
1947  /* We're eating a potentially set latch, so check for interrupts */
1949 
1950  /*
1951  * (TAR_SEND_SIZE / throttling_sample * elapsed_min_unit) should be
1952  * the maximum time to sleep. Thus the cast to long is safe.
1953  */
1954  wait_result = WaitLatch(MyLatch,
1956  (long) (sleep / 1000),
1958 
1959  if (wait_result & WL_LATCH_SET)
1961 
1962  /* Done waiting? */
1963  if (wait_result & WL_TIMEOUT)
1964  break;
1965  }
1966 
1967  /*
1968  * As we work with integers, only whole multiple of throttling_sample was
1969  * processed. The rest will be done during the next call of this function.
1970  */
1972 
1973  /*
1974  * Time interval for the remaining amount and possible next increments
1975  * starts now.
1976  */
1978 }
#define WL_TIMEOUT
Definition: latch.h:128
TimestampTz GetCurrentTimestamp(void)
Definition: timestamp.c:1580
void ResetLatch(Latch *latch)
Definition: latch.c:660
int WaitLatch(Latch *latch, int wakeEvents, long timeout, uint32 wait_event_info)
Definition: latch.c:452
int64 TimeOffset
Definition: timestamp.h:40
static TimestampTz throttled_last
Definition: basebackup.c:113
struct Latch * MyLatch
Definition: globals.c:57
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:120
static int64 throttling_counter
Definition: basebackup.c:107
#define WL_LATCH_SET
Definition: latch.h:125
static uint64 throttling_sample
Definition: basebackup.c:104
static TimeOffset elapsed_min_unit
Definition: basebackup.c:110
#define WL_EXIT_ON_PM_DEATH
Definition: latch.h:130

◆ update_basebackup_progress()

static void update_basebackup_progress ( int64  delta)
static

Definition at line 1986 of file basebackup.c.

References backup_streamed, backup_total, pgstat_progress_update_multi_param(), PROGRESS_BASEBACKUP_BACKUP_STREAMED, PROGRESS_BASEBACKUP_BACKUP_TOTAL, and val.

Referenced by _tarWriteHeader(), perform_base_backup(), sendFile(), and sendFileWithContent().

1987 {
1988  const int index[] = {
1991  };
1992  int64 val[2];
1993  int nparam = 0;
1994 
1995  backup_streamed += delta;
1996  val[nparam++] = backup_streamed;
1997 
1998  /*
1999  * Avoid overflowing past 100% or the full size. This may make the total
2000  * size number change as we approach the end of the backup (the estimate
2001  * will always be wrong if WAL is included), but that's better than having
2002  * the done column be bigger than the total.
2003  */
2005  {
2007  val[nparam++] = backup_total;
2008  }
2009 
2010  pgstat_progress_update_multi_param(nparam, index, val);
2011 }
static int64 backup_total
Definition: basebackup.c:128
void pgstat_progress_update_multi_param(int nparam, const int *index, const int64 *val)
Definition: type.h:89
#define PROGRESS_BASEBACKUP_BACKUP_STREAMED
Definition: progress.h:125
static int64 backup_streamed
Definition: basebackup.c:131
#define PROGRESS_BASEBACKUP_BACKUP_TOTAL
Definition: progress.h:124
long val
Definition: informix.c:664

Variable Documentation

◆ backup_started_in_recovery

bool backup_started_in_recovery = false
static

Definition at line 88 of file basebackup.c.

Referenced by do_pg_start_backup(), do_pg_stop_backup(), perform_base_backup(), and sendDir().

◆ backup_streamed

int64 backup_streamed = 0
static

Definition at line 131 of file basebackup.c.

Referenced by perform_base_backup(), and update_basebackup_progress().

◆ backup_total

int64 backup_total = 0
static

Definition at line 128 of file basebackup.c.

Referenced by perform_base_backup(), and update_basebackup_progress().

◆ elapsed_min_unit

TimeOffset elapsed_min_unit
static

Definition at line 110 of file basebackup.c.

Referenced by perform_base_backup(), and throttle().

◆ excludeDirContents

const char* const excludeDirContents[]
static
Initial value:
=
{
"pg_replslot",
"pg_notify",
"pg_serial",
"pg_snapshots",
"pg_subtrans",
NULL
}
#define PG_DYNSHMEM_DIR
Definition: dsm_impl.h:51
#define PG_STAT_TMP_DIR
Definition: pgstat.h:33

Definition at line 153 of file basebackup.c.

Referenced by sendDir().

◆ excludeFiles

const struct exclude_list_item excludeFiles[]
static
Initial value:
=
{
{PG_AUTOCONF_FILENAME ".tmp", false},
{TABLESPACE_MAP, false},
{"backup_manifest", false},
{"postmaster.pid", false},
{"postmaster.opts", false},
{NULL, false}
}
#define TABLESPACE_MAP
Definition: xlog.h:366
#define RELCACHE_INIT_FILENAME
Definition: relcache.h:24
#define PG_AUTOCONF_FILENAME
Definition: guc.h:34
#define LOG_METAINFO_DATAFILE_TMP
Definition: syslogger.h:100
#define BACKUP_LABEL_FILE
Definition: xlog.h:363

Definition at line 194 of file basebackup.c.

◆ noChecksumFiles

const struct exclude_list_item noChecksumFiles[]
static
Initial value:
= {
{"pg_control", false},
{"pg_filenode.map", false},
{"pg_internal.init", true},
{"PG_VERSION", false},
{NULL, false}
}

Definition at line 238 of file basebackup.c.

◆ noverify_checksums

bool noverify_checksums = false
static

Definition at line 122 of file basebackup.c.

Referenced by parse_basebackup_options(), and sendFile().

◆ startptr

◆ statrelpath

char* statrelpath = NULL
static

Definition at line 91 of file basebackup.c.

Referenced by perform_base_backup(), and sendDir().

◆ throttled_last

TimestampTz throttled_last
static

Definition at line 113 of file basebackup.c.

Referenced by perform_base_backup(), and throttle().

◆ throttling_counter

int64 throttling_counter
static

Definition at line 107 of file basebackup.c.

Referenced by perform_base_backup(), and throttle().

◆ throttling_sample

uint64 throttling_sample
static

Definition at line 104 of file basebackup.c.

Referenced by perform_base_backup(), and throttle().

◆ total_checksum_failures

long long int total_checksum_failures
static

Definition at line 119 of file basebackup.c.

Referenced by perform_base_backup(), and sendFile().