PostgreSQL Source Code git master
Loading...
Searching...
No Matches
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 MULTIXACTOFFSET_FORMATCHANGE_CAT_VER   202512091
 
#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 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_info (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, char *new_tablespace)
 
void init_tablespaces (void)
 
PGconnconnectToServer (ClusterInfo *cluster, const char *db_name)
 
PGresultexecuteQueryOrDie (PGconn *conn, const char *fmt,...) pg_attribute_printf(2
 
PGresult charcluster_conn_opts (ClusterInfo *cluster)
 
bool start_postmaster (ClusterInfo *cluster, bool report_and_exit_on_error)
 
void stop_postmaster (bool in_atexit)
 
void check_pghost_envvar (void)
 
charquote_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 protocol_negotiation_supported (const ClusterInfo *cluster)
 
void report_extension_updates (ClusterInfo *cluster)
 
MultiXactOffset rewrite_multixacts (MultiXactId from_multi, MultiXactId to_multi)
 
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, char *new_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

charoutput_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 115 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 390 of file pg_upgrade.h.

◆ fopen_priv

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

Definition at line 413 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.

◆ 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.

◆ MULTIXACTOFFSET_FORMATCHANGE_CAT_VER

#define MULTIXACTOFFSET_FORMATCHANGE_CAT_VER   202512091

Definition at line 109 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.

Typedef Documentation

◆ DataTypesUsageVersionCheck

typedef bool(* DataTypesUsageVersionCheck) (ClusterInfo *cluster)

Definition at line 351 of file pg_upgrade.h.

◆ UpgradeTask

Definition at line 497 of file pg_upgrade.h.

◆ UpgradeTaskProcessCB

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

Definition at line 494 of file pg_upgrade.h.

Enumeration Type Documentation

◆ eLogType

Enumerator
PG_VERBOSE 
PG_STATUS 
PG_REPORT_NONL 
PG_REPORT 
PG_WARNING 
PG_FATAL 

Definition at line 254 of file pg_upgrade.h.

255{
257 PG_STATUS, /* these messages do not get a newline added */
258 PG_REPORT_NONL, /* these too */
259 PG_REPORT,
261 PG_FATAL,
262} eLogType;
eLogType
Definition pg_upgrade.h:255
@ PG_FATAL
Definition pg_upgrade.h:261
@ PG_STATUS
Definition pg_upgrade.h:257
@ PG_WARNING
Definition pg_upgrade.h:260
@ PG_REPORT_NONL
Definition pg_upgrade.h:258
@ PG_VERBOSE
Definition pg_upgrade.h:256
@ PG_REPORT
Definition pg_upgrade.h:259

◆ transferMode

Enumerator
TRANSFER_MODE_CLONE 
TRANSFER_MODE_COPY 
TRANSFER_MODE_COPY_FILE_RANGE 
TRANSFER_MODE_LINK 
TRANSFER_MODE_SWAP 

Definition at line 242 of file pg_upgrade.h.

243{
transferMode
Definition pg_upgrade.h:243
@ TRANSFER_MODE_COPY
Definition pg_upgrade.h:245
@ TRANSFER_MODE_LINK
Definition pg_upgrade.h:247
@ TRANSFER_MODE_SWAP
Definition pg_upgrade.h:248
@ TRANSFER_MODE_CLONE
Definition pg_upgrade.h:244
@ TRANSFER_MODE_COPY_FILE_RANGE
Definition pg_upgrade.h:246

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],
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 */
483
484 cluster->pgdata = pg_strdup(cmd_output);
485
486 check_ok();
487}
char * pg_strdup(const char *in)
Definition fe_memutils.c:91
FILE * output
static void check_ok(void)
Definition initdb.c:2138
#define pg_fatal(...)
#define MAXPGPATH
static char * filename
Definition pg_dumpall.c:120
ClusterInfo old_cluster
Definition pg_upgrade.c:73
#define MAX_STRING
Definition pg_upgrade.h:22
void prep_status(const char *fmt,...) pg_attribute_printf(1
#define snprintf
Definition port.h:261
static int fb(int x)
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(), fb(), 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 531 of file check.c.

532{
533 /* -- OLD -- */
534
537
538 /*
539 * First check that all databases allow connections since we'll otherwise
540 * fail in later stages.
541 */
543
544 /*
545 * Check for encodings that are no longer supported.
546 */
548
549 /*
550 * Validate database, user, role and tablespace names from the old
551 * cluster. No need to check in 19 or newer as newline and carriage return
552 * are not allowed at the creation time of the object.
553 */
556
557 /*
558 * Extract a list of databases, tables, and logical replication slots from
559 * the old cluster.
560 */
562
564
566
567
568 /*
569 * Check for various failure cases
570 */
574
576 {
577 /*
578 * Logical replication slots can be migrated since PG17. See comments
579 * in get_db_rel_and_slot_infos().
580 */
582
583 /*
584 * Subscriptions and their dependencies can be migrated since PG17.
585 * Before that the logical slots are not upgraded, so we will not be
586 * able to upgrade the logical replication clusters completely.
587 */
590 }
591
593
594 /*
595 * Unicode updates can affect some objects that use expressions with
596 * functions dependent on Unicode.
597 */
599
600 /*
601 * PG 14 changed the function signature of encoding conversion functions.
602 * Conversions from older versions cannot be upgraded automatically
603 * because the user-defined functions used by the encoding conversions
604 * need to be changed to match the new signature.
605 */
608
609 /*
610 * Pre-PG 14 allowed user defined postfix operators, which are not
611 * supported anymore. Verify there are none, iff applicable.
612 */
615
616 /*
617 * PG 14 changed polymorphic functions from anyarray to
618 * anycompatiblearray.
619 */
622
623 /*
624 * Pre-PG 12 allowed tables to be declared WITH OIDS, which is not
625 * supported anymore. Verify there are none, iff applicable.
626 */
629
630 /*
631 * Pre-PG 18 allowed child tables to omit not-null constraints that their
632 * parents columns have, but schema restore fails for them. Verify there
633 * are none, iff applicable.
634 */
637
638 /*
639 * The btree_gist extension contains gist_inet_ops and gist_cidr_ops
640 * opclasses that do not reliably give correct answers. We want to
641 * deprecate and eventually remove those, and as a first step v19 marks
642 * them not-opcdefault and instead marks the replacement in-core opclass
643 * "inet_ops" as opcdefault. That creates a problem for pg_upgrade: in
644 * versions where those opclasses were marked opcdefault, pg_dump will
645 * dump indexes using them with no explicit opclass specification, so that
646 * restore would create them using the inet_ops opclass. That would be
647 * incompatible with what's actually in the on-disk files. So refuse to
648 * upgrade if there are any such indexes.
649 */
652
653 /*
654 * While not a check option, we do this now because this is the only time
655 * the old server is running.
656 */
657 if (!user_opts.check)
659
661 stop_postmaster(false);
662}
static void check_for_tables_with_oids(ClusterInfo *cluster)
Definition check.c:1581
static void check_for_data_types_usage(ClusterInfo *cluster)
Definition check.c:406
static void check_for_gist_inet_ops(ClusterInfo *cluster)
Definition check.c:1737
static void check_old_cluster_subscription_state(void)
Definition check.c:2325
static void check_for_unicode_update(ClusterInfo *cluster)
Definition check.c:1918
static void check_is_install_user(ClusterInfo *cluster)
Definition check.c:1016
static void check_for_not_null_inheritance(ClusterInfo *cluster)
Definition check.c:1658
static void check_for_connection_status(ClusterInfo *cluster)
Definition check.c:1074
static void check_for_isn_and_int8_passing_mismatch(ClusterInfo *cluster)
Definition check.c:1283
static void check_for_unsupported_encodings(ClusterInfo *cluster)
Definition check.c:1159
static void check_old_cluster_for_valid_slots(void)
Definition check.c:2203
static void check_for_user_defined_postfix_ops(ClusterInfo *cluster)
Definition check.c:1368
static void check_for_prepared_transactions(ClusterInfo *cluster)
Definition check.c:1220
static void check_for_user_defined_encoding_conversions(ClusterInfo *cluster)
Definition check.c:1812
static void check_old_cluster_global_names(ClusterInfo *cluster)
Definition check.c:2432
static void check_for_incompatible_polymorphics(ClusterInfo *cluster)
Definition check.c:1456
void generate_old_dump(void)
Definition dump.c:16
void get_loadable_libraries(void)
Definition function.c:77
void get_subscription_info(ClusterInfo *cluster)
Definition info.c:841
void get_db_rel_and_slot_infos(ClusterInfo *cluster)
Definition info.c:279
static pid_t start_postmaster(void)
Definition pg_ctl.c:443
static void stop_postmaster(void)
Definition pg_regress.c:444
void init_tablespaces(void)
Definition tablespace.c:19
#define GET_MAJOR_VERSION(v)
Definition pg_upgrade.h:27
UserOpts user_opts
Definition option.c:30
uint32 major_version
Definition pg_upgrade.h:283
bool live_check
Definition pg_upgrade.h:318
bool check
Definition pg_upgrade.h:317

References UserOpts::check, check_for_connection_status(), check_for_data_types_usage(), check_for_gist_inet_ops(), check_for_incompatible_polymorphics(), check_for_isn_and_int8_passing_mismatch(), check_for_not_null_inheritance(), check_for_prepared_transactions(), check_for_tables_with_oids(), check_for_unicode_update(), check_for_unsupported_encodings(), 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_global_names(), check_old_cluster_subscription_state(), generate_old_dump(), get_db_rel_and_slot_infos(), get_loadable_libraries(), GET_MAJOR_VERSION, get_subscription_info(), init_tablespaces(), UserOpts::live_check, ClusterInfo::major_version, old_cluster, start_postmaster(), stop_postmaster(), and user_opts.

Referenced by main().

◆ check_cluster_compatibility()

void check_cluster_compatibility ( void  )

Definition at line 843 of file check.c.

844{
845 /* get/check pg_control data of servers */
849
851 pg_fatal("When checking a live server, "
852 "the old and new port numbers must be different.");
853}
void get_control_data(ClusterInfo *cluster)
Definition controldata.c:39
void check_control_data(ControlData *oldctrl, ControlData *newctrl)
ClusterInfo new_cluster
Definition pg_upgrade.c:74
unsigned short port
Definition pg_upgrade.h:282
ControlData controldata
Definition pg_upgrade.h:272

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

789{
790 prep_status("Checking cluster versions");
791
792 /* cluster versions should already have been obtained */
795
796 /*
797 * We allow upgrades from/to the same major version for alpha/beta
798 * upgrades
799 */
800
802 pg_fatal("This utility can only upgrade from PostgreSQL version %s and later.",
803 "10");
804
805 /* Only current PG version is supported as a target */
807 pg_fatal("This utility can only upgrade to PostgreSQL version %s.",
809
810 /*
811 * We can't allow downgrading because we use the target pg_dump, and
812 * pg_dump cannot operate on newer database versions, only current and
813 * older versions.
814 */
816 pg_fatal("This utility cannot be used to downgrade to older major PostgreSQL versions.");
817
818 /* Ensure binaries match the designated data directories */
821 pg_fatal("Old cluster data and binary directories are from different major versions.");
824 pg_fatal("New cluster data and binary directories are from different major versions.");
825
826 /*
827 * Since from version 18, newly created database clusters always have
828 * 'signed' default char-signedness, it makes less sense to use
829 * --set-char-signedness option for upgrading from version 18 or later.
830 * Users who want to change the default char signedness of the new
831 * cluster, they can use pg_resetwal manually before the upgrade.
832 */
835 pg_fatal("The option %s cannot be used for upgrades from PostgreSQL %s and later.",
836 "--set-char-signedness", "18");
837
838 check_ok();
839}
#define Assert(condition)
Definition c.h:1002
uint32 bin_version
Definition pg_upgrade.h:285
int char_signedness
Definition pg_upgrade.h:325

References Assert, ClusterInfo::bin_version, UserOpts::char_signedness, check_ok(), fb(), 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 616 of file controldata.c.

618{
619 if (oldctrl->align == 0 || oldctrl->align != newctrl->align)
620 pg_fatal("old and new pg_controldata alignments are invalid or do not match.\n"
621 "Likely one cluster is a 32-bit install, the other 64-bit");
622
623 if (oldctrl->blocksz == 0 || oldctrl->blocksz != newctrl->blocksz)
624 pg_fatal("old and new pg_controldata block sizes are invalid or do not match");
625
626 if (oldctrl->largesz == 0 || oldctrl->largesz != newctrl->largesz)
627 pg_fatal("old and new pg_controldata maximum relation segment sizes are invalid or do not match");
628
629 if (oldctrl->walsz == 0 || oldctrl->walsz != newctrl->walsz)
630 pg_fatal("old and new pg_controldata WAL block sizes are invalid or do not match");
631
632 if (oldctrl->walseg == 0 || oldctrl->walseg != newctrl->walseg)
633 pg_fatal("old and new pg_controldata WAL segment sizes are invalid or do not match");
634
635 if (oldctrl->ident == 0 || oldctrl->ident != newctrl->ident)
636 pg_fatal("old and new pg_controldata maximum identifier lengths are invalid or do not match");
637
638 if (oldctrl->index == 0 || oldctrl->index != newctrl->index)
639 pg_fatal("old and new pg_controldata maximum indexed columns are invalid or do not match");
640
641 if (oldctrl->toast == 0 || oldctrl->toast != newctrl->toast)
642 pg_fatal("old and new pg_controldata maximum TOAST chunk sizes are invalid or do not match");
643
644 if (oldctrl->large_object == 0 ||
645 oldctrl->large_object != newctrl->large_object)
646 pg_fatal("old and new pg_controldata large-object chunk sizes are invalid or do not match");
647
648 if (oldctrl->date_is_int != newctrl->date_is_int)
649 pg_fatal("old and new pg_controldata date/time storage types do not match");
650
651 /*
652 * float8_pass_by_value does not need to match, but is used in
653 * check_for_isn_and_int8_passing_mismatch().
654 */
655
656 /*
657 * If data checksums are in any in-progress state then disallow the
658 * upgrade. The user should either let the process finish, or turn off
659 * data checksums, before retrying.
660 */
661 if (oldctrl->data_checksum_version > PG_DATA_CHECKSUM_VERSION)
662 pg_fatal("data checksums are being enabled in the old cluster");
663
664 /*
665 * We might eventually allow upgrades from checksum to no-checksum
666 * clusters.
667 */
668 if (oldctrl->data_checksum_version == PG_DATA_CHECKSUM_OFF &&
669 newctrl->data_checksum_version != PG_DATA_CHECKSUM_OFF)
670 pg_fatal("old cluster does not use data checksums but the new one does");
671 else if (oldctrl->data_checksum_version != PG_DATA_CHECKSUM_OFF &&
672 newctrl->data_checksum_version == PG_DATA_CHECKSUM_OFF)
673 pg_fatal("old cluster uses data checksums but the new one does not");
674 else if (oldctrl->data_checksum_version != newctrl->data_checksum_version)
675 pg_fatal("old and new cluster pg_controldata checksum versions do not match");
676}
@ PG_DATA_CHECKSUM_VERSION
Definition checksum.h:29
@ PG_DATA_CHECKSUM_OFF
Definition checksum.h:28

References fb(), PG_DATA_CHECKSUM_OFF, PG_DATA_CHECKSUM_VERSION, and pg_fatal.

Referenced by check_cluster_compatibility().

◆ check_copy_file_range()

void check_copy_file_range ( void  )

Definition at line 236 of file file.c.

237{
240
241 snprintf(existing_file, sizeof(existing_file), "%s/PG_VERSION", old_cluster.pgdata);
242 snprintf(new_link_file, sizeof(new_link_file), "%s/PG_VERSION.copy_file_range_test", new_cluster.pgdata);
243 unlink(new_link_file); /* might fail */
244
245#if defined(HAVE_COPY_FILE_RANGE)
246 {
247 int src_fd;
248 int dest_fd;
249
250 if ((src_fd = open(existing_file, O_RDONLY | PG_BINARY, 0)) < 0)
251 pg_fatal("could not open file \"%s\": %m",
253
256 pg_fatal("could not create file \"%s\": %m",
258
260 pg_fatal("could not copy file range between old and new data directories: %m");
261
262 close(src_fd);
263 close(dest_fd);
264 }
265#else
266 pg_fatal("copy_file_range not supported on this platform");
267#endif
268
270}
#define PG_BINARY
Definition c.h:1431
int pg_file_create_mode
Definition file_perm.c:19
#define close(a)
Definition win32.h:12
char * pgdata
Definition pg_upgrade.h:275

References close, fb(), 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 196 of file file.c.

197{
200
201 snprintf(existing_file, sizeof(existing_file), "%s/PG_VERSION", old_cluster.pgdata);
202 snprintf(new_link_file, sizeof(new_link_file), "%s/PG_VERSION.clonetest", new_cluster.pgdata);
203 unlink(new_link_file); /* might fail */
204
205#if defined(HAVE_COPYFILE) && defined(COPYFILE_CLONE_FORCE)
207 pg_fatal("could not clone file between old and new data directories: %m");
208#elif defined(__linux__) && defined(FICLONE)
209 {
210 int src_fd;
211 int dest_fd;
212
213 if ((src_fd = open(existing_file, O_RDONLY | PG_BINARY, 0)) < 0)
214 pg_fatal("could not open file \"%s\": %m",
216
219 pg_fatal("could not create file \"%s\": %m",
221
222 if (ioctl(dest_fd, FICLONE, src_fd) < 0)
223 pg_fatal("could not clone file between old and new data directories: %m");
224
225 close(src_fd);
226 close(dest_fd);
227 }
228#else
229 pg_fatal("file cloning not supported on this platform");
230#endif
231
233}

References close, fb(), 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 273 of file file.c.

274{
277
278 snprintf(existing_file, sizeof(existing_file), "%s/PG_VERSION", old_cluster.pgdata);
279 snprintf(new_link_file, sizeof(new_link_file), "%s/PG_VERSION.linktest", new_cluster.pgdata);
280 unlink(new_link_file); /* might fail */
281
283 {
284 if (transfer_mode == TRANSFER_MODE_LINK)
285 pg_fatal("could not create hard link between old and new data directories: %m\n"
286 "In link mode the old and new data directories must be on the same file system.");
287 else if (transfer_mode == TRANSFER_MODE_SWAP)
288 pg_fatal("could not create hard link between old and new data directories: %m\n"
289 "In swap mode the old and new data directories must be on the same file system.");
290 else
291 pg_fatal("unrecognized transfer mode");
292 }
293
295}

References fb(), 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 171 of file function.c.

172{
173 PGconn *conn = connectToServer(&new_cluster, "template1");
174 int libnum;
175 int was_load_failure = false;
176 FILE *script = NULL;
178
179 prep_status("Checking for presence of required libraries");
180
181 snprintf(output_path, sizeof(output_path), "%s/%s",
182 log_opts.basedir, "loadable_libraries.txt");
183
184 /*
185 * Now we want to sort the library names into order. This avoids multiple
186 * probes of the same library, and ensures that libraries are probed in a
187 * consistent order, which is important for reproducible behavior if one
188 * library depends on another.
189 */
192
194 {
196 int llen = strlen(lib);
197 char cmd[7 + 2 * MAXPGPATH + 1];
198 PGresult *res;
199
200 /* Did the library name change? Probe it. */
201 if (libnum == 0 || strcmp(lib, os_info.libraries[libnum - 1].name) != 0)
202 {
203 strcpy(cmd, "LOAD '");
204 PQescapeStringConn(conn, cmd + strlen(cmd), lib, llen, NULL);
205 strcat(cmd, "'");
206
207 res = PQexec(conn, cmd);
208
210 {
211 was_load_failure = true;
212
213 if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL)
214 pg_fatal("could not open file \"%s\": %m", output_path);
215 fprintf(script, _("could not load library \"%s\": %s"),
216 lib,
218 }
219 else
220 was_load_failure = false;
221
222 PQclear(res);
223 }
224
226 fprintf(script, _("In database: %s\n"),
228 }
229
230 PQfinish(conn);
231
232 if (script)
233 {
234 fclose(script);
235 pg_log(PG_REPORT, "fatal");
236 pg_fatal("Your installation references loadable libraries that are missing from the\n"
237 "new installation. You can add these libraries to the new installation,\n"
238 "or remove the functions using them from the old installation. A list of\n"
239 "problem libraries is in the file:\n"
240 " %s", output_path);
241 }
242 else
243 check_ok();
244}
#define fprintf(file, fmt, msg)
Definition cubescan.l:21
#define _(x)
Definition elog.c:96
void PQfinish(PGconn *conn)
char * PQerrorMessage(const PGconn *conn)
size_t PQescapeStringConn(PGconn *conn, char *to, const char *from, size_t length, int *error)
Definition fe-exec.c:4213
PGresult * PQexec(PGconn *conn, const char *query)
Definition fe-exec.c:2279
static int library_name_compare(const void *p1, const void *p2)
Definition function.c:29
#define PQclear
#define PQresultStatus
@ PGRES_COMMAND_OK
Definition libpq-fe.h:131
OSInfo os_info
Definition pg_upgrade.c:75
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:413
#define qsort(a, b, c, d)
Definition port.h:496
PGconn * conn
Definition streamutil.c:52
DbInfoArr dbarr
Definition pg_upgrade.h:274
DbInfo * dbs
Definition pg_upgrade.h:203
char * db_name
Definition pg_upgrade.h:182
char * name
Definition pg_upgrade.h:332
char * basedir
Definition pg_upgrade.h:305
LibraryInfo * libraries
Definition pg_upgrade.h:344
int num_libraries
Definition pg_upgrade.h:345

References _, LogOpts::basedir, check_ok(), conn, connectToServer(), DbInfo::db_name, ClusterInfo::dbarr, LibraryInfo::dbnum, DbInfoArr::dbs, fb(), 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 666 of file check.c.

667{
669
671
673
674 switch (user_opts.transfer_mode)
675 {
678 break;
680 break;
683 break;
686 break;
688
689 /*
690 * We do the hard link check for --swap, too, since it's an easy
691 * way to verify the clusters are in the same file system. This
692 * allows us to take some shortcuts in the file synchronization
693 * step. With some more effort, we could probably support the
694 * separate-file-system use case, but this mode is unlikely to
695 * offer much benefit if we have to copy the files across file
696 * system boundaries.
697 */
699 break;
700 }
701
703
705
707
709
711}
static void check_new_cluster_replication_slots(void)
Definition check.c:2052
static void check_new_cluster_subscription_configuration(void)
Definition check.c:2160
static void check_new_cluster_is_empty(void)
Definition check.c:857
static void check_for_new_tablespace_dir(void)
Definition check.c:889
void check_file_clone(void)
Definition file.c:196
void check_hard_link(transferMode transfer_mode)
Definition file.c:273
void check_copy_file_range(void)
Definition file.c:236
void check_loadable_libraries(void)
Definition function.c:171
transferMode transfer_mode
Definition pg_upgrade.h:320

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_replication_slots(), check_new_cluster_subscription_configuration(), get_db_rel_and_slot_infos(), new_cluster, UserOpts::transfer_mode, TRANSFER_MODE_CLONE, TRANSFER_MODE_COPY, TRANSFER_MODE_COPY_FILE_RANGE, TRANSFER_MODE_LINK, 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 320 of file server.c.

321{
324
325 /* Get valid libpq env vars from the PQconndefaults function */
326
328
329 if (!start)
330 pg_fatal("out of memory");
331
332 for (option = start; option->keyword != NULL; option++)
333 {
334 if (option->envvar && (strcmp(option->envvar, "PGHOST") == 0 ||
335 strcmp(option->envvar, "PGHOSTADDR") == 0))
336 {
337 const char *value = getenv(option->envvar);
338
339 if (value && strlen(value) > 0 &&
340 /* check for 'local' host values */
341 (strcmp(value, "localhost") != 0 && strcmp(value, "127.0.0.1") != 0 &&
342 strcmp(value, "::1") != 0 && !is_unixsock_path(value)))
343 pg_fatal("libpq environment variable %s has a non-local server value: %s",
344 option->envvar, value);
345 }
346 }
347
348 /* Free the memory that libpq allocated on our behalf */
350}
void PQconninfoFree(PQconninfoOption *connOptions)
PQconninfoOption * PQconndefaults(void)
return str start
static struct @175 value
static bool is_unixsock_path(const char *path)
Definition pqcomm.h:66

References fb(), 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{
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:304
bool retain
Definition pg_upgrade.h:302
FILE * internal
Definition pg_upgrade.h:300

References Assert, LogOpts::basedir, fb(), 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 35 of file file.c.

37{
38#if defined(HAVE_COPYFILE) && defined(COPYFILE_CLONE_FORCE)
39 if (copyfile(src, dst, NULL, COPYFILE_CLONE_FORCE) < 0)
40 pg_fatal("error while cloning relation \"%s.%s\" (\"%s\" to \"%s\"): %m",
41 schemaName, relName, src, dst);
42#elif defined(__linux__) && defined(FICLONE)
43 int src_fd;
44 int dest_fd;
45
46 if ((src_fd = open(src, O_RDONLY | PG_BINARY, 0)) < 0)
47 pg_fatal("error while cloning relation \"%s.%s\": could not open file \"%s\": %m",
48 schemaName, relName, src);
49
52 pg_fatal("error while cloning relation \"%s.%s\": could not create file \"%s\": %m",
54
55 if (ioctl(dest_fd, FICLONE, src_fd) < 0)
56 {
57 int save_errno = errno;
58
59 unlink(dst);
60
61 pg_fatal("error while cloning relation \"%s.%s\" (\"%s\" to \"%s\"): %s",
63 }
64
67#endif
68}
#define strerror
Definition port.h:274

References close, fb(), 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 94 of file server.c.

95{
96 static PQExpBuffer buf;
97
98 if (buf == NULL)
100 else
102
103 if (cluster->sockdir)
104 {
105 appendPQExpBufferStr(buf, "--host ");
106 appendShellString(buf, cluster->sockdir);
108 }
109 appendPQExpBuffer(buf, "--port %d --username ", cluster->port);
111
112 return buf->data;
113}
static char buf[DEFAULT_XLOG_SEG_SIZE]
PQExpBuffer createPQExpBuffer(void)
Definition pqexpbuffer.c:72
void resetPQExpBuffer(PQExpBuffer str)
void appendPQExpBuffer(PQExpBuffer str, const char *fmt,...)
void appendPQExpBufferChar(PQExpBuffer str, char ch)
void appendPQExpBufferStr(PQExpBuffer str, const char *data)
void appendShellString(PQExpBuffer buf, const char *str)
char * user
Definition pg_upgrade.h:342

References appendPQExpBuffer(), appendPQExpBufferChar(), appendPQExpBufferStr(), appendShellString(), buf, createPQExpBuffer(), fb(), 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)
@ CONNECTION_OK
Definition libpq-fe.h:90
#define printf(...)
Definition port.h:267
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:124

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

Referenced by check_for_connection_status(), check_for_prepared_transactions(), check_for_unsupported_encodings(), check_is_install_user(), check_loadable_libraries(), check_new_cluster_replication_slots(), check_new_cluster_subscription_configuration(), check_old_cluster_global_names(), check_old_cluster_subscription_state(), create_conflict_detection_slot(), create_logical_replication_slots(), create_new_objects(), get_db_infos(), get_subscription_info(), get_tablespace_paths(), get_template0_info(), 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 78 of file file.c.

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

149{
150#ifdef HAVE_COPY_FILE_RANGE
151 int src_fd;
152 int dest_fd;
153 ssize_t nbytes;
154
155 if ((src_fd = open(src, O_RDONLY | PG_BINARY, 0)) < 0)
156 pg_fatal("error while copying relation \"%s.%s\": could not open file \"%s\": %m",
157 schemaName, relName, src);
158
161 pg_fatal("error while copying relation \"%s.%s\": could not create file \"%s\": %m",
163
164 do
165 {
167 if (nbytes < 0)
168 pg_fatal("error while copying relation \"%s.%s\": could not copy file range from \"%s\" to \"%s\": %m",
169 schemaName, relName, src, dst);
170 }
171 while (nbytes > 0);
172
173 close(src_fd);
174 close(dest_fd);
175#endif
176}

References close, fb(), 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 825 of file info.c.

826{
827 int slot_count = 0;
828
829 for (int dbnum = 0; dbnum < old_cluster.dbarr.ndbs; dbnum++)
831
832 return slot_count;
833}
LogicalSlotInfoArr slot_arr
Definition pg_upgrade.h:186

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

Referenced by check_new_cluster_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 918 of file check.c.

919{
920 FILE *script = NULL;
921 int tblnum;
924 char *old_tblspc_suffix;
925
926 *deletion_script_file_name = psprintf("%sdelete_old_cluster.%s",
928
931
934
935 /* Some people put the new data directory inside the old one. */
937 {
939 "\nWARNING: new data directory should not be inside the old data directory, i.e. %s", old_cluster_pgdata);
940
941 /* Unlink file in case it is left over from a previous run. */
945 return;
946 }
947
948 /*
949 * Some users (oddly) create tablespaces inside the cluster data
950 * directory. We can't create a proper old cluster delete script in that
951 * case.
952 */
954 {
956
960 {
961 /* reproduce warning from CREATE TABLESPACE that is in the log */
963 "\nWARNING: user-defined tablespace locations should not be inside the data directory, i.e. %s", new_tablespace_dir);
964
965 /* Unlink file in case it is left over from a previous run. */
969 return;
970 }
971 }
972
973 prep_status("Creating script to delete old cluster");
974
975 if ((script = fopen_priv(*deletion_script_file_name, "w")) == NULL)
976 pg_fatal("could not open file \"%s\": %m",
978
979#ifndef WIN32
980 /* add shebang header */
981 fprintf(script, "#!/bin/sh\n\n");
982#endif
983
984 /* delete old cluster's default tablespace */
985 fprintf(script, RMDIR_CMD " %c%s%c\n", PATH_QUOTE,
987
988 /* delete old cluster's alternate tablespaces */
992 fprintf(script, RMDIR_CMD " %c%s%s%c\n", PATH_QUOTE,
996
997 fclose(script);
998
999#ifndef WIN32
1001 pg_fatal("could not add execute permission to file \"%s\": %m",
1003#endif
1004
1005 check_ok();
1006}
static char * fix_path_separator(char *path)
Definition check.c:492
void pfree(void *pointer)
Definition mcxt.c:1619
#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:654
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
int num_tablespaces
Definition pg_upgrade.h:287
char ** tablespaces
Definition pg_upgrade.h:286
const char * tablespace_suffix
Definition pg_upgrade.h:288
#define S_IRWXU
Definition win32_port.h:305

References canonicalize_path(), check_ok(), fb(), fix_path_separator(), fopen_priv, fprintf, MAXPGPATH, new_cluster, ClusterInfo::num_tablespaces, old_cluster, 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(), ClusterInfo::tablespace_suffix, and ClusterInfo::tablespaces.

Referenced by main().

◆ disable_old_cluster()

void disable_old_cluster ( transferMode  transfer_mode)

Definition at line 680 of file controldata.c.

681{
682 char old_path[MAXPGPATH],
684
685 /* rename pg_control so old server cannot be accidentally started */
686 /* translator: %s is the file path of the control file */
687 prep_status("Adding \".old\" suffix to old \"%s\"", XLOG_CONTROL_FILE);
688
691 if (pg_mv_file(old_path, new_path) != 0)
692 pg_fatal("could not rename file \"%s\" to \"%s\": %m",
694 check_ok();
695
696 if (transfer_mode == TRANSFER_MODE_LINK)
697 /* translator: %s/%s is the file path of the control file */
698 pg_log(PG_REPORT, "\n"
699 "If you want to start the old cluster, you will need to remove\n"
700 "the \".old\" suffix from \"%s/%s.old\".\n"
701 "Because \"link\" mode was used, the old cluster cannot be safely\n"
702 "started once the new cluster has been started.",
704 else if (transfer_mode == TRANSFER_MODE_SWAP)
705 pg_log(PG_REPORT, "\n"
706 "Because \"swap\" mode was used, the old cluster can no longer be\n"
707 "safely started.");
708 else
709 pg_fatal("unrecognized transfer mode");
710}
#define pg_mv_file
Definition pg_upgrade.h:81
#define XLOG_CONTROL_FILE

References check_ok(), fb(), 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:308
bool verbose
Definition pg_upgrade.h:301

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

References create_rel_filename_map(), fb(), maps, pg_fatal, pg_log(), pg_malloc_array, PG_WARNING, 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%s --globals-only --quote-all-identifiers "
25 "--binary-upgrade %s --no-sync -f \"%s/%s\"",
27 protocol_negotiation_supported(&old_cluster) ? "" : " -d \"max_protocol_version=3.0\"",
28 log_opts.verbose ? "--verbose" : "",
29 log_opts.dumpdir,
31 check_ok();
32
33 prep_status_progress("Creating dump of database schemas");
34
35 /* create per-db dump files */
36 for (dbnum = 0; dbnum < old_cluster.dbarr.ndbs; dbnum++)
37 {
43
45 appendPQExpBufferStr(&connstr, "dbname=");
48 appendPQExpBufferStr(&connstr, " max_protocol_version=3.0");
49
53
54 pg_log(PG_STATUS, "%s", old_db->db_name);
57
59 "\"%s/pg_dump\" %s --no-data %s %s --quote-all-identifiers "
60 "--binary-upgrade --format=custom %s --no-sync --file=\"%s/%s\" %s",
63 "" : "--sequence-data",
64 log_opts.verbose ? "--verbose" : "",
65 user_opts.do_statistics ? "--statistics" : "--no-statistics",
66 log_opts.dumpdir,
68
70 }
71
72 /* reap all children */
73 while (reap_child(true) == true)
74 ;
75
77 check_ok();
78}
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:77
bool reap_child(bool wait_for_child)
Definition parallel.c:281
void parallel_exec_prog(const char *log_file, const char *opt_log_file, const char *fmt,...)
Definition parallel.c:63
static int verbose
const void * data
static const char * connstr
Definition pg_dumpall.c:82
PGresult char * cluster_conn_opts(ClusterInfo *cluster)
Definition server.c:94
#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
bool protocol_negotiation_supported(const ClusterInfo *cluster)
Definition version.c:20
#define DB_DUMP_FILE_MASK
Definition pg_upgrade.h:31
void initPQExpBuffer(PQExpBuffer str)
Definition pqexpbuffer.c:90
void termPQExpBuffer(PQExpBuffer str)
void appendConnStrVal(PQExpBuffer buf, const char *str)
char * bindir
Definition pg_upgrade.h:278

References appendConnStrVal(), appendPQExpBufferStr(), appendShellString(), ClusterInfo::bindir, check_ok(), cluster_conn_opts(), connstr, DB_DUMP_FILE_MASK, DB_DUMP_LOG_FILE_MASK, ClusterInfo::dbarr, DbInfoArr::dbs, UserOpts::do_statistics, LogOpts::dumpdir, end_progress_output(), exec_prog(), fb(), 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(), protocol_negotiation_supported(), 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 39 of file controldata.c.

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

References Assert, DEFAULT_CHAR_SIGNEDNESS_CAT_VER, fb(), lc_collate, lc_ctype, lc_messages, lc_monetary, lc_numeric, lc_time, UserOpts::live_check, MAX_STRING, MAXPGPATH, 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 279 of file info.c.

280{
282 char *rel_infos_query = NULL;
283
284 if (cluster->dbarr.dbs != NULL)
286
289
294 true, NULL);
295
296 /*
297 * Logical slots are only carried over to the new cluster when the old
298 * cluster is on PG17 or newer. This is because before that the logical
299 * slots are not saved at shutdown, so there is no guarantee that the
300 * latest confirmed_flush_lsn is saved to disk which can lead to data
301 * loss. It is still not guaranteed for manually created slots in PG17, so
302 * subsequent checks done in check_old_cluster_for_valid_slots() would
303 * raise a FATAL error if such slots are included.
304 */
305 if (cluster == &old_cluster &&
306 GET_MAJOR_VERSION(cluster->major_version) > 1600)
310 true, NULL);
311
314
316
317 if (cluster == &old_cluster)
318 pg_log(PG_VERBOSE, "\nsource databases:");
319 else
320 pg_log(PG_VERBOSE, "\ntarget databases:");
321
322 if (log_opts.verbose)
323 print_db_infos(&cluster->dbarr);
324}
static void process_rel_infos(DbInfo *dbinfo, PGresult *res, void *arg)
Definition info.c:578
static void get_template0_info(ClusterInfo *cluster)
Definition info.c:332
static void get_db_infos(ClusterInfo *cluster)
Definition info.c:397
static void free_db_and_rel_infos(DbInfoArr *db_arr)
Definition info.c:869
static char * get_rel_infos_query(void)
Definition info.c:480
static void process_old_cluster_logical_slot_infos(DbInfo *dbinfo, PGresult *res, void *arg)
Definition info.c:774
static const char * get_old_cluster_logical_slot_infos_query(ClusterInfo *cluster)
Definition info.c:678
static void print_db_infos(DbInfoArr *db_arr)
Definition info.c:903
UpgradeTask * upgrade_task_create(void)
Definition task.c:117
void upgrade_task_run(const UpgradeTask *task, const ClusterInfo *cluster)
Definition task.c:421
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 fb(), 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 77 of file function.c.

78{
79 int totaltups;
80 int dbnum;
81 int n_libinfos;
84 char *query;
85
87 state.totaltups = 0;
88
89 query = psprintf("SELECT DISTINCT probin "
90 "FROM pg_catalog.pg_proc "
91 "WHERE prolang = %u AND "
92 "probin IS NOT NULL AND "
93 "oid >= %u",
96
98 false, &state);
99
102
103 /*
104 * Allocate memory for required libraries and logical replication output
105 * plugins.
106 */
109 totaltups = 0;
110
111 for (dbnum = 0; dbnum < old_cluster.dbarr.ndbs; dbnum++)
112 {
113 PGresult *res = state.ress[dbnum];
114 int ntups;
115 int rowno;
116 LogicalSlotInfoArr *slot_arr = &old_cluster.dbarr.dbs[dbnum].slot_arr;
117
118 ntups = PQntuples(res);
119 for (rowno = 0; rowno < ntups; rowno++)
120 {
121 char *lib = PQgetvalue(res, rowno, 0);
122
123 /*
124 * Starting with version 19, for extensions with hardcoded
125 * '$libdir/' library names, we strip the prefix to allow the
126 * library search path to be used.
127 */
128 if (strncmp(lib, "$libdir/", 8) == 0)
129 lib += 8;
130
133
134 totaltups++;
135 }
136 PQclear(res);
137
138 /*
139 * Store the names of output plugins as well. There is a possibility
140 * that duplicated plugins are set, but the consumer function
141 * check_loadable_libraries() will avoid checking the same library, so
142 * we do not have to consider their uniqueness here.
143 */
144 for (int slotno = 0; slotno < slot_arr->nslots; slotno++)
145 {
146 if (slot_arr->slots[slotno].invalid)
147 continue;
148
151
152 totaltups++;
153 }
154 }
155
156 pg_free(state.ress);
157 pfree(query);
158
160}
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:825
#define PQgetvalue
#define PQntuples
LogicalSlotInfo * slots
Definition pg_upgrade.h:157
#define FirstNormalObjectId
Definition transam.h:197

References count_old_cluster_logical_slots(), ClusterInfo::dbarr, LibraryInfo::dbnum, DbInfoArr::dbs, fb(), FirstNormalObjectId, LogicalSlotInfo::invalid, OSInfo::libraries, LibraryInfo::name, DbInfoArr::ndbs, LogicalSlotInfoArr::nslots, OSInfo::num_libraries, old_cluster, os_info, pfree(), pg_free(), pg_malloc_array, 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_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 */
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:1125
#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:322

References DEF_PGUPORT, fb(), 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_info()

void get_subscription_info ( ClusterInfo cluster)

Definition at line 841 of file info.c.

842{
843 PGconn *conn;
844 PGresult *res;
845 int i_nsub;
847
848 conn = connectToServer(cluster, "template1");
849 if (GET_MAJOR_VERSION(cluster->major_version) >= 1900)
850 res = executeQueryOrDie(conn, "SELECT count(*) AS nsub,"
851 "COUNT(CASE WHEN subretaindeadtuples THEN 1 END) > 0 AS retain_dead_tuples "
852 "FROM pg_catalog.pg_subscription");
853 else
854 res = executeQueryOrDie(conn, "SELECT count(*) AS nsub,"
855 "'f' AS retain_dead_tuples "
856 "FROM pg_catalog.pg_subscription");
857
858 i_nsub = PQfnumber(res, "nsub");
859 i_retain_dead_tuples = PQfnumber(res, "retain_dead_tuples");
860
861 cluster->nsubs = atoi(PQgetvalue(res, 0, i_nsub));
862 cluster->sub_retain_dead_tuples = (strcmp(PQgetvalue(res, 0, i_retain_dead_tuples), "t") == 0);
863
864 PQclear(res);
865 PQfinish(conn);
866}
int PQfnumber(const PGresult *res, const char *field_name)
Definition fe-exec.c:3620
PGresult * executeQueryOrDie(PGconn *conn, const char *fmt,...) pg_attribute_printf(2

References conn, connectToServer(), executeQueryOrDie(), fb(), GET_MAJOR_VERSION, PQclear, PQfinish(), PQfnumber(), 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}
const char * get_user_name(char **errstr)
Definition username.c:31

References fb(), 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 {
29 for (int i = 0; i < old_cluster.num_tablespaces; i++)
30 {
31 /*
32 * In-place tablespaces are okay for same-version upgrades because
33 * their paths will differ between clusters.
34 */
36 pg_fatal("Cannot upgrade to/from the same system catalog version when\n"
37 "using tablespaces.");
38 }
39 }
40}
static void set_tablespace_directory_suffix(ClusterInfo *cluster)
Definition tablespace.c:142
static void get_tablespace_paths(void)
Definition tablespace.c:50
int i
Definition isn.c:77

References fb(), get_tablespace_paths(), i, new_cluster, ClusterInfo::num_tablespaces, old_cluster, pg_fatal, set_tablespace_directory_suffix(), ClusterInfo::tablespace_suffix, and ClusterInfo::tablespaces.

Referenced by check_and_dump_old_cluster().

◆ issue_warnings_and_set_wal_level()

void issue_warnings_and_set_wal_level ( void  )

Definition at line 734 of file check.c.

735{
736 /*
737 * We unconditionally start/stop the new server because pg_resetwal -o set
738 * wal_level to 'minimum'. If the user is upgrading standby servers using
739 * the rsync instructions, they will need pg_upgrade to write its final
740 * WAL record showing wal_level as 'replica'.
741 */
743
745
746 stop_postmaster(false);
747}
void report_extension_updates(ClusterInfo *cluster)
Definition version.c:68

References new_cluster, report_extension_updates(), start_postmaster(), and stop_postmaster().

Referenced by main().

◆ linkFile()

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

Definition at line 186 of file file.c.

188{
189 if (link(src, dst) < 0)
190 pg_fatal("error while creating link for relation \"%s.%s\" (\"%s\" to \"%s\"): %m",
191 schemaName, relName, src, dst);
192}

References fb(), and pg_fatal.

Referenced by transfer_relfile().

◆ output_check_banner()

void output_check_banner ( void  )

Definition at line 513 of file check.c.

514{
516 {
518 "Performing Consistency Checks on Old Live Server\n"
519 "------------------------------------------------");
520 }
521 else
522 {
524 "Performing Consistency Checks\n"
525 "-----------------------------");
526 }
527}

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

752{
754
757 {
761 }
762
764 "Some statistics are not transferred by pg_upgrade.\n"
765 "Once you start the new server, consider running these two commands:\n"
766 " %s/vacuumdb %s--all --analyze-in-stages --missing-stats-only\n"
767 " %s/vacuumdb %s--all --analyze-only",
770
773 "Running this script will delete the old cluster's data files:\n"
774 " %s",
776 else
778 "Could not create a script to delete the old cluster's data files\n"
779 "because user-defined tablespaces or the new cluster's data directory\n"
780 "exist in the old cluster directory. The old cluster's contents must\n"
781 "be deleted manually.");
782
784}
bool user_specified
Definition pg_upgrade.h:343

References appendPQExpBufferChar(), appendPQExpBufferStr(), appendShellString(), ClusterInfo::bindir, fb(), 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,
char new_tablespace 
)

Definition at line 173 of file parallel.c.

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

References fb(), i, UserOpts::jobs, parallel_jobs, pg_fatal, pg_free(), pg_malloc0_object, pg_malloc_array, 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 */
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
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':
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 {
156
159 }
160 break;
161
162 case 'O':
163 /* append option? */
164 if (!new_cluster.pgopts)
166 else
167 {
169
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],
289
292
293 if (!getcwd(cwd, MAXPGPATH))
294 pg_fatal("could not determine current directory");
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
bool parse_sync_method(const char *optarg, DataDirSyncMethod *sync_method)
PGDLLIMPORT int optind
Definition getopt.c:47
PGDLLIMPORT char * optarg
Definition getopt.c:49
int get_user_info(char **user_name_p)
Definition util.c:323
int pg_strcasecmp(const char *s1, const char *s2)
const char * get_progname(const char *argv0)
Definition path.c:669
#define free(a)
#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:279
const char * progname
Definition pg_upgrade.h:341
char * sync_method
Definition pg_upgrade.h:323
bool do_statistics
Definition pg_upgrade.h:324
bool do_sync
Definition pg_upgrade.h:319

References _, ClusterInfo::bindir, canonicalize_path(), UserOpts::char_signedness, UserOpts::check, check_required_directory(), DEF_PGUPORT, UserOpts::do_statistics, UserOpts::do_sync, fb(), 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, 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 225 of file exec.c.

226{
227 char path[MAXPGPATH];
228 int fd;
229
230 snprintf(path, sizeof(path), "%s/postmaster.pid", datadir);
231
232 if ((fd = open(path, O_RDONLY, 0)) < 0)
233 {
234 /* ENOTDIR means we will throw a more useful error later */
235 if (errno != ENOENT && errno != ENOTDIR)
236 pg_fatal("could not open file \"%s\" for reading: %m", path);
237
238 return false;
239 }
240
241 close(fd);
242 return true;
243}
char * datadir
static int fd(const char *x, int i)

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

Referenced by setup().

◆ prep_status()

◆ prep_status_progress()

◆ protocol_negotiation_supported()

bool protocol_negotiation_supported ( const ClusterInfo cluster)

Definition at line 20 of file version.c.

21{
22 /*
23 * The February 2018 patch release (9.3.21, 9.4.16, 9.5.11, 9.6.7, and
24 * 10.2) added support for NegotiateProtocolVersion. But ClusterInfo only
25 * has information about the major version number. To ensure we can still
26 * upgrade older unpatched servers, just assume anything prior to PG11
27 * can't negotiate. It's not possible for those servers to make use of
28 * newer protocols anyway, so nothing is lost.
29 */
30 return (GET_MAJOR_VERSION(cluster->major_version) >= 1100);
31}

References fb(), and GET_MAJOR_VERSION.

Referenced by generate_old_dump(), get_db_conn(), and start_conn().

◆ quote_identifier()

char * quote_identifier ( const char s)

Definition at line 13817 of file ruleutils.c.

13818{
13819 /*
13820 * Can avoid quoting if ident starts with a lowercase letter or underscore
13821 * and contains only lowercase letters, digits, and underscores, *and* is
13822 * not any SQL keyword. Otherwise, supply quotes.
13823 */
13824 int nquotes = 0;
13825 bool safe;
13826 const char *ptr;
13827 char *result;
13828 char *optr;
13829
13830 /*
13831 * would like to use <ctype.h> macros here, but they might yield unwanted
13832 * locale-specific results...
13833 */
13834 safe = ((ident[0] >= 'a' && ident[0] <= 'z') || ident[0] == '_');
13835
13836 for (ptr = ident; *ptr; ptr++)
13837 {
13838 char ch = *ptr;
13839
13840 if ((ch >= 'a' && ch <= 'z') ||
13841 (ch >= '0' && ch <= '9') ||
13842 (ch == '_'))
13843 {
13844 /* okay */
13845 }
13846 else
13847 {
13848 safe = false;
13849 if (ch == '"')
13850 nquotes++;
13851 }
13852 }
13853
13855 safe = false;
13856
13857 if (safe)
13858 {
13859 /*
13860 * Check for keyword. We quote keywords except for unreserved ones.
13861 * (In some cases we could avoid quoting a col_name or type_func_name
13862 * keyword, but it seems much harder than it's worth to tell that.)
13863 *
13864 * Note: ScanKeywordLookup() does case-insensitive comparison, but
13865 * that's fine, since we already know we have all-lower-case.
13866 */
13868
13870 safe = false;
13871 }
13872
13873 if (safe)
13874 return ident; /* no change needed */
13875
13876 result = (char *) palloc(strlen(ident) + nquotes + 2 + 1);
13877
13878 optr = result;
13879 *optr++ = '"';
13880 for (ptr = ident; *ptr; ptr++)
13881 {
13882 char ch = *ptr;
13883
13884 if (ch == '"')
13885 *optr++ = '"';
13886 *optr++ = ch;
13887 }
13888 *optr++ = '"';
13889 *optr = '\0';
13890
13891 return result;
13892}
uint32 result
const uint8 ScanKeywordCategories[SCANKEYWORDS_NUM_KEYWORDS]
Definition keywords.c:29
#define ident
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:1390
bool quote_all_identifiers
Definition ruleutils.c:344

◆ reap_child()

bool reap_child ( bool  wait_for_child)

Definition at line 281 of file parallel.c.

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

References fb(), 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 715 of file check.c.

716{
717 if (user_opts.check)
718 {
719 pg_log(PG_REPORT, "\n*Clusters are compatible*");
720 /* stops new cluster */
721 stop_postmaster(false);
722
724 exit(0);
725 }
726
727 pg_log(PG_REPORT, "\n"
728 "If pg_upgrade fails after this point, you must re-initdb the\n"
729 "new cluster before continuing.");
730}
void cleanup_output_dirs(void)
Definition util.c:63

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

Referenced by main().

◆ report_extension_updates()

void report_extension_updates ( ClusterInfo cluster)

Definition at line 68 of file version.c.

69{
70 UpgradeTaskReport report;
72 const char *query = "SELECT name "
73 "FROM pg_available_extensions "
74 "WHERE installed_version != default_version";
75
76 prep_status("Checking for extension updates");
77
78 report.file = NULL;
79 strcpy(report.path, "update_extensions.sql");
80
82 true, &report);
83
86
87 if (report.file)
88 {
89 fclose(report.file);
90 report_status(PG_REPORT, "notice");
91 pg_log(PG_REPORT, "\n"
92 "Your installation contains extensions that should be updated\n"
93 "with the ALTER EXTENSION command. The file\n"
94 " %s\n"
95 "when executed by psql by the database superuser will update\n"
96 "these extensions.",
97 report.path);
98 }
99 else
100 check_ok();
101}
static void process_extension_updates(DbInfo *dbinfo, PGresult *res, void *arg)
Definition version.c:39
void report_status(eLogType type, const char *fmt,...) pg_attribute_printf(2
char path[MAXPGPATH]
Definition pg_upgrade.h:510

References check_ok(), fb(), 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()

◆ rewrite_multixacts()

MultiXactOffset rewrite_multixacts ( MultiXactId  from_multi,
MultiXactId  to_multi 
)

Definition at line 35 of file multixact_rewrite.c.

36{
37 MultiXactOffset next_offset;
40 char dir[MAXPGPATH] = {0};
41 bool prev_multixid_valid = false;
43
44 /*
45 * The range of valid multi XIDs is unchanged by the conversion (they are
46 * referenced from the heap tables), but the members SLRU is rewritten to
47 * start from offset 1.
48 */
49 next_offset = 1;
50
51 /* Prepare to write the new SLRU files */
52 pg_sprintf(dir, "%s/pg_multixact/offsets", new_cluster.pgdata);
53 offsets_writer = AllocSlruWrite(dir, false);
55
56 pg_sprintf(dir, "%s/pg_multixact/members", new_cluster.pgdata);
57 members_writer = AllocSlruWrite(dir, true /* use long segment names */ );
59
60 /*
61 * Convert old multixids, if needed, by reading them one-by-one from the
62 * old cluster.
63 */
67
68 for (MultiXactId multi = from_multi; multi != to_multi;)
69 {
70 MultiXactMember member;
71 bool multixid_valid;
72
73 /*
74 * Read this multixid's members.
75 *
76 * Locking-only XIDs that may be part of multi-xids don't matter after
77 * upgrade, as there can be no transactions running across upgrade. So
78 * as a small optimization, we only read one member from each
79 * multixid: the one updating one, or if there was no update,
80 * arbitrarily the first locking xid.
81 */
83
84 /*
85 * Write the new offset to pg_multixact/offsets.
86 *
87 * Even if this multixid is invalid, we still need to write its offset
88 * if the *previous* multixid was valid. That's because when reading
89 * a multixid, the number of members is calculated from the difference
90 * between the two offsets.
91 */
93 (multixid_valid || prev_multixid_valid) ? next_offset : 0);
94
95 /* Write the members */
97 {
98 RecordMultiXactMembers(members_writer, next_offset, 1, &member);
99 next_offset += 1;
100 }
101
102 /* Advance to next multixid, handling wraparound */
103 multi++;
104 if (multi < FirstMultiXactId)
105 multi = FirstMultiXactId;
107 }
108
110
111 /* Write the final 'next' offset to the last SLRU page */
113 prev_multixid_valid ? next_offset : 0);
114
115 /* Flush the last SLRU pages */
118
119 return next_offset;
120}
TransactionId MultiXactId
Definition c.h:805
uint64 MultiXactOffset
Definition c.h:807
#define FirstMultiXactId
Definition multixact.h:26
static int64 MXOffsetToMemberPage(MultiXactOffset32 offset)
bool GetOldMultiXactIdSingleMember(OldMultiXactReader *state, MultiXactId multi, MultiXactMember *member)
static int64 MultiXactIdToOffsetPage(MultiXactId multi)
OldMultiXactReader * AllocOldMultiXactRead(char *pgdata, MultiXactId nextMulti, MultiXactOffset32 nextOffset)
void FreeOldMultiXactReader(OldMultiXactReader *state)
static void RecordMultiXactOffset(SlruSegState *offsets_writer, MultiXactId multi, MultiXactOffset offset)
static void RecordMultiXactMembers(SlruSegState *members_writer, MultiXactOffset offset, int nmembers, MultiXactMember *members)
int int int int pg_sprintf(char *str, const char *fmt,...) pg_attribute_printf(2
void FreeSlruWrite(SlruSegState *state)
Definition slru_io.c:260
SlruSegState * AllocSlruWrite(const char *dir, bool long_segment_names)
Definition slru_io.c:166
static char * SlruWriteSwitchPage(SlruSegState *state, uint64 pageno)
Definition slru_io.h:45
uint32 chkpnt_nxtmulti
Definition pg_upgrade.h:220
uint64 chkpnt_nxtmxoff
Definition pg_upgrade.h:221

References AllocOldMultiXactRead(), AllocSlruWrite(), ControlData::chkpnt_nxtmulti, ControlData::chkpnt_nxtmxoff, ClusterInfo::controldata, fb(), FirstMultiXactId, FreeOldMultiXactReader(), FreeSlruWrite(), GetOldMultiXactIdSingleMember(), MAXPGPATH, MultiXactIdToOffsetPage(), MXOffsetToMemberPage(), new_cluster, old_cluster, pg_sprintf(), ClusterInfo::pgdata, RecordMultiXactMembers(), RecordMultiXactOffset(), and SlruWriteSwitchPage().

Referenced by copy_xact_xlog_xid().

◆ start_postmaster()

bool start_postmaster ( ClusterInfo cluster,
bool  report_and_exit_on_error 
)

Definition at line 161 of file server.c.

162{
163 char cmd[MAXPGPATH * 4 + 1000];
164 PGconn *conn;
165 bool pg_ctl_return = false;
166 char socket_string[MAXPGPATH + 200];
167 PQExpBufferData pgoptions;
168
169 static bool exit_hook_registered = false;
170
172 {
175 }
176
177 socket_string[0] = '\0';
178
179#if !defined(WIN32)
180 /* prevent TCP/IP connections, restrict socket access */
182 " -c listen_addresses='' -c unix_socket_permissions=0700");
183
184 /* Have a sockdir? Tell the postmaster. */
185 if (cluster->sockdir)
188 " -c %s='%s'",
189 "unix_socket_directories",
190 cluster->sockdir);
191#endif
192
193 initPQExpBuffer(&pgoptions);
194
195 /*
196 * Construct a parameter string which is passed to the server process.
197 *
198 * Turn off durability requirements to improve object creation speed, and
199 * we only modify the new cluster, so only use it there. If there is a
200 * crash, the new cluster has to be recreated anyway. fsync=off is a big
201 * win on ext4.
202 */
203 if (cluster == &new_cluster)
204 appendPQExpBufferStr(&pgoptions, " -c synchronous_commit=off -c fsync=off -c full_page_writes=off");
205
206 /*
207 * Use -b to disable autovacuum and logical replication launcher
208 * (effective in PG17 or later for the latter).
209 */
210 snprintf(cmd, sizeof(cmd),
211 "\"%s/pg_ctl\" -w -l \"%s/%s\" -D \"%s\" -o \"-p %d -b%s %s%s\" start",
212 cluster->bindir,
214 SERVER_LOG_FILE, cluster->pgconfig, cluster->port,
215 pgoptions.data,
216 cluster->pgopts ? cluster->pgopts : "", socket_string);
217
218 termPQExpBuffer(&pgoptions);
219
220 /*
221 * Don't throw an error right away, let connecting throw the error because
222 * it might supply a reason for the failure.
223 */
225 /* pass both file names if they differ */
227 SERVER_START_LOG_FILE) != 0) ?
230 "%s", cmd);
231
232 /* Did it fail and we are just testing if the server could be started? */
234 return false;
235
236 /*
237 * We set this here to make sure atexit() shuts down the server, but only
238 * if we started the server successfully. We do it before checking for
239 * connectivity in case the server started but there is a connectivity
240 * failure. If pg_ctl did not return success, we will exit below.
241 *
242 * Pre-9.1 servers do not have PQping(), so we could be leaving the server
243 * running if authentication was misconfigured, so someday we might went
244 * to be more aggressive about doing server shutdowns even if pg_ctl
245 * fails, but now (2013-08-14) it seems prudent to be cautious. We don't
246 * want to shutdown a server that might have been accidentally started
247 * during the upgrade.
248 */
249 if (pg_ctl_return)
251
252 /*
253 * pg_ctl -w might have failed because the server couldn't be started, or
254 * there might have been a connection problem in _checking_ if the server
255 * has started. Therefore, even if pg_ctl failed, we continue and test
256 * for connectivity in case we get a connection reason for the failure.
257 */
258 if ((conn = get_db_conn(cluster, "template1")) == NULL ||
260 {
262 if (conn)
263 PQfinish(conn);
264 if (cluster == &old_cluster)
265 pg_fatal("could not connect to source postmaster started with the command:\n"
266 "%s",
267 cmd);
268 else
269 pg_fatal("could not connect to target postmaster started with the command:\n"
270 "%s",
271 cmd);
272 }
273 PQfinish(conn);
274
275 /*
276 * If pg_ctl failed, and the connection didn't fail, and
277 * report_and_exit_on_error is enabled, fail now. This could happen if
278 * the server was already running.
279 */
280 if (!pg_ctl_return)
281 {
282 if (cluster == &old_cluster)
283 pg_fatal("pg_ctl failed to start the source server, or connection failed");
284 else
285 pg_fatal("pg_ctl failed to start the target server, or connection failed");
286 }
287
288 return true;
289}
#define false
#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:154
char * logdir
Definition pg_upgrade.h:307
ClusterInfo * running_cluster
Definition pg_upgrade.h:346

References appendPQExpBufferStr(), conn, CONNECTION_OK, PQExpBufferData::data, exec_prog(), fb(), get_db_conn(), 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 293 of file server.c.

294{
296
301 else
302 return; /* no cluster running */
303
305 "\"%s/pg_ctl\" -w -D \"%s\" -o \"%s\" %s stop",
306 cluster->bindir, cluster->pgconfig,
307 cluster->pgopts ? cluster->pgopts : "",
308 in_atexit ? "-m fast" : "-m smart");
309
311}
#define SERVER_STOP_LOG_FILE
Definition pg_upgrade.h:68

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

◆ 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 fb(), and 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,
char new_tablespace 
)

Definition at line 172 of file relfilenumber.c.

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

References fb(), gen_db_file_maps(), 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)
140 else
141 {
142 int tblnum;
143
144 /* transfer default tablespace */
147
155 /* reap all children */
156 while (reap_child(true) == true)
157 ;
158 }
159
161 check_ok();
162}
void parallel_transfer_all_new_dbs(DbInfoArr *old_db_arr, DbInfoArr *new_db_arr, char *old_pgdata, char *new_pgdata, char *old_tablespace, char *new_tablespace)
Definition parallel.c:173

References check_ok(), end_progress_output(), fb(), UserOpts::jobs, new_cluster, ClusterInfo::num_tablespaces, old_cluster, parallel_transfer_all_new_dbs(), prep_status_progress(), reap_child(), ClusterInfo::tablespaces, 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 
)

◆ upgrade_task_create()

◆ upgrade_task_free()

◆ upgrade_task_run()

void upgrade_task_run ( const UpgradeTask task,
const ClusterInfo cluster 
)

Definition at line 421 of file task.c.

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

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

Referenced by check_for_data_types_usage(), check_for_gist_inet_ops(), check_for_incompatible_polymorphics(), check_for_isn_and_int8_passing_mismatch(), check_for_not_null_inheritance(), 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 255 of file exec.c.

256{
257#ifndef WIN32
258 if (access(".", R_OK | W_OK | X_OK) != 0)
259#else
261#endif
262 pg_fatal("You must have read and write access in the current directory.");
263
264 check_bin_dir(&old_cluster, false);
268}
static void check_bin_dir(ClusterInfo *cluster, bool check_versions)
Definition exec.c:365
static void check_data_dir(ClusterInfo *cluster)
Definition exec.c:333
short access

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

Referenced by setup().

Variable Documentation

◆ log_opts

◆ new_cluster

ClusterInfo new_cluster

Definition at line 359 of file pg_upgrade.h.

◆ old_cluster

◆ os_info

◆ output_files

char* output_files[]
extern

Definition at line 77 of file pg_upgrade.c.

77 {
79#ifdef WIN32
80 /* unique file for pg_ctl start */
82#endif
85 NULL
86};
#define INTERNAL_LOG_FILE
Definition pg_upgrade.h:46

Referenced by make_outputdirs().

◆ user_opts