PostgreSQL Source Code  git master
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
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:107
char * pg_strdup(const char *in)
Definition: fe_memutils.c:85
FILE * output
static void check_ok(void)
Definition: initdb.c:2091
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:154
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 586 of file check.c.

587 {
588  /* -- OLD -- */
589 
590  if (!user_opts.live_check)
592 
593  /*
594  * First check that all databases allow connections since we'll otherwise
595  * fail in later stages.
596  */
598 
599  /*
600  * Extract a list of databases, tables, and logical replication slots from
601  * the old cluster.
602  */
604 
606 
608 
609 
610  /*
611  * Check for various failure cases
612  */
616 
618  {
619  /*
620  * Logical replication slots can be migrated since PG17. See comments
621  * atop get_old_cluster_logical_slot_infos().
622  */
624 
625  /*
626  * Subscriptions and their dependencies can be migrated since PG17.
627  * Before that the logical slots are not upgraded, so we will not be
628  * able to upgrade the logical replication clusters completely.
629  */
632  }
633 
635 
636  /*
637  * PG 14 changed the function signature of encoding conversion functions.
638  * Conversions from older versions cannot be upgraded automatically
639  * because the user-defined functions used by the encoding conversions
640  * need to be changed to match the new signature.
641  */
644 
645  /*
646  * Pre-PG 14 allowed user defined postfix operators, which are not
647  * supported anymore. Verify there are none, iff applicable.
648  */
651 
652  /*
653  * PG 14 changed polymorphic functions from anyarray to
654  * anycompatiblearray.
655  */
658 
659  /*
660  * Pre-PG 12 allowed tables to be declared WITH OIDS, which is not
661  * supported anymore. Verify there are none, iff applicable.
662  */
665 
666  /*
667  * Pre-PG 10 allowed tables with 'unknown' type columns and non WAL logged
668  * hash indexes
669  */
671  {
672  if (user_opts.check)
674  }
675 
676  /* 9.5 and below should not have roles starting with pg_ */
679 
680  /*
681  * While not a check option, we do this now because this is the only time
682  * the old server is running.
683  */
684  if (!user_opts.check)
686 
687  if (!user_opts.live_check)
688  stop_postmaster(false);
689 }
static void check_for_tables_with_oids(ClusterInfo *cluster)
Definition: check.c:1564
static void check_for_pg_role_prefix(ClusterInfo *cluster)
Definition: check.c:1608
static void check_for_data_types_usage(ClusterInfo *cluster)
Definition: check.c:461
static void check_old_cluster_subscription_state(void)
Definition: check.c:1974
static void check_is_install_user(ClusterInfo *cluster)
Definition: check.c:1044
static void check_for_connection_status(ClusterInfo *cluster)
Definition: check.c:1102
static void check_for_isn_and_int8_passing_mismatch(ClusterInfo *cluster)
Definition: check.c:1256
static void check_old_cluster_for_valid_slots(void)
Definition: check.c:1866
static void check_for_user_defined_postfix_ops(ClusterInfo *cluster)
Definition: check.c:1344
static void check_for_prepared_transactions(ClusterInfo *cluster)
Definition: check.c:1190
static void check_for_user_defined_encoding_conversions(ClusterInfo *cluster)
Definition: check.c:1697
static void check_for_incompatible_polymorphics(ClusterInfo *cluster)
Definition: check.c:1435
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_connection_status(), 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(), 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 846 of file check.c.

847 {
848  /* get/check pg_control data of servers */
852 
854  pg_fatal("When checking a live server, "
855  "the old and new port numbers must be different.");
856 }
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 803 of file check.c.

804 {
805  prep_status("Checking cluster versions");
806 
807  /* cluster versions should already have been obtained */
810 
811  /*
812  * We allow upgrades from/to the same major version for alpha/beta
813  * upgrades
814  */
815 
817  pg_fatal("This utility can only upgrade from PostgreSQL version %s and later.",
818  "9.2");
819 
820  /* Only current PG version is supported as a target */
822  pg_fatal("This utility can only upgrade to PostgreSQL version %s.",
823  PG_MAJORVERSION);
824 
825  /*
826  * We can't allow downgrading because we use the target pg_dump, and
827  * pg_dump cannot operate on newer database versions, only current and
828  * older versions.
829  */
831  pg_fatal("This utility cannot be used to downgrade to older major PostgreSQL versions.");
832 
833  /* Ensure binaries match the designated data directories */
836  pg_fatal("Old cluster data and binary directories are from different major versions.");
839  pg_fatal("New cluster data and binary directories are from different major versions.");
840 
841  check_ok();
842 }
#define Assert(condition)
Definition: c.h:837
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:1252
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:7200
void PQfinish(PGconn *conn)
Definition: fe-connect.c:4879
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:53
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 693 of file check.c.

694 {
696 
698 
700 
701  switch (user_opts.transfer_mode)
702  {
703  case TRANSFER_MODE_CLONE:
705  break;
706  case TRANSFER_MODE_COPY:
707  break;
710  break;
711  case TRANSFER_MODE_LINK:
712  check_hard_link();
713  break;
714  }
715 
717 
719 
721 
723 
725 }
static void check_new_cluster_logical_replication_slots(void)
Definition: check.c:1750
static void check_new_cluster_subscription_configuration(void)
Definition: check.c:1823
static void check_new_cluster_is_empty(void)
Definition: check.c:860
static void check_for_new_tablespace_dir(void)
Definition: check.c:892
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:7023
return str start
static struct @160 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 }
void pg_log(eLogType type, const char *fmt,...)
Definition: util.c:259
LogOpts log_opts
Definition: util.c:17
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

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:72
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:7137
@ 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_connection_status(), 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(), 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 921 of file check.c.

922 {
923  FILE *script = NULL;
924  int tblnum;
925  char old_cluster_pgdata[MAXPGPATH],
926  new_cluster_pgdata[MAXPGPATH];
927 
928  *deletion_script_file_name = psprintf("%sdelete_old_cluster.%s",
930 
931  strlcpy(old_cluster_pgdata, old_cluster.pgdata, MAXPGPATH);
932  canonicalize_path(old_cluster_pgdata);
933 
934  strlcpy(new_cluster_pgdata, new_cluster.pgdata, MAXPGPATH);
935  canonicalize_path(new_cluster_pgdata);
936 
937  /* Some people put the new data directory inside the old one. */
938  if (path_is_prefix_of_path(old_cluster_pgdata, new_cluster_pgdata))
939  {
941  "\nWARNING: new data directory should not be inside the old data directory, i.e. %s", old_cluster_pgdata);
942 
943  /* Unlink file in case it is left over from a previous run. */
944  unlink(*deletion_script_file_name);
945  pg_free(*deletion_script_file_name);
946  *deletion_script_file_name = NULL;
947  return;
948  }
949 
950  /*
951  * Some users (oddly) create tablespaces inside the cluster data
952  * directory. We can't create a proper old cluster delete script in that
953  * case.
954  */
955  for (tblnum = 0; tblnum < os_info.num_old_tablespaces; tblnum++)
956  {
957  char old_tablespace_dir[MAXPGPATH];
958 
959  strlcpy(old_tablespace_dir, os_info.old_tablespaces[tblnum], MAXPGPATH);
960  canonicalize_path(old_tablespace_dir);
961  if (path_is_prefix_of_path(old_cluster_pgdata, old_tablespace_dir))
962  {
963  /* reproduce warning from CREATE TABLESPACE that is in the log */
965  "\nWARNING: user-defined tablespace locations should not be inside the data directory, i.e. %s", old_tablespace_dir);
966 
967  /* Unlink file in case it is left over from a previous run. */
968  unlink(*deletion_script_file_name);
969  pg_free(*deletion_script_file_name);
970  *deletion_script_file_name = NULL;
971  return;
972  }
973  }
974 
975  prep_status("Creating script to delete old cluster");
976 
977  if ((script = fopen_priv(*deletion_script_file_name, "w")) == NULL)
978  pg_fatal("could not open file \"%s\": %m",
979  *deletion_script_file_name);
980 
981 #ifndef WIN32
982  /* add shebang header */
983  fprintf(script, "#!/bin/sh\n\n");
984 #endif
985 
986  /* delete old cluster's default tablespace */
987  fprintf(script, RMDIR_CMD " %c%s%c\n", PATH_QUOTE,
989 
990  /* delete old cluster's alternate tablespaces */
991  for (tblnum = 0; tblnum < os_info.num_old_tablespaces; tblnum++)
992  {
993  /*
994  * Do the old cluster's per-database directories share a directory
995  * with a new version-specific tablespace?
996  */
997  if (strlen(old_cluster.tablespace_suffix) == 0)
998  {
999  /* delete per-database directories */
1000  int dbnum;
1001 
1002  fprintf(script, "\n");
1003 
1004  for (dbnum = 0; dbnum < old_cluster.dbarr.ndbs; dbnum++)
1005  fprintf(script, RMDIR_CMD " %c%s%c%u%c\n", PATH_QUOTE,
1008  PATH_QUOTE);
1009  }
1010  else
1011  {
1012  char *suffix_path = pg_strdup(old_cluster.tablespace_suffix);
1013 
1014  /*
1015  * Simply delete the tablespace directory, which might be ".old"
1016  * or a version-specific subdirectory.
1017  */
1018  fprintf(script, RMDIR_CMD " %c%s%s%c\n", PATH_QUOTE,
1020  fix_path_separator(suffix_path), PATH_QUOTE);
1021  pfree(suffix_path);
1022  }
1023  }
1024 
1025  fclose(script);
1026 
1027 #ifndef WIN32
1028  if (chmod(*deletion_script_file_name, S_IRWXU) != 0)
1029  pg_fatal("could not add execute permission to file \"%s\": %m",
1030  *deletion_script_file_name);
1031 #endif
1032 
1033  check_ok();
1034 }
static char * fix_path_separator(char *path)
Definition: check.c:547
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:43
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:492
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:977
#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 }
void pg_fatal(const char *fmt,...)
Definition: util.c:270
const char * get_user_name(char **errstr)
Definition: username.c:31

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

749 {
750  /*
751  * We unconditionally start/stop the new server because pg_resetwal -o set
752  * wal_level to 'minimum'. If the user is upgrading standby servers using
753  * the rsync instructions, they will need pg_upgrade to write its final
754  * WAL record showing wal_level as 'replica'.
755  */
757 
758  /* Reindex hash indexes for old < 10.0 */
761 
763 
764  stop_postmaster(false);
765 }
void report_extension_updates(ClusterInfo *cluster)
Definition: version.c:179

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:12868
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 568 of file check.c.

569 {
570  if (user_opts.live_check)
571  {
573  "Performing Consistency Checks on Old Live Server\n"
574  "------------------------------------------------");
575  }
576  else
577  {
579  "Performing Consistency Checks\n"
580  "-----------------------------");
581  }
582 }

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

770 {
771  PQExpBufferData user_specification;
772 
773  initPQExpBuffer(&user_specification);
775  {
776  appendPQExpBufferStr(&user_specification, "-U ");
777  appendShellString(&user_specification, os_info.user);
778  appendPQExpBufferChar(&user_specification, ' ');
779  }
780 
782  "Optimizer statistics are not transferred by pg_upgrade.\n"
783  "Once you start the new server, consider running:\n"
784  " %s/vacuumdb %s--all --analyze-in-stages", new_cluster.bindir, user_specification.data);
785 
786  if (deletion_script_file_name)
788  "Running this script will delete the old cluster's data files:\n"
789  " %s",
790  deletion_script_file_name);
791  else
793  "Could not create a script to delete the old cluster's data files\n"
794  "because user-defined tablespaces or the new cluster's data directory\n"
795  "exist in the old cluster directory. The old cluster's contents must\n"
796  "be deleted manually.");
797 
798  termPQExpBuffer(&user_specification);
799 }
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:72
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:87
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:51
PGDLLIMPORT char * optarg
Definition: getopt.c:53
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 12868 of file ruleutils.c.

12869 {
12870  /*
12871  * Can avoid quoting if ident starts with a lowercase letter or underscore
12872  * and contains only lowercase letters, digits, and underscores, *and* is
12873  * not any SQL keyword. Otherwise, supply quotes.
12874  */
12875  int nquotes = 0;
12876  bool safe;
12877  const char *ptr;
12878  char *result;
12879  char *optr;
12880 
12881  /*
12882  * would like to use <ctype.h> macros here, but they might yield unwanted
12883  * locale-specific results...
12884  */
12885  safe = ((ident[0] >= 'a' && ident[0] <= 'z') || ident[0] == '_');
12886 
12887  for (ptr = ident; *ptr; ptr++)
12888  {
12889  char ch = *ptr;
12890 
12891  if ((ch >= 'a' && ch <= 'z') ||
12892  (ch >= '0' && ch <= '9') ||
12893  (ch == '_'))
12894  {
12895  /* okay */
12896  }
12897  else
12898  {
12899  safe = false;
12900  if (ch == '"')
12901  nquotes++;
12902  }
12903  }
12904 
12906  safe = false;
12907 
12908  if (safe)
12909  {
12910  /*
12911  * Check for keyword. We quote keywords except for unreserved ones.
12912  * (In some cases we could avoid quoting a col_name or type_func_name
12913  * keyword, but it seems much harder than it's worth to tell that.)
12914  *
12915  * Note: ScanKeywordLookup() does case-insensitive comparison, but
12916  * that's fine, since we already know we have all-lower-case.
12917  */
12918  int kwnum = ScanKeywordLookup(ident, &ScanKeywords);
12919 
12920  if (kwnum >= 0 && ScanKeywordCategories[kwnum] != UNRESERVED_KEYWORD)
12921  safe = false;
12922  }
12923 
12924  if (safe)
12925  return ident; /* no change needed */
12926 
12927  result = (char *) palloc(strlen(ident) + nquotes + 2 + 1);
12928 
12929  optr = result;
12930  *optr++ = '"';
12931  for (ptr = ident; *ptr; ptr++)
12932  {
12933  char ch = *ptr;
12934 
12935  if (ch == '"')
12936  *optr++ = '"';
12937  *optr++ = ch;
12938  }
12939  *optr++ = '"';
12940  *optr = '\0';
12941 
12942  return result;
12943 }
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 729 of file check.c.

730 {
731  if (user_opts.check)
732  {
733  pg_log(PG_REPORT, "\n*Clusters are compatible*");
734  /* stops new cluster */
735  stop_postmaster(false);
736 
738  exit(0);
739  }
740 
741  pg_log(PG_REPORT, "\n"
742  "If pg_upgrade fails after this point, you must re-initdb the\n"
743  "new cluster before continuing.");
744 }
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 179 of file version.c.

180 {
181  UpgradeTaskReport report;
183  const char *query = "SELECT name "
184  "FROM pg_available_extensions "
185  "WHERE installed_version != default_version";
186 
187  prep_status("Checking for extension updates");
188 
189  report.file = NULL;
190  strcpy(report.path, "update_extensions.sql");
191 
193  true, &report);
194 
195  upgrade_task_run(task, cluster);
196  upgrade_task_free(task);
197 
198  if (report.file)
199  {
200  fclose(report.file);
201  report_status(PG_REPORT, "notice");
202  pg_log(PG_REPORT, "\n"
203  "Your installation contains extensions that should be updated\n"
204  "with the ALTER EXTENSION command. The file\n"
205  " %s\n"
206  "when executed by psql by the database superuser will update\n"
207  "these extensions.",
208  report.path);
209  }
210  else
211  check_ok();
212 }
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:491
unsigned char uint8
Definition: c.h:490
uint16 pg_checksum_page(char *page, BlockNumber blkno)
#define BITS_PER_BYTE
char data[BLCKSZ]
Definition: c.h:1116
#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 87 of file relfilenumber.c.

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

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