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

Go to the source code of this file.

Data Structures

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

Macros

#define DEF_PGUPORT   50432
 
#define MAX_STRING   1024
 
#define QUERY_ALLOC   8192
 
#define MESSAGE_WIDTH   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)
 

Enumerations

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

Functions

void output_check_banner (bool live_check)
 
void check_and_dump_old_cluster (bool live_check)
 
void check_new_cluster (void)
 
void report_clusters_compatible (void)
 
void issue_warnings_and_set_wal_level (void)
 
void output_completion_banner (char *deletion_script_file_name)
 
void check_cluster_versions (void)
 
void check_cluster_compatibility (bool live_check)
 
void create_script_for_old_cluster_deletion (char **deletion_script_file_name)
 
void get_control_data (ClusterInfo *cluster, bool live_check)
 
void check_control_data (ControlData *oldctrl, ControlData *newctrl)
 
void disable_old_cluster (void)
 
void generate_old_dump (void)
 
bool exec_prog (const char *log_filename, const char *opt_log_file, bool report_error, bool exit_on_error, const char *fmt,...) pg_attribute_printf(5
 
bool void verify_directories (void)
 
bool pid_lock_file_exists (const char *datadir)
 
void cloneFile (const char *src, const char *dst, const char *schemaName, const char *relName)
 
void copyFile (const char *src, const char *dst, const char *schemaName, const char *relName)
 
void linkFile (const char *src, const char *dst, const char *schemaName, const char *relName)
 
void rewriteVisibilityMap (const char *fromfile, const char *tofile, const char *schemaName, const char *relName)
 
void check_file_clone (void)
 
void check_hard_link (void)
 
void get_loadable_libraries (void)
 
void check_loadable_libraries (void)
 
FileNameMapgen_db_file_maps (DbInfo *old_db, DbInfo *new_db, int *nmaps, const char *old_pgdata, const char *new_pgdata)
 
void get_db_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 39 of file pg_upgrade.h.

◆ DB_DUMP_FILE_MASK

#define DB_DUMP_FILE_MASK   "pg_upgrade_dump_%u.custom"

Definition at line 31 of file pg_upgrade.h.

◆ DB_DUMP_LOG_FILE_MASK

#define DB_DUMP_LOG_FILE_MASK   "pg_upgrade_dump_%u.log"

Definition at line 43 of file pg_upgrade.h.

◆ DEF_PGUPORT

#define DEF_PGUPORT   50432

Definition at line 20 of file pg_upgrade.h.

◆ DUMP_OUTPUTDIR

#define DUMP_OUTPUTDIR   "dump"

Definition at line 41 of file pg_upgrade.h.

◆ ECHO_BLANK

#define ECHO_BLANK   ""

Definition at line 89 of file pg_upgrade.h.

◆ ECHO_QUOTE

#define ECHO_QUOTE   "'"

Definition at line 88 of file pg_upgrade.h.

◆ EXEC_PSQL_ARGS

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

Definition at line 368 of file pg_upgrade.h.

◆ fopen_priv

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

Definition at line 390 of file pg_upgrade.h.

◆ GET_MAJOR_VERSION

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

Definition at line 27 of file pg_upgrade.h.

◆ GLOBALS_DUMP_FILE

#define GLOBALS_DUMP_FILE   "pg_upgrade_dump_globals.sql"

Definition at line 30 of file pg_upgrade.h.

◆ INTERNAL_LOG_FILE

#define INTERNAL_LOG_FILE   "pg_upgrade_internal.log"

Definition at line 46 of file pg_upgrade.h.

◆ JSONB_FORMAT_CHANGE_CAT_VER

#define JSONB_FORMAT_CHANGE_CAT_VER   201409291

Definition at line 127 of file pg_upgrade.h.

◆ LARGE_OBJECT_SIZE_PG_CONTROL_VER

#define LARGE_OBJECT_SIZE_PG_CONTROL_VER   942

Definition at line 122 of file pg_upgrade.h.

◆ LOG_OUTPUTDIR

#define LOG_OUTPUTDIR   "log"

Definition at line 40 of file pg_upgrade.h.

◆ MAX_STRING

#define MAX_STRING   1024

Definition at line 22 of file pg_upgrade.h.

◆ MESSAGE_WIDTH

#define MESSAGE_WIDTH   60

Definition at line 25 of file pg_upgrade.h.

◆ MULTIXACT_FORMATCHANGE_CAT_VER

#define MULTIXACT_FORMATCHANGE_CAT_VER   201301231

Definition at line 116 of file pg_upgrade.h.

◆ PATH_QUOTE

#define PATH_QUOTE   '\''

Definition at line 83 of file pg_upgrade.h.

◆ PATH_SEPARATOR

#define PATH_SEPARATOR   '/'

Definition at line 82 of file pg_upgrade.h.

◆ pg_mv_file

#define pg_mv_file   rename

Definition at line 81 of file pg_upgrade.h.

◆ QUERY_ALLOC

#define QUERY_ALLOC   8192

Definition at line 23 of file pg_upgrade.h.

◆ RM_CMD

#define RM_CMD   "rm -f"

Definition at line 84 of file pg_upgrade.h.

◆ RMDIR_CMD

#define RMDIR_CMD   "rm -rf"

Definition at line 85 of file pg_upgrade.h.

◆ SCRIPT_EXT

#define SCRIPT_EXT   "sh"

Definition at line 87 of file pg_upgrade.h.

◆ SCRIPT_PREFIX

#define SCRIPT_PREFIX   "./"

Definition at line 86 of file pg_upgrade.h.

◆ SERVER_LOG_FILE

#define SERVER_LOG_FILE   "pg_upgrade_server.log"

Definition at line 44 of file pg_upgrade.h.

◆ SERVER_START_LOG_FILE

#define SERVER_START_LOG_FILE   SERVER_LOG_FILE

Definition at line 67 of file pg_upgrade.h.

◆ SERVER_STOP_LOG_FILE

#define SERVER_STOP_LOG_FILE   SERVER_LOG_FILE

Definition at line 68 of file pg_upgrade.h.

◆ UTILITY_LOG_FILE

#define UTILITY_LOG_FILE   "pg_upgrade_utility.log"

Definition at line 45 of file pg_upgrade.h.

◆ VISIBILITY_MAP_FROZEN_BIT_CAT_VER

#define VISIBILITY_MAP_FROZEN_BIT_CAT_VER   201603011

Definition at line 108 of file pg_upgrade.h.

Enumeration Type Documentation

◆ eLogType

enum eLogType
Enumerator
PG_VERBOSE 
PG_STATUS 
PG_REPORT_NONL 
PG_REPORT 
PG_WARNING 
PG_FATAL 

Definition at line 243 of file pg_upgrade.h.

244 {
245  PG_VERBOSE,
246  PG_STATUS, /* these messages do not get a newline added */
247  PG_REPORT_NONL, /* these too */
248  PG_REPORT,
249  PG_WARNING,
250  PG_FATAL
251 } eLogType;
eLogType
Definition: pg_upgrade.h:244
@ PG_FATAL
Definition: pg_upgrade.h:250
@ PG_STATUS
Definition: pg_upgrade.h:246
@ PG_WARNING
Definition: pg_upgrade.h:249
@ PG_REPORT_NONL
Definition: pg_upgrade.h:247
@ PG_VERBOSE
Definition: pg_upgrade.h:245
@ PG_REPORT
Definition: pg_upgrade.h:248

◆ transferMode

Enumerator
TRANSFER_MODE_CLONE 
TRANSFER_MODE_COPY 
TRANSFER_MODE_LINK 

Definition at line 233 of file pg_upgrade.h.

234 {
238 } transferMode;
transferMode
Definition: pg_upgrade.h:234
@ TRANSFER_MODE_COPY
Definition: pg_upgrade.h:236
@ TRANSFER_MODE_LINK
Definition: pg_upgrade.h:237
@ TRANSFER_MODE_CLONE
Definition: pg_upgrade.h:235

Function Documentation

◆ adjust_data_dir()

void adjust_data_dir ( ClusterInfo cluster)

Definition at line 386 of file option.c.

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

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

◆ check_and_dump_old_cluster()

void check_and_dump_old_cluster ( bool  live_check)

Definition at line 82 of file check.c.

83 {
84  /* -- OLD -- */
85 
86  if (!live_check)
88 
89  /* Extract a list of databases and tables from the old cluster */
91 
93 
95 
96 
97  /*
98  * Check for various failure cases
99  */
106 
107  /*
108  * PG 16 increased the size of the 'aclitem' type, which breaks the
109  * on-disk format for existing data.
110  */
113 
114  /*
115  * PG 14 changed the function signature of encoding conversion functions.
116  * Conversions from older versions cannot be upgraded automatically
117  * because the user-defined functions used by the encoding conversions
118  * need to be changed to match the new signature.
119  */
122 
123  /*
124  * Pre-PG 14 allowed user defined postfix operators, which are not
125  * supported anymore. Verify there are none, iff applicable.
126  */
129 
130  /*
131  * PG 14 changed polymorphic functions from anyarray to
132  * anycompatiblearray.
133  */
136 
137  /*
138  * Pre-PG 12 allowed tables to be declared WITH OIDS, which is not
139  * supported anymore. Verify there are none, iff applicable.
140  */
143 
144  /*
145  * PG 12 changed the 'sql_identifier' type storage to be based on name,
146  * not varchar, which breaks on-disk format for existing data. So we need
147  * to prevent upgrade when used in user objects (tables, indexes, ...).
148  */
151 
152  /*
153  * Pre-PG 10 allowed tables with 'unknown' type columns and non WAL logged
154  * hash indexes
155  */
157  {
159  if (user_opts.check)
161  }
162 
163  /* 9.5 and below should not have roles starting with pg_ */
166 
170 
171  /* Pre-PG 9.4 had a different 'line' data type internal format */
174 
175  /*
176  * While not a check option, we do this now because this is the only time
177  * the old server is running.
178  */
179  if (!user_opts.check)
181 
182  if (!live_check)
183  stop_postmaster(false);
184 }
static void check_for_tables_with_oids(ClusterInfo *cluster)
Definition: check.c:1018
static void check_for_pg_role_prefix(ClusterInfo *cluster)
Definition: check.c:1272
static void check_for_composite_data_type_usage(ClusterInfo *cluster)
Definition: check.c:1098
static void check_is_install_user(ClusterInfo *cluster)
Definition: check.c:532
static void check_for_isn_and_int8_passing_mismatch(ClusterInfo *cluster)
Definition: check.c:710
static void check_for_user_defined_postfix_ops(ClusterInfo *cluster)
Definition: check.c:792
static void check_for_prepared_transactions(ClusterInfo *cluster)
Definition: check.c:675
static void check_proper_datallowconn(ClusterInfo *cluster)
Definition: check.c:590
static void check_for_aclitem_data_type_usage(ClusterInfo *cluster)
Definition: check.c:1214
static void check_for_user_defined_encoding_conversions(ClusterInfo *cluster)
Definition: check.c:1328
static void check_for_jsonb_9_4_usage(ClusterInfo *cluster)
Definition: check.c:1242
static void check_for_incompatible_polymorphics(ClusterInfo *cluster)
Definition: check.c:891
static void check_for_reg_data_type_usage(ClusterInfo *cluster)
Definition: check.c:1159
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:275
static pid_t start_postmaster(void)
Definition: pg_ctl.c:440
void init_tablespaces(void)
Definition: tablespace.c:19
void old_11_check_for_sql_identifier_data_type_usage(ClusterInfo *cluster)
Definition: version.c:365
void old_9_3_check_for_line_data_type_usage(ClusterInfo *cluster)
Definition: version.c:180
void old_9_6_check_for_unknown_data_type_usage(ClusterInfo *cluster)
Definition: version.c:220
#define GET_MAJOR_VERSION(v)
Definition: pg_upgrade.h:27
void stop_postmaster(bool in_atexit)
Definition: server.c:320
void old_9_6_invalidate_hash_indexes(ClusterInfo *cluster, bool check_mode)
Definition: version.c:250
#define JSONB_FORMAT_CHANGE_CAT_VER
Definition: pg_upgrade.h:127
UserOpts user_opts
Definition: option.c:29
ControlData controldata
Definition: pg_upgrade.h:261
uint32 major_version
Definition: pg_upgrade.h:272
uint32 cat_ver
Definition: pg_upgrade.h:207
bool check
Definition: pg_upgrade.h:301

References ControlData::cat_ver, UserOpts::check, check_for_aclitem_data_type_usage(), check_for_composite_data_type_usage(), check_for_incompatible_polymorphics(), check_for_isn_and_int8_passing_mismatch(), check_for_jsonb_9_4_usage(), check_for_pg_role_prefix(), check_for_prepared_transactions(), check_for_reg_data_type_usage(), check_for_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 334 of file check.c.

335 {
336  /* get/check pg_control data of servers */
337  get_control_data(&old_cluster, live_check);
338  get_control_data(&new_cluster, false);
340 
341  if (live_check && old_cluster.port == new_cluster.port)
342  pg_fatal("When checking a live server, "
343  "the old and new port numbers must be different.");
344 }
void get_control_data(ClusterInfo *cluster, bool live_check)
Definition: controldata.c:36
void check_control_data(ControlData *oldctrl, ControlData *newctrl)
Definition: controldata.c:655
ClusterInfo new_cluster
Definition: pg_upgrade.c:64
unsigned short port
Definition: pg_upgrade.h:271

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

292 {
293  prep_status("Checking cluster versions");
294 
295  /* cluster versions should already have been obtained */
298 
299  /*
300  * We allow upgrades from/to the same major version for alpha/beta
301  * upgrades
302  */
303 
305  pg_fatal("This utility can only upgrade from PostgreSQL version %s and later.",
306  "9.2");
307 
308  /* Only current PG version is supported as a target */
310  pg_fatal("This utility can only upgrade to PostgreSQL version %s.",
311  PG_MAJORVERSION);
312 
313  /*
314  * We can't allow downgrading because we use the target pg_dump, and
315  * pg_dump cannot operate on newer database versions, only current and
316  * older versions.
317  */
319  pg_fatal("This utility cannot be used to downgrade to older major PostgreSQL versions.");
320 
321  /* Ensure binaries match the designated data directories */
324  pg_fatal("Old cluster data and binary directories are from different major versions.");
327  pg_fatal("New cluster data and binary directories are from different major versions.");
328 
329  check_ok();
330 }
Assert(fmt[strlen(fmt) - 1] !='\n')
uint32 bin_version
Definition: pg_upgrade.h:274

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

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

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

Referenced by check_cluster_compatibility().

◆ check_file_clone()

void check_file_clone ( void  )

Definition at line 320 of file file.c.

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

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

Referenced by check_new_cluster().

◆ check_for_data_type_usage()

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

Definition at line 153 of file version.c.

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

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

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

◆ check_for_data_types_usage()

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

Definition at line 31 of file version.c.

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

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

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

◆ check_hard_link()

void check_hard_link ( void  )

Definition at line 362 of file file.c.

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

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

Referenced by check_new_cluster().

◆ check_loadable_libraries()

void check_loadable_libraries ( void  )

Definition at line 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  char output_path[MAXPGPATH];
127 
128  prep_status("Checking for presence of required libraries");
129 
130  snprintf(output_path, sizeof(output_path), "%s/%s",
131  log_opts.basedir, "loadable_libraries.txt");
132 
133  /*
134  * Now we want to sort the library names into order. This avoids multiple
135  * probes of the same library, and ensures that libraries are probed in a
136  * consistent order, which is important for reproducible behavior if one
137  * library depends on another.
138  */
141 
142  for (libnum = 0; libnum < os_info.num_libraries; libnum++)
143  {
144  char *lib = os_info.libraries[libnum].name;
145  int llen = strlen(lib);
146  char cmd[7 + 2 * MAXPGPATH + 1];
147  PGresult *res;
148 
149  /* Did the library name change? Probe it. */
150  if (libnum == 0 || strcmp(lib, os_info.libraries[libnum - 1].name) != 0)
151  {
152  strcpy(cmd, "LOAD '");
153  PQescapeStringConn(conn, cmd + strlen(cmd), lib, llen, NULL);
154  strcat(cmd, "'");
155 
156  res = PQexec(conn, cmd);
157 
159  {
160  was_load_failure = true;
161 
162  if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL)
163  pg_fatal("could not open file \"%s\": %s",
164  output_path, strerror(errno));
165  fprintf(script, _("could not load library \"%s\": %s"),
166  lib,
168  }
169  else
170  was_load_failure = false;
171 
172  PQclear(res);
173  }
174 
175  if (was_load_failure)
176  fprintf(script, _("In database: %s\n"),
178  }
179 
180  PQfinish(conn);
181 
182  if (script)
183  {
184  fclose(script);
185  pg_log(PG_REPORT, "fatal");
186  pg_fatal("Your installation references loadable libraries that are missing from the\n"
187  "new installation. You can add these libraries to the new installation,\n"
188  "or remove the functions using them from the old installation. A list of\n"
189  "problem libraries is in the file:\n"
190  " %s", output_path);
191  }
192  else
193  check_ok();
194 }
#define _(x)
Definition: elog.c:91
char * PQerrorMessage(const PGconn *conn)
Definition: fe-connect.c:7245
size_t PQescapeStringConn(PGconn *conn, char *to, const char *from, size_t length, int *error)
Definition: fe-exec.c:3982
ExecStatusType PQresultStatus(const PGresult *res)
Definition: fe-exec.c:3244
PGresult * PQexec(PGconn *conn, const char *query)
Definition: fe-exec.c:2228
static int library_name_compare(const void *p1, const void *p2)
Definition: function.c:28
@ PGRES_COMMAND_OK
Definition: libpq-fe.h:97
OSInfo os_info
Definition: pg_upgrade.c:65
void void pg_log(eLogType type, const char *fmt,...) pg_attribute_printf(2
LogOpts log_opts
Definition: util.c:17
#define qsort(a, b, c, d)
Definition: port.h:445
DbInfoArr dbarr
Definition: pg_upgrade.h:263
DbInfo * dbs
Definition: pg_upgrade.h:195
char * name
Definition: pg_upgrade.h:311
char * basedir
Definition: pg_upgrade.h:289
LibraryInfo * libraries
Definition: pg_upgrade.h:325
int num_libraries
Definition: pg_upgrade.h:326

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

189 {
191 
193 
195 
196  switch (user_opts.transfer_mode)
197  {
198  case TRANSFER_MODE_CLONE:
200  break;
201  case TRANSFER_MODE_COPY:
202  break;
203  case TRANSFER_MODE_LINK:
204  check_hard_link();
205  break;
206  }
207 
209 
211 
213 }
static void check_new_cluster_is_empty(void)
Definition: check.c:348
static void check_for_new_tablespace_dir(ClusterInfo *new_cluster)
Definition: check.c:380
void check_file_clone(void)
Definition: file.c:320
void check_hard_link(void)
Definition: file.c:362
void check_loadable_libraries(void)
Definition: function.c:120
transferMode transfer_mode
Definition: pg_upgrade.h:304

References check_file_clone(), check_for_new_tablespace_dir(), check_for_prepared_transactions(), check_hard_link(), check_is_install_user(), check_loadable_libraries(), check_new_cluster_is_empty(), 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 284 of file util.c.

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

References PG_REPORT, and report_status().

◆ check_pghost_envvar()

void check_pghost_envvar ( void  )

Definition at line 347 of file server.c.

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

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

Referenced by setup().

◆ cleanup_output_dirs()

void cleanup_output_dirs ( void  )

Definition at line 63 of file util.c.

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

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

Referenced by main(), and report_clusters_compatible().

◆ cloneFile()

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

Definition at line 38 of file file.c.

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

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

Referenced by transfer_relfile().

◆ cluster_conn_opts()

PGresult char* cluster_conn_opts ( ClusterInfo cluster)

Definition at line 92 of file server.c.

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

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:7192
@ CONNECTION_OK
Definition: libpq-fe.h:60
exit(1)
#define printf(...)
Definition: port.h:244
PGresult * executeQueryOrDie(PGconn *conn, const char *fmt,...)
Definition: server.c:122
static PGconn * get_db_conn(ClusterInfo *cluster, const char *db_name)
Definition: server.c:57

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

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

◆ copyFile()

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

Definition at line 81 of file file.c.

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

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

Referenced by transfer_relfile().

◆ create_script_for_old_cluster_deletion()

void create_script_for_old_cluster_deletion ( char **  deletion_script_file_name)

Definition at line 409 of file check.c.

410 {
411  FILE *script = NULL;
412  int tblnum;
413  char old_cluster_pgdata[MAXPGPATH],
414  new_cluster_pgdata[MAXPGPATH];
415 
416  *deletion_script_file_name = psprintf("%sdelete_old_cluster.%s",
418 
419  strlcpy(old_cluster_pgdata, old_cluster.pgdata, MAXPGPATH);
420  canonicalize_path(old_cluster_pgdata);
421 
422  strlcpy(new_cluster_pgdata, new_cluster.pgdata, MAXPGPATH);
423  canonicalize_path(new_cluster_pgdata);
424 
425  /* Some people put the new data directory inside the old one. */
426  if (path_is_prefix_of_path(old_cluster_pgdata, new_cluster_pgdata))
427  {
429  "\nWARNING: new data directory should not be inside the old data directory, i.e. %s", old_cluster_pgdata);
430 
431  /* Unlink file in case it is left over from a previous run. */
432  unlink(*deletion_script_file_name);
433  pg_free(*deletion_script_file_name);
434  *deletion_script_file_name = NULL;
435  return;
436  }
437 
438  /*
439  * Some users (oddly) create tablespaces inside the cluster data
440  * directory. We can't create a proper old cluster delete script in that
441  * case.
442  */
443  for (tblnum = 0; tblnum < os_info.num_old_tablespaces; tblnum++)
444  {
445  char old_tablespace_dir[MAXPGPATH];
446 
447  strlcpy(old_tablespace_dir, os_info.old_tablespaces[tblnum], MAXPGPATH);
448  canonicalize_path(old_tablespace_dir);
449  if (path_is_prefix_of_path(old_cluster_pgdata, old_tablespace_dir))
450  {
451  /* reproduce warning from CREATE TABLESPACE that is in the log */
453  "\nWARNING: user-defined tablespace locations should not be inside the data directory, i.e. %s", old_tablespace_dir);
454 
455  /* Unlink file in case it is left over from a previous run. */
456  unlink(*deletion_script_file_name);
457  pg_free(*deletion_script_file_name);
458  *deletion_script_file_name = NULL;
459  return;
460  }
461  }
462 
463  prep_status("Creating script to delete old cluster");
464 
465  if ((script = fopen_priv(*deletion_script_file_name, "w")) == NULL)
466  pg_fatal("could not open file \"%s\": %s",
467  *deletion_script_file_name, strerror(errno));
468 
469 #ifndef WIN32
470  /* add shebang header */
471  fprintf(script, "#!/bin/sh\n\n");
472 #endif
473 
474  /* delete old cluster's default tablespace */
475  fprintf(script, RMDIR_CMD " %c%s%c\n", PATH_QUOTE,
477 
478  /* delete old cluster's alternate tablespaces */
479  for (tblnum = 0; tblnum < os_info.num_old_tablespaces; tblnum++)
480  {
481  /*
482  * Do the old cluster's per-database directories share a directory
483  * with a new version-specific tablespace?
484  */
485  if (strlen(old_cluster.tablespace_suffix) == 0)
486  {
487  /* delete per-database directories */
488  int dbnum;
489 
490  fprintf(script, "\n");
491 
492  for (dbnum = 0; dbnum < old_cluster.dbarr.ndbs; dbnum++)
493  fprintf(script, RMDIR_CMD " %c%s%c%u%c\n", PATH_QUOTE,
496  PATH_QUOTE);
497  }
498  else
499  {
500  char *suffix_path = pg_strdup(old_cluster.tablespace_suffix);
501 
502  /*
503  * Simply delete the tablespace directory, which might be ".old"
504  * or a version-specific subdirectory.
505  */
506  fprintf(script, RMDIR_CMD " %c%s%s%c\n", PATH_QUOTE,
508  fix_path_separator(suffix_path), PATH_QUOTE);
509  pfree(suffix_path);
510  }
511  }
512 
513  fclose(script);
514 
515 #ifndef WIN32
516  if (chmod(*deletion_script_file_name, S_IRWXU) != 0)
517  pg_fatal("could not add execute permission to file \"%s\": %s",
518  *deletion_script_file_name, strerror(errno));
519 #endif
520 
521  check_ok();
522 }
static char * fix_path_separator(char *path)
Definition: check.c:43
void pfree(void *pointer)
Definition: mcxt.c:1456
#define PATH_SEPARATOR
Definition: pg_upgrade.h:82
#define RMDIR_CMD
Definition: pg_upgrade.h:85
#define SCRIPT_EXT
Definition: pg_upgrade.h:87
#define SCRIPT_PREFIX
Definition: pg_upgrade.h:86
#define PATH_QUOTE
Definition: pg_upgrade.h:83
bool path_is_prefix_of_path(const char *path1, const char *path2)
Definition: path.c:559
void canonicalize_path(char *path)
Definition: path.c:264
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition: strlcpy.c:45
const char * tablespace_suffix
Definition: pg_upgrade.h:275
Oid db_oid
Definition: pg_upgrade.h:174
int num_old_tablespaces
Definition: pg_upgrade.h:324
char ** old_tablespaces
Definition: pg_upgrade.h:323
#define S_IRWXU
Definition: win32_port.h:306

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

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

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

Referenced by main().

◆ end_progress_output()

void end_progress_output ( void  )

Definition at line 43 of file util.c.

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

References LogOpts::isatty, log_opts, MESSAGE_WIDTH, pg_log(), PG_REPORT_NONL, 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_filename,
const char *  opt_log_file,
bool  report_error,
bool  exit_on_error,
const char *  fmt,
  ... 
)

◆ executeQueryOrDie()

◆ gen_db_file_maps()

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

Definition at line 40 of file info.c.

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

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

Referenced by transfer_all_new_dbs().

◆ generate_old_dump()

void generate_old_dump ( void  )

Definition at line 16 of file dump.c.

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

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

Referenced by check_and_dump_old_cluster().

◆ get_control_data()

void get_control_data ( ClusterInfo cluster,
bool  live_check 
)

Definition at line 36 of file controldata.c.

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

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

Referenced by check_cluster_compatibility().

◆ get_db_and_rel_infos()

void get_db_and_rel_infos ( ClusterInfo cluster)

Definition at line 275 of file info.c.

276 {
277  int dbnum;
278 
279  if (cluster->dbarr.dbs != NULL)
281 
284 
285  for (dbnum = 0; dbnum < cluster->dbarr.ndbs; dbnum++)
286  get_rel_infos(cluster, &cluster->dbarr.dbs[dbnum]);
287 
288  if (cluster == &old_cluster)
289  pg_log(PG_VERBOSE, "\nsource databases:");
290  else
291  pg_log(PG_VERBOSE, "\ntarget databases:");
292 
293  if (log_opts.verbose)
294  print_db_infos(&cluster->dbarr);
295 }
static void get_template0_info(ClusterInfo *cluster)
Definition: info.c:303
static void get_db_infos(ClusterInfo *cluster)
Definition: info.c:362
static void free_db_and_rel_infos(DbInfoArr *db_arr)
Definition: info.c:605
static void print_db_infos(DbInfoArr *db_arr)
Definition: info.c:639
static void get_rel_infos(ClusterInfo *cluster, DbInfo *dbinfo)
Definition: info.c:425

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

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

◆ get_loadable_libraries()

void get_loadable_libraries ( void  )

Definition at line 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", ver_filename);
170 
171  if (fscanf(version_fd, "%63s", cluster->major_version_str) == 0 ||
172  sscanf(cluster->major_version_str, "%d.%d", &v1, &v2) < 1)
173  pg_fatal("could not parse version file \"%s\"", ver_filename);
174 
175  fclose(version_fd);
176 
177  if (v1 < 10)
178  {
179  /* old style, e.g. 9.6.1 */
180  return v1 * 10000 + v2 * 100;
181  }
182  else
183  {
184  /* new style, e.g. 10.1 */
185  return v1 * 10000;
186  }
187 }

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

Referenced by check_data_dir().

◆ get_sock_dir()

void get_sock_dir ( ClusterInfo cluster,
bool  live_check 
)

Definition at line 456 of file option.c.

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

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

Referenced by main().

◆ get_user_info()

int get_user_info ( char **  user_name_p)

Definition at line 323 of file util.c.

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

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

Referenced by parseCommandLine().

◆ init_tablespaces()

void init_tablespaces ( void  )

Definition at line 19 of file tablespace.c.

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

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

Referenced by check_and_dump_old_cluster().

◆ issue_warnings_and_set_wal_level()

void issue_warnings_and_set_wal_level ( void  )

Definition at line 236 of file check.c.

237 {
238  /*
239  * We unconditionally start/stop the new server because pg_resetwal -o set
240  * wal_level to 'minimum'. If the user is upgrading standby servers using
241  * the rsync instructions, they will need pg_upgrade to write its final
242  * WAL record showing wal_level as 'replica'.
243  */
245 
246  /* Reindex hash indexes for old < 10.0 */
249 
251 
252  stop_postmaster(false);
253 }
void report_extension_updates(ClusterInfo *cluster)
Definition: version.c:396

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

Referenced by main().

◆ linkFile()

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

Definition at line 150 of file file.c.

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

References link(), pg_fatal, and strerror.

Referenced by transfer_relfile().

◆ old_11_check_for_sql_identifier_data_type_usage()

void old_11_check_for_sql_identifier_data_type_usage ( ClusterInfo cluster)

Definition at line 365 of file version.c.

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

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

Referenced by check_and_dump_old_cluster().

◆ old_9_3_check_for_line_data_type_usage()

void old_9_3_check_for_line_data_type_usage ( ClusterInfo cluster)

Definition at line 180 of file version.c.

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

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

Referenced by check_and_dump_old_cluster().

◆ old_9_6_check_for_unknown_data_type_usage()

void old_9_6_check_for_unknown_data_type_usage ( ClusterInfo cluster)

Definition at line 220 of file version.c.

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

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

Referenced by check_and_dump_old_cluster().

◆ old_9_6_invalidate_hash_indexes()

void old_9_6_invalidate_hash_indexes ( ClusterInfo cluster,
bool  check_mode 
)

Definition at line 250 of file version.c.

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

65 {
66  if (user_opts.check && live_check)
67  {
69  "Performing Consistency Checks on Old Live Server\n"
70  "------------------------------------------------");
71  }
72  else
73  {
75  "Performing Consistency Checks\n"
76  "-----------------------------");
77  }
78 }

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

258 {
259  PQExpBufferData user_specification;
260 
261  initPQExpBuffer(&user_specification);
263  {
264  appendPQExpBufferStr(&user_specification, "-U ");
265  appendShellString(&user_specification, os_info.user);
266  appendPQExpBufferChar(&user_specification, ' ');
267  }
268 
270  "Optimizer statistics are not transferred by pg_upgrade.\n"
271  "Once you start the new server, consider running:\n"
272  " %s/vacuumdb %s--all --analyze-in-stages", new_cluster.bindir, user_specification.data);
273 
274  if (deletion_script_file_name)
276  "Running this script will delete the old cluster's data files:\n"
277  " %s",
278  deletion_script_file_name);
279  else
281  "Could not create a script to delete the old cluster's data files\n"
282  "because user-defined tablespaces or the new cluster's data directory\n"
283  "exist in the old cluster directory. The old cluster's contents must\n"
284  "be deleted manually.");
285 
286  termPQExpBuffer(&user_specification);
287 }
bool user_specified
Definition: pg_upgrade.h:322

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

Referenced by main().

◆ parallel_exec_prog()

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

◆ parallel_transfer_all_new_dbs()

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

Definition at line 172 of file parallel.c.

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

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

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

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

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

Referenced by setup().

◆ prep_status()

◆ prep_status_progress()

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

◆ quote_identifier()

char* quote_identifier ( const char *  s)

Definition at line 11930 of file ruleutils.c.

11931 {
11932  /*
11933  * Can avoid quoting if ident starts with a lowercase letter or underscore
11934  * and contains only lowercase letters, digits, and underscores, *and* is
11935  * not any SQL keyword. Otherwise, supply quotes.
11936  */
11937  int nquotes = 0;
11938  bool safe;
11939  const char *ptr;
11940  char *result;
11941  char *optr;
11942 
11943  /*
11944  * would like to use <ctype.h> macros here, but they might yield unwanted
11945  * locale-specific results...
11946  */
11947  safe = ((ident[0] >= 'a' && ident[0] <= 'z') || ident[0] == '_');
11948 
11949  for (ptr = ident; *ptr; ptr++)
11950  {
11951  char ch = *ptr;
11952 
11953  if ((ch >= 'a' && ch <= 'z') ||
11954  (ch >= '0' && ch <= '9') ||
11955  (ch == '_'))
11956  {
11957  /* okay */
11958  }
11959  else
11960  {
11961  safe = false;
11962  if (ch == '"')
11963  nquotes++;
11964  }
11965  }
11966 
11968  safe = false;
11969 
11970  if (safe)
11971  {
11972  /*
11973  * Check for keyword. We quote keywords except for unreserved ones.
11974  * (In some cases we could avoid quoting a col_name or type_func_name
11975  * keyword, but it seems much harder than it's worth to tell that.)
11976  *
11977  * Note: ScanKeywordLookup() does case-insensitive comparison, but
11978  * that's fine, since we already know we have all-lower-case.
11979  */
11980  int kwnum = ScanKeywordLookup(ident, &ScanKeywords);
11981 
11982  if (kwnum >= 0 && ScanKeywordCategories[kwnum] != UNRESERVED_KEYWORD)
11983  safe = false;
11984  }
11985 
11986  if (safe)
11987  return ident; /* no change needed */
11988 
11989  result = (char *) palloc(strlen(ident) + nquotes + 2 + 1);
11990 
11991  optr = result;
11992  *optr++ = '"';
11993  for (ptr = ident; *ptr; ptr++)
11994  {
11995  char ch = *ptr;
11996 
11997  if (ch == '"')
11998  *optr++ = '"';
11999  *optr++ = ch;
12000  }
12001  *optr++ = '"';
12002  *optr = '\0';
12003 
12004  return result;
12005 }
const uint8 ScanKeywordCategories[SCANKEYWORDS_NUM_KEYWORDS]
Definition: keywords.c:29
#define ident
Definition: indent_codes.h:47
PGDLLIMPORT const ScanKeywordList ScanKeywords
#define UNRESERVED_KEYWORD
Definition: keywords.h:20
int ScanKeywordLookup(const char *str, const ScanKeywordList *keywords)
Definition: kwlookup.c:38
void * palloc(Size size)
Definition: mcxt.c:1226
bool quote_all_identifiers
Definition: ruleutils.c:324

◆ reap_child()

bool reap_child ( bool  wait_for_child)

Definition at line 278 of file parallel.c.

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

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

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

◆ report_clusters_compatible()

void report_clusters_compatible ( void  )

Definition at line 217 of file check.c.

218 {
219  if (user_opts.check)
220  {
221  pg_log(PG_REPORT, "\n*Clusters are compatible*");
222  /* stops new cluster */
223  stop_postmaster(false);
224 
226  exit(0);
227  }
228 
229  pg_log(PG_REPORT, "\n"
230  "If pg_upgrade fails after this point, you must re-initdb the\n"
231  "new cluster before continuing.");
232 }
void cleanup_output_dirs(void)
Definition: util.c:63

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

Referenced by main().

◆ report_extension_updates()

void report_extension_updates ( ClusterInfo cluster)

Definition at line 396 of file version.c.

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

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

Referenced by issue_warnings_and_set_wal_level().

◆ report_status()

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

◆ rewriteVisibilityMap()

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

Definition at line 176 of file file.c.

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

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

Referenced by transfer_relfile().

◆ start_postmaster()

bool start_postmaster ( ClusterInfo cluster,
bool  report_and_exit_on_error 
)

Definition at line 198 of file server.c.

199 {
200  char cmd[MAXPGPATH * 4 + 1000];
201  PGconn *conn;
202  bool pg_ctl_return = false;
203  char socket_string[MAXPGPATH + 200];
204 
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(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  snprintf(cmd, sizeof(cmd),
239  "\"%s/pg_ctl\" -w -l \"%s/%s\" -D \"%s\" -o \"-p %d -b%s %s%s\" start",
240  cluster->bindir,
242  SERVER_LOG_FILE, cluster->pgconfig, cluster->port,
243  (cluster == &new_cluster) ?
244  " -c synchronous_commit=off -c fsync=off -c full_page_writes=off" : "",
245  cluster->pgopts ? cluster->pgopts : "", socket_string);
246 
247  /*
248  * Don't throw an error right away, let connecting throw the error because
249  * it might supply a reason for the failure.
250  */
251  pg_ctl_return = exec_prog(SERVER_START_LOG_FILE,
252  /* pass both file names if they differ */
253  (strcmp(SERVER_LOG_FILE,
254  SERVER_START_LOG_FILE) != 0) ?
255  SERVER_LOG_FILE : NULL,
256  report_and_exit_on_error, false,
257  "%s", cmd);
258 
259  /* Did it fail and we are just testing if the server could be started? */
260  if (!pg_ctl_return && !report_and_exit_on_error)
261  return false;
262 
263  /*
264  * We set this here to make sure atexit() shuts down the server, but only
265  * if we started the server successfully. We do it before checking for
266  * connectivity in case the server started but there is a connectivity
267  * failure. If pg_ctl did not return success, we will exit below.
268  *
269  * Pre-9.1 servers do not have PQping(), so we could be leaving the server
270  * running if authentication was misconfigured, so someday we might went
271  * to be more aggressive about doing server shutdowns even if pg_ctl
272  * fails, but now (2013-08-14) it seems prudent to be cautious. We don't
273  * want to shutdown a server that might have been accidentally started
274  * during the upgrade.
275  */
276  if (pg_ctl_return)
278 
279  /*
280  * pg_ctl -w might have failed because the server couldn't be started, or
281  * there might have been a connection problem in _checking_ if the server
282  * has started. Therefore, even if pg_ctl failed, we continue and test
283  * for connectivity in case we get a connection reason for the failure.
284  */
285  if ((conn = get_db_conn(cluster, "template1")) == NULL ||
287  {
288  pg_log(PG_REPORT, "\n%s", PQerrorMessage(conn));
289  if (conn)
290  PQfinish(conn);
291  if (cluster == &old_cluster)
292  pg_fatal("could not connect to source postmaster started with the command:\n"
293  "%s",
294  cmd);
295  else
296  pg_fatal("could not connect to target postmaster started with the command:\n"
297  "%s",
298  cmd);
299  }
300  PQfinish(conn);
301 
302  /*
303  * If pg_ctl failed, and the connection didn't fail, and
304  * report_and_exit_on_error is enabled, fail now. This could happen if
305  * the server was already running.
306  */
307  if (!pg_ctl_return)
308  {
309  if (cluster == &old_cluster)
310  pg_fatal("pg_ctl failed to start the source server, or connection failed");
311  else
312  pg_fatal("pg_ctl failed to start the target server, or connection failed");
313  }
314 
315  return true;
316 }
#define SERVER_START_LOG_FILE
Definition: pg_upgrade.h:67
#define SERVER_LOG_FILE
Definition: pg_upgrade.h:44
static void stop_postmaster_atexit(void)
Definition: server.c:191
char * logdir
Definition: pg_upgrade.h:291
ClusterInfo * running_cluster
Definition: pg_upgrade.h:327

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

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

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

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

◆ str2uint()

void void unsigned int str2uint ( const char *  str)

Definition at line 352 of file util.c.

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

References generate_unaccent_rules::str.

Referenced by get_control_data().

◆ transfer_all_new_dbs()

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

Definition at line 86 of file relfilenumber.c.

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

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

Referenced by parallel_transfer_all_new_dbs().

◆ transfer_all_new_tablespaces()

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

Definition at line 29 of file relfilenumber.c.

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

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

Referenced by main().

◆ verify_directories()

bool void verify_directories ( void  )

Definition at line 265 of file exec.c.

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

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

Referenced by setup().

Variable Documentation

◆ log_opts

◆ new_cluster

ClusterInfo new_cluster

Definition at line 337 of file pg_upgrade.h.

◆ old_cluster

◆ os_info

◆ output_files

char* output_files[]
extern

Definition at line 67 of file pg_upgrade.c.

Referenced by make_outputdirs().

◆ user_opts