PostgreSQL Source Code git master
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
pg_upgrade.h File Reference
#include <unistd.h>
#include <assert.h>
#include <sys/stat.h>
#include <sys/time.h>
#include "common/relpath.h"
#include "libpq-fe.h"
Include dependency graph for pg_upgrade.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

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

Macros

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

Typedefs

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

Enumerations

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

Functions

void output_check_banner (void)
 
void check_and_dump_old_cluster (void)
 
void check_new_cluster (void)
 
void report_clusters_compatible (void)
 
void issue_warnings_and_set_wal_level (void)
 
void output_completion_banner (char *deletion_script_file_name)
 
void check_cluster_versions (void)
 
void check_cluster_compatibility (void)
 
void create_script_for_old_cluster_deletion (char **deletion_script_file_name)
 
void get_control_data (ClusterInfo *cluster)
 
void check_control_data (ControlData *oldctrl, ControlData *newctrl)
 
void disable_old_cluster (transferMode transfer_mode)
 
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 (transferMode transfer_mode)
 
void get_loadable_libraries (void)
 
void check_loadable_libraries (void)
 
FileNameMapgen_db_file_maps (DbInfo *old_db, DbInfo *new_db, int *nmaps, const char *old_pgdata, const char *new_pgdata)
 
void get_db_rel_and_slot_infos (ClusterInfo *cluster)
 
int count_old_cluster_logical_slots (void)
 
void get_subscription_count (ClusterInfo *cluster)
 
void parseCommandLine (int argc, char *argv[])
 
void adjust_data_dir (ClusterInfo *cluster)
 
void get_sock_dir (ClusterInfo *cluster)
 
void transfer_all_new_tablespaces (DbInfoArr *old_db_arr, DbInfoArr *new_db_arr, char *old_pgdata, char *new_pgdata)
 
void transfer_all_new_dbs (DbInfoArr *old_db_arr, DbInfoArr *new_db_arr, char *old_pgdata, char *new_pgdata, char *old_tablespace)
 
void init_tablespaces (void)
 
PGconnconnectToServer (ClusterInfo *cluster, const char *db_name)
 
PGresultexecuteQueryOrDie (PGconn *conn, const char *fmt,...) pg_attribute_printf(2
 
PGresult char * cluster_conn_opts (ClusterInfo *cluster)
 
bool start_postmaster (ClusterInfo *cluster, bool report_and_exit_on_error)
 
void stop_postmaster (bool in_atexit)
 
uint32 get_major_server_version (ClusterInfo *cluster)
 
void check_pghost_envvar (void)
 
char * quote_identifier (const char *s)
 
int get_user_info (char **user_name_p)
 
void check_ok (void)
 
void report_status (eLogType type, const char *fmt,...) pg_attribute_printf(2
 
void void pg_log (eLogType type, const char *fmt,...) pg_attribute_printf(2
 
void void pg_noreturn void pg_fatal (const char *fmt,...) pg_attribute_printf(1
 
void void pg_noreturn void void end_progress_output (void)
 
void cleanup_output_dirs (void)
 
void prep_status (const char *fmt,...) pg_attribute_printf(1
 
void void prep_status_progress (const char *fmt,...) pg_attribute_printf(1
 
void void unsigned int str2uint (const char *str)
 
bool jsonb_9_4_check_applicable (ClusterInfo *cluster)
 
void old_9_6_invalidate_hash_indexes (ClusterInfo *cluster, bool check_mode)
 
void report_extension_updates (ClusterInfo *cluster)
 
void parallel_exec_prog (const char *log_file, const char *opt_log_file, const char *fmt,...) pg_attribute_printf(3
 
void void parallel_transfer_all_new_dbs (DbInfoArr *old_db_arr, DbInfoArr *new_db_arr, char *old_pgdata, char *new_pgdata, char *old_tablespace)
 
bool reap_child (bool wait_for_child)
 
UpgradeTaskupgrade_task_create (void)
 
void upgrade_task_add_step (UpgradeTask *task, const char *query, UpgradeTaskProcessCB process_cb, bool free_result, void *arg)
 
void upgrade_task_run (const UpgradeTask *task, const ClusterInfo *cluster)
 
void upgrade_task_free (UpgradeTask *task)
 

Variables

char * output_files []
 
LogOpts log_opts
 
UserOpts user_opts
 
ClusterInfo old_cluster
 
ClusterInfo new_cluster
 
OSInfo os_info
 

Macro Definition Documentation

◆ BASE_OUTPUTDIR

#define BASE_OUTPUTDIR   "pg_upgrade_output.d"

Definition at line 39 of file pg_upgrade.h.

◆ DB_DUMP_FILE_MASK

#define DB_DUMP_FILE_MASK   "pg_upgrade_dump_%u.custom"

Definition at line 31 of file pg_upgrade.h.

◆ DB_DUMP_LOG_FILE_MASK

#define DB_DUMP_LOG_FILE_MASK   "pg_upgrade_dump_%u.log"

Definition at line 43 of file pg_upgrade.h.

◆ DEF_PGUPORT

#define DEF_PGUPORT   50432

Definition at line 20 of file pg_upgrade.h.

◆ DEFAULT_CHAR_SIGNEDNESS_CAT_VER

#define DEFAULT_CHAR_SIGNEDNESS_CAT_VER   202502212

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

◆ fopen_priv

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

Definition at line 430 of file pg_upgrade.h.

◆ GET_MAJOR_VERSION

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

Definition at line 27 of file pg_upgrade.h.

◆ GLOBALS_DUMP_FILE

#define GLOBALS_DUMP_FILE   "pg_upgrade_dump_globals.sql"

Definition at line 30 of file pg_upgrade.h.

◆ INTERNAL_LOG_FILE

#define INTERNAL_LOG_FILE   "pg_upgrade_internal.log"

Definition at line 46 of file pg_upgrade.h.

◆ JSONB_FORMAT_CHANGE_CAT_VER

#define JSONB_FORMAT_CHANGE_CAT_VER   201409291

Definition at line 126 of file pg_upgrade.h.

◆ LARGE_OBJECT_SIZE_PG_CONTROL_VER

#define LARGE_OBJECT_SIZE_PG_CONTROL_VER   942

Definition at line 121 of file pg_upgrade.h.

◆ LOG_OUTPUTDIR

#define LOG_OUTPUTDIR   "log"

Definition at line 40 of file pg_upgrade.h.

◆ MAX_STRING

#define MAX_STRING   1024

Definition at line 22 of file pg_upgrade.h.

◆ MESSAGE_WIDTH

#define MESSAGE_WIDTH   62

Definition at line 25 of file pg_upgrade.h.

◆ MULTIXACT_FORMATCHANGE_CAT_VER

#define MULTIXACT_FORMATCHANGE_CAT_VER   201301231

Definition at line 115 of file pg_upgrade.h.

◆ PATH_QUOTE

#define PATH_QUOTE   '\''

Definition at line 83 of file pg_upgrade.h.

◆ PATH_SEPARATOR

#define PATH_SEPARATOR   '/'

Definition at line 82 of file pg_upgrade.h.

◆ pg_mv_file

#define pg_mv_file   rename

Definition at line 81 of file pg_upgrade.h.

◆ QUERY_ALLOC

#define QUERY_ALLOC   8192

Definition at line 23 of file pg_upgrade.h.

◆ RM_CMD

#define RM_CMD   "rm -f"

Definition at line 84 of file pg_upgrade.h.

◆ RMDIR_CMD

#define RMDIR_CMD   "rm -rf"

Definition at line 85 of file pg_upgrade.h.

◆ SCRIPT_EXT

#define SCRIPT_EXT   "sh"

Definition at line 87 of file pg_upgrade.h.

◆ SCRIPT_PREFIX

#define SCRIPT_PREFIX   "./"

Definition at line 86 of file pg_upgrade.h.

◆ SERVER_LOG_FILE

#define SERVER_LOG_FILE   "pg_upgrade_server.log"

Definition at line 44 of file pg_upgrade.h.

◆ SERVER_START_LOG_FILE

#define SERVER_START_LOG_FILE   SERVER_LOG_FILE

Definition at line 67 of file pg_upgrade.h.

◆ SERVER_STOP_LOG_FILE

#define SERVER_STOP_LOG_FILE   SERVER_LOG_FILE

Definition at line 68 of file pg_upgrade.h.

◆ UTILITY_LOG_FILE

#define UTILITY_LOG_FILE   "pg_upgrade_utility.log"

Definition at line 45 of file pg_upgrade.h.

◆ VISIBILITY_MAP_FROZEN_BIT_CAT_VER

#define VISIBILITY_MAP_FROZEN_BIT_CAT_VER   201603011

Definition at line 107 of file pg_upgrade.h.

Typedef Documentation

◆ DataTypesUsageVersionCheck

typedef bool(* DataTypesUsageVersionCheck) (ClusterInfo *cluster)

Definition at line 366 of file pg_upgrade.h.

◆ UpgradeTask

typedef struct UpgradeTask UpgradeTask

Definition at line 514 of file pg_upgrade.h.

◆ UpgradeTaskProcessCB

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

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

272{
274 PG_STATUS, /* these messages do not get a newline added */
275 PG_REPORT_NONL, /* these too */
276 PG_REPORT,
278 PG_FATAL,
279} eLogType;
eLogType
Definition: pg_upgrade.h:272
@ PG_FATAL
Definition: pg_upgrade.h:278
@ PG_STATUS
Definition: pg_upgrade.h:274
@ PG_WARNING
Definition: pg_upgrade.h:277
@ PG_REPORT_NONL
Definition: pg_upgrade.h:275
@ PG_VERBOSE
Definition: pg_upgrade.h:273
@ PG_REPORT
Definition: pg_upgrade.h:276

◆ transferMode

Enumerator
TRANSFER_MODE_CLONE 
TRANSFER_MODE_COPY 
TRANSFER_MODE_COPY_FILE_RANGE 
TRANSFER_MODE_LINK 
TRANSFER_MODE_SWAP 

Definition at line 259 of file pg_upgrade.h.

260{
transferMode
Definition: pg_upgrade.h:260
@ TRANSFER_MODE_COPY
Definition: pg_upgrade.h:262
@ TRANSFER_MODE_LINK
Definition: pg_upgrade.h:264
@ TRANSFER_MODE_SWAP
Definition: pg_upgrade.h:265
@ TRANSFER_MODE_CLONE
Definition: pg_upgrade.h:261
@ TRANSFER_MODE_COPY_FILE_RANGE
Definition: pg_upgrade.h:263

Function Documentation

◆ adjust_data_dir()

void adjust_data_dir ( ClusterInfo cluster)

Definition at line 430 of file option.c.

431{
432 char filename[MAXPGPATH];
433 char cmd[MAXPGPATH],
434 cmd_output[MAX_STRING];
435 FILE *fp,
436 *output;
437 int rc;
438
439 /* Initially assume config dir and data dir are the same */
440 cluster->pgconfig = pg_strdup(cluster->pgdata);
441
442 /* If there is no postgresql.conf, it can't be a config-only dir */
443 snprintf(filename, sizeof(filename), "%s/postgresql.conf", cluster->pgconfig);
444 if ((fp = fopen(filename, "r")) == NULL)
445 return;
446 fclose(fp);
447
448 /* If PG_VERSION exists, it can't be a config-only dir */
449 snprintf(filename, sizeof(filename), "%s/PG_VERSION", cluster->pgconfig);
450 if ((fp = fopen(filename, "r")) != NULL)
451 {
452 fclose(fp);
453 return;
454 }
455
456 /* Must be a configuration directory, so find the real data directory. */
457
458 if (cluster == &old_cluster)
459 prep_status("Finding the real data directory for the source cluster");
460 else
461 prep_status("Finding the real data directory for the target cluster");
462
463 /*
464 * We don't have a data directory yet, so we can't check the PG version,
465 * so this might fail --- only works for PG 9.2+. If this fails,
466 * pg_upgrade will fail anyway because the data files will not be found.
467 */
468 snprintf(cmd, sizeof(cmd), "\"%s/postgres\" -D \"%s\" -C data_directory",
469 cluster->bindir, cluster->pgconfig);
470 fflush(NULL);
471
472 if ((output = popen(cmd, "r")) == NULL ||
473 fgets(cmd_output, sizeof(cmd_output), output) == NULL)
474 pg_fatal("could not get data directory using %s: %m", cmd);
475
476 rc = pclose(output);
477 if (rc != 0)
478 pg_fatal("could not get data directory using %s: %s",
479 cmd, wait_result_to_str(rc));
480
481 /* strip trailing newline and carriage return */
482 (void) pg_strip_crlf(cmd_output);
483
484 cluster->pgdata = pg_strdup(cmd_output);
485
486 check_ok();
487}
void cluster(ParseState *pstate, ClusterStmt *stmt, bool isTopLevel)
Definition: cluster.c:107
char * pg_strdup(const char *in)
Definition: fe_memutils.c:85
FILE * output
static void check_ok(void)
Definition: initdb.c:2117
#define pg_fatal(...)
#define MAXPGPATH
static char * filename
Definition: pg_dumpall.c:123
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:239
int pg_strip_crlf(char *str)
Definition: string.c:154
char * wait_result_to_str(int exitstatus)
Definition: wait_error.c:33

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

◆ check_and_dump_old_cluster()

void check_and_dump_old_cluster ( void  )

Definition at line 588 of file check.c.

589{
590 /* -- OLD -- */
591
594
595 /*
596 * First check that all databases allow connections since we'll otherwise
597 * fail in later stages.
598 */
600
601 /*
602 * Extract a list of databases, tables, and logical replication slots from
603 * the old cluster.
604 */
606
608
610
611
612 /*
613 * Check for various failure cases
614 */
618
620 {
621 /*
622 * Logical replication slots can be migrated since PG17. See comments
623 * atop get_old_cluster_logical_slot_infos().
624 */
626
627 /*
628 * Subscriptions and their dependencies can be migrated since PG17.
629 * Before that the logical slots are not upgraded, so we will not be
630 * able to upgrade the logical replication clusters completely.
631 */
634 }
635
637
638 /*
639 * Unicode updates can affect some objects that use expressions with
640 * functions dependent on Unicode.
641 */
643
644 /*
645 * PG 14 changed the function signature of encoding conversion functions.
646 * Conversions from older versions cannot be upgraded automatically
647 * because the user-defined functions used by the encoding conversions
648 * need to be changed to match the new signature.
649 */
652
653 /*
654 * Pre-PG 14 allowed user defined postfix operators, which are not
655 * supported anymore. Verify there are none, iff applicable.
656 */
659
660 /*
661 * PG 14 changed polymorphic functions from anyarray to
662 * anycompatiblearray.
663 */
666
667 /*
668 * Pre-PG 12 allowed tables to be declared WITH OIDS, which is not
669 * supported anymore. Verify there are none, iff applicable.
670 */
673
674 /*
675 * Pre-PG 10 allowed tables with 'unknown' type columns and non WAL logged
676 * hash indexes
677 */
679 {
680 if (user_opts.check)
682 }
683
684 /* 9.5 and below should not have roles starting with pg_ */
687
688 /*
689 * While not a check option, we do this now because this is the only time
690 * the old server is running.
691 */
692 if (!user_opts.check)
694
696 stop_postmaster(false);
697}
static void check_for_tables_with_oids(ClusterInfo *cluster)
Definition: check.c:1586
static void check_for_pg_role_prefix(ClusterInfo *cluster)
Definition: check.c:1630
static void check_for_data_types_usage(ClusterInfo *cluster)
Definition: check.c:463
static void check_old_cluster_subscription_state(void)
Definition: check.c:2173
static void check_for_unicode_update(ClusterInfo *cluster)
Definition: check.c:1825
static void check_is_install_user(ClusterInfo *cluster)
Definition: check.c:1066
static void check_for_connection_status(ClusterInfo *cluster)
Definition: check.c:1124
static void check_for_isn_and_int8_passing_mismatch(ClusterInfo *cluster)
Definition: check.c:1278
static void check_old_cluster_for_valid_slots(void)
Definition: check.c:2065
static void check_for_user_defined_postfix_ops(ClusterInfo *cluster)
Definition: check.c:1366
static void check_for_prepared_transactions(ClusterInfo *cluster)
Definition: check.c:1212
static void check_for_user_defined_encoding_conversions(ClusterInfo *cluster)
Definition: check.c:1719
static void check_for_incompatible_polymorphics(ClusterInfo *cluster)
Definition: check.c:1457
void generate_old_dump(void)
Definition: dump.c:16
void get_loadable_libraries(void)
Definition: function.c:79
void get_subscription_count(ClusterInfo *cluster)
Definition: info.c:760
void get_db_rel_and_slot_infos(ClusterInfo *cluster)
Definition: info.c:280
static pid_t start_postmaster(void)
Definition: pg_ctl.c:440
void init_tablespaces(void)
Definition: tablespace.c:19
#define GET_MAJOR_VERSION(v)
Definition: pg_upgrade.h:27
void stop_postmaster(bool in_atexit)
Definition: server.c:349
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:300
bool live_check
Definition: pg_upgrade.h:331
bool check
Definition: pg_upgrade.h:330

References UserOpts::check, check_for_connection_status(), check_for_data_types_usage(), check_for_incompatible_polymorphics(), check_for_isn_and_int8_passing_mismatch(), check_for_pg_role_prefix(), check_for_prepared_transactions(), check_for_tables_with_oids(), check_for_unicode_update(), check_for_user_defined_encoding_conversions(), check_for_user_defined_postfix_ops(), check_is_install_user(), check_old_cluster_for_valid_slots(), check_old_cluster_subscription_state(), generate_old_dump(), get_db_rel_and_slot_infos(), get_loadable_libraries(), GET_MAJOR_VERSION, get_subscription_count(), init_tablespaces(), UserOpts::live_check, ClusterInfo::major_version, old_9_6_invalidate_hash_indexes(), old_cluster, start_postmaster(), stop_postmaster(), and user_opts.

Referenced by main().

◆ check_cluster_compatibility()

void check_cluster_compatibility ( void  )

Definition at line 893 of file check.c.

894{
895 /* get/check pg_control data of servers */
899
901 pg_fatal("When checking a live server, "
902 "the old and new port numbers must be different.");
903}
void get_control_data(ClusterInfo *cluster)
Definition: controldata.c:38
void check_control_data(ControlData *oldctrl, ControlData *newctrl)
Definition: controldata.c:698
ClusterInfo new_cluster
Definition: pg_upgrade.c:72
unsigned short port
Definition: pg_upgrade.h:299
ControlData controldata
Definition: pg_upgrade.h:289

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

Referenced by main().

◆ check_cluster_versions()

void check_cluster_versions ( void  )

Definition at line 838 of file check.c.

839{
840 prep_status("Checking cluster versions");
841
842 /* cluster versions should already have been obtained */
845
846 /*
847 * We allow upgrades from/to the same major version for alpha/beta
848 * upgrades
849 */
850
852 pg_fatal("This utility can only upgrade from PostgreSQL version %s and later.",
853 "9.2");
854
855 /* Only current PG version is supported as a target */
857 pg_fatal("This utility can only upgrade to PostgreSQL version %s.",
858 PG_MAJORVERSION);
859
860 /*
861 * We can't allow downgrading because we use the target pg_dump, and
862 * pg_dump cannot operate on newer database versions, only current and
863 * older versions.
864 */
866 pg_fatal("This utility cannot be used to downgrade to older major PostgreSQL versions.");
867
868 /* Ensure binaries match the designated data directories */
871 pg_fatal("Old cluster data and binary directories are from different major versions.");
874 pg_fatal("New cluster data and binary directories are from different major versions.");
875
876 /*
877 * Since from version 18, newly created database clusters always have
878 * 'signed' default char-signedness, it makes less sense to use
879 * --set-char-signedness option for upgrading from version 18 or later.
880 * Users who want to change the default char signedness of the new
881 * cluster, they can use pg_resetwal manually before the upgrade.
882 */
885 pg_fatal("%s option cannot be used to upgrade from PostgreSQL %s and later.",
886 "--set-char-signedness", "18");
887
888 check_ok();
889}
Assert(PointerIsAligned(start, uint64))
uint32 bin_version
Definition: pg_upgrade.h:302
int char_signedness
Definition: pg_upgrade.h:338

References Assert(), ClusterInfo::bin_version, UserOpts::char_signedness, check_ok(), GET_MAJOR_VERSION, ClusterInfo::major_version, new_cluster, old_cluster, pg_fatal, prep_status(), and user_opts.

Referenced by main().

◆ check_control_data()

void check_control_data ( ControlData oldctrl,
ControlData newctrl 
)

Definition at line 698 of file controldata.c.

700{
701 if (oldctrl->align == 0 || oldctrl->align != newctrl->align)
702 pg_fatal("old and new pg_controldata alignments are invalid or do not match.\n"
703 "Likely one cluster is a 32-bit install, the other 64-bit");
704
705 if (oldctrl->blocksz == 0 || oldctrl->blocksz != newctrl->blocksz)
706 pg_fatal("old and new pg_controldata block sizes are invalid or do not match");
707
708 if (oldctrl->largesz == 0 || oldctrl->largesz != newctrl->largesz)
709 pg_fatal("old and new pg_controldata maximum relation segment sizes are invalid or do not match");
710
711 if (oldctrl->walsz == 0 || oldctrl->walsz != newctrl->walsz)
712 pg_fatal("old and new pg_controldata WAL block sizes are invalid or do not match");
713
714 if (oldctrl->walseg == 0 || oldctrl->walseg != newctrl->walseg)
715 pg_fatal("old and new pg_controldata WAL segment sizes are invalid or do not match");
716
717 if (oldctrl->ident == 0 || oldctrl->ident != newctrl->ident)
718 pg_fatal("old and new pg_controldata maximum identifier lengths are invalid or do not match");
719
720 if (oldctrl->index == 0 || oldctrl->index != newctrl->index)
721 pg_fatal("old and new pg_controldata maximum indexed columns are invalid or do not match");
722
723 if (oldctrl->toast == 0 || oldctrl->toast != newctrl->toast)
724 pg_fatal("old and new pg_controldata maximum TOAST chunk sizes are invalid or do not match");
725
726 /* large_object added in 9.5, so it might not exist in the old cluster */
727 if (oldctrl->large_object != 0 &&
728 oldctrl->large_object != newctrl->large_object)
729 pg_fatal("old and new pg_controldata large-object chunk sizes are invalid or do not match");
730
731 if (oldctrl->date_is_int != newctrl->date_is_int)
732 pg_fatal("old and new pg_controldata date/time storage types do not match");
733
734 /*
735 * float8_pass_by_value does not need to match, but is used in
736 * check_for_isn_and_int8_passing_mismatch().
737 */
738
739 /*
740 * We might eventually allow upgrades from checksum to no-checksum
741 * clusters.
742 */
743 if (oldctrl->data_checksum_version == 0 &&
744 newctrl->data_checksum_version != 0)
745 pg_fatal("old cluster does not use data checksums but the new one does");
746 else if (oldctrl->data_checksum_version != 0 &&
747 newctrl->data_checksum_version == 0)
748 pg_fatal("old cluster uses data checksums but the new one does not");
749 else if (oldctrl->data_checksum_version != newctrl->data_checksum_version)
750 pg_fatal("old and new cluster pg_controldata checksum versions do not match");
751}
uint32 data_checksum_version
Definition: pg_upgrade.h:252
uint32 toast
Definition: pg_upgrade.h:248
uint32 index
Definition: pg_upgrade.h:247
uint32 walseg
Definition: pg_upgrade.h:245
uint32 blocksz
Definition: pg_upgrade.h:242
uint32 walsz
Definition: pg_upgrade.h:244
uint32 ident
Definition: pg_upgrade.h:246
bool date_is_int
Definition: pg_upgrade.h:250
uint32 large_object
Definition: pg_upgrade.h:249
uint32 align
Definition: pg_upgrade.h:241
uint32 largesz
Definition: pg_upgrade.h:243

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,
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:1244
int pg_file_create_mode
Definition: file_perm.c:19
#define close(a)
Definition: win32.h:12
char * pgdata
Definition: pg_upgrade.h:292

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,
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 ( transferMode  transfer_mode)

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 {
448 if (transfer_mode == TRANSFER_MODE_LINK)
449 pg_fatal("could not create hard link between old and new data directories: %m\n"
450 "In link mode the old and new data directories must be on the same file system.");
451 else if (transfer_mode == TRANSFER_MODE_SWAP)
452 pg_fatal("could not create hard link between old and new data directories: %m\n"
453 "In swap mode the old and new data directories must be on the same file system.");
454 else
455 pg_fatal("unrecognized transfer mode");
456 }
457
458 unlink(new_link_file);
459}

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

Referenced by check_new_cluster().

◆ check_loadable_libraries()

void check_loadable_libraries ( void  )

Definition at line 165 of file function.c.

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

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

Referenced by check_new_cluster().

◆ check_new_cluster()

void check_new_cluster ( void  )

Definition at line 701 of file check.c.

702{
704
706
708
709 switch (user_opts.transfer_mode)
710 {
713 break;
715 break;
718 break;
721 break;
723
724 /*
725 * We do the hard link check for --swap, too, since it's an easy
726 * way to verify the clusters are in the same file system. This
727 * allows us to take some shortcuts in the file synchronization
728 * step. With some more effort, we could probably support the
729 * separate-file-system use case, but this mode is unlikely to
730 * offer much benefit if we have to copy the files across file
731 * system boundaries.
732 */
734
735 /*
736 * There are a few known issues with using --swap to upgrade from
737 * versions older than 10. For example, the sequence tuple format
738 * changed in v10, and the visibility map format changed in 9.6.
739 * While such problems are not insurmountable (and we may have to
740 * deal with similar problems in the future, anyway), it doesn't
741 * seem worth the effort to support swap mode for upgrades from
742 * long-unsupported versions.
743 */
745 pg_fatal("Swap mode can only upgrade clusters from PostgreSQL version %s and later.",
746 "10");
747
748 break;
749 }
750
752
754
756
758
760}
static void check_new_cluster_logical_replication_slots(void)
Definition: check.c:1949
static void check_new_cluster_subscription_configuration(void)
Definition: check.c:2022
static void check_new_cluster_is_empty(void)
Definition: check.c:907
static void check_for_new_tablespace_dir(void)
Definition: check.c:939
void check_file_clone(void)
Definition: file.c:360
void check_hard_link(transferMode transfer_mode)
Definition: file.c:437
void check_copy_file_range(void)
Definition: file.c:400
void check_loadable_libraries(void)
Definition: function.c:165
transferMode transfer_mode
Definition: pg_upgrade.h:333

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(), GET_MAJOR_VERSION, ClusterInfo::major_version, new_cluster, old_cluster, pg_fatal, UserOpts::transfer_mode, TRANSFER_MODE_CLONE, TRANSFER_MODE_COPY, TRANSFER_MODE_COPY_FILE_RANGE, TRANSFER_MODE_LINK, TRANSFER_MODE_SWAP, 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 */
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 376 of file server.c.

377{
380
381 /* Get valid libpq env vars from the PQconndefaults function */
382
384
385 if (!start)
386 pg_fatal("out of memory");
387
388 for (option = start; option->keyword != NULL; option++)
389 {
390 if (option->envvar && (strcmp(option->envvar, "PGHOST") == 0 ||
391 strcmp(option->envvar, "PGHOSTADDR") == 0))
392 {
393 const char *value = getenv(option->envvar);
394
395 if (value && strlen(value) > 0 &&
396 /* check for 'local' host values */
397 (strcmp(value, "localhost") != 0 && strcmp(value, "127.0.0.1") != 0 &&
398 strcmp(value, "::1") != 0 && !is_unixsock_path(value)))
399 pg_fatal("libpq environment variable %s has a non-local server value: %s",
400 option->envvar, value);
401 }
402 }
403
404 /* Free the memory that libpq allocated on our behalf */
406}
void PQconninfoFree(PQconninfoOption *connOptions)
Definition: fe-connect.c:7434
PQconninfoOption * PQconndefaults(void)
Definition: fe-connect.c:2190
return str start
static struct @165 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 */
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",
109 break;
110 }
111}
void pg_log(eLogType type, const char *fmt,...)
Definition: util.c:259
LogOpts log_opts
Definition: util.c:17
int pg_check_dir(const char *dir)
Definition: pgcheckdir.c:33
bool rmtree(const char *path, bool rmtopdir)
Definition: rmtree.c:50
char * rootdir
Definition: pg_upgrade.h:317
bool retain
Definition: pg_upgrade.h:315
FILE * internal
Definition: pg_upgrade.h:313

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,
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:252

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

Referenced by transfer_relfile().

◆ cluster_conn_opts()

PGresult char * cluster_conn_opts ( ClusterInfo cluster)

Definition at line 92 of file server.c.

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

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

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

Referenced by check_for_connection_status(), check_for_pg_role_prefix(), check_for_prepared_transactions(), check_is_install_user(), check_loadable_libraries(), check_new_cluster_logical_replication_slots(), check_new_cluster_subscription_configuration(), check_old_cluster_subscription_state(), create_logical_replication_slots(), create_new_objects(), get_db_infos(), get_subscription_count(), get_tablespace_paths(), get_template0_info(), old_9_6_invalidate_hash_indexes(), set_frozenxids(), set_locale_and_encoding(), and unicode_version_changed().

◆ 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,
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_malloc(size_t size)
Definition: fe_memutils.c:47
void pg_free(void *ptr)
Definition: fe_memutils.c:105
#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,
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 744 of file info.c.

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

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

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

◆ create_script_for_old_cluster_deletion()

void create_script_for_old_cluster_deletion ( char **  deletion_script_file_name)

Definition at line 968 of file check.c.

969{
970 FILE *script = NULL;
971 int tblnum;
972 char old_cluster_pgdata[MAXPGPATH],
973 new_cluster_pgdata[MAXPGPATH];
974 char *old_tblspc_suffix;
975
976 *deletion_script_file_name = psprintf("%sdelete_old_cluster.%s",
978
979 strlcpy(old_cluster_pgdata, old_cluster.pgdata, MAXPGPATH);
980 canonicalize_path(old_cluster_pgdata);
981
982 strlcpy(new_cluster_pgdata, new_cluster.pgdata, MAXPGPATH);
983 canonicalize_path(new_cluster_pgdata);
984
985 /* Some people put the new data directory inside the old one. */
986 if (path_is_prefix_of_path(old_cluster_pgdata, new_cluster_pgdata))
987 {
989 "\nWARNING: new data directory should not be inside the old data directory, i.e. %s", old_cluster_pgdata);
990
991 /* Unlink file in case it is left over from a previous run. */
992 unlink(*deletion_script_file_name);
993 pg_free(*deletion_script_file_name);
994 *deletion_script_file_name = NULL;
995 return;
996 }
997
998 /*
999 * Some users (oddly) create tablespaces inside the cluster data
1000 * directory. We can't create a proper old cluster delete script in that
1001 * case.
1002 */
1003 for (tblnum = 0; tblnum < os_info.num_old_tablespaces; tblnum++)
1004 {
1005 char old_tablespace_dir[MAXPGPATH];
1006
1007 strlcpy(old_tablespace_dir, os_info.old_tablespaces[tblnum], MAXPGPATH);
1008 canonicalize_path(old_tablespace_dir);
1009 if (path_is_prefix_of_path(old_cluster_pgdata, old_tablespace_dir))
1010 {
1011 /* reproduce warning from CREATE TABLESPACE that is in the log */
1013 "\nWARNING: user-defined tablespace locations should not be inside the data directory, i.e. %s", old_tablespace_dir);
1014
1015 /* Unlink file in case it is left over from a previous run. */
1016 unlink(*deletion_script_file_name);
1017 pg_free(*deletion_script_file_name);
1018 *deletion_script_file_name = NULL;
1019 return;
1020 }
1021 }
1022
1023 prep_status("Creating script to delete old cluster");
1024
1025 if ((script = fopen_priv(*deletion_script_file_name, "w")) == NULL)
1026 pg_fatal("could not open file \"%s\": %m",
1027 *deletion_script_file_name);
1028
1029#ifndef WIN32
1030 /* add shebang header */
1031 fprintf(script, "#!/bin/sh\n\n");
1032#endif
1033
1034 /* delete old cluster's default tablespace */
1035 fprintf(script, RMDIR_CMD " %c%s%c\n", PATH_QUOTE,
1037
1038 /* delete old cluster's alternate tablespaces */
1039 old_tblspc_suffix = pg_strdup(old_cluster.tablespace_suffix);
1040 fix_path_separator(old_tblspc_suffix);
1041 for (tblnum = 0; tblnum < os_info.num_old_tablespaces; tblnum++)
1042 fprintf(script, RMDIR_CMD " %c%s%s%c\n", PATH_QUOTE,
1044 old_tblspc_suffix, PATH_QUOTE);
1045 pfree(old_tblspc_suffix);
1046
1047 fclose(script);
1048
1049#ifndef WIN32
1050 if (chmod(*deletion_script_file_name, S_IRWXU) != 0)
1051 pg_fatal("could not add execute permission to file \"%s\": %m",
1052 *deletion_script_file_name);
1053#endif
1054
1055 check_ok();
1056}
static char * fix_path_separator(char *path)
Definition: check.c:549
void pfree(void *pointer)
Definition: mcxt.c:2150
#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:637
void canonicalize_path(char *path)
Definition: path.c:337
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition: strlcpy.c:45
char * psprintf(const char *fmt,...)
Definition: psprintf.c:43
const char * tablespace_suffix
Definition: pg_upgrade.h:303
int num_old_tablespaces
Definition: pg_upgrade.h:358
char ** old_tablespaces
Definition: pg_upgrade.h:357
#define S_IRWXU
Definition: win32_port.h:288

References canonicalize_path(), check_ok(), fix_path_separator(), fopen_priv, fprintf, MAXPGPATH, new_cluster, OSInfo::num_old_tablespaces, old_cluster, OSInfo::old_tablespaces, os_info, path_is_prefix_of_path(), PATH_QUOTE, 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 ( transferMode  transfer_mode)

Definition at line 755 of file controldata.c.

756{
757 char old_path[MAXPGPATH],
758 new_path[MAXPGPATH];
759
760 /* rename pg_control so old server cannot be accidentally started */
761 /* translator: %s is the file path of the control file */
762 prep_status("Adding \".old\" suffix to old \"%s\"", XLOG_CONTROL_FILE);
763
764 snprintf(old_path, sizeof(old_path), "%s/%s", old_cluster.pgdata, XLOG_CONTROL_FILE);
765 snprintf(new_path, sizeof(new_path), "%s/%s.old", old_cluster.pgdata, XLOG_CONTROL_FILE);
766 if (pg_mv_file(old_path, new_path) != 0)
767 pg_fatal("could not rename file \"%s\" to \"%s\": %m",
768 old_path, new_path);
769 check_ok();
770
771 if (transfer_mode == TRANSFER_MODE_LINK)
772 /* translator: %s/%s is the file path of the control file */
773 pg_log(PG_REPORT, "\n"
774 "If you want to start the old cluster, you will need to remove\n"
775 "the \".old\" suffix from \"%s/%s.old\".\n"
776 "Because \"link\" mode was used, the old cluster cannot be safely\n"
777 "started once the new cluster has been started.",
779 else if (transfer_mode == TRANSFER_MODE_SWAP)
780 pg_log(PG_REPORT, "\n"
781 "Because \"swap\" mode was used, the old cluster can no longer be\n"
782 "safely started.");
783 else
784 pg_fatal("unrecognized transfer mode");
785}
#define pg_mv_file
Definition: pg_upgrade.h:81
#define XLOG_CONTROL_FILE

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

Referenced by main().

◆ end_progress_output()

void void pg_noreturn void 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");
54 }
55 else if (log_opts.verbose)
57}
#define MESSAGE_WIDTH
Definition: pg_upgrade.h:25
bool isatty
Definition: pg_upgrade.h:321
bool verbose
Definition: pg_upgrade.h:314

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

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

◆ exec_prog()

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

◆ executeQueryOrDie()

◆ gen_db_file_maps()

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

Definition at line 45 of file info.c.

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

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

Referenced by transfer_all_new_dbs().

◆ generate_old_dump()

void generate_old_dump ( void  )

Definition at line 16 of file dump.c.

17{
18 int dbnum;
19
20 prep_status("Creating dump of global objects");
21
22 /* run new pg_dumpall binary for globals */
23 exec_prog(UTILITY_LOG_FILE, NULL, true, true,
24 "\"%s/pg_dumpall\" %s --globals-only --quote-all-identifiers "
25 "--binary-upgrade %s --no-sync -f \"%s/%s\"",
27 log_opts.verbose ? "--verbose" : "",
30 check_ok();
31
32 prep_status_progress("Creating dump of database schemas");
33
34 /* create per-db dump files */
35 for (dbnum = 0; dbnum < old_cluster.dbarr.ndbs; dbnum++)
36 {
37 char sql_file_name[MAXPGPATH],
38 log_file_name[MAXPGPATH];
39 DbInfo *old_db = &old_cluster.dbarr.dbs[dbnum];
41 escaped_connstr;
42
44 appendPQExpBufferStr(&connstr, "dbname=");
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 --no-data %s %s --quote-all-identifiers "
56 "--binary-upgrade --format=custom %s --no-sync --file=\"%s/%s\" %s",
59 "" : "--sequence-data",
60 log_opts.verbose ? "--verbose" : "",
61 user_opts.do_statistics ? "" : "--no-statistics",
63 sql_file_name, escaped_connstr.data);
64
65 termPQExpBuffer(&escaped_connstr);
66 }
67
68 /* reap all children */
69 while (reap_child(true) == true)
70 ;
71
73 check_ok();
74}
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 const char * connstr
Definition: pg_dumpall.c:84
PGresult char * cluster_conn_opts(ClusterInfo *cluster)
Definition: server.c:92
#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 void pg_noreturn void void end_progress_output(void)
Definition: util.c:43
#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:698
char * bindir
Definition: pg_upgrade.h:295
Oid db_oid
Definition: pg_upgrade.h:198
char * dumpdir
Definition: pg_upgrade.h:319
bool do_statistics
Definition: pg_upgrade.h:337

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, UserOpts::do_statistics, 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(), UserOpts::transfer_mode, TRANSFER_MODE_SWAP, user_opts, UTILITY_LOG_FILE, and LogOpts::verbose.

Referenced by check_and_dump_old_cluster().

◆ get_control_data()

void get_control_data ( ClusterInfo cluster)

Definition at line 38 of file controldata.c.

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

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

Referenced by check_cluster_compatibility().

◆ get_db_rel_and_slot_infos()

void get_db_rel_and_slot_infos ( ClusterInfo cluster)

Definition at line 280 of file info.c.

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

References cluster(), free_db_and_rel_infos(), get_db_infos(), GET_MAJOR_VERSION, get_old_cluster_logical_slot_infos_query(), get_rel_infos_query(), get_template0_info(), log_opts, old_cluster, pg_free(), pg_log(), PG_VERBOSE, print_db_infos(), process_old_cluster_logical_slot_infos(), process_rel_infos(), upgrade_task_add_step(), upgrade_task_create(), upgrade_task_free(), upgrade_task_run(), and LogOpts::verbose.

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

◆ get_loadable_libraries()

void get_loadable_libraries ( void  )

Definition at line 79 of file function.c.

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

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

Referenced by check_and_dump_old_cluster().

◆ get_major_server_version()

uint32 get_major_server_version ( ClusterInfo cluster)

Definition at line 159 of file server.c.

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

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

Referenced by check_data_dir().

◆ get_sock_dir()

void get_sock_dir ( ClusterInfo cluster)

Definition at line 499 of file option.c.

500{
501#if !defined(WIN32)
503 cluster->sockdir = user_opts.socketdir;
504 else
505 {
506 /*
507 * If we are doing a live check, we will use the old cluster's Unix
508 * domain socket directory so we can connect to the live server.
509 */
510 unsigned short orig_port = cluster->port;
511 char filename[MAXPGPATH],
512 line[MAXPGPATH];
513 FILE *fp;
514 int lineno;
515
516 snprintf(filename, sizeof(filename), "%s/postmaster.pid",
517 cluster->pgdata);
518 if ((fp = fopen(filename, "r")) == NULL)
519 pg_fatal("could not open file \"%s\": %m", filename);
520
521 for (lineno = 1;
523 lineno++)
524 {
525 if (fgets(line, sizeof(line), fp) == NULL)
526 pg_fatal("could not read line %d from file \"%s\": %m",
527 lineno, filename);
528
529 /* potentially overwrite user-supplied value */
530 if (lineno == LOCK_FILE_LINE_PORT)
531 sscanf(line, "%hu", &old_cluster.port);
532 if (lineno == LOCK_FILE_LINE_SOCKET_DIR)
533 {
534 /* strip trailing newline and carriage return */
535 cluster->sockdir = pg_strdup(line);
536 (void) pg_strip_crlf(cluster->sockdir);
537 }
538 }
539 fclose(fp);
540
541 /* warn of port number correction */
542 if (orig_port != DEF_PGUPORT && old_cluster.port != orig_port)
543 pg_log(PG_WARNING, "user-supplied old port number %hu corrected to %hu",
544 orig_port, cluster->port);
545 }
546#else /* WIN32 */
547 cluster->sockdir = NULL;
548#endif
549}
#define Max(x, y)
Definition: c.h:969
#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:335

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

Referenced by main().

◆ get_subscription_count()

void get_subscription_count ( ClusterInfo cluster)

Definition at line 760 of file info.c.

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

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

Referenced by check_and_dump_old_cluster().

◆ get_user_info()

int get_user_info ( char **  user_name_p)

Definition at line 323 of file util.c.

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

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

Referenced by parseCommandLine().

◆ init_tablespaces()

void init_tablespaces ( void  )

Definition at line 19 of file tablespace.c.

20{
22
25
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 783 of file check.c.

784{
785 /*
786 * We unconditionally start/stop the new server because pg_resetwal -o set
787 * wal_level to 'minimum'. If the user is upgrading standby servers using
788 * the rsync instructions, they will need pg_upgrade to write its final
789 * WAL record showing wal_level as 'replica'.
790 */
792
793 /* Reindex hash indexes for old < 10.0 */
796
798
799 stop_postmaster(false);
800}
void report_extension_updates(ClusterInfo *cluster)
Definition: version.c:179

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

Referenced by main().

◆ jsonb_9_4_check_applicable()

bool jsonb_9_4_check_applicable ( ClusterInfo cluster)

Definition at line 21 of file version.c.

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

References cluster(), GET_MAJOR_VERSION, and JSONB_FORMAT_CHANGE_CAT_VER.

◆ linkFile()

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

Definition at line 190 of file file.c.

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

References link(), and pg_fatal.

Referenced by transfer_relfile().

◆ old_9_6_invalidate_hash_indexes()

void old_9_6_invalidate_hash_indexes ( ClusterInfo cluster,
bool  check_mode 
)

Definition at line 37 of file version.c.

38{
39 int dbnum;
40 FILE *script = NULL;
41 bool found = false;
42 char *output_path = "reindex_hash.sql";
43
44 prep_status("Checking for hash indexes");
45
46 for (dbnum = 0; dbnum < cluster->dbarr.ndbs; dbnum++)
47 {
48 PGresult *res;
49 bool db_used = false;
50 int ntups;
51 int rowno;
52 int i_nspname,
53 i_relname;
54 DbInfo *active_db = &cluster->dbarr.dbs[dbnum];
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:13019
void appendPsqlMetaConnect(PQExpBuffer buf, const char *dbname)
Definition: string_utils.c:743

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(), and termPQExpBuffer().

Referenced by check_and_dump_old_cluster(), and issue_warnings_and_set_wal_level().

◆ output_check_banner()

void output_check_banner ( void  )

Definition at line 570 of file check.c.

571{
573 {
575 "Performing Consistency Checks on Old Live Server\n"
576 "------------------------------------------------");
577 }
578 else
579 {
581 "Performing Consistency Checks\n"
582 "-----------------------------");
583 }
584}

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

Referenced by main().

◆ output_completion_banner()

void output_completion_banner ( char *  deletion_script_file_name)

Definition at line 804 of file check.c.

805{
806 PQExpBufferData user_specification;
807
808 initPQExpBuffer(&user_specification);
810 {
811 appendPQExpBufferStr(&user_specification, "-U ");
812 appendShellString(&user_specification, os_info.user);
813 appendPQExpBufferChar(&user_specification, ' ');
814 }
815
817 "Some optimizer statistics may not have been transferred by pg_upgrade.\n"
818 "Once you start the new server, consider running:\n"
819 " %s/vacuumdb %s--all --analyze-in-stages --missing-stats-only", new_cluster.bindir, user_specification.data);
820
821 if (deletion_script_file_name)
823 "Running this script will delete the old cluster's data files:\n"
824 " %s",
825 deletion_script_file_name);
826 else
828 "Could not create a script to delete the old cluster's data files\n"
829 "because user-defined tablespaces or the new cluster's data directory\n"
830 "exist in the old cluster directory. The old cluster's contents must\n"
831 "be deleted manually.");
832
833 termPQExpBuffer(&user_specification);
834}
bool user_specified
Definition: pg_upgrade.h:356

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 */
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:77
void transfer_all_new_dbs(DbInfoArr *old_db_arr, DbInfoArr *new_db_arr, char *old_pgdata, char *new_pgdata, char *old_tablespace)
int jobs
Definition: pg_upgrade.h:334

References 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 {"no-statistics", no_argument, NULL, 5},
64 {"set-char-signedness", required_argument, NULL, 6},
65 {"swap", no_argument, NULL, 7},
66
67 {NULL, 0, NULL, 0}
68 };
69 int option; /* Command line option */
70 int optindex = 0; /* used by getopt_long */
71 int os_user_effective_id;
72 DataDirSyncMethod unused;
73
74 user_opts.do_sync = true;
78
79 os_info.progname = get_progname(argv[0]);
80
81 /* Process libpq env. variables; load values here for usage() output */
82 old_cluster.port = getenv("PGPORTOLD") ? atoi(getenv("PGPORTOLD")) : DEF_PGUPORT;
83 new_cluster.port = getenv("PGPORTNEW") ? atoi(getenv("PGPORTNEW")) : DEF_PGUPORT;
84
85 os_user_effective_id = get_user_info(&os_info.user);
86 /* we override just the database user name; we got the OS id above */
87 if (getenv("PGUSER"))
88 {
90 /* must save value, getenv()'s pointer is not stable */
91 os_info.user = pg_strdup(getenv("PGUSER"));
92 }
93
94 if (argc > 1)
95 {
96 if (strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-?") == 0)
97 {
98 usage();
99 exit(0);
100 }
101 if (strcmp(argv[1], "--version") == 0 || strcmp(argv[1], "-V") == 0)
102 {
103 puts("pg_upgrade (PostgreSQL) " PG_VERSION);
104 exit(0);
105 }
106 }
107
108 /* Allow help and version to be run as root, so do the test here. */
109 if (os_user_effective_id == 0)
110 pg_fatal("%s: cannot be run as root", os_info.progname);
111
112 while ((option = getopt_long(argc, argv, "b:B:cd:D:j:kNo:O:p:P:rs:U:v",
113 long_options, &optindex)) != -1)
114 {
115 switch (option)
116 {
117 case 'b':
119 break;
120
121 case 'B':
123 break;
124
125 case 'c':
126 user_opts.check = true;
127 break;
128
129 case 'd':
131 break;
132
133 case 'D':
135 break;
136
137 case 'j':
138 user_opts.jobs = atoi(optarg);
139 break;
140
141 case 'k':
143 break;
144
145 case 'N':
146 user_opts.do_sync = false;
147 break;
148
149 case 'o':
150 /* append option? */
151 if (!old_cluster.pgopts)
153 else
154 {
155 char *old_pgopts = old_cluster.pgopts;
156
157 old_cluster.pgopts = psprintf("%s %s", old_pgopts, optarg);
158 free(old_pgopts);
159 }
160 break;
161
162 case 'O':
163 /* append option? */
164 if (!new_cluster.pgopts)
166 else
167 {
168 char *new_pgopts = new_cluster.pgopts;
169
170 new_cluster.pgopts = psprintf("%s %s", new_pgopts, optarg);
171 free(new_pgopts);
172 }
173 break;
174
175 case 'p':
176 if ((old_cluster.port = atoi(optarg)) <= 0)
177 pg_fatal("invalid old port number");
178 break;
179
180 case 'P':
181 if ((new_cluster.port = atoi(optarg)) <= 0)
182 pg_fatal("invalid new port number");
183 break;
184
185 case 'r':
186 log_opts.retain = true;
187 break;
188
189 case 's':
191 break;
192
193 case 'U':
196 os_info.user_specified = true;
197 break;
198
199 case 'v':
200 log_opts.verbose = true;
201 break;
202
203 case 1:
205 break;
206
207 case 2:
209 break;
210
211 case 3:
213 break;
214 case 4:
215 if (!parse_sync_method(optarg, &unused))
216 exit(1);
218 break;
219
220 case 5:
221 user_opts.do_statistics = false;
222 break;
223
224 case 6:
225 if (pg_strcasecmp(optarg, "signed") == 0)
227 else if (pg_strcasecmp(optarg, "unsigned") == 0)
229 else
230 pg_fatal("invalid argument for option %s", "--set-char-signedness");
231 break;
232
233 case 7:
235 break;
236
237 default:
238 fprintf(stderr, _("Try \"%s --help\" for more information.\n"),
240 exit(1);
241 }
242 }
243
244 if (optind < argc)
245 pg_fatal("too many command-line arguments (first is \"%s\")", argv[optind]);
246
249
250 if (log_opts.verbose)
251 pg_log(PG_REPORT, "Running in verbose mode");
252
253 log_opts.isatty = isatty(fileno(stdout));
254
255 /* Turn off read-only mode; add prefix to PGOPTIONS? */
256 if (getenv("PGOPTIONS"))
257 {
258 char *pgoptions = psprintf("%s %s", FIX_DEFAULT_READ_ONLY,
259 getenv("PGOPTIONS"));
260
261 setenv("PGOPTIONS", pgoptions, 1);
262 pfree(pgoptions);
263 }
264 else
265 setenv("PGOPTIONS", FIX_DEFAULT_READ_ONLY, 1);
266
267 /* Get values from env if not already set */
268 check_required_directory(&old_cluster.bindir, "PGBINOLD", false,
269 "-b", _("old cluster binaries reside"), false);
270 check_required_directory(&new_cluster.bindir, "PGBINNEW", false,
271 "-B", _("new cluster binaries reside"), true);
272 check_required_directory(&old_cluster.pgdata, "PGDATAOLD", false,
273 "-d", _("old cluster data resides"), false);
274 check_required_directory(&new_cluster.pgdata, "PGDATANEW", false,
275 "-D", _("new cluster data resides"), false);
276 check_required_directory(&user_opts.socketdir, "PGSOCKETDIR", true,
277 "-s", _("sockets will be created"), false);
278
279#ifdef WIN32
280
281 /*
282 * On Windows, initdb --sync-only will fail with a "Permission denied"
283 * error on file pg_upgrade_utility.log if pg_upgrade is run inside the
284 * new cluster directory, so we do a check here.
285 */
286 {
287 char cwd[MAXPGPATH],
288 new_cluster_pgdata[MAXPGPATH];
289
290 strlcpy(new_cluster_pgdata, new_cluster.pgdata, MAXPGPATH);
291 canonicalize_path(new_cluster_pgdata);
292
293 if (!getcwd(cwd, MAXPGPATH))
294 pg_fatal("could not determine current directory");
296 if (path_is_prefix_of_path(new_cluster_pgdata, cwd))
297 pg_fatal("cannot run pg_upgrade from inside the new cluster data directory on Windows");
298 }
299#endif
300}
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:25
#define required_argument
Definition: getopt_long.h:26
#define free(a)
Definition: header.h:65
bool parse_sync_method(const char *optarg, DataDirSyncMethod *sync_method)
Definition: option_utils.c:90
PGDLLIMPORT int optind
Definition: getopt.c:51
PGDLLIMPORT char * optarg
Definition: getopt.c:53
int get_user_info(char **user_name_p)
Definition: util.c:323
int pg_strcasecmp(const char *s1, const char *s2)
Definition: pgstrcasecmp.c:36
const char * get_progname(const char *argv0)
Definition: path.c:652
#define FIX_DEFAULT_READ_ONLY
Definition: option.c:27
static void usage(void)
Definition: option.c:304
static void check_required_directory(char **dirpath, const char *envVarName, bool useCwd, const char *cmdLineOption, const char *description, bool missingOk)
Definition: option.c:385
char * pgopts
Definition: pg_upgrade.h:296
const char * progname
Definition: pg_upgrade.h:354
char * sync_method
Definition: pg_upgrade.h:336
bool do_sync
Definition: pg_upgrade.h:332

References _, ClusterInfo::bindir, canonicalize_path(), UserOpts::char_signedness, UserOpts::check, check_required_directory(), DEF_PGUPORT, UserOpts::do_statistics, UserOpts::do_sync, 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_strcasecmp(), 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, TRANSFER_MODE_SWAP, usage(), OSInfo::user, user_opts, OSInfo::user_specified, and LogOpts::verbose.

Referenced by main().

◆ pg_fatal()

void void pg_noreturn 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 13019 of file ruleutils.c.

13020{
13021 /*
13022 * Can avoid quoting if ident starts with a lowercase letter or underscore
13023 * and contains only lowercase letters, digits, and underscores, *and* is
13024 * not any SQL keyword. Otherwise, supply quotes.
13025 */
13026 int nquotes = 0;
13027 bool safe;
13028 const char *ptr;
13029 char *result;
13030 char *optr;
13031
13032 /*
13033 * would like to use <ctype.h> macros here, but they might yield unwanted
13034 * locale-specific results...
13035 */
13036 safe = ((ident[0] >= 'a' && ident[0] <= 'z') || ident[0] == '_');
13037
13038 for (ptr = ident; *ptr; ptr++)
13039 {
13040 char ch = *ptr;
13041
13042 if ((ch >= 'a' && ch <= 'z') ||
13043 (ch >= '0' && ch <= '9') ||
13044 (ch == '_'))
13045 {
13046 /* okay */
13047 }
13048 else
13049 {
13050 safe = false;
13051 if (ch == '"')
13052 nquotes++;
13053 }
13054 }
13055
13057 safe = false;
13058
13059 if (safe)
13060 {
13061 /*
13062 * Check for keyword. We quote keywords except for unreserved ones.
13063 * (In some cases we could avoid quoting a col_name or type_func_name
13064 * keyword, but it seems much harder than it's worth to tell that.)
13065 *
13066 * Note: ScanKeywordLookup() does case-insensitive comparison, but
13067 * that's fine, since we already know we have all-lower-case.
13068 */
13069 int kwnum = ScanKeywordLookup(ident, &ScanKeywords);
13070
13071 if (kwnum >= 0 && ScanKeywordCategories[kwnum] != UNRESERVED_KEYWORD)
13072 safe = false;
13073 }
13074
13075 if (safe)
13076 return ident; /* no change needed */
13077
13078 result = (char *) palloc(strlen(ident) + nquotes + 2 + 1);
13079
13080 optr = result;
13081 *optr++ = '"';
13082 for (ptr = ident; *ptr; ptr++)
13083 {
13084 char ch = *ptr;
13085
13086 if (ch == '"')
13087 *optr++ = '"';
13088 *optr++ = ch;
13089 }
13090 *optr++ = '"';
13091 *optr = '\0';
13092
13093 return result;
13094}
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:1943
bool quote_all_identifiers
Definition: ruleutils.c:339

◆ 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 */
339
340 return true;
341}

References UserOpts::jobs, parallel_jobs, pg_fatal, 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 764 of file check.c.

765{
766 if (user_opts.check)
767 {
768 pg_log(PG_REPORT, "\n*Clusters are compatible*");
769 /* stops new cluster */
770 stop_postmaster(false);
771
773 exit(0);
774 }
775
776 pg_log(PG_REPORT, "\n"
777 "If pg_upgrade fails after this point, you must re-initdb the\n"
778 "new cluster before continuing.");
779}
void cleanup_output_dirs(void)
Definition: util.c:63

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

Referenced by main().

◆ report_extension_updates()

void report_extension_updates ( ClusterInfo cluster)

Definition at line 179 of file version.c.

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

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

Referenced by issue_warnings_and_set_wal_level().

◆ report_status()

◆ 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,
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:174
#define SizeOfPageHeaderData
Definition: bufpage.h:217
uint8_t uint8
Definition: c.h:500
uint16_t uint16
Definition: c.h:501
uint16 pg_checksum_page(char *page, BlockNumber blkno)
#define BITS_PER_BYTE
char data[BLCKSZ]
Definition: c.h:1108
#define BITS_PER_HEAPBLOCK
#define VISIBILITYMAP_ALL_VISIBLE
#define fstat
Definition: win32_port.h:273

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 {
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 idle_replication_slot_timeout=0 to prevent slot invalidation due to
257 * idle_timeout by checkpointer process during upgrade.
258 */
259 if (GET_MAJOR_VERSION(cluster->major_version) >= 1800)
260 appendPQExpBufferStr(&pgoptions, " -c idle_replication_slot_timeout=0");
261
262 /*
263 * Use -b to disable autovacuum and logical replication launcher
264 * (effective in PG17 or later for the latter).
265 */
266 snprintf(cmd, sizeof(cmd),
267 "\"%s/pg_ctl\" -w -l \"%s/%s\" -D \"%s\" -o \"-p %d -b%s %s%s\" start",
268 cluster->bindir,
270 SERVER_LOG_FILE, cluster->pgconfig, cluster->port,
271 pgoptions.data,
272 cluster->pgopts ? cluster->pgopts : "", socket_string);
273
274 termPQExpBuffer(&pgoptions);
275
276 /*
277 * Don't throw an error right away, let connecting throw the error because
278 * it might supply a reason for the failure.
279 */
280 pg_ctl_return = exec_prog(SERVER_START_LOG_FILE,
281 /* pass both file names if they differ */
282 (strcmp(SERVER_LOG_FILE,
283 SERVER_START_LOG_FILE) != 0) ?
284 SERVER_LOG_FILE : NULL,
285 report_and_exit_on_error, false,
286 "%s", cmd);
287
288 /* Did it fail and we are just testing if the server could be started? */
289 if (!pg_ctl_return && !report_and_exit_on_error)
290 return false;
291
292 /*
293 * We set this here to make sure atexit() shuts down the server, but only
294 * if we started the server successfully. We do it before checking for
295 * connectivity in case the server started but there is a connectivity
296 * failure. If pg_ctl did not return success, we will exit below.
297 *
298 * Pre-9.1 servers do not have PQping(), so we could be leaving the server
299 * running if authentication was misconfigured, so someday we might went
300 * to be more aggressive about doing server shutdowns even if pg_ctl
301 * fails, but now (2013-08-14) it seems prudent to be cautious. We don't
302 * want to shutdown a server that might have been accidentally started
303 * during the upgrade.
304 */
305 if (pg_ctl_return)
307
308 /*
309 * pg_ctl -w might have failed because the server couldn't be started, or
310 * there might have been a connection problem in _checking_ if the server
311 * has started. Therefore, even if pg_ctl failed, we continue and test
312 * for connectivity in case we get a connection reason for the failure.
313 */
314 if ((conn = get_db_conn(cluster, "template1")) == NULL ||
316 {
318 if (conn)
319 PQfinish(conn);
320 if (cluster == &old_cluster)
321 pg_fatal("could not connect to source postmaster started with the command:\n"
322 "%s",
323 cmd);
324 else
325 pg_fatal("could not connect to target postmaster started with the command:\n"
326 "%s",
327 cmd);
328 }
329 PQfinish(conn);
330
331 /*
332 * If pg_ctl failed, and the connection didn't fail, and
333 * report_and_exit_on_error is enabled, fail now. This could happen if
334 * the server was already running.
335 */
336 if (!pg_ctl_return)
337 {
338 if (cluster == &old_cluster)
339 pg_fatal("pg_ctl failed to start the source server, or connection failed");
340 else
341 pg_fatal("pg_ctl failed to start the target server, or connection failed");
342 }
343
344 return true;
345}
#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:320
ClusterInfo * running_cluster
Definition: pg_upgrade.h:361

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

350{
352
357 else
358 return; /* no cluster running */
359
360 exec_prog(SERVER_STOP_LOG_FILE, NULL, !in_atexit, !in_atexit,
361 "\"%s/pg_ctl\" -w -D \"%s\" -o \"%s\" %s stop",
362 cluster->bindir, cluster->pgconfig,
363 cluster->pgopts ? cluster->pgopts : "",
364 in_atexit ? "-m fast" : "-m smart");
365
367}
#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 171 of file relfilenumber.c.

173{
174 int old_dbnum,
175 new_dbnum;
176
177 /* Scan the old cluster databases and transfer their files */
178 for (old_dbnum = new_dbnum = 0;
179 old_dbnum < old_db_arr->ndbs;
180 old_dbnum++, new_dbnum++)
181 {
182 DbInfo *old_db = &old_db_arr->dbs[old_dbnum],
183 *new_db = NULL;
184 FileNameMap *mappings;
185 int n_maps;
186
187 /*
188 * Advance past any databases that exist in the new cluster but not in
189 * the old, e.g. "postgres". (The user might have removed the
190 * 'postgres' database from the old cluster.)
191 */
192 for (; new_dbnum < new_db_arr->ndbs; new_dbnum++)
193 {
194 new_db = &new_db_arr->dbs[new_dbnum];
195 if (strcmp(old_db->db_name, new_db->db_name) == 0)
196 break;
197 }
198
199 if (new_dbnum >= new_db_arr->ndbs)
200 pg_fatal("old database \"%s\" not found in the new cluster",
201 old_db->db_name);
202
203 mappings = gen_db_file_maps(old_db, new_db, &n_maps, old_pgdata,
204 new_pgdata);
205 if (n_maps)
206 {
207 transfer_single_new_db(mappings, n_maps, old_tablespace);
208 }
209 /* We allocate something even for n_maps == 0 */
210 pg_free(mappings);
211 }
212
213 /*
214 * Make sure anything pending synchronization in swap mode is fully
215 * persisted to disk. This is a no-op for other transfer modes.
216 */
219}
FileNameMap * gen_db_file_maps(DbInfo *old_db, DbInfo *new_db, int *nmaps, const char *old_pgdata, const char *new_pgdata)
Definition: info.c:45
static void sync_queue_destroy(void)
Definition: relfilenumber.c:87
static void transfer_single_new_db(FileNameMap *maps, int size, char *old_tablespace)
static void sync_queue_sync_all(void)
Definition: relfilenumber.c:60

References DbInfo::db_name, DbInfoArr::dbs, gen_db_file_maps(), DbInfoArr::ndbs, pg_fatal, pg_free(), sync_queue_destroy(), sync_queue_sync_all(), 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 108 of file relfilenumber.c.

110{
111 switch (user_opts.transfer_mode)
112 {
114 prep_status_progress("Cloning user relation files");
115 break;
117 prep_status_progress("Copying user relation files");
118 break;
120 prep_status_progress("Copying user relation files with copy_file_range");
121 break;
123 prep_status_progress("Linking user relation files");
124 break;
126 prep_status_progress("Swapping data directories");
127 break;
128 }
129
130 /*
131 * Transferring files by tablespace is tricky because a single database
132 * can use multiple tablespaces. For non-parallel mode, we just pass a
133 * NULL tablespace path, which matches all tablespaces. In parallel mode,
134 * we pass the default tablespace and all user-created tablespaces and let
135 * those operations happen in parallel.
136 */
137 if (user_opts.jobs <= 1)
138 parallel_transfer_all_new_dbs(old_db_arr, new_db_arr, old_pgdata,
139 new_pgdata, NULL);
140 else
141 {
142 int tblnum;
143
144 /* transfer default tablespace */
145 parallel_transfer_all_new_dbs(old_db_arr, new_db_arr, old_pgdata,
146 new_pgdata, old_pgdata);
147
148 for (tblnum = 0; tblnum < os_info.num_old_tablespaces; tblnum++)
150 new_db_arr,
151 old_pgdata,
152 new_pgdata,
153 os_info.old_tablespaces[tblnum]);
154 /* reap all children */
155 while (reap_child(true) == true)
156 ;
157 }
158
160 check_ok();
161}
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, TRANSFER_MODE_SWAP, and user_opts.

Referenced by main().

◆ upgrade_task_add_step()

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

Definition at line 151 of file task.c.

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

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

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

◆ upgrade_task_create()

UpgradeTask * upgrade_task_create ( void  )

Definition at line 117 of file task.c.

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

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

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

◆ upgrade_task_free()

◆ upgrade_task_run()

void upgrade_task_run ( const UpgradeTask task,
const ClusterInfo cluster 
)

Definition at line 420 of file task.c.

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

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

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

◆ verify_directories()

bool void verify_directories ( void  )

Definition at line 263 of file exec.c.

264{
265#ifndef WIN32
266 if (access(".", R_OK | W_OK | X_OK) != 0)
267#else
268 if (win32_check_directory_write_permissions() != 0)
269#endif
270 pg_fatal("You must have read and write access in the current directory.");
271
272 check_bin_dir(&old_cluster, false);
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 374 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