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 "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  FileNameMap
 
struct  DbInfo
 
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   60
 
#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)
 

Typedefs

typedef long pgpid_t
 

Enumerations

enum  transferMode { TRANSFER_MODE_CLONE , TRANSFER_MODE_COPY , TRANSFER_MODE_LINK }
 
enum  eLogType {
  PG_VERBOSE , PG_STATUS , 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_file, 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_and_rel_infos (ClusterInfo *cluster)
 
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 38 of file pg_upgrade.h.

◆ DB_DUMP_FILE_MASK

#define DB_DUMP_FILE_MASK   "pg_upgrade_dump_%u.custom"

Definition at line 30 of file pg_upgrade.h.

◆ DB_DUMP_LOG_FILE_MASK

#define DB_DUMP_LOG_FILE_MASK   "pg_upgrade_dump_%u.log"

Definition at line 42 of file pg_upgrade.h.

◆ DEF_PGUPORT

#define DEF_PGUPORT   50432

Definition at line 19 of file pg_upgrade.h.

◆ DUMP_OUTPUTDIR

#define DUMP_OUTPUTDIR   "dump"

Definition at line 40 of file pg_upgrade.h.

◆ ECHO_BLANK

#define ECHO_BLANK   ""

Definition at line 88 of file pg_upgrade.h.

◆ ECHO_QUOTE

#define ECHO_QUOTE   "'"

Definition at line 87 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 361 of file pg_upgrade.h.

◆ fopen_priv

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

Definition at line 383 of file pg_upgrade.h.

◆ GET_MAJOR_VERSION

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

Definition at line 26 of file pg_upgrade.h.

◆ GLOBALS_DUMP_FILE

#define GLOBALS_DUMP_FILE   "pg_upgrade_dump_globals.sql"

Definition at line 29 of file pg_upgrade.h.

◆ INTERNAL_LOG_FILE

#define INTERNAL_LOG_FILE   "pg_upgrade_internal.log"

Definition at line 45 of file pg_upgrade.h.

◆ JSONB_FORMAT_CHANGE_CAT_VER

#define JSONB_FORMAT_CHANGE_CAT_VER   201409291

Definition at line 126 of file pg_upgrade.h.

◆ LARGE_OBJECT_SIZE_PG_CONTROL_VER

#define LARGE_OBJECT_SIZE_PG_CONTROL_VER   942

Definition at line 121 of file pg_upgrade.h.

◆ LOG_OUTPUTDIR

#define LOG_OUTPUTDIR   "log"

Definition at line 39 of file pg_upgrade.h.

◆ MAX_STRING

#define MAX_STRING   1024

Definition at line 21 of file pg_upgrade.h.

◆ MESSAGE_WIDTH

#define MESSAGE_WIDTH   60

Definition at line 24 of file pg_upgrade.h.

◆ MULTIXACT_FORMATCHANGE_CAT_VER

#define MULTIXACT_FORMATCHANGE_CAT_VER   201301231

Definition at line 115 of file pg_upgrade.h.

◆ PATH_QUOTE

#define PATH_QUOTE   '\''

Definition at line 82 of file pg_upgrade.h.

◆ PATH_SEPARATOR

#define PATH_SEPARATOR   '/'

Definition at line 81 of file pg_upgrade.h.

◆ pg_mv_file

#define pg_mv_file   rename

Definition at line 80 of file pg_upgrade.h.

◆ QUERY_ALLOC

#define QUERY_ALLOC   8192

Definition at line 22 of file pg_upgrade.h.

◆ RM_CMD

#define RM_CMD   "rm -f"

Definition at line 83 of file pg_upgrade.h.

◆ RMDIR_CMD

#define RMDIR_CMD   "rm -rf"

Definition at line 84 of file pg_upgrade.h.

◆ SCRIPT_EXT

#define SCRIPT_EXT   "sh"

Definition at line 86 of file pg_upgrade.h.

◆ SCRIPT_PREFIX

#define SCRIPT_PREFIX   "./"

Definition at line 85 of file pg_upgrade.h.

◆ SERVER_LOG_FILE

#define SERVER_LOG_FILE   "pg_upgrade_server.log"

Definition at line 43 of file pg_upgrade.h.

◆ SERVER_START_LOG_FILE

#define SERVER_START_LOG_FILE   SERVER_LOG_FILE

Definition at line 66 of file pg_upgrade.h.

◆ SERVER_STOP_LOG_FILE

#define SERVER_STOP_LOG_FILE   SERVER_LOG_FILE

Definition at line 67 of file pg_upgrade.h.

◆ UTILITY_LOG_FILE

#define UTILITY_LOG_FILE   "pg_upgrade_utility.log"

Definition at line 44 of file pg_upgrade.h.

◆ VISIBILITY_MAP_FROZEN_BIT_CAT_VER

#define VISIBILITY_MAP_FROZEN_BIT_CAT_VER   201603011

Definition at line 107 of file pg_upgrade.h.

Typedef Documentation

◆ pgpid_t

typedef long pgpid_t

Definition at line 245 of file pg_upgrade.h.

Enumeration Type Documentation

◆ eLogType

enum eLogType
Enumerator
PG_VERBOSE 
PG_STATUS 
PG_REPORT 
PG_WARNING 
PG_FATAL 

Definition at line 235 of file pg_upgrade.h.

236 {
237  PG_VERBOSE,
238  PG_STATUS,
239  PG_REPORT,
240  PG_WARNING,
241  PG_FATAL
242 } eLogType;
eLogType
Definition: pg_upgrade.h:236
@ PG_FATAL
Definition: pg_upgrade.h:241
@ PG_STATUS
Definition: pg_upgrade.h:238
@ PG_WARNING
Definition: pg_upgrade.h:240
@ PG_VERBOSE
Definition: pg_upgrade.h:237
@ PG_REPORT
Definition: pg_upgrade.h:239

◆ transferMode

Enumerator
TRANSFER_MODE_CLONE 
TRANSFER_MODE_COPY 
TRANSFER_MODE_LINK 

Definition at line 225 of file pg_upgrade.h.

226 {
230 } transferMode;
transferMode
Definition: pg_upgrade.h:226
@ TRANSFER_MODE_COPY
Definition: pg_upgrade.h:228
@ TRANSFER_MODE_LINK
Definition: pg_upgrade.h:229
@ TRANSFER_MODE_CLONE
Definition: pg_upgrade.h:227

Function Documentation

◆ adjust_data_dir()

void adjust_data_dir ( ClusterInfo cluster)

Definition at line 380 of file option.c.

381 {
382  char filename[MAXPGPATH];
383  char cmd[MAXPGPATH],
384  cmd_output[MAX_STRING];
385  FILE *fp,
386  *output;
387 
388  /* Initially assume config dir and data dir are the same */
389  cluster->pgconfig = pg_strdup(cluster->pgdata);
390 
391  /* If there is no postgresql.conf, it can't be a config-only dir */
392  snprintf(filename, sizeof(filename), "%s/postgresql.conf", cluster->pgconfig);
393  if ((fp = fopen(filename, "r")) == NULL)
394  return;
395  fclose(fp);
396 
397  /* If PG_VERSION exists, it can't be a config-only dir */
398  snprintf(filename, sizeof(filename), "%s/PG_VERSION", cluster->pgconfig);
399  if ((fp = fopen(filename, "r")) != NULL)
400  {
401  fclose(fp);
402  return;
403  }
404 
405  /* Must be a configuration directory, so find the real data directory. */
406 
407  if (cluster == &old_cluster)
408  prep_status("Finding the real data directory for the source cluster");
409  else
410  prep_status("Finding the real data directory for the target cluster");
411 
412  /*
413  * We don't have a data directory yet, so we can't check the PG version,
414  * so this might fail --- only works for PG 9.2+. If this fails,
415  * pg_upgrade will fail anyway because the data files will not be found.
416  */
417  snprintf(cmd, sizeof(cmd), "\"%s/postgres\" -D \"%s\" -C data_directory",
418  cluster->bindir, cluster->pgconfig);
419 
420  if ((output = popen(cmd, "r")) == NULL ||
421  fgets(cmd_output, sizeof(cmd_output), output) == NULL)
422  pg_fatal("could not get data directory using %s: %s\n",
423  cmd, strerror(errno));
424 
425  pclose(output);
426 
427  /* strip trailing newline and carriage return */
428  (void) pg_strip_crlf(cmd_output);
429 
430  cluster->pgdata = pg_strdup(cmd_output);
431 
432  check_ok();
433 }
void cluster(ParseState *pstate, ClusterStmt *stmt, bool isTopLevel)
Definition: cluster.c:108
char * pg_strdup(const char *in)
Definition: fe_memutils.c:85
static void check_ok(void)
Definition: initdb.c:1908
#define pg_fatal(...)
#define MAXPGPATH
static char * filename
Definition: pg_dumpall.c:94
static void output(uint64 loop_count)
ClusterInfo old_cluster
Definition: pg_upgrade.c:62
#define MAX_STRING
Definition: pg_upgrade.h:21
void prep_status(const char *fmt,...) pg_attribute_printf(1
#define strerror
Definition: port.h:238
#define snprintf
Definition: port.h:225
int pg_strip_crlf(char *str)
Definition: string.c:121

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

◆ check_and_dump_old_cluster()

void check_and_dump_old_cluster ( bool  live_check)

Definition at line 84 of file check.c.

85 {
86  /* -- OLD -- */
87 
88  if (!live_check)
90 
91  /* Extract a list of databases and tables from the old cluster */
93 
95 
97 
98 
99  /*
100  * Check for various failure cases
101  */
108 
109  /*
110  * PG 14 changed the function signature of encoding conversion functions.
111  * Conversions from older versions cannot be upgraded automatically
112  * because the user-defined functions used by the encoding conversions
113  * need to be changed to match the new signature.
114  */
117 
118  /*
119  * Pre-PG 14 allowed user defined postfix operators, which are not
120  * supported anymore. Verify there are none, iff applicable.
121  */
124 
125  /*
126  * Pre-PG 12 allowed tables to be declared WITH OIDS, which is not
127  * supported anymore. Verify there are none, iff applicable.
128  */
131 
132  /*
133  * PG 12 changed the 'sql_identifier' type storage to be based on name,
134  * not varchar, which breaks on-disk format for existing data. So we need
135  * to prevent upgrade when used in user objects (tables, indexes, ...).
136  */
139 
140  /*
141  * Pre-PG 10 allowed tables with 'unknown' type columns and non WAL logged
142  * hash indexes
143  */
145  {
147  if (user_opts.check)
149  }
150 
151  /* 9.5 and below should not have roles starting with pg_ */
154 
158 
159  /* Pre-PG 9.4 had a different 'line' data type internal format */
162 
163  /*
164  * While not a check option, we do this now because this is the only time
165  * the old server is running.
166  */
167  if (!user_opts.check)
169 
170  if (!live_check)
171  stop_postmaster(false);
172 }
static void check_for_tables_with_oids(ClusterInfo *cluster)
Definition: check.c:1006
static void check_for_pg_role_prefix(ClusterInfo *cluster)
Definition: check.c:1231
static void check_for_composite_data_type_usage(ClusterInfo *cluster)
Definition: check.c:1090
static void check_is_install_user(ClusterInfo *cluster)
Definition: check.c:638
static void check_for_isn_and_int8_passing_mismatch(ClusterInfo *cluster)
Definition: check.c:820
static void check_for_user_defined_postfix_ops(ClusterInfo *cluster)
Definition: check.c:906
static void check_for_prepared_transactions(ClusterInfo *cluster)
Definition: check.c:785
static void check_proper_datallowconn(ClusterInfo *cluster)
Definition: check.c:696
static void check_for_user_defined_encoding_conversions(ClusterInfo *cluster)
Definition: check.c:1262
static void check_for_jsonb_9_4_usage(ClusterInfo *cluster)
Definition: check.c:1203
static void check_for_reg_data_type_usage(ClusterInfo *cluster)
Definition: check.c:1149
void generate_old_dump(void)
Definition: dump.c:16
void get_loadable_libraries(void)
Definition: function.c:53
void get_db_and_rel_infos(ClusterInfo *cluster)
Definition: info.c:274
static pgpid_t start_postmaster(void)
Definition: pg_ctl.c:445
void init_tablespaces(void)
Definition: tablespace.c:19
void old_11_check_for_sql_identifier_data_type_usage(ClusterInfo *cluster)
Definition: version.c:361
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:218
#define GET_MAJOR_VERSION(v)
Definition: pg_upgrade.h:26
void stop_postmaster(bool in_atexit)
Definition: server.c:323
void old_9_6_invalidate_hash_indexes(ClusterInfo *cluster, bool check_mode)
Definition: version.c:246
#define JSONB_FORMAT_CHANGE_CAT_VER
Definition: pg_upgrade.h:126
UserOpts user_opts
Definition: option.c:29
ControlData controldata
Definition: pg_upgrade.h:255
uint32 major_version
Definition: pg_upgrade.h:265
uint32 cat_ver
Definition: pg_upgrade.h:199
bool check
Definition: pg_upgrade.h:294

References ControlData::cat_ver, UserOpts::check, check_for_composite_data_type_usage(), 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_tables_with_oids(), check_for_user_defined_encoding_conversions(), check_for_user_defined_postfix_ops(), check_is_install_user(), check_proper_datallowconn(), ClusterInfo::controldata, generate_old_dump(), get_db_and_rel_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 323 of file check.c.

324 {
325  /* get/check pg_control data of servers */
326  get_control_data(&old_cluster, live_check);
327  get_control_data(&new_cluster, false);
329 
330  if (live_check && old_cluster.port == new_cluster.port)
331  pg_fatal("When checking a live server, "
332  "the old and new port numbers must be different.\n");
333 }
void get_control_data(ClusterInfo *cluster, bool live_check)
Definition: controldata.c:34
void check_control_data(ControlData *oldctrl, ControlData *newctrl)
Definition: controldata.c:648
ClusterInfo new_cluster
Definition: pg_upgrade.c:63
unsigned short port
Definition: pg_upgrade.h:264

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 280 of file check.c.

281 {
282  prep_status("Checking cluster versions");
283 
284  /* cluster versions should already have been obtained */
287 
288  /*
289  * We allow upgrades from/to the same major version for alpha/beta
290  * upgrades
291  */
292 
294  pg_fatal("This utility can only upgrade from PostgreSQL version %s and later.\n",
295  "9.2");
296 
297  /* Only current PG version is supported as a target */
299  pg_fatal("This utility can only upgrade to PostgreSQL version %s.\n",
300  PG_MAJORVERSION);
301 
302  /*
303  * We can't allow downgrading because we use the target pg_dump, and
304  * pg_dump cannot operate on newer database versions, only current and
305  * older versions.
306  */
308  pg_fatal("This utility cannot be used to downgrade to older major PostgreSQL versions.\n");
309 
310  /* Ensure binaries match the designated data directories */
313  pg_fatal("Old cluster data and binary directories are from different major versions.\n");
316  pg_fatal("New cluster data and binary directories are from different major versions.\n");
317 
318  check_ok();
319 }
Assert(fmt[strlen(fmt) - 1] !='\n')
uint32 bin_version
Definition: pg_upgrade.h:267

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 648 of file controldata.c.

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

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 317 of file file.c.

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

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_jsonb_9_4_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\n", 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:289
void PQfinish(PGconn *conn)
Definition: fe-connect.c:4261
void PQclear(PGresult *res)
Definition: fe-exec.c:718
int PQntuples(const PGresult *res)
Definition: fe-exec.c:3340
char * PQgetvalue(const PGresult *res, int tup_num, int field_num)
Definition: fe-exec.c:3735
int PQfnumber(const PGresult *res, const char *field_name)
Definition: fe-exec.c:3448
#define fopen_priv(path, mode)
Definition: pg_upgrade.h:383
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:229
void initPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:92
void appendPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:267
void termPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:131
PGconn * conn
Definition: streamutil.c:54
char * db_name
Definition: pg_upgrade.h:174

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 359 of file file.c.

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

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 120 of file function.c.

121 {
122  PGconn *conn = connectToServer(&new_cluster, "template1");
123  int libnum;
124  int was_load_failure = false;
125  FILE *script = NULL;
126  bool found = false;
127  char output_path[MAXPGPATH];
128 
129  prep_status("Checking for presence of required libraries");
130 
131  snprintf(output_path, sizeof(output_path), "%s/%s",
132  log_opts.basedir, "loadable_libraries.txt");
133 
134  /*
135  * Now we want to sort the library names into order. This avoids multiple
136  * probes of the same library, and ensures that libraries are probed in a
137  * consistent order, which is important for reproducible behavior if one
138  * library depends on another.
139  */
142 
143  for (libnum = 0; libnum < os_info.num_libraries; libnum++)
144  {
145  char *lib = os_info.libraries[libnum].name;
146  int llen = strlen(lib);
147  char cmd[7 + 2 * MAXPGPATH + 1];
148  PGresult *res;
149 
150  /* Did the library name change? Probe it. */
151  if (libnum == 0 || strcmp(lib, os_info.libraries[libnum - 1].name) != 0)
152  {
153  strcpy(cmd, "LOAD '");
154  PQescapeStringConn(conn, cmd + strlen(cmd), lib, llen, NULL);
155  strcat(cmd, "'");
156 
157  res = PQexec(conn, cmd);
158 
160  {
161  found = true;
162  was_load_failure = true;
163 
164  if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL)
165  pg_fatal("could not open file \"%s\": %s\n",
166  output_path, strerror(errno));
167  fprintf(script, _("could not load library \"%s\": %s"),
168  lib,
170  }
171  else
172  was_load_failure = false;
173 
174  PQclear(res);
175  }
176 
177  if (was_load_failure)
178  fprintf(script, _("In database: %s\n"),
180  }
181 
182  PQfinish(conn);
183 
184  if (found)
185  {
186  fclose(script);
187  pg_log(PG_REPORT, "fatal\n");
188  pg_fatal("Your installation references loadable libraries that are missing from the\n"
189  "new installation. You can add these libraries to the new installation,\n"
190  "or remove the functions using them from the old installation. A list of\n"
191  "problem libraries is in the file:\n"
192  " %s\n\n", output_path);
193  }
194  else
195  check_ok();
196 }
#define _(x)
Definition: elog.c:89
char * PQerrorMessage(const PGconn *conn)
Definition: fe-connect.c:6908
size_t PQescapeStringConn(PGconn *conn, char *to, const char *from, size_t length, int *error)
Definition: fe-exec.c:4005
ExecStatusType PQresultStatus(const PGresult *res)
Definition: fe-exec.c:3270
PGresult * PQexec(PGconn *conn, const char *query)
Definition: fe-exec.c:2273
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:64
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:495
DbInfoArr dbarr
Definition: pg_upgrade.h:256
DbInfo * dbs
Definition: pg_upgrade.h:187
char * name
Definition: pg_upgrade.h:304
char * basedir
Definition: pg_upgrade.h:282
LibraryInfo * libraries
Definition: pg_upgrade.h:318
int num_libraries
Definition: pg_upgrade.h:319

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 176 of file check.c.

177 {
179 
182 
184 
185  switch (user_opts.transfer_mode)
186  {
187  case TRANSFER_MODE_CLONE:
189  break;
190  case TRANSFER_MODE_COPY:
191  break;
192  case TRANSFER_MODE_LINK:
193  check_hard_link();
194  break;
195  }
196 
198 
200 
202 }
static void check_databases_are_compatible(void)
Definition: check.c:452
static void check_new_cluster_is_empty(void)
Definition: check.c:425
static void check_for_new_tablespace_dir(ClusterInfo *new_cluster)
Definition: check.c:486
void check_file_clone(void)
Definition: file.c:317
void check_hard_link(void)
Definition: file.c:359
void check_loadable_libraries(void)
Definition: function.c:120
transferMode transfer_mode
Definition: pg_upgrade.h:297

References check_databases_are_compatible(), 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(), get_db_and_rel_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 256 of file util.c.

257 {
258  /* all seems well */
259  report_status(PG_REPORT, "ok");
260  fflush(stdout);
261 }
static void const char fflush(stdout)
static void void report_status(eLogType type, const char *fmt,...)
Definition: util.c:28

References fflush(), PG_REPORT, report_status(), and generate_unaccent_rules::stdout.

◆ check_pghost_envvar()

void check_pghost_envvar ( void  )

Definition at line 350 of file server.c.

351 {
353  PQconninfoOption *start;
354 
355  /* Get valid libpq env vars from the PQconndefaults function */
356 
357  start = PQconndefaults();
358 
359  if (!start)
360  pg_fatal("out of memory\n");
361 
362  for (option = start; option->keyword != NULL; option++)
363  {
364  if (option->envvar && (strcmp(option->envvar, "PGHOST") == 0 ||
365  strcmp(option->envvar, "PGHOSTADDR") == 0))
366  {
367  const char *value = getenv(option->envvar);
368 
369  if (value && strlen(value) > 0 &&
370  /* check for 'local' host values */
371  (strcmp(value, "localhost") != 0 && strcmp(value, "127.0.0.1") != 0 &&
372  strcmp(value, "::1") != 0 && !is_unixsock_path(value)))
373  pg_fatal("libpq environment variable %s has a non-local server value: %s\n",
374  option->envvar, value);
375  }
376  }
377 
378  /* Free the memory that libpq allocated on our behalf */
379  PQconninfoFree(start);
380 }
PQconninfoOption * PQconndefaults(void)
Definition: fe-connect.c:1477
void PQconninfoFree(PQconninfoOption *connOptions)
Definition: fe-connect.c:6736
static struct @151 value
static bool is_unixsock_path(const char *path)
Definition: pqcomm.h:93

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

Referenced by setup().

◆ cleanup_output_dirs()

void cleanup_output_dirs ( void  )

Definition at line 62 of file util.c.

63 {
64  fclose(log_opts.internal);
65 
66  /* Remove dump and log files? */
67  if (log_opts.retain)
68  return;
69 
70  (void) rmtree(log_opts.basedir, true);
71 
72  /* Remove pg_upgrade_output.d only if empty */
73  switch (pg_check_dir(log_opts.rootdir))
74  {
75  case 0: /* non-existent */
76  case 3: /* exists and contains a mount point */
77  Assert(false);
78  break;
79 
80  case 1: /* exists and empty */
81  case 2: /* exists and contains only dot files */
82  (void) rmtree(log_opts.rootdir, true);
83  break;
84 
85  case 4: /* exists */
86 
87  /*
88  * Keep the root directory as this includes some past log
89  * activity.
90  */
91  break;
92 
93  default:
94  /* different failure, just report it */
95  pg_log(PG_WARNING, "could not access directory \"%s\": %m\n",
97  break;
98  }
99 }
int pg_check_dir(const char *dir)
Definition: pgcheckdir.c:33
bool rmtree(const char *path, bool rmtopdir)
Definition: rmtree.c:42
char * rootdir
Definition: pg_upgrade.h:281
bool retain
Definition: pg_upgrade.h:279
FILE * internal
Definition: pg_upgrade.h:277
void pg_log(eLogType type, const char *fmt,...)
Definition: util.c:232
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\n",
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\n",
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\n",
56  schemaName, relName, dst, strerror(errno));
57 
58  if (ioctl(dest_fd, FICLONE, src_fd) < 0)
59  {
60  unlink(dst);
61  pg_fatal("error while cloning relation \"%s.%s\" (\"%s\" to \"%s\"): %s\n",
62  schemaName, relName, src, dst, strerror(errno));
63  }
64 
65  close(src_fd);
66  close(dest_fd);
67 #endif
68 }

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:67
PQExpBuffer createPQExpBuffer(void)
Definition: pqexpbuffer.c:74
void resetPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:148
void appendPQExpBufferChar(PQExpBuffer str, char ch)
Definition: pqexpbuffer.c:380
void appendPQExpBufferStr(PQExpBuffer str, const char *data)
Definition: pqexpbuffer.c:369
void appendShellString(PQExpBuffer buf, const char *str)
Definition: string_utils.c:429
char * user
Definition: pg_upgrade.h:314

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:6855
@ CONNECTION_OK
Definition: libpq-fe.h:60
exit(1)
#define printf(...)
Definition: port.h:231
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_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_proper_datallowconn(), get_db_infos(), get_loadable_libraries(), get_rel_infos(), get_tablespace_paths(), old_9_6_invalidate_hash_indexes(), report_extension_updates(), and set_frozenxids().

◆ copyFile()

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

Definition at line 78 of file file.c.

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

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().

◆ create_script_for_old_cluster_deletion()

void create_script_for_old_cluster_deletion ( char **  deletion_script_file_name)

Definition at line 515 of file check.c.

516 {
517  FILE *script = NULL;
518  int tblnum;
519  char old_cluster_pgdata[MAXPGPATH],
520  new_cluster_pgdata[MAXPGPATH];
521 
522  *deletion_script_file_name = psprintf("%sdelete_old_cluster.%s",
524 
525  strlcpy(old_cluster_pgdata, old_cluster.pgdata, MAXPGPATH);
526  canonicalize_path(old_cluster_pgdata);
527 
528  strlcpy(new_cluster_pgdata, new_cluster.pgdata, MAXPGPATH);
529  canonicalize_path(new_cluster_pgdata);
530 
531  /* Some people put the new data directory inside the old one. */
532  if (path_is_prefix_of_path(old_cluster_pgdata, new_cluster_pgdata))
533  {
535  "\nWARNING: new data directory should not be inside the old data directory, e.g. %s\n", old_cluster_pgdata);
536 
537  /* Unlink file in case it is left over from a previous run. */
538  unlink(*deletion_script_file_name);
539  pg_free(*deletion_script_file_name);
540  *deletion_script_file_name = NULL;
541  return;
542  }
543 
544  /*
545  * Some users (oddly) create tablespaces inside the cluster data
546  * directory. We can't create a proper old cluster delete script in that
547  * case.
548  */
549  for (tblnum = 0; tblnum < os_info.num_old_tablespaces; tblnum++)
550  {
551  char old_tablespace_dir[MAXPGPATH];
552 
553  strlcpy(old_tablespace_dir, os_info.old_tablespaces[tblnum], MAXPGPATH);
554  canonicalize_path(old_tablespace_dir);
555  if (path_is_prefix_of_path(old_cluster_pgdata, old_tablespace_dir))
556  {
557  /* reproduce warning from CREATE TABLESPACE that is in the log */
559  "\nWARNING: user-defined tablespace locations should not be inside the data directory, e.g. %s\n", old_tablespace_dir);
560 
561  /* Unlink file in case it is left over from a previous run. */
562  unlink(*deletion_script_file_name);
563  pg_free(*deletion_script_file_name);
564  *deletion_script_file_name = NULL;
565  return;
566  }
567  }
568 
569  prep_status("Creating script to delete old cluster");
570 
571  if ((script = fopen_priv(*deletion_script_file_name, "w")) == NULL)
572  pg_fatal("could not open file \"%s\": %s\n",
573  *deletion_script_file_name, strerror(errno));
574 
575 #ifndef WIN32
576  /* add shebang header */
577  fprintf(script, "#!/bin/sh\n\n");
578 #endif
579 
580  /* delete old cluster's default tablespace */
581  fprintf(script, RMDIR_CMD " %c%s%c\n", PATH_QUOTE,
583 
584  /* delete old cluster's alternate tablespaces */
585  for (tblnum = 0; tblnum < os_info.num_old_tablespaces; tblnum++)
586  {
587  /*
588  * Do the old cluster's per-database directories share a directory
589  * with a new version-specific tablespace?
590  */
591  if (strlen(old_cluster.tablespace_suffix) == 0)
592  {
593  /* delete per-database directories */
594  int dbnum;
595 
596  fprintf(script, "\n");
597 
598  for (dbnum = 0; dbnum < old_cluster.dbarr.ndbs; dbnum++)
599  fprintf(script, RMDIR_CMD " %c%s%c%u%c\n", PATH_QUOTE,
602  PATH_QUOTE);
603  }
604  else
605  {
606  char *suffix_path = pg_strdup(old_cluster.tablespace_suffix);
607 
608  /*
609  * Simply delete the tablespace directory, which might be ".old"
610  * or a version-specific subdirectory.
611  */
612  fprintf(script, RMDIR_CMD " %c%s%s%c\n", PATH_QUOTE,
614  fix_path_separator(suffix_path), PATH_QUOTE);
615  pfree(suffix_path);
616  }
617  }
618 
619  fclose(script);
620 
621 #ifndef WIN32
622  if (chmod(*deletion_script_file_name, S_IRWXU) != 0)
623  pg_fatal("could not add execute permission to file \"%s\": %s\n",
624  *deletion_script_file_name, strerror(errno));
625 #endif
626 
627  check_ok();
628 }
static char * fix_path_separator(char *path)
Definition: check.c:45
void pfree(void *pointer)
Definition: mcxt.c:1175
#define PATH_SEPARATOR
Definition: pg_upgrade.h:81
#define RMDIR_CMD
Definition: pg_upgrade.h:84
#define SCRIPT_EXT
Definition: pg_upgrade.h:86
#define SCRIPT_PREFIX
Definition: pg_upgrade.h:85
#define PATH_QUOTE
Definition: pg_upgrade.h:82
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:268
Oid db_oid
Definition: pg_upgrade.h:173
int num_old_tablespaces
Definition: pg_upgrade.h:317
char ** old_tablespaces
Definition: pg_upgrade.h:316
#define S_IRWXU
Definition: win32_port.h:297

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 705 of file controldata.c.

706 {
707  char old_path[MAXPGPATH],
708  new_path[MAXPGPATH];
709 
710  /* rename pg_control so old server cannot be accidentally started */
711  prep_status("Adding \".old\" suffix to old global/pg_control");
712 
713  snprintf(old_path, sizeof(old_path), "%s/global/pg_control", old_cluster.pgdata);
714  snprintf(new_path, sizeof(new_path), "%s/global/pg_control.old", old_cluster.pgdata);
715  if (pg_mv_file(old_path, new_path) != 0)
716  pg_fatal("Unable to rename %s to %s.\n", old_path, new_path);
717  check_ok();
718 
719  pg_log(PG_REPORT, "\n"
720  "If you want to start the old cluster, you will need to remove\n"
721  "the \".old\" suffix from %s/global/pg_control.old.\n"
722  "Because \"link\" mode was used, the old cluster cannot be safely\n"
723  "started once the new cluster has been started.\n\n", old_cluster.pgdata);
724 }
#define pg_mv_file
Definition: pg_upgrade.h:80

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 42 of file util.c.

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

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

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

◆ exec_prog()

bool exec_prog ( const char *  log_file,
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 39 of file info.c.

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

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 34 of file controldata.c.

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

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_VERBOSE, setenv, snprintf, generate_unaccent_rules::stdout, str2uint(), strerror, strlcpy(), and unsetenv.

Referenced by check_cluster_compatibility().

◆ get_db_and_rel_infos()

void get_db_and_rel_infos ( ClusterInfo cluster)

Definition at line 274 of file info.c.

275 {
276  int dbnum;
277 
278  if (cluster->dbarr.dbs != NULL)
280 
282 
283  for (dbnum = 0; dbnum < cluster->dbarr.ndbs; dbnum++)
284  get_rel_infos(cluster, &cluster->dbarr.dbs[dbnum]);
285 
286  if (cluster == &old_cluster)
287  pg_log(PG_VERBOSE, "\nsource databases:\n");
288  else
289  pg_log(PG_VERBOSE, "\ntarget databases:\n");
290 
291  if (log_opts.verbose)
292  print_db_infos(&cluster->dbarr);
293 }
static void print_db_infos(DbInfoArr *dbinfo)
Definition: info.c:599
static void get_db_infos(ClusterInfo *cluster)
Definition: info.c:303
static void free_db_and_rel_infos(DbInfoArr *db_arr)
Definition: info.c:565
static void get_rel_infos(ClusterInfo *cluster, DbInfo *dbinfo)
Definition: info.c:384

References cluster(), free_db_and_rel_infos(), get_db_infos(), get_rel_infos(), 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 53 of file function.c.

54 {
55  PGresult **ress;
56  int totaltups;
57  int dbnum;
58 
59  ress = (PGresult **) pg_malloc(old_cluster.dbarr.ndbs * sizeof(PGresult *));
60  totaltups = 0;
61 
62  /* Fetch all library names, removing duplicates within each DB */
63  for (dbnum = 0; dbnum < old_cluster.dbarr.ndbs; dbnum++)
64  {
65  DbInfo *active_db = &old_cluster.dbarr.dbs[dbnum];
67 
68  /*
69  * Fetch all libraries containing non-built-in C functions in this DB.
70  */
71  ress[dbnum] = executeQueryOrDie(conn,
72  "SELECT DISTINCT probin "
73  "FROM pg_catalog.pg_proc "
74  "WHERE prolang = %u AND "
75  "probin IS NOT NULL AND "
76  "oid >= %u;",
77  ClanguageId,
79  totaltups += PQntuples(ress[dbnum]);
80 
81  PQfinish(conn);
82  }
83 
84  os_info.libraries = (LibraryInfo *) pg_malloc(totaltups * sizeof(LibraryInfo));
85  totaltups = 0;
86 
87  for (dbnum = 0; dbnum < old_cluster.dbarr.ndbs; dbnum++)
88  {
89  PGresult *res = ress[dbnum];
90  int ntups;
91  int rowno;
92 
93  ntups = PQntuples(res);
94  for (rowno = 0; rowno < ntups; rowno++)
95  {
96  char *lib = PQgetvalue(res, rowno, 0);
97 
98  os_info.libraries[totaltups].name = pg_strdup(lib);
99  os_info.libraries[totaltups].dbnum = dbnum;
100 
101  totaltups++;
102  }
103  PQclear(res);
104  }
105 
106  pg_free(ress);
107 
108  os_info.num_libraries = totaltups;
109 }
#define FirstNormalObjectId
Definition: transam.h:197

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

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\n", 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\"\n", 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 445 of file option.c.

446 {
447 #if defined(HAVE_UNIX_SOCKETS) && !defined(WIN32)
448  if (!live_check)
449  cluster->sockdir = user_opts.socketdir;
450  else
451  {
452  /*
453  * If we are doing a live check, we will use the old cluster's Unix
454  * domain socket directory so we can connect to the live server.
455  */
456  unsigned short orig_port = cluster->port;
457  char filename[MAXPGPATH],
458  line[MAXPGPATH];
459  FILE *fp;
460  int lineno;
461 
462  snprintf(filename, sizeof(filename), "%s/postmaster.pid",
463  cluster->pgdata);
464  if ((fp = fopen(filename, "r")) == NULL)
465  pg_fatal("could not open file \"%s\": %s\n",
466  filename, strerror(errno));
467 
468  for (lineno = 1;
470  lineno++)
471  {
472  if (fgets(line, sizeof(line), fp) == NULL)
473  pg_fatal("could not read line %d from file \"%s\": %s\n",
474  lineno, filename, strerror(errno));
475 
476  /* potentially overwrite user-supplied value */
477  if (lineno == LOCK_FILE_LINE_PORT)
478  sscanf(line, "%hu", &old_cluster.port);
479  if (lineno == LOCK_FILE_LINE_SOCKET_DIR)
480  {
481  /* strip trailing newline and carriage return */
482  cluster->sockdir = pg_strdup(line);
483  (void) pg_strip_crlf(cluster->sockdir);
484  }
485  }
486  fclose(fp);
487 
488  /* warn of port number correction */
489  if (orig_port != DEF_PGUPORT && old_cluster.port != orig_port)
490  pg_log(PG_WARNING, "user-supplied old port number %hu corrected to %hu\n",
491  orig_port, cluster->port);
492  }
493 #else /* !HAVE_UNIX_SOCKETS || WIN32 */
494  cluster->sockdir = NULL;
495 #endif
496 }
#define Max(x, y)
Definition: c.h:980
#define DEF_PGUPORT
Definition: pg_upgrade.h:19
#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:299

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 296 of file util.c.

297 {
298  int user_id;
299  const char *user_name;
300  char *errstr;
301 
302 #ifndef WIN32
303  user_id = geteuid();
304 #else
305  user_id = 1;
306 #endif
307 
308  user_name = get_user_name(&errstr);
309  if (!user_name)
310  pg_fatal("%s\n", errstr);
311 
312  /* make a copy */
313  *user_name_p = pg_strdup(user_name);
314 
315  return user_id;
316 }
const char * get_user_name(char **errstr)
Definition: username.c:31
void pg_fatal(const char *fmt,...)
Definition: util.c:243

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.\n");
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 225 of file check.c.

226 {
227  /*
228  * We unconditionally start/stop the new server because pg_resetwal -o set
229  * wal_level to 'minimum'. If the user is upgrading standby servers using
230  * the rsync instructions, they will need pg_upgrade to write its final
231  * WAL record showing wal_level as 'replica'.
232  */
234 
235  /* Reindex hash indexes for old < 10.0 */
238 
240 
241  stop_postmaster(false);
242 }
void report_extension_updates(ClusterInfo *cluster)
Definition: version.c:390

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 147 of file file.c.

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

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 361 of file version.c.

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

References check_for_data_type_usage(), check_ok(), cluster(), 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), "tables_using_line.txt");
187 
188  if (check_for_data_type_usage(cluster, "pg_catalog.line", output_path))
189  {
190  pg_log(PG_REPORT, "fatal\n");
191  pg_fatal("Your installation contains the \"line\" data type in user tables.\n"
192  "This data type changed its internal and input/output format\n"
193  "between your old and new versions so this\n"
194  "cluster cannot currently be upgraded. You can\n"
195  "drop the problem columns and restart the upgrade.\n"
196  "A list of the problem columns is in the file:\n"
197  " %s\n\n", output_path);
198  }
199  else
200  check_ok();
201 }

References check_for_data_type_usage(), check_ok(), cluster(), 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 218 of file version.c.

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

References check_for_data_type_usage(), check_ok(), cluster(), 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 246 of file version.c.

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

67 {
68  if (user_opts.check && live_check)
69  {
71  "Performing Consistency Checks on Old Live Server\n"
72  "------------------------------------------------\n");
73  }
74  else
75  {
77  "Performing Consistency Checks\n"
78  "-----------------------------\n");
79  }
80 }

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 246 of file check.c.

247 {
248  PQExpBufferData user_specification;
249 
250  initPQExpBuffer(&user_specification);
252  {
253  appendPQExpBufferStr(&user_specification, "-U ");
254  appendShellString(&user_specification, os_info.user);
255  appendPQExpBufferChar(&user_specification, ' ');
256  }
257 
259  "Optimizer statistics are not transferred by pg_upgrade.\n"
260  "Once you start the new server, consider running:\n"
261  " %s/vacuumdb %s--all --analyze-in-stages\n\n", new_cluster.bindir, user_specification.data);
262 
263  if (deletion_script_file_name)
265  "Running this script will delete the old cluster's data files:\n"
266  " %s\n",
267  deletion_script_file_name);
268  else
270  "Could not create a script to delete the old cluster's data files\n"
271  "because user-defined tablespaces or the new cluster's data directory\n"
272  "exist in the old cluster directory. The old cluster's contents must\n"
273  "be deleted manually.\n");
274 
275  termPQExpBuffer(&user_specification);
276 }
bool user_specified
Definition: pg_upgrade.h:315

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 175 of file parallel.c.

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

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 38 of file option.c.

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

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, 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::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 223 of file exec.c.

224 {
225  char path[MAXPGPATH];
226  int fd;
227 
228  snprintf(path, sizeof(path), "%s/postmaster.pid", datadir);
229 
230  if ((fd = open(path, O_RDONLY, 0)) < 0)
231  {
232  /* ENOTDIR means we will throw a more useful error later */
233  if (errno != ENOENT && errno != ENOTDIR)
234  pg_fatal("could not open file \"%s\" for reading: %s\n",
235  path, strerror(errno));
236 
237  return false;
238  }
239 
240  close(fd);
241  return true;
242 }
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 12192 of file ruleutils.c.

12193 {
12194  /*
12195  * Can avoid quoting if ident starts with a lowercase letter or underscore
12196  * and contains only lowercase letters, digits, and underscores, *and* is
12197  * not any SQL keyword. Otherwise, supply quotes.
12198  */
12199  int nquotes = 0;
12200  bool safe;
12201  const char *ptr;
12202  char *result;
12203  char *optr;
12204 
12205  /*
12206  * would like to use <ctype.h> macros here, but they might yield unwanted
12207  * locale-specific results...
12208  */
12209  safe = ((ident[0] >= 'a' && ident[0] <= 'z') || ident[0] == '_');
12210 
12211  for (ptr = ident; *ptr; ptr++)
12212  {
12213  char ch = *ptr;
12214 
12215  if ((ch >= 'a' && ch <= 'z') ||
12216  (ch >= '0' && ch <= '9') ||
12217  (ch == '_'))
12218  {
12219  /* okay */
12220  }
12221  else
12222  {
12223  safe = false;
12224  if (ch == '"')
12225  nquotes++;
12226  }
12227  }
12228 
12230  safe = false;
12231 
12232  if (safe)
12233  {
12234  /*
12235  * Check for keyword. We quote keywords except for unreserved ones.
12236  * (In some cases we could avoid quoting a col_name or type_func_name
12237  * keyword, but it seems much harder than it's worth to tell that.)
12238  *
12239  * Note: ScanKeywordLookup() does case-insensitive comparison, but
12240  * that's fine, since we already know we have all-lower-case.
12241  */
12242  int kwnum = ScanKeywordLookup(ident, &ScanKeywords);
12243 
12244  if (kwnum >= 0 && ScanKeywordCategories[kwnum] != UNRESERVED_KEYWORD)
12245  safe = false;
12246  }
12247 
12248  if (safe)
12249  return ident; /* no change needed */
12250 
12251  result = (char *) palloc(strlen(ident) + nquotes + 2 + 1);
12252 
12253  optr = result;
12254  *optr++ = '"';
12255  for (ptr = ident; *ptr; ptr++)
12256  {
12257  char ch = *ptr;
12258 
12259  if (ch == '"')
12260  *optr++ = '"';
12261  *optr++ = ch;
12262  }
12263  *optr++ = '"';
12264  *optr = '\0';
12265 
12266  return result;
12267 }
const uint8 ScanKeywordCategories[SCANKEYWORDS_NUM_KEYWORDS]
Definition: keywords.c:29
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:1068
bool quote_all_identifiers
Definition: ruleutils.c:323

◆ reap_child()

bool reap_child ( bool  wait_for_child)

Definition at line 284 of file parallel.c.

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

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 206 of file check.c.

207 {
208  if (user_opts.check)
209  {
210  pg_log(PG_REPORT, "\n*Clusters are compatible*\n");
211  /* stops new cluster */
212  stop_postmaster(false);
213 
215  exit(0);
216  }
217 
218  pg_log(PG_REPORT, "\n"
219  "If pg_upgrade fails after this point, you must re-initdb the\n"
220  "new cluster before continuing.\n");
221 }
void cleanup_output_dirs(void)
Definition: util.c:62

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 390 of file version.c.

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

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 173 of file file.c.

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

References BITS_PER_BYTE, BITS_PER_HEAPBLOCK, close, ClusterInfo::controldata, PGAlignedBlock::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 
205  static bool exit_hook_registered = false;
206 
207  if (!exit_hook_registered)
208  {
209  atexit(stop_postmaster_atexit);
210  exit_hook_registered = true;
211  }
212 
213  socket_string[0] = '\0';
214 
215 #if defined(HAVE_UNIX_SOCKETS) && !defined(WIN32)
216  /* prevent TCP/IP connections, restrict socket access */
217  strcat(socket_string,
218  " -c listen_addresses='' -c unix_socket_permissions=0700");
219 
220  /* Have a sockdir? Tell the postmaster. */
221  if (cluster->sockdir)
222  snprintf(socket_string + strlen(socket_string),
223  sizeof(socket_string) - strlen(socket_string),
224  " -c %s='%s'",
225  (GET_MAJOR_VERSION(cluster->major_version) <= 902) ?
226  "unix_socket_directory" : "unix_socket_directories",
227  cluster->sockdir);
228 #endif
229 
230  /*
231  * Use -b to disable autovacuum.
232  *
233  * Turn off durability requirements to improve object creation speed, and
234  * we only modify the new cluster, so only use it there. If there is a
235  * crash, the new cluster has to be recreated anyway. fsync=off is a big
236  * win on ext4.
237  *
238  * Force vacuum_defer_cleanup_age to 0 on the new cluster, so that
239  * vacuumdb --freeze actually freezes the tuples.
240  */
241  snprintf(cmd, sizeof(cmd),
242  "\"%s/pg_ctl\" -w -l \"%s/%s\" -D \"%s\" -o \"-p %d -b%s %s%s\" start",
243  cluster->bindir,
245  SERVER_LOG_FILE, cluster->pgconfig, cluster->port,
246  (cluster == &new_cluster) ?
247  " -c synchronous_commit=off -c fsync=off -c full_page_writes=off -c vacuum_defer_cleanup_age=0" : "",
248  cluster->pgopts ? cluster->pgopts : "", socket_string);
249 
250  /*
251  * Don't throw an error right away, let connecting throw the error because
252  * it might supply a reason for the failure.
253  */
254  pg_ctl_return = exec_prog(SERVER_START_LOG_FILE,
255  /* pass both file names if they differ */
256  (strcmp(SERVER_LOG_FILE,
257  SERVER_START_LOG_FILE) != 0) ?
258  SERVER_LOG_FILE : NULL,
259  report_and_exit_on_error, false,
260  "%s", cmd);
261 
262  /* Did it fail and we are just testing if the server could be started? */
263  if (!pg_ctl_return && !report_and_exit_on_error)
264  return false;
265 
266  /*
267  * We set this here to make sure atexit() shuts down the server, but only
268  * if we started the server successfully. We do it before checking for
269  * connectivity in case the server started but there is a connectivity
270  * failure. If pg_ctl did not return success, we will exit below.
271  *
272  * Pre-9.1 servers do not have PQping(), so we could be leaving the server
273  * running if authentication was misconfigured, so someday we might went
274  * to be more aggressive about doing server shutdowns even if pg_ctl
275  * fails, but now (2013-08-14) it seems prudent to be cautious. We don't
276  * want to shutdown a server that might have been accidentally started
277  * during the upgrade.
278  */
279  if (pg_ctl_return)
281 
282  /*
283  * pg_ctl -w might have failed because the server couldn't be started, or
284  * there might have been a connection problem in _checking_ if the server
285  * has started. Therefore, even if pg_ctl failed, we continue and test
286  * for connectivity in case we get a connection reason for the failure.
287  */
288  if ((conn = get_db_conn(cluster, "template1")) == NULL ||
290  {
291  pg_log(PG_REPORT, "\n%s", PQerrorMessage(conn));
292  if (conn)
293  PQfinish(conn);
294  if (cluster == &old_cluster)
295  pg_fatal("could not connect to source postmaster started with the command:\n"
296  "%s\n",
297  cmd);
298  else
299  pg_fatal("could not connect to target postmaster started with the command:\n"
300  "%s\n",
301  cmd);
302  }
303  PQfinish(conn);
304 
305  /*
306  * If pg_ctl failed, and the connection didn't fail, and
307  * report_and_exit_on_error is enabled, fail now. This could happen if
308  * the server was already running.
309  */
310  if (!pg_ctl_return)
311  {
312  if (cluster == &old_cluster)
313  pg_fatal("pg_ctl failed to start the source server, or connection failed\n");
314  else
315  pg_fatal("pg_ctl failed to start the target server, or connection failed\n");
316  }
317 
318  return true;
319 }
#define SERVER_START_LOG_FILE
Definition: pg_upgrade.h:66
#define SERVER_LOG_FILE
Definition: pg_upgrade.h:43
static void stop_postmaster_atexit(void)
Definition: server.c:191
char * logdir
Definition: pg_upgrade.h:284
ClusterInfo * running_cluster
Definition: pg_upgrade.h:320

References cluster(), conn, CONNECTION_OK, exec_prog(), get_db_conn(), GET_MAJOR_VERSION, 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, and stop_postmaster_atexit().

◆ stop_postmaster()

void stop_postmaster ( bool  in_atexit)

Definition at line 323 of file server.c.

324 {
326 
328  cluster = &old_cluster;
329  else if (os_info.running_cluster == &new_cluster)
330  cluster = &new_cluster;
331  else
332  return; /* no cluster running */
333 
334  exec_prog(SERVER_STOP_LOG_FILE, NULL, !in_atexit, !in_atexit,
335  "\"%s/pg_ctl\" -w -D \"%s\" -o \"%s\" %s stop",
336  cluster->bindir, cluster->pgconfig,
337  cluster->pgopts ? cluster->pgopts : "",
338  in_atexit ? "-m fast" : "-m smart");
339 
340  os_info.running_cluster = NULL;
341 }
#define SERVER_STOP_LOG_FILE
Definition: pg_upgrade.h:67

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 325 of file util.c.

326 {
327  return strtoul(str, NULL, 10);
328 }

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 relfilenode.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\n",
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:39
static void transfer_single_new_db(FileNameMap *maps, int size, char *old_tablespace)
Definition: relfilenode.c:135

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 relfilenode.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:175

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 254 of file exec.c.

255 {
256 #ifndef WIN32
257  if (access(".", R_OK | W_OK | X_OK) != 0)
258 #else
259  if (win32_check_directory_write_permissions() != 0)
260 #endif
261  pg_fatal("You must have read and write access in the current directory.\n");
262 
263  check_bin_dir(&old_cluster, false);
265  check_bin_dir(&new_cluster, true);
267 }
static void check_bin_dir(ClusterInfo *cluster, bool check_versions)
Definition: exec.c:374
static void check_data_dir(ClusterInfo *cluster)
Definition: exec.c:332

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 330 of file pg_upgrade.h.

◆ old_cluster

◆ os_info

◆ output_files

char* output_files[]
extern

Definition at line 66 of file pg_upgrade.c.

Referenced by make_outputdirs().

◆ user_opts