PostgreSQL Source Code  git master
pg_upgrade.h File Reference
#include <unistd.h>
#include <assert.h>
#include <sys/stat.h>
#include <sys/time.h>
#include "common/relpath.h"
#include "libpq-fe.h"
Include dependency graph for pg_upgrade.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  RelInfo
 
struct  RelInfoArr
 
struct  LogicalSlotInfo
 
struct  LogicalSlotInfoArr
 
struct  FileNameMap
 
struct  DbInfo
 
struct  DbLocaleInfo
 
struct  DbInfoArr
 
struct  ControlData
 
struct  ClusterInfo
 
struct  LogOpts
 
struct  UserOpts
 
struct  LibraryInfo
 
struct  OSInfo
 

Macros

#define DEF_PGUPORT   50432
 
#define MAX_STRING   1024
 
#define QUERY_ALLOC   8192
 
#define MESSAGE_WIDTH   62
 
#define GET_MAJOR_VERSION(v)   ((v) / 100)
 
#define GLOBALS_DUMP_FILE   "pg_upgrade_dump_globals.sql"
 
#define DB_DUMP_FILE_MASK   "pg_upgrade_dump_%u.custom"
 
#define BASE_OUTPUTDIR   "pg_upgrade_output.d"
 
#define LOG_OUTPUTDIR   "log"
 
#define DUMP_OUTPUTDIR   "dump"
 
#define DB_DUMP_LOG_FILE_MASK   "pg_upgrade_dump_%u.log"
 
#define SERVER_LOG_FILE   "pg_upgrade_server.log"
 
#define UTILITY_LOG_FILE   "pg_upgrade_utility.log"
 
#define INTERNAL_LOG_FILE   "pg_upgrade_internal.log"
 
#define SERVER_START_LOG_FILE   SERVER_LOG_FILE
 
#define SERVER_STOP_LOG_FILE   SERVER_LOG_FILE
 
#define pg_mv_file   rename
 
#define PATH_SEPARATOR   '/'
 
#define PATH_QUOTE   '\''
 
#define RM_CMD   "rm -f"
 
#define RMDIR_CMD   "rm -rf"
 
#define SCRIPT_PREFIX   "./"
 
#define SCRIPT_EXT   "sh"
 
#define ECHO_QUOTE   "'"
 
#define ECHO_BLANK   ""
 
#define VISIBILITY_MAP_FROZEN_BIT_CAT_VER   201603011
 
#define MULTIXACT_FORMATCHANGE_CAT_VER   201301231
 
#define LARGE_OBJECT_SIZE_PG_CONTROL_VER   942
 
#define JSONB_FORMAT_CHANGE_CAT_VER   201409291
 
#define EXEC_PSQL_ARGS   "--echo-queries --set ON_ERROR_STOP=on --no-psqlrc --dbname=template1"
 
#define fopen_priv(path, mode)   fopen(path, mode)
 

Enumerations

enum  transferMode { TRANSFER_MODE_CLONE , TRANSFER_MODE_COPY , TRANSFER_MODE_LINK }
 
enum  eLogType {
  PG_VERBOSE , PG_STATUS , PG_REPORT_NONL , PG_REPORT ,
  PG_WARNING , PG_FATAL
}
 

Functions

void output_check_banner (bool live_check)
 
void check_and_dump_old_cluster (bool live_check)
 
void check_new_cluster (void)
 
void report_clusters_compatible (void)
 
void issue_warnings_and_set_wal_level (void)
 
void output_completion_banner (char *deletion_script_file_name)
 
void check_cluster_versions (void)
 
void check_cluster_compatibility (bool live_check)
 
void create_script_for_old_cluster_deletion (char **deletion_script_file_name)
 
void get_control_data (ClusterInfo *cluster, bool live_check)
 
void check_control_data (ControlData *oldctrl, ControlData *newctrl)
 
void disable_old_cluster (void)
 
void generate_old_dump (void)
 
bool exec_prog (const char *log_filename, const char *opt_log_file, bool report_error, bool exit_on_error, const char *fmt,...) pg_attribute_printf(5
 
bool void verify_directories (void)
 
bool pid_lock_file_exists (const char *datadir)
 
void cloneFile (const char *src, const char *dst, const char *schemaName, const char *relName)
 
void copyFile (const char *src, const char *dst, const char *schemaName, const char *relName)
 
void linkFile (const char *src, const char *dst, const char *schemaName, const char *relName)
 
void rewriteVisibilityMap (const char *fromfile, const char *tofile, const char *schemaName, const char *relName)
 
void check_file_clone (void)
 
void check_hard_link (void)
 
void get_loadable_libraries (void)
 
void check_loadable_libraries (void)
 
FileNameMapgen_db_file_maps (DbInfo *old_db, DbInfo *new_db, int *nmaps, const char *old_pgdata, const char *new_pgdata)
 
void get_db_rel_and_slot_infos (ClusterInfo *cluster, bool live_check)
 
int count_old_cluster_logical_slots (void)
 
void parseCommandLine (int argc, char *argv[])
 
void adjust_data_dir (ClusterInfo *cluster)
 
void get_sock_dir (ClusterInfo *cluster, bool live_check)
 
void transfer_all_new_tablespaces (DbInfoArr *old_db_arr, DbInfoArr *new_db_arr, char *old_pgdata, char *new_pgdata)
 
void transfer_all_new_dbs (DbInfoArr *old_db_arr, DbInfoArr *new_db_arr, char *old_pgdata, char *new_pgdata, char *old_tablespace)
 
void init_tablespaces (void)
 
PGconnconnectToServer (ClusterInfo *cluster, const char *db_name)
 
PGresultexecuteQueryOrDie (PGconn *conn, const char *fmt,...) pg_attribute_printf(2
 
PGresult char * cluster_conn_opts (ClusterInfo *cluster)
 
bool start_postmaster (ClusterInfo *cluster, bool report_and_exit_on_error)
 
void stop_postmaster (bool in_atexit)
 
uint32 get_major_server_version (ClusterInfo *cluster)
 
void check_pghost_envvar (void)
 
char * quote_identifier (const char *s)
 
int get_user_info (char **user_name_p)
 
void check_ok (void)
 
void report_status (eLogType type, const char *fmt,...) pg_attribute_printf(2
 
void void pg_log (eLogType type, const char *fmt,...) pg_attribute_printf(2
 
void void void pg_fatal (const char *fmt,...) pg_attribute_printf(1
 
void void void pg_attribute_noreturn ()
 
void end_progress_output (void)
 
void cleanup_output_dirs (void)
 
void prep_status (const char *fmt,...) pg_attribute_printf(1
 
void void prep_status_progress (const char *fmt,...) pg_attribute_printf(1
 
void void unsigned int str2uint (const char *str)
 
bool check_for_data_types_usage (ClusterInfo *cluster, const char *base_query, const char *output_path)
 
bool check_for_data_type_usage (ClusterInfo *cluster, const char *type_name, const char *output_path)
 
void old_9_3_check_for_line_data_type_usage (ClusterInfo *cluster)
 
void old_9_6_check_for_unknown_data_type_usage (ClusterInfo *cluster)
 
void old_9_6_invalidate_hash_indexes (ClusterInfo *cluster, bool check_mode)
 
void old_11_check_for_sql_identifier_data_type_usage (ClusterInfo *cluster)
 
void report_extension_updates (ClusterInfo *cluster)
 
void parallel_exec_prog (const char *log_file, const char *opt_log_file, const char *fmt,...) pg_attribute_printf(3
 
void void parallel_transfer_all_new_dbs (DbInfoArr *old_db_arr, DbInfoArr *new_db_arr, char *old_pgdata, char *new_pgdata, char *old_tablespace)
 
bool reap_child (bool wait_for_child)
 

Variables

char * output_files []
 
LogOpts log_opts
 
UserOpts user_opts
 
ClusterInfo old_cluster
 
ClusterInfo new_cluster
 
OSInfo os_info
 

Macro Definition Documentation

◆ BASE_OUTPUTDIR

#define BASE_OUTPUTDIR   "pg_upgrade_output.d"

Definition at line 39 of file pg_upgrade.h.

◆ DB_DUMP_FILE_MASK

#define DB_DUMP_FILE_MASK   "pg_upgrade_dump_%u.custom"

Definition at line 31 of file pg_upgrade.h.

◆ DB_DUMP_LOG_FILE_MASK

#define DB_DUMP_LOG_FILE_MASK   "pg_upgrade_dump_%u.log"

Definition at line 43 of file pg_upgrade.h.

◆ DEF_PGUPORT

#define DEF_PGUPORT   50432

Definition at line 20 of file pg_upgrade.h.

◆ DUMP_OUTPUTDIR

#define DUMP_OUTPUTDIR   "dump"

Definition at line 41 of file pg_upgrade.h.

◆ ECHO_BLANK

#define ECHO_BLANK   ""

Definition at line 89 of file pg_upgrade.h.

◆ ECHO_QUOTE

#define ECHO_QUOTE   "'"

Definition at line 88 of file pg_upgrade.h.

◆ EXEC_PSQL_ARGS

#define EXEC_PSQL_ARGS   "--echo-queries --set ON_ERROR_STOP=on --no-psqlrc --dbname=template1"

Definition at line 388 of file pg_upgrade.h.

◆ fopen_priv

#define fopen_priv (   path,
  mode 
)    fopen(path, mode)

Definition at line 410 of file pg_upgrade.h.

◆ GET_MAJOR_VERSION

#define GET_MAJOR_VERSION (   v)    ((v) / 100)

Definition at line 27 of file pg_upgrade.h.

◆ GLOBALS_DUMP_FILE

#define GLOBALS_DUMP_FILE   "pg_upgrade_dump_globals.sql"

Definition at line 30 of file pg_upgrade.h.

◆ INTERNAL_LOG_FILE

#define INTERNAL_LOG_FILE   "pg_upgrade_internal.log"

Definition at line 46 of file pg_upgrade.h.

◆ JSONB_FORMAT_CHANGE_CAT_VER

#define JSONB_FORMAT_CHANGE_CAT_VER   201409291

Definition at line 127 of file pg_upgrade.h.

◆ LARGE_OBJECT_SIZE_PG_CONTROL_VER

#define LARGE_OBJECT_SIZE_PG_CONTROL_VER   942

Definition at line 122 of file pg_upgrade.h.

◆ LOG_OUTPUTDIR

#define LOG_OUTPUTDIR   "log"

Definition at line 40 of file pg_upgrade.h.

◆ MAX_STRING

#define MAX_STRING   1024

Definition at line 22 of file pg_upgrade.h.

◆ MESSAGE_WIDTH

#define MESSAGE_WIDTH   62

Definition at line 25 of file pg_upgrade.h.

◆ MULTIXACT_FORMATCHANGE_CAT_VER

#define MULTIXACT_FORMATCHANGE_CAT_VER   201301231

Definition at line 116 of file pg_upgrade.h.

◆ PATH_QUOTE

#define PATH_QUOTE   '\''

Definition at line 83 of file pg_upgrade.h.

◆ PATH_SEPARATOR

#define PATH_SEPARATOR   '/'

Definition at line 82 of file pg_upgrade.h.

◆ pg_mv_file

#define pg_mv_file   rename

Definition at line 81 of file pg_upgrade.h.

◆ QUERY_ALLOC

#define QUERY_ALLOC   8192

Definition at line 23 of file pg_upgrade.h.

◆ RM_CMD

#define RM_CMD   "rm -f"

Definition at line 84 of file pg_upgrade.h.

◆ RMDIR_CMD

#define RMDIR_CMD   "rm -rf"

Definition at line 85 of file pg_upgrade.h.

◆ SCRIPT_EXT

#define SCRIPT_EXT   "sh"

Definition at line 87 of file pg_upgrade.h.

◆ SCRIPT_PREFIX

#define SCRIPT_PREFIX   "./"

Definition at line 86 of file pg_upgrade.h.

◆ SERVER_LOG_FILE

#define SERVER_LOG_FILE   "pg_upgrade_server.log"

Definition at line 44 of file pg_upgrade.h.

◆ SERVER_START_LOG_FILE

#define SERVER_START_LOG_FILE   SERVER_LOG_FILE

Definition at line 67 of file pg_upgrade.h.

◆ SERVER_STOP_LOG_FILE

#define SERVER_STOP_LOG_FILE   SERVER_LOG_FILE

Definition at line 68 of file pg_upgrade.h.

◆ UTILITY_LOG_FILE

#define UTILITY_LOG_FILE   "pg_upgrade_utility.log"

Definition at line 45 of file pg_upgrade.h.

◆ VISIBILITY_MAP_FROZEN_BIT_CAT_VER

#define VISIBILITY_MAP_FROZEN_BIT_CAT_VER   201603011

Definition at line 108 of file pg_upgrade.h.

Enumeration Type Documentation

◆ eLogType

enum eLogType
Enumerator
PG_VERBOSE 
PG_STATUS 
PG_REPORT_NONL 
PG_REPORT 
PG_WARNING 
PG_FATAL 

Definition at line 262 of file pg_upgrade.h.

263 {
264  PG_VERBOSE,
265  PG_STATUS, /* these messages do not get a newline added */
266  PG_REPORT_NONL, /* these too */
267  PG_REPORT,
268  PG_WARNING,
269  PG_FATAL,
270 } eLogType;
eLogType
Definition: pg_upgrade.h:263
@ PG_FATAL
Definition: pg_upgrade.h:269
@ PG_STATUS
Definition: pg_upgrade.h:265
@ PG_WARNING
Definition: pg_upgrade.h:268
@ PG_REPORT_NONL
Definition: pg_upgrade.h:266
@ PG_VERBOSE
Definition: pg_upgrade.h:264
@ PG_REPORT
Definition: pg_upgrade.h:267

◆ transferMode

Enumerator
TRANSFER_MODE_CLONE 
TRANSFER_MODE_COPY 
TRANSFER_MODE_LINK 

Definition at line 252 of file pg_upgrade.h.

253 {
257 } transferMode;
transferMode
Definition: pg_upgrade.h:253
@ TRANSFER_MODE_COPY
Definition: pg_upgrade.h:255
@ TRANSFER_MODE_LINK
Definition: pg_upgrade.h:256
@ TRANSFER_MODE_CLONE
Definition: pg_upgrade.h:254

Function Documentation

◆ adjust_data_dir()

void adjust_data_dir ( ClusterInfo cluster)

Definition at line 399 of file option.c.

400 {
401  char filename[MAXPGPATH];
402  char cmd[MAXPGPATH],
403  cmd_output[MAX_STRING];
404  FILE *fp,
405  *output;
406  int rc;
407 
408  /* Initially assume config dir and data dir are the same */
409  cluster->pgconfig = pg_strdup(cluster->pgdata);
410 
411  /* If there is no postgresql.conf, it can't be a config-only dir */
412  snprintf(filename, sizeof(filename), "%s/postgresql.conf", cluster->pgconfig);
413  if ((fp = fopen(filename, "r")) == NULL)
414  return;
415  fclose(fp);
416 
417  /* If PG_VERSION exists, it can't be a config-only dir */
418  snprintf(filename, sizeof(filename), "%s/PG_VERSION", cluster->pgconfig);
419  if ((fp = fopen(filename, "r")) != NULL)
420  {
421  fclose(fp);
422  return;
423  }
424 
425  /* Must be a configuration directory, so find the real data directory. */
426 
427  if (cluster == &old_cluster)
428  prep_status("Finding the real data directory for the source cluster");
429  else
430  prep_status("Finding the real data directory for the target cluster");
431 
432  /*
433  * We don't have a data directory yet, so we can't check the PG version,
434  * so this might fail --- only works for PG 9.2+. If this fails,
435  * pg_upgrade will fail anyway because the data files will not be found.
436  */
437  snprintf(cmd, sizeof(cmd), "\"%s/postgres\" -D \"%s\" -C data_directory",
438  cluster->bindir, cluster->pgconfig);
439  fflush(NULL);
440 
441  if ((output = popen(cmd, "r")) == NULL ||
442  fgets(cmd_output, sizeof(cmd_output), output) == NULL)
443  pg_fatal("could not get data directory using %s: %s",
444  cmd, strerror(errno));
445 
446  rc = pclose(output);
447  if (rc != 0)
448  pg_fatal("could not get data directory using %s: %s",
449  cmd, wait_result_to_str(rc));
450 
451  /* strip trailing newline and carriage return */
452  (void) pg_strip_crlf(cmd_output);
453 
454  cluster->pgdata = pg_strdup(cmd_output);
455 
456  check_ok();
457 }
void cluster(ParseState *pstate, ClusterStmt *stmt, bool isTopLevel)
Definition: cluster.c:110
char * pg_strdup(const char *in)
Definition: fe_memutils.c:85
FILE * output
static void check_ok(void)
Definition: initdb.c:2036
static void const char fflush(stdout)
#define pg_fatal(...)
#define MAXPGPATH
static char * filename
Definition: pg_dumpall.c:121
ClusterInfo old_cluster
Definition: pg_upgrade.c:64
#define MAX_STRING
Definition: pg_upgrade.h:22
void prep_status(const char *fmt,...) pg_attribute_printf(1
#define strerror
Definition: port.h:251
#define snprintf
Definition: port.h:238
int pg_strip_crlf(char *str)
Definition: string.c:155
char * wait_result_to_str(int exitstatus)
Definition: wait_error.c:33

References check_ok(), cluster(), fflush(), filename, MAX_STRING, MAXPGPATH, old_cluster, output, pg_fatal, pg_strdup(), pg_strip_crlf(), prep_status(), snprintf, strerror, and wait_result_to_str().

◆ check_and_dump_old_cluster()

void check_and_dump_old_cluster ( bool  live_check)

Definition at line 87 of file check.c.

88 {
89  /* -- OLD -- */
90 
91  if (!live_check)
93 
94  /*
95  * Extract a list of databases, tables, and logical replication slots from
96  * the old cluster.
97  */
99 
101 
103 
104 
105  /*
106  * Check for various failure cases
107  */
114 
115  /*
116  * Logical replication slots can be migrated since PG17. See comments atop
117  * get_old_cluster_logical_slot_infos().
118  */
121 
122  /*
123  * PG 16 increased the size of the 'aclitem' type, which breaks the
124  * on-disk format for existing data.
125  */
128 
129  /*
130  * PG 12 removed types abstime, reltime, tinterval.
131  */
133  {
136  check_for_removed_data_type_usage(&old_cluster, "12", "tinterval");
137  }
138 
139  /*
140  * PG 14 changed the function signature of encoding conversion functions.
141  * Conversions from older versions cannot be upgraded automatically
142  * because the user-defined functions used by the encoding conversions
143  * need to be changed to match the new signature.
144  */
147 
148  /*
149  * Pre-PG 14 allowed user defined postfix operators, which are not
150  * supported anymore. Verify there are none, iff applicable.
151  */
154 
155  /*
156  * PG 14 changed polymorphic functions from anyarray to
157  * anycompatiblearray.
158  */
161 
162  /*
163  * Pre-PG 12 allowed tables to be declared WITH OIDS, which is not
164  * supported anymore. Verify there are none, iff applicable.
165  */
168 
169  /*
170  * PG 12 changed the 'sql_identifier' type storage to be based on name,
171  * not varchar, which breaks on-disk format for existing data. So we need
172  * to prevent upgrade when used in user objects (tables, indexes, ...).
173  */
176 
177  /*
178  * Pre-PG 10 allowed tables with 'unknown' type columns and non WAL logged
179  * hash indexes
180  */
182  {
184  if (user_opts.check)
186  }
187 
188  /* 9.5 and below should not have roles starting with pg_ */
191 
195 
196  /* Pre-PG 9.4 had a different 'line' data type internal format */
199 
200  /*
201  * While not a check option, we do this now because this is the only time
202  * the old server is running.
203  */
204  if (!user_opts.check)
206 
207  if (!live_check)
208  stop_postmaster(false);
209 }
static void check_for_tables_with_oids(ClusterInfo *cluster)
Definition: check.c:1045
static void check_for_pg_role_prefix(ClusterInfo *cluster)
Definition: check.c:1335
static void check_for_composite_data_type_usage(ClusterInfo *cluster)
Definition: check.c:1125
static void check_for_removed_data_type_usage(ClusterInfo *cluster, const char *version, const char *datatype)
Definition: check.c:1271
static void check_old_cluster_for_valid_slots(bool live_check)
Definition: check.c:1548
static void check_is_install_user(ClusterInfo *cluster)
Definition: check.c:559
static void check_for_isn_and_int8_passing_mismatch(ClusterInfo *cluster)
Definition: check.c:737
static void check_for_user_defined_postfix_ops(ClusterInfo *cluster)
Definition: check.c:819
static void check_for_prepared_transactions(ClusterInfo *cluster)
Definition: check.c:702
static void check_proper_datallowconn(ClusterInfo *cluster)
Definition: check.c:617
static void check_for_aclitem_data_type_usage(ClusterInfo *cluster)
Definition: check.c:1241
static void check_for_user_defined_encoding_conversions(ClusterInfo *cluster)
Definition: check.c:1391
static void check_for_jsonb_9_4_usage(ClusterInfo *cluster)
Definition: check.c:1305
static void check_for_incompatible_polymorphics(ClusterInfo *cluster)
Definition: check.c:918
static void check_for_reg_data_type_usage(ClusterInfo *cluster)
Definition: check.c:1186
void generate_old_dump(void)
Definition: dump.c:16
void get_loadable_libraries(void)
Definition: function.c:55
void get_db_rel_and_slot_infos(ClusterInfo *cluster, bool live_check)
Definition: info.c:279
static pid_t start_postmaster(void)
Definition: pg_ctl.c:439
void init_tablespaces(void)
Definition: tablespace.c:19
void old_11_check_for_sql_identifier_data_type_usage(ClusterInfo *cluster)
Definition: version.c:365
void old_9_3_check_for_line_data_type_usage(ClusterInfo *cluster)
Definition: version.c:180
void old_9_6_check_for_unknown_data_type_usage(ClusterInfo *cluster)
Definition: version.c:220
#define GET_MAJOR_VERSION(v)
Definition: pg_upgrade.h:27
void stop_postmaster(bool in_atexit)
Definition: server.c:347
void old_9_6_invalidate_hash_indexes(ClusterInfo *cluster, bool check_mode)
Definition: version.c:250
#define JSONB_FORMAT_CHANGE_CAT_VER
Definition: pg_upgrade.h:127
UserOpts user_opts
Definition: option.c:30
ControlData controldata
Definition: pg_upgrade.h:280
uint32 major_version
Definition: pg_upgrade.h:291
uint32 cat_ver
Definition: pg_upgrade.h:226
bool check
Definition: pg_upgrade.h:320

References ControlData::cat_ver, UserOpts::check, check_for_aclitem_data_type_usage(), check_for_composite_data_type_usage(), check_for_incompatible_polymorphics(), check_for_isn_and_int8_passing_mismatch(), check_for_jsonb_9_4_usage(), check_for_pg_role_prefix(), check_for_prepared_transactions(), check_for_reg_data_type_usage(), check_for_removed_data_type_usage(), check_for_tables_with_oids(), check_for_user_defined_encoding_conversions(), check_for_user_defined_postfix_ops(), check_is_install_user(), check_old_cluster_for_valid_slots(), check_proper_datallowconn(), ClusterInfo::controldata, generate_old_dump(), get_db_rel_and_slot_infos(), get_loadable_libraries(), GET_MAJOR_VERSION, init_tablespaces(), JSONB_FORMAT_CHANGE_CAT_VER, ClusterInfo::major_version, old_11_check_for_sql_identifier_data_type_usage(), old_9_3_check_for_line_data_type_usage(), old_9_6_check_for_unknown_data_type_usage(), old_9_6_invalidate_hash_indexes(), old_cluster, start_postmaster(), stop_postmaster(), and user_opts.

Referenced by main().

◆ check_cluster_compatibility()

void check_cluster_compatibility ( bool  live_check)

Definition at line 361 of file check.c.

362 {
363  /* get/check pg_control data of servers */
364  get_control_data(&old_cluster, live_check);
365  get_control_data(&new_cluster, false);
367 
368  if (live_check && old_cluster.port == new_cluster.port)
369  pg_fatal("When checking a live server, "
370  "the old and new port numbers must be different.");
371 }
void get_control_data(ClusterInfo *cluster, bool live_check)
Definition: controldata.c:36
void check_control_data(ControlData *oldctrl, ControlData *newctrl)
Definition: controldata.c:656
ClusterInfo new_cluster
Definition: pg_upgrade.c:65
unsigned short port
Definition: pg_upgrade.h:290

References check_control_data(), ClusterInfo::controldata, get_control_data(), new_cluster, old_cluster, pg_fatal, and ClusterInfo::port.

Referenced by main().

◆ check_cluster_versions()

void check_cluster_versions ( void  )

Definition at line 318 of file check.c.

319 {
320  prep_status("Checking cluster versions");
321 
322  /* cluster versions should already have been obtained */
325 
326  /*
327  * We allow upgrades from/to the same major version for alpha/beta
328  * upgrades
329  */
330 
332  pg_fatal("This utility can only upgrade from PostgreSQL version %s and later.",
333  "9.2");
334 
335  /* Only current PG version is supported as a target */
337  pg_fatal("This utility can only upgrade to PostgreSQL version %s.",
338  PG_MAJORVERSION);
339 
340  /*
341  * We can't allow downgrading because we use the target pg_dump, and
342  * pg_dump cannot operate on newer database versions, only current and
343  * older versions.
344  */
346  pg_fatal("This utility cannot be used to downgrade to older major PostgreSQL versions.");
347 
348  /* Ensure binaries match the designated data directories */
351  pg_fatal("Old cluster data and binary directories are from different major versions.");
354  pg_fatal("New cluster data and binary directories are from different major versions.");
355 
356  check_ok();
357 }
Assert(fmt[strlen(fmt) - 1] !='\n')
uint32 bin_version
Definition: pg_upgrade.h:293

References Assert(), ClusterInfo::bin_version, check_ok(), GET_MAJOR_VERSION, ClusterInfo::major_version, new_cluster, old_cluster, pg_fatal, and prep_status().

Referenced by main().

◆ check_control_data()

void check_control_data ( ControlData oldctrl,
ControlData newctrl 
)

Definition at line 656 of file controldata.c.

658 {
659  if (oldctrl->align == 0 || oldctrl->align != newctrl->align)
660  pg_fatal("old and new pg_controldata alignments are invalid or do not match.\n"
661  "Likely one cluster is a 32-bit install, the other 64-bit");
662 
663  if (oldctrl->blocksz == 0 || oldctrl->blocksz != newctrl->blocksz)
664  pg_fatal("old and new pg_controldata block sizes are invalid or do not match");
665 
666  if (oldctrl->largesz == 0 || oldctrl->largesz != newctrl->largesz)
667  pg_fatal("old and new pg_controldata maximum relation segment sizes are invalid or do not match");
668 
669  if (oldctrl->walsz == 0 || oldctrl->walsz != newctrl->walsz)
670  pg_fatal("old and new pg_controldata WAL block sizes are invalid or do not match");
671 
672  if (oldctrl->walseg == 0 || oldctrl->walseg != newctrl->walseg)
673  pg_fatal("old and new pg_controldata WAL segment sizes are invalid or do not match");
674 
675  if (oldctrl->ident == 0 || oldctrl->ident != newctrl->ident)
676  pg_fatal("old and new pg_controldata maximum identifier lengths are invalid or do not match");
677 
678  if (oldctrl->index == 0 || oldctrl->index != newctrl->index)
679  pg_fatal("old and new pg_controldata maximum indexed columns are invalid or do not match");
680 
681  if (oldctrl->toast == 0 || oldctrl->toast != newctrl->toast)
682  pg_fatal("old and new pg_controldata maximum TOAST chunk sizes are invalid or do not match");
683 
684  /* large_object added in 9.5, so it might not exist in the old cluster */
685  if (oldctrl->large_object != 0 &&
686  oldctrl->large_object != newctrl->large_object)
687  pg_fatal("old and new pg_controldata large-object chunk sizes are invalid or do not match");
688 
689  if (oldctrl->date_is_int != newctrl->date_is_int)
690  pg_fatal("old and new pg_controldata date/time storage types do not match");
691 
692  /*
693  * float8_pass_by_value does not need to match, but is used in
694  * check_for_isn_and_int8_passing_mismatch().
695  */
696 
697  /*
698  * We might eventually allow upgrades from checksum to no-checksum
699  * clusters.
700  */
701  if (oldctrl->data_checksum_version == 0 &&
702  newctrl->data_checksum_version != 0)
703  pg_fatal("old cluster does not use data checksums but the new one does");
704  else if (oldctrl->data_checksum_version != 0 &&
705  newctrl->data_checksum_version == 0)
706  pg_fatal("old cluster uses data checksums but the new one does not");
707  else if (oldctrl->data_checksum_version != newctrl->data_checksum_version)
708  pg_fatal("old and new cluster pg_controldata checksum versions do not match");
709 }
uint32 data_checksum_version
Definition: pg_upgrade.h:246
uint32 toast
Definition: pg_upgrade.h:242
uint32 index
Definition: pg_upgrade.h:241
uint32 walseg
Definition: pg_upgrade.h:239
uint32 blocksz
Definition: pg_upgrade.h:236
uint32 walsz
Definition: pg_upgrade.h:238
uint32 ident
Definition: pg_upgrade.h:240
bool date_is_int
Definition: pg_upgrade.h:244
uint32 large_object
Definition: pg_upgrade.h:243
uint32 align
Definition: pg_upgrade.h:235
uint32 largesz
Definition: pg_upgrade.h:237

References ControlData::align, ControlData::blocksz, ControlData::data_checksum_version, ControlData::date_is_int, ControlData::ident, ControlData::index, ControlData::large_object, ControlData::largesz, pg_fatal, ControlData::toast, ControlData::walseg, and ControlData::walsz.

Referenced by check_cluster_compatibility().

◆ check_file_clone()

void check_file_clone ( void  )

Definition at line 320 of file file.c.

321 {
322  char existing_file[MAXPGPATH];
323  char new_link_file[MAXPGPATH];
324 
325  snprintf(existing_file, sizeof(existing_file), "%s/PG_VERSION", old_cluster.pgdata);
326  snprintf(new_link_file, sizeof(new_link_file), "%s/PG_VERSION.clonetest", new_cluster.pgdata);
327  unlink(new_link_file); /* might fail */
328 
329 #if defined(HAVE_COPYFILE) && defined(COPYFILE_CLONE_FORCE)
330  if (copyfile(existing_file, new_link_file, NULL, COPYFILE_CLONE_FORCE) < 0)
331  pg_fatal("could not clone file between old and new data directories: %s",
332  strerror(errno));
333 #elif defined(__linux__) && defined(FICLONE)
334  {
335  int src_fd;
336  int dest_fd;
337 
338  if ((src_fd = open(existing_file, O_RDONLY | PG_BINARY, 0)) < 0)
339  pg_fatal("could not open file \"%s\": %s",
340  existing_file, strerror(errno));
341 
342  if ((dest_fd = open(new_link_file, O_RDWR | O_CREAT | O_EXCL | PG_BINARY,
343  pg_file_create_mode)) < 0)
344  pg_fatal("could not create file \"%s\": %s",
345  new_link_file, strerror(errno));
346 
347  if (ioctl(dest_fd, FICLONE, src_fd) < 0)
348  pg_fatal("could not clone file between old and new data directories: %s",
349  strerror(errno));
350 
351  close(src_fd);
352  close(dest_fd);
353  }
354 #else
355  pg_fatal("file cloning not supported on this platform");
356 #endif
357 
358  unlink(new_link_file);
359 }
#define PG_BINARY
Definition: c.h:1283
int pg_file_create_mode
Definition: file_perm.c:19
#define close(a)
Definition: win32.h:12
char * pgdata
Definition: pg_upgrade.h:283

References close, MAXPGPATH, new_cluster, old_cluster, PG_BINARY, pg_fatal, pg_file_create_mode, ClusterInfo::pgdata, snprintf, and strerror.

Referenced by check_new_cluster().

◆ check_for_data_type_usage()

bool check_for_data_type_usage ( ClusterInfo cluster,
const char *  type_name,
const char *  output_path 
)

Definition at line 153 of file version.c.

156 {
157  bool found;
158  char *base_query;
159 
160  base_query = psprintf("SELECT '%s'::pg_catalog.regtype AS oid",
161  type_name);
162 
163  found = check_for_data_types_usage(cluster, base_query, output_path);
164 
165  free(base_query);
166 
167  return found;
168 }
bool check_for_data_types_usage(ClusterInfo *cluster, const char *base_query, const char *output_path)
Definition: version.c:31
#define free(a)
Definition: header.h:65
char * psprintf(const char *fmt,...)
Definition: psprintf.c:46

References check_for_data_types_usage(), cluster(), free, and psprintf().

Referenced by check_for_aclitem_data_type_usage(), check_for_jsonb_9_4_usage(), check_for_removed_data_type_usage(), old_11_check_for_sql_identifier_data_type_usage(), old_9_3_check_for_line_data_type_usage(), and old_9_6_check_for_unknown_data_type_usage().

◆ check_for_data_types_usage()

bool check_for_data_types_usage ( ClusterInfo cluster,
const char *  base_query,
const char *  output_path 
)

Definition at line 31 of file version.c.

34 {
35  bool found = false;
36  FILE *script = NULL;
37  int dbnum;
38 
39  for (dbnum = 0; dbnum < cluster->dbarr.ndbs; dbnum++)
40  {
41  DbInfo *active_db = &cluster->dbarr.dbs[dbnum];
42  PGconn *conn = connectToServer(cluster, active_db->db_name);
43  PQExpBufferData querybuf;
44  PGresult *res;
45  bool db_used = false;
46  int ntups;
47  int rowno;
48  int i_nspname,
49  i_relname,
50  i_attname;
51 
52  /*
53  * The type(s) of interest might be wrapped in a domain, array,
54  * composite, or range, and these container types can be nested (to
55  * varying extents depending on server version, but that's not of
56  * concern here). To handle all these cases we need a recursive CTE.
57  */
58  initPQExpBuffer(&querybuf);
59  appendPQExpBuffer(&querybuf,
60  "WITH RECURSIVE oids AS ( "
61  /* start with the type(s) returned by base_query */
62  " %s "
63  " UNION ALL "
64  " SELECT * FROM ( "
65  /* inner WITH because we can only reference the CTE once */
66  " WITH x AS (SELECT oid FROM oids) "
67  /* domains on any type selected so far */
68  " SELECT t.oid FROM pg_catalog.pg_type t, x WHERE typbasetype = x.oid AND typtype = 'd' "
69  " UNION ALL "
70  /* arrays over any type selected so far */
71  " SELECT t.oid FROM pg_catalog.pg_type t, x WHERE typelem = x.oid AND typtype = 'b' "
72  " UNION ALL "
73  /* composite types containing any type selected so far */
74  " SELECT t.oid FROM pg_catalog.pg_type t, pg_catalog.pg_class c, pg_catalog.pg_attribute a, x "
75  " WHERE t.typtype = 'c' AND "
76  " t.oid = c.reltype AND "
77  " c.oid = a.attrelid AND "
78  " NOT a.attisdropped AND "
79  " a.atttypid = x.oid "
80  " UNION ALL "
81  /* ranges containing any type selected so far */
82  " SELECT t.oid FROM pg_catalog.pg_type t, pg_catalog.pg_range r, x "
83  " WHERE t.typtype = 'r' AND r.rngtypid = t.oid AND r.rngsubtype = x.oid"
84  " ) foo "
85  ") "
86  /* now look for stored columns of any such type */
87  "SELECT n.nspname, c.relname, a.attname "
88  "FROM pg_catalog.pg_class c, "
89  " pg_catalog.pg_namespace n, "
90  " pg_catalog.pg_attribute a "
91  "WHERE c.oid = a.attrelid AND "
92  " NOT a.attisdropped AND "
93  " a.atttypid IN (SELECT oid FROM oids) AND "
94  " c.relkind IN ("
95  CppAsString2(RELKIND_RELATION) ", "
96  CppAsString2(RELKIND_MATVIEW) ", "
97  CppAsString2(RELKIND_INDEX) ") AND "
98  " c.relnamespace = n.oid AND "
99  /* exclude possible orphaned temp tables */
100  " n.nspname !~ '^pg_temp_' AND "
101  " n.nspname !~ '^pg_toast_temp_' AND "
102  /* exclude system catalogs, too */
103  " n.nspname NOT IN ('pg_catalog', 'information_schema')",
104  base_query);
105 
106  res = executeQueryOrDie(conn, "%s", querybuf.data);
107 
108  ntups = PQntuples(res);
109  i_nspname = PQfnumber(res, "nspname");
110  i_relname = PQfnumber(res, "relname");
111  i_attname = PQfnumber(res, "attname");
112  for (rowno = 0; rowno < ntups; rowno++)
113  {
114  found = true;
115  if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL)
116  pg_fatal("could not open file \"%s\": %s", output_path,
117  strerror(errno));
118  if (!db_used)
119  {
120  fprintf(script, "In database: %s\n", active_db->db_name);
121  db_used = true;
122  }
123  fprintf(script, " %s.%s.%s\n",
124  PQgetvalue(res, rowno, i_nspname),
125  PQgetvalue(res, rowno, i_relname),
126  PQgetvalue(res, rowno, i_attname));
127  }
128 
129  PQclear(res);
130 
131  termPQExpBuffer(&querybuf);
132 
133  PQfinish(conn);
134  }
135 
136  if (script)
137  fclose(script);
138 
139  return found;
140 }
#define CppAsString2(x)
Definition: c.h:316
void PQfinish(PGconn *conn)
Definition: fe-connect.c:4602
int PQntuples(const PGresult *res)
Definition: fe-exec.c:3403
char * PQgetvalue(const PGresult *res, int tup_num, int field_num)
Definition: fe-exec.c:3798
int PQfnumber(const PGresult *res, const char *field_name)
Definition: fe-exec.c:3511
#define fopen_priv(path, mode)
Definition: pg_upgrade.h:410
PGconn * connectToServer(ClusterInfo *cluster, const char *db_name)
Definition: server.c:28
PGresult * executeQueryOrDie(PGconn *conn, const char *fmt,...) pg_attribute_printf(2
#define fprintf
Definition: port.h:242
void initPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:90
void appendPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:265
void termPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:129
PGconn * conn
Definition: streamutil.c:54
char * db_name
Definition: pg_upgrade.h:193

References appendPQExpBuffer(), cluster(), conn, connectToServer(), CppAsString2, PQExpBufferData::data, DbInfo::db_name, executeQueryOrDie(), fopen_priv, fprintf, initPQExpBuffer(), pg_fatal, PQclear(), PQfinish(), PQfnumber(), PQgetvalue(), PQntuples(), res, strerror, and termPQExpBuffer().

Referenced by check_for_composite_data_type_usage(), check_for_data_type_usage(), and check_for_reg_data_type_usage().

◆ check_hard_link()

void check_hard_link ( void  )

Definition at line 362 of file file.c.

363 {
364  char existing_file[MAXPGPATH];
365  char new_link_file[MAXPGPATH];
366 
367  snprintf(existing_file, sizeof(existing_file), "%s/PG_VERSION", old_cluster.pgdata);
368  snprintf(new_link_file, sizeof(new_link_file), "%s/PG_VERSION.linktest", new_cluster.pgdata);
369  unlink(new_link_file); /* might fail */
370 
371  if (link(existing_file, new_link_file) < 0)
372  pg_fatal("could not create hard link between old and new data directories: %s\n"
373  "In link mode the old and new data directories must be on the same file system.",
374  strerror(errno));
375 
376  unlink(new_link_file);
377 }

References link(), MAXPGPATH, new_cluster, old_cluster, pg_fatal, ClusterInfo::pgdata, snprintf, and strerror.

Referenced by check_new_cluster().

◆ check_loadable_libraries()

void check_loadable_libraries ( void  )

Definition at line 146 of file function.c.

147 {
148  PGconn *conn = connectToServer(&new_cluster, "template1");
149  int libnum;
150  int was_load_failure = false;
151  FILE *script = NULL;
152  char output_path[MAXPGPATH];
153 
154  prep_status("Checking for presence of required libraries");
155 
156  snprintf(output_path, sizeof(output_path), "%s/%s",
157  log_opts.basedir, "loadable_libraries.txt");
158 
159  /*
160  * Now we want to sort the library names into order. This avoids multiple
161  * probes of the same library, and ensures that libraries are probed in a
162  * consistent order, which is important for reproducible behavior if one
163  * library depends on another.
164  */
167 
168  for (libnum = 0; libnum < os_info.num_libraries; libnum++)
169  {
170  char *lib = os_info.libraries[libnum].name;
171  int llen = strlen(lib);
172  char cmd[7 + 2 * MAXPGPATH + 1];
173  PGresult *res;
174 
175  /* Did the library name change? Probe it. */
176  if (libnum == 0 || strcmp(lib, os_info.libraries[libnum - 1].name) != 0)
177  {
178  strcpy(cmd, "LOAD '");
179  PQescapeStringConn(conn, cmd + strlen(cmd), lib, llen, NULL);
180  strcat(cmd, "'");
181 
182  res = PQexec(conn, cmd);
183 
185  {
186  was_load_failure = true;
187 
188  if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL)
189  pg_fatal("could not open file \"%s\": %s",
190  output_path, strerror(errno));
191  fprintf(script, _("could not load library \"%s\": %s"),
192  lib,
194  }
195  else
196  was_load_failure = false;
197 
198  PQclear(res);
199  }
200 
201  if (was_load_failure)
202  fprintf(script, _("In database: %s\n"),
204  }
205 
206  PQfinish(conn);
207 
208  if (script)
209  {
210  fclose(script);
211  pg_log(PG_REPORT, "fatal");
212  pg_fatal("Your installation references loadable libraries that are missing from the\n"
213  "new installation. You can add these libraries to the new installation,\n"
214  "or remove the functions using them from the old installation. A list of\n"
215  "problem libraries is in the file:\n"
216  " %s", output_path);
217  }
218  else
219  check_ok();
220 }
#define _(x)
Definition: elog.c:91
char * PQerrorMessage(const PGconn *conn)
Definition: fe-connect.c:7248
size_t PQescapeStringConn(PGconn *conn, char *to, const char *from, size_t length, int *error)
Definition: fe-exec.c:4067
ExecStatusType PQresultStatus(const PGresult *res)
Definition: fe-exec.c:3333
PGresult * PQexec(PGconn *conn, const char *query)
Definition: fe-exec.c:2228
static int library_name_compare(const void *p1, const void *p2)
Definition: function.c:28
@ PGRES_COMMAND_OK
Definition: libpq-fe.h:97
OSInfo os_info
Definition: pg_upgrade.c:66
void void pg_log(eLogType type, const char *fmt,...) pg_attribute_printf(2
LogOpts log_opts
Definition: util.c:17
#define qsort(a, b, c, d)
Definition: port.h:445
DbInfoArr dbarr
Definition: pg_upgrade.h:282
DbInfo * dbs
Definition: pg_upgrade.h:214
char * name
Definition: pg_upgrade.h:331
char * basedir
Definition: pg_upgrade.h:308
LibraryInfo * libraries
Definition: pg_upgrade.h:345
int num_libraries
Definition: pg_upgrade.h:346

References _, LogOpts::basedir, check_ok(), conn, connectToServer(), DbInfo::db_name, ClusterInfo::dbarr, LibraryInfo::dbnum, DbInfoArr::dbs, fopen_priv, fprintf, OSInfo::libraries, library_name_compare(), log_opts, MAXPGPATH, LibraryInfo::name, new_cluster, OSInfo::num_libraries, old_cluster, os_info, pg_fatal, pg_log(), PG_REPORT, PGRES_COMMAND_OK, PQclear(), PQerrorMessage(), PQescapeStringConn(), PQexec(), PQfinish(), PQresultStatus(), prep_status(), qsort, res, snprintf, and strerror.

Referenced by check_new_cluster().

◆ check_new_cluster()

void check_new_cluster ( void  )

Definition at line 213 of file check.c.

214 {
216 
218 
220 
221  switch (user_opts.transfer_mode)
222  {
223  case TRANSFER_MODE_CLONE:
225  break;
226  case TRANSFER_MODE_COPY:
227  break;
228  case TRANSFER_MODE_LINK:
229  check_hard_link();
230  break;
231  }
232 
234 
236 
238 
240 }
static void check_new_cluster_logical_replication_slots(void)
Definition: check.c:1476
static void check_new_cluster_is_empty(void)
Definition: check.c:375
static void check_for_new_tablespace_dir(void)
Definition: check.c:407
void check_file_clone(void)
Definition: file.c:320
void check_hard_link(void)
Definition: file.c:362
void check_loadable_libraries(void)
Definition: function.c:146
transferMode transfer_mode
Definition: pg_upgrade.h:323

References check_file_clone(), check_for_new_tablespace_dir(), check_for_prepared_transactions(), check_hard_link(), check_is_install_user(), check_loadable_libraries(), check_new_cluster_is_empty(), check_new_cluster_logical_replication_slots(), get_db_rel_and_slot_infos(), new_cluster, UserOpts::transfer_mode, TRANSFER_MODE_CLONE, TRANSFER_MODE_COPY, TRANSFER_MODE_LINK, and user_opts.

Referenced by main().

◆ check_ok()

void check_ok ( void  )

Definition at line 284 of file util.c.

285 {
286  /* all seems well */
287  report_status(PG_REPORT, "ok");
288 }
static void void report_status(eLogType type, const char *fmt,...)
Definition: util.c:32

References PG_REPORT, and report_status().

◆ check_pghost_envvar()

void check_pghost_envvar ( void  )

Definition at line 374 of file server.c.

375 {
377  PQconninfoOption *start;
378 
379  /* Get valid libpq env vars from the PQconndefaults function */
380 
381  start = PQconndefaults();
382 
383  if (!start)
384  pg_fatal("out of memory");
385 
386  for (option = start; option->keyword != NULL; option++)
387  {
388  if (option->envvar && (strcmp(option->envvar, "PGHOST") == 0 ||
389  strcmp(option->envvar, "PGHOSTADDR") == 0))
390  {
391  const char *value = getenv(option->envvar);
392 
393  if (value && strlen(value) > 0 &&
394  /* check for 'local' host values */
395  (strcmp(value, "localhost") != 0 && strcmp(value, "127.0.0.1") != 0 &&
396  strcmp(value, "::1") != 0 && !is_unixsock_path(value)))
397  pg_fatal("libpq environment variable %s has a non-local server value: %s",
398  option->envvar, value);
399  }
400  }
401 
402  /* Free the memory that libpq allocated on our behalf */
403  PQconninfoFree(start);
404 }
PQconninfoOption * PQconndefaults(void)
Definition: fe-connect.c:1778
void PQconninfoFree(PQconninfoOption *connOptions)
Definition: fe-connect.c:7081
static struct @148 value
static bool is_unixsock_path(const char *path)
Definition: pqcomm.h:67

References is_unixsock_path(), pg_fatal, PQconndefaults(), PQconninfoFree(), and value.

Referenced by setup().

◆ cleanup_output_dirs()

void cleanup_output_dirs ( void  )

Definition at line 63 of file util.c.

64 {
65  fclose(log_opts.internal);
66 
67  /* Remove dump and log files? */
68  if (log_opts.retain)
69  return;
70 
71  /*
72  * Try twice. The second time might wait for files to finish being
73  * unlinked, on Windows.
74  */
75  if (!rmtree(log_opts.basedir, true))
76  rmtree(log_opts.basedir, true);
77 
78  /* Remove pg_upgrade_output.d only if empty */
79  switch (pg_check_dir(log_opts.rootdir))
80  {
81  case 0: /* non-existent */
82  case 3: /* exists and contains a mount point */
83  Assert(false);
84  break;
85 
86  case 1: /* exists and empty */
87  case 2: /* exists and contains only dot files */
88 
89  /*
90  * Try twice. The second time might wait for files to finish
91  * being unlinked, on Windows.
92  */
93  if (!rmtree(log_opts.rootdir, true))
94  rmtree(log_opts.rootdir, true);
95  break;
96 
97  case 4: /* exists */
98 
99  /*
100  * Keep the root directory as this includes some past log
101  * activity.
102  */
103  break;
104 
105  default:
106  /* different failure, just report it */
107  pg_log(PG_WARNING, "could not access directory \"%s\": %m",
108  log_opts.rootdir);
109  break;
110  }
111 }
int pg_check_dir(const char *dir)
Definition: pgcheckdir.c:33
bool rmtree(const char *path, bool rmtopdir)
Definition: rmtree.c:50
char * rootdir
Definition: pg_upgrade.h:307
bool retain
Definition: pg_upgrade.h:305
FILE * internal
Definition: pg_upgrade.h:303
void pg_log(eLogType type, const char *fmt,...)
Definition: util.c:259
LogOpts log_opts
Definition: util.c:17

References Assert(), LogOpts::basedir, LogOpts::internal, log_opts, pg_check_dir(), pg_log(), PG_WARNING, LogOpts::retain, rmtree(), and LogOpts::rootdir.

Referenced by main(), and report_clusters_compatible().

◆ cloneFile()

void cloneFile ( const char *  src,
const char *  dst,
const char *  schemaName,
const char *  relName 
)

Definition at line 38 of file file.c.

40 {
41 #if defined(HAVE_COPYFILE) && defined(COPYFILE_CLONE_FORCE)
42  if (copyfile(src, dst, NULL, COPYFILE_CLONE_FORCE) < 0)
43  pg_fatal("error while cloning relation \"%s.%s\" (\"%s\" to \"%s\"): %s",
44  schemaName, relName, src, dst, strerror(errno));
45 #elif defined(__linux__) && defined(FICLONE)
46  int src_fd;
47  int dest_fd;
48 
49  if ((src_fd = open(src, O_RDONLY | PG_BINARY, 0)) < 0)
50  pg_fatal("error while cloning relation \"%s.%s\": could not open file \"%s\": %s",
51  schemaName, relName, src, strerror(errno));
52 
53  if ((dest_fd = open(dst, O_RDWR | O_CREAT | O_EXCL | PG_BINARY,
54  pg_file_create_mode)) < 0)
55  pg_fatal("error while cloning relation \"%s.%s\": could not create file \"%s\": %s",
56  schemaName, relName, dst, strerror(errno));
57 
58  if (ioctl(dest_fd, FICLONE, src_fd) < 0)
59  {
60  int save_errno = errno;
61 
62  unlink(dst);
63 
64  pg_fatal("error while cloning relation \"%s.%s\" (\"%s\" to \"%s\"): %s",
65  schemaName, relName, src, dst, strerror(save_errno));
66  }
67 
68  close(src_fd);
69  close(dest_fd);
70 #endif
71 }

References close, PG_BINARY, pg_fatal, pg_file_create_mode, and strerror.

Referenced by transfer_relfile().

◆ cluster_conn_opts()

PGresult char* cluster_conn_opts ( ClusterInfo cluster)

Definition at line 92 of file server.c.

93 {
94  static PQExpBuffer buf;
95 
96  if (buf == NULL)
98  else
100 
101  if (cluster->sockdir)
102  {
103  appendPQExpBufferStr(buf, "--host ");
104  appendShellString(buf, cluster->sockdir);
106  }
107  appendPQExpBuffer(buf, "--port %d --username ", cluster->port);
109 
110  return buf->data;
111 }
static char * buf
Definition: pg_test_fsync.c:73
PQExpBuffer createPQExpBuffer(void)
Definition: pqexpbuffer.c:72
void resetPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:146
void appendPQExpBufferChar(PQExpBuffer str, char ch)
Definition: pqexpbuffer.c:378
void appendPQExpBufferStr(PQExpBuffer str, const char *data)
Definition: pqexpbuffer.c:367
void appendShellString(PQExpBuffer buf, const char *str)
Definition: string_utils.c:429
char * user
Definition: pg_upgrade.h:341

References appendPQExpBuffer(), appendPQExpBufferChar(), appendPQExpBufferStr(), appendShellString(), buf, cluster(), createPQExpBuffer(), os_info, resetPQExpBuffer(), and OSInfo::user.

Referenced by create_new_objects(), generate_old_dump(), prepare_new_cluster(), and prepare_new_globals().

◆ connectToServer()

PGconn* connectToServer ( ClusterInfo cluster,
const char *  db_name 
)

Definition at line 28 of file server.c.

29 {
30  PGconn *conn = get_db_conn(cluster, db_name);
31 
32  if (conn == NULL || PQstatus(conn) != CONNECTION_OK)
33  {
35 
36  if (conn)
37  PQfinish(conn);
38 
39  printf(_("Failure, exiting\n"));
40  exit(1);
41  }
42 
44 
45  return conn;
46 }
#define ALWAYS_SECURE_SEARCH_PATH_SQL
Definition: connect.h:25
ConnStatusType PQstatus(const PGconn *conn)
Definition: fe-connect.c:7195
@ CONNECTION_OK
Definition: libpq-fe.h:60
exit(1)
#define printf(...)
Definition: port.h:244
PGresult * executeQueryOrDie(PGconn *conn, const char *fmt,...)
Definition: server.c:122
static PGconn * get_db_conn(ClusterInfo *cluster, const char *db_name)
Definition: server.c:57

References _, ALWAYS_SECURE_SEARCH_PATH_SQL, cluster(), conn, CONNECTION_OK, executeQueryOrDie(), exit(), get_db_conn(), pg_log(), PG_REPORT, PQclear(), PQerrorMessage(), PQfinish(), PQstatus(), and printf.

Referenced by check_for_data_types_usage(), check_for_incompatible_polymorphics(), check_for_isn_and_int8_passing_mismatch(), check_for_pg_role_prefix(), check_for_prepared_transactions(), check_for_tables_with_oids(), check_for_user_defined_encoding_conversions(), check_for_user_defined_postfix_ops(), check_is_install_user(), check_loadable_libraries(), check_new_cluster_logical_replication_slots(), check_proper_datallowconn(), create_logical_replication_slots(), get_db_infos(), get_loadable_libraries(), get_old_cluster_logical_slot_infos(), get_rel_infos(), get_tablespace_paths(), get_template0_info(), old_9_6_invalidate_hash_indexes(), report_extension_updates(), set_frozenxids(), and set_locale_and_encoding().

◆ copyFile()

void copyFile ( const char *  src,
const char *  dst,
const char *  schemaName,
const char *  relName 
)

Definition at line 81 of file file.c.

83 {
84 #ifndef WIN32
85  int src_fd;
86  int dest_fd;
87  char *buffer;
88 
89  if ((src_fd = open(src, O_RDONLY | PG_BINARY, 0)) < 0)
90  pg_fatal("error while copying relation \"%s.%s\": could not open file \"%s\": %s",
91  schemaName, relName, src, strerror(errno));
92 
93  if ((dest_fd = open(dst, O_RDWR | O_CREAT | O_EXCL | PG_BINARY,
94  pg_file_create_mode)) < 0)
95  pg_fatal("error while copying relation \"%s.%s\": could not create file \"%s\": %s",
96  schemaName, relName, dst, strerror(errno));
97 
98  /* copy in fairly large chunks for best efficiency */
99 #define COPY_BUF_SIZE (50 * BLCKSZ)
100 
101  buffer = (char *) pg_malloc(COPY_BUF_SIZE);
102 
103  /* perform data copying i.e read src source, write to destination */
104  while (true)
105  {
106  ssize_t nbytes = read(src_fd, buffer, COPY_BUF_SIZE);
107 
108  if (nbytes < 0)
109  pg_fatal("error while copying relation \"%s.%s\": could not read file \"%s\": %s",
110  schemaName, relName, src, strerror(errno));
111 
112  if (nbytes == 0)
113  break;
114 
115  errno = 0;
116  if (write(dest_fd, buffer, nbytes) != nbytes)
117  {
118  /* if write didn't set errno, assume problem is no disk space */
119  if (errno == 0)
120  errno = ENOSPC;
121  pg_fatal("error while copying relation \"%s.%s\": could not write file \"%s\": %s",
122  schemaName, relName, dst, strerror(errno));
123  }
124  }
125 
126  pg_free(buffer);
127  close(src_fd);
128  close(dest_fd);
129 
130 #else /* WIN32 */
131 
132  if (CopyFile(src, dst, true) == 0)
133  {
134  _dosmaperr(GetLastError());
135  pg_fatal("error while copying relation \"%s.%s\" (\"%s\" to \"%s\"): %s",
136  schemaName, relName, src, dst, strerror(errno));
137  }
138 
139 #endif /* WIN32 */
140 }
void pg_free(void *ptr)
Definition: fe_memutils.c:105
void * pg_malloc(size_t size)
Definition: fe_memutils.c:47
#define COPY_BUF_SIZE
#define write(a, b, c)
Definition: win32.h:14
#define read(a, b, c)
Definition: win32.h:13
void _dosmaperr(unsigned long)
Definition: win32error.c:177

References _dosmaperr(), close, COPY_BUF_SIZE, PG_BINARY, pg_fatal, pg_file_create_mode, pg_free(), pg_malloc(), read, strerror, and write.

Referenced by transfer_relfile().

◆ count_old_cluster_logical_slots()

int count_old_cluster_logical_slots ( void  )

Definition at line 723 of file info.c.

724 {
725  int slot_count = 0;
726 
727  for (int dbnum = 0; dbnum < old_cluster.dbarr.ndbs; dbnum++)
728  slot_count += old_cluster.dbarr.dbs[dbnum].slot_arr.nslots;
729 
730  return slot_count;
731 }
LogicalSlotInfoArr slot_arr
Definition: pg_upgrade.h:197

References ClusterInfo::dbarr, DbInfoArr::dbs, DbInfoArr::ndbs, LogicalSlotInfoArr::nslots, old_cluster, and DbInfo::slot_arr.

Referenced by check_new_cluster_logical_replication_slots(), get_loadable_libraries(), and main().

◆ create_script_for_old_cluster_deletion()

void create_script_for_old_cluster_deletion ( char **  deletion_script_file_name)

Definition at line 436 of file check.c.

437 {
438  FILE *script = NULL;
439  int tblnum;
440  char old_cluster_pgdata[MAXPGPATH],
441  new_cluster_pgdata[MAXPGPATH];
442 
443  *deletion_script_file_name = psprintf("%sdelete_old_cluster.%s",
445 
446  strlcpy(old_cluster_pgdata, old_cluster.pgdata, MAXPGPATH);
447  canonicalize_path(old_cluster_pgdata);
448 
449  strlcpy(new_cluster_pgdata, new_cluster.pgdata, MAXPGPATH);
450  canonicalize_path(new_cluster_pgdata);
451 
452  /* Some people put the new data directory inside the old one. */
453  if (path_is_prefix_of_path(old_cluster_pgdata, new_cluster_pgdata))
454  {
456  "\nWARNING: new data directory should not be inside the old data directory, i.e. %s", old_cluster_pgdata);
457 
458  /* Unlink file in case it is left over from a previous run. */
459  unlink(*deletion_script_file_name);
460  pg_free(*deletion_script_file_name);
461  *deletion_script_file_name = NULL;
462  return;
463  }
464 
465  /*
466  * Some users (oddly) create tablespaces inside the cluster data
467  * directory. We can't create a proper old cluster delete script in that
468  * case.
469  */
470  for (tblnum = 0; tblnum < os_info.num_old_tablespaces; tblnum++)
471  {
472  char old_tablespace_dir[MAXPGPATH];
473 
474  strlcpy(old_tablespace_dir, os_info.old_tablespaces[tblnum], MAXPGPATH);
475  canonicalize_path(old_tablespace_dir);
476  if (path_is_prefix_of_path(old_cluster_pgdata, old_tablespace_dir))
477  {
478  /* reproduce warning from CREATE TABLESPACE that is in the log */
480  "\nWARNING: user-defined tablespace locations should not be inside the data directory, i.e. %s", old_tablespace_dir);
481 
482  /* Unlink file in case it is left over from a previous run. */
483  unlink(*deletion_script_file_name);
484  pg_free(*deletion_script_file_name);
485  *deletion_script_file_name = NULL;
486  return;
487  }
488  }
489 
490  prep_status("Creating script to delete old cluster");
491 
492  if ((script = fopen_priv(*deletion_script_file_name, "w")) == NULL)
493  pg_fatal("could not open file \"%s\": %s",
494  *deletion_script_file_name, strerror(errno));
495 
496 #ifndef WIN32
497  /* add shebang header */
498  fprintf(script, "#!/bin/sh\n\n");
499 #endif
500 
501  /* delete old cluster's default tablespace */
502  fprintf(script, RMDIR_CMD " %c%s%c\n", PATH_QUOTE,
504 
505  /* delete old cluster's alternate tablespaces */
506  for (tblnum = 0; tblnum < os_info.num_old_tablespaces; tblnum++)
507  {
508  /*
509  * Do the old cluster's per-database directories share a directory
510  * with a new version-specific tablespace?
511  */
512  if (strlen(old_cluster.tablespace_suffix) == 0)
513  {
514  /* delete per-database directories */
515  int dbnum;
516 
517  fprintf(script, "\n");
518 
519  for (dbnum = 0; dbnum < old_cluster.dbarr.ndbs; dbnum++)
520  fprintf(script, RMDIR_CMD " %c%s%c%u%c\n", PATH_QUOTE,
523  PATH_QUOTE);
524  }
525  else
526  {
527  char *suffix_path = pg_strdup(old_cluster.tablespace_suffix);
528 
529  /*
530  * Simply delete the tablespace directory, which might be ".old"
531  * or a version-specific subdirectory.
532  */
533  fprintf(script, RMDIR_CMD " %c%s%s%c\n", PATH_QUOTE,
535  fix_path_separator(suffix_path), PATH_QUOTE);
536  pfree(suffix_path);
537  }
538  }
539 
540  fclose(script);
541 
542 #ifndef WIN32
543  if (chmod(*deletion_script_file_name, S_IRWXU) != 0)
544  pg_fatal("could not add execute permission to file \"%s\": %s",
545  *deletion_script_file_name, strerror(errno));
546 #endif
547 
548  check_ok();
549 }
static char * fix_path_separator(char *path)
Definition: check.c:48
void pfree(void *pointer)
Definition: mcxt.c:1456
#define PATH_SEPARATOR
Definition: pg_upgrade.h:82
#define RMDIR_CMD
Definition: pg_upgrade.h:85
#define SCRIPT_EXT
Definition: pg_upgrade.h:87
#define SCRIPT_PREFIX
Definition: pg_upgrade.h:86
#define PATH_QUOTE
Definition: pg_upgrade.h:83
bool path_is_prefix_of_path(const char *path1, const char *path2)
Definition: path.c:559
void canonicalize_path(char *path)
Definition: path.c:264
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition: strlcpy.c:45
const char * tablespace_suffix
Definition: pg_upgrade.h:294
Oid db_oid
Definition: pg_upgrade.h:192
int num_old_tablespaces
Definition: pg_upgrade.h:344
char ** old_tablespaces
Definition: pg_upgrade.h:343
#define S_IRWXU
Definition: win32_port.h:298

References canonicalize_path(), check_ok(), DbInfo::db_oid, ClusterInfo::dbarr, DbInfoArr::dbs, fix_path_separator(), fopen_priv, fprintf, MAXPGPATH, DbInfoArr::ndbs, new_cluster, OSInfo::num_old_tablespaces, old_cluster, OSInfo::old_tablespaces, os_info, path_is_prefix_of_path(), PATH_QUOTE, PATH_SEPARATOR, pfree(), pg_fatal, pg_free(), pg_log(), pg_strdup(), PG_WARNING, ClusterInfo::pgdata, prep_status(), psprintf(), RMDIR_CMD, S_IRWXU, SCRIPT_EXT, SCRIPT_PREFIX, strerror, strlcpy(), and ClusterInfo::tablespace_suffix.

Referenced by main().

◆ disable_old_cluster()

void disable_old_cluster ( void  )

Definition at line 713 of file controldata.c.

714 {
715  char old_path[MAXPGPATH],
716  new_path[MAXPGPATH];
717 
718  /* rename pg_control so old server cannot be accidentally started */
719  prep_status("Adding \".old\" suffix to old global/pg_control");
720 
721  snprintf(old_path, sizeof(old_path), "%s/global/pg_control", old_cluster.pgdata);
722  snprintf(new_path, sizeof(new_path), "%s/global/pg_control.old", old_cluster.pgdata);
723  if (pg_mv_file(old_path, new_path) != 0)
724  pg_fatal("could not rename file \"%s\" to \"%s\": %m",
725  old_path, new_path);
726  check_ok();
727 
728  pg_log(PG_REPORT, "\n"
729  "If you want to start the old cluster, you will need to remove\n"
730  "the \".old\" suffix from %s/global/pg_control.old.\n"
731  "Because \"link\" mode was used, the old cluster cannot be safely\n"
732  "started once the new cluster has been started.",
734 }
#define pg_mv_file
Definition: pg_upgrade.h:81

References check_ok(), MAXPGPATH, old_cluster, pg_fatal, pg_log(), pg_mv_file, PG_REPORT, ClusterInfo::pgdata, prep_status(), and snprintf.

Referenced by main().

◆ end_progress_output()

void end_progress_output ( void  )

Definition at line 43 of file util.c.

44 {
45  /*
46  * For output to a tty, erase prior contents of progress line. When either
47  * tty or verbose, indent so that report_status() output will align
48  * nicely.
49  */
50  if (log_opts.isatty)
51  {
52  printf("\r");
53  pg_log(PG_REPORT_NONL, "%-*s", MESSAGE_WIDTH, "");
54  }
55  else if (log_opts.verbose)
56  pg_log(PG_REPORT_NONL, "%-*s", MESSAGE_WIDTH, "");
57 }
#define MESSAGE_WIDTH
Definition: pg_upgrade.h:25
bool isatty
Definition: pg_upgrade.h:311
bool verbose
Definition: pg_upgrade.h:304

References LogOpts::isatty, log_opts, MESSAGE_WIDTH, pg_log(), PG_REPORT_NONL, printf, and LogOpts::verbose.

Referenced by create_logical_replication_slots(), create_new_objects(), generate_old_dump(), and transfer_all_new_tablespaces().

◆ exec_prog()

bool exec_prog ( const char *  log_filename,
const char *  opt_log_file,
bool  report_error,
bool  exit_on_error,
const char *  fmt,
  ... 
)

◆ executeQueryOrDie()

◆ gen_db_file_maps()

FileNameMap* gen_db_file_maps ( DbInfo old_db,
DbInfo new_db,
int *  nmaps,
const char *  old_pgdata,
const char *  new_pgdata 
)

Definition at line 42 of file info.c.

45 {
47  int old_relnum,
48  new_relnum;
49  int num_maps = 0;
50  bool all_matched = true;
51 
52  /* There will certainly not be more mappings than there are old rels */
53  maps = (FileNameMap *) pg_malloc(sizeof(FileNameMap) *
54  old_db->rel_arr.nrels);
55 
56  /*
57  * Each of the RelInfo arrays should be sorted by OID. Scan through them
58  * and match them up. If we fail to match everything, we'll abort, but
59  * first print as much info as we can about mismatches.
60  */
61  old_relnum = new_relnum = 0;
62  while (old_relnum < old_db->rel_arr.nrels ||
63  new_relnum < new_db->rel_arr.nrels)
64  {
65  RelInfo *old_rel = (old_relnum < old_db->rel_arr.nrels) ?
66  &old_db->rel_arr.rels[old_relnum] : NULL;
67  RelInfo *new_rel = (new_relnum < new_db->rel_arr.nrels) ?
68  &new_db->rel_arr.rels[new_relnum] : NULL;
69 
70  /* handle running off one array before the other */
71  if (!new_rel)
72  {
73  /*
74  * old_rel is unmatched. This should never happen, because we
75  * force new rels to have TOAST tables if the old one did.
76  */
77  report_unmatched_relation(old_rel, old_db, false);
78  all_matched = false;
79  old_relnum++;
80  continue;
81  }
82  if (!old_rel)
83  {
84  /*
85  * new_rel is unmatched. This shouldn't really happen either, but
86  * if it's a TOAST table, we can ignore it and continue
87  * processing, assuming that the new server made a TOAST table
88  * that wasn't needed.
89  */
90  if (strcmp(new_rel->nspname, "pg_toast") != 0)
91  {
92  report_unmatched_relation(new_rel, new_db, true);
93  all_matched = false;
94  }
95  new_relnum++;
96  continue;
97  }
98 
99  /* check for mismatched OID */
100  if (old_rel->reloid < new_rel->reloid)
101  {
102  /* old_rel is unmatched, see comment above */
103  report_unmatched_relation(old_rel, old_db, false);
104  all_matched = false;
105  old_relnum++;
106  continue;
107  }
108  else if (old_rel->reloid > new_rel->reloid)
109  {
110  /* new_rel is unmatched, see comment above */
111  if (strcmp(new_rel->nspname, "pg_toast") != 0)
112  {
113  report_unmatched_relation(new_rel, new_db, true);
114  all_matched = false;
115  }
116  new_relnum++;
117  continue;
118  }
119 
120  /*
121  * Verify that rels of same OID have same name. The namespace name
122  * should always match, but the relname might not match for TOAST
123  * tables (and, therefore, their indexes).
124  */
125  if (strcmp(old_rel->nspname, new_rel->nspname) != 0 ||
126  strcmp(old_rel->relname, new_rel->relname) != 0)
127  {
128  pg_log(PG_WARNING, "Relation names for OID %u in database \"%s\" do not match: "
129  "old name \"%s.%s\", new name \"%s.%s\"",
130  old_rel->reloid, old_db->db_name,
131  old_rel->nspname, old_rel->relname,
132  new_rel->nspname, new_rel->relname);
133  all_matched = false;
134  old_relnum++;
135  new_relnum++;
136  continue;
137  }
138 
139  /* OK, create a mapping entry */
140  create_rel_filename_map(old_pgdata, new_pgdata, old_db, new_db,
141  old_rel, new_rel, maps + num_maps);
142  num_maps++;
143  old_relnum++;
144  new_relnum++;
145  }
146 
147  if (!all_matched)
148  pg_fatal("Failed to match up old and new tables in database \"%s\"",
149  old_db->db_name);
150 
151  *nmaps = num_maps;
152  return maps;
153 }
static void report_unmatched_relation(const RelInfo *rel, const DbInfo *db, bool is_new_db)
Definition: info.c:211
static void create_rel_filename_map(const char *old_data, const char *new_data, const DbInfo *old_db, const DbInfo *new_db, const RelInfo *old_rel, const RelInfo *new_rel, FileNameMap *map)
Definition: info.c:162
RelInfoArr rel_arr
Definition: pg_upgrade.h:196
RelInfo * rels
Definition: pg_upgrade.h:149
Oid reloid
Definition: pg_upgrade.h:138
char * nspname
Definition: pg_upgrade.h:136
char * relname
Definition: pg_upgrade.h:137
static const pg_conv_map maps[]

References create_rel_filename_map(), DbInfo::db_name, maps, RelInfoArr::nrels, RelInfo::nspname, pg_fatal, pg_log(), pg_malloc(), PG_WARNING, DbInfo::rel_arr, RelInfo::relname, RelInfo::reloid, RelInfoArr::rels, and report_unmatched_relation().

Referenced by transfer_all_new_dbs().

◆ generate_old_dump()

void generate_old_dump ( void  )

Definition at line 16 of file dump.c.

17 {
18  int dbnum;
19 
20  prep_status("Creating dump of global objects");
21 
22  /* run new pg_dumpall binary for globals */
23  exec_prog(UTILITY_LOG_FILE, NULL, true, true,
24  "\"%s/pg_dumpall\" %s --globals-only --quote-all-identifiers "
25  "--binary-upgrade %s -f \"%s/%s\"",
27  log_opts.verbose ? "--verbose" : "",
30  check_ok();
31 
32  prep_status_progress("Creating dump of database schemas");
33 
34  /* create per-db dump files */
35  for (dbnum = 0; dbnum < old_cluster.dbarr.ndbs; dbnum++)
36  {
37  char sql_file_name[MAXPGPATH],
38  log_file_name[MAXPGPATH];
39  DbInfo *old_db = &old_cluster.dbarr.dbs[dbnum];
41  escaped_connstr;
42 
44  appendPQExpBufferStr(&connstr, "dbname=");
45  appendConnStrVal(&connstr, old_db->db_name);
46  initPQExpBuffer(&escaped_connstr);
47  appendShellString(&escaped_connstr, connstr.data);
49 
50  pg_log(PG_STATUS, "%s", old_db->db_name);
51  snprintf(sql_file_name, sizeof(sql_file_name), DB_DUMP_FILE_MASK, old_db->db_oid);
52  snprintf(log_file_name, sizeof(log_file_name), DB_DUMP_LOG_FILE_MASK, old_db->db_oid);
53 
54  parallel_exec_prog(log_file_name, NULL,
55  "\"%s/pg_dump\" %s --schema-only --quote-all-identifiers "
56  "--binary-upgrade --format=custom %s --file=\"%s/%s\" %s",
58  log_opts.verbose ? "--verbose" : "",
60  sql_file_name, escaped_connstr.data);
61 
62  termPQExpBuffer(&escaped_connstr);
63  }
64 
65  /* reap all children */
66  while (reap_child(true) == true)
67  ;
68 
70  check_ok();
71 }
bool exec_prog(const char *log_filename, const char *opt_log_file, bool report_error, bool exit_on_error, const char *fmt,...)
Definition: exec.c:86
bool reap_child(bool wait_for_child)
Definition: parallel.c:278
void parallel_exec_prog(const char *log_file, const char *opt_log_file, const char *fmt,...)
Definition: parallel.c:62
static char * connstr
Definition: pg_dumpall.c:90
#define GLOBALS_DUMP_FILE
Definition: pg_upgrade.h:30
#define DB_DUMP_LOG_FILE_MASK
Definition: pg_upgrade.h:43
#define UTILITY_LOG_FILE
Definition: pg_upgrade.h:45
void void prep_status_progress(const char *fmt,...) pg_attribute_printf(1
void end_progress_output(void)
Definition: util.c:43
PGresult char * cluster_conn_opts(ClusterInfo *cluster)
Definition: server.c:92
#define DB_DUMP_FILE_MASK
Definition: pg_upgrade.h:31
void appendConnStrVal(PQExpBuffer buf, const char *str)
Definition: string_utils.c:545
char * bindir
Definition: pg_upgrade.h:286
char * dumpdir
Definition: pg_upgrade.h:309

References appendConnStrVal(), appendPQExpBufferStr(), appendShellString(), ClusterInfo::bindir, check_ok(), cluster_conn_opts(), connstr, PQExpBufferData::data, DB_DUMP_FILE_MASK, DB_DUMP_LOG_FILE_MASK, DbInfo::db_name, DbInfo::db_oid, ClusterInfo::dbarr, DbInfoArr::dbs, LogOpts::dumpdir, end_progress_output(), exec_prog(), GLOBALS_DUMP_FILE, initPQExpBuffer(), log_opts, MAXPGPATH, DbInfoArr::ndbs, new_cluster, old_cluster, parallel_exec_prog(), pg_log(), PG_STATUS, prep_status(), prep_status_progress(), reap_child(), snprintf, termPQExpBuffer(), UTILITY_LOG_FILE, and LogOpts::verbose.

Referenced by check_and_dump_old_cluster().

◆ get_control_data()

void get_control_data ( ClusterInfo cluster,
bool  live_check 
)

Definition at line 36 of file controldata.c.

37 {
38  char cmd[MAXPGPATH];
39  char bufin[MAX_STRING];
40  FILE *output;
41  char *p;
42  bool got_tli = false;
43  bool got_log_id = false;
44  bool got_log_seg = false;
45  bool got_xid = false;
46  bool got_oid = false;
47  bool got_multi = false;
48  bool got_oldestmulti = false;
49  bool got_oldestxid = false;
50  bool got_mxoff = false;
51  bool got_nextxlogfile = false;
52  bool got_float8_pass_by_value = false;
53  bool got_align = false;
54  bool got_blocksz = false;
55  bool got_largesz = false;
56  bool got_walsz = false;
57  bool got_walseg = false;
58  bool got_ident = false;
59  bool got_index = false;
60  bool got_toast = false;
61  bool got_large_object = false;
62  bool got_date_is_int = false;
63  bool got_data_checksum_version = false;
64  bool got_cluster_state = false;
65  char *lc_collate = NULL;
66  char *lc_ctype = NULL;
67  char *lc_monetary = NULL;
68  char *lc_numeric = NULL;
69  char *lc_time = NULL;
70  char *lang = NULL;
71  char *language = NULL;
72  char *lc_all = NULL;
73  char *lc_messages = NULL;
74  uint32 tli = 0;
75  uint32 logid = 0;
76  uint32 segno = 0;
77  char *resetwal_bin;
78  int rc;
79 
80  /*
81  * Because we test the pg_resetwal output as strings, it has to be in
82  * English. Copied from pg_regress.c.
83  */
84  if (getenv("LC_COLLATE"))
85  lc_collate = pg_strdup(getenv("LC_COLLATE"));
86  if (getenv("LC_CTYPE"))
87  lc_ctype = pg_strdup(getenv("LC_CTYPE"));
88  if (getenv("LC_MONETARY"))
89  lc_monetary = pg_strdup(getenv("LC_MONETARY"));
90  if (getenv("LC_NUMERIC"))
91  lc_numeric = pg_strdup(getenv("LC_NUMERIC"));
92  if (getenv("LC_TIME"))
93  lc_time = pg_strdup(getenv("LC_TIME"));
94  if (getenv("LANG"))
95  lang = pg_strdup(getenv("LANG"));
96  if (getenv("LANGUAGE"))
97  language = pg_strdup(getenv("LANGUAGE"));
98  if (getenv("LC_ALL"))
99  lc_all = pg_strdup(getenv("LC_ALL"));
100  if (getenv("LC_MESSAGES"))
101  lc_messages = pg_strdup(getenv("LC_MESSAGES"));
102 
103  unsetenv("LC_COLLATE");
104  unsetenv("LC_CTYPE");
105  unsetenv("LC_MONETARY");
106  unsetenv("LC_NUMERIC");
107  unsetenv("LC_TIME");
108 #ifndef WIN32
109  unsetenv("LANG");
110 #else
111  /* On Windows the default locale may not be English, so force it */
112  setenv("LANG", "en", 1);
113 #endif
114  unsetenv("LANGUAGE");
115  unsetenv("LC_ALL");
116  setenv("LC_MESSAGES", "C", 1);
117 
118  /*
119  * Check for clean shutdown
120  */
121  if (!live_check || cluster == &new_cluster)
122  {
123  /* only pg_controldata outputs the cluster state */
124  snprintf(cmd, sizeof(cmd), "\"%s/pg_controldata\" \"%s\"",
125  cluster->bindir, cluster->pgdata);
126  fflush(NULL);
127 
128  if ((output = popen(cmd, "r")) == NULL)
129  pg_fatal("could not get control data using %s: %s",
130  cmd, strerror(errno));
131 
132  /* we have the result of cmd in "output". so parse it line by line now */
133  while (fgets(bufin, sizeof(bufin), output))
134  {
135  if ((p = strstr(bufin, "Database cluster state:")) != NULL)
136  {
137  p = strchr(p, ':');
138 
139  if (p == NULL || strlen(p) <= 1)
140  pg_fatal("%d: database cluster state problem", __LINE__);
141 
142  p++; /* remove ':' char */
143 
144  /*
145  * We checked earlier for a postmaster lock file, and if we
146  * found one, we tried to start/stop the server to replay the
147  * WAL. However, pg_ctl -m immediate doesn't leave a lock
148  * file, but does require WAL replay, so we check here that
149  * the server was shut down cleanly, from the controldata
150  * perspective.
151  */
152  /* Remove trailing newline and leading spaces */
153  (void) pg_strip_crlf(p);
154  while (*p == ' ')
155  p++;
156  if (strcmp(p, "shut down in recovery") == 0)
157  {
158  if (cluster == &old_cluster)
159  pg_fatal("The source cluster was shut down while in recovery mode. To upgrade, use \"rsync\" as documented or shut it down as a primary.");
160  else
161  pg_fatal("The target cluster was shut down while in recovery mode. To upgrade, use \"rsync\" as documented or shut it down as a primary.");
162  }
163  else if (strcmp(p, "shut down") != 0)
164  {
165  if (cluster == &old_cluster)
166  pg_fatal("The source cluster was not shut down cleanly, state reported as: \"%s\"", p);
167  else
168  pg_fatal("The target cluster was not shut down cleanly, state reported as: \"%s\"", p);
169  }
170  got_cluster_state = true;
171  }
172  }
173 
174  rc = pclose(output);
175  if (rc != 0)
176  pg_fatal("could not get control data using %s: %s",
177  cmd, wait_result_to_str(rc));
178 
179  if (!got_cluster_state)
180  {
181  if (cluster == &old_cluster)
182  pg_fatal("The source cluster lacks cluster state information:");
183  else
184  pg_fatal("The target cluster lacks cluster state information:");
185  }
186  }
187 
188  /* pg_resetxlog has been renamed to pg_resetwal in version 10 */
189  if (GET_MAJOR_VERSION(cluster->bin_version) <= 906)
190  resetwal_bin = "pg_resetxlog\" -n";
191  else
192  resetwal_bin = "pg_resetwal\" -n";
193  snprintf(cmd, sizeof(cmd), "\"%s/%s \"%s\"",
194  cluster->bindir,
195  live_check ? "pg_controldata\"" : resetwal_bin,
196  cluster->pgdata);
197  fflush(NULL);
198 
199  if ((output = popen(cmd, "r")) == NULL)
200  pg_fatal("could not get control data using %s: %s",
201  cmd, strerror(errno));
202 
203  /* Only in <= 9.2 */
204  if (GET_MAJOR_VERSION(cluster->major_version) <= 902)
205  {
206  cluster->controldata.data_checksum_version = 0;
207  got_data_checksum_version = true;
208  }
209 
210  /* we have the result of cmd in "output". so parse it line by line now */
211  while (fgets(bufin, sizeof(bufin), output))
212  {
213  /* In verbose mode, log each line */
214  pg_strip_crlf(bufin);
215  pg_log(PG_VERBOSE, "%s", bufin);
216 
217  if ((p = strstr(bufin, "pg_control version number:")) != NULL)
218  {
219  p = strchr(p, ':');
220 
221  if (p == NULL || strlen(p) <= 1)
222  pg_fatal("%d: pg_resetwal problem", __LINE__);
223 
224  p++; /* remove ':' char */
225  cluster->controldata.ctrl_ver = str2uint(p);
226  }
227  else if ((p = strstr(bufin, "Catalog version number:")) != NULL)
228  {
229  p = strchr(p, ':');
230 
231  if (p == NULL || strlen(p) <= 1)
232  pg_fatal("%d: controldata retrieval problem", __LINE__);
233 
234  p++; /* remove ':' char */
235  cluster->controldata.cat_ver = str2uint(p);
236  }
237  else if ((p = strstr(bufin, "Latest checkpoint's TimeLineID:")) != NULL)
238  {
239  p = strchr(p, ':');
240 
241  if (p == NULL || strlen(p) <= 1)
242  pg_fatal("%d: controldata retrieval problem", __LINE__);
243 
244  p++; /* remove ':' char */
245  tli = str2uint(p);
246  got_tli = true;
247  }
248  else if ((p = strstr(bufin, "First log file ID after reset:")) != NULL)
249  {
250  p = strchr(p, ':');
251 
252  if (p == NULL || strlen(p) <= 1)
253  pg_fatal("%d: controldata retrieval problem", __LINE__);
254 
255  p++; /* remove ':' char */
256  logid = str2uint(p);
257  got_log_id = true;
258  }
259  else if ((p = strstr(bufin, "First log file segment after reset:")) != NULL)
260  {
261  p = strchr(p, ':');
262 
263  if (p == NULL || strlen(p) <= 1)
264  pg_fatal("%d: controldata retrieval problem", __LINE__);
265 
266  p++; /* remove ':' char */
267  segno = str2uint(p);
268  got_log_seg = true;
269  }
270  else if ((p = strstr(bufin, "Latest checkpoint's NextXID:")) != NULL)
271  {
272  p = strchr(p, ':');
273 
274  if (p == NULL || strlen(p) <= 1)
275  pg_fatal("%d: controldata retrieval problem", __LINE__);
276 
277  p++; /* remove ':' char */
278  cluster->controldata.chkpnt_nxtepoch = str2uint(p);
279 
280  /*
281  * Delimiter changed from '/' to ':' in 9.6. We don't test for
282  * the catalog version of the change because the catalog version
283  * is pulled from pg_controldata too, and it isn't worth adding an
284  * order dependency for this --- we just check the string.
285  */
286  if (strchr(p, '/') != NULL)
287  p = strchr(p, '/');
288  else if (GET_MAJOR_VERSION(cluster->major_version) >= 906)
289  p = strchr(p, ':');
290  else
291  p = NULL;
292 
293  if (p == NULL || strlen(p) <= 1)
294  pg_fatal("%d: controldata retrieval problem", __LINE__);
295 
296  p++; /* remove '/' or ':' char */
297  cluster->controldata.chkpnt_nxtxid = str2uint(p);
298  got_xid = true;
299  }
300  else if ((p = strstr(bufin, "Latest checkpoint's NextOID:")) != NULL)
301  {
302  p = strchr(p, ':');
303 
304  if (p == NULL || strlen(p) <= 1)
305  pg_fatal("%d: controldata retrieval problem", __LINE__);
306 
307  p++; /* remove ':' char */
308  cluster->controldata.chkpnt_nxtoid = str2uint(p);
309  got_oid = true;
310  }
311  else if ((p = strstr(bufin, "Latest checkpoint's NextMultiXactId:")) != NULL)
312  {
313  p = strchr(p, ':');
314 
315  if (p == NULL || strlen(p) <= 1)
316  pg_fatal("%d: controldata retrieval problem", __LINE__);
317 
318  p++; /* remove ':' char */
319  cluster->controldata.chkpnt_nxtmulti = str2uint(p);
320  got_multi = true;
321  }
322  else if ((p = strstr(bufin, "Latest checkpoint's oldestXID:")) != NULL)
323  {
324  p = strchr(p, ':');
325 
326  if (p == NULL || strlen(p) <= 1)
327  pg_fatal("%d: controldata retrieval problem", __LINE__);
328 
329  p++; /* remove ':' char */
330  cluster->controldata.chkpnt_oldstxid = str2uint(p);
331  got_oldestxid = true;
332  }
333  else if ((p = strstr(bufin, "Latest checkpoint's oldestMultiXid:")) != NULL)
334  {
335  p = strchr(p, ':');
336 
337  if (p == NULL || strlen(p) <= 1)
338  pg_fatal("%d: controldata retrieval problem", __LINE__);
339 
340  p++; /* remove ':' char */
341  cluster->controldata.chkpnt_oldstMulti = str2uint(p);
342  got_oldestmulti = true;
343  }
344  else if ((p = strstr(bufin, "Latest checkpoint's NextMultiOffset:")) != NULL)
345  {
346  p = strchr(p, ':');
347 
348  if (p == NULL || strlen(p) <= 1)
349  pg_fatal("%d: controldata retrieval problem", __LINE__);
350 
351  p++; /* remove ':' char */
352  cluster->controldata.chkpnt_nxtmxoff = str2uint(p);
353  got_mxoff = true;
354  }
355  else if ((p = strstr(bufin, "First log segment after reset:")) != NULL)
356  {
357  /* Skip the colon and any whitespace after it */
358  p = strchr(p, ':');
359  if (p == NULL || strlen(p) <= 1)
360  pg_fatal("%d: controldata retrieval problem", __LINE__);
361  p = strpbrk(p, "01234567890ABCDEF");
362  if (p == NULL || strlen(p) <= 1)
363  pg_fatal("%d: controldata retrieval problem", __LINE__);
364 
365  /* Make sure it looks like a valid WAL file name */
366  if (strspn(p, "0123456789ABCDEF") != 24)
367  pg_fatal("%d: controldata retrieval problem", __LINE__);
368 
369  strlcpy(cluster->controldata.nextxlogfile, p, 25);
370  got_nextxlogfile = true;
371  }
372  else if ((p = strstr(bufin, "Float8 argument passing:")) != NULL)
373  {
374  p = strchr(p, ':');
375 
376  if (p == NULL || strlen(p) <= 1)
377  pg_fatal("%d: controldata retrieval problem", __LINE__);
378 
379  p++; /* remove ':' char */
380  /* used later for contrib check */
381  cluster->controldata.float8_pass_by_value = strstr(p, "by value") != NULL;
382  got_float8_pass_by_value = true;
383  }
384  else if ((p = strstr(bufin, "Maximum data alignment:")) != NULL)
385  {
386  p = strchr(p, ':');
387 
388  if (p == NULL || strlen(p) <= 1)
389  pg_fatal("%d: controldata retrieval problem", __LINE__);
390 
391  p++; /* remove ':' char */
392  cluster->controldata.align = str2uint(p);
393  got_align = true;
394  }
395  else if ((p = strstr(bufin, "Database block size:")) != NULL)
396  {
397  p = strchr(p, ':');
398 
399  if (p == NULL || strlen(p) <= 1)
400  pg_fatal("%d: controldata retrieval problem", __LINE__);
401 
402  p++; /* remove ':' char */
403  cluster->controldata.blocksz = str2uint(p);
404  got_blocksz = true;
405  }
406  else if ((p = strstr(bufin, "Blocks per segment of large relation:")) != NULL)
407  {
408  p = strchr(p, ':');
409 
410  if (p == NULL || strlen(p) <= 1)
411  pg_fatal("%d: controldata retrieval problem", __LINE__);
412 
413  p++; /* remove ':' char */
414  cluster->controldata.largesz = str2uint(p);
415  got_largesz = true;
416  }
417  else if ((p = strstr(bufin, "WAL block size:")) != NULL)
418  {
419  p = strchr(p, ':');
420 
421  if (p == NULL || strlen(p) <= 1)
422  pg_fatal("%d: controldata retrieval problem", __LINE__);
423 
424  p++; /* remove ':' char */
425  cluster->controldata.walsz = str2uint(p);
426  got_walsz = true;
427  }
428  else if ((p = strstr(bufin, "Bytes per WAL segment:")) != NULL)
429  {
430  p = strchr(p, ':');
431 
432  if (p == NULL || strlen(p) <= 1)
433  pg_fatal("%d: controldata retrieval problem", __LINE__);
434 
435  p++; /* remove ':' char */
436  cluster->controldata.walseg = str2uint(p);
437  got_walseg = true;
438  }
439  else if ((p = strstr(bufin, "Maximum length of identifiers:")) != NULL)
440  {
441  p = strchr(p, ':');
442 
443  if (p == NULL || strlen(p) <= 1)
444  pg_fatal("%d: controldata retrieval problem", __LINE__);
445 
446  p++; /* remove ':' char */
447  cluster->controldata.ident = str2uint(p);
448  got_ident = true;
449  }
450  else if ((p = strstr(bufin, "Maximum columns in an index:")) != NULL)
451  {
452  p = strchr(p, ':');
453 
454  if (p == NULL || strlen(p) <= 1)
455  pg_fatal("%d: controldata retrieval problem", __LINE__);
456 
457  p++; /* remove ':' char */
458  cluster->controldata.index = str2uint(p);
459  got_index = true;
460  }
461  else if ((p = strstr(bufin, "Maximum size of a TOAST chunk:")) != NULL)
462  {
463  p = strchr(p, ':');
464 
465  if (p == NULL || strlen(p) <= 1)
466  pg_fatal("%d: controldata retrieval problem", __LINE__);
467 
468  p++; /* remove ':' char */
469  cluster->controldata.toast = str2uint(p);
470  got_toast = true;
471  }
472  else if ((p = strstr(bufin, "Size of a large-object chunk:")) != NULL)
473  {
474  p = strchr(p, ':');
475 
476  if (p == NULL || strlen(p) <= 1)
477  pg_fatal("%d: controldata retrieval problem", __LINE__);
478 
479  p++; /* remove ':' char */
480  cluster->controldata.large_object = str2uint(p);
481  got_large_object = true;
482  }
483  else if ((p = strstr(bufin, "Date/time type storage:")) != NULL)
484  {
485  p = strchr(p, ':');
486 
487  if (p == NULL || strlen(p) <= 1)
488  pg_fatal("%d: controldata retrieval problem", __LINE__);
489 
490  p++; /* remove ':' char */
491  cluster->controldata.date_is_int = strstr(p, "64-bit integers") != NULL;
492  got_date_is_int = true;
493  }
494  else if ((p = strstr(bufin, "checksum")) != NULL)
495  {
496  p = strchr(p, ':');
497 
498  if (p == NULL || strlen(p) <= 1)
499  pg_fatal("%d: controldata retrieval problem", __LINE__);
500 
501  p++; /* remove ':' char */
502  cluster->controldata.data_checksum_version = str2uint(p);
503  got_data_checksum_version = true;
504  }
505  }
506 
507  rc = pclose(output);
508  if (rc != 0)
509  pg_fatal("could not get control data using %s: %s",
510  cmd, wait_result_to_str(rc));
511 
512  /*
513  * Restore environment variables. Note all but LANG and LC_MESSAGES were
514  * unset above.
515  */
516  if (lc_collate)
517  setenv("LC_COLLATE", lc_collate, 1);
518  if (lc_ctype)
519  setenv("LC_CTYPE", lc_ctype, 1);
520  if (lc_monetary)
521  setenv("LC_MONETARY", lc_monetary, 1);
522  if (lc_numeric)
523  setenv("LC_NUMERIC", lc_numeric, 1);
524  if (lc_time)
525  setenv("LC_TIME", lc_time, 1);
526  if (lang)
527  setenv("LANG", lang, 1);
528  else
529  unsetenv("LANG");
530  if (language)
531  setenv("LANGUAGE", language, 1);
532  if (lc_all)
533  setenv("LC_ALL", lc_all, 1);
534  if (lc_messages)
535  setenv("LC_MESSAGES", lc_messages, 1);
536  else
537  unsetenv("LC_MESSAGES");
538 
540  pg_free(lc_ctype);
543  pg_free(lc_time);
544  pg_free(lang);
545  pg_free(language);
546  pg_free(lc_all);
548 
549  /*
550  * Before 9.3, pg_resetwal reported the xlogid and segno of the first log
551  * file after reset as separate lines. Starting with 9.3, it reports the
552  * WAL file name. If the old cluster is older than 9.3, we construct the
553  * WAL file name from the xlogid and segno.
554  */
555  if (GET_MAJOR_VERSION(cluster->major_version) <= 902)
556  {
557  if (got_tli && got_log_id && got_log_seg)
558  {
559  snprintf(cluster->controldata.nextxlogfile, 25, "%08X%08X%08X",
560  tli, logid, segno);
561  got_nextxlogfile = true;
562  }
563  }
564 
565  /* verify that we got all the mandatory pg_control data */
566  if (!got_xid || !got_oid ||
567  !got_multi || !got_oldestxid ||
568  (!got_oldestmulti &&
569  cluster->controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER) ||
570  !got_mxoff || (!live_check && !got_nextxlogfile) ||
571  !got_float8_pass_by_value || !got_align || !got_blocksz ||
572  !got_largesz || !got_walsz || !got_walseg || !got_ident ||
573  !got_index || !got_toast ||
574  (!got_large_object &&
575  cluster->controldata.ctrl_ver >= LARGE_OBJECT_SIZE_PG_CONTROL_VER) ||
576  !got_date_is_int || !got_data_checksum_version)
577  {
578  if (cluster == &old_cluster)
580  "The source cluster lacks some required control information:");
581  else
583  "The target cluster lacks some required control information:");
584 
585  if (!got_xid)
586  pg_log(PG_REPORT, " checkpoint next XID");
587 
588  if (!got_oid)
589  pg_log(PG_REPORT, " latest checkpoint next OID");
590 
591  if (!got_multi)
592  pg_log(PG_REPORT, " latest checkpoint next MultiXactId");
593 
594  if (!got_oldestmulti &&
595  cluster->controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER)
596  pg_log(PG_REPORT, " latest checkpoint oldest MultiXactId");
597 
598  if (!got_oldestxid)
599  pg_log(PG_REPORT, " latest checkpoint oldestXID");
600 
601  if (!got_mxoff)
602  pg_log(PG_REPORT, " latest checkpoint next MultiXactOffset");
603 
604  if (!live_check && !got_nextxlogfile)
605  pg_log(PG_REPORT, " first WAL segment after reset");
606 
607  if (!got_float8_pass_by_value)
608  pg_log(PG_REPORT, " float8 argument passing method");
609 
610  if (!got_align)
611  pg_log(PG_REPORT, " maximum alignment");
612 
613  if (!got_blocksz)
614  pg_log(PG_REPORT, " block size");
615 
616  if (!got_largesz)
617  pg_log(PG_REPORT, " large relation segment size");
618 
619  if (!got_walsz)
620  pg_log(PG_REPORT, " WAL block size");
621 
622  if (!got_walseg)
623  pg_log(PG_REPORT, " WAL segment size");
624 
625  if (!got_ident)
626  pg_log(PG_REPORT, " maximum identifier length");
627 
628  if (!got_index)
629  pg_log(PG_REPORT, " maximum number of indexed columns");
630 
631  if (!got_toast)
632  pg_log(PG_REPORT, " maximum TOAST chunk size");
633 
634  if (!got_large_object &&
635  cluster->controldata.ctrl_ver >= LARGE_OBJECT_SIZE_PG_CONTROL_VER)
636  pg_log(PG_REPORT, " large-object chunk size");
637 
638  if (!got_date_is_int)
639  pg_log(PG_REPORT, " dates/times are integers?");
640 
641  /* value added in Postgres 9.3 */
642  if (!got_data_checksum_version)
643  pg_log(PG_REPORT, " data checksum version");
644 
645  pg_fatal("Cannot continue without required control information, terminating");
646  }
647 }
unsigned int uint32
Definition: c.h:495
static char * lc_collate
Definition: initdb.c:141
static char * lc_time
Definition: initdb.c:145
static char * lc_ctype
Definition: initdb.c:142
static char * lc_messages
Definition: initdb.c:146
static char * lc_numeric
Definition: initdb.c:144
static char * lc_monetary
Definition: initdb.c:143
#define LARGE_OBJECT_SIZE_PG_CONTROL_VER
Definition: pg_upgrade.h:122
#define MULTIXACT_FORMATCHANGE_CAT_VER
Definition: pg_upgrade.h:116
void void unsigned int str2uint(const char *str)
Definition: util.c:352
#define unsetenv(x)
Definition: win32_port.h:538
#define setenv(x, y, z)
Definition: win32_port.h:537

References cluster(), fflush(), GET_MAJOR_VERSION, LARGE_OBJECT_SIZE_PG_CONTROL_VER, lc_collate, lc_ctype, lc_messages, lc_monetary, lc_numeric, lc_time, MAX_STRING, MAXPGPATH, MULTIXACT_FORMATCHANGE_CAT_VER, new_cluster, old_cluster, output, pg_fatal, pg_free(), pg_log(), PG_REPORT, pg_strdup(), pg_strip_crlf(), PG_VERBOSE, setenv, snprintf, str2uint(), strerror, strlcpy(), unsetenv, and wait_result_to_str().

Referenced by check_cluster_compatibility().

◆ get_db_rel_and_slot_infos()

void get_db_rel_and_slot_infos ( ClusterInfo cluster,
bool  live_check 
)

Definition at line 279 of file info.c.

280 {
281  int dbnum;
282 
283  if (cluster->dbarr.dbs != NULL)
285 
288 
289  for (dbnum = 0; dbnum < cluster->dbarr.ndbs; dbnum++)
290  {
291  DbInfo *pDbInfo = &cluster->dbarr.dbs[dbnum];
292 
293  get_rel_infos(cluster, pDbInfo);
294 
295  /*
296  * Retrieve the logical replication slots infos for the old cluster.
297  */
298  if (cluster == &old_cluster)
299  get_old_cluster_logical_slot_infos(pDbInfo, live_check);
300  }
301 
302  if (cluster == &old_cluster)
303  pg_log(PG_VERBOSE, "\nsource databases:");
304  else
305  pg_log(PG_VERBOSE, "\ntarget databases:");
306 
307  if (log_opts.verbose)
308  print_db_infos(&cluster->dbarr);
309 }
static void get_template0_info(ClusterInfo *cluster)
Definition: info.c:317
static void get_old_cluster_logical_slot_infos(DbInfo *dbinfo, bool live_check)
Definition: info.c:634
static void get_db_infos(ClusterInfo *cluster)
Definition: info.c:376
static void free_db_and_rel_infos(DbInfoArr *db_arr)
Definition: info.c:734
static void print_db_infos(DbInfoArr *db_arr)
Definition: info.c:768
static void get_rel_infos(ClusterInfo *cluster, DbInfo *dbinfo)
Definition: info.c:439

References cluster(), free_db_and_rel_infos(), get_db_infos(), get_old_cluster_logical_slot_infos(), get_rel_infos(), get_template0_info(), log_opts, old_cluster, pg_log(), PG_VERBOSE, print_db_infos(), and LogOpts::verbose.

Referenced by check_and_dump_old_cluster(), check_new_cluster(), and create_new_objects().

◆ get_loadable_libraries()

void get_loadable_libraries ( void  )

Definition at line 55 of file function.c.

56 {
57  PGresult **ress;
58  int totaltups;
59  int dbnum;
60  int n_libinfos;
61 
62  ress = (PGresult **) pg_malloc(old_cluster.dbarr.ndbs * sizeof(PGresult *));
63  totaltups = 0;
64 
65  /* Fetch all library names, removing duplicates within each DB */
66  for (dbnum = 0; dbnum < old_cluster.dbarr.ndbs; dbnum++)
67  {
68  DbInfo *active_db = &old_cluster.dbarr.dbs[dbnum];
70 
71  /*
72  * Fetch all libraries containing non-built-in C functions in this DB.
73  */
74  ress[dbnum] = executeQueryOrDie(conn,
75  "SELECT DISTINCT probin "
76  "FROM pg_catalog.pg_proc "
77  "WHERE prolang = %u AND "
78  "probin IS NOT NULL AND "
79  "oid >= %u;",
80  ClanguageId,
82  totaltups += PQntuples(ress[dbnum]);
83 
84  PQfinish(conn);
85  }
86 
87  /*
88  * Allocate memory for required libraries and logical replication output
89  * plugins.
90  */
91  n_libinfos = totaltups + count_old_cluster_logical_slots();
92  os_info.libraries = (LibraryInfo *) pg_malloc(sizeof(LibraryInfo) * n_libinfos);
93  totaltups = 0;
94 
95  for (dbnum = 0; dbnum < old_cluster.dbarr.ndbs; dbnum++)
96  {
97  PGresult *res = ress[dbnum];
98  int ntups;
99  int rowno;
100  LogicalSlotInfoArr *slot_arr = &old_cluster.dbarr.dbs[dbnum].slot_arr;
101 
102  ntups = PQntuples(res);
103  for (rowno = 0; rowno < ntups; rowno++)
104  {
105  char *lib = PQgetvalue(res, rowno, 0);
106 
107  os_info.libraries[totaltups].name = pg_strdup(lib);
108  os_info.libraries[totaltups].dbnum = dbnum;
109 
110  totaltups++;
111  }
112  PQclear(res);
113 
114  /*
115  * Store the names of output plugins as well. There is a possibility
116  * that duplicated plugins are set, but the consumer function
117  * check_loadable_libraries() will avoid checking the same library, so
118  * we do not have to consider their uniqueness here.
119  */
120  for (int slotno = 0; slotno < slot_arr->nslots; slotno++)
121  {
122  if (slot_arr->slots[slotno].invalid)
123  continue;
124 
125  os_info.libraries[totaltups].name = pg_strdup(slot_arr->slots[slotno].plugin);
126  os_info.libraries[totaltups].dbnum = dbnum;
127 
128  totaltups++;
129  }
130  }
131 
132  pg_free(ress);
133 
134  os_info.num_libraries = totaltups;
135 }
int count_old_cluster_logical_slots(void)
Definition: info.c:723
LogicalSlotInfo * slots
Definition: pg_upgrade.h:168
#define FirstNormalObjectId
Definition: transam.h:197

References conn, connectToServer(), count_old_cluster_logical_slots(), DbInfo::db_name, ClusterInfo::dbarr, LibraryInfo::dbnum, DbInfoArr::dbs, executeQueryOrDie(), FirstNormalObjectId, LogicalSlotInfo::invalid, OSInfo::libraries, LibraryInfo::name, DbInfoArr::ndbs, LogicalSlotInfoArr::nslots, OSInfo::num_libraries, old_cluster, os_info, pg_free(), pg_malloc(), pg_strdup(), LogicalSlotInfo::plugin, PQclear(), PQfinish(), PQgetvalue(), PQntuples(), res, DbInfo::slot_arr, and LogicalSlotInfoArr::slots.

Referenced by check_and_dump_old_cluster().

◆ get_major_server_version()

uint32 get_major_server_version ( ClusterInfo cluster)

Definition at line 159 of file server.c.

160 {
161  FILE *version_fd;
162  char ver_filename[MAXPGPATH];
163  int v1 = 0,
164  v2 = 0;
165 
166  snprintf(ver_filename, sizeof(ver_filename), "%s/PG_VERSION",
167  cluster->pgdata);
168  if ((version_fd = fopen(ver_filename, "r")) == NULL)
169  pg_fatal("could not open version file \"%s\": %m", ver_filename);
170 
171  if (fscanf(version_fd, "%63s", cluster->major_version_str) == 0 ||
172  sscanf(cluster->major_version_str, "%d.%d", &v1, &v2) < 1)
173  pg_fatal("could not parse version file \"%s\"", ver_filename);
174 
175  fclose(version_fd);
176 
177  if (v1 < 10)
178  {
179  /* old style, e.g. 9.6.1 */
180  return v1 * 10000 + v2 * 100;
181  }
182  else
183  {
184  /* new style, e.g. 10.1 */
185  return v1 * 10000;
186  }
187 }

References cluster(), MAXPGPATH, pg_fatal, and snprintf.

Referenced by check_data_dir().

◆ get_sock_dir()

void get_sock_dir ( ClusterInfo cluster,
bool  live_check 
)

Definition at line 469 of file option.c.

470 {
471 #if !defined(WIN32)
472  if (!live_check)
473  cluster->sockdir = user_opts.socketdir;
474  else
475  {
476  /*
477  * If we are doing a live check, we will use the old cluster's Unix
478  * domain socket directory so we can connect to the live server.
479  */
480  unsigned short orig_port = cluster->port;
481  char filename[MAXPGPATH],
482  line[MAXPGPATH];
483  FILE *fp;
484  int lineno;
485 
486  snprintf(filename, sizeof(filename), "%s/postmaster.pid",
487  cluster->pgdata);
488  if ((fp = fopen(filename, "r")) == NULL)
489  pg_fatal("could not open file \"%s\": %s",
490  filename, strerror(errno));
491 
492  for (lineno = 1;
494  lineno++)
495  {
496  if (fgets(line, sizeof(line), fp) == NULL)
497  pg_fatal("could not read line %d from file \"%s\": %s",
498  lineno, filename, strerror(errno));
499 
500  /* potentially overwrite user-supplied value */
501  if (lineno == LOCK_FILE_LINE_PORT)
502  sscanf(line, "%hu", &old_cluster.port);
503  if (lineno == LOCK_FILE_LINE_SOCKET_DIR)
504  {
505  /* strip trailing newline and carriage return */
506  cluster->sockdir = pg_strdup(line);
507  (void) pg_strip_crlf(cluster->sockdir);
508  }
509  }
510  fclose(fp);
511 
512  /* warn of port number correction */
513  if (orig_port != DEF_PGUPORT && old_cluster.port != orig_port)
514  pg_log(PG_WARNING, "user-supplied old port number %hu corrected to %hu",
515  orig_port, cluster->port);
516  }
517 #else /* WIN32 */
518  cluster->sockdir = NULL;
519 #endif
520 }
#define Max(x, y)
Definition: c.h:987
#define DEF_PGUPORT
Definition: pg_upgrade.h:20
#define LOCK_FILE_LINE_PORT
Definition: pidfile.h:40
#define LOCK_FILE_LINE_SOCKET_DIR
Definition: pidfile.h:41
char * socketdir
Definition: pg_upgrade.h:325

References cluster(), DEF_PGUPORT, filename, LOCK_FILE_LINE_PORT, LOCK_FILE_LINE_SOCKET_DIR, Max, MAXPGPATH, old_cluster, pg_fatal, pg_log(), pg_strdup(), pg_strip_crlf(), PG_WARNING, ClusterInfo::port, snprintf, UserOpts::socketdir, strerror, and user_opts.

Referenced by main().

◆ get_user_info()

int get_user_info ( char **  user_name_p)

Definition at line 323 of file util.c.

324 {
325  int user_id;
326  const char *user_name;
327  char *errstr;
328 
329 #ifndef WIN32
330  user_id = geteuid();
331 #else
332  user_id = 1;
333 #endif
334 
335  user_name = get_user_name(&errstr);
336  if (!user_name)
337  pg_fatal("%s", errstr);
338 
339  /* make a copy */
340  *user_name_p = pg_strdup(user_name);
341 
342  return user_id;
343 }
const char * get_user_name(char **errstr)
Definition: username.c:31
void pg_fatal(const char *fmt,...)
Definition: util.c:270

References get_user_name(), pg_fatal(), and pg_strdup().

Referenced by parseCommandLine().

◆ init_tablespaces()

void init_tablespaces ( void  )

Definition at line 19 of file tablespace.c.

20 {
22 
25 
26  if (os_info.num_old_tablespaces > 0 &&
28  pg_fatal("Cannot upgrade to/from the same system catalog version when\n"
29  "using tablespaces.");
30 }
static void set_tablespace_directory_suffix(ClusterInfo *cluster)
Definition: tablespace.c:103
static void get_tablespace_paths(void)
Definition: tablespace.c:40

References get_tablespace_paths(), new_cluster, OSInfo::num_old_tablespaces, old_cluster, os_info, pg_fatal, set_tablespace_directory_suffix(), and ClusterInfo::tablespace_suffix.

Referenced by check_and_dump_old_cluster().

◆ issue_warnings_and_set_wal_level()

void issue_warnings_and_set_wal_level ( void  )

Definition at line 263 of file check.c.

264 {
265  /*
266  * We unconditionally start/stop the new server because pg_resetwal -o set
267  * wal_level to 'minimum'. If the user is upgrading standby servers using
268  * the rsync instructions, they will need pg_upgrade to write its final
269  * WAL record showing wal_level as 'replica'.
270  */
272 
273  /* Reindex hash indexes for old < 10.0 */
276 
278 
279  stop_postmaster(false);
280 }
void report_extension_updates(ClusterInfo *cluster)
Definition: version.c:396

References GET_MAJOR_VERSION, ClusterInfo::major_version, new_cluster, old_9_6_invalidate_hash_indexes(), old_cluster, report_extension_updates(), start_postmaster(), and stop_postmaster().

Referenced by main().

◆ linkFile()

void linkFile ( const char *  src,
const char *  dst,
const char *  schemaName,
const char *  relName 
)

Definition at line 150 of file file.c.

152 {
153  if (link(src, dst) < 0)
154  pg_fatal("error while creating link for relation \"%s.%s\" (\"%s\" to \"%s\"): %s",
155  schemaName, relName, src, dst, strerror(errno));
156 }

References link(), pg_fatal, and strerror.

Referenced by transfer_relfile().

◆ old_11_check_for_sql_identifier_data_type_usage()

void old_11_check_for_sql_identifier_data_type_usage ( ClusterInfo cluster)

Definition at line 365 of file version.c.

366 {
367  char output_path[MAXPGPATH];
368 
369  prep_status("Checking for invalid \"sql_identifier\" user columns");
370 
371  snprintf(output_path, sizeof(output_path), "%s/%s",
373  "tables_using_sql_identifier.txt");
374 
375  if (check_for_data_type_usage(cluster, "information_schema.sql_identifier",
376  output_path))
377  {
378  pg_log(PG_REPORT, "fatal");
379  pg_fatal("Your installation contains the \"sql_identifier\" data type in user tables.\n"
380  "The on-disk format for this data type has changed, so this\n"
381  "cluster cannot currently be upgraded. You can\n"
382  "drop the problem columns and restart the upgrade.\n"
383  "A list of the problem columns is in the file:\n"
384  " %s", output_path);
385  }
386  else
387  check_ok();
388 }
bool check_for_data_type_usage(ClusterInfo *cluster, const char *type_name, const char *output_path)
Definition: version.c:153

References LogOpts::basedir, check_for_data_type_usage(), check_ok(), cluster(), log_opts, MAXPGPATH, pg_fatal, pg_log(), PG_REPORT, prep_status(), and snprintf.

Referenced by check_and_dump_old_cluster().

◆ old_9_3_check_for_line_data_type_usage()

void old_9_3_check_for_line_data_type_usage ( ClusterInfo cluster)

Definition at line 180 of file version.c.

181 {
182  char output_path[MAXPGPATH];
183 
184  prep_status("Checking for incompatible \"line\" data type");
185 
186  snprintf(output_path, sizeof(output_path), "%s/%s",
188  "tables_using_line.txt");
189 
190  if (check_for_data_type_usage(cluster, "pg_catalog.line", output_path))
191  {
192  pg_log(PG_REPORT, "fatal");
193  pg_fatal("Your installation contains the \"line\" data type in user tables.\n"
194  "This data type changed its internal and input/output format\n"
195  "between your old and new versions so this\n"
196  "cluster cannot currently be upgraded. You can\n"
197  "drop the problem columns and restart the upgrade.\n"
198  "A list of the problem columns is in the file:\n"
199  " %s", output_path);
200  }
201  else
202  check_ok();
203 }

References LogOpts::basedir, check_for_data_type_usage(), check_ok(), cluster(), log_opts, MAXPGPATH, pg_fatal, pg_log(), PG_REPORT, prep_status(), and snprintf.

Referenced by check_and_dump_old_cluster().

◆ old_9_6_check_for_unknown_data_type_usage()

void old_9_6_check_for_unknown_data_type_usage ( ClusterInfo cluster)

Definition at line 220 of file version.c.

221 {
222  char output_path[MAXPGPATH];
223 
224  prep_status("Checking for invalid \"unknown\" user columns");
225 
226  snprintf(output_path, sizeof(output_path), "%s/%s",
228  "tables_using_unknown.txt");
229 
230  if (check_for_data_type_usage(cluster, "pg_catalog.unknown", output_path))
231  {
232  pg_log(PG_REPORT, "fatal");
233  pg_fatal("Your installation contains the \"unknown\" data type in user tables.\n"
234  "This data type is no longer allowed in tables, so this\n"
235  "cluster cannot currently be upgraded. You can\n"
236  "drop the problem columns and restart the upgrade.\n"
237  "A list of the problem columns is in the file:\n"
238  " %s", output_path);
239  }
240  else
241  check_ok();
242 }

References LogOpts::basedir, check_for_data_type_usage(), check_ok(), cluster(), log_opts, MAXPGPATH, pg_fatal, pg_log(), PG_REPORT, prep_status(), and snprintf.

Referenced by check_and_dump_old_cluster().

◆ old_9_6_invalidate_hash_indexes()

void old_9_6_invalidate_hash_indexes ( ClusterInfo cluster,
bool  check_mode 
)

Definition at line 250 of file version.c.

251 {
252  int dbnum;
253  FILE *script = NULL;
254  bool found = false;
255  char *output_path = "reindex_hash.sql";
256 
257  prep_status("Checking for hash indexes");
258 
259  for (dbnum = 0; dbnum < cluster->dbarr.ndbs; dbnum++)
260  {
261  PGresult *res;
262  bool db_used = false;
263  int ntups;
264  int rowno;
265  int i_nspname,
266  i_relname;
267  DbInfo *active_db = &cluster->dbarr.dbs[dbnum];
268  PGconn *conn = connectToServer(cluster, active_db->db_name);
269 
270  /* find hash indexes */
272  "SELECT n.nspname, c.relname "
273  "FROM pg_catalog.pg_class c, "
274  " pg_catalog.pg_index i, "
275  " pg_catalog.pg_am a, "
276  " pg_catalog.pg_namespace n "
277  "WHERE i.indexrelid = c.oid AND "
278  " c.relam = a.oid AND "
279  " c.relnamespace = n.oid AND "
280  " a.amname = 'hash'"
281  );
282 
283  ntups = PQntuples(res);
284  i_nspname = PQfnumber(res, "nspname");
285  i_relname = PQfnumber(res, "relname");
286  for (rowno = 0; rowno < ntups; rowno++)
287  {
288  found = true;
289  if (!check_mode)
290  {
291  if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL)
292  pg_fatal("could not open file \"%s\": %s", output_path,
293  strerror(errno));
294  if (!db_used)
295  {
296  PQExpBufferData connectbuf;
297 
298  initPQExpBuffer(&connectbuf);
299  appendPsqlMetaConnect(&connectbuf, active_db->db_name);
300  fputs(connectbuf.data, script);
301  termPQExpBuffer(&connectbuf);
302  db_used = true;
303  }
304  fprintf(script, "REINDEX INDEX %s.%s;\n",
305  quote_identifier(PQgetvalue(res, rowno, i_nspname)),
306  quote_identifier(PQgetvalue(res, rowno, i_relname)));
307  }
308  }
309 
310  PQclear(res);
311 
312  if (!check_mode && db_used)
313  {
314  /* mark hash indexes as invalid */
316  "UPDATE pg_catalog.pg_index i "
317  "SET indisvalid = false "
318  "FROM pg_catalog.pg_class c, "
319  " pg_catalog.pg_am a, "
320  " pg_catalog.pg_namespace n "
321  "WHERE i.indexrelid = c.oid AND "
322  " c.relam = a.oid AND "
323  " c.relnamespace = n.oid AND "
324  " a.amname = 'hash'"));
325  }
326 
327  PQfinish(conn);
328  }
329 
330  if (script)
331  fclose(script);
332 
333  if (found)
334  {
335  report_status(PG_WARNING, "warning");
336  if (check_mode)
337  pg_log(PG_WARNING, "\n"
338  "Your installation contains hash indexes. These indexes have different\n"
339  "internal formats between your old and new clusters, so they must be\n"
340  "reindexed with the REINDEX command. After upgrading, you will be given\n"
341  "REINDEX instructions.");
342  else
343  pg_log(PG_WARNING, "\n"
344  "Your installation contains hash indexes. These indexes have different\n"
345  "internal formats between your old and new clusters, so they must be\n"
346  "reindexed with the REINDEX command. The file\n"
347  " %s\n"
348  "when executed by psql by the database superuser will recreate all invalid\n"
349  "indexes; until then, none of these indexes will be used.",
350  output_path);
351  }
352  else
353  check_ok();
354 }
void report_status(eLogType type, const char *fmt,...) pg_attribute_printf(2
const char * quote_identifier(const char *ident)
Definition: ruleutils.c:11975
void appendPsqlMetaConnect(PQExpBuffer buf, const char *dbname)
Definition: string_utils.c:590

References appendPsqlMetaConnect(), check_ok(), cluster(), conn, connectToServer(), PQExpBufferData::data, DbInfo::db_name, executeQueryOrDie(), fopen_priv, fprintf, initPQExpBuffer(), pg_fatal, pg_log(), PG_WARNING, PQclear(), PQfinish(), PQfnumber(), PQgetvalue(), PQntuples(), prep_status(), quote_identifier(), report_status(), res, strerror, and termPQExpBuffer().

Referenced by check_and_dump_old_cluster(), and issue_warnings_and_set_wal_level().

◆ output_check_banner()

void output_check_banner ( bool  live_check)

Definition at line 69 of file check.c.

70 {
71  if (user_opts.check && live_check)
72  {
74  "Performing Consistency Checks on Old Live Server\n"
75  "------------------------------------------------");
76  }
77  else
78  {
80  "Performing Consistency Checks\n"
81  "-----------------------------");
82  }
83 }

References UserOpts::check, pg_log(), PG_REPORT, and user_opts.

Referenced by main().

◆ output_completion_banner()

void output_completion_banner ( char *  deletion_script_file_name)

Definition at line 284 of file check.c.

285 {
286  PQExpBufferData user_specification;
287 
288  initPQExpBuffer(&user_specification);
290  {
291  appendPQExpBufferStr(&user_specification, "-U ");
292  appendShellString(&user_specification, os_info.user);
293  appendPQExpBufferChar(&user_specification, ' ');
294  }
295 
297  "Optimizer statistics are not transferred by pg_upgrade.\n"
298  "Once you start the new server, consider running:\n"
299  " %s/vacuumdb %s--all --analyze-in-stages", new_cluster.bindir, user_specification.data);
300 
301  if (deletion_script_file_name)
303  "Running this script will delete the old cluster's data files:\n"
304  " %s",
305  deletion_script_file_name);
306  else
308  "Could not create a script to delete the old cluster's data files\n"
309  "because user-defined tablespaces or the new cluster's data directory\n"
310  "exist in the old cluster directory. The old cluster's contents must\n"
311  "be deleted manually.");
312 
313  termPQExpBuffer(&user_specification);
314 }
bool user_specified
Definition: pg_upgrade.h:342

References appendPQExpBufferChar(), appendPQExpBufferStr(), appendShellString(), ClusterInfo::bindir, PQExpBufferData::data, initPQExpBuffer(), new_cluster, os_info, pg_log(), PG_REPORT, termPQExpBuffer(), OSInfo::user, and OSInfo::user_specified.

Referenced by main().

◆ parallel_exec_prog()

void parallel_exec_prog ( const char *  log_file,
const char *  opt_log_file,
const char *  fmt,
  ... 
)

◆ parallel_transfer_all_new_dbs()

void void parallel_transfer_all_new_dbs ( DbInfoArr old_db_arr,
DbInfoArr new_db_arr,
char *  old_pgdata,
char *  new_pgdata,
char *  old_tablespace 
)

Definition at line 172 of file parallel.c.

175 {
176 #ifndef WIN32
177  pid_t child;
178 #else
179  HANDLE child;
180  transfer_thread_arg *new_arg;
181 #endif
182 
183  if (user_opts.jobs <= 1)
184  transfer_all_new_dbs(old_db_arr, new_db_arr, old_pgdata, new_pgdata, NULL);
185  else
186  {
187  /* parallel */
188 #ifdef WIN32
189  if (thread_handles == NULL)
190  thread_handles = pg_malloc(user_opts.jobs * sizeof(HANDLE));
191 
192  if (transfer_thread_args == NULL)
193  {
194  int i;
195 
196  transfer_thread_args = pg_malloc(user_opts.jobs * sizeof(transfer_thread_arg *));
197 
198  /*
199  * For safety and performance, we keep the args allocated during
200  * the entire life of the process, and we don't free the args in a
201  * thread different from the one that allocated it.
202  */
203  for (i = 0; i < user_opts.jobs; i++)
204  transfer_thread_args[i] = pg_malloc0(sizeof(transfer_thread_arg));
205  }
206 
207  cur_thread_args = (void **) transfer_thread_args;
208 #endif
209  /* harvest any dead children */
210  while (reap_child(false) == true)
211  ;
212 
213  /* must we wait for a dead child? */
215  reap_child(true);
216 
217  /* set this before we start the job */
218  parallel_jobs++;
219 
220  /* Ensure stdio state is quiesced before forking */
221  fflush(NULL);
222 
223 #ifndef WIN32
224  child = fork();
225  if (child == 0)
226  {
227  transfer_all_new_dbs(old_db_arr, new_db_arr, old_pgdata, new_pgdata,
228  old_tablespace);
229  /* if we take another exit path, it will be non-zero */
230  /* use _exit to skip atexit() functions */
231  _exit(0);
232  }
233  else if (child < 0)
234  /* fork failed */
235  pg_fatal("could not create worker process: %s", strerror(errno));
236 #else
237  /* empty array element are always at the end */
238  new_arg = transfer_thread_args[parallel_jobs - 1];
239 
240  /* Can only pass one pointer into the function, so use a struct */
241  new_arg->old_db_arr = old_db_arr;
242  new_arg->new_db_arr = new_db_arr;
243  pg_free(new_arg->old_pgdata);
244  new_arg->old_pgdata = pg_strdup(old_pgdata);
245  pg_free(new_arg->new_pgdata);
246  new_arg->new_pgdata = pg_strdup(new_pgdata);
247  pg_free(new_arg->old_tablespace);
248  new_arg->old_tablespace = old_tablespace ? pg_strdup(old_tablespace) : NULL;
249 
250  child = (HANDLE) _beginthreadex(NULL, 0, (void *) win32_transfer_all_new_dbs,
251  new_arg, 0, NULL);
252  if (child == 0)
253  pg_fatal("could not create worker thread: %s", strerror(errno));
254 
255  thread_handles[parallel_jobs - 1] = child;
256 #endif
257  }
258 }
static int parallel_jobs
Definition: parallel.c:19
void * pg_malloc0(size_t size)
Definition: fe_memutils.c:53
int i
Definition: isn.c:73
void transfer_all_new_dbs(DbInfoArr *old_db_arr, DbInfoArr *new_db_arr, char *old_pgdata, char *new_pgdata, char *old_tablespace)
Definition: relfilenumber.c:86
int jobs
Definition: pg_upgrade.h:324

References fflush(), i, UserOpts::jobs, parallel_jobs, pg_fatal, pg_free(), pg_malloc(), pg_malloc0(), pg_strdup(), reap_child(), strerror, transfer_all_new_dbs(), and user_opts.

Referenced by transfer_all_new_tablespaces().

◆ parseCommandLine()

void parseCommandLine ( int  argc,
char *  argv[] 
)

Definition at line 39 of file option.c.

40 {
41  static struct option long_options[] = {
42  {"old-datadir", required_argument, NULL, 'd'},
43  {"new-datadir", required_argument, NULL, 'D'},
44  {"old-bindir", required_argument, NULL, 'b'},
45  {"new-bindir", required_argument, NULL, 'B'},
46  {"no-sync", no_argument, NULL, 'N'},
47  {"old-options", required_argument, NULL, 'o'},
48  {"new-options", required_argument, NULL, 'O'},
49  {"old-port", required_argument, NULL, 'p'},
50  {"new-port", required_argument, NULL, 'P'},
51 
52  {"username", required_argument, NULL, 'U'},
53  {"check", no_argument, NULL, 'c'},
54  {"link", no_argument, NULL, 'k'},
55  {"retain", no_argument, NULL, 'r'},
56  {"jobs", required_argument, NULL, 'j'},
57  {"socketdir", required_argument, NULL, 's'},
58  {"verbose", no_argument, NULL, 'v'},
59  {"clone", no_argument, NULL, 1},
60  {"copy", no_argument, NULL, 2},
61  {"sync-method", required_argument, NULL, 3},
62 
63  {NULL, 0, NULL, 0}
64  };
65  int option; /* Command line option */
66  int optindex = 0; /* used by getopt_long */
67  int os_user_effective_id;
68  DataDirSyncMethod unused;
69 
70  user_opts.do_sync = true;
72 
73  os_info.progname = get_progname(argv[0]);
74 
75  /* Process libpq env. variables; load values here for usage() output */
76  old_cluster.port = getenv("PGPORTOLD") ? atoi(getenv("PGPORTOLD")) : DEF_PGUPORT;
77  new_cluster.port = getenv("PGPORTNEW") ? atoi(getenv("PGPORTNEW")) : DEF_PGUPORT;
78 
79  os_user_effective_id = get_user_info(&os_info.user);
80  /* we override just the database user name; we got the OS id above */
81  if (getenv("PGUSER"))
82  {
84  /* must save value, getenv()'s pointer is not stable */
85  os_info.user = pg_strdup(getenv("PGUSER"));
86  }
87 
88  if (argc > 1)
89  {
90  if (strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-?") == 0)
91  {
92  usage();
93  exit(0);
94  }
95  if (strcmp(argv[1], "--version") == 0 || strcmp(argv[1], "-V") == 0)
96  {
97  puts("pg_upgrade (PostgreSQL) " PG_VERSION);
98  exit(0);
99  }
100  }
101 
102  /* Allow help and version to be run as root, so do the test here. */
103  if (os_user_effective_id == 0)
104  pg_fatal("%s: cannot be run as root", os_info.progname);
105 
106  while ((option = getopt_long(argc, argv, "b:B:cd:D:j:kNo:O:p:P:rs:U:v",
107  long_options, &optindex)) != -1)
108  {
109  switch (option)
110  {
111  case 'b':
113  break;
114 
115  case 'B':
117  break;
118 
119  case 'c':
120  user_opts.check = true;
121  break;
122 
123  case 'd':
125  break;
126 
127  case 'D':
129  break;
130 
131  case 'j':
132  user_opts.jobs = atoi(optarg);
133  break;
134 
135  case 'k':
137  break;
138 
139  case 'N':
140  user_opts.do_sync = false;
141  break;
142 
143  case 'o':
144  /* append option? */
145  if (!old_cluster.pgopts)
147  else
148  {
149  char *old_pgopts = old_cluster.pgopts;
150 
151  old_cluster.pgopts = psprintf("%s %s", old_pgopts, optarg);
152  free(old_pgopts);
153  }
154  break;
155 
156  case 'O':
157  /* append option? */
158  if (!new_cluster.pgopts)
160  else
161  {
162  char *new_pgopts = new_cluster.pgopts;
163 
164  new_cluster.pgopts = psprintf("%s %s", new_pgopts, optarg);
165  free(new_pgopts);
166  }
167  break;
168 
169  case 'p':
170  if ((old_cluster.port = atoi(optarg)) <= 0)
171  pg_fatal("invalid old port number");
172  break;
173 
174  case 'P':
175  if ((new_cluster.port = atoi(optarg)) <= 0)
176  pg_fatal("invalid new port number");
177  break;
178 
179  case 'r':
180  log_opts.retain = true;
181  break;
182 
183  case 's':
185  break;
186 
187  case 'U':
190  os_info.user_specified = true;
191  break;
192 
193  case 'v':
194  log_opts.verbose = true;
195  break;
196 
197  case 1:
199  break;
200 
201  case 2:
203  break;
204 
205  case 3:
206  if (!parse_sync_method(optarg, &unused))
207  exit(1);
209  break;
210 
211  default:
212  fprintf(stderr, _("Try \"%s --help\" for more information.\n"),
213  os_info.progname);
214  exit(1);
215  }
216  }
217 
218  if (optind < argc)
219  pg_fatal("too many command-line arguments (first is \"%s\")", argv[optind]);
220 
221  if (!user_opts.sync_method)
222  user_opts.sync_method = pg_strdup("fsync");
223 
224  if (log_opts.verbose)
225  pg_log(PG_REPORT, "Running in verbose mode");
226 
227  log_opts.isatty = isatty(fileno(stdout));
228 
229  /* Turn off read-only mode; add prefix to PGOPTIONS? */
230  if (getenv("PGOPTIONS"))
231  {
232  char *pgoptions = psprintf("%s %s", FIX_DEFAULT_READ_ONLY,
233  getenv("PGOPTIONS"));
234 
235  setenv("PGOPTIONS", pgoptions, 1);
236  pfree(pgoptions);
237  }
238  else
239  setenv("PGOPTIONS", FIX_DEFAULT_READ_ONLY, 1);
240 
241  /* Get values from env if not already set */
242  check_required_directory(&old_cluster.bindir, "PGBINOLD", false,
243  "-b", _("old cluster binaries reside"), false);
244  check_required_directory(&new_cluster.bindir, "PGBINNEW", false,
245  "-B", _("new cluster binaries reside"), true);
246  check_required_directory(&old_cluster.pgdata, "PGDATAOLD", false,
247  "-d", _("old cluster data resides"), false);
248  check_required_directory(&new_cluster.pgdata, "PGDATANEW", false,
249  "-D", _("new cluster data resides"), false);
250  check_required_directory(&user_opts.socketdir, "PGSOCKETDIR", true,
251  "-s", _("sockets will be created"), false);
252 
253 #ifdef WIN32
254 
255  /*
256  * On Windows, initdb --sync-only will fail with a "Permission denied"
257  * error on file pg_upgrade_utility.log if pg_upgrade is run inside the
258  * new cluster directory, so we do a check here.
259  */
260  {
261  char cwd[MAXPGPATH],
262  new_cluster_pgdata[MAXPGPATH];
263 
264  strlcpy(new_cluster_pgdata, new_cluster.pgdata, MAXPGPATH);
265  canonicalize_path(new_cluster_pgdata);
266 
267  if (!getcwd(cwd, MAXPGPATH))
268  pg_fatal("could not determine current directory");
269  canonicalize_path(cwd);
270  if (path_is_prefix_of_path(new_cluster_pgdata, cwd))
271  pg_fatal("cannot run pg_upgrade from inside the new cluster data directory on Windows");
272  }
273 #endif
274 }
DataDirSyncMethod
Definition: file_utils.h:28
int getopt_long(int argc, char *const argv[], const char *optstring, const struct option *longopts, int *longindex)
Definition: getopt_long.c:60
#define no_argument
Definition: getopt_long.h:24
#define required_argument
Definition: getopt_long.h:25
bool parse_sync_method(const char *optarg, DataDirSyncMethod *sync_method)
Definition: option_utils.c:90
PGDLLIMPORT int optind
Definition: getopt.c:50
PGDLLIMPORT char * optarg
Definition: getopt.c:52
int get_user_info(char **user_name_p)
Definition: util.c:323
const char * get_progname(const char *argv0)
Definition: path.c:574
#define FIX_DEFAULT_READ_ONLY
Definition: option.c:27
static void usage(void)
Definition: option.c:278
static void check_required_directory(char **dirpath, const char *envVarName, bool useCwd, const char *cmdLineOption, const char *description, bool missingOk)
Definition: option.c:354
char * pgopts
Definition: pg_upgrade.h:287
const char * progname
Definition: pg_upgrade.h:340
char * sync_method
Definition: pg_upgrade.h:326
bool do_sync
Definition: pg_upgrade.h:322

References _, ClusterInfo::bindir, canonicalize_path(), UserOpts::check, check_required_directory(), DEF_PGUPORT, UserOpts::do_sync, exit(), FIX_DEFAULT_READ_ONLY, fprintf, free, get_progname(), get_user_info(), getopt_long(), LogOpts::isatty, UserOpts::jobs, log_opts, MAXPGPATH, new_cluster, no_argument, old_cluster, optarg, optind, os_info, parse_sync_method(), path_is_prefix_of_path(), pfree(), pg_fatal, pg_free(), pg_log(), PG_REPORT, pg_strdup(), ClusterInfo::pgdata, ClusterInfo::pgopts, ClusterInfo::port, OSInfo::progname, psprintf(), required_argument, LogOpts::retain, setenv, UserOpts::socketdir, generate_unaccent_rules::stdout, strlcpy(), UserOpts::sync_method, UserOpts::transfer_mode, TRANSFER_MODE_CLONE, TRANSFER_MODE_COPY, TRANSFER_MODE_LINK, usage(), OSInfo::user, user_opts, OSInfo::user_specified, and LogOpts::verbose.

Referenced by main().

◆ pg_attribute_noreturn()

void void void pg_attribute_noreturn ( )

◆ pg_fatal()

void void void pg_fatal ( const char *  fmt,
  ... 
)

◆ pg_log()

◆ pid_lock_file_exists()

bool pid_lock_file_exists ( const char *  datadir)

Definition at line 234 of file exec.c.

235 {
236  char path[MAXPGPATH];
237  int fd;
238 
239  snprintf(path, sizeof(path), "%s/postmaster.pid", datadir);
240 
241  if ((fd = open(path, O_RDONLY, 0)) < 0)
242  {
243  /* ENOTDIR means we will throw a more useful error later */
244  if (errno != ENOENT && errno != ENOTDIR)
245  pg_fatal("could not open file \"%s\" for reading: %s",
246  path, strerror(errno));
247 
248  return false;
249  }
250 
251  close(fd);
252  return true;
253 }
char * datadir
static int fd(const char *x, int i)
Definition: preproc-init.c:105

References close, datadir, fd(), MAXPGPATH, pg_fatal, snprintf, and strerror.

Referenced by setup().

◆ prep_status()

◆ prep_status_progress()

void void prep_status_progress ( const char *  fmt,
  ... 
)

◆ quote_identifier()

char* quote_identifier ( const char *  s)

Definition at line 11975 of file ruleutils.c.

11976 {
11977  /*
11978  * Can avoid quoting if ident starts with a lowercase letter or underscore
11979  * and contains only lowercase letters, digits, and underscores, *and* is
11980  * not any SQL keyword. Otherwise, supply quotes.
11981  */
11982  int nquotes = 0;
11983  bool safe;
11984  const char *ptr;
11985  char *result;
11986  char *optr;
11987 
11988  /*
11989  * would like to use <ctype.h> macros here, but they might yield unwanted
11990  * locale-specific results...
11991  */
11992  safe = ((ident[0] >= 'a' && ident[0] <= 'z') || ident[0] == '_');
11993 
11994  for (ptr = ident; *ptr; ptr++)
11995  {
11996  char ch = *ptr;
11997 
11998  if ((ch >= 'a' && ch <= 'z') ||
11999  (ch >= '0' && ch <= '9') ||
12000  (ch == '_'))
12001  {
12002  /* okay */
12003  }
12004  else
12005  {
12006  safe = false;
12007  if (ch == '"')
12008  nquotes++;
12009  }
12010  }
12011 
12013  safe = false;
12014 
12015  if (safe)
12016  {
12017  /*
12018  * Check for keyword. We quote keywords except for unreserved ones.
12019  * (In some cases we could avoid quoting a col_name or type_func_name
12020  * keyword, but it seems much harder than it's worth to tell that.)
12021  *
12022  * Note: ScanKeywordLookup() does case-insensitive comparison, but
12023  * that's fine, since we already know we have all-lower-case.
12024  */
12025  int kwnum = ScanKeywordLookup(ident, &ScanKeywords);
12026 
12027  if (kwnum >= 0 && ScanKeywordCategories[kwnum] != UNRESERVED_KEYWORD)
12028  safe = false;
12029  }
12030 
12031  if (safe)
12032  return ident; /* no change needed */
12033 
12034  result = (char *) palloc(strlen(ident) + nquotes + 2 + 1);
12035 
12036  optr = result;
12037  *optr++ = '"';
12038  for (ptr = ident; *ptr; ptr++)
12039  {
12040  char ch = *ptr;
12041 
12042  if (ch == '"')
12043  *optr++ = '"';
12044  *optr++ = ch;
12045  }
12046  *optr++ = '"';
12047  *optr = '\0';
12048 
12049  return result;
12050 }
const uint8 ScanKeywordCategories[SCANKEYWORDS_NUM_KEYWORDS]
Definition: keywords.c:29
#define ident
Definition: indent_codes.h:47
PGDLLIMPORT const ScanKeywordList ScanKeywords
#define UNRESERVED_KEYWORD
Definition: keywords.h:20
int ScanKeywordLookup(const char *str, const ScanKeywordList *keywords)
Definition: kwlookup.c:38
void * palloc(Size size)
Definition: mcxt.c:1226
bool quote_all_identifiers
Definition: ruleutils.c:324

◆ reap_child()

bool reap_child ( bool  wait_for_child)

Definition at line 278 of file parallel.c.

279 {
280 #ifndef WIN32
281  int work_status;
282  pid_t child;
283 #else
284  int thread_num;
285  DWORD res;
286 #endif
287 
288  if (user_opts.jobs <= 1 || parallel_jobs == 0)
289  return false;
290 
291 #ifndef WIN32
292  child = waitpid(-1, &work_status, wait_for_child ? 0 : WNOHANG);
293  if (child == (pid_t) -1)
294  pg_fatal("%s() failed: %s", "waitpid", strerror(errno));
295  if (child == 0)
296  return false; /* no children, or no dead children */
297  if (work_status != 0)
298  pg_fatal("child process exited abnormally: status %d", work_status);
299 #else
300  /* wait for one to finish */
301  thread_num = WaitForMultipleObjects(parallel_jobs, thread_handles,
302  false, wait_for_child ? INFINITE : 0);
303 
304  if (thread_num == WAIT_TIMEOUT || thread_num == WAIT_FAILED)
305  return false;
306 
307  /* compute thread index in active_threads */
308  thread_num -= WAIT_OBJECT_0;
309 
310  /* get the result */
311  GetExitCodeThread(thread_handles[thread_num], &res);
312  if (res != 0)
313  pg_fatal("child worker exited abnormally: %s", strerror(errno));
314 
315  /* dispose of handle to stop leaks */
316  CloseHandle(thread_handles[thread_num]);
317 
318  /* Move last slot into dead child's position */
319  if (thread_num != parallel_jobs - 1)
320  {
321  void *tmp_args;
322 
323  thread_handles[thread_num] = thread_handles[parallel_jobs - 1];
324 
325  /*
326  * Move last active thread arg struct into the now-dead slot, and the
327  * now-dead slot to the end for reuse by the next thread. Though the
328  * thread struct is in use by another thread, we can safely swap the
329  * struct pointers within the array.
330  */
331  tmp_args = cur_thread_args[thread_num];
332  cur_thread_args[thread_num] = cur_thread_args[parallel_jobs - 1];
333  cur_thread_args[parallel_jobs - 1] = tmp_args;
334  }
335 #endif
336 
337  /* do this after job has been removed */
338  parallel_jobs--;
339 
340  return true;
341 }

References UserOpts::jobs, parallel_jobs, pg_fatal, res, strerror, and user_opts.

Referenced by create_new_objects(), generate_old_dump(), parallel_exec_prog(), parallel_transfer_all_new_dbs(), and transfer_all_new_tablespaces().

◆ report_clusters_compatible()

void report_clusters_compatible ( void  )

Definition at line 244 of file check.c.

245 {
246  if (user_opts.check)
247  {
248  pg_log(PG_REPORT, "\n*Clusters are compatible*");
249  /* stops new cluster */
250  stop_postmaster(false);
251 
253  exit(0);
254  }
255 
256  pg_log(PG_REPORT, "\n"
257  "If pg_upgrade fails after this point, you must re-initdb the\n"
258  "new cluster before continuing.");
259 }
void cleanup_output_dirs(void)
Definition: util.c:63

References UserOpts::check, cleanup_output_dirs(), exit(), pg_log(), PG_REPORT, stop_postmaster(), and user_opts.

Referenced by main().

◆ report_extension_updates()

void report_extension_updates ( ClusterInfo cluster)

Definition at line 396 of file version.c.

397 {
398  int dbnum;
399  FILE *script = NULL;
400  char *output_path = "update_extensions.sql";
401 
402  prep_status("Checking for extension updates");
403 
404  for (dbnum = 0; dbnum < cluster->dbarr.ndbs; dbnum++)
405  {
406  PGresult *res;
407  bool db_used = false;
408  int ntups;
409  int rowno;
410  int i_name;
411  DbInfo *active_db = &cluster->dbarr.dbs[dbnum];
412  PGconn *conn = connectToServer(cluster, active_db->db_name);
413 
414  /* find extensions needing updates */
416  "SELECT name "
417  "FROM pg_available_extensions "
418  "WHERE installed_version != default_version"
419  );
420 
421  ntups = PQntuples(res);
422  i_name = PQfnumber(res, "name");
423  for (rowno = 0; rowno < ntups; rowno++)
424  {
425  if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL)
426  pg_fatal("could not open file \"%s\": %s", output_path,
427  strerror(errno));
428  if (!db_used)
429  {
430  PQExpBufferData connectbuf;
431 
432  initPQExpBuffer(&connectbuf);
433  appendPsqlMetaConnect(&connectbuf, active_db->db_name);
434  fputs(connectbuf.data, script);
435  termPQExpBuffer(&connectbuf);
436  db_used = true;
437  }
438  fprintf(script, "ALTER EXTENSION %s UPDATE;\n",
439  quote_identifier(PQgetvalue(res, rowno, i_name)));
440  }
441 
442  PQclear(res);
443 
444  PQfinish(conn);
445  }
446 
447  if (script)
448  {
449  fclose(script);
450  report_status(PG_REPORT, "notice");
451  pg_log(PG_REPORT, "\n"
452  "Your installation contains extensions that should be updated\n"
453  "with the ALTER EXTENSION command. The file\n"
454  " %s\n"
455  "when executed by psql by the database superuser will update\n"
456  "these extensions.",
457  output_path);
458  }
459  else
460  check_ok();
461 }

References appendPsqlMetaConnect(), check_ok(), cluster(), conn, connectToServer(), PQExpBufferData::data, DbInfo::db_name, executeQueryOrDie(), fopen_priv, fprintf, initPQExpBuffer(), pg_fatal, pg_log(), PG_REPORT, PQclear(), PQfinish(), PQfnumber(), PQgetvalue(), PQntuples(), prep_status(), quote_identifier(), report_status(), res, strerror, and termPQExpBuffer().

Referenced by issue_warnings_and_set_wal_level().

◆ report_status()

void report_status ( eLogType  type,
const char *  fmt,
  ... 
)

◆ rewriteVisibilityMap()

void rewriteVisibilityMap ( const char *  fromfile,
const char *  tofile,
const char *  schemaName,
const char *  relName 
)

Definition at line 176 of file file.c.

178 {
179  int src_fd;
180  int dst_fd;
181  PGIOAlignedBlock buffer;
182  PGIOAlignedBlock new_vmbuf;
183  ssize_t totalBytesRead = 0;
184  ssize_t src_filesize;
185  int rewriteVmBytesPerPage;
186  BlockNumber new_blkno = 0;
187  struct stat statbuf;
188 
189  /* Compute number of old-format bytes per new page */
190  rewriteVmBytesPerPage = (BLCKSZ - SizeOfPageHeaderData) / 2;
191 
192  if ((src_fd = open(fromfile, O_RDONLY | PG_BINARY, 0)) < 0)
193  pg_fatal("error while copying relation \"%s.%s\": could not open file \"%s\": %s",
194  schemaName, relName, fromfile, strerror(errno));
195 
196  if (fstat(src_fd, &statbuf) != 0)
197  pg_fatal("error while copying relation \"%s.%s\": could not stat file \"%s\": %s",
198  schemaName, relName, fromfile, strerror(errno));
199 
200  if ((dst_fd = open(tofile, O_RDWR | O_CREAT | O_EXCL | PG_BINARY,
201  pg_file_create_mode)) < 0)
202  pg_fatal("error while copying relation \"%s.%s\": could not create file \"%s\": %s",
203  schemaName, relName, tofile, strerror(errno));
204 
205  /* Save old file size */
206  src_filesize = statbuf.st_size;
207 
208  /*
209  * Turn each visibility map page into 2 pages one by one. Each new page
210  * has the same page header as the old one. If the last section of the
211  * last page is empty, we skip it, mostly to avoid turning one-page
212  * visibility maps for small relations into two pages needlessly.
213  */
214  while (totalBytesRead < src_filesize)
215  {
216  ssize_t bytesRead;
217  char *old_cur;
218  char *old_break;
219  char *old_blkend;
220  PageHeaderData pageheader;
221  bool old_lastblk;
222 
223  if ((bytesRead = read(src_fd, buffer.data, BLCKSZ)) != BLCKSZ)
224  {
225  if (bytesRead < 0)
226  pg_fatal("error while copying relation \"%s.%s\": could not read file \"%s\": %s",
227  schemaName, relName, fromfile, strerror(errno));
228  else
229  pg_fatal("error while copying relation \"%s.%s\": partial page found in file \"%s\"",
230  schemaName, relName, fromfile);
231  }
232 
233  totalBytesRead += BLCKSZ;
234  old_lastblk = (totalBytesRead == src_filesize);
235 
236  /* Save the page header data */
237  memcpy(&pageheader, buffer.data, SizeOfPageHeaderData);
238 
239  /*
240  * These old_* variables point to old visibility map page. old_cur
241  * points to current position on old page. old_blkend points to end of
242  * old block. old_break is the end+1 position on the old page for the
243  * data that will be transferred to the current new page.
244  */
245  old_cur = buffer.data + SizeOfPageHeaderData;
246  old_blkend = buffer.data + bytesRead;
247  old_break = old_cur + rewriteVmBytesPerPage;
248 
249  while (old_break <= old_blkend)
250  {
251  char *new_cur;
252  bool empty = true;
253  bool old_lastpart;
254 
255  /* First, copy old page header to new page */
256  memcpy(new_vmbuf.data, &pageheader, SizeOfPageHeaderData);
257 
258  /* Rewriting the last part of the last old page? */
259  old_lastpart = old_lastblk && (old_break == old_blkend);
260 
261  new_cur = new_vmbuf.data + SizeOfPageHeaderData;
262 
263  /* Process old page bytes one by one, and turn it into new page. */
264  while (old_cur < old_break)
265  {
266  uint8 byte = *(uint8 *) old_cur;
267  uint16 new_vmbits = 0;
268  int i;
269 
270  /* Generate new format bits while keeping old information */
271  for (i = 0; i < BITS_PER_BYTE; i++)
272  {
273  if (byte & (1 << i))
274  {
275  empty = false;
276  new_vmbits |=
278  }
279  }
280 
281  /* Copy new visibility map bytes to new-format page */
282  new_cur[0] = (char) (new_vmbits & 0xFF);
283  new_cur[1] = (char) (new_vmbits >> 8);
284 
285  old_cur++;
286  new_cur += BITS_PER_HEAPBLOCK;
287  }
288 
289  /* If the last part of the last page is empty, skip writing it */
290  if (old_lastpart && empty)
291  break;
292 
293  /* Set new checksum for visibility map page, if enabled */
295  ((PageHeader) new_vmbuf.data)->pd_checksum =
296  pg_checksum_page(new_vmbuf.data, new_blkno);
297 
298  errno = 0;
299  if (write(dst_fd, new_vmbuf.data, BLCKSZ) != BLCKSZ)
300  {
301  /* if write didn't set errno, assume problem is no disk space */
302  if (errno == 0)
303  errno = ENOSPC;
304  pg_fatal("error while copying relation \"%s.%s\": could not write file \"%s\": %s",
305  schemaName, relName, tofile, strerror(errno));
306  }
307 
308  /* Advance for next new page */
309  old_break += rewriteVmBytesPerPage;
310  new_blkno++;
311  }
312  }
313 
314  /* Clean up */
315  close(dst_fd);
316  close(src_fd);
317 }
uint32 BlockNumber
Definition: block.h:31
PageHeaderData * PageHeader
Definition: bufpage.h:170
#define SizeOfPageHeaderData
Definition: bufpage.h:213
unsigned short uint16
Definition: c.h:494
unsigned char uint8
Definition: c.h:493
uint16 pg_checksum_page(char *page, BlockNumber blkno)
#define BITS_PER_BYTE
char data[BLCKSZ]
Definition: c.h:1150
#define BITS_PER_HEAPBLOCK
#define VISIBILITYMAP_ALL_VISIBLE
#define fstat
Definition: win32_port.h:283

References BITS_PER_BYTE, BITS_PER_HEAPBLOCK, close, ClusterInfo::controldata, PGIOAlignedBlock::data, ControlData::data_checksum_version, fstat, i, new_cluster, PG_BINARY, pg_checksum_page(), pg_fatal, pg_file_create_mode, read, SizeOfPageHeaderData, stat::st_size, strerror, VISIBILITYMAP_ALL_VISIBLE, and write.

Referenced by transfer_relfile().

◆ start_postmaster()

bool start_postmaster ( ClusterInfo cluster,
bool  report_and_exit_on_error 
)

Definition at line 198 of file server.c.

199 {
200  char cmd[MAXPGPATH * 4 + 1000];
201  PGconn *conn;
202  bool pg_ctl_return = false;
203  char socket_string[MAXPGPATH + 200];
204  PQExpBufferData pgoptions;
205 
206  static bool exit_hook_registered = false;
207 
208  if (!exit_hook_registered)
209  {
210  atexit(stop_postmaster_atexit);
211  exit_hook_registered = true;
212  }
213 
214  socket_string[0] = '\0';
215 
216 #if !defined(WIN32)
217  /* prevent TCP/IP connections, restrict socket access */
218  strcat(socket_string,
219  " -c listen_addresses='' -c unix_socket_permissions=0700");
220 
221  /* Have a sockdir? Tell the postmaster. */
222  if (cluster->sockdir)
223  snprintf(socket_string + strlen(socket_string),
224  sizeof(socket_string) - strlen(socket_string),
225  " -c %s='%s'",
226  (GET_MAJOR_VERSION(cluster->major_version) <= 902) ?
227  "unix_socket_directory" : "unix_socket_directories",
228  cluster->sockdir);
229 #endif
230 
231  initPQExpBuffer(&pgoptions);
232 
233  /*
234  * Construct a parameter string which is passed to the server process.
235  *
236  * Turn off durability requirements to improve object creation speed, and
237  * we only modify the new cluster, so only use it there. If there is a
238  * crash, the new cluster has to be recreated anyway. fsync=off is a big
239  * win on ext4.
240  */
241  if (cluster == &new_cluster)
242  appendPQExpBufferStr(&pgoptions, " -c synchronous_commit=off -c fsync=off -c full_page_writes=off");
243 
244  /*
245  * Use max_slot_wal_keep_size as -1 to prevent the WAL removal by the
246  * checkpointer process. If WALs required by logical replication slots
247  * are removed, the slots are unusable. This setting prevents the
248  * invalidation of slots during the upgrade. We set this option when
249  * cluster is PG17 or later because logical replication slots can only be
250  * migrated since then. Besides, max_slot_wal_keep_size is added in PG13.
251  *
252  * Use max_logical_replication_workers as 0 to prevent a startup of the
253  * logical replication launcher while upgrading because it may start apply
254  * workers that could start receiving changes from the publisher before
255  * the physical files are put in place, causing corruption on the new
256  * cluster upgrading to. Like the previous parameter, this is set only
257  * when a cluster is PG17 or later as logical slots can only be migrated
258  * since this version.
259  */
260  if (GET_MAJOR_VERSION(cluster->major_version) >= 1700)
261  appendPQExpBufferStr(&pgoptions, " -c max_slot_wal_keep_size=-1 -c max_logical_replication_workers=0");
262 
263  /* Use -b to disable autovacuum. */
264  snprintf(cmd, sizeof(cmd),
265  "\"%s/pg_ctl\" -w -l \"%s/%s\" -D \"%s\" -o \"-p %d -b%s %s%s\" start",
266  cluster->bindir,
268  SERVER_LOG_FILE, cluster->pgconfig, cluster->port,
269  pgoptions.data,
270  cluster->pgopts ? cluster->pgopts : "", socket_string);
271 
272  termPQExpBuffer(&pgoptions);
273 
274  /*
275  * Don't throw an error right away, let connecting throw the error because
276  * it might supply a reason for the failure.
277  */
278  pg_ctl_return = exec_prog(SERVER_START_LOG_FILE,
279  /* pass both file names if they differ */
280  (strcmp(SERVER_LOG_FILE,
281  SERVER_START_LOG_FILE) != 0) ?
282  SERVER_LOG_FILE : NULL,
283  report_and_exit_on_error, false,
284  "%s", cmd);
285 
286  /* Did it fail and we are just testing if the server could be started? */
287  if (!pg_ctl_return && !report_and_exit_on_error)
288  return false;
289 
290  /*
291  * We set this here to make sure atexit() shuts down the server, but only
292  * if we started the server successfully. We do it before checking for
293  * connectivity in case the server started but there is a connectivity
294  * failure. If pg_ctl did not return success, we will exit below.
295  *
296  * Pre-9.1 servers do not have PQping(), so we could be leaving the server
297  * running if authentication was misconfigured, so someday we might went
298  * to be more aggressive about doing server shutdowns even if pg_ctl
299  * fails, but now (2013-08-14) it seems prudent to be cautious. We don't
300  * want to shutdown a server that might have been accidentally started
301  * during the upgrade.
302  */
303  if (pg_ctl_return)
305 
306  /*
307  * pg_ctl -w might have failed because the server couldn't be started, or
308  * there might have been a connection problem in _checking_ if the server
309  * has started. Therefore, even if pg_ctl failed, we continue and test
310  * for connectivity in case we get a connection reason for the failure.
311  */
312  if ((conn = get_db_conn(cluster, "template1")) == NULL ||
314  {
315  pg_log(PG_REPORT, "\n%s", PQerrorMessage(conn));
316  if (conn)
317  PQfinish(conn);
318  if (cluster == &old_cluster)
319  pg_fatal("could not connect to source postmaster started with the command:\n"
320  "%s",
321  cmd);
322  else
323  pg_fatal("could not connect to target postmaster started with the command:\n"
324  "%s",
325  cmd);
326  }
327  PQfinish(conn);
328 
329  /*
330  * If pg_ctl failed, and the connection didn't fail, and
331  * report_and_exit_on_error is enabled, fail now. This could happen if
332  * the server was already running.
333  */
334  if (!pg_ctl_return)
335  {
336  if (cluster == &old_cluster)
337  pg_fatal("pg_ctl failed to start the source server, or connection failed");
338  else
339  pg_fatal("pg_ctl failed to start the target server, or connection failed");
340  }
341 
342  return true;
343 }
#define SERVER_START_LOG_FILE
Definition: pg_upgrade.h:67
#define SERVER_LOG_FILE
Definition: pg_upgrade.h:44
static void stop_postmaster_atexit(void)
Definition: server.c:191
char * logdir
Definition: pg_upgrade.h:310
ClusterInfo * running_cluster
Definition: pg_upgrade.h:347

References appendPQExpBufferStr(), cluster(), conn, CONNECTION_OK, PQExpBufferData::data, exec_prog(), get_db_conn(), GET_MAJOR_VERSION, initPQExpBuffer(), log_opts, LogOpts::logdir, MAXPGPATH, new_cluster, old_cluster, os_info, pg_fatal, pg_log(), PG_REPORT, PQerrorMessage(), PQfinish(), PQstatus(), OSInfo::running_cluster, SERVER_LOG_FILE, SERVER_START_LOG_FILE, snprintf, stop_postmaster_atexit(), and termPQExpBuffer().

◆ stop_postmaster()

void stop_postmaster ( bool  in_atexit)

Definition at line 347 of file server.c.

348 {
350 
352  cluster = &old_cluster;
353  else if (os_info.running_cluster == &new_cluster)
354  cluster = &new_cluster;
355  else
356  return; /* no cluster running */
357 
358  exec_prog(SERVER_STOP_LOG_FILE, NULL, !in_atexit, !in_atexit,
359  "\"%s/pg_ctl\" -w -D \"%s\" -o \"%s\" %s stop",
360  cluster->bindir, cluster->pgconfig,
361  cluster->pgopts ? cluster->pgopts : "",
362  in_atexit ? "-m fast" : "-m smart");
363 
364  os_info.running_cluster = NULL;
365 }
#define SERVER_STOP_LOG_FILE
Definition: pg_upgrade.h:68

References cluster(), exec_prog(), new_cluster, old_cluster, os_info, OSInfo::running_cluster, and SERVER_STOP_LOG_FILE.

Referenced by check_and_dump_old_cluster(), issue_warnings_and_set_wal_level(), main(), report_clusters_compatible(), setup(), and stop_postmaster_atexit().

◆ str2uint()

void void unsigned int str2uint ( const char *  str)

Definition at line 352 of file util.c.

353 {
354  return strtoul(str, NULL, 10);
355 }

References generate_unaccent_rules::str.

Referenced by get_control_data().

◆ transfer_all_new_dbs()

void transfer_all_new_dbs ( DbInfoArr old_db_arr,
DbInfoArr new_db_arr,
char *  old_pgdata,
char *  new_pgdata,
char *  old_tablespace 
)

Definition at line 86 of file relfilenumber.c.

88 {
89  int old_dbnum,
90  new_dbnum;
91 
92  /* Scan the old cluster databases and transfer their files */
93  for (old_dbnum = new_dbnum = 0;
94  old_dbnum < old_db_arr->ndbs;
95  old_dbnum++, new_dbnum++)
96  {
97  DbInfo *old_db = &old_db_arr->dbs[old_dbnum],
98  *new_db = NULL;
99  FileNameMap *mappings;
100  int n_maps;
101 
102  /*
103  * Advance past any databases that exist in the new cluster but not in
104  * the old, e.g. "postgres". (The user might have removed the
105  * 'postgres' database from the old cluster.)
106  */
107  for (; new_dbnum < new_db_arr->ndbs; new_dbnum++)
108  {
109  new_db = &new_db_arr->dbs[new_dbnum];
110  if (strcmp(old_db->db_name, new_db->db_name) == 0)
111  break;
112  }
113 
114  if (new_dbnum >= new_db_arr->ndbs)
115  pg_fatal("old database \"%s\" not found in the new cluster",
116  old_db->db_name);
117 
118  mappings = gen_db_file_maps(old_db, new_db, &n_maps, old_pgdata,
119  new_pgdata);
120  if (n_maps)
121  {
122  transfer_single_new_db(mappings, n_maps, old_tablespace);
123  }
124  /* We allocate something even for n_maps == 0 */
125  pg_free(mappings);
126  }
127 }
FileNameMap * gen_db_file_maps(DbInfo *old_db, DbInfo *new_db, int *nmaps, const char *old_pgdata, const char *new_pgdata)
Definition: info.c:42
static void transfer_single_new_db(FileNameMap *maps, int size, char *old_tablespace)

References DbInfo::db_name, DbInfoArr::dbs, gen_db_file_maps(), DbInfoArr::ndbs, pg_fatal, pg_free(), and transfer_single_new_db().

Referenced by parallel_transfer_all_new_dbs().

◆ transfer_all_new_tablespaces()

void transfer_all_new_tablespaces ( DbInfoArr old_db_arr,
DbInfoArr new_db_arr,
char *  old_pgdata,
char *  new_pgdata 
)

Definition at line 29 of file relfilenumber.c.

31 {
32  switch (user_opts.transfer_mode)
33  {
35  prep_status_progress("Cloning user relation files");
36  break;
37  case TRANSFER_MODE_COPY:
38  prep_status_progress("Copying user relation files");
39  break;
40  case TRANSFER_MODE_LINK:
41  prep_status_progress("Linking user relation files");
42  break;
43  }
44 
45  /*
46  * Transferring files by tablespace is tricky because a single database
47  * can use multiple tablespaces. For non-parallel mode, we just pass a
48  * NULL tablespace path, which matches all tablespaces. In parallel mode,
49  * we pass the default tablespace and all user-created tablespaces and let
50  * those operations happen in parallel.
51  */
52  if (user_opts.jobs <= 1)
53  parallel_transfer_all_new_dbs(old_db_arr, new_db_arr, old_pgdata,
54  new_pgdata, NULL);
55  else
56  {
57  int tblnum;
58 
59  /* transfer default tablespace */
60  parallel_transfer_all_new_dbs(old_db_arr, new_db_arr, old_pgdata,
61  new_pgdata, old_pgdata);
62 
63  for (tblnum = 0; tblnum < os_info.num_old_tablespaces; tblnum++)
65  new_db_arr,
66  old_pgdata,
67  new_pgdata,
68  os_info.old_tablespaces[tblnum]);
69  /* reap all children */
70  while (reap_child(true) == true)
71  ;
72  }
73 
75  check_ok();
76 }
void parallel_transfer_all_new_dbs(DbInfoArr *old_db_arr, DbInfoArr *new_db_arr, char *old_pgdata, char *new_pgdata, char *old_tablespace)
Definition: parallel.c:172

References check_ok(), end_progress_output(), UserOpts::jobs, OSInfo::num_old_tablespaces, OSInfo::old_tablespaces, os_info, parallel_transfer_all_new_dbs(), prep_status_progress(), reap_child(), UserOpts::transfer_mode, TRANSFER_MODE_CLONE, TRANSFER_MODE_COPY, TRANSFER_MODE_LINK, and user_opts.

Referenced by main().

◆ verify_directories()

bool void verify_directories ( void  )

Definition at line 265 of file exec.c.

266 {
267 #ifndef WIN32
268  if (access(".", R_OK | W_OK | X_OK) != 0)
269 #else
270  if (win32_check_directory_write_permissions() != 0)
271 #endif
272  pg_fatal("You must have read and write access in the current directory.");
273 
274  check_bin_dir(&old_cluster, false);
276  check_bin_dir(&new_cluster, true);
278 }
static void check_bin_dir(ClusterInfo *cluster, bool check_versions)
Definition: exec.c:385
static void check_data_dir(ClusterInfo *cluster)
Definition: exec.c:343
short access
Definition: preproc-type.c:36

References check_bin_dir(), check_data_dir(), new_cluster, old_cluster, and pg_fatal.

Referenced by setup().

Variable Documentation

◆ log_opts

◆ new_cluster

ClusterInfo new_cluster

Definition at line 357 of file pg_upgrade.h.

◆ old_cluster

◆ os_info

◆ output_files

char* output_files[]
extern

Definition at line 68 of file pg_upgrade.c.

Referenced by make_outputdirs().

◆ user_opts