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

Go to the source code of this file.

Data Structures

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

Macros

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

Typedefs

typedef bool(* DataTypesUsageVersionCheck) (ClusterInfo *cluster)
 
typedef void(* UpgradeTaskProcessCB) (DbInfo *dbinfo, PGresult *res, void *arg)
 
typedef struct UpgradeTask UpgradeTask
 

Enumerations

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

Functions

void output_check_banner (void)
 
void check_and_dump_old_cluster (void)
 
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 (void)
 
void create_script_for_old_cluster_deletion (char **deletion_script_file_name)
 
void get_control_data (ClusterInfo *cluster)
 
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 copyFileByRange (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_copy_file_range (void)
 
void check_hard_link (void)
 
void get_loadable_libraries (void)
 
void check_loadable_libraries (void)
 
FileNameMapgen_db_file_maps (DbInfo *old_db, DbInfo *new_db, int *nmaps, const char *old_pgdata, const char *new_pgdata)
 
void get_db_rel_and_slot_infos (ClusterInfo *cluster)
 
int count_old_cluster_logical_slots (void)
 
void get_subscription_count (ClusterInfo *cluster)
 
void parseCommandLine (int argc, char *argv[])
 
void adjust_data_dir (ClusterInfo *cluster)
 
void get_sock_dir (ClusterInfo *cluster)
 
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 jsonb_9_4_check_applicable (ClusterInfo *cluster)
 
void old_9_6_invalidate_hash_indexes (ClusterInfo *cluster, bool check_mode)
 
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)
 
UpgradeTaskupgrade_task_create (void)
 
void upgrade_task_add_step (UpgradeTask *task, const char *query, UpgradeTaskProcessCB process_cb, bool free_result, void *arg)
 
void upgrade_task_run (const UpgradeTask *task, const ClusterInfo *cluster)
 
void upgrade_task_free (UpgradeTask *task)
 

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

◆ fopen_priv

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

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

◆ LARGE_OBJECT_SIZE_PG_CONTROL_VER

#define LARGE_OBJECT_SIZE_PG_CONTROL_VER   942

Definition at line 121 of file pg_upgrade.h.

◆ LOG_OUTPUTDIR

#define LOG_OUTPUTDIR   "log"

Definition at line 40 of file pg_upgrade.h.

◆ MAX_STRING

#define MAX_STRING   1024

Definition at line 22 of file pg_upgrade.h.

◆ MESSAGE_WIDTH

#define MESSAGE_WIDTH   62

Definition at line 25 of file pg_upgrade.h.

◆ MULTIXACT_FORMATCHANGE_CAT_VER

#define MULTIXACT_FORMATCHANGE_CAT_VER   201301231

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

Typedef Documentation

◆ DataTypesUsageVersionCheck

typedef bool(* DataTypesUsageVersionCheck) (ClusterInfo *cluster)

Definition at line 355 of file pg_upgrade.h.

◆ UpgradeTask

typedef struct UpgradeTask UpgradeTask

Definition at line 500 of file pg_upgrade.h.

◆ UpgradeTaskProcessCB

typedef void(* UpgradeTaskProcessCB) (DbInfo *dbinfo, PGresult *res, void *arg)

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

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

◆ transferMode

Enumerator
TRANSFER_MODE_CLONE 
TRANSFER_MODE_COPY 
TRANSFER_MODE_COPY_FILE_RANGE 
TRANSFER_MODE_LINK 

Definition at line 253 of file pg_upgrade.h.

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

Function Documentation

◆ adjust_data_dir()

void adjust_data_dir ( ClusterInfo cluster)

Definition at line 404 of file option.c.

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

◆ check_and_dump_old_cluster()

void check_and_dump_old_cluster ( void  )

Definition at line 607 of file check.c.

608 {
609  /* -- OLD -- */
610 
611  if (!user_opts.live_check)
613 
614  /*
615  * Extract a list of databases, tables, and logical replication slots from
616  * the old cluster.
617  */
619 
621 
623 
624 
625  /*
626  * Check for various failure cases
627  */
632 
634  {
635  /*
636  * Logical replication slots can be migrated since PG17. See comments
637  * atop get_old_cluster_logical_slot_infos().
638  */
640 
641  /*
642  * Subscriptions and their dependencies can be migrated since PG17.
643  * Before that the logical slots are not upgraded, so we will not be
644  * able to upgrade the logical replication clusters completely.
645  */
648  }
649 
651 
652  /*
653  * PG 14 changed the function signature of encoding conversion functions.
654  * Conversions from older versions cannot be upgraded automatically
655  * because the user-defined functions used by the encoding conversions
656  * need to be changed to match the new signature.
657  */
660 
661  /*
662  * Pre-PG 14 allowed user defined postfix operators, which are not
663  * supported anymore. Verify there are none, iff applicable.
664  */
667 
668  /*
669  * PG 14 changed polymorphic functions from anyarray to
670  * anycompatiblearray.
671  */
674 
675  /*
676  * Pre-PG 12 allowed tables to be declared WITH OIDS, which is not
677  * supported anymore. Verify there are none, iff applicable.
678  */
681 
682  /*
683  * Pre-PG 10 allowed tables with 'unknown' type columns and non WAL logged
684  * hash indexes
685  */
687  {
688  if (user_opts.check)
690  }
691 
692  /* 9.5 and below should not have roles starting with pg_ */
695 
696  /*
697  * While not a check option, we do this now because this is the only time
698  * the old server is running.
699  */
700  if (!user_opts.check)
702 
703  if (!user_opts.live_check)
704  stop_postmaster(false);
705 }
static void check_for_tables_with_oids(ClusterInfo *cluster)
Definition: check.c:1591
static void check_for_pg_role_prefix(ClusterInfo *cluster)
Definition: check.c:1635
static void check_for_data_types_usage(ClusterInfo *cluster)
Definition: check.c:478
static void check_old_cluster_subscription_state(void)
Definition: check.c:2005
static void check_is_install_user(ClusterInfo *cluster)
Definition: check.c:1060
static void check_for_isn_and_int8_passing_mismatch(ClusterInfo *cluster)
Definition: check.c:1270
static void check_old_cluster_for_valid_slots(void)
Definition: check.c:1898
static void check_for_user_defined_postfix_ops(ClusterInfo *cluster)
Definition: check.c:1363
static void check_for_prepared_transactions(ClusterInfo *cluster)
Definition: check.c:1202
static void check_proper_datallowconn(ClusterInfo *cluster)
Definition: check.c:1118
static void check_for_user_defined_encoding_conversions(ClusterInfo *cluster)
Definition: check.c:1729
static void check_for_incompatible_polymorphics(ClusterInfo *cluster)
Definition: check.c:1457
void generate_old_dump(void)
Definition: dump.c:16
void get_loadable_libraries(void)
Definition: function.c:79
void get_subscription_count(ClusterInfo *cluster)
Definition: info.c:758
void get_db_rel_and_slot_infos(ClusterInfo *cluster)
Definition: info.c:280
static pid_t start_postmaster(void)
Definition: pg_ctl.c:440
void init_tablespaces(void)
Definition: tablespace.c:19
#define GET_MAJOR_VERSION(v)
Definition: pg_upgrade.h:27
void stop_postmaster(bool in_atexit)
Definition: server.c:342
void old_9_6_invalidate_hash_indexes(ClusterInfo *cluster, bool check_mode)
Definition: version.c:37
UserOpts user_opts
Definition: option.c:30
uint32 major_version
Definition: pg_upgrade.h:293
bool live_check
Definition: pg_upgrade.h:324
bool check
Definition: pg_upgrade.h:323

References UserOpts::check, 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_old_cluster_for_valid_slots(), check_old_cluster_subscription_state(), check_proper_datallowconn(), generate_old_dump(), get_db_rel_and_slot_infos(), get_loadable_libraries(), GET_MAJOR_VERSION, get_subscription_count(), init_tablespaces(), UserOpts::live_check, ClusterInfo::major_version, 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 ( void  )

Definition at line 862 of file check.c.

863 {
864  /* get/check pg_control data of servers */
868 
870  pg_fatal("When checking a live server, "
871  "the old and new port numbers must be different.");
872 }
void get_control_data(ClusterInfo *cluster)
Definition: controldata.c:36
void check_control_data(ControlData *oldctrl, ControlData *newctrl)
Definition: controldata.c:655
ClusterInfo new_cluster
Definition: pg_upgrade.c:68
unsigned short port
Definition: pg_upgrade.h:292
ControlData controldata
Definition: pg_upgrade.h:282

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

Referenced by main().

◆ check_cluster_versions()

void check_cluster_versions ( void  )

Definition at line 819 of file check.c.

820 {
821  prep_status("Checking cluster versions");
822 
823  /* cluster versions should already have been obtained */
826 
827  /*
828  * We allow upgrades from/to the same major version for alpha/beta
829  * upgrades
830  */
831 
833  pg_fatal("This utility can only upgrade from PostgreSQL version %s and later.",
834  "9.2");
835 
836  /* Only current PG version is supported as a target */
838  pg_fatal("This utility can only upgrade to PostgreSQL version %s.",
839  PG_MAJORVERSION);
840 
841  /*
842  * We can't allow downgrading because we use the target pg_dump, and
843  * pg_dump cannot operate on newer database versions, only current and
844  * older versions.
845  */
847  pg_fatal("This utility cannot be used to downgrade to older major PostgreSQL versions.");
848 
849  /* Ensure binaries match the designated data directories */
852  pg_fatal("Old cluster data and binary directories are from different major versions.");
855  pg_fatal("New cluster data and binary directories are from different major versions.");
856 
857  check_ok();
858 }
#define Assert(condition)
Definition: c.h:858
uint32 bin_version
Definition: pg_upgrade.h:295

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:247
uint32 toast
Definition: pg_upgrade.h:243
uint32 index
Definition: pg_upgrade.h:242
uint32 walseg
Definition: pg_upgrade.h:240
uint32 blocksz
Definition: pg_upgrade.h:237
uint32 walsz
Definition: pg_upgrade.h:239
uint32 ident
Definition: pg_upgrade.h:241
bool date_is_int
Definition: pg_upgrade.h:245
uint32 large_object
Definition: pg_upgrade.h:244
uint32 align
Definition: pg_upgrade.h:236
uint32 largesz
Definition: pg_upgrade.h:238

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

void check_copy_file_range ( void  )

Definition at line 400 of file file.c.

401 {
402  char existing_file[MAXPGPATH];
403  char new_link_file[MAXPGPATH];
404 
405  snprintf(existing_file, sizeof(existing_file), "%s/PG_VERSION", old_cluster.pgdata);
406  snprintf(new_link_file, sizeof(new_link_file), "%s/PG_VERSION.copy_file_range_test", new_cluster.pgdata);
407  unlink(new_link_file); /* might fail */
408 
409 #if defined(HAVE_COPY_FILE_RANGE)
410  {
411  int src_fd;
412  int dest_fd;
413 
414  if ((src_fd = open(existing_file, O_RDONLY | PG_BINARY, 0)) < 0)
415  pg_fatal("could not open file \"%s\": %m",
416  existing_file);
417 
418  if ((dest_fd = open(new_link_file, O_RDWR | O_CREAT | O_EXCL | PG_BINARY,
419  pg_file_create_mode)) < 0)
420  pg_fatal("could not create file \"%s\": %m",
421  new_link_file);
422 
423  if (copy_file_range(src_fd, NULL, dest_fd, NULL, SSIZE_MAX, 0) < 0)
424  pg_fatal("could not copy file range between old and new data directories: %m");
425 
426  close(src_fd);
427  close(dest_fd);
428  }
429 #else
430  pg_fatal("copy_file_range not supported on this platform");
431 #endif
432 
433  unlink(new_link_file);
434 }
#define PG_BINARY
Definition: c.h:1273
int pg_file_create_mode
Definition: file_perm.c:19
#define close(a)
Definition: win32.h:12
char * pgdata
Definition: pg_upgrade.h:285

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

Referenced by check_new_cluster().

◆ check_file_clone()

void check_file_clone ( void  )

Definition at line 360 of file file.c.

361 {
362  char existing_file[MAXPGPATH];
363  char new_link_file[MAXPGPATH];
364 
365  snprintf(existing_file, sizeof(existing_file), "%s/PG_VERSION", old_cluster.pgdata);
366  snprintf(new_link_file, sizeof(new_link_file), "%s/PG_VERSION.clonetest", new_cluster.pgdata);
367  unlink(new_link_file); /* might fail */
368 
369 #if defined(HAVE_COPYFILE) && defined(COPYFILE_CLONE_FORCE)
370  if (copyfile(existing_file, new_link_file, NULL, COPYFILE_CLONE_FORCE) < 0)
371  pg_fatal("could not clone file between old and new data directories: %m");
372 #elif defined(__linux__) && defined(FICLONE)
373  {
374  int src_fd;
375  int dest_fd;
376 
377  if ((src_fd = open(existing_file, O_RDONLY | PG_BINARY, 0)) < 0)
378  pg_fatal("could not open file \"%s\": %m",
379  existing_file);
380 
381  if ((dest_fd = open(new_link_file, O_RDWR | O_CREAT | O_EXCL | PG_BINARY,
382  pg_file_create_mode)) < 0)
383  pg_fatal("could not create file \"%s\": %m",
384  new_link_file);
385 
386  if (ioctl(dest_fd, FICLONE, src_fd) < 0)
387  pg_fatal("could not clone file between old and new data directories: %m");
388 
389  close(src_fd);
390  close(dest_fd);
391  }
392 #else
393  pg_fatal("file cloning not supported on this platform");
394 #endif
395 
396  unlink(new_link_file);
397 }

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

Referenced by check_new_cluster().

◆ check_hard_link()

void check_hard_link ( void  )

Definition at line 437 of file file.c.

438 {
439  char existing_file[MAXPGPATH];
440  char new_link_file[MAXPGPATH];
441 
442  snprintf(existing_file, sizeof(existing_file), "%s/PG_VERSION", old_cluster.pgdata);
443  snprintf(new_link_file, sizeof(new_link_file), "%s/PG_VERSION.linktest", new_cluster.pgdata);
444  unlink(new_link_file); /* might fail */
445 
446  if (link(existing_file, new_link_file) < 0)
447  pg_fatal("could not create hard link between old and new data directories: %m\n"
448  "In link mode the old and new data directories must be on the same file system.");
449 
450  unlink(new_link_file);
451 }

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

Referenced by check_new_cluster().

◆ check_loadable_libraries()

void check_loadable_libraries ( void  )

Definition at line 165 of file function.c.

166 {
167  PGconn *conn = connectToServer(&new_cluster, "template1");
168  int libnum;
169  int was_load_failure = false;
170  FILE *script = NULL;
171  char output_path[MAXPGPATH];
172 
173  prep_status("Checking for presence of required libraries");
174 
175  snprintf(output_path, sizeof(output_path), "%s/%s",
176  log_opts.basedir, "loadable_libraries.txt");
177 
178  /*
179  * Now we want to sort the library names into order. This avoids multiple
180  * probes of the same library, and ensures that libraries are probed in a
181  * consistent order, which is important for reproducible behavior if one
182  * library depends on another.
183  */
186 
187  for (libnum = 0; libnum < os_info.num_libraries; libnum++)
188  {
189  char *lib = os_info.libraries[libnum].name;
190  int llen = strlen(lib);
191  char cmd[7 + 2 * MAXPGPATH + 1];
192  PGresult *res;
193 
194  /* Did the library name change? Probe it. */
195  if (libnum == 0 || strcmp(lib, os_info.libraries[libnum - 1].name) != 0)
196  {
197  strcpy(cmd, "LOAD '");
198  PQescapeStringConn(conn, cmd + strlen(cmd), lib, llen, NULL);
199  strcat(cmd, "'");
200 
201  res = PQexec(conn, cmd);
202 
204  {
205  was_load_failure = true;
206 
207  if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL)
208  pg_fatal("could not open file \"%s\": %m", output_path);
209  fprintf(script, _("could not load library \"%s\": %s"),
210  lib,
212  }
213  else
214  was_load_failure = false;
215 
216  PQclear(res);
217  }
218 
219  if (was_load_failure)
220  fprintf(script, _("In database: %s\n"),
222  }
223 
224  PQfinish(conn);
225 
226  if (script)
227  {
228  fclose(script);
229  pg_log(PG_REPORT, "fatal");
230  pg_fatal("Your installation references loadable libraries that are missing from the\n"
231  "new installation. You can add these libraries to the new installation,\n"
232  "or remove the functions using them from the old installation. A list of\n"
233  "problem libraries is in the file:\n"
234  " %s", output_path);
235  }
236  else
237  check_ok();
238 }
#define _(x)
Definition: elog.c:90
char * PQerrorMessage(const PGconn *conn)
Definition: fe-connect.c:7182
void PQfinish(PGconn *conn)
Definition: fe-connect.c:4893
size_t PQescapeStringConn(PGconn *conn, char *to, const char *from, size_t length, int *error)
Definition: fe-exec.c:4145
ExecStatusType PQresultStatus(const PGresult *res)
Definition: fe-exec.c:3411
PGresult * PQexec(PGconn *conn, const char *query)
Definition: fe-exec.c:2262
static int library_name_compare(const void *p1, const void *p2)
Definition: function.c:29
@ PGRES_COMMAND_OK
Definition: libpq-fe.h:120
OSInfo os_info
Definition: pg_upgrade.c:69
void void pg_log(eLogType type, const char *fmt,...) pg_attribute_printf(2
LogOpts log_opts
Definition: util.c:17
#define fopen_priv(path, mode)
Definition: pg_upgrade.h:419
PGconn * connectToServer(ClusterInfo *cluster, const char *db_name)
Definition: server.c:28
#define fprintf
Definition: port.h:242
#define qsort(a, b, c, d)
Definition: port.h:447
PGconn * conn
Definition: streamutil.c:55
DbInfoArr dbarr
Definition: pg_upgrade.h:284
DbInfo * dbs
Definition: pg_upgrade.h:215
char * db_name
Definition: pg_upgrade.h:194
char * name
Definition: pg_upgrade.h:334
char * basedir
Definition: pg_upgrade.h:311
LibraryInfo * libraries
Definition: pg_upgrade.h:348
int num_libraries
Definition: pg_upgrade.h:349

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, and snprintf.

Referenced by check_new_cluster().

◆ check_new_cluster()

void check_new_cluster ( void  )

Definition at line 709 of file check.c.

710 {
712 
714 
716 
717  switch (user_opts.transfer_mode)
718  {
719  case TRANSFER_MODE_CLONE:
721  break;
722  case TRANSFER_MODE_COPY:
723  break;
726  break;
727  case TRANSFER_MODE_LINK:
728  check_hard_link();
729  break;
730  }
731 
733 
735 
737 
739 
741 }
static void check_new_cluster_logical_replication_slots(void)
Definition: check.c:1782
static void check_new_cluster_subscription_configuration(void)
Definition: check.c:1855
static void check_new_cluster_is_empty(void)
Definition: check.c:876
static void check_for_new_tablespace_dir(void)
Definition: check.c:908
void check_file_clone(void)
Definition: file.c:360
void check_hard_link(void)
Definition: file.c:437
void check_copy_file_range(void)
Definition: file.c:400
void check_loadable_libraries(void)
Definition: function.c:165
transferMode transfer_mode
Definition: pg_upgrade.h:326

References check_copy_file_range(), check_file_clone(), check_for_new_tablespace_dir(), check_for_prepared_transactions(), check_hard_link(), check_is_install_user(), check_loadable_libraries(), check_new_cluster_is_empty(), check_new_cluster_logical_replication_slots(), check_new_cluster_subscription_configuration(), get_db_rel_and_slot_infos(), new_cluster, UserOpts::transfer_mode, TRANSFER_MODE_CLONE, TRANSFER_MODE_COPY, TRANSFER_MODE_COPY_FILE_RANGE, 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 369 of file server.c.

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

References is_unixsock_path(), pg_fatal, PQconndefaults(), PQconninfoFree(), start, 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:310
bool retain
Definition: pg_upgrade.h:308
FILE * internal
Definition: pg_upgrade.h:306
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 39 of file file.c.

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

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

Referenced by transfer_relfile().

◆ cluster_conn_opts()

PGresult char* cluster_conn_opts ( ClusterInfo cluster)

Definition at line 92 of file server.c.

93 {
94  static PQExpBuffer buf;
95 
96  if (buf == NULL)
98  else
100 
101  if (cluster->sockdir)
102  {
103  appendPQExpBufferStr(buf, "--host ");
104  appendShellString(buf, cluster->sockdir);
106  }
107  appendPQExpBuffer(buf, "--port %d --username ", cluster->port);
109 
110  return buf->data;
111 }
static char * buf
Definition: pg_test_fsync.c:73
PQExpBuffer createPQExpBuffer(void)
Definition: pqexpbuffer.c:72
void resetPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:146
void appendPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:265
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:344

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:7119
@ CONNECTION_OK
Definition: libpq-fe.h:81
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_pg_role_prefix(), check_for_prepared_transactions(), check_is_install_user(), check_loadable_libraries(), check_new_cluster_logical_replication_slots(), check_new_cluster_subscription_configuration(), check_old_cluster_subscription_state(), check_proper_datallowconn(), create_logical_replication_slots(), create_new_objects(), get_db_infos(), get_subscription_count(), get_tablespace_paths(), get_template0_info(), old_9_6_invalidate_hash_indexes(), 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 82 of file file.c.

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

Referenced by transfer_relfile().

◆ copyFileByRange()

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

Definition at line 151 of file file.c.

153 {
154 #ifdef HAVE_COPY_FILE_RANGE
155  int src_fd;
156  int dest_fd;
157  ssize_t nbytes;
158 
159  if ((src_fd = open(src, O_RDONLY | PG_BINARY, 0)) < 0)
160  pg_fatal("error while copying relation \"%s.%s\": could not open file \"%s\": %m",
161  schemaName, relName, src);
162 
163  if ((dest_fd = open(dst, O_RDWR | O_CREAT | O_EXCL | PG_BINARY,
164  pg_file_create_mode)) < 0)
165  pg_fatal("error while copying relation \"%s.%s\": could not create file \"%s\": %m",
166  schemaName, relName, dst);
167 
168  do
169  {
170  nbytes = copy_file_range(src_fd, NULL, dest_fd, NULL, SSIZE_MAX, 0);
171  if (nbytes < 0)
172  pg_fatal("error while copying relation \"%s.%s\": could not copy file range from \"%s\" to \"%s\": %m",
173  schemaName, relName, src, dst);
174  }
175  while (nbytes > 0);
176 
177  close(src_fd);
178  close(dest_fd);
179 #endif
180 }

References close, PG_BINARY, pg_fatal, and pg_file_create_mode.

Referenced by transfer_relfile().

◆ count_old_cluster_logical_slots()

int count_old_cluster_logical_slots ( void  )

Definition at line 742 of file info.c.

743 {
744  int slot_count = 0;
745 
746  for (int dbnum = 0; dbnum < old_cluster.dbarr.ndbs; dbnum++)
747  slot_count += old_cluster.dbarr.dbs[dbnum].slot_arr.nslots;
748 
749  return slot_count;
750 }
LogicalSlotInfoArr slot_arr
Definition: pg_upgrade.h:198

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

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

◆ create_script_for_old_cluster_deletion()

void create_script_for_old_cluster_deletion ( char **  deletion_script_file_name)

Definition at line 937 of file check.c.

938 {
939  FILE *script = NULL;
940  int tblnum;
941  char old_cluster_pgdata[MAXPGPATH],
942  new_cluster_pgdata[MAXPGPATH];
943 
944  *deletion_script_file_name = psprintf("%sdelete_old_cluster.%s",
946 
947  strlcpy(old_cluster_pgdata, old_cluster.pgdata, MAXPGPATH);
948  canonicalize_path(old_cluster_pgdata);
949 
950  strlcpy(new_cluster_pgdata, new_cluster.pgdata, MAXPGPATH);
951  canonicalize_path(new_cluster_pgdata);
952 
953  /* Some people put the new data directory inside the old one. */
954  if (path_is_prefix_of_path(old_cluster_pgdata, new_cluster_pgdata))
955  {
957  "\nWARNING: new data directory should not be inside the old data directory, i.e. %s", old_cluster_pgdata);
958 
959  /* Unlink file in case it is left over from a previous run. */
960  unlink(*deletion_script_file_name);
961  pg_free(*deletion_script_file_name);
962  *deletion_script_file_name = NULL;
963  return;
964  }
965 
966  /*
967  * Some users (oddly) create tablespaces inside the cluster data
968  * directory. We can't create a proper old cluster delete script in that
969  * case.
970  */
971  for (tblnum = 0; tblnum < os_info.num_old_tablespaces; tblnum++)
972  {
973  char old_tablespace_dir[MAXPGPATH];
974 
975  strlcpy(old_tablespace_dir, os_info.old_tablespaces[tblnum], MAXPGPATH);
976  canonicalize_path(old_tablespace_dir);
977  if (path_is_prefix_of_path(old_cluster_pgdata, old_tablespace_dir))
978  {
979  /* reproduce warning from CREATE TABLESPACE that is in the log */
981  "\nWARNING: user-defined tablespace locations should not be inside the data directory, i.e. %s", old_tablespace_dir);
982 
983  /* Unlink file in case it is left over from a previous run. */
984  unlink(*deletion_script_file_name);
985  pg_free(*deletion_script_file_name);
986  *deletion_script_file_name = NULL;
987  return;
988  }
989  }
990 
991  prep_status("Creating script to delete old cluster");
992 
993  if ((script = fopen_priv(*deletion_script_file_name, "w")) == NULL)
994  pg_fatal("could not open file \"%s\": %m",
995  *deletion_script_file_name);
996 
997 #ifndef WIN32
998  /* add shebang header */
999  fprintf(script, "#!/bin/sh\n\n");
1000 #endif
1001 
1002  /* delete old cluster's default tablespace */
1003  fprintf(script, RMDIR_CMD " %c%s%c\n", PATH_QUOTE,
1005 
1006  /* delete old cluster's alternate tablespaces */
1007  for (tblnum = 0; tblnum < os_info.num_old_tablespaces; tblnum++)
1008  {
1009  /*
1010  * Do the old cluster's per-database directories share a directory
1011  * with a new version-specific tablespace?
1012  */
1013  if (strlen(old_cluster.tablespace_suffix) == 0)
1014  {
1015  /* delete per-database directories */
1016  int dbnum;
1017 
1018  fprintf(script, "\n");
1019 
1020  for (dbnum = 0; dbnum < old_cluster.dbarr.ndbs; dbnum++)
1021  fprintf(script, RMDIR_CMD " %c%s%c%u%c\n", PATH_QUOTE,
1024  PATH_QUOTE);
1025  }
1026  else
1027  {
1028  char *suffix_path = pg_strdup(old_cluster.tablespace_suffix);
1029 
1030  /*
1031  * Simply delete the tablespace directory, which might be ".old"
1032  * or a version-specific subdirectory.
1033  */
1034  fprintf(script, RMDIR_CMD " %c%s%s%c\n", PATH_QUOTE,
1036  fix_path_separator(suffix_path), PATH_QUOTE);
1037  pfree(suffix_path);
1038  }
1039  }
1040 
1041  fclose(script);
1042 
1043 #ifndef WIN32
1044  if (chmod(*deletion_script_file_name, S_IRWXU) != 0)
1045  pg_fatal("could not add execute permission to file \"%s\": %m",
1046  *deletion_script_file_name);
1047 #endif
1048 
1049  check_ok();
1050 }
static char * fix_path_separator(char *path)
Definition: check.c:568
void pfree(void *pointer)
Definition: mcxt.c:1521
#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:560
void canonicalize_path(char *path)
Definition: path.c:265
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition: strlcpy.c:45
char * psprintf(const char *fmt,...)
Definition: psprintf.c:46
const char * tablespace_suffix
Definition: pg_upgrade.h:296
Oid db_oid
Definition: pg_upgrade.h:193
int num_old_tablespaces
Definition: pg_upgrade.h:347
char ** old_tablespaces
Definition: pg_upgrade.h:346
#define S_IRWXU
Definition: win32_port.h:298

References canonicalize_path(), check_ok(), DbInfo::db_oid, ClusterInfo::dbarr, DbInfoArr::dbs, fix_path_separator(), fopen_priv, fprintf, MAXPGPATH, DbInfoArr::ndbs, new_cluster, OSInfo::num_old_tablespaces, old_cluster, OSInfo::old_tablespaces, os_info, path_is_prefix_of_path(), PATH_QUOTE, PATH_SEPARATOR, pfree(), pg_fatal, pg_free(), pg_log(), pg_strdup(), PG_WARNING, ClusterInfo::pgdata, prep_status(), psprintf(), RMDIR_CMD, S_IRWXU, SCRIPT_EXT, SCRIPT_PREFIX, 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:314
bool verbose
Definition: pg_upgrade.h:307

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

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

◆ exec_prog()

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

◆ executeQueryOrDie()

◆ gen_db_file_maps()

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

Definition at line 45 of file info.c.

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

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

Referenced by transfer_all_new_dbs().

◆ generate_old_dump()

void generate_old_dump ( void  )

Definition at line 16 of file dump.c.

17 {
18  int dbnum;
19 
20  prep_status("Creating dump of global objects");
21 
22  /* run new pg_dumpall binary for globals */
23  exec_prog(UTILITY_LOG_FILE, NULL, true, true,
24  "\"%s/pg_dumpall\" %s --globals-only --quote-all-identifiers "
25  "--binary-upgrade %s --no-sync -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 --no-sync --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:85
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 initPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:90
void termPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:129
void appendConnStrVal(PQExpBuffer buf, const char *str)
Definition: string_utils.c:545
char * bindir
Definition: pg_upgrade.h:288
char * dumpdir
Definition: pg_upgrade.h:312

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)

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  bool live_check = (cluster == &old_cluster && user_opts.live_check);
80 
81  /*
82  * Because we test the pg_resetwal output as strings, it has to be in
83  * English. Copied from pg_regress.c.
84  */
85  if (getenv("LC_COLLATE"))
86  lc_collate = pg_strdup(getenv("LC_COLLATE"));
87  if (getenv("LC_CTYPE"))
88  lc_ctype = pg_strdup(getenv("LC_CTYPE"));
89  if (getenv("LC_MONETARY"))
90  lc_monetary = pg_strdup(getenv("LC_MONETARY"));
91  if (getenv("LC_NUMERIC"))
92  lc_numeric = pg_strdup(getenv("LC_NUMERIC"));
93  if (getenv("LC_TIME"))
94  lc_time = pg_strdup(getenv("LC_TIME"));
95  if (getenv("LANG"))
96  lang = pg_strdup(getenv("LANG"));
97  if (getenv("LANGUAGE"))
98  language = pg_strdup(getenv("LANGUAGE"));
99  if (getenv("LC_ALL"))
100  lc_all = pg_strdup(getenv("LC_ALL"));
101  if (getenv("LC_MESSAGES"))
102  lc_messages = pg_strdup(getenv("LC_MESSAGES"));
103 
104  unsetenv("LC_COLLATE");
105  unsetenv("LC_CTYPE");
106  unsetenv("LC_MONETARY");
107  unsetenv("LC_NUMERIC");
108  unsetenv("LC_TIME");
109 #ifndef WIN32
110  unsetenv("LANG");
111 #else
112  /* On Windows the default locale may not be English, so force it */
113  setenv("LANG", "en", 1);
114 #endif
115  unsetenv("LANGUAGE");
116  unsetenv("LC_ALL");
117  setenv("LC_MESSAGES", "C", 1);
118 
119  /*
120  * Check for clean shutdown
121  */
122  if (!live_check || cluster == &new_cluster)
123  {
124  /* only pg_controldata outputs the cluster state */
125  snprintf(cmd, sizeof(cmd), "\"%s/pg_controldata\" \"%s\"",
126  cluster->bindir, cluster->pgdata);
127  fflush(NULL);
128 
129  if ((output = popen(cmd, "r")) == NULL)
130  pg_fatal("could not get control data using %s: %m", cmd);
131 
132  /* we have the result of cmd in "output". so parse it line by line now */
133  while (fgets(bufin, sizeof(bufin), output))
134  {
135  if ((p = strstr(bufin, "Database cluster state:")) != NULL)
136  {
137  p = strchr(p, ':');
138 
139  if (p == NULL || strlen(p) <= 1)
140  pg_fatal("%d: database cluster state problem", __LINE__);
141 
142  p++; /* remove ':' char */
143 
144  /*
145  * We checked earlier for a postmaster lock file, and if we
146  * found one, we tried to start/stop the server to replay the
147  * WAL. However, pg_ctl -m immediate doesn't leave a lock
148  * file, but does require WAL replay, so we check here that
149  * the server was shut down cleanly, from the controldata
150  * perspective.
151  */
152  /* Remove trailing newline and leading spaces */
153  (void) pg_strip_crlf(p);
154  while (*p == ' ')
155  p++;
156  if (strcmp(p, "shut down in recovery") == 0)
157  {
158  if (cluster == &old_cluster)
159  pg_fatal("The source cluster was shut down while in recovery mode. To upgrade, use \"rsync\" as documented or shut it down as a primary.");
160  else
161  pg_fatal("The target cluster was shut down while in recovery mode. To upgrade, use \"rsync\" as documented or shut it down as a primary.");
162  }
163  else if (strcmp(p, "shut down") != 0)
164  {
165  if (cluster == &old_cluster)
166  pg_fatal("The source cluster was not shut down cleanly, state reported as: \"%s\"", p);
167  else
168  pg_fatal("The target cluster was not shut down cleanly, state reported as: \"%s\"", p);
169  }
170  got_cluster_state = true;
171  }
172  }
173 
174  rc = pclose(output);
175  if (rc != 0)
176  pg_fatal("could not get control data using %s: %s",
177  cmd, wait_result_to_str(rc));
178 
179  if (!got_cluster_state)
180  {
181  if (cluster == &old_cluster)
182  pg_fatal("The source cluster lacks cluster state information:");
183  else
184  pg_fatal("The target cluster lacks cluster state information:");
185  }
186  }
187 
188  /* pg_resetxlog has been renamed to pg_resetwal in version 10 */
189  if (GET_MAJOR_VERSION(cluster->bin_version) <= 906)
190  resetwal_bin = "pg_resetxlog\" -n";
191  else
192  resetwal_bin = "pg_resetwal\" -n";
193  snprintf(cmd, sizeof(cmd), "\"%s/%s \"%s\"",
194  cluster->bindir,
195  live_check ? "pg_controldata\"" : resetwal_bin,
196  cluster->pgdata);
197  fflush(NULL);
198 
199  if ((output = popen(cmd, "r")) == NULL)
200  pg_fatal("could not get control data using %s: %m", cmd);
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:506
static char * lc_collate
Definition: initdb.c:141
static char * lc_time
Definition: initdb.c:145
static char * lc_ctype
Definition: initdb.c:142
static char * lc_messages
Definition: initdb.c:146
static char * lc_numeric
Definition: initdb.c:144
static char * lc_monetary
Definition: initdb.c:143
#define LARGE_OBJECT_SIZE_PG_CONTROL_VER
Definition: pg_upgrade.h:121
#define MULTIXACT_FORMATCHANGE_CAT_VER
Definition: pg_upgrade.h:115
void void unsigned int str2uint(const char *str)
Definition: util.c:352
#define unsetenv(x)
Definition: win32_port.h:556
#define setenv(x, y, z)
Definition: win32_port.h:555

References cluster(), fflush(), GET_MAJOR_VERSION, LARGE_OBJECT_SIZE_PG_CONTROL_VER, lc_collate, lc_ctype, lc_messages, lc_monetary, lc_numeric, lc_time, UserOpts::live_check, 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(), strlcpy(), unsetenv, user_opts, and wait_result_to_str().

Referenced by check_cluster_compatibility().

◆ get_db_rel_and_slot_infos()

void get_db_rel_and_slot_infos ( ClusterInfo cluster)

Definition at line 280 of file info.c.

281 {
283  char *rel_infos_query = NULL;
284  char *logical_slot_infos_query = NULL;
285 
286  if (cluster->dbarr.dbs != NULL)
288 
291 
292  rel_infos_query = get_rel_infos_query();
294  rel_infos_query,
296  true, NULL);
297 
298  /*
299  * Logical slots are only carried over to the new cluster when the old
300  * cluster is on PG17 or newer. This is because before that the logical
301  * slots are not saved at shutdown, so there is no guarantee that the
302  * latest confirmed_flush_lsn is saved to disk which can lead to data
303  * loss. It is still not guaranteed for manually created slots in PG17, so
304  * subsequent checks done in check_old_cluster_for_valid_slots() would
305  * raise a FATAL error if such slots are included.
306  */
307  if (cluster == &old_cluster &&
308  GET_MAJOR_VERSION(cluster->major_version) > 1600)
309  {
310  logical_slot_infos_query = get_old_cluster_logical_slot_infos_query();
312  logical_slot_infos_query,
314  true, NULL);
315  }
316 
317  upgrade_task_run(task, cluster);
318  upgrade_task_free(task);
319 
320  pg_free(rel_infos_query);
321  if (logical_slot_infos_query)
322  pg_free(logical_slot_infos_query);
323 
324  if (cluster == &old_cluster)
325  pg_log(PG_VERBOSE, "\nsource databases:");
326  else
327  pg_log(PG_VERBOSE, "\ntarget databases:");
328 
329  if (log_opts.verbose)
330  print_db_infos(&cluster->dbarr);
331 }
static void process_rel_infos(DbInfo *dbinfo, PGresult *res, void *arg)
Definition: info.c:562
static void get_template0_info(ClusterInfo *cluster)
Definition: info.c:339
static void get_db_infos(ClusterInfo *cluster)
Definition: info.c:404
static void free_db_and_rel_infos(DbInfoArr *db_arr)
Definition: info.c:773
static char * get_rel_infos_query(void)
Definition: info.c:471
static void process_old_cluster_logical_slot_infos(DbInfo *dbinfo, PGresult *res, void *arg)
Definition: info.c:688
static void print_db_infos(DbInfoArr *db_arr)
Definition: info.c:807
static char * get_old_cluster_logical_slot_infos_query(void)
Definition: info.c:650
UpgradeTask * upgrade_task_create(void)
Definition: task.c:117
void upgrade_task_run(const UpgradeTask *task, const ClusterInfo *cluster)
Definition: task.c:420
void upgrade_task_free(UpgradeTask *task)
Definition: task.c:133
void upgrade_task_add_step(UpgradeTask *task, const char *query, UpgradeTaskProcessCB process_cb, bool free_result, void *arg)
Definition: task.c:151

References cluster(), free_db_and_rel_infos(), get_db_infos(), GET_MAJOR_VERSION, get_old_cluster_logical_slot_infos_query(), get_rel_infos_query(), get_template0_info(), log_opts, old_cluster, pg_free(), pg_log(), PG_VERBOSE, print_db_infos(), process_old_cluster_logical_slot_infos(), process_rel_infos(), upgrade_task_add_step(), upgrade_task_create(), upgrade_task_free(), upgrade_task_run(), 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 79 of file function.c.

80 {
81  int totaltups;
82  int dbnum;
83  int n_libinfos;
86  char *query;
87 
88  state.ress = (PGresult **) pg_malloc(old_cluster.dbarr.ndbs * sizeof(PGresult *));
89  state.totaltups = 0;
90 
91  query = psprintf("SELECT DISTINCT probin "
92  "FROM pg_catalog.pg_proc "
93  "WHERE prolang = %u AND "
94  "probin IS NOT NULL AND "
95  "oid >= %u",
96  ClanguageId,
98 
100  false, &state);
101 
103  upgrade_task_free(task);
104 
105  /*
106  * Allocate memory for required libraries and logical replication output
107  * plugins.
108  */
109  n_libinfos = state.totaltups + count_old_cluster_logical_slots();
110  os_info.libraries = (LibraryInfo *) pg_malloc(sizeof(LibraryInfo) * n_libinfos);
111  totaltups = 0;
112 
113  for (dbnum = 0; dbnum < old_cluster.dbarr.ndbs; dbnum++)
114  {
115  PGresult *res = state.ress[dbnum];
116  int ntups;
117  int rowno;
118  LogicalSlotInfoArr *slot_arr = &old_cluster.dbarr.dbs[dbnum].slot_arr;
119 
120  ntups = PQntuples(res);
121  for (rowno = 0; rowno < ntups; rowno++)
122  {
123  char *lib = PQgetvalue(res, rowno, 0);
124 
126  os_info.libraries[totaltups].dbnum = dbnum;
127 
128  totaltups++;
129  }
130  PQclear(res);
131 
132  /*
133  * Store the names of output plugins as well. There is a possibility
134  * that duplicated plugins are set, but the consumer function
135  * check_loadable_libraries() will avoid checking the same library, so
136  * we do not have to consider their uniqueness here.
137  */
138  for (int slotno = 0; slotno < slot_arr->nslots; slotno++)
139  {
140  if (slot_arr->slots[slotno].invalid)
141  continue;
142 
143  os_info.libraries[totaltups].name = pg_strdup(slot_arr->slots[slotno].plugin);
144  os_info.libraries[totaltups].dbnum = dbnum;
145 
146  totaltups++;
147  }
148  }
149 
150  pg_free(state.ress);
151  pg_free(query);
152 
154 }
int PQntuples(const PGresult *res)
Definition: fe-exec.c:3481
char * PQgetvalue(const PGresult *res, int tup_num, int field_num)
Definition: fe-exec.c:3876
static void process_loadable_libraries(DbInfo *dbinfo, PGresult *res, void *arg)
Definition: function.c:60
int count_old_cluster_logical_slots(void)
Definition: info.c:742
LogicalSlotInfo * slots
Definition: pg_upgrade.h:169
Definition: regguts.h:323
#define FirstNormalObjectId
Definition: transam.h:197

References count_old_cluster_logical_slots(), ClusterInfo::dbarr, LibraryInfo::dbnum, DbInfoArr::dbs, FirstNormalObjectId, LogicalSlotInfo::invalid, OSInfo::libraries, LibraryInfo::name, DbInfoArr::ndbs, LogicalSlotInfoArr::nslots, OSInfo::num_libraries, old_cluster, os_info, pg_free(), pg_malloc(), pg_strdup(), LogicalSlotInfo::plugin, PQclear(), PQgetvalue(), PQntuples(), process_loadable_libraries(), psprintf(), res, DbInfo::slot_arr, LogicalSlotInfoArr::slots, loadable_libraries_state::totaltups, upgrade_task_add_step(), upgrade_task_create(), upgrade_task_free(), and upgrade_task_run().

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)

Definition at line 473 of file option.c.

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

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

Referenced by main().

◆ get_subscription_count()

void get_subscription_count ( ClusterInfo cluster)

Definition at line 758 of file info.c.

759 {
760  PGconn *conn;
761  PGresult *res;
762 
763  conn = connectToServer(cluster, "template1");
764  res = executeQueryOrDie(conn, "SELECT count(*) "
765  "FROM pg_catalog.pg_subscription");
766  cluster->nsubs = atoi(PQgetvalue(res, 0, 0));
767 
768  PQclear(res);
769  PQfinish(conn);
770 }
PGresult * executeQueryOrDie(PGconn *conn, const char *fmt,...) pg_attribute_printf(2

References cluster(), conn, connectToServer(), executeQueryOrDie(), PQclear(), PQfinish(), PQgetvalue(), and res.

Referenced by check_and_dump_old_cluster().

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

765 {
766  /*
767  * We unconditionally start/stop the new server because pg_resetwal -o set
768  * wal_level to 'minimum'. If the user is upgrading standby servers using
769  * the rsync instructions, they will need pg_upgrade to write its final
770  * WAL record showing wal_level as 'replica'.
771  */
773 
774  /* Reindex hash indexes for old < 10.0 */
777 
779 
780  stop_postmaster(false);
781 }
void report_extension_updates(ClusterInfo *cluster)
Definition: version.c:182

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

◆ jsonb_9_4_check_applicable()

bool jsonb_9_4_check_applicable ( ClusterInfo cluster)

Definition at line 21 of file version.c.

22 {
23  /* JSONB changed its storage format during 9.4 beta */
24  if (GET_MAJOR_VERSION(cluster->major_version) == 904 &&
25  cluster->controldata.cat_ver < JSONB_FORMAT_CHANGE_CAT_VER)
26  return true;
27 
28  return false;
29 }
#define JSONB_FORMAT_CHANGE_CAT_VER
Definition: pg_upgrade.h:126

References cluster(), GET_MAJOR_VERSION, and JSONB_FORMAT_CHANGE_CAT_VER.

◆ linkFile()

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

Definition at line 190 of file file.c.

192 {
193  if (link(src, dst) < 0)
194  pg_fatal("error while creating link for relation \"%s.%s\" (\"%s\" to \"%s\"): %m",
195  schemaName, relName, src, dst);
196 }

References link(), and pg_fatal.

Referenced by transfer_relfile().

◆ old_9_6_invalidate_hash_indexes()

void old_9_6_invalidate_hash_indexes ( ClusterInfo cluster,
bool  check_mode 
)

Definition at line 37 of file version.c.

38 {
39  int dbnum;
40  FILE *script = NULL;
41  bool found = false;
42  char *output_path = "reindex_hash.sql";
43 
44  prep_status("Checking for hash indexes");
45 
46  for (dbnum = 0; dbnum < cluster->dbarr.ndbs; dbnum++)
47  {
48  PGresult *res;
49  bool db_used = false;
50  int ntups;
51  int rowno;
52  int i_nspname,
53  i_relname;
54  DbInfo *active_db = &cluster->dbarr.dbs[dbnum];
55  PGconn *conn = connectToServer(cluster, active_db->db_name);
56 
57  /* find hash indexes */
59  "SELECT n.nspname, c.relname "
60  "FROM pg_catalog.pg_class c, "
61  " pg_catalog.pg_index i, "
62  " pg_catalog.pg_am a, "
63  " pg_catalog.pg_namespace n "
64  "WHERE i.indexrelid = c.oid AND "
65  " c.relam = a.oid AND "
66  " c.relnamespace = n.oid AND "
67  " a.amname = 'hash'"
68  );
69 
70  ntups = PQntuples(res);
71  i_nspname = PQfnumber(res, "nspname");
72  i_relname = PQfnumber(res, "relname");
73  for (rowno = 0; rowno < ntups; rowno++)
74  {
75  found = true;
76  if (!check_mode)
77  {
78  if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL)
79  pg_fatal("could not open file \"%s\": %m", output_path);
80  if (!db_used)
81  {
82  PQExpBufferData connectbuf;
83 
84  initPQExpBuffer(&connectbuf);
85  appendPsqlMetaConnect(&connectbuf, active_db->db_name);
86  fputs(connectbuf.data, script);
87  termPQExpBuffer(&connectbuf);
88  db_used = true;
89  }
90  fprintf(script, "REINDEX INDEX %s.%s;\n",
91  quote_identifier(PQgetvalue(res, rowno, i_nspname)),
92  quote_identifier(PQgetvalue(res, rowno, i_relname)));
93  }
94  }
95 
96  PQclear(res);
97 
98  if (!check_mode && db_used)
99  {
100  /* mark hash indexes as invalid */
102  "UPDATE pg_catalog.pg_index i "
103  "SET indisvalid = false "
104  "FROM pg_catalog.pg_class c, "
105  " pg_catalog.pg_am a, "
106  " pg_catalog.pg_namespace n "
107  "WHERE i.indexrelid = c.oid AND "
108  " c.relam = a.oid AND "
109  " c.relnamespace = n.oid AND "
110  " a.amname = 'hash'"));
111  }
112 
113  PQfinish(conn);
114  }
115 
116  if (script)
117  fclose(script);
118 
119  if (found)
120  {
121  report_status(PG_WARNING, "warning");
122  if (check_mode)
123  pg_log(PG_WARNING, "\n"
124  "Your installation contains hash indexes. These indexes have different\n"
125  "internal formats between your old and new clusters, so they must be\n"
126  "reindexed with the REINDEX command. After upgrading, you will be given\n"
127  "REINDEX instructions.");
128  else
129  pg_log(PG_WARNING, "\n"
130  "Your installation contains hash indexes. These indexes have different\n"
131  "internal formats between your old and new clusters, so they must be\n"
132  "reindexed with the REINDEX command. The file\n"
133  " %s\n"
134  "when executed by psql by the database superuser will recreate all invalid\n"
135  "indexes; until then, none of these indexes will be used.",
136  output_path);
137  }
138  else
139  check_ok();
140 }
int PQfnumber(const PGresult *res, const char *field_name)
Definition: fe-exec.c:3589
void report_status(eLogType type, const char *fmt,...) pg_attribute_printf(2
const char * quote_identifier(const char *ident)
Definition: ruleutils.c:12840
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, and termPQExpBuffer().

Referenced by check_and_dump_old_cluster(), and issue_warnings_and_set_wal_level().

◆ output_check_banner()

void output_check_banner ( void  )

Definition at line 589 of file check.c.

590 {
591  if (user_opts.live_check)
592  {
594  "Performing Consistency Checks on Old Live Server\n"
595  "------------------------------------------------");
596  }
597  else
598  {
600  "Performing Consistency Checks\n"
601  "-----------------------------");
602  }
603 }

References UserOpts::live_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 785 of file check.c.

786 {
787  PQExpBufferData user_specification;
788 
789  initPQExpBuffer(&user_specification);
791  {
792  appendPQExpBufferStr(&user_specification, "-U ");
793  appendShellString(&user_specification, os_info.user);
794  appendPQExpBufferChar(&user_specification, ' ');
795  }
796 
798  "Optimizer statistics are not transferred by pg_upgrade.\n"
799  "Once you start the new server, consider running:\n"
800  " %s/vacuumdb %s--all --analyze-in-stages", new_cluster.bindir, user_specification.data);
801 
802  if (deletion_script_file_name)
804  "Running this script will delete the old cluster's data files:\n"
805  " %s",
806  deletion_script_file_name);
807  else
809  "Could not create a script to delete the old cluster's data files\n"
810  "because user-defined tablespaces or the new cluster's data directory\n"
811  "exist in the old cluster directory. The old cluster's contents must\n"
812  "be deleted manually.");
813 
814  termPQExpBuffer(&user_specification);
815 }
bool user_specified
Definition: pg_upgrade.h:345

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: %m");
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: %m");
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:89
int jobs
Definition: pg_upgrade.h:327

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

Referenced by transfer_all_new_tablespaces().

◆ parseCommandLine()

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

Definition at line 39 of file option.c.

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

References _, ClusterInfo::bindir, canonicalize_path(), UserOpts::check, check_required_directory(), DEF_PGUPORT, UserOpts::do_sync, exit(), FIX_DEFAULT_READ_ONLY, fprintf, free, get_progname(), get_user_info(), getopt_long(), LogOpts::isatty, UserOpts::jobs, log_opts, MAXPGPATH, new_cluster, no_argument, old_cluster, optarg, optind, os_info, parse_sync_method(), path_is_prefix_of_path(), pfree(), pg_fatal, pg_free(), pg_log(), PG_REPORT, pg_strdup(), ClusterInfo::pgdata, ClusterInfo::pgopts, ClusterInfo::port, OSInfo::progname, psprintf(), required_argument, LogOpts::retain, setenv, UserOpts::socketdir, generate_unaccent_rules::stdout, strlcpy(), UserOpts::sync_method, UserOpts::transfer_mode, TRANSFER_MODE_CLONE, TRANSFER_MODE_COPY, TRANSFER_MODE_COPY_FILE_RANGE, 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 233 of file exec.c.

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

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

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

12841 {
12842  /*
12843  * Can avoid quoting if ident starts with a lowercase letter or underscore
12844  * and contains only lowercase letters, digits, and underscores, *and* is
12845  * not any SQL keyword. Otherwise, supply quotes.
12846  */
12847  int nquotes = 0;
12848  bool safe;
12849  const char *ptr;
12850  char *result;
12851  char *optr;
12852 
12853  /*
12854  * would like to use <ctype.h> macros here, but they might yield unwanted
12855  * locale-specific results...
12856  */
12857  safe = ((ident[0] >= 'a' && ident[0] <= 'z') || ident[0] == '_');
12858 
12859  for (ptr = ident; *ptr; ptr++)
12860  {
12861  char ch = *ptr;
12862 
12863  if ((ch >= 'a' && ch <= 'z') ||
12864  (ch >= '0' && ch <= '9') ||
12865  (ch == '_'))
12866  {
12867  /* okay */
12868  }
12869  else
12870  {
12871  safe = false;
12872  if (ch == '"')
12873  nquotes++;
12874  }
12875  }
12876 
12878  safe = false;
12879 
12880  if (safe)
12881  {
12882  /*
12883  * Check for keyword. We quote keywords except for unreserved ones.
12884  * (In some cases we could avoid quoting a col_name or type_func_name
12885  * keyword, but it seems much harder than it's worth to tell that.)
12886  *
12887  * Note: ScanKeywordLookup() does case-insensitive comparison, but
12888  * that's fine, since we already know we have all-lower-case.
12889  */
12890  int kwnum = ScanKeywordLookup(ident, &ScanKeywords);
12891 
12892  if (kwnum >= 0 && ScanKeywordCategories[kwnum] != UNRESERVED_KEYWORD)
12893  safe = false;
12894  }
12895 
12896  if (safe)
12897  return ident; /* no change needed */
12898 
12899  result = (char *) palloc(strlen(ident) + nquotes + 2 + 1);
12900 
12901  optr = result;
12902  *optr++ = '"';
12903  for (ptr = ident; *ptr; ptr++)
12904  {
12905  char ch = *ptr;
12906 
12907  if (ch == '"')
12908  *optr++ = '"';
12909  *optr++ = ch;
12910  }
12911  *optr++ = '"';
12912  *optr = '\0';
12913 
12914  return result;
12915 }
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:1317
bool quote_all_identifiers
Definition: ruleutils.c:337

◆ 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: %m", "waitpid");
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: %m");
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, 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 745 of file check.c.

746 {
747  if (user_opts.check)
748  {
749  pg_log(PG_REPORT, "\n*Clusters are compatible*");
750  /* stops new cluster */
751  stop_postmaster(false);
752 
754  exit(0);
755  }
756 
757  pg_log(PG_REPORT, "\n"
758  "If pg_upgrade fails after this point, you must re-initdb the\n"
759  "new cluster before continuing.");
760 }
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 182 of file version.c.

183 {
184  UpgradeTaskReport report;
186  const char *query = "SELECT name "
187  "FROM pg_available_extensions "
188  "WHERE installed_version != default_version";
189 
190  prep_status("Checking for extension updates");
191 
192  report.file = NULL;
193  strcpy(report.path, "update_extensions.sql");
194 
196  true, &report);
197 
198  upgrade_task_run(task, cluster);
199  upgrade_task_free(task);
200 
201  if (report.file)
202  {
203  fclose(report.file);
204  report_status(PG_REPORT, "notice");
205  pg_log(PG_REPORT, "\n"
206  "Your installation contains extensions that should be updated\n"
207  "with the ALTER EXTENSION command. The file\n"
208  " %s\n"
209  "when executed by psql by the database superuser will update\n"
210  "these extensions.",
211  report.path);
212  }
213  else
214  check_ok();
215 }
static void process_extension_updates(DbInfo *dbinfo, PGresult *res, void *arg)
Definition: version.c:148
char path[MAXPGPATH]
Definition: pg_upgrade.h:516

References check_ok(), cluster(), UpgradeTaskReport::file, UpgradeTaskReport::path, pg_log(), PG_REPORT, prep_status(), process_extension_updates(), report_status(), upgrade_task_add_step(), upgrade_task_create(), upgrade_task_free(), and upgrade_task_run().

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

218 {
219  int src_fd;
220  int dst_fd;
221  PGIOAlignedBlock buffer;
222  PGIOAlignedBlock new_vmbuf;
223  ssize_t totalBytesRead = 0;
224  ssize_t src_filesize;
225  int rewriteVmBytesPerPage;
226  BlockNumber new_blkno = 0;
227  struct stat statbuf;
228 
229  /* Compute number of old-format bytes per new page */
230  rewriteVmBytesPerPage = (BLCKSZ - SizeOfPageHeaderData) / 2;
231 
232  if ((src_fd = open(fromfile, O_RDONLY | PG_BINARY, 0)) < 0)
233  pg_fatal("error while copying relation \"%s.%s\": could not open file \"%s\": %m",
234  schemaName, relName, fromfile);
235 
236  if (fstat(src_fd, &statbuf) != 0)
237  pg_fatal("error while copying relation \"%s.%s\": could not stat file \"%s\": %m",
238  schemaName, relName, fromfile);
239 
240  if ((dst_fd = open(tofile, O_RDWR | O_CREAT | O_EXCL | PG_BINARY,
241  pg_file_create_mode)) < 0)
242  pg_fatal("error while copying relation \"%s.%s\": could not create file \"%s\": %m",
243  schemaName, relName, tofile);
244 
245  /* Save old file size */
246  src_filesize = statbuf.st_size;
247 
248  /*
249  * Turn each visibility map page into 2 pages one by one. Each new page
250  * has the same page header as the old one. If the last section of the
251  * last page is empty, we skip it, mostly to avoid turning one-page
252  * visibility maps for small relations into two pages needlessly.
253  */
254  while (totalBytesRead < src_filesize)
255  {
256  ssize_t bytesRead;
257  char *old_cur;
258  char *old_break;
259  char *old_blkend;
260  PageHeaderData pageheader;
261  bool old_lastblk;
262 
263  if ((bytesRead = read(src_fd, buffer.data, BLCKSZ)) != BLCKSZ)
264  {
265  if (bytesRead < 0)
266  pg_fatal("error while copying relation \"%s.%s\": could not read file \"%s\": %m",
267  schemaName, relName, fromfile);
268  else
269  pg_fatal("error while copying relation \"%s.%s\": partial page found in file \"%s\"",
270  schemaName, relName, fromfile);
271  }
272 
273  totalBytesRead += BLCKSZ;
274  old_lastblk = (totalBytesRead == src_filesize);
275 
276  /* Save the page header data */
277  memcpy(&pageheader, buffer.data, SizeOfPageHeaderData);
278 
279  /*
280  * These old_* variables point to old visibility map page. old_cur
281  * points to current position on old page. old_blkend points to end of
282  * old block. old_break is the end+1 position on the old page for the
283  * data that will be transferred to the current new page.
284  */
285  old_cur = buffer.data + SizeOfPageHeaderData;
286  old_blkend = buffer.data + bytesRead;
287  old_break = old_cur + rewriteVmBytesPerPage;
288 
289  while (old_break <= old_blkend)
290  {
291  char *new_cur;
292  bool empty = true;
293  bool old_lastpart;
294 
295  /* First, copy old page header to new page */
296  memcpy(new_vmbuf.data, &pageheader, SizeOfPageHeaderData);
297 
298  /* Rewriting the last part of the last old page? */
299  old_lastpart = old_lastblk && (old_break == old_blkend);
300 
301  new_cur = new_vmbuf.data + SizeOfPageHeaderData;
302 
303  /* Process old page bytes one by one, and turn it into new page. */
304  while (old_cur < old_break)
305  {
306  uint8 byte = *(uint8 *) old_cur;
307  uint16 new_vmbits = 0;
308  int i;
309 
310  /* Generate new format bits while keeping old information */
311  for (i = 0; i < BITS_PER_BYTE; i++)
312  {
313  if (byte & (1 << i))
314  {
315  empty = false;
316  new_vmbits |=
318  }
319  }
320 
321  /* Copy new visibility map bytes to new-format page */
322  new_cur[0] = (char) (new_vmbits & 0xFF);
323  new_cur[1] = (char) (new_vmbits >> 8);
324 
325  old_cur++;
326  new_cur += BITS_PER_HEAPBLOCK;
327  }
328 
329  /* If the last part of the last page is empty, skip writing it */
330  if (old_lastpart && empty)
331  break;
332 
333  /* Set new checksum for visibility map page, if enabled */
335  ((PageHeader) new_vmbuf.data)->pd_checksum =
336  pg_checksum_page(new_vmbuf.data, new_blkno);
337 
338  errno = 0;
339  if (write(dst_fd, new_vmbuf.data, BLCKSZ) != BLCKSZ)
340  {
341  /* if write didn't set errno, assume problem is no disk space */
342  if (errno == 0)
343  errno = ENOSPC;
344  pg_fatal("error while copying relation \"%s.%s\": could not write file \"%s\": %m",
345  schemaName, relName, tofile);
346  }
347 
348  /* Advance for next new page */
349  old_break += rewriteVmBytesPerPage;
350  new_blkno++;
351  }
352  }
353 
354  /* Clean up */
355  close(dst_fd);
356  close(src_fd);
357 }
uint32 BlockNumber
Definition: block.h:31
PageHeaderData * PageHeader
Definition: bufpage.h:173
#define SizeOfPageHeaderData
Definition: bufpage.h:216
unsigned short uint16
Definition: c.h:505
unsigned char uint8
Definition: c.h:504
uint16 pg_checksum_page(char *page, BlockNumber blkno)
#define BITS_PER_BYTE
char data[BLCKSZ]
Definition: c.h:1137
#define BITS_PER_HEAPBLOCK
#define VISIBILITYMAP_ALL_VISIBLE
#define fstat
Definition: win32_port.h:283

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

Referenced by transfer_relfile().

◆ start_postmaster()

bool start_postmaster ( ClusterInfo cluster,
bool  report_and_exit_on_error 
)

Definition at line 198 of file server.c.

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

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

◆ stop_postmaster()

void stop_postmaster ( bool  in_atexit)

Definition at line 342 of file server.c.

343 {
345 
347  cluster = &old_cluster;
348  else if (os_info.running_cluster == &new_cluster)
349  cluster = &new_cluster;
350  else
351  return; /* no cluster running */
352 
353  exec_prog(SERVER_STOP_LOG_FILE, NULL, !in_atexit, !in_atexit,
354  "\"%s/pg_ctl\" -w -D \"%s\" -o \"%s\" %s stop",
355  cluster->bindir, cluster->pgconfig,
356  cluster->pgopts ? cluster->pgopts : "",
357  in_atexit ? "-m fast" : "-m smart");
358 
359  os_info.running_cluster = NULL;
360 }
#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 }
const char * str

References 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 89 of file relfilenumber.c.

91 {
92  int old_dbnum,
93  new_dbnum;
94 
95  /* Scan the old cluster databases and transfer their files */
96  for (old_dbnum = new_dbnum = 0;
97  old_dbnum < old_db_arr->ndbs;
98  old_dbnum++, new_dbnum++)
99  {
100  DbInfo *old_db = &old_db_arr->dbs[old_dbnum],
101  *new_db = NULL;
102  FileNameMap *mappings;
103  int n_maps;
104 
105  /*
106  * Advance past any databases that exist in the new cluster but not in
107  * the old, e.g. "postgres". (The user might have removed the
108  * 'postgres' database from the old cluster.)
109  */
110  for (; new_dbnum < new_db_arr->ndbs; new_dbnum++)
111  {
112  new_db = &new_db_arr->dbs[new_dbnum];
113  if (strcmp(old_db->db_name, new_db->db_name) == 0)
114  break;
115  }
116 
117  if (new_dbnum >= new_db_arr->ndbs)
118  pg_fatal("old database \"%s\" not found in the new cluster",
119  old_db->db_name);
120 
121  mappings = gen_db_file_maps(old_db, new_db, &n_maps, old_pgdata,
122  new_pgdata);
123  if (n_maps)
124  {
125  transfer_single_new_db(mappings, n_maps, old_tablespace);
126  }
127  /* We allocate something even for n_maps == 0 */
128  pg_free(mappings);
129  }
130 }
FileNameMap * gen_db_file_maps(DbInfo *old_db, DbInfo *new_db, int *nmaps, const char *old_pgdata, const char *new_pgdata)
Definition: info.c:45
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;
41  prep_status_progress("Copying user relation files with copy_file_range");
42  break;
43  case TRANSFER_MODE_LINK:
44  prep_status_progress("Linking user relation files");
45  break;
46  }
47 
48  /*
49  * Transferring files by tablespace is tricky because a single database
50  * can use multiple tablespaces. For non-parallel mode, we just pass a
51  * NULL tablespace path, which matches all tablespaces. In parallel mode,
52  * we pass the default tablespace and all user-created tablespaces and let
53  * those operations happen in parallel.
54  */
55  if (user_opts.jobs <= 1)
56  parallel_transfer_all_new_dbs(old_db_arr, new_db_arr, old_pgdata,
57  new_pgdata, NULL);
58  else
59  {
60  int tblnum;
61 
62  /* transfer default tablespace */
63  parallel_transfer_all_new_dbs(old_db_arr, new_db_arr, old_pgdata,
64  new_pgdata, old_pgdata);
65 
66  for (tblnum = 0; tblnum < os_info.num_old_tablespaces; tblnum++)
68  new_db_arr,
69  old_pgdata,
70  new_pgdata,
71  os_info.old_tablespaces[tblnum]);
72  /* reap all children */
73  while (reap_child(true) == true)
74  ;
75  }
76 
78  check_ok();
79 }
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_COPY_FILE_RANGE, TRANSFER_MODE_LINK, and user_opts.

Referenced by main().

◆ upgrade_task_add_step()

void upgrade_task_add_step ( UpgradeTask task,
const char *  query,
UpgradeTaskProcessCB  process_cb,
bool  free_result,
void *  arg 
)

Definition at line 151 of file task.c.

154 {
155  UpgradeTaskStep *new_step;
156 
157  task->steps = pg_realloc(task->steps,
158  ++task->num_steps * sizeof(UpgradeTaskStep));
159 
160  new_step = &task->steps[task->num_steps - 1];
161  new_step->process_cb = process_cb;
162  new_step->free_result = free_result;
163  new_step->arg = arg;
164 
165  appendPQExpBuffer(task->queries, "%s;", query);
166 }
void * pg_realloc(void *ptr, size_t size)
Definition: fe_memutils.c:65
void * arg
bool free_result
Definition: task.c:74
UpgradeTaskProcessCB process_cb
Definition: task.c:73
void * arg
Definition: task.c:75
PQExpBuffer queries
Definition: task.c:86
UpgradeTaskStep * steps
Definition: task.c:84
int num_steps
Definition: task.c:85

References appendPQExpBuffer(), arg, UpgradeTaskStep::arg, UpgradeTaskStep::free_result, UpgradeTask::num_steps, pg_realloc(), UpgradeTaskStep::process_cb, UpgradeTask::queries, and UpgradeTask::steps.

Referenced by check_for_data_types_usage(), check_for_incompatible_polymorphics(), check_for_isn_and_int8_passing_mismatch(), check_for_tables_with_oids(), check_for_user_defined_encoding_conversions(), check_for_user_defined_postfix_ops(), check_old_cluster_subscription_state(), get_db_rel_and_slot_infos(), get_loadable_libraries(), report_extension_updates(), and upgrade_task_create().

◆ upgrade_task_create()

UpgradeTask* upgrade_task_create ( void  )

Definition at line 117 of file task.c.

118 {
119  UpgradeTask *task = pg_malloc0(sizeof(UpgradeTask));
120 
121  task->queries = createPQExpBuffer();
122 
123  /* All tasks must first set a secure search_path. */
124  upgrade_task_add_step(task, ALWAYS_SECURE_SEARCH_PATH_SQL, NULL, true, NULL);
125 
126  return task;
127 }
void upgrade_task_add_step(UpgradeTask *task, const char *query, UpgradeTaskProcessCB process_cb, bool free_result, void *arg)
Definition: task.c:151

References ALWAYS_SECURE_SEARCH_PATH_SQL, createPQExpBuffer(), pg_malloc0(), UpgradeTask::queries, and upgrade_task_add_step().

Referenced by check_for_data_types_usage(), check_for_incompatible_polymorphics(), check_for_isn_and_int8_passing_mismatch(), check_for_tables_with_oids(), check_for_user_defined_encoding_conversions(), check_for_user_defined_postfix_ops(), check_old_cluster_subscription_state(), get_db_rel_and_slot_infos(), get_loadable_libraries(), and report_extension_updates().

◆ upgrade_task_free()

◆ upgrade_task_run()

void upgrade_task_run ( const UpgradeTask task,
const ClusterInfo cluster 
)

Definition at line 420 of file task.c.

421 {
422  int jobs = Max(1, user_opts.jobs);
423  UpgradeTaskSlot *slots = pg_malloc0(sizeof(UpgradeTaskSlot) * jobs);
424 
425  dbs_complete = 0;
426  dbs_processing = 0;
427 
428  /*
429  * Process every slot the first time round.
430  */
431  for (int i = 0; i < jobs; i++)
432  slots[i].ready = true;
433 
434  while (dbs_complete < cluster->dbarr.ndbs)
435  {
436  for (int i = 0; i < jobs; i++)
437  process_slot(cluster, &slots[i], task);
438 
439  wait_on_slots(slots, jobs);
440  }
441 
442  pg_free(slots);
443 }
static int dbs_processing
Definition: task.c:63
static void wait_on_slots(UpgradeTaskSlot *slots, int numslots)
Definition: task.c:364
static int dbs_complete
Definition: task.c:56
static void process_slot(const ClusterInfo *cluster, UpgradeTaskSlot *slot, const UpgradeTask *task)
Definition: task.c:235

References cluster(), dbs_complete, dbs_processing, i, UserOpts::jobs, Max, pg_free(), pg_malloc0(), process_slot(), user_opts, and wait_on_slots().

Referenced by check_for_data_types_usage(), check_for_incompatible_polymorphics(), check_for_isn_and_int8_passing_mismatch(), check_for_tables_with_oids(), check_for_user_defined_encoding_conversions(), check_for_user_defined_postfix_ops(), check_old_cluster_subscription_state(), get_db_rel_and_slot_infos(), get_loadable_libraries(), and report_extension_updates().

◆ verify_directories()

bool void verify_directories ( void  )

Definition at line 263 of file exec.c.

264 {
265 #ifndef WIN32
266  if (access(".", R_OK | W_OK | X_OK) != 0)
267 #else
268  if (win32_check_directory_write_permissions() != 0)
269 #endif
270  pg_fatal("You must have read and write access in the current directory.");
271 
272  check_bin_dir(&old_cluster, false);
274  check_bin_dir(&new_cluster, true);
276 }
static void check_bin_dir(ClusterInfo *cluster, bool check_versions)
Definition: exec.c:383
static void check_data_dir(ClusterInfo *cluster)
Definition: exec.c:341
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 363 of file pg_upgrade.h.

◆ old_cluster

◆ os_info

◆ output_files

char* output_files[]
extern

Definition at line 71 of file pg_upgrade.c.

Referenced by make_outputdirs().

◆ user_opts