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

Go to the source code of this file.

Data Structures

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

Macros

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

Typedefs

typedef bool(* DataTypesUsageVersionCheck) (ClusterInfo *cluster)
 

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 (bool live_check)
 
void check_and_dump_old_cluster (bool live_check)
 
void check_new_cluster (void)
 
void report_clusters_compatible (void)
 
void issue_warnings_and_set_wal_level (void)
 
void output_completion_banner (char *deletion_script_file_name)
 
void check_cluster_versions (void)
 
void check_cluster_compatibility (bool live_check)
 
void create_script_for_old_cluster_deletion (char **deletion_script_file_name)
 
void get_control_data (ClusterInfo *cluster, bool live_check)
 
void check_control_data (ControlData *oldctrl, ControlData *newctrl)
 
void disable_old_cluster (void)
 
void generate_old_dump (void)
 
bool exec_prog (const char *log_filename, const char *opt_log_file, bool report_error, bool exit_on_error, const char *fmt,...) pg_attribute_printf(5
 
bool void verify_directories (void)
 
bool pid_lock_file_exists (const char *datadir)
 
void cloneFile (const char *src, const char *dst, const char *schemaName, const char *relName)
 
void copyFile (const char *src, const char *dst, const char *schemaName, const char *relName)
 
void 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, bool live_check)
 
int count_old_cluster_logical_slots (void)
 
int count_old_cluster_subscriptions (void)
 
void parseCommandLine (int argc, char *argv[])
 
void adjust_data_dir (ClusterInfo *cluster)
 
void get_sock_dir (ClusterInfo *cluster, bool live_check)
 
void transfer_all_new_tablespaces (DbInfoArr *old_db_arr, DbInfoArr *new_db_arr, char *old_pgdata, char *new_pgdata)
 
void transfer_all_new_dbs (DbInfoArr *old_db_arr, DbInfoArr *new_db_arr, char *old_pgdata, char *new_pgdata, char *old_tablespace)
 
void init_tablespaces (void)
 
PGconnconnectToServer (ClusterInfo *cluster, const char *db_name)
 
PGresultexecuteQueryOrDie (PGconn *conn, const char *fmt,...) pg_attribute_printf(2
 
PGresult char * cluster_conn_opts (ClusterInfo *cluster)
 
bool start_postmaster (ClusterInfo *cluster, bool report_and_exit_on_error)
 
void stop_postmaster (bool in_atexit)
 
uint32 get_major_server_version (ClusterInfo *cluster)
 
void check_pghost_envvar (void)
 
char * quote_identifier (const char *s)
 
int get_user_info (char **user_name_p)
 
void check_ok (void)
 
void report_status (eLogType type, const char *fmt,...) pg_attribute_printf(2
 
void void pg_log (eLogType type, const char *fmt,...) pg_attribute_printf(2
 
void void void pg_fatal (const char *fmt,...) pg_attribute_printf(1
 
void void void pg_attribute_noreturn ()
 
void end_progress_output (void)
 
void cleanup_output_dirs (void)
 
void prep_status (const char *fmt,...) pg_attribute_printf(1
 
void void prep_status_progress (const char *fmt,...) pg_attribute_printf(1
 
void void unsigned int str2uint (const char *str)
 
bool 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)
 

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

◆ fopen_priv

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

Definition at line 420 of file pg_upgrade.h.

◆ GET_MAJOR_VERSION

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

Definition at line 27 of file pg_upgrade.h.

◆ GLOBALS_DUMP_FILE

#define GLOBALS_DUMP_FILE   "pg_upgrade_dump_globals.sql"

Definition at line 30 of file pg_upgrade.h.

◆ INTERNAL_LOG_FILE

#define INTERNAL_LOG_FILE   "pg_upgrade_internal.log"

Definition at line 46 of file pg_upgrade.h.

◆ JSONB_FORMAT_CHANGE_CAT_VER

#define JSONB_FORMAT_CHANGE_CAT_VER   201409291

Definition at line 127 of file pg_upgrade.h.

◆ LARGE_OBJECT_SIZE_PG_CONTROL_VER

#define LARGE_OBJECT_SIZE_PG_CONTROL_VER   942

Definition at line 122 of file pg_upgrade.h.

◆ LOG_OUTPUTDIR

#define LOG_OUTPUTDIR   "log"

Definition at line 40 of file pg_upgrade.h.

◆ MAX_STRING

#define MAX_STRING   1024

Definition at line 22 of file pg_upgrade.h.

◆ MESSAGE_WIDTH

#define MESSAGE_WIDTH   62

Definition at line 25 of file pg_upgrade.h.

◆ MULTIXACT_FORMATCHANGE_CAT_VER

#define MULTIXACT_FORMATCHANGE_CAT_VER   201301231

Definition at line 116 of file pg_upgrade.h.

◆ PATH_QUOTE

#define PATH_QUOTE   '\''

Definition at line 83 of file pg_upgrade.h.

◆ PATH_SEPARATOR

#define PATH_SEPARATOR   '/'

Definition at line 82 of file pg_upgrade.h.

◆ pg_mv_file

#define pg_mv_file   rename

Definition at line 81 of file pg_upgrade.h.

◆ QUERY_ALLOC

#define QUERY_ALLOC   8192

Definition at line 23 of file pg_upgrade.h.

◆ RM_CMD

#define RM_CMD   "rm -f"

Definition at line 84 of file pg_upgrade.h.

◆ RMDIR_CMD

#define RMDIR_CMD   "rm -rf"

Definition at line 85 of file pg_upgrade.h.

◆ SCRIPT_EXT

#define SCRIPT_EXT   "sh"

Definition at line 87 of file pg_upgrade.h.

◆ SCRIPT_PREFIX

#define SCRIPT_PREFIX   "./"

Definition at line 86 of file pg_upgrade.h.

◆ SERVER_LOG_FILE

#define SERVER_LOG_FILE   "pg_upgrade_server.log"

Definition at line 44 of file pg_upgrade.h.

◆ SERVER_START_LOG_FILE

#define SERVER_START_LOG_FILE   SERVER_LOG_FILE

Definition at line 67 of file pg_upgrade.h.

◆ SERVER_STOP_LOG_FILE

#define SERVER_STOP_LOG_FILE   SERVER_LOG_FILE

Definition at line 68 of file pg_upgrade.h.

◆ UTILITY_LOG_FILE

#define UTILITY_LOG_FILE   "pg_upgrade_utility.log"

Definition at line 45 of file pg_upgrade.h.

◆ VISIBILITY_MAP_FROZEN_BIT_CAT_VER

#define VISIBILITY_MAP_FROZEN_BIT_CAT_VER   201603011

Definition at line 108 of file pg_upgrade.h.

Typedef Documentation

◆ DataTypesUsageVersionCheck

typedef bool(* DataTypesUsageVersionCheck) (ClusterInfo *cluster)

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

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

◆ transferMode

Enumerator
TRANSFER_MODE_CLONE 
TRANSFER_MODE_COPY 
TRANSFER_MODE_COPY_FILE_RANGE 
TRANSFER_MODE_LINK 

Definition at line 255 of file pg_upgrade.h.

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

Function Documentation

◆ adjust_data_dir()

void adjust_data_dir ( ClusterInfo cluster)

Definition at line 404 of file option.c.

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

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

◆ check_and_dump_old_cluster()

void check_and_dump_old_cluster ( bool  live_check)

Definition at line 576 of file check.c.

577 {
578  /* -- OLD -- */
579 
580  if (!live_check)
582 
583  /*
584  * Extract a list of databases, tables, and logical replication slots from
585  * the old cluster.
586  */
588 
590 
592 
593 
594  /*
595  * Check for various failure cases
596  */
601 
603  {
604  /*
605  * Logical replication slots can be migrated since PG17. See comments
606  * atop get_old_cluster_logical_slot_infos().
607  */
609 
610  /*
611  * Subscriptions and their dependencies can be migrated since PG17.
612  * See comments atop get_db_subscription_count().
613  */
615  }
616 
618 
619  /*
620  * PG 14 changed the function signature of encoding conversion functions.
621  * Conversions from older versions cannot be upgraded automatically
622  * because the user-defined functions used by the encoding conversions
623  * need to be changed to match the new signature.
624  */
627 
628  /*
629  * Pre-PG 14 allowed user defined postfix operators, which are not
630  * supported anymore. Verify there are none, iff applicable.
631  */
634 
635  /*
636  * PG 14 changed polymorphic functions from anyarray to
637  * anycompatiblearray.
638  */
641 
642  /*
643  * Pre-PG 12 allowed tables to be declared WITH OIDS, which is not
644  * supported anymore. Verify there are none, iff applicable.
645  */
648 
649  /*
650  * Pre-PG 10 allowed tables with 'unknown' type columns and non WAL logged
651  * hash indexes
652  */
654  {
655  if (user_opts.check)
657  }
658 
659  /* 9.5 and below should not have roles starting with pg_ */
662 
663  /*
664  * While not a check option, we do this now because this is the only time
665  * the old server is running.
666  */
667  if (!user_opts.check)
669 
670  if (!live_check)
671  stop_postmaster(false);
672 }
static void check_for_tables_with_oids(ClusterInfo *cluster)
Definition: check.c:1509
static void check_for_pg_role_prefix(ClusterInfo *cluster)
Definition: check.c:1584
static DataTypesUsageChecks data_types_usage_checks[]
Definition: check.c:97
static void check_old_cluster_subscription_state(void)
Definition: check.c:1917
static void check_for_data_types_usage(ClusterInfo *cluster, DataTypesUsageChecks *checks)
Definition: check.c:337
static void check_old_cluster_for_valid_slots(bool live_check)
Definition: check.c:1842
static void check_is_install_user(ClusterInfo *cluster)
Definition: check.c:1027
static void check_for_isn_and_int8_passing_mismatch(ClusterInfo *cluster)
Definition: check.c:1204
static void check_for_user_defined_postfix_ops(ClusterInfo *cluster)
Definition: check.c:1285
static void check_for_prepared_transactions(ClusterInfo *cluster)
Definition: check.c:1169
static void check_proper_datallowconn(ClusterInfo *cluster)
Definition: check.c:1085
static void check_for_user_defined_encoding_conversions(ClusterInfo *cluster)
Definition: check.c:1639
static void check_for_incompatible_polymorphics(ClusterInfo *cluster)
Definition: check.c:1383
void generate_old_dump(void)
Definition: dump.c:16
void get_loadable_libraries(void)
Definition: function.c:55
void get_db_rel_and_slot_infos(ClusterInfo *cluster, bool live_check)
Definition: info.c:280
static pid_t start_postmaster(void)
Definition: pg_ctl.c:439
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:295
bool check
Definition: pg_upgrade.h:324

References UserOpts::check, check_for_data_types_usage(), check_for_incompatible_polymorphics(), check_for_isn_and_int8_passing_mismatch(), check_for_pg_role_prefix(), check_for_prepared_transactions(), check_for_tables_with_oids(), check_for_user_defined_encoding_conversions(), check_for_user_defined_postfix_ops(), check_is_install_user(), check_old_cluster_for_valid_slots(), check_old_cluster_subscription_state(), check_proper_datallowconn(), data_types_usage_checks, generate_old_dump(), get_db_rel_and_slot_infos(), get_loadable_libraries(), GET_MAJOR_VERSION, init_tablespaces(), 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 ( bool  live_check)

Definition at line 829 of file check.c.

830 {
831  /* get/check pg_control data of servers */
832  get_control_data(&old_cluster, live_check);
833  get_control_data(&new_cluster, false);
835 
836  if (live_check && old_cluster.port == new_cluster.port)
837  pg_fatal("When checking a live server, "
838  "the old and new port numbers must be different.");
839 }
void get_control_data(ClusterInfo *cluster, bool live_check)
Definition: controldata.c:36
void check_control_data(ControlData *oldctrl, ControlData *newctrl)
Definition: controldata.c:654
ClusterInfo new_cluster
Definition: pg_upgrade.c:72
unsigned short port
Definition: pg_upgrade.h:294
ControlData controldata
Definition: pg_upgrade.h:284

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

Referenced by main().

◆ check_cluster_versions()

void check_cluster_versions ( void  )

Definition at line 786 of file check.c.

787 {
788  prep_status("Checking cluster versions");
789 
790  /* cluster versions should already have been obtained */
793 
794  /*
795  * We allow upgrades from/to the same major version for alpha/beta
796  * upgrades
797  */
798 
800  pg_fatal("This utility can only upgrade from PostgreSQL version %s and later.",
801  "9.2");
802 
803  /* Only current PG version is supported as a target */
805  pg_fatal("This utility can only upgrade to PostgreSQL version %s.",
806  PG_MAJORVERSION);
807 
808  /*
809  * We can't allow downgrading because we use the target pg_dump, and
810  * pg_dump cannot operate on newer database versions, only current and
811  * older versions.
812  */
814  pg_fatal("This utility cannot be used to downgrade to older major PostgreSQL versions.");
815 
816  /* Ensure binaries match the designated data directories */
819  pg_fatal("Old cluster data and binary directories are from different major versions.");
822  pg_fatal("New cluster data and binary directories are from different major versions.");
823 
824  check_ok();
825 }
#define Assert(condition)
Definition: c.h:858
uint32 bin_version
Definition: pg_upgrade.h:297

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

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

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

Referenced by check_cluster_compatibility().

◆ check_copy_file_range()

void check_copy_file_range ( void  )

Definition at line 400 of file file.c.

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

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

147 {
148  PGconn *conn = connectToServer(&new_cluster, "template1");
149  int libnum;
150  int was_load_failure = false;
151  FILE *script = NULL;
152  char output_path[MAXPGPATH];
153 
154  prep_status("Checking for presence of required libraries");
155 
156  snprintf(output_path, sizeof(output_path), "%s/%s",
157  log_opts.basedir, "loadable_libraries.txt");
158 
159  /*
160  * Now we want to sort the library names into order. This avoids multiple
161  * probes of the same library, and ensures that libraries are probed in a
162  * consistent order, which is important for reproducible behavior if one
163  * library depends on another.
164  */
167 
168  for (libnum = 0; libnum < os_info.num_libraries; libnum++)
169  {
170  char *lib = os_info.libraries[libnum].name;
171  int llen = strlen(lib);
172  char cmd[7 + 2 * MAXPGPATH + 1];
173  PGresult *res;
174 
175  /* Did the library name change? Probe it. */
176  if (libnum == 0 || strcmp(lib, os_info.libraries[libnum - 1].name) != 0)
177  {
178  strcpy(cmd, "LOAD '");
179  PQescapeStringConn(conn, cmd + strlen(cmd), lib, llen, NULL);
180  strcat(cmd, "'");
181 
182  res = PQexec(conn, cmd);
183 
185  {
186  was_load_failure = true;
187 
188  if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL)
189  pg_fatal("could not open file \"%s\": %m", output_path);
190  fprintf(script, _("could not load library \"%s\": %s"),
191  lib,
193  }
194  else
195  was_load_failure = false;
196 
197  PQclear(res);
198  }
199 
200  if (was_load_failure)
201  fprintf(script, _("In database: %s\n"),
203  }
204 
205  PQfinish(conn);
206 
207  if (script)
208  {
209  fclose(script);
210  pg_log(PG_REPORT, "fatal");
211  pg_fatal("Your installation references loadable libraries that are missing from the\n"
212  "new installation. You can add these libraries to the new installation,\n"
213  "or remove the functions using them from the old installation. A list of\n"
214  "problem libraries is in the file:\n"
215  " %s", output_path);
216  }
217  else
218  check_ok();
219 }
#define _(x)
Definition: elog.c:90
char * PQerrorMessage(const PGconn *conn)
Definition: fe-connect.c:7147
void PQfinish(PGconn *conn)
Definition: fe-connect.c:4868
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:100
OSInfo os_info
Definition: pg_upgrade.c:73
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:420
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:449
PGconn * conn
Definition: streamutil.c:55
DbInfoArr dbarr
Definition: pg_upgrade.h:286
DbInfo * dbs
Definition: pg_upgrade.h:217
char * db_name
Definition: pg_upgrade.h:195
char * name
Definition: pg_upgrade.h:335
char * basedir
Definition: pg_upgrade.h:312
LibraryInfo * libraries
Definition: pg_upgrade.h:349
int num_libraries
Definition: pg_upgrade.h:350

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

677 {
679 
681 
683 
684  switch (user_opts.transfer_mode)
685  {
686  case TRANSFER_MODE_CLONE:
688  break;
689  case TRANSFER_MODE_COPY:
690  break;
693  break;
694  case TRANSFER_MODE_LINK:
695  check_hard_link();
696  break;
697  }
698 
700 
702 
704 
706 
708 }
static void check_new_cluster_logical_replication_slots(void)
Definition: check.c:1723
static void check_new_cluster_subscription_configuration(void)
Definition: check.c:1796
static void check_new_cluster_is_empty(void)
Definition: check.c:843
static void check_for_new_tablespace_dir(void)
Definition: check.c:875
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:146
transferMode transfer_mode
Definition: pg_upgrade.h:327

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:1863
void PQconninfoFree(PQconninfoOption *connOptions)
Definition: fe-connect.c:6980
return str start
static struct @155 value
static bool is_unixsock_path(const char *path)
Definition: pqcomm.h:67

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

Referenced by setup().

◆ cleanup_output_dirs()

void cleanup_output_dirs ( void  )

Definition at line 63 of file util.c.

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

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

Referenced by main(), and report_clusters_compatible().

◆ cloneFile()

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

Definition at line 39 of file file.c.

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

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

Referenced by transfer_relfile().

◆ cluster_conn_opts()

PGresult char* cluster_conn_opts ( ClusterInfo cluster)

Definition at line 92 of file server.c.

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

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

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

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

◆ copyFile()

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

Definition at line 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 740 of file info.c.

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

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

◆ count_old_cluster_subscriptions()

int count_old_cluster_subscriptions ( void  )

Definition at line 789 of file info.c.

790 {
791  int nsubs = 0;
792 
793  for (int dbnum = 0; dbnum < old_cluster.dbarr.ndbs; dbnum++)
794  nsubs += old_cluster.dbarr.dbs[dbnum].nsubs;
795 
796  return nsubs;
797 }
int nsubs
Definition: pg_upgrade.h:200

References ClusterInfo::dbarr, DbInfoArr::dbs, DbInfoArr::ndbs, DbInfo::nsubs, and old_cluster.

Referenced by check_new_cluster_subscription_configuration().

◆ create_script_for_old_cluster_deletion()

void create_script_for_old_cluster_deletion ( char **  deletion_script_file_name)

Definition at line 904 of file check.c.

905 {
906  FILE *script = NULL;
907  int tblnum;
908  char old_cluster_pgdata[MAXPGPATH],
909  new_cluster_pgdata[MAXPGPATH];
910 
911  *deletion_script_file_name = psprintf("%sdelete_old_cluster.%s",
913 
914  strlcpy(old_cluster_pgdata, old_cluster.pgdata, MAXPGPATH);
915  canonicalize_path(old_cluster_pgdata);
916 
917  strlcpy(new_cluster_pgdata, new_cluster.pgdata, MAXPGPATH);
918  canonicalize_path(new_cluster_pgdata);
919 
920  /* Some people put the new data directory inside the old one. */
921  if (path_is_prefix_of_path(old_cluster_pgdata, new_cluster_pgdata))
922  {
924  "\nWARNING: new data directory should not be inside the old data directory, i.e. %s", old_cluster_pgdata);
925 
926  /* Unlink file in case it is left over from a previous run. */
927  unlink(*deletion_script_file_name);
928  pg_free(*deletion_script_file_name);
929  *deletion_script_file_name = NULL;
930  return;
931  }
932 
933  /*
934  * Some users (oddly) create tablespaces inside the cluster data
935  * directory. We can't create a proper old cluster delete script in that
936  * case.
937  */
938  for (tblnum = 0; tblnum < os_info.num_old_tablespaces; tblnum++)
939  {
940  char old_tablespace_dir[MAXPGPATH];
941 
942  strlcpy(old_tablespace_dir, os_info.old_tablespaces[tblnum], MAXPGPATH);
943  canonicalize_path(old_tablespace_dir);
944  if (path_is_prefix_of_path(old_cluster_pgdata, old_tablespace_dir))
945  {
946  /* reproduce warning from CREATE TABLESPACE that is in the log */
948  "\nWARNING: user-defined tablespace locations should not be inside the data directory, i.e. %s", old_tablespace_dir);
949 
950  /* Unlink file in case it is left over from a previous run. */
951  unlink(*deletion_script_file_name);
952  pg_free(*deletion_script_file_name);
953  *deletion_script_file_name = NULL;
954  return;
955  }
956  }
957 
958  prep_status("Creating script to delete old cluster");
959 
960  if ((script = fopen_priv(*deletion_script_file_name, "w")) == NULL)
961  pg_fatal("could not open file \"%s\": %m",
962  *deletion_script_file_name);
963 
964 #ifndef WIN32
965  /* add shebang header */
966  fprintf(script, "#!/bin/sh\n\n");
967 #endif
968 
969  /* delete old cluster's default tablespace */
970  fprintf(script, RMDIR_CMD " %c%s%c\n", PATH_QUOTE,
972 
973  /* delete old cluster's alternate tablespaces */
974  for (tblnum = 0; tblnum < os_info.num_old_tablespaces; tblnum++)
975  {
976  /*
977  * Do the old cluster's per-database directories share a directory
978  * with a new version-specific tablespace?
979  */
980  if (strlen(old_cluster.tablespace_suffix) == 0)
981  {
982  /* delete per-database directories */
983  int dbnum;
984 
985  fprintf(script, "\n");
986 
987  for (dbnum = 0; dbnum < old_cluster.dbarr.ndbs; dbnum++)
988  fprintf(script, RMDIR_CMD " %c%s%c%u%c\n", PATH_QUOTE,
991  PATH_QUOTE);
992  }
993  else
994  {
995  char *suffix_path = pg_strdup(old_cluster.tablespace_suffix);
996 
997  /*
998  * Simply delete the tablespace directory, which might be ".old"
999  * or a version-specific subdirectory.
1000  */
1001  fprintf(script, RMDIR_CMD " %c%s%s%c\n", PATH_QUOTE,
1003  fix_path_separator(suffix_path), PATH_QUOTE);
1004  pfree(suffix_path);
1005  }
1006  }
1007 
1008  fclose(script);
1009 
1010 #ifndef WIN32
1011  if (chmod(*deletion_script_file_name, S_IRWXU) != 0)
1012  pg_fatal("could not add execute permission to file \"%s\": %m",
1013  *deletion_script_file_name);
1014 #endif
1015 
1016  check_ok();
1017 }
static char * fix_path_separator(char *path)
Definition: check.c:537
void pfree(void *pointer)
Definition: mcxt.c:1520
#define PATH_SEPARATOR
Definition: pg_upgrade.h:82
#define RMDIR_CMD
Definition: pg_upgrade.h:85
#define SCRIPT_EXT
Definition: pg_upgrade.h:87
#define SCRIPT_PREFIX
Definition: pg_upgrade.h:86
#define PATH_QUOTE
Definition: pg_upgrade.h:83
bool path_is_prefix_of_path(const char *path1, const char *path2)
Definition: path.c:559
void canonicalize_path(char *path)
Definition: path.c:264
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition: strlcpy.c:45
char * psprintf(const char *fmt,...)
Definition: psprintf.c:46
const char * tablespace_suffix
Definition: pg_upgrade.h:298
Oid db_oid
Definition: pg_upgrade.h:194
int num_old_tablespaces
Definition: pg_upgrade.h:348
char ** old_tablespaces
Definition: pg_upgrade.h:347
#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 711 of file controldata.c.

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

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

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

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

Referenced by transfer_all_new_dbs().

◆ generate_old_dump()

void generate_old_dump ( void  )

Definition at line 16 of file dump.c.

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

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

Referenced by check_and_dump_old_cluster().

◆ get_control_data()

void get_control_data ( ClusterInfo cluster,
bool  live_check 
)

Definition at line 36 of file controldata.c.

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

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

Referenced by check_cluster_compatibility().

◆ get_db_rel_and_slot_infos()

void get_db_rel_and_slot_infos ( ClusterInfo cluster,
bool  live_check 
)

Definition at line 280 of file info.c.

281 {
282  int dbnum;
283 
284  if (cluster->dbarr.dbs != NULL)
286 
289 
290  for (dbnum = 0; dbnum < cluster->dbarr.ndbs; dbnum++)
291  {
292  DbInfo *pDbInfo = &cluster->dbarr.dbs[dbnum];
293 
294  get_rel_infos(cluster, pDbInfo);
295 
296  /*
297  * Retrieve the logical replication slots infos and the subscriptions
298  * count for the old cluster.
299  */
300  if (cluster == &old_cluster)
301  {
302  get_old_cluster_logical_slot_infos(pDbInfo, live_check);
303  get_db_subscription_count(pDbInfo);
304  }
305  }
306 
307  if (cluster == &old_cluster)
308  pg_log(PG_VERBOSE, "\nsource databases:");
309  else
310  pg_log(PG_VERBOSE, "\ntarget databases:");
311 
312  if (log_opts.verbose)
313  print_db_infos(&cluster->dbarr);
314 }
static void get_template0_info(ClusterInfo *cluster)
Definition: info.c:322
static void get_old_cluster_logical_slot_infos(DbInfo *dbinfo, bool live_check)
Definition: info.c:648
static void get_db_subscription_count(DbInfo *dbinfo)
Definition: info.c:760
static void get_db_infos(ClusterInfo *cluster)
Definition: info.c:387
static void free_db_and_rel_infos(DbInfoArr *db_arr)
Definition: info.c:800
static void print_db_infos(DbInfoArr *db_arr)
Definition: info.c:834
static void get_rel_infos(ClusterInfo *cluster, DbInfo *dbinfo)
Definition: info.c:453

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

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

◆ get_loadable_libraries()

void get_loadable_libraries ( void  )

Definition at line 55 of file function.c.

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

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

Referenced by check_and_dump_old_cluster().

◆ get_major_server_version()

uint32 get_major_server_version ( ClusterInfo cluster)

Definition at line 159 of file server.c.

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

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

Referenced by check_data_dir().

◆ get_sock_dir()

void get_sock_dir ( ClusterInfo cluster,
bool  live_check 
)

Definition at line 473 of file option.c.

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

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

Referenced by main().

◆ get_user_info()

int get_user_info ( char **  user_name_p)

Definition at line 323 of file util.c.

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

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

Referenced by parseCommandLine().

◆ init_tablespaces()

void init_tablespaces ( void  )

Definition at line 19 of file tablespace.c.

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

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

Referenced by check_and_dump_old_cluster().

◆ issue_warnings_and_set_wal_level()

void issue_warnings_and_set_wal_level ( void  )

Definition at line 731 of file check.c.

732 {
733  /*
734  * We unconditionally start/stop the new server because pg_resetwal -o set
735  * wal_level to 'minimum'. If the user is upgrading standby servers using
736  * the rsync instructions, they will need pg_upgrade to write its final
737  * WAL record showing wal_level as 'replica'.
738  */
740 
741  /* Reindex hash indexes for old < 10.0 */
744 
746 
747  stop_postmaster(false);
748 }
void report_extension_updates(ClusterInfo *cluster)
Definition: version.c:147

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:127

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:12623
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 ( bool  live_check)

Definition at line 558 of file check.c.

559 {
560  if (user_opts.check && live_check)
561  {
563  "Performing Consistency Checks on Old Live Server\n"
564  "------------------------------------------------");
565  }
566  else
567  {
569  "Performing Consistency Checks\n"
570  "-----------------------------");
571  }
572 }

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

Referenced by main().

◆ output_completion_banner()

void output_completion_banner ( char *  deletion_script_file_name)

Definition at line 752 of file check.c.

753 {
754  PQExpBufferData user_specification;
755 
756  initPQExpBuffer(&user_specification);
758  {
759  appendPQExpBufferStr(&user_specification, "-U ");
760  appendShellString(&user_specification, os_info.user);
761  appendPQExpBufferChar(&user_specification, ' ');
762  }
763 
765  "Optimizer statistics are not transferred by pg_upgrade.\n"
766  "Once you start the new server, consider running:\n"
767  " %s/vacuumdb %s--all --analyze-in-stages", new_cluster.bindir, user_specification.data);
768 
769  if (deletion_script_file_name)
771  "Running this script will delete the old cluster's data files:\n"
772  " %s",
773  deletion_script_file_name);
774  else
776  "Could not create a script to delete the old cluster's data files\n"
777  "because user-defined tablespaces or the new cluster's data directory\n"
778  "exist in the old cluster directory. The old cluster's contents must\n"
779  "be deleted manually.");
780 
781  termPQExpBuffer(&user_specification);
782 }
bool user_specified
Definition: pg_upgrade.h:346

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

Referenced by main().

◆ parallel_exec_prog()

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

◆ parallel_transfer_all_new_dbs()

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

Definition at line 172 of file parallel.c.

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

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

Referenced by transfer_all_new_tablespaces().

◆ parseCommandLine()

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

Definition at line 39 of file option.c.

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

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

12624 {
12625  /*
12626  * Can avoid quoting if ident starts with a lowercase letter or underscore
12627  * and contains only lowercase letters, digits, and underscores, *and* is
12628  * not any SQL keyword. Otherwise, supply quotes.
12629  */
12630  int nquotes = 0;
12631  bool safe;
12632  const char *ptr;
12633  char *result;
12634  char *optr;
12635 
12636  /*
12637  * would like to use <ctype.h> macros here, but they might yield unwanted
12638  * locale-specific results...
12639  */
12640  safe = ((ident[0] >= 'a' && ident[0] <= 'z') || ident[0] == '_');
12641 
12642  for (ptr = ident; *ptr; ptr++)
12643  {
12644  char ch = *ptr;
12645 
12646  if ((ch >= 'a' && ch <= 'z') ||
12647  (ch >= '0' && ch <= '9') ||
12648  (ch == '_'))
12649  {
12650  /* okay */
12651  }
12652  else
12653  {
12654  safe = false;
12655  if (ch == '"')
12656  nquotes++;
12657  }
12658  }
12659 
12661  safe = false;
12662 
12663  if (safe)
12664  {
12665  /*
12666  * Check for keyword. We quote keywords except for unreserved ones.
12667  * (In some cases we could avoid quoting a col_name or type_func_name
12668  * keyword, but it seems much harder than it's worth to tell that.)
12669  *
12670  * Note: ScanKeywordLookup() does case-insensitive comparison, but
12671  * that's fine, since we already know we have all-lower-case.
12672  */
12673  int kwnum = ScanKeywordLookup(ident, &ScanKeywords);
12674 
12675  if (kwnum >= 0 && ScanKeywordCategories[kwnum] != UNRESERVED_KEYWORD)
12676  safe = false;
12677  }
12678 
12679  if (safe)
12680  return ident; /* no change needed */
12681 
12682  result = (char *) palloc(strlen(ident) + nquotes + 2 + 1);
12683 
12684  optr = result;
12685  *optr++ = '"';
12686  for (ptr = ident; *ptr; ptr++)
12687  {
12688  char ch = *ptr;
12689 
12690  if (ch == '"')
12691  *optr++ = '"';
12692  *optr++ = ch;
12693  }
12694  *optr++ = '"';
12695  *optr = '\0';
12696 
12697  return result;
12698 }
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:1316
bool quote_all_identifiers
Definition: ruleutils.c:323

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

713 {
714  if (user_opts.check)
715  {
716  pg_log(PG_REPORT, "\n*Clusters are compatible*");
717  /* stops new cluster */
718  stop_postmaster(false);
719 
721  exit(0);
722  }
723 
724  pg_log(PG_REPORT, "\n"
725  "If pg_upgrade fails after this point, you must re-initdb the\n"
726  "new cluster before continuing.");
727 }
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 147 of file version.c.

148 {
149  int dbnum;
150  FILE *script = NULL;
151  char *output_path = "update_extensions.sql";
152 
153  prep_status("Checking for extension updates");
154 
155  for (dbnum = 0; dbnum < cluster->dbarr.ndbs; dbnum++)
156  {
157  PGresult *res;
158  bool db_used = false;
159  int ntups;
160  int rowno;
161  int i_name;
162  DbInfo *active_db = &cluster->dbarr.dbs[dbnum];
163  PGconn *conn = connectToServer(cluster, active_db->db_name);
164 
165  /* find extensions needing updates */
167  "SELECT name "
168  "FROM pg_available_extensions "
169  "WHERE installed_version != default_version"
170  );
171 
172  ntups = PQntuples(res);
173  i_name = PQfnumber(res, "name");
174  for (rowno = 0; rowno < ntups; rowno++)
175  {
176  if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL)
177  pg_fatal("could not open file \"%s\": %m", output_path);
178  if (!db_used)
179  {
180  PQExpBufferData connectbuf;
181 
182  initPQExpBuffer(&connectbuf);
183  appendPsqlMetaConnect(&connectbuf, active_db->db_name);
184  fputs(connectbuf.data, script);
185  termPQExpBuffer(&connectbuf);
186  db_used = true;
187  }
188  fprintf(script, "ALTER EXTENSION %s UPDATE;\n",
189  quote_identifier(PQgetvalue(res, rowno, i_name)));
190  }
191 
192  PQclear(res);
193 
194  PQfinish(conn);
195  }
196 
197  if (script)
198  {
199  fclose(script);
200  report_status(PG_REPORT, "notice");
201  pg_log(PG_REPORT, "\n"
202  "Your installation contains extensions that should be updated\n"
203  "with the ALTER EXTENSION command. The file\n"
204  " %s\n"
205  "when executed by psql by the database superuser will update\n"
206  "these extensions.",
207  output_path);
208  }
209  else
210  check_ok();
211 }

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

Referenced by issue_warnings_and_set_wal_level().

◆ report_status()

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

◆ rewriteVisibilityMap()

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

Definition at line 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:170
#define SizeOfPageHeaderData
Definition: bufpage.h:213
unsigned short uint16
Definition: c.h:505
unsigned char uint8
Definition: c.h:504
uint16 pg_checksum_page(char *page, BlockNumber blkno)
#define BITS_PER_BYTE
char data[BLCKSZ]
Definition: c.h:1137
#define BITS_PER_HEAPBLOCK
#define VISIBILITYMAP_ALL_VISIBLE
#define fstat
Definition: win32_port.h:283

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

Referenced by transfer_relfile().

◆ start_postmaster()

bool start_postmaster ( ClusterInfo cluster,
bool  report_and_exit_on_error 
)

Definition at line 198 of file server.c.

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

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

◆ stop_postmaster()

void stop_postmaster ( bool  in_atexit)

Definition at line 342 of file server.c.

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

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

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

◆ str2uint()

void void unsigned int str2uint ( const char *  str)

Definition at line 352 of file util.c.

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

References str.

Referenced by get_control_data().

◆ transfer_all_new_dbs()

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

Definition at line 89 of file relfilenumber.c.

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

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

Referenced by parallel_transfer_all_new_dbs().

◆ transfer_all_new_tablespaces()

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

Definition at line 29 of file relfilenumber.c.

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

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

Referenced by main().

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

◆ old_cluster

◆ os_info

◆ output_files

char* output_files[]
extern

Definition at line 75 of file pg_upgrade.c.

Referenced by make_outputdirs().

◆ user_opts