PostgreSQL Source Code  git master
pg_basebackup.c File Reference
#include "postgres_fe.h"
#include <unistd.h>
#include <dirent.h>
#include <limits.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <signal.h>
#include <time.h>
#include "access/xlog_internal.h"
#include "common/file_perm.h"
#include "common/file_utils.h"
#include "common/logging.h"
#include "common/string.h"
#include "fe_utils/option_utils.h"
#include "fe_utils/recovery_gen.h"
#include "fe_utils/string_utils.h"
#include "getopt_long.h"
#include "libpq-fe.h"
#include "pgtar.h"
#include "pgtime.h"
#include "pqexpbuffer.h"
#include "receivelog.h"
#include "replication/basebackup.h"
#include "streamutil.h"
Include dependency graph for pg_basebackup.c:

Go to the source code of this file.

Data Structures

struct  TablespaceListCell
 
struct  TablespaceList
 
struct  WriteTarState
 
struct  UnpackTarState
 
struct  WriteManifestState
 
struct  logstreamer_param
 

Macros

#define ERRCODE_DATA_CORRUPTED   "XX001"
 
#define MINIMUM_VERSION_FOR_PG_WAL   100000
 
#define MINIMUM_VERSION_FOR_TEMP_SLOTS   100000
 
#define MINIMUM_VERSION_FOR_MANIFESTS   130000
 
#define VERBOSE_FILENAME_LENGTH   35
 

Typedefs

typedef struct TablespaceListCell TablespaceListCell
 
typedef struct TablespaceList TablespaceList
 
typedef struct WriteTarState WriteTarState
 
typedef struct UnpackTarState UnpackTarState
 
typedef struct WriteManifestState WriteManifestState
 
typedef void(* WriteDataCallback) (size_t nbytes, char *buf, void *callback_data)
 

Enumerations

enum  IncludeWal { NO_WAL, FETCH_WAL, STREAM_WAL }
 

Functions

static void usage (void)
 
static void verify_dir_is_empty_or_create (char *dirname, bool *created, bool *found)
 
static void progress_report (int tablespacenum, const char *filename, bool force, bool finished)
 
static void ReceiveTarFile (PGconn *conn, PGresult *res, int rownum)
 
static void ReceiveTarCopyChunk (size_t r, char *copybuf, void *callback_data)
 
static void ReceiveAndUnpackTarFile (PGconn *conn, PGresult *res, int rownum)
 
static void ReceiveTarAndUnpackCopyChunk (size_t r, char *copybuf, void *callback_data)
 
static void ReceiveBackupManifest (PGconn *conn)
 
static void ReceiveBackupManifestChunk (size_t r, char *copybuf, void *callback_data)
 
static void ReceiveBackupManifestInMemory (PGconn *conn, PQExpBuffer buf)
 
static void ReceiveBackupManifestInMemoryChunk (size_t r, char *copybuf, void *callback_data)
 
static void BaseBackup (void)
 
static bool reached_end_position (XLogRecPtr segendpos, uint32 timeline, bool segment_finished)
 
static const char * get_tablespace_mapping (const char *dir)
 
static void tablespace_list_append (const char *arg)
 
static void cleanup_directories_atexit (void)
 
static void disconnect_atexit (void)
 
static void kill_bgchild_atexit (void)
 
static int LogStreamerMain (logstreamer_param *param)
 
static void StartLogStreamer (char *startpos, uint32 timeline, char *sysidentifier)
 
static int32 parse_max_rate (char *src)
 
static void ReceiveCopyData (PGconn *conn, WriteDataCallback callback, void *callback_data)
 
static void writeTarData (WriteTarState *state, char *buf, int r)
 
int main (int argc, char **argv)
 

Variables

static char * basedir = NULL
 
static TablespaceList tablespace_dirs = {NULL, NULL}
 
static char * xlog_dir = NULL
 
static char format = 'p'
 
static char * label = "pg_basebackup base backup"
 
static bool noclean = false
 
static bool checksum_failure = false
 
static bool showprogress = false
 
static bool estimatesize = true
 
static int verbose = 0
 
static int compresslevel = 0
 
static IncludeWal includewal = STREAM_WAL
 
static bool fastcheckpoint = false
 
static bool writerecoveryconf = false
 
static bool do_sync = true
 
static int standby_message_timeout = 10 * 1000
 
static pg_time_t last_progress_report = 0
 
static int32 maxrate = 0
 
static char * replication_slot = NULL
 
static bool temp_replication_slot = true
 
static bool create_slot = false
 
static bool no_slot = false
 
static bool verify_checksums = true
 
static bool manifest = true
 
static bool manifest_force_encode = false
 
static char * manifest_checksums = NULL
 
static bool success = false
 
static bool made_new_pgdata = false
 
static bool found_existing_pgdata = false
 
static bool made_new_xlogdir = false
 
static bool found_existing_xlogdir = false
 
static bool made_tablespace_dirs = false
 
static bool found_tablespace_dirs = false
 
static uint64 totalsize_kb
 
static uint64 totaldone
 
static int tablespacecount
 
static int bgpipe [2] = {-1, -1}
 
static pid_t bgchild = -1
 
static bool in_log_streamer = false
 
static XLogRecPtr xlogendptr
 
static int has_xlogendptr = 0
 
static PQExpBuffer recoveryconfcontents = NULL
 

Macro Definition Documentation

◆ ERRCODE_DATA_CORRUPTED

◆ MINIMUM_VERSION_FOR_MANIFESTS

#define MINIMUM_VERSION_FOR_MANIFESTS   130000

Definition at line 116 of file pg_basebackup.c.

Referenced by main().

◆ MINIMUM_VERSION_FOR_PG_WAL

#define MINIMUM_VERSION_FOR_PG_WAL   100000

Definition at line 106 of file pg_basebackup.c.

Referenced by main(), and StartLogStreamer().

◆ MINIMUM_VERSION_FOR_TEMP_SLOTS

#define MINIMUM_VERSION_FOR_TEMP_SLOTS   100000

Definition at line 111 of file pg_basebackup.c.

Referenced by StartLogStreamer().

◆ VERBOSE_FILENAME_LENGTH

#define VERBOSE_FILENAME_LENGTH   35

Referenced by progress_report().

Typedef Documentation

◆ TablespaceList

◆ TablespaceListCell

◆ UnpackTarState

◆ WriteDataCallback

typedef void(* WriteDataCallback) (size_t nbytes, char *buf, void *callback_data)

Definition at line 99 of file pg_basebackup.c.

◆ WriteManifestState

◆ WriteTarState

typedef struct WriteTarState WriteTarState

Enumeration Type Documentation

◆ IncludeWal

enum IncludeWal
Enumerator
NO_WAL 
FETCH_WAL 
STREAM_WAL 

Definition at line 121 of file pg_basebackup.c.

122 {
123  NO_WAL,
124  FETCH_WAL,
125  STREAM_WAL
126 } IncludeWal;
IncludeWal

Function Documentation

◆ BaseBackup()

static void BaseBackup ( void  )
static

Definition at line 1805 of file pg_basebackup.c.

References _dosmaperr(), Assert, basedir, bgchild, bgpipe, CheckServerVersionForStreaming(), checksum_failure, conn, destroyPQExpBuffer(), do_sync, durable_rename(), ERRCODE_DATA_CORRUPTED, estimatesize, fastcheckpoint, FETCH_WAL, filename, format, found_tablespace_dirs, fprintf, GenerateRecoveryConfig(), get_tablespace_mapping(), has_xlogendptr, i, includewal, label, made_tablespace_dirs, manifest, manifest_checksums, manifest_force_encode, MAXPGPATH, maxrate, MemSet, NO_WAL, PG_DIAG_SQLSTATE, pg_log_error, pg_log_info, PGRES_COMMAND_OK, PGRES_TUPLES_OK, PQclear(), PQerrorMessage(), PQescapeStringConn(), PQfinish(), PQgetisnull(), PQgetResult(), PQgetvalue(), PQnfields(), PQntuples(), PQparameterStatus(), PQresultErrorField(), PQresultStatus(), PQsendQuery(), PQserverVersion(), progress_report(), psprintf(), ReceiveAndUnpackTarFile(), ReceiveBackupManifest(), ReceiveTarFile(), replication_slot, RunIdentifySystem(), showprogress, snprintf, StartLogStreamer(), status(), STREAM_WAL, strlcpy(), tablespacecount, totaldone, totalsize_kb, unconstify, verbose, verify_checksums, verify_dir_is_empty_or_create(), wait_result_to_str(), write, writerecoveryconf, and xlogendptr.

Referenced by main().

1806 {
1807  PGresult *res;
1808  char *sysidentifier;
1809  TimeLineID latesttli;
1810  TimeLineID starttli;
1811  char *basebkp;
1812  char escaped_label[MAXPGPATH];
1813  char *maxrate_clause = NULL;
1814  char *manifest_clause = NULL;
1815  char *manifest_checksums_clause = "";
1816  int i;
1817  char xlogstart[64];
1818  char xlogend[64];
1819  int minServerMajor,
1820  maxServerMajor;
1821  int serverVersion,
1822  serverMajor;
1823  int writing_to_stdout;
1824 
1825  Assert(conn != NULL);
1826 
1827  /*
1828  * Check server version. BASE_BACKUP command was introduced in 9.1, so we
1829  * can't work with servers older than 9.1.
1830  */
1831  minServerMajor = 901;
1832  maxServerMajor = PG_VERSION_NUM / 100;
1833  serverVersion = PQserverVersion(conn);
1834  serverMajor = serverVersion / 100;
1835  if (serverMajor < minServerMajor || serverMajor > maxServerMajor)
1836  {
1837  const char *serverver = PQparameterStatus(conn, "server_version");
1838 
1839  pg_log_error("incompatible server version %s",
1840  serverver ? serverver : "'unknown'");
1841  exit(1);
1842  }
1843 
1844  /*
1845  * If WAL streaming was requested, also check that the server is new
1846  * enough for that.
1847  */
1849  {
1850  /*
1851  * Error message already written in CheckServerVersionForStreaming(),
1852  * but add a hint about using -X none.
1853  */
1854  pg_log_info("HINT: use -X none or -X fetch to disable log streaming");
1855  exit(1);
1856  }
1857 
1858  /*
1859  * Build contents of configuration file if requested
1860  */
1861  if (writerecoveryconf)
1863 
1864  /*
1865  * Run IDENTIFY_SYSTEM so we can get the timeline
1866  */
1867  if (!RunIdentifySystem(conn, &sysidentifier, &latesttli, NULL, NULL))
1868  exit(1);
1869 
1870  /*
1871  * Start the actual backup
1872  */
1873  PQescapeStringConn(conn, escaped_label, label, sizeof(escaped_label), &i);
1874 
1875  if (maxrate > 0)
1876  maxrate_clause = psprintf("MAX_RATE %u", maxrate);
1877 
1878  if (manifest)
1879  {
1881  manifest_clause = "MANIFEST 'force-encode'";
1882  else
1883  manifest_clause = "MANIFEST 'yes'";
1884  if (manifest_checksums != NULL)
1885  manifest_checksums_clause = psprintf("MANIFEST_CHECKSUMS '%s'",
1887  }
1888 
1889  if (verbose)
1890  pg_log_info("initiating base backup, waiting for checkpoint to complete");
1891 
1892  if (showprogress && !verbose)
1893  {
1894  fprintf(stderr, "waiting for checkpoint");
1895  if (isatty(fileno(stderr)))
1896  fprintf(stderr, "\r");
1897  else
1898  fprintf(stderr, "\n");
1899  }
1900 
1901  basebkp =
1902  psprintf("BASE_BACKUP LABEL '%s' %s %s %s %s %s %s %s %s %s",
1903  escaped_label,
1904  estimatesize ? "PROGRESS" : "",
1905  includewal == FETCH_WAL ? "WAL" : "",
1906  fastcheckpoint ? "FAST" : "",
1907  includewal == NO_WAL ? "" : "NOWAIT",
1908  maxrate_clause ? maxrate_clause : "",
1909  format == 't' ? "TABLESPACE_MAP" : "",
1910  verify_checksums ? "" : "NOVERIFY_CHECKSUMS",
1911  manifest_clause ? manifest_clause : "",
1912  manifest_checksums_clause);
1913 
1914  if (PQsendQuery(conn, basebkp) == 0)
1915  {
1916  pg_log_error("could not send replication command \"%s\": %s",
1917  "BASE_BACKUP", PQerrorMessage(conn));
1918  exit(1);
1919  }
1920 
1921  /*
1922  * Get the starting WAL location
1923  */
1924  res = PQgetResult(conn);
1925  if (PQresultStatus(res) != PGRES_TUPLES_OK)
1926  {
1927  pg_log_error("could not initiate base backup: %s",
1928  PQerrorMessage(conn));
1929  exit(1);
1930  }
1931  if (PQntuples(res) != 1)
1932  {
1933  pg_log_error("server returned unexpected response to BASE_BACKUP command; got %d rows and %d fields, expected %d rows and %d fields",
1934  PQntuples(res), PQnfields(res), 1, 2);
1935  exit(1);
1936  }
1937 
1938  strlcpy(xlogstart, PQgetvalue(res, 0, 0), sizeof(xlogstart));
1939 
1940  if (verbose)
1941  pg_log_info("checkpoint completed");
1942 
1943  /*
1944  * 9.3 and later sends the TLI of the starting point. With older servers,
1945  * assume it's the same as the latest timeline reported by
1946  * IDENTIFY_SYSTEM.
1947  */
1948  if (PQnfields(res) >= 2)
1949  starttli = atoi(PQgetvalue(res, 0, 1));
1950  else
1951  starttli = latesttli;
1952  PQclear(res);
1953  MemSet(xlogend, 0, sizeof(xlogend));
1954 
1955  if (verbose && includewal != NO_WAL)
1956  pg_log_info("write-ahead log start point: %s on timeline %u",
1957  xlogstart, starttli);
1958 
1959  /*
1960  * Get the header
1961  */
1962  res = PQgetResult(conn);
1963  if (PQresultStatus(res) != PGRES_TUPLES_OK)
1964  {
1965  pg_log_error("could not get backup header: %s",
1966  PQerrorMessage(conn));
1967  exit(1);
1968  }
1969  if (PQntuples(res) < 1)
1970  {
1971  pg_log_error("no data returned from server");
1972  exit(1);
1973  }
1974 
1975  /*
1976  * Sum up the total size, for progress reporting
1977  */
1978  totalsize_kb = totaldone = 0;
1979  tablespacecount = PQntuples(res);
1980  for (i = 0; i < PQntuples(res); i++)
1981  {
1982  totalsize_kb += atol(PQgetvalue(res, i, 2));
1983 
1984  /*
1985  * Verify tablespace directories are empty. Don't bother with the
1986  * first once since it can be relocated, and it will be checked before
1987  * we do anything anyway.
1988  */
1989  if (format == 'p' && !PQgetisnull(res, i, 1))
1990  {
1991  char *path = unconstify(char *, get_tablespace_mapping(PQgetvalue(res, i, 1)));
1992 
1994  }
1995  }
1996 
1997  /*
1998  * When writing to stdout, require a single tablespace
1999  */
2000  writing_to_stdout = format == 't' && strcmp(basedir, "-") == 0;
2001  if (writing_to_stdout && PQntuples(res) > 1)
2002  {
2003  pg_log_error("can only write single tablespace to stdout, database has %d",
2004  PQntuples(res));
2005  exit(1);
2006  }
2007 
2008  /*
2009  * If we're streaming WAL, start the streaming session before we start
2010  * receiving the actual data chunks.
2011  */
2012  if (includewal == STREAM_WAL)
2013  {
2014  if (verbose)
2015  pg_log_info("starting background WAL receiver");
2016  StartLogStreamer(xlogstart, starttli, sysidentifier);
2017  }
2018 
2019  /*
2020  * Start receiving chunks
2021  */
2022  for (i = 0; i < PQntuples(res); i++)
2023  {
2024  if (format == 't')
2025  ReceiveTarFile(conn, res, i);
2026  else
2027  ReceiveAndUnpackTarFile(conn, res, i);
2028  } /* Loop over all tablespaces */
2029 
2030  /*
2031  * Now receive backup manifest, if appropriate.
2032  *
2033  * If we're writing a tarfile to stdout, ReceiveTarFile will have already
2034  * processed the backup manifest and included it in the output tarfile.
2035  * Such a configuration doesn't allow for writing multiple files.
2036  *
2037  * If we're talking to an older server, it won't send a backup manifest,
2038  * so don't try to receive one.
2039  */
2040  if (!writing_to_stdout && manifest)
2042 
2043  if (showprogress)
2044  progress_report(PQntuples(res), NULL, true, true);
2045 
2046  PQclear(res);
2047 
2048  /*
2049  * Get the stop position
2050  */
2051  res = PQgetResult(conn);
2052  if (PQresultStatus(res) != PGRES_TUPLES_OK)
2053  {
2054  pg_log_error("could not get write-ahead log end position from server: %s",
2055  PQerrorMessage(conn));
2056  exit(1);
2057  }
2058  if (PQntuples(res) != 1)
2059  {
2060  pg_log_error("no write-ahead log end position returned from server");
2061  exit(1);
2062  }
2063  strlcpy(xlogend, PQgetvalue(res, 0, 0), sizeof(xlogend));
2064  if (verbose && includewal != NO_WAL)
2065  pg_log_info("write-ahead log end point: %s", xlogend);
2066  PQclear(res);
2067 
2068  res = PQgetResult(conn);
2069  if (PQresultStatus(res) != PGRES_COMMAND_OK)
2070  {
2071  const char *sqlstate = PQresultErrorField(res, PG_DIAG_SQLSTATE);
2072 
2073  if (sqlstate &&
2074  strcmp(sqlstate, ERRCODE_DATA_CORRUPTED) == 0)
2075  {
2076  pg_log_error("checksum error occurred");
2077  checksum_failure = true;
2078  }
2079  else
2080  {
2081  pg_log_error("final receive failed: %s",
2082  PQerrorMessage(conn));
2083  }
2084  exit(1);
2085  }
2086 
2087  if (bgchild > 0)
2088  {
2089 #ifndef WIN32
2090  int status;
2091  pid_t r;
2092 #else
2093  DWORD status;
2094 
2095  /*
2096  * get a pointer sized version of bgchild to avoid warnings about
2097  * casting to a different size on WIN64.
2098  */
2099  intptr_t bgchild_handle = bgchild;
2100  uint32 hi,
2101  lo;
2102 #endif
2103 
2104  if (verbose)
2105  pg_log_info("waiting for background process to finish streaming ...");
2106 
2107 #ifndef WIN32
2108  if (write(bgpipe[1], xlogend, strlen(xlogend)) != strlen(xlogend))
2109  {
2110  pg_log_info("could not send command to background pipe: %m");
2111  exit(1);
2112  }
2113 
2114  /* Just wait for the background process to exit */
2115  r = waitpid(bgchild, &status, 0);
2116  if (r == (pid_t) -1)
2117  {
2118  pg_log_error("could not wait for child process: %m");
2119  exit(1);
2120  }
2121  if (r != bgchild)
2122  {
2123  pg_log_error("child %d died, expected %d", (int) r, (int) bgchild);
2124  exit(1);
2125  }
2126  if (status != 0)
2127  {
2128  pg_log_error("%s", wait_result_to_str(status));
2129  exit(1);
2130  }
2131  /* Exited normally, we're happy! */
2132 #else /* WIN32 */
2133 
2134  /*
2135  * On Windows, since we are in the same process, we can just store the
2136  * value directly in the variable, and then set the flag that says
2137  * it's there.
2138  */
2139  if (sscanf(xlogend, "%X/%X", &hi, &lo) != 2)
2140  {
2141  pg_log_error("could not parse write-ahead log location \"%s\"",
2142  xlogend);
2143  exit(1);
2144  }
2145  xlogendptr = ((uint64) hi) << 32 | lo;
2146  InterlockedIncrement(&has_xlogendptr);
2147 
2148  /* First wait for the thread to exit */
2149  if (WaitForSingleObjectEx((HANDLE) bgchild_handle, INFINITE, FALSE) !=
2150  WAIT_OBJECT_0)
2151  {
2152  _dosmaperr(GetLastError());
2153  pg_log_error("could not wait for child thread: %m");
2154  exit(1);
2155  }
2156  if (GetExitCodeThread((HANDLE) bgchild_handle, &status) == 0)
2157  {
2158  _dosmaperr(GetLastError());
2159  pg_log_error("could not get child thread exit status: %m");
2160  exit(1);
2161  }
2162  if (status != 0)
2163  {
2164  pg_log_error("child thread exited with error %u",
2165  (unsigned int) status);
2166  exit(1);
2167  }
2168  /* Exited normally, we're happy */
2169 #endif
2170  }
2171 
2172  /* Free the configuration file contents */
2174 
2175  /*
2176  * End of copy data. Final result is already checked inside the loop.
2177  */
2178  PQclear(res);
2179  PQfinish(conn);
2180  conn = NULL;
2181 
2182  /*
2183  * Make data persistent on disk once backup is completed. For tar format
2184  * sync the parent directory and all its contents as each tar file was not
2185  * synced after being completed. In plain format, all the data of the
2186  * base directory is synced, taking into account all the tablespaces.
2187  * Errors are not considered fatal.
2188  */
2189  if (do_sync)
2190  {
2191  if (verbose)
2192  pg_log_info("syncing data to disk ...");
2193  if (format == 't')
2194  {
2195  if (strcmp(basedir, "-") != 0)
2196  (void) fsync_dir_recurse(basedir);
2197  }
2198  else
2199  {
2200  (void) fsync_pgdata(basedir, serverVersion);
2201  }
2202  }
2203 
2204  /*
2205  * After synchronizing data to disk, perform a durable rename of
2206  * backup_manifest.tmp to backup_manifest, if we wrote such a file. This
2207  * way, a failure or system crash before we reach this point will leave us
2208  * without a backup_manifest file, decreasing the chances that a directory
2209  * we leave behind will be mistaken for a valid backup.
2210  */
2211  if (!writing_to_stdout && manifest)
2212  {
2213  char tmp_filename[MAXPGPATH];
2214  char filename[MAXPGPATH];
2215 
2216  if (verbose)
2217  pg_log_info("renaming backup_manifest.tmp to backup_manifest");
2218 
2219  snprintf(tmp_filename, MAXPGPATH, "%s/backup_manifest.tmp", basedir);
2220  snprintf(filename, MAXPGPATH, "%s/backup_manifest", basedir);
2221 
2222  /* durable_rename emits its own log message in case of failure */
2223  if (durable_rename(tmp_filename, filename) != 0)
2224  exit(1);
2225  }
2226 
2227  if (verbose)
2228  pg_log_info("base backup completed");
2229 }
int PQnfields(const PGresult *res)
Definition: fe-exec.c:3256
static PQExpBuffer recoveryconfcontents
static IncludeWal includewal
char * PQerrorMessage(const PGconn *conn)
Definition: fe-connect.c:6737
static bool verify_checksums
static int bgpipe[2]
uint32 TimeLineID
Definition: xlogdefs.h:59
static bool found_tablespace_dirs
char * PQgetvalue(const PGresult *res, int tup_num, int field_num)
Definition: fe-exec.c:3642
const char * PQparameterStatus(const PGconn *conn, const char *paramName)
Definition: fe-connect.c:6702
#define write(a, b, c)
Definition: win32.h:14
#define pg_log_error(...)
Definition: logging.h:80
static bool manifest_force_encode
char * psprintf(const char *fmt,...)
Definition: psprintf.c:46
static int tablespacecount
void _dosmaperr(unsigned long)
Definition: win32error.c:171
bool RunIdentifySystem(PGconn *conn, char **sysid, TimeLineID *starttli, XLogRecPtr *startpos, char **db_name)
Definition: streamutil.c:409
static bool writerecoveryconf
void PQfinish(PGconn *conn)
Definition: fe-connect.c:4224
static bool checksum_failure
#define MemSet(start, val, len)
Definition: c.h:1008
static void ReceiveBackupManifest(PGconn *conn)
int PQserverVersion(const PGconn *conn)
Definition: fe-connect.c:6727
int PQntuples(const PGresult *res)
Definition: fe-exec.c:3248
#define PG_DIAG_SQLSTATE
Definition: postgres_ext.h:57
#define fprintf
Definition: port.h:220
char * wait_result_to_str(int exitstatus)
Definition: wait_error.c:32
static char * basedir
ExecStatusType PQresultStatus(const PGresult *res)
Definition: fe-exec.c:3178
int PQsendQuery(PGconn *conn, const char *query)
Definition: fe-exec.c:1326
void destroyPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:116
PGconn * conn
Definition: streamutil.c:54
#define MAXPGPATH
static uint64 totaldone
static bool estimatesize
static int32 maxrate
static int has_xlogendptr
size_t PQescapeStringConn(PGconn *conn, char *to, const char *from, size_t length, int *error)
Definition: fe-exec.c:3910
unsigned int uint32
Definition: c.h:441
static char * manifest_checksums
static const char * get_tablespace_mapping(const char *dir)
int durable_rename(const char *oldfile, const char *newfile, int elevel)
Definition: fd.c:692
PQExpBuffer GenerateRecoveryConfig(PGconn *pgconn, char *replication_slot)
Definition: recovery_gen.c:23
#define ERRCODE_DATA_CORRUPTED
Definition: pg_basebackup.c:47
static int verbose
#define unconstify(underlying_type, expr)
Definition: c.h:1243
static bool showprogress
static void ReceiveTarFile(PGconn *conn, PGresult *res, int rownum)
static char * label
static void StartLogStreamer(char *startpos, uint32 timeline, char *sysidentifier)
void PQclear(PGresult *res)
Definition: fe-exec.c:694
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition: strlcpy.c:45
char * PQresultErrorField(const PGresult *res, int fieldcode)
Definition: fe-exec.c:3233
#define Assert(condition)
Definition: c.h:804
static void ReceiveAndUnpackTarFile(PGconn *conn, PGresult *res, int rownum)
static bool manifest
static XLogRecPtr xlogendptr
static bool fastcheckpoint
static bool made_tablespace_dirs
static char * filename
Definition: pg_dumpall.c:92
static pid_t bgchild
static uint64 totalsize_kb
int i
static bool do_sync
static void verify_dir_is_empty_or_create(char *dirname, bool *created, bool *found)
static char format
static char * replication_slot
static void static void status(const char *fmt,...) pg_attribute_printf(1
Definition: pg_regress.c:227
int PQgetisnull(const PGresult *res, int tup_num, int field_num)
Definition: fe-exec.c:3667
#define snprintf
Definition: port.h:216
PGresult * PQgetResult(PGconn *conn)
Definition: fe-exec.c:1978
#define pg_log_info(...)
Definition: logging.h:88
bool CheckServerVersionForStreaming(PGconn *conn)
Definition: receivelog.c:366
static void progress_report(int tablespacenum, const char *filename, bool force, bool finished)

◆ cleanup_directories_atexit()

static void cleanup_directories_atexit ( void  )
static

Definition at line 217 of file pg_basebackup.c.

References basedir, checksum_failure, found_existing_pgdata, found_existing_xlogdir, found_tablespace_dirs, in_log_streamer, made_new_pgdata, made_new_xlogdir, made_tablespace_dirs, noclean, pg_log_error, pg_log_info, rmtree(), success, and xlog_dir.

Referenced by main().

218 {
219  if (success || in_log_streamer)
220  return;
221 
222  if (!noclean && !checksum_failure)
223  {
224  if (made_new_pgdata)
225  {
226  pg_log_info("removing data directory \"%s\"", basedir);
227  if (!rmtree(basedir, true))
228  pg_log_error("failed to remove data directory");
229  }
230  else if (found_existing_pgdata)
231  {
232  pg_log_info("removing contents of data directory \"%s\"", basedir);
233  if (!rmtree(basedir, false))
234  pg_log_error("failed to remove contents of data directory");
235  }
236 
237  if (made_new_xlogdir)
238  {
239  pg_log_info("removing WAL directory \"%s\"", xlog_dir);
240  if (!rmtree(xlog_dir, true))
241  pg_log_error("failed to remove WAL directory");
242  }
243  else if (found_existing_xlogdir)
244  {
245  pg_log_info("removing contents of WAL directory \"%s\"", xlog_dir);
246  if (!rmtree(xlog_dir, false))
247  pg_log_error("failed to remove contents of WAL directory");
248  }
249  }
250  else
251  {
253  pg_log_info("data directory \"%s\" not removed at user's request", basedir);
254 
256  pg_log_info("WAL directory \"%s\" not removed at user's request", xlog_dir);
257  }
258 
260  pg_log_info("changes to tablespace directories will not be undone");
261 }
static bool found_existing_pgdata
static bool found_tablespace_dirs
#define pg_log_error(...)
Definition: logging.h:80
static bool checksum_failure
static char * basedir
static bool found_existing_xlogdir
static bool success
static bool made_new_pgdata
bool rmtree(const char *path, bool rmtopdir)
Definition: rmtree.c:42
static bool in_log_streamer
static char * xlog_dir
static bool made_new_xlogdir
static bool made_tablespace_dirs
#define pg_log_info(...)
Definition: logging.h:88
static bool noclean

◆ disconnect_atexit()

static void disconnect_atexit ( void  )
static

Definition at line 264 of file pg_basebackup.c.

References conn, and PQfinish().

Referenced by main().

265 {
266  if (conn != NULL)
267  PQfinish(conn);
268 }
void PQfinish(PGconn *conn)
Definition: fe-connect.c:4224
PGconn * conn
Definition: streamutil.c:54

◆ get_tablespace_mapping()

static const char * get_tablespace_mapping ( const char *  dir)
static

Definition at line 1490 of file pg_basebackup.c.

References canonicalize_path(), TablespaceList::head, MAXPGPATH, TablespaceListCell::new_dir, TablespaceListCell::next, TablespaceListCell::old_dir, and strlcpy().

Referenced by BaseBackup(), ReceiveAndUnpackTarFile(), and ReceiveTarAndUnpackCopyChunk().

1491 {
1492  TablespaceListCell *cell;
1493  char canon_dir[MAXPGPATH];
1494 
1495  /* Canonicalize path for comparison consistency */
1496  strlcpy(canon_dir, dir, sizeof(canon_dir));
1497  canonicalize_path(canon_dir);
1498 
1499  for (cell = tablespace_dirs.head; cell; cell = cell->next)
1500  if (strcmp(canon_dir, cell->old_dir) == 0)
1501  return cell->new_dir;
1502 
1503  return dir;
1504 }
static TablespaceList tablespace_dirs
char old_dir[MAXPGPATH]
Definition: pg_basebackup.c:52
void canonicalize_path(char *path)
Definition: path.c:254
char new_dir[MAXPGPATH]
Definition: pg_basebackup.c:53
#define MAXPGPATH
struct TablespaceListCell * next
Definition: pg_basebackup.c:51
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition: strlcpy.c:45
TablespaceListCell * head
Definition: pg_basebackup.c:58

◆ kill_bgchild_atexit()

static void kill_bgchild_atexit ( void  )
static

Definition at line 277 of file pg_basebackup.c.

References bgchild, and kill.

Referenced by StartLogStreamer().

278 {
279  if (bgchild > 0)
280  kill(bgchild, SIGTERM);
281 }
#define kill(pid, sig)
Definition: win32_port.h:454
static pid_t bgchild

◆ LogStreamerMain()

static int LogStreamerMain ( logstreamer_param param)
static

Definition at line 533 of file pg_basebackup.c.

References logstreamer_param::bgconn, bgpipe, compresslevel, CreateWalDirectoryMethod(), CreateWalTarMethod(), StreamCtl::do_sync, WalWriteMethod::finish, format, FreeWalDirectoryMethod(), FreeWalTarMethod(), in_log_streamer, StreamCtl::mark_done, MemSet, StreamCtl::partial_suffix, pg_free(), pg_log_error, PGINVALID_SOCKET, PQfinish(), reached_end_position(), ReceiveXlogStream(), StreamCtl::replication_slot, replication_slot, StreamCtl::standby_message_timeout, standby_message_timeout, StreamCtl::startpos, logstreamer_param::startptr, StreamCtl::stop_socket, StreamCtl::stream_stop, StreamCtl::synchronous, StreamCtl::sysidentifier, logstreamer_param::sysidentifier, StreamCtl::timeline, logstreamer_param::timeline, StreamCtl::walmethod, and logstreamer_param::xlog.

Referenced by StartLogStreamer().

534 {
535  StreamCtl stream;
536 
537  in_log_streamer = true;
538 
539  MemSet(&stream, 0, sizeof(stream));
540  stream.startpos = param->startptr;
541  stream.timeline = param->timeline;
542  stream.sysidentifier = param->sysidentifier;
544 #ifndef WIN32
545  stream.stop_socket = bgpipe[0];
546 #else
547  stream.stop_socket = PGINVALID_SOCKET;
548 #endif
550  stream.synchronous = false;
551  /* fsync happens at the end of pg_basebackup for all data */
552  stream.do_sync = false;
553  stream.mark_done = true;
554  stream.partial_suffix = NULL;
556 
557  if (format == 'p')
558  stream.walmethod = CreateWalDirectoryMethod(param->xlog, 0,
559  stream.do_sync);
560  else
562  stream.do_sync);
563 
564  if (!ReceiveXlogStream(param->bgconn, &stream))
565 
566  /*
567  * Any errors will already have been reported in the function process,
568  * but we need to tell the parent that we didn't shutdown in a nice
569  * way.
570  */
571  return 1;
572 
573  if (!stream.walmethod->finish())
574  {
575  pg_log_error("could not finish writing WAL files: %m");
576  return 1;
577  }
578 
579  PQfinish(param->bgconn);
580 
581  if (format == 'p')
583  else
585  pg_free(stream.walmethod);
586 
587  return 0;
588 }
static int bgpipe[2]
bool do_sync
Definition: receivelog.h:38
#define pg_log_error(...)
Definition: logging.h:80
char * sysidentifier
Definition: receivelog.h:33
void PQfinish(PGconn *conn)
Definition: fe-connect.c:4224
static int compresslevel
#define MemSet(start, val, len)
Definition: c.h:1008
XLogRecPtr startpos
Definition: receivelog.h:31
char * partial_suffix
Definition: receivelog.h:47
static bool reached_end_position(XLogRecPtr segendpos, uint32 timeline, bool segment_finished)
TimeLineID timeline
Definition: receivelog.h:32
WalWriteMethod * CreateWalDirectoryMethod(const char *basedir, int compression, bool sync)
Definition: walmethods.c:376
char * replication_slot
Definition: receivelog.h:48
bool mark_done
Definition: receivelog.h:37
XLogRecPtr startptr
stream_stop_callback stream_stop
Definition: receivelog.h:41
WalWriteMethod * walmethod
Definition: receivelog.h:46
static int standby_message_timeout
void FreeWalTarMethod(void)
Definition: walmethods.c:1068
#define PGINVALID_SOCKET
Definition: port.h:33
static bool in_log_streamer
WalWriteMethod * CreateWalTarMethod(const char *tarbase, int compression, bool sync)
Definition: walmethods.c:1035
bool ReceiveXlogStream(PGconn *conn, StreamCtl *stream)
Definition: receivelog.c:444
bool synchronous
Definition: receivelog.h:36
void pg_free(void *ptr)
Definition: fe_memutils.c:105
bool(* finish)(void)
Definition: walmethods.h:84
pgsocket stop_socket
Definition: receivelog.h:43
int standby_message_timeout
Definition: receivelog.h:35
static char format
static char * replication_slot
void FreeWalDirectoryMethod(void)
Definition: walmethods.c:402
char xlog[MAXPGPATH]

◆ main()

int main ( int  argc,
char **  argv 
)

Definition at line 2233 of file pg_basebackup.c.

References _, BaseBackup(), basedir, canonicalize_path(), cleanup_directories_atexit(), compresslevel, conn, connection_string, create_slot, dbgetpassword, dbhost, dbport, dbuser, disconnect_atexit(), do_sync, estimatesize, fastcheckpoint, FETCH_WAL, format, found_existing_pgdata, found_existing_xlogdir, fprintf, free, get_progname(), GetConnection(), getopt_long(), includewal, is_absolute_path, label, made_new_pgdata, made_new_xlogdir, manifest, manifest_checksums, manifest_force_encode, maxrate, MINIMUM_VERSION_FOR_MANIFESTS, MINIMUM_VERSION_FOR_PG_WAL, no_argument, no_slot, NO_WAL, noclean, optarg, optind, option_parse_int(), parse_max_rate(), pg_log_error, pg_logging_init(), pg_mode_mask, pg_strcasecmp(), pg_strdup(), PG_TEXTDOMAIN, PQserverVersion(), progname, psprintf(), replication_slot, required_argument, RetrieveWalSegSize(), set_pglocale_pgservice(), showprogress, standby_message_timeout, STREAM_WAL, success, symlink, tablespace_list_append(), temp_replication_slot, usage(), verbose, verify_checksums, verify_dir_is_empty_or_create(), writerecoveryconf, xlog_dir, and Z_DEFAULT_COMPRESSION.

2234 {
2235  static struct option long_options[] = {
2236  {"help", no_argument, NULL, '?'},
2237  {"version", no_argument, NULL, 'V'},
2238  {"pgdata", required_argument, NULL, 'D'},
2239  {"format", required_argument, NULL, 'F'},
2240  {"checkpoint", required_argument, NULL, 'c'},
2241  {"create-slot", no_argument, NULL, 'C'},
2242  {"max-rate", required_argument, NULL, 'r'},
2243  {"write-recovery-conf", no_argument, NULL, 'R'},
2244  {"slot", required_argument, NULL, 'S'},
2245  {"tablespace-mapping", required_argument, NULL, 'T'},
2246  {"wal-method", required_argument, NULL, 'X'},
2247  {"gzip", no_argument, NULL, 'z'},
2248  {"compress", required_argument, NULL, 'Z'},
2249  {"label", required_argument, NULL, 'l'},
2250  {"no-clean", no_argument, NULL, 'n'},
2251  {"no-sync", no_argument, NULL, 'N'},
2252  {"dbname", required_argument, NULL, 'd'},
2253  {"host", required_argument, NULL, 'h'},
2254  {"port", required_argument, NULL, 'p'},
2255  {"username", required_argument, NULL, 'U'},
2256  {"no-password", no_argument, NULL, 'w'},
2257  {"password", no_argument, NULL, 'W'},
2258  {"status-interval", required_argument, NULL, 's'},
2259  {"verbose", no_argument, NULL, 'v'},
2260  {"progress", no_argument, NULL, 'P'},
2261  {"waldir", required_argument, NULL, 1},
2262  {"no-slot", no_argument, NULL, 2},
2263  {"no-verify-checksums", no_argument, NULL, 3},
2264  {"no-estimate-size", no_argument, NULL, 4},
2265  {"no-manifest", no_argument, NULL, 5},
2266  {"manifest-force-encode", no_argument, NULL, 6},
2267  {"manifest-checksums", required_argument, NULL, 7},
2268  {NULL, 0, NULL, 0}
2269  };
2270  int c;
2271 
2272  int option_index;
2273 
2274  pg_logging_init(argv[0]);
2275  progname = get_progname(argv[0]);
2276  set_pglocale_pgservice(argv[0], PG_TEXTDOMAIN("pg_basebackup"));
2277 
2278  if (argc > 1)
2279  {
2280  if (strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-?") == 0)
2281  {
2282  usage();
2283  exit(0);
2284  }
2285  else if (strcmp(argv[1], "-V") == 0
2286  || strcmp(argv[1], "--version") == 0)
2287  {
2288  puts("pg_basebackup (PostgreSQL) " PG_VERSION);
2289  exit(0);
2290  }
2291  }
2292 
2294 
2295  while ((c = getopt_long(argc, argv, "CD:F:r:RS:T:X:l:nNzZ:d:c:h:p:U:s:wWkvP",
2296  long_options, &option_index)) != -1)
2297  {
2298  switch (c)
2299  {
2300  case 'C':
2301  create_slot = true;
2302  break;
2303  case 'D':
2305  break;
2306  case 'F':
2307  if (strcmp(optarg, "p") == 0 || strcmp(optarg, "plain") == 0)
2308  format = 'p';
2309  else if (strcmp(optarg, "t") == 0 || strcmp(optarg, "tar") == 0)
2310  format = 't';
2311  else
2312  {
2313  pg_log_error("invalid output format \"%s\", must be \"plain\" or \"tar\"",
2314  optarg);
2315  exit(1);
2316  }
2317  break;
2318  case 'r':
2320  break;
2321  case 'R':
2322  writerecoveryconf = true;
2323  break;
2324  case 'S':
2325 
2326  /*
2327  * When specifying replication slot name, use a permanent
2328  * slot.
2329  */
2331  temp_replication_slot = false;
2332  break;
2333  case 2:
2334  no_slot = true;
2335  break;
2336  case 'T':
2338  break;
2339  case 'X':
2340  if (strcmp(optarg, "n") == 0 ||
2341  strcmp(optarg, "none") == 0)
2342  {
2343  includewal = NO_WAL;
2344  }
2345  else if (strcmp(optarg, "f") == 0 ||
2346  strcmp(optarg, "fetch") == 0)
2347  {
2349  }
2350  else if (strcmp(optarg, "s") == 0 ||
2351  strcmp(optarg, "stream") == 0)
2352  {
2354  }
2355  else
2356  {
2357  pg_log_error("invalid wal-method option \"%s\", must be \"fetch\", \"stream\", or \"none\"",
2358  optarg);
2359  exit(1);
2360  }
2361  break;
2362  case 1:
2364  break;
2365  case 'l':
2366  label = pg_strdup(optarg);
2367  break;
2368  case 'n':
2369  noclean = true;
2370  break;
2371  case 'N':
2372  do_sync = false;
2373  break;
2374  case 'z':
2375 #ifdef HAVE_LIBZ
2377 #else
2378  compresslevel = 1; /* will be rejected below */
2379 #endif
2380  break;
2381  case 'Z':
2382  if (!option_parse_int(optarg, "-Z/--compress", 0, 9,
2383  &compresslevel))
2384  exit(1);
2385  break;
2386  case 'c':
2387  if (pg_strcasecmp(optarg, "fast") == 0)
2388  fastcheckpoint = true;
2389  else if (pg_strcasecmp(optarg, "spread") == 0)
2390  fastcheckpoint = false;
2391  else
2392  {
2393  pg_log_error("invalid checkpoint argument \"%s\", must be \"fast\" or \"spread\"",
2394  optarg);
2395  exit(1);
2396  }
2397  break;
2398  case 'd':
2400  break;
2401  case 'h':
2402  dbhost = pg_strdup(optarg);
2403  break;
2404  case 'p':
2405  dbport = pg_strdup(optarg);
2406  break;
2407  case 'U':
2408  dbuser = pg_strdup(optarg);
2409  break;
2410  case 'w':
2411  dbgetpassword = -1;
2412  break;
2413  case 'W':
2414  dbgetpassword = 1;
2415  break;
2416  case 's':
2417  if (!option_parse_int(optarg, "-s/--status-interval", 0,
2418  INT_MAX / 1000,
2420  exit(1);
2421  standby_message_timeout *= 1000;
2422  break;
2423  case 'v':
2424  verbose++;
2425  break;
2426  case 'P':
2427  showprogress = true;
2428  break;
2429  case 3:
2430  verify_checksums = false;
2431  break;
2432  case 4:
2433  estimatesize = false;
2434  break;
2435  case 5:
2436  manifest = false;
2437  break;
2438  case 6:
2439  manifest_force_encode = true;
2440  break;
2441  case 7:
2443  break;
2444  default:
2445 
2446  /*
2447  * getopt_long already emitted a complaint
2448  */
2449  fprintf(stderr, _("Try \"%s --help\" for more information.\n"),
2450  progname);
2451  exit(1);
2452  }
2453  }
2454 
2455  /*
2456  * Any non-option arguments?
2457  */
2458  if (optind < argc)
2459  {
2460  pg_log_error("too many command-line arguments (first is \"%s\")",
2461  argv[optind]);
2462  fprintf(stderr, _("Try \"%s --help\" for more information.\n"),
2463  progname);
2464  exit(1);
2465  }
2466 
2467  /*
2468  * Required arguments
2469  */
2470  if (basedir == NULL)
2471  {
2472  pg_log_error("no target directory specified");
2473  fprintf(stderr, _("Try \"%s --help\" for more information.\n"),
2474  progname);
2475  exit(1);
2476  }
2477 
2478  /*
2479  * Mutually exclusive arguments
2480  */
2481  if (format == 'p' && compresslevel != 0)
2482  {
2483  pg_log_error("only tar mode backups can be compressed");
2484  fprintf(stderr, _("Try \"%s --help\" for more information.\n"),
2485  progname);
2486  exit(1);
2487  }
2488 
2489  if (format == 't' && includewal == STREAM_WAL && strcmp(basedir, "-") == 0)
2490  {
2491  pg_log_error("cannot stream write-ahead logs in tar mode to stdout");
2492  fprintf(stderr, _("Try \"%s --help\" for more information.\n"),
2493  progname);
2494  exit(1);
2495  }
2496 
2498  {
2499  pg_log_error("replication slots can only be used with WAL streaming");
2500  fprintf(stderr, _("Try \"%s --help\" for more information.\n"),
2501  progname);
2502  exit(1);
2503  }
2504 
2505  if (no_slot)
2506  {
2507  if (replication_slot)
2508  {
2509  pg_log_error("--no-slot cannot be used with slot name");
2510  fprintf(stderr, _("Try \"%s --help\" for more information.\n"),
2511  progname);
2512  exit(1);
2513  }
2514  temp_replication_slot = false;
2515  }
2516 
2517  if (create_slot)
2518  {
2519  if (!replication_slot)
2520  {
2521  pg_log_error("%s needs a slot to be specified using --slot",
2522  "--create-slot");
2523  fprintf(stderr, _("Try \"%s --help\" for more information.\n"),
2524  progname);
2525  exit(1);
2526  }
2527 
2528  if (no_slot)
2529  {
2530  pg_log_error("%s and %s are incompatible options",
2531  "--create-slot", "--no-slot");
2532  fprintf(stderr, _("Try \"%s --help\" for more information.\n"),
2533  progname);
2534  exit(1);
2535  }
2536  }
2537 
2538  if (xlog_dir)
2539  {
2540  if (format != 'p')
2541  {
2542  pg_log_error("WAL directory location can only be specified in plain mode");
2543  fprintf(stderr, _("Try \"%s --help\" for more information.\n"),
2544  progname);
2545  exit(1);
2546  }
2547 
2548  /* clean up xlog directory name, check it's absolute */
2550  if (!is_absolute_path(xlog_dir))
2551  {
2552  pg_log_error("WAL directory location must be an absolute path");
2553  fprintf(stderr, _("Try \"%s --help\" for more information.\n"),
2554  progname);
2555  exit(1);
2556  }
2557  }
2558 
2559 #ifndef HAVE_LIBZ
2560  if (compresslevel != 0)
2561  {
2562  pg_log_error("this build does not support compression");
2563  exit(1);
2564  }
2565 #endif
2566 
2567  if (showprogress && !estimatesize)
2568  {
2569  pg_log_error("%s and %s are incompatible options",
2570  "--progress", "--no-estimate-size");
2571  fprintf(stderr, _("Try \"%s --help\" for more information.\n"),
2572  progname);
2573  exit(1);
2574  }
2575 
2576  if (!manifest && manifest_checksums != NULL)
2577  {
2578  pg_log_error("%s and %s are incompatible options",
2579  "--no-manifest", "--manifest-checksums");
2580  fprintf(stderr, _("Try \"%s --help\" for more information.\n"),
2581  progname);
2582  exit(1);
2583  }
2584 
2586  {
2587  pg_log_error("%s and %s are incompatible options",
2588  "--no-manifest", "--manifest-force-encode");
2589  fprintf(stderr, _("Try \"%s --help\" for more information.\n"),
2590  progname);
2591  exit(1);
2592  }
2593 
2594  /* connection in replication mode to server */
2595  conn = GetConnection();
2596  if (!conn)
2597  {
2598  /* Error message already written in GetConnection() */
2599  exit(1);
2600  }
2601  atexit(disconnect_atexit);
2602 
2603  /*
2604  * Set umask so that directories/files are created with the same
2605  * permissions as directories/files in the source data directory.
2606  *
2607  * pg_mode_mask is set to owner-only by default and then updated in
2608  * GetConnection() where we get the mode from the server-side with
2609  * RetrieveDataDirCreatePerm() and then call SetDataDirectoryCreatePerm().
2610  */
2611  umask(pg_mode_mask);
2612 
2613  /* Backup manifests are supported in 13 and newer versions */
2615  manifest = false;
2616 
2617  /*
2618  * Verify that the target directory exists, or create it. For plaintext
2619  * backups, always require the directory. For tar backups, require it
2620  * unless we are writing to stdout.
2621  */
2622  if (format == 'p' || strcmp(basedir, "-") != 0)
2624 
2625  /* determine remote server's xlog segment size */
2626  if (!RetrieveWalSegSize(conn))
2627  exit(1);
2628 
2629  /* Create pg_wal symlink, if required */
2630  if (xlog_dir)
2631  {
2632  char *linkloc;
2633 
2635 
2636  /*
2637  * Form name of the place where the symlink must go. pg_xlog has been
2638  * renamed to pg_wal in post-10 clusters.
2639  */
2640  linkloc = psprintf("%s/%s", basedir,
2642  "pg_xlog" : "pg_wal");
2643 
2644 #ifdef HAVE_SYMLINK
2645  if (symlink(xlog_dir, linkloc) != 0)
2646  {
2647  pg_log_error("could not create symbolic link \"%s\": %m", linkloc);
2648  exit(1);
2649  }
2650 #else
2651  pg_log_error("symlinks are not supported on this platform");
2652  exit(1);
2653 #endif
2654  free(linkloc);
2655  }
2656 
2657  BaseBackup();
2658 
2659  success = true;
2660  return 0;
2661 }
static IncludeWal includewal
#define Z_DEFAULT_COMPRESSION
static bool verify_checksums
static bool found_existing_pgdata
const char * progname
Definition: main.c:46
static void usage(void)
bool option_parse_int(const char *optarg, const char *optname, int min_range, int max_range, int *result)
Definition: option_utils.c:50
const char * get_progname(const char *argv0)
Definition: path.c:453
#define pg_log_error(...)
Definition: logging.h:80
int getopt_long(int argc, char *const argv[], const char *optstring, const struct option *longopts, int *longindex)
Definition: getopt_long.c:57
static int32 parse_max_rate(char *src)
static bool manifest_force_encode
void pg_logging_init(const char *argv0)
Definition: logging.c:81
char * psprintf(const char *fmt,...)
Definition: psprintf.c:46
void canonicalize_path(char *path)
Definition: path.c:254
static bool writerecoveryconf
static bool create_slot
static int compresslevel
int pg_strcasecmp(const char *s1, const char *s2)
Definition: pgstrcasecmp.c:36
int PQserverVersion(const PGconn *conn)
Definition: fe-connect.c:6727
#define fprintf
Definition: port.h:220
static char * basedir
static void BaseBackup(void)
#define required_argument
Definition: getopt_long.h:25
int optind
Definition: getopt.c:50
PGconn * GetConnection(UserMapping *user, bool will_prep_stmt, PgFdwConnState **state)
Definition: connection.c:125
char * connection_string
Definition: streamutil.c:47
bool RetrieveWalSegSize(PGconn *conn)
Definition: streamutil.c:277
PGconn * conn
Definition: streamutil.c:54
#define MINIMUM_VERSION_FOR_PG_WAL
static bool found_existing_xlogdir
static bool estimatesize
static bool success
static int32 maxrate
char * c
#define symlink(oldpath, newpath)
Definition: win32_port.h:227
static bool made_new_pgdata
#define is_absolute_path(filename)
Definition: port.h:86
char * pg_strdup(const char *in)
Definition: fe_memutils.c:85
static char * manifest_checksums
static int verbose
static int standby_message_timeout
static bool showprogress
int dbgetpassword
Definition: streamutil.c:52
#define no_argument
Definition: getopt_long.h:24
#define PG_TEXTDOMAIN(domain)
Definition: c.h:1215
static bool temp_replication_slot
static char * label
static void disconnect_atexit(void)
char * dbport
Definition: streamutil.c:50
static void cleanup_directories_atexit(void)
#define free(a)
Definition: header.h:65
#define MINIMUM_VERSION_FOR_MANIFESTS
char * dbhost
Definition: streamutil.c:48
static char * xlog_dir
static bool manifest
static bool no_slot
static bool made_new_xlogdir
static bool fastcheckpoint
static void tablespace_list_append(const char *arg)
void set_pglocale_pgservice(const char *argv0, const char *app)
Definition: exec.c:433
char * dbuser
Definition: streamutil.c:49
char * optarg
Definition: getopt.c:52
static bool do_sync
static void verify_dir_is_empty_or_create(char *dirname, bool *created, bool *found)
static char format
static char * replication_slot
#define _(x)
Definition: elog.c:89
int pg_mode_mask
Definition: file_perm.c:25
static bool noclean

◆ parse_max_rate()

static int32 parse_max_rate ( char *  src)
static

Definition at line 869 of file pg_basebackup.c.

References MAX_RATE_UPPER, and pg_log_error.

Referenced by main().

870 {
871  double result;
872  char *after_num;
873  char *suffix = NULL;
874 
875  errno = 0;
876  result = strtod(src, &after_num);
877  if (src == after_num)
878  {
879  pg_log_error("transfer rate \"%s\" is not a valid value", src);
880  exit(1);
881  }
882  if (errno != 0)
883  {
884  pg_log_error("invalid transfer rate \"%s\": %m", src);
885  exit(1);
886  }
887 
888  if (result <= 0)
889  {
890  /*
891  * Reject obviously wrong values here.
892  */
893  pg_log_error("transfer rate must be greater than zero");
894  exit(1);
895  }
896 
897  /*
898  * Evaluate suffix, after skipping over possible whitespace. Lack of
899  * suffix means kilobytes.
900  */
901  while (*after_num != '\0' && isspace((unsigned char) *after_num))
902  after_num++;
903 
904  if (*after_num != '\0')
905  {
906  suffix = after_num;
907  if (*after_num == 'k')
908  {
909  /* kilobyte is the expected unit. */
910  after_num++;
911  }
912  else if (*after_num == 'M')
913  {
914  after_num++;
915  result *= 1024.0;
916  }
917  }
918 
919  /* The rest can only consist of white space. */
920  while (*after_num != '\0' && isspace((unsigned char) *after_num))
921  after_num++;
922 
923  if (*after_num != '\0')
924  {
925  pg_log_error("invalid --max-rate unit: \"%s\"", suffix);
926  exit(1);
927  }
928 
929  /* Valid integer? */
930  if ((uint64) result != (uint64) ((uint32) result))
931  {
932  pg_log_error("transfer rate \"%s\" exceeds integer range", src);
933  exit(1);
934  }
935 
936  /*
937  * The range is checked on the server side too, but avoid the server
938  * connection if a nonsensical value was passed.
939  */
940  if (result < MAX_RATE_LOWER || result > MAX_RATE_UPPER)
941  {
942  pg_log_error("transfer rate \"%s\" is out of range", src);
943  exit(1);
944  }
945 
946  return (int32) result;
947 }
#define pg_log_error(...)
Definition: logging.h:80
signed int int32
Definition: c.h:429
#define MAX_RATE_UPPER
Definition: basebackup.h:21
unsigned int uint32
Definition: c.h:441

◆ progress_report()

static void progress_report ( int  tablespacenum,
const char *  filename,
bool  force,
bool  finished 
)
static

Definition at line 778 of file pg_basebackup.c.

References fprintf, INT64_FORMAT, last_progress_report, ngettext, now(), showprogress, snprintf, tablespacecount, totaldone, totalsize_kb, verbose, and VERBOSE_FILENAME_LENGTH.

Referenced by BaseBackup(), ReceiveAndUnpackTarFile(), ReceiveTarAndUnpackCopyChunk(), ReceiveTarCopyChunk(), and ReceiveTarFile().

780 {
781  int percent;
782  char totaldone_str[32];
783  char totalsize_str[32];
784  pg_time_t now;
785 
786  if (!showprogress)
787  return;
788 
789  now = time(NULL);
790  if (now == last_progress_report && !force && !finished)
791  return; /* Max once per second */
792 
794  percent = totalsize_kb ? (int) ((totaldone / 1024) * 100 / totalsize_kb) : 0;
795 
796  /*
797  * Avoid overflowing past 100% or the full size. This may make the total
798  * size number change as we approach the end of the backup (the estimate
799  * will always be wrong if WAL is included), but that's better than having
800  * the done column be bigger than the total.
801  */
802  if (percent > 100)
803  percent = 100;
804  if (totaldone / 1024 > totalsize_kb)
805  totalsize_kb = totaldone / 1024;
806 
807  /*
808  * Separate step to keep platform-dependent format code out of
809  * translatable strings. And we only test for INT64_FORMAT availability
810  * in snprintf, not fprintf.
811  */
812  snprintf(totaldone_str, sizeof(totaldone_str), INT64_FORMAT,
813  totaldone / 1024);
814  snprintf(totalsize_str, sizeof(totalsize_str), INT64_FORMAT, totalsize_kb);
815 
816 #define VERBOSE_FILENAME_LENGTH 35
817  if (verbose)
818  {
819  if (!filename)
820 
821  /*
822  * No filename given, so clear the status line (used for last
823  * call)
824  */
825  fprintf(stderr,
826  ngettext("%*s/%s kB (100%%), %d/%d tablespace %*s",
827  "%*s/%s kB (100%%), %d/%d tablespaces %*s",
829  (int) strlen(totalsize_str),
830  totaldone_str, totalsize_str,
831  tablespacenum, tablespacecount,
832  VERBOSE_FILENAME_LENGTH + 5, "");
833  else
834  {
835  bool truncate = (strlen(filename) > VERBOSE_FILENAME_LENGTH);
836 
837  fprintf(stderr,
838  ngettext("%*s/%s kB (%d%%), %d/%d tablespace (%s%-*.*s)",
839  "%*s/%s kB (%d%%), %d/%d tablespaces (%s%-*.*s)",
841  (int) strlen(totalsize_str),
842  totaldone_str, totalsize_str, percent,
843  tablespacenum, tablespacecount,
844  /* Prefix with "..." if we do leading truncation */
845  truncate ? "..." : "",
848  /* Truncate filename at beginning if it's too long */
849  truncate ? filename + strlen(filename) - VERBOSE_FILENAME_LENGTH + 3 : filename);
850  }
851  }
852  else
853  fprintf(stderr,
854  ngettext("%*s/%s kB (%d%%), %d/%d tablespace",
855  "%*s/%s kB (%d%%), %d/%d tablespaces",
857  (int) strlen(totalsize_str),
858  totaldone_str, totalsize_str, percent,
859  tablespacenum, tablespacecount);
860 
861  /*
862  * Stay on the same line if reporting to a terminal and we're not done
863  * yet.
864  */
865  fputc((!finished && isatty(fileno(stderr))) ? '\r' : '\n', stderr);
866 }
int64 pg_time_t
Definition: pgtime.h:23
static pg_time_t last_progress_report
static int tablespacecount
#define VERBOSE_FILENAME_LENGTH
#define fprintf
Definition: port.h:220
static uint64 totaldone
static int verbose
static bool showprogress
#define ngettext(s, p, n)
Definition: c.h:1182
#define INT64_FORMAT
Definition: c.h:483
static char * filename
Definition: pg_dumpall.c:92
static uint64 totalsize_kb
#define snprintf
Definition: port.h:216
Datum now(PG_FUNCTION_ARGS)
Definition: timestamp.c:1544

◆ reached_end_position()

static bool reached_end_position ( XLogRecPtr  segendpos,
uint32  timeline,
bool  segment_finished 
)
static

Definition at line 443 of file pg_basebackup.c.

References bgpipe, has_xlogendptr, MemSet, pg_log_error, read, select, and xlogendptr.

Referenced by LogStreamerMain().

445 {
446  if (!has_xlogendptr)
447  {
448 #ifndef WIN32
449  fd_set fds;
450  struct timeval tv;
451  int r;
452 
453  /*
454  * Don't have the end pointer yet - check our pipe to see if it has
455  * been sent yet.
456  */
457  FD_ZERO(&fds);
458  FD_SET(bgpipe[0], &fds);
459 
460  MemSet(&tv, 0, sizeof(tv));
461 
462  r = select(bgpipe[0] + 1, &fds, NULL, NULL, &tv);
463  if (r == 1)
464  {
465  char xlogend[64];
466  uint32 hi,
467  lo;
468 
469  MemSet(xlogend, 0, sizeof(xlogend));
470  r = read(bgpipe[0], xlogend, sizeof(xlogend) - 1);
471  if (r < 0)
472  {
473  pg_log_error("could not read from ready pipe: %m");
474  exit(1);
475  }
476 
477  if (sscanf(xlogend, "%X/%X", &hi, &lo) != 2)
478  {
479  pg_log_error("could not parse write-ahead log location \"%s\"",
480  xlogend);
481  exit(1);
482  }
483  xlogendptr = ((uint64) hi) << 32 | lo;
484  has_xlogendptr = 1;
485 
486  /*
487  * Fall through to check if we've reached the point further
488  * already.
489  */
490  }
491  else
492  {
493  /*
494  * No data received on the pipe means we don't know the end
495  * position yet - so just say it's not time to stop yet.
496  */
497  return false;
498  }
499 #else
500 
501  /*
502  * On win32, has_xlogendptr is set by the main thread, so if it's not
503  * set here, we just go back and wait until it shows up.
504  */
505  return false;
506 #endif
507  }
508 
509  /*
510  * At this point we have an end pointer, so compare it to the current
511  * position to figure out if it's time to stop.
512  */
513  if (segendpos >= xlogendptr)
514  return true;
515 
516  /*
517  * Have end pointer, but haven't reached it yet - so tell the caller to
518  * keep streaming.
519  */
520  return false;
521 }
static int bgpipe[2]
#define pg_log_error(...)
Definition: logging.h:80
#define MemSet(start, val, len)
Definition: c.h:1008
static int has_xlogendptr
#define select(n, r, w, e, timeout)
Definition: win32_port.h:464
unsigned int uint32
Definition: c.h:441
static XLogRecPtr xlogendptr
#define read(a, b, c)
Definition: win32.h:13

◆ ReceiveAndUnpackTarFile()

static void ReceiveAndUnpackTarFile ( PGconn conn,
PGresult res,
int  rownum 
)
static

Definition at line 1517 of file pg_basebackup.c.

References basedir, UnpackTarState::current_path, UnpackTarState::file, UnpackTarState::filename, get_tablespace_mapping(), pg_log_error, PQgetisnull(), PQgetvalue(), progress_report(), ReceiveCopyData(), ReceiveTarAndUnpackCopyChunk(), strlcpy(), UnpackTarState::tablespacenum, writerecoveryconf, and WriteRecoveryConfig().

Referenced by BaseBackup().

1518 {
1520  bool basetablespace;
1521 
1522  memset(&state, 0, sizeof(state));
1523  state.tablespacenum = rownum;
1524 
1525  basetablespace = PQgetisnull(res, rownum, 0);
1526  if (basetablespace)
1527  strlcpy(state.current_path, basedir, sizeof(state.current_path));
1528  else
1529  strlcpy(state.current_path,
1530  get_tablespace_mapping(PQgetvalue(res, rownum, 1)),
1531  sizeof(state.current_path));
1532 
1534 
1535 
1536  if (state.file)
1537  fclose(state.file);
1538 
1539  progress_report(rownum, state.filename, true, false);
1540 
1541  if (state.file != NULL)
1542  {
1543  pg_log_error("COPY stream ended before last file was finished");
1544  exit(1);
1545  }
1546 
1547  if (basetablespace && writerecoveryconf)
1549 
1550  /*
1551  * No data is synced here, everything is done for all tablespaces at the
1552  * end.
1553  */
1554 }
char current_path[MAXPGPATH]
Definition: pg_basebackup.c:85
static PQExpBuffer recoveryconfcontents
char * PQgetvalue(const PGresult *res, int tup_num, int field_num)
Definition: fe-exec.c:3642
#define pg_log_error(...)
Definition: logging.h:80
void WriteRecoveryConfig(PGconn *pgconn, char *target_dir, PQExpBuffer contents)
Definition: recovery_gen.c:117
static bool writerecoveryconf
char filename[MAXPGPATH]
Definition: pg_basebackup.c:86
static char * basedir
static void ReceiveTarAndUnpackCopyChunk(size_t r, char *copybuf, void *callback_data)
static void ReceiveCopyData(PGconn *conn, WriteDataCallback callback, void *callback_data)
static const char * get_tablespace_mapping(const char *dir)
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition: strlcpy.c:45
Definition: regguts.h:317
int PQgetisnull(const PGresult *res, int tup_num, int field_num)
Definition: fe-exec.c:3667
static void progress_report(int tablespacenum, const char *filename, bool force, bool finished)

◆ ReceiveBackupManifest()

static void ReceiveBackupManifest ( PGconn conn)
static

Definition at line 1746 of file pg_basebackup.c.

References basedir, WriteManifestState::file, WriteManifestState::filename, pg_log_error, ReceiveBackupManifestChunk(), ReceiveCopyData(), and snprintf.

Referenced by BaseBackup().

1747 {
1749 
1750  snprintf(state.filename, sizeof(state.filename),
1751  "%s/backup_manifest.tmp", basedir);
1752  state.file = fopen(state.filename, "wb");
1753  if (state.file == NULL)
1754  {
1755  pg_log_error("could not create file \"%s\": %m", state.filename);
1756  exit(1);
1757  }
1758 
1760 
1761  fclose(state.file);
1762 }
#define pg_log_error(...)
Definition: logging.h:80
static char * basedir
static void ReceiveCopyData(PGconn *conn, WriteDataCallback callback, void *callback_data)
static void ReceiveBackupManifestChunk(size_t r, char *copybuf, void *callback_data)
Definition: regguts.h:317
char filename[MAXPGPATH]
Definition: pg_basebackup.c:95
#define snprintf
Definition: port.h:216

◆ ReceiveBackupManifestChunk()

static void ReceiveBackupManifestChunk ( size_t  r,
char *  copybuf,
void *  callback_data 
)
static

Definition at line 1768 of file pg_basebackup.c.

References WriteManifestState::file, WriteManifestState::filename, and pg_log_error.

Referenced by ReceiveBackupManifest().

1769 {
1770  WriteManifestState *state = callback_data;
1771 
1772  errno = 0;
1773  if (fwrite(copybuf, r, 1, state->file) != 1)
1774  {
1775  /* if write didn't set errno, assume problem is no disk space */
1776  if (errno == 0)
1777  errno = ENOSPC;
1778  pg_log_error("could not write to file \"%s\": %m", state->filename);
1779  exit(1);
1780  }
1781 }
#define pg_log_error(...)
Definition: logging.h:80
StringInfo copybuf
Definition: tablesync.c:124
Definition: regguts.h:317
char filename[MAXPGPATH]
Definition: pg_basebackup.c:95

◆ ReceiveBackupManifestInMemory()

static void ReceiveBackupManifestInMemory ( PGconn conn,
PQExpBuffer  buf 
)
static

Definition at line 1787 of file pg_basebackup.c.

References ReceiveBackupManifestInMemoryChunk(), and ReceiveCopyData().

Referenced by ReceiveTarFile().

1788 {
1790 }
static void ReceiveCopyData(PGconn *conn, WriteDataCallback callback, void *callback_data)
static void ReceiveBackupManifestInMemoryChunk(size_t r, char *copybuf, void *callback_data)

◆ ReceiveBackupManifestInMemoryChunk()

static void ReceiveBackupManifestInMemoryChunk ( size_t  r,
char *  copybuf,
void *  callback_data 
)
static

Definition at line 1796 of file pg_basebackup.c.

References appendPQExpBuffer(), and buf.

Referenced by ReceiveBackupManifestInMemory().

1798 {
1799  PQExpBuffer buf = callback_data;
1800 
1801  appendPQExpBuffer(buf, copybuf, r);
1802 }
void appendPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:267
static char * buf
Definition: pg_test_fsync.c:68
StringInfo copybuf
Definition: tablesync.c:124

◆ ReceiveCopyData()

static void ReceiveCopyData ( PGconn conn,
WriteDataCallback  callback,
void *  callback_data 
)
static

Definition at line 954 of file pg_basebackup.c.

References copybuf, pg_log_error, PGRES_COPY_OUT, PQclear(), PQerrorMessage(), PQfreemem(), PQgetCopyData(), PQgetResult(), and PQresultStatus().

Referenced by ReceiveAndUnpackTarFile(), ReceiveBackupManifest(), ReceiveBackupManifestInMemory(), and ReceiveTarFile().

956 {
957  PGresult *res;
958 
959  /* Get the COPY data stream. */
960  res = PQgetResult(conn);
961  if (PQresultStatus(res) != PGRES_COPY_OUT)
962  {
963  pg_log_error("could not get COPY data stream: %s",
964  PQerrorMessage(conn));
965  exit(1);
966  }
967  PQclear(res);
968 
969  /* Loop over chunks until done. */
970  while (1)
971  {
972  int r;
973  char *copybuf;
974 
975  r = PQgetCopyData(conn, &copybuf, 0);
976  if (r == -1)
977  {
978  /* End of chunk. */
979  break;
980  }
981  else if (r == -2)
982  {
983  pg_log_error("could not read COPY data: %s",
984  PQerrorMessage(conn));
985  exit(1);
986  }
987 
988  (*callback) (r, copybuf, callback_data);
989 
990  PQfreemem(copybuf);
991  }
992 }
char * PQerrorMessage(const PGconn *conn)
Definition: fe-connect.c:6737
#define pg_log_error(...)
Definition: logging.h:80
ExecStatusType PQresultStatus(const PGresult *res)
Definition: fe-exec.c:3178
int PQgetCopyData(PGconn *conn, char **buffer, int async)
Definition: fe-exec.c:2668
StringInfo copybuf
Definition: tablesync.c:124
void PQclear(PGresult *res)
Definition: fe-exec.c:694
void PQfreemem(void *ptr)
Definition: fe-exec.c:3796
PGresult * PQgetResult(PGconn *conn)
Definition: fe-exec.c:1978

◆ ReceiveTarAndUnpackCopyChunk()

static void ReceiveTarAndUnpackCopyChunk ( size_t  r,
char *  copybuf,
void *  callback_data 
)
static

Definition at line 1557 of file pg_basebackup.c.

References UnpackTarState::current_len_left, UnpackTarState::current_padding, UnpackTarState::current_path, UnpackTarState::file, UnpackTarState::filename, get_tablespace_mapping(), UnpackTarState::mapped_tblspc_path, mkdir, pg_dir_create_mode, pg_log_error, pg_str_endswith(), progress_report(), read_tar_number(), snprintf, symlink, UnpackTarState::tablespacenum, TAR_BLOCK_SIZE, tarPaddingBytesRequired(), and totaldone.

Referenced by ReceiveAndUnpackTarFile().

1558 {
1559  UnpackTarState *state = callback_data;
1560 
1561  if (state->file == NULL)
1562  {
1563 #ifndef WIN32
1564  int filemode;
1565 #endif
1566 
1567  /*
1568  * No current file, so this must be the header for a new file
1569  */
1570  if (r != TAR_BLOCK_SIZE)
1571  {
1572  pg_log_error("invalid tar block header size: %zu", r);
1573  exit(1);
1574  }
1576 
1577  state->current_len_left = read_tar_number(&copybuf[124], 12);
1578 
1579 #ifndef WIN32
1580  /* Set permissions on the file */
1581  filemode = read_tar_number(&copybuf[100], 8);
1582 #endif
1583 
1584  /*
1585  * All files are padded up to a multiple of TAR_BLOCK_SIZE
1586  */
1587  state->current_padding =
1589 
1590  /*
1591  * First part of header is zero terminated filename
1592  */
1593  snprintf(state->filename, sizeof(state->filename),
1594  "%s/%s", state->current_path, copybuf);
1595  if (state->filename[strlen(state->filename) - 1] == '/')
1596  {
1597  /*
1598  * Ends in a slash means directory or symlink to directory
1599  */
1600  if (copybuf[156] == '5')
1601  {
1602  /*
1603  * Directory. Remove trailing slash first.
1604  */
1605  state->filename[strlen(state->filename) - 1] = '\0';
1606  if (mkdir(state->filename, pg_dir_create_mode) != 0)
1607  {
1608  /*
1609  * When streaming WAL, pg_wal (or pg_xlog for pre-9.6
1610  * clusters) will have been created by the wal receiver
1611  * process. Also, when the WAL directory location was
1612  * specified, pg_wal (or pg_xlog) has already been created
1613  * as a symbolic link before starting the actual backup.
1614  * So just ignore creation failures on related
1615  * directories.
1616  */
1617  if (!((pg_str_endswith(state->filename, "/pg_wal") ||
1618  pg_str_endswith(state->filename, "/pg_xlog") ||
1619  pg_str_endswith(state->filename, "/archive_status")) &&
1620  errno == EEXIST))
1621  {
1622  pg_log_error("could not create directory \"%s\": %m",
1623  state->filename);
1624  exit(1);
1625  }
1626  }
1627 #ifndef WIN32
1628  if (chmod(state->filename, (mode_t) filemode))
1629  {
1630  pg_log_error("could not set permissions on directory \"%s\": %m",
1631  state->filename);
1632  exit(1);
1633  }
1634 #endif
1635  }
1636  else if (copybuf[156] == '2')
1637  {
1638  /*
1639  * Symbolic link
1640  *
1641  * It's most likely a link in pg_tblspc directory, to the
1642  * location of a tablespace. Apply any tablespace mapping
1643  * given on the command line (--tablespace-mapping). (We
1644  * blindly apply the mapping without checking that the link
1645  * really is inside pg_tblspc. We don't expect there to be
1646  * other symlinks in a data directory, but if there are, you
1647  * can call it an undocumented feature that you can map them
1648  * too.)
1649  */
1650  state->filename[strlen(state->filename) - 1] = '\0'; /* Remove trailing slash */
1651 
1652  state->mapped_tblspc_path =
1654  if (symlink(state->mapped_tblspc_path, state->filename) != 0)
1655  {
1656  pg_log_error("could not create symbolic link from \"%s\" to \"%s\": %m",
1657  state->filename, state->mapped_tblspc_path);
1658  exit(1);
1659  }
1660  }
1661  else
1662  {
1663  pg_log_error("unrecognized link indicator \"%c\"",
1664  copybuf[156]);
1665  exit(1);
1666  }
1667  return; /* directory or link handled */
1668  }
1669 
1670  /*
1671  * regular file
1672  */
1673  state->file = fopen(state->filename, "wb");
1674  if (!state->file)
1675  {
1676  pg_log_error("could not create file \"%s\": %m", state->filename);
1677  exit(1);
1678  }
1679 
1680 #ifndef WIN32
1681  if (chmod(state->filename, (mode_t) filemode))
1682  {
1683  pg_log_error("could not set permissions on file \"%s\": %m",
1684  state->filename);
1685  exit(1);
1686  }
1687 #endif
1688 
1689  if (state->current_len_left == 0)
1690  {
1691  /*
1692  * Done with this file, next one will be a new tar header
1693  */
1694  fclose(state->file);
1695  state->file = NULL;
1696  return;
1697  }
1698  } /* new file */
1699  else
1700  {
1701  /*
1702  * Continuing blocks in existing file
1703  */
1704  if (state->current_len_left == 0 && r == state->current_padding)
1705  {
1706  /*
1707  * Received the padding block for this file, ignore it and close
1708  * the file, then move on to the next tar header.
1709  */
1710  fclose(state->file);
1711  state->file = NULL;
1712  totaldone += r;
1713  return;
1714  }
1715 
1716  errno = 0;
1717  if (fwrite(copybuf, r, 1, state->file) != 1)
1718  {
1719  /* if write didn't set errno, assume problem is no disk space */
1720  if (errno == 0)
1721  errno = ENOSPC;
1722  pg_log_error("could not write to file \"%s\": %m", state->filename);
1723  exit(1);
1724  }
1725  totaldone += r;
1726  progress_report(state->tablespacenum, state->filename, false, false);
1727 
1728  state->current_len_left -= r;
1729  if (state->current_len_left == 0 && state->current_padding == 0)
1730  {
1731  /*
1732  * Received the last block, and there is no padding to be
1733  * expected. Close the file and move on to the next tar header.
1734  */
1735  fclose(state->file);
1736  state->file = NULL;
1737  return;
1738  }
1739  } /* continuing data in existing file */
1740 }
char current_path[MAXPGPATH]
Definition: pg_basebackup.c:85
const char * mapped_tblspc_path
Definition: pg_basebackup.c:87
bool pg_str_endswith(const char *str, const char *end)
Definition: string.c:31
uint64 read_tar_number(const char *s, int len)
Definition: tar.c:58
#define pg_log_error(...)
Definition: logging.h:80
char filename[MAXPGPATH]
Definition: pg_basebackup.c:86
static uint64 totaldone
#define TAR_BLOCK_SIZE
Definition: pgtar.h:17
#define symlink(oldpath, newpath)
Definition: win32_port.h:227
static const char * get_tablespace_mapping(const char *dir)
int pg_dir_create_mode
Definition: file_perm.c:18
StringInfo copybuf
Definition: tablesync.c:124
static size_t tarPaddingBytesRequired(size_t len)
Definition: pgtar.h:40
Definition: regguts.h:317
#define mkdir(a, b)
Definition: win32_port.h:63
#define snprintf
Definition: port.h:216
static void progress_report(int tablespacenum, const char *filename, bool force, bool finished)
pgoff_t current_len_left
Definition: pg_basebackup.c:88

◆ ReceiveTarCopyChunk()

static void ReceiveTarCopyChunk ( size_t  r,
char *  copybuf,
void *  callback_data 
)
static

Definition at line 1300 of file pg_basebackup.c.

References WriteTarState::basetablespace, PQExpBufferData::data, WriteTarState::file_padding_len, WriteTarState::filename, WriteTarState::filesz, WriteTarState::found_postgresql_auto_conf, header(), WriteTarState::in_tarhdr, WriteTarState::is_postgresql_auto_conf, WriteTarState::is_recovery_guc_supported, PQExpBufferData::len, MemSet, pg_file_create_mode, progress_report(), read_tar_number(), WriteTarState::skip_file, WriteTarState::tablespacenum, TAR_BLOCK_SIZE, tarCreateHeader(), WriteTarState::tarhdr, WriteTarState::tarhdrsz, tarPaddingBytesRequired(), totaldone, writerecoveryconf, and writeTarData().

Referenced by ReceiveTarFile().

1301 {
1302  WriteTarState *state = callback_data;
1303 
1304  if (!writerecoveryconf || !state->basetablespace)
1305  {
1306  /*
1307  * When not writing config file, or when not working on the base
1308  * tablespace, we never have to look for an existing configuration
1309  * file in the stream.
1310  */
1311  writeTarData(state, copybuf, r);
1312  }
1313  else
1314  {
1315  /*
1316  * Look for a config file in the existing tar stream. If it's there,
1317  * we must skip it so we can later overwrite it with our own version
1318  * of the file.
1319  *
1320  * To do this, we have to process the individual files inside the TAR
1321  * stream. The stream consists of a header and zero or more chunks,
1322  * each with a length equal to TAR_BLOCK_SIZE. The stream from the
1323  * server is broken up into smaller pieces, so we have to track the
1324  * size of the files to find the next header structure.
1325  */
1326  int rr = r;
1327  int pos = 0;
1328 
1329  while (rr > 0)
1330  {
1331  if (state->in_tarhdr)
1332  {
1333  /*
1334  * We're currently reading a header structure inside the TAR
1335  * stream, i.e. the file metadata.
1336  */
1337  if (state->tarhdrsz < TAR_BLOCK_SIZE)
1338  {
1339  /*
1340  * Copy the header structure into tarhdr in case the
1341  * header is not aligned properly or it's not returned in
1342  * whole by the last PQgetCopyData call.
1343  */
1344  int hdrleft;
1345  int bytes2copy;
1346 
1347  hdrleft = TAR_BLOCK_SIZE - state->tarhdrsz;
1348  bytes2copy = (rr > hdrleft ? hdrleft : rr);
1349 
1350  memcpy(&state->tarhdr[state->tarhdrsz], copybuf + pos,
1351  bytes2copy);
1352 
1353  rr -= bytes2copy;
1354  pos += bytes2copy;
1355  state->tarhdrsz += bytes2copy;
1356  }
1357  else
1358  {
1359  /*
1360  * We have the complete header structure in tarhdr, look
1361  * at the file metadata: we may want append recovery info
1362  * into postgresql.auto.conf and skip standby.signal file
1363  * if recovery parameters are integrated as GUCs, and
1364  * recovery.conf otherwise. In both cases we must
1365  * calculate tar padding.
1366  */
1367  if (state->is_recovery_guc_supported)
1368  {
1369  state->skip_file =
1370  (strcmp(&state->tarhdr[0], "standby.signal") == 0);
1371  state->is_postgresql_auto_conf =
1372  (strcmp(&state->tarhdr[0], "postgresql.auto.conf") == 0);
1373  }
1374  else
1375  state->skip_file =
1376  (strcmp(&state->tarhdr[0], "recovery.conf") == 0);
1377 
1378  state->filesz = read_tar_number(&state->tarhdr[124], 12);
1379  state->file_padding_len =
1381 
1382  if (state->is_recovery_guc_supported &&
1383  state->is_postgresql_auto_conf &&
1385  {
1386  /* replace tar header */
1387  char header[TAR_BLOCK_SIZE];
1388 
1389  tarCreateHeader(header, "postgresql.auto.conf", NULL,
1390  state->filesz + recoveryconfcontents->len,
1391  pg_file_create_mode, 04000, 02000,
1392  time(NULL));
1393 
1394  writeTarData(state, header, sizeof(header));
1395  }
1396  else
1397  {
1398  /* copy stream with padding */
1399  state->filesz += state->file_padding_len;
1400 
1401  if (!state->skip_file)
1402  {
1403  /*
1404  * If we're not skipping the file, write the tar
1405  * header unmodified.
1406  */
1407  writeTarData(state, state->tarhdr, TAR_BLOCK_SIZE);
1408  }
1409  }
1410 
1411  /* Next part is the file, not the header */
1412  state->in_tarhdr = false;
1413  }
1414  }
1415  else
1416  {
1417  /*
1418  * We're processing a file's contents.
1419  */
1420  if (state->filesz > 0)
1421  {
1422  /*
1423  * We still have data to read (and possibly write).
1424  */
1425  int bytes2write;
1426 
1427  bytes2write = (state->filesz > rr ? rr : state->filesz);
1428 
1429  if (!state->skip_file)
1430  writeTarData(state, copybuf + pos, bytes2write);
1431 
1432  rr -= bytes2write;
1433  pos += bytes2write;
1434  state->filesz -= bytes2write;
1435  }
1436  else if (state->is_recovery_guc_supported &&
1437  state->is_postgresql_auto_conf &&
1439  {
1440  /* append recovery config to postgresql.auto.conf */
1441  int padding;
1442  int tailsize;
1443 
1444  tailsize = (TAR_BLOCK_SIZE - state->file_padding_len) + recoveryconfcontents->len;
1445  padding = tarPaddingBytesRequired(tailsize);
1446 
1449 
1450  if (padding)
1451  {
1452  char zerobuf[TAR_BLOCK_SIZE];
1453 
1454  MemSet(zerobuf, 0, sizeof(zerobuf));
1455  writeTarData(state, zerobuf, padding);
1456  }
1457 
1458  /* skip original file padding */
1459  state->is_postgresql_auto_conf = false;
1460  state->skip_file = true;
1461  state->filesz += state->file_padding_len;
1462 
1463  state->found_postgresql_auto_conf = true;
1464  }
1465  else
1466  {
1467  /*
1468  * No more data in the current file, the next piece of
1469  * data (if any) will be a new file header structure.
1470  */
1471  state->in_tarhdr = true;
1472  state->skip_file = false;
1473  state->is_postgresql_auto_conf = false;
1474  state->tarhdrsz = 0;
1475  state->filesz = 0;
1476  }
1477  }
1478  }
1479  }
1480  totaldone += r;
1481  progress_report(state->tablespacenum, state->filename, false, false);
1482 }
bool found_postgresql_auto_conf
Definition: pg_basebackup.c:73
static PQExpBuffer recoveryconfcontents
int pg_file_create_mode
Definition: file_perm.c:19
bool is_recovery_guc_supported
Definition: pg_basebackup.c:71
uint64 read_tar_number(const char *s, int len)
Definition: tar.c:58
char tarhdr[TAR_BLOCK_SIZE]
Definition: pg_basebackup.c:67
static void writeTarData(WriteTarState *state, char *buf, int r)
static bool writerecoveryconf
#define MemSet(start, val, len)
Definition: c.h:1008
pgoff_t filesz
Definition: pg_basebackup.c:76
bool is_postgresql_auto_conf
Definition: pg_basebackup.c:72
static uint64 totaldone
#define TAR_BLOCK_SIZE
Definition: pgtar.h:17
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
StringInfo copybuf
Definition: tablesync.c:124
static size_t tarPaddingBytesRequired(size_t len)
Definition: pgtar.h:40
Definition: regguts.h:317
static void header(const char *fmt,...) pg_attribute_printf(1
Definition: pg_regress.c:210
char filename[MAXPGPATH]
Definition: pg_basebackup.c:65
static void progress_report(int tablespacenum, const char *filename, bool force, bool finished)

◆ ReceiveTarFile()

static void ReceiveTarFile ( PGconn conn,
PGresult res,
int  rownum 
)
static

Definition at line 1041 of file pg_basebackup.c.

References basedir, WriteTarState::basetablespace, buf, compresslevel, PQExpBufferData::data, fd(), WriteTarState::filename, WriteTarState::found_postgresql_auto_conf, header(), WriteTarState::in_tarhdr, initPQExpBuffer(), WriteTarState::is_recovery_guc_supported, PQExpBufferData::len, manifest, MemSet, MINIMUM_VERSION_FOR_RECOVERY_GUC, pg_file_create_mode, pg_log_error, PQExpBufferDataBroken, PQgetisnull(), PQgetvalue(), PQserverVersion(), progress_report(), ReceiveBackupManifestInMemory(), ReceiveCopyData(), ReceiveTarCopyChunk(), snprintf, generate_unaccent_rules::stdout, WriteTarState::tablespacenum, TAR_BLOCK_SIZE, tarCreateHeader(), WriteTarState::tarfile, tarPaddingBytesRequired(), termPQExpBuffer(), writerecoveryconf, and writeTarData().

Referenced by BaseBackup().

1042 {
1043  char zerobuf[TAR_BLOCK_SIZE * 2];
1045 
1046  memset(&state, 0, sizeof(state));
1047  state.tablespacenum = rownum;
1048  state.basetablespace = PQgetisnull(res, rownum, 0);
1049  state.in_tarhdr = true;
1050 
1051  /* recovery.conf is integrated into postgresql.conf in 12 and newer */
1053  state.is_recovery_guc_supported = true;
1054 
1055  if (state.basetablespace)
1056  {
1057  /*
1058  * Base tablespaces
1059  */
1060  if (strcmp(basedir, "-") == 0)
1061  {
1062 #ifdef WIN32
1063  _setmode(fileno(stdout), _O_BINARY);
1064 #endif
1065 
1066 #ifdef HAVE_LIBZ
1067  if (compresslevel != 0)
1068  {
1069  int fd = dup(fileno(stdout));
1070 
1071  if (fd < 0)
1072  {
1073  pg_log_error("could not duplicate stdout: %m");
1074  exit(1);
1075  }
1076 
1077  state.ztarfile = gzdopen(fd, "wb");
1078  if (state.ztarfile == NULL)
1079  {
1080  pg_log_error("could not open output file: %m");
1081  exit(1);
1082  }
1083 
1084  if (gzsetparams(state.ztarfile, compresslevel,
1085  Z_DEFAULT_STRATEGY) != Z_OK)
1086  {
1087  pg_log_error("could not set compression level %d: %s",
1088  compresslevel, get_gz_error(state.ztarfile));
1089  exit(1);
1090  }
1091  }
1092  else
1093 #endif
1094  state.tarfile = stdout;
1095  strcpy(state.filename, "-");
1096  }
1097  else
1098  {
1099 #ifdef HAVE_LIBZ
1100  if (compresslevel != 0)
1101  {
1102  snprintf(state.filename, sizeof(state.filename),
1103  "%s/base.tar.gz", basedir);
1104  state.ztarfile = gzopen(state.filename, "wb");
1105  if (gzsetparams(state.ztarfile, compresslevel,
1106  Z_DEFAULT_STRATEGY) != Z_OK)
1107  {
1108  pg_log_error("could not set compression level %d: %s",
1109  compresslevel, get_gz_error(state.ztarfile));
1110  exit(1);
1111  }
1112  }
1113  else
1114 #endif
1115  {
1116  snprintf(state.filename, sizeof(state.filename),
1117  "%s/base.tar", basedir);
1118  state.tarfile = fopen(state.filename, "wb");
1119  }
1120  }
1121  }
1122  else
1123  {
1124  /*
1125  * Specific tablespace
1126  */
1127 #ifdef HAVE_LIBZ
1128  if (compresslevel != 0)
1129  {
1130  snprintf(state.filename, sizeof(state.filename),
1131  "%s/%s.tar.gz",
1132  basedir, PQgetvalue(res, rownum, 0));
1133  state.ztarfile = gzopen(state.filename, "wb");
1134  if (gzsetparams(state.ztarfile, compresslevel,
1135  Z_DEFAULT_STRATEGY) != Z_OK)
1136  {
1137  pg_log_error("could not set compression level %d: %s",
1138  compresslevel, get_gz_error(state.ztarfile));
1139  exit(1);
1140  }
1141  }
1142  else
1143 #endif
1144  {
1145  snprintf(state.filename, sizeof(state.filename), "%s/%s.tar",
1146  basedir, PQgetvalue(res, rownum, 0));
1147  state.tarfile = fopen(state.filename, "wb");
1148  }
1149  }
1150 
1151 #ifdef HAVE_LIBZ
1152  if (compresslevel != 0)
1153  {
1154  if (!state.ztarfile)
1155  {
1156  /* Compression is in use */
1157  pg_log_error("could not create compressed file \"%s\": %s",
1158  state.filename, get_gz_error(state.ztarfile));
1159  exit(1);
1160  }
1161  }
1162  else
1163 #endif
1164  {
1165  /* Either no zlib support, or zlib support but compresslevel = 0 */
1166  if (!state.tarfile)
1167  {
1168  pg_log_error("could not create file \"%s\": %m", state.filename);
1169  exit(1);
1170  }
1171  }
1172 
1173  ReceiveCopyData(conn, ReceiveTarCopyChunk, &state);
1174 
1175  /*
1176  * End of copy data. If requested, and this is the base tablespace, write
1177  * configuration file into the tarfile. When done, close the file (but not
1178  * stdout).
1179  *
1180  * Also, write two completely empty blocks at the end of the tar file, as
1181  * required by some tar programs.
1182  */
1183 
1184  MemSet(zerobuf, 0, sizeof(zerobuf));
1185 
1186  if (state.basetablespace && writerecoveryconf)
1187  {
1188  char header[TAR_BLOCK_SIZE];
1189 
1190  /*
1191  * If postgresql.auto.conf has not been found in the streamed data,
1192  * add recovery configuration to postgresql.auto.conf if recovery
1193  * parameters are GUCs. If the instance connected to is older than
1194  * 12, create recovery.conf with this data otherwise.
1195  */
1197  {
1198  int padding;
1199 
1200  tarCreateHeader(header,
1201  state.is_recovery_guc_supported ? "postgresql.auto.conf" : "recovery.conf",
1202  NULL,
1204  pg_file_create_mode, 04000, 02000,
1205  time(NULL));
1206 
1208 
1209  writeTarData(&state, header, sizeof(header));
1212  if (padding)
1213  writeTarData(&state, zerobuf, padding);
1214  }
1215 
1216  /*
1217  * standby.signal is supported only if recovery parameters are GUCs.
1218  */
1219  if (state.is_recovery_guc_supported)
1220  {
1221  tarCreateHeader(header, "standby.signal", NULL,
1222  0, /* zero-length file */
1223  pg_file_create_mode, 04000, 02000,
1224  time(NULL));
1225 
1226  writeTarData(&state, header, sizeof(header));
1227 
1228  /*
1229  * we don't need to pad out to a multiple of the tar block size
1230  * here, because the file is zero length, which is a multiple of
1231  * any block size.
1232  */
1233  }
1234  }
1235 
1236  /*
1237  * Normally, we emit the backup manifest as a separate file, but when
1238  * we're writing a tarfile to stdout, we don't have that option, so
1239  * include it in the one tarfile we've got.
1240  */
1241  if (strcmp(basedir, "-") == 0 && manifest)
1242  {
1243  char header[TAR_BLOCK_SIZE];
1245 
1246  initPQExpBuffer(&buf);
1247  ReceiveBackupManifestInMemory(conn, &buf);
1248  if (PQExpBufferDataBroken(buf))
1249  {
1250  pg_log_error("out of memory");
1251  exit(1);
1252  }
1253  tarCreateHeader(header, "backup_manifest", NULL, buf.len,
1254  pg_file_create_mode, 04000, 02000,
1255  time(NULL));
1256  writeTarData(&state, header, sizeof(header));
1257  writeTarData(&state, buf.data, buf.len);
1258  termPQExpBuffer(&buf);
1259  }
1260 
1261  /* 2 * TAR_BLOCK_SIZE bytes empty data at end of file */
1262  writeTarData(&state, zerobuf, sizeof(zerobuf));
1263 
1264 #ifdef HAVE_LIBZ
1265  if (state.ztarfile != NULL)
1266  {
1267  if (gzclose(state.ztarfile) != 0)
1268  {
1269  pg_log_error("could not close compressed file \"%s\": %s",
1270  state.filename, get_gz_error(state.ztarfile));
1271  exit(1);
1272  }
1273  }
1274  else
1275 #endif
1276  {
1277  if (strcmp(basedir, "-") != 0)
1278  {
1279  if (fclose(state.tarfile) != 0)
1280  {
1281  pg_log_error("could not close file \"%s\": %m",
1282  state.filename);
1283  exit(1);
1284  }
1285  }
1286  }
1287 
1288  progress_report(rownum, state.filename, true, false);
1289 
1290  /*
1291  * Do not sync the resulting tar file yet, all files are synced once at
1292  * the end.
1293  */
1294 }
bool found_postgresql_auto_conf
Definition: pg_basebackup.c:73
static PQExpBuffer recoveryconfcontents
int pg_file_create_mode
Definition: file_perm.c:19
bool is_recovery_guc_supported
Definition: pg_basebackup.c:71
char * PQgetvalue(const PGresult *res, int tup_num, int field_num)
Definition: fe-exec.c:3642
void termPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:131
#define pg_log_error(...)
Definition: logging.h:80
static void writeTarData(WriteTarState *state, char *buf, int r)
static bool writerecoveryconf
static int compresslevel
#define MemSet(start, val, len)
Definition: c.h:1008
#define MINIMUM_VERSION_FOR_RECOVERY_GUC
Definition: recovery_gen.h:21
int PQserverVersion(const PGconn *conn)
Definition: fe-connect.c:6727
static int fd(const char *x, int i)
Definition: preproc-init.c:105
static char * basedir
static void ReceiveBackupManifestInMemory(PGconn *conn, PQExpBuffer buf)
static void ReceiveCopyData(PGconn *conn, WriteDataCallback callback, void *callback_data)
#define TAR_BLOCK_SIZE
Definition: pgtar.h:17
static char * buf
Definition: pg_test_fsync.c:68
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
static size_t tarPaddingBytesRequired(size_t len)
Definition: pgtar.h:40
#define PQExpBufferDataBroken(buf)
Definition: pqexpbuffer.h:67
static void ReceiveTarCopyChunk(size_t r, char *copybuf, void *callback_data)
Definition: regguts.h:317
static bool manifest
static void header(const char *fmt,...) pg_attribute_printf(1
Definition: pg_regress.c:210
int PQgetisnull(const PGresult *res, int tup_num, int field_num)
Definition: fe-exec.c:3667
#define snprintf
Definition: port.h:216
void initPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:92
char filename[MAXPGPATH]
Definition: pg_basebackup.c:65
static void progress_report(int tablespacenum, const char *filename, bool force, bool finished)

◆ StartLogStreamer()

static void StartLogStreamer ( char *  startpos,
uint32  timeline,
char *  sysidentifier 
)
static

Definition at line 596 of file pg_basebackup.c.

References basedir, bgchild, logstreamer_param::bgconn, bgpipe, conn, create_slot, CreateReplicationSlot(), format, GetConnection(), kill_bgchild_atexit(), LogStreamerMain(), MAXPGPATH, MINIMUM_VERSION_FOR_PG_WAL, MINIMUM_VERSION_FOR_TEMP_SLOTS, pg_dir_create_mode, pg_log_error, pg_log_info, pg_malloc0(), pg_mkdir_p(), PQbackendPID(), PQserverVersion(), psprintf(), replication_slot, snprintf, logstreamer_param::startptr, logstreamer_param::sysidentifier, temp_replication_slot, logstreamer_param::timeline, verbose, WalSegSz, logstreamer_param::xlog, and XLogSegmentOffset.

Referenced by BaseBackup().

597 {
598  logstreamer_param *param;
599  uint32 hi,
600  lo;
601  char statusdir[MAXPGPATH];
602 
603  param = pg_malloc0(sizeof(logstreamer_param));
604  param->timeline = timeline;
605  param->sysidentifier = sysidentifier;
606 
607  /* Convert the starting position */
608  if (sscanf(startpos, "%X/%X", &hi, &lo) != 2)
609  {
610  pg_log_error("could not parse write-ahead log location \"%s\"",
611  startpos);
612  exit(1);
613  }
614  param->startptr = ((uint64) hi) << 32 | lo;
615  /* Round off to even segment position */
616  param->startptr -= XLogSegmentOffset(param->startptr, WalSegSz);
617 
618 #ifndef WIN32
619  /* Create our background pipe */
620  if (pipe(bgpipe) < 0)
621  {
622  pg_log_error("could not create pipe for background process: %m");
623  exit(1);
624  }
625 #endif
626 
627  /* Get a second connection */
628  param->bgconn = GetConnection();
629  if (!param->bgconn)
630  /* Error message already written in GetConnection() */
631  exit(1);
632 
633  /* In post-10 cluster, pg_xlog has been renamed to pg_wal */
634  snprintf(param->xlog, sizeof(param->xlog), "%s/%s",
635  basedir,
637  "pg_xlog" : "pg_wal");
638 
639  /* Temporary replication slots are only supported in 10 and newer */
641  temp_replication_slot = false;
642 
643  /*
644  * Create replication slot if requested
645  */
647  replication_slot = psprintf("pg_basebackup_%d", (int) PQbackendPID(param->bgconn));
649  {
650  if (!CreateReplicationSlot(param->bgconn, replication_slot, NULL,
651  temp_replication_slot, true, true, false, false))
652  exit(1);
653 
654  if (verbose)
655  {
657  pg_log_info("created temporary replication slot \"%s\"",
659  else
660  pg_log_info("created replication slot \"%s\"",
662  }
663  }
664 
665  if (format == 'p')
666  {
667  /*
668  * Create pg_wal/archive_status or pg_xlog/archive_status (and thus
669  * pg_wal or pg_xlog) depending on the target server so we can write
670  * to basedir/pg_wal or basedir/pg_xlog as the directory entry in the
671  * tar file may arrive later.
672  */
673  snprintf(statusdir, sizeof(statusdir), "%s/%s/archive_status",
674  basedir,
676  "pg_xlog" : "pg_wal");
677 
678  if (pg_mkdir_p(statusdir, pg_dir_create_mode) != 0 && errno != EEXIST)
679  {
680  pg_log_error("could not create directory \"%s\": %m", statusdir);
681  exit(1);
682  }
683  }
684 
685  /*
686  * Start a child process and tell it to start streaming. On Unix, this is
687  * a fork(). On Windows, we create a thread.
688  */
689 #ifndef WIN32
690  bgchild = fork();
691  if (bgchild == 0)
692  {
693  /* in child process */
694  exit(LogStreamerMain(param));
695  }
696  else if (bgchild < 0)
697  {
698  pg_log_error("could not create background process: %m");
699  exit(1);
700  }
701 
702  /*
703  * Else we are in the parent process and all is well.
704  */
705  atexit(kill_bgchild_atexit);
706 #else /* WIN32 */
707  bgchild = _beginthreadex(NULL, 0, (void *) LogStreamerMain, param, 0, NULL);
708  if (bgchild == 0)
709  {
710  pg_log_error("could not create background thread: %m");
711  exit(1);
712  }
713 #endif
714 }
static int bgpipe[2]
int pg_mkdir_p(char *path, int omode)
Definition: pgmkdirp.c:57
#define pg_log_error(...)
Definition: logging.h:80
char * psprintf(const char *fmt,...)
Definition: psprintf.c:46
static bool create_slot
int PQserverVersion(const PGconn *conn)
Definition: fe-connect.c:6727
static char * basedir
PGconn * GetConnection(UserMapping *user, bool will_prep_stmt, PgFdwConnState **state)
Definition: connection.c:125
void * pg_malloc0(size_t size)
Definition: fe_memutils.c:53
PGconn * conn
Definition: streamutil.c:54
#define MAXPGPATH
#define MINIMUM_VERSION_FOR_PG_WAL
unsigned int uint32
Definition: c.h:441
XLogRecPtr startptr
static int verbose
int pg_dir_create_mode
Definition: file_perm.c:18
static bool temp_replication_slot
int PQbackendPID(const PGconn *conn)
Definition: fe-connect.c:6771
#define XLogSegmentOffset(xlogptr, wal_segsz_bytes)
static void kill_bgchild_atexit(void)
static XLogRecPtr startpos
static void CreateReplicationSlot(CreateReplicationSlotCmd *cmd)
Definition: walsender.c:924
uint32 WalSegSz
Definition: streamutil.c:34
static pid_t bgchild
static char format
static char * replication_slot
static int LogStreamerMain(logstreamer_param *param)
#define snprintf
Definition: port.h:216
#define MINIMUM_VERSION_FOR_TEMP_SLOTS
#define pg_log_info(...)
Definition: logging.h:88
char xlog[MAXPGPATH]

◆ tablespace_list_append()

static void tablespace_list_append ( const char *  arg)
static

Definition at line 289 of file pg_basebackup.c.

References canonicalize_path(), errmsg(), TablespaceList::head, is_absolute_path, MAXPGPATH, TablespaceListCell::new_dir, TablespaceListCell::next, TablespaceListCell::old_dir, pg_log_error, pg_malloc0(), strerror, and TablespaceList::tail.

Referenced by main().

290 {
292  char *dst;
293  char *dst_ptr;
294  const char *arg_ptr;
295 
296  dst_ptr = dst = cell->old_dir;
297  for (arg_ptr = arg; *arg_ptr; arg_ptr++)
298  {
299  if (dst_ptr - dst >= MAXPGPATH)
300  {
301  pg_log_error("directory name too long");
302  exit(1);
303  }
304 
305  if (*arg_ptr == '\\' && *(arg_ptr + 1) == '=')
306  ; /* skip backslash escaping = */
307  else if (*arg_ptr == '=' && (arg_ptr == arg || *(arg_ptr - 1) != '\\'))
308  {
309  if (*cell->new_dir)
310  {
311  pg_log_error("multiple \"=\" signs in tablespace mapping");
312  exit(1);
313  }
314  else
315  dst = dst_ptr = cell->new_dir;
316  }
317  else
318  *dst_ptr++ = *arg_ptr;
319  }
320 
321  if (!*cell->old_dir || !*cell->new_dir)
322  {
323  pg_log_error("invalid tablespace mapping format \"%s\", must be \"OLDDIR=NEWDIR\"", arg);
324  exit(1);
325  }
326 
327  /*
328  * This check isn't absolutely necessary. But all tablespaces are created
329  * with absolute directories, so specifying a non-absolute path here would
330  * just never match, possibly confusing users. It's also good to be
331  * consistent with the new_dir check.
332  */
333  if (!is_absolute_path(cell->old_dir))
334  {
335  pg_log_error("old directory is not an absolute path in tablespace mapping: %s",
336  cell->old_dir);
337  exit(1);
338  }
339 
340  if (!is_absolute_path(cell->new_dir))
341  {
342  pg_log_error("new directory is not an absolute path in tablespace mapping: %s",
343  cell->new_dir);
344  exit(1);
345  }
346 
347  /*
348  * Comparisons done with these values should involve similarly
349  * canonicalized path values. This is particularly sensitive on Windows
350  * where path values may not necessarily use Unix slashes.
351  */
352  canonicalize_path(cell->old_dir);
353  canonicalize_path(cell->new_dir);
354 
355  if (tablespace_dirs.tail)
356  tablespace_dirs.tail->next = cell;
357  else
358  tablespace_dirs.head = cell;
359  tablespace_dirs.tail = cell;
360 }
static TablespaceList tablespace_dirs
#define pg_log_error(...)
Definition: logging.h:80
char old_dir[MAXPGPATH]
Definition: pg_basebackup.c:52
void canonicalize_path(char *path)
Definition: path.c:254
char new_dir[MAXPGPATH]
Definition: pg_basebackup.c:53
void * pg_malloc0(size_t size)
Definition: fe_memutils.c:53
#define MAXPGPATH
#define is_absolute_path(filename)
Definition: port.h:86
struct TablespaceListCell * next
Definition: pg_basebackup.c:51
TablespaceListCell * tail
Definition: pg_basebackup.c:59
TablespaceListCell * head
Definition: pg_basebackup.c:58
void * arg

◆ usage()

static void usage ( void  )
static

Definition at line 379 of file pg_basebackup.c.

References _, printf, and progname.

Referenced by main().

380 {
381  printf(_("%s takes a base backup of a running PostgreSQL server.\n\n"),
382  progname);
383  printf(_("Usage:\n"));
384  printf(_(" %s [OPTION]...\n"), progname);
385  printf(_("\nOptions controlling the output:\n"));
386  printf(_(" -D, --pgdata=DIRECTORY receive base backup into directory\n"));
387  printf(_(" -F, --format=p|t output format (plain (default), tar)\n"));
388  printf(_(" -r, --max-rate=RATE maximum transfer rate to transfer data directory\n"
389  " (in kB/s, or use suffix \"k\" or \"M\")\n"));
390  printf(_(" -R, --write-recovery-conf\n"
391  " write configuration for replication\n"));
392  printf(_(" -T, --tablespace-mapping=OLDDIR=NEWDIR\n"
393  " relocate tablespace in OLDDIR to NEWDIR\n"));
394  printf(_(" --waldir=WALDIR location for the write-ahead log directory\n"));
395  printf(_(" -X, --wal-method=none|fetch|stream\n"
396  " include required WAL files with specified method\n"));
397  printf(_(" -z, --gzip compress tar output\n"));
398  printf(_(" -Z, --compress=0-9 compress tar output with given compression level\n"));
399  printf(_("\nGeneral options:\n"));
400  printf(_(" -c, --checkpoint=fast|spread\n"
401  " set fast or spread checkpointing\n"));
402  printf(_(" -C, --create-slot create replication slot\n"));
403  printf(_(" -l, --label=LABEL set backup label\n"));
404  printf(_(" -n, --no-clean do not clean up after errors\n"));
405  printf(_(" -N, --no-sync do not wait for changes to be written safely to disk\n"));
406  printf(_(" -P, --progress show progress information\n"));
407  printf(_(" -S, --slot=SLOTNAME replication slot to use\n"));
408  printf(_(" -v, --verbose output verbose messages\n"));
409  printf(_(" -V, --version output version information, then exit\n"));
410  printf(_(" --manifest-checksums=SHA{224,256,384,512}|CRC32C|NONE\n"
411  " use algorithm for manifest checksums\n"));
412  printf(_(" --manifest-force-encode\n"
413  " hex encode all file names in manifest\n"));
414  printf(_(" --no-estimate-size do not estimate backup size in server side\n"));
415  printf(_(" --no-manifest suppress generation of backup manifest\n"));
416  printf(_(" --no-slot prevent creation of temporary replication slot\n"));
417  printf(_(" --no-verify-checksums\n"
418  " do not verify checksums\n"));
419  printf(_(" -?, --help show this help, then exit\n"));
420  printf(_("\nConnection options:\n"));
421  printf(_(" -d, --dbname=CONNSTR connection string\n"));
422  printf(_(" -h, --host=HOSTNAME database server host or socket directory\n"));
423  printf(_(" -p, --port=PORT database server port number\n"));
424  printf(_(" -s, --status-interval=INTERVAL\n"
425  " time between status packets sent to server (in seconds)\n"));
426  printf(_(" -U, --username=NAME connect as specified database user\n"));
427  printf(_(" -w, --no-password never prompt for password\n"));
428  printf(_(" -W, --password force password prompt (should happen automatically)\n"));
429  printf(_("\nReport bugs to <%s>.\n"), PACKAGE_BUGREPORT);
430  printf(_("%s home page: <%s>\n"), PACKAGE_NAME, PACKAGE_URL);
431 }
const char * progname
Definition: main.c:46
#define printf(...)
Definition: port.h:222
#define _(x)
Definition: elog.c:89

◆ verify_dir_is_empty_or_create()

static void verify_dir_is_empty_or_create ( char *  dirname,
bool created,
bool found 
)
static

Definition at line 722 of file pg_basebackup.c.

References pg_check_dir(), pg_dir_create_mode, pg_log_error, and pg_mkdir_p().

Referenced by BaseBackup(), and main().

723 {
724  switch (pg_check_dir(dirname))
725  {
726  case 0:
727 
728  /*
729  * Does not exist, so create
730  */
731  if (pg_mkdir_p(dirname, pg_dir_create_mode) == -1)
732  {
733  pg_log_error("could not create directory \"%s\": %m", dirname);
734  exit(1);
735  }
736  if (created)
737  *created = true;
738  return;
739  case 1:
740 
741  /*
742  * Exists, empty
743  */
744  if (found)
745  *found = true;
746  return;
747  case 2:
748  case 3:
749  case 4:
750 
751  /*
752  * Exists, not empty
753  */
754  pg_log_error("directory \"%s\" exists but is not empty", dirname);
755  exit(1);
756  case -1:
757 
758  /*
759  * Access problem
760  */
761  pg_log_error("could not access directory \"%s\": %m", dirname);
762  exit(1);
763  }
764 }
int pg_mkdir_p(char *path, int omode)
Definition: pgmkdirp.c:57
#define pg_log_error(...)
Definition: logging.h:80
int pg_dir_create_mode
Definition: file_perm.c:18
int pg_check_dir(const char *dir)
Definition: pgcheckdir.c:31

◆ writeTarData()

static void writeTarData ( WriteTarState state,
char *  buf,
int  r 
)
static

Definition at line 998 of file pg_basebackup.c.

References WriteTarState::filename, pg_log_error, and WriteTarState::tarfile.

Referenced by ReceiveTarCopyChunk(), and ReceiveTarFile().

999 {
1000 #ifdef HAVE_LIBZ
1001  if (state->ztarfile != NULL)
1002  {
1003  errno = 0;
1004  if (gzwrite(state->ztarfile, buf, r) != r)
1005  {
1006  /* if write didn't set errno, assume problem is no disk space */
1007  if (errno == 0)
1008  errno = ENOSPC;
1009  pg_log_error("could not write to compressed file \"%s\": %s",
1010  state->filename, get_gz_error(state->ztarfile));
1011  exit(1);
1012  }
1013  }
1014  else
1015 #endif
1016  {
1017  errno = 0;
1018  if (fwrite(buf, r, 1, state->tarfile) != 1)
1019  {
1020  /* if write didn't set errno, assume problem is no disk space */
1021  if (errno == 0)
1022  errno = ENOSPC;
1023  pg_log_error("could not write to file \"%s\": %m",
1024  state->filename);
1025  exit(1);
1026  }
1027  }
1028 }
#define pg_log_error(...)
Definition: logging.h:80
static char * buf
Definition: pg_test_fsync.c:68
char filename[MAXPGPATH]
Definition: pg_basebackup.c:65

Variable Documentation

◆ basedir

◆ bgchild

pid_t bgchild = -1
static

Definition at line 175 of file pg_basebackup.c.

Referenced by BaseBackup(), kill_bgchild_atexit(), and StartLogStreamer().

◆ bgpipe

int bgpipe[2] = {-1, -1}
static

◆ checksum_failure

bool checksum_failure = false
static

Definition at line 135 of file pg_basebackup.c.

Referenced by BaseBackup(), cleanup_directories_atexit(), and PageIsVerifiedExtended().

◆ compresslevel

int compresslevel = 0
static

Definition at line 139 of file pg_basebackup.c.

Referenced by LogStreamerMain(), main(), and ReceiveTarFile().

◆ create_slot

bool create_slot = false
static

Definition at line 149 of file pg_basebackup.c.

Referenced by main(), and StartLogStreamer().

◆ do_sync

bool do_sync = true
static

Definition at line 143 of file pg_basebackup.c.

Referenced by BaseBackup(), and main().

◆ estimatesize

bool estimatesize = true
static

Definition at line 137 of file pg_basebackup.c.

Referenced by BaseBackup(), and main().

◆ fastcheckpoint

bool fastcheckpoint = false
static

Definition at line 141 of file pg_basebackup.c.

Referenced by BaseBackup(), and main().

◆ format

◆ found_existing_pgdata

bool found_existing_pgdata = false
static

Definition at line 158 of file pg_basebackup.c.

Referenced by cleanup_directories_atexit(), and main().

◆ found_existing_xlogdir

bool found_existing_xlogdir = false
static

Definition at line 160 of file pg_basebackup.c.

Referenced by cleanup_directories_atexit(), and main().

◆ found_tablespace_dirs

bool found_tablespace_dirs = false
static

Definition at line 162 of file pg_basebackup.c.

Referenced by BaseBackup(), and cleanup_directories_atexit().

◆ has_xlogendptr

int has_xlogendptr = 0
static

Definition at line 182 of file pg_basebackup.c.

Referenced by BaseBackup(), and reached_end_position().

◆ in_log_streamer

bool in_log_streamer = false
static

Definition at line 176 of file pg_basebackup.c.

Referenced by cleanup_directories_atexit(), and LogStreamerMain().

◆ includewal

IncludeWal includewal = STREAM_WAL
static

Definition at line 140 of file pg_basebackup.c.

Referenced by BaseBackup(), and main().

◆ label

◆ last_progress_report

pg_time_t last_progress_report = 0
static

Definition at line 145 of file pg_basebackup.c.

Referenced by progress_report().

◆ made_new_pgdata

bool made_new_pgdata = false
static

Definition at line 157 of file pg_basebackup.c.

Referenced by cleanup_directories_atexit(), and main().

◆ made_new_xlogdir

bool made_new_xlogdir = false
static

Definition at line 159 of file pg_basebackup.c.

Referenced by cleanup_directories_atexit(), and main().

◆ made_tablespace_dirs

bool made_tablespace_dirs = false
static

Definition at line 161 of file pg_basebackup.c.

Referenced by BaseBackup(), and cleanup_directories_atexit().

◆ manifest

bool manifest = true
static

Definition at line 152 of file pg_basebackup.c.

Referenced by BaseBackup(), main(), perform_base_backup(), and ReceiveTarFile().

◆ manifest_checksums

char* manifest_checksums = NULL
static

Definition at line 154 of file pg_basebackup.c.

Referenced by BaseBackup(), and main().

◆ manifest_force_encode

bool manifest_force_encode = false
static

Definition at line 153 of file pg_basebackup.c.

Referenced by BaseBackup(), and main().

◆ maxrate

int32 maxrate = 0
static

Definition at line 146 of file pg_basebackup.c.

Referenced by BaseBackup(), main(), and parse_basebackup_options().

◆ no_slot

bool no_slot = false
static

Definition at line 150 of file pg_basebackup.c.

Referenced by main().

◆ noclean

bool noclean = false
static

Definition at line 134 of file pg_basebackup.c.

Referenced by cleanup_directories_atexit(), and main().

◆ recoveryconfcontents

PQExpBuffer recoveryconfcontents = NULL
static

Definition at line 188 of file pg_basebackup.c.

◆ replication_slot

char* replication_slot = NULL
static

Definition at line 147 of file pg_basebackup.c.

Referenced by BaseBackup(), LogStreamerMain(), main(), and StartLogStreamer().

◆ showprogress

bool showprogress = false
static

Definition at line 136 of file pg_basebackup.c.

Referenced by BaseBackup(), main(), and progress_report().

◆ standby_message_timeout

int standby_message_timeout = 10 * 1000
static

Definition at line 144 of file pg_basebackup.c.

Referenced by LogStreamerMain(), and main().

◆ success

bool success = false
static

Definition at line 156 of file pg_basebackup.c.

Referenced by cleanup_directories_atexit(), and main().

◆ tablespace_dirs

TablespaceList tablespace_dirs = {NULL, NULL}
static

Definition at line 130 of file pg_basebackup.c.

◆ tablespacecount

int tablespacecount
static

Definition at line 167 of file pg_basebackup.c.

Referenced by BaseBackup(), and progress_report().

◆ temp_replication_slot

bool temp_replication_slot = true
static

Definition at line 148 of file pg_basebackup.c.

Referenced by main(), and StartLogStreamer().

◆ totaldone

uint64 totaldone
static

◆ totalsize_kb

uint64 totalsize_kb
static

Definition at line 165 of file pg_basebackup.c.

Referenced by BaseBackup(), and progress_report().

◆ verbose

int verbose = 0
static

◆ verify_checksums

bool verify_checksums = true
static

Definition at line 151 of file pg_basebackup.c.

Referenced by BaseBackup(), and main().

◆ writerecoveryconf

bool writerecoveryconf = false
static

◆ xlog_dir

char* xlog_dir = NULL
static

Definition at line 131 of file pg_basebackup.c.

Referenced by cleanup_directories_atexit(), and main().

◆ xlogendptr

XLogRecPtr xlogendptr
static

Definition at line 179 of file pg_basebackup.c.

Referenced by BaseBackup(), and reached_end_position().