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

Go to the source code of this file.

Data Structures

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

Macros

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

Typedefs

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

Enumerations

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

Functions

void output_check_banner (void)
 
void check_and_dump_old_cluster (void)
 
void check_new_cluster (void)
 
void report_clusters_compatible (void)
 
void issue_warnings_and_set_wal_level (void)
 
void output_completion_banner (char *deletion_script_file_name)
 
void check_cluster_versions (void)
 
void check_cluster_compatibility (void)
 
void create_script_for_old_cluster_deletion (char **deletion_script_file_name)
 
void get_control_data (ClusterInfo *cluster)
 
void check_control_data (ControlData *oldctrl, ControlData *newctrl)
 
void disable_old_cluster (void)
 
void generate_old_dump (void)
 
bool exec_prog (const char *log_filename, const char *opt_log_file, bool report_error, bool exit_on_error, const char *fmt,...) pg_attribute_printf(5
 
bool void verify_directories (void)
 
bool pid_lock_file_exists (const char *datadir)
 
void cloneFile (const char *src, const char *dst, const char *schemaName, const char *relName)
 
void copyFile (const char *src, const char *dst, const char *schemaName, const char *relName)
 
void copyFileByRange (const char *src, const char *dst, const char *schemaName, const char *relName)
 
void linkFile (const char *src, const char *dst, const char *schemaName, const char *relName)
 
void rewriteVisibilityMap (const char *fromfile, const char *tofile, const char *schemaName, const char *relName)
 
void check_file_clone (void)
 
void check_copy_file_range (void)
 
void check_hard_link (void)
 
void get_loadable_libraries (void)
 
void check_loadable_libraries (void)
 
FileNameMapgen_db_file_maps (DbInfo *old_db, DbInfo *new_db, int *nmaps, const char *old_pgdata, const char *new_pgdata)
 
void get_db_rel_and_slot_infos (ClusterInfo *cluster)
 
int count_old_cluster_logical_slots (void)
 
void get_subscription_count (ClusterInfo *cluster)
 
void parseCommandLine (int argc, char *argv[])
 
void adjust_data_dir (ClusterInfo *cluster)
 
void get_sock_dir (ClusterInfo *cluster)
 
void transfer_all_new_tablespaces (DbInfoArr *old_db_arr, DbInfoArr *new_db_arr, char *old_pgdata, char *new_pgdata)
 
void transfer_all_new_dbs (DbInfoArr *old_db_arr, DbInfoArr *new_db_arr, char *old_pgdata, char *new_pgdata, char *old_tablespace)
 
void init_tablespaces (void)
 
PGconnconnectToServer (ClusterInfo *cluster, const char *db_name)
 
PGresultexecuteQueryOrDie (PGconn *conn, const char *fmt,...) pg_attribute_printf(2
 
PGresult char * cluster_conn_opts (ClusterInfo *cluster)
 
bool start_postmaster (ClusterInfo *cluster, bool report_and_exit_on_error)
 
void stop_postmaster (bool in_atexit)
 
uint32 get_major_server_version (ClusterInfo *cluster)
 
void check_pghost_envvar (void)
 
char * quote_identifier (const char *s)
 
int get_user_info (char **user_name_p)
 
void check_ok (void)
 
void report_status (eLogType type, const char *fmt,...) pg_attribute_printf(2
 
void void pg_log (eLogType type, const char *fmt,...) pg_attribute_printf(2
 
void void void pg_fatal (const char *fmt,...) pg_attribute_printf(1
 
void void void pg_attribute_noreturn ()
 
void end_progress_output (void)
 
void cleanup_output_dirs (void)
 
void prep_status (const char *fmt,...) pg_attribute_printf(1
 
void void prep_status_progress (const char *fmt,...) pg_attribute_printf(1
 
void void unsigned int str2uint (const char *str)
 
bool jsonb_9_4_check_applicable (ClusterInfo *cluster)
 
void old_9_6_invalidate_hash_indexes (ClusterInfo *cluster, bool check_mode)
 
void report_extension_updates (ClusterInfo *cluster)
 
void parallel_exec_prog (const char *log_file, const char *opt_log_file, const char *fmt,...) pg_attribute_printf(3
 
void void parallel_transfer_all_new_dbs (DbInfoArr *old_db_arr, DbInfoArr *new_db_arr, char *old_pgdata, char *new_pgdata, char *old_tablespace)
 
bool reap_child (bool wait_for_child)
 
UpgradeTaskupgrade_task_create (void)
 
void upgrade_task_add_step (UpgradeTask *task, const char *query, UpgradeTaskProcessCB process_cb, bool free_result, void *arg)
 
void upgrade_task_run (const UpgradeTask *task, const ClusterInfo *cluster)
 
void upgrade_task_free (UpgradeTask *task)
 

Variables

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

Macro Definition Documentation

◆ BASE_OUTPUTDIR

#define BASE_OUTPUTDIR   "pg_upgrade_output.d"

Definition at line 39 of file pg_upgrade.h.

◆ DB_DUMP_FILE_MASK

#define DB_DUMP_FILE_MASK   "pg_upgrade_dump_%u.custom"

Definition at line 31 of file pg_upgrade.h.

◆ DB_DUMP_LOG_FILE_MASK

#define DB_DUMP_LOG_FILE_MASK   "pg_upgrade_dump_%u.log"

Definition at line 43 of file pg_upgrade.h.

◆ DEF_PGUPORT

#define DEF_PGUPORT   50432

Definition at line 20 of file pg_upgrade.h.

◆ DUMP_OUTPUTDIR

#define DUMP_OUTPUTDIR   "dump"

Definition at line 41 of file pg_upgrade.h.

◆ ECHO_BLANK

#define ECHO_BLANK   ""

Definition at line 89 of file pg_upgrade.h.

◆ ECHO_QUOTE

#define ECHO_QUOTE   "'"

Definition at line 88 of file pg_upgrade.h.

◆ EXEC_PSQL_ARGS

#define EXEC_PSQL_ARGS   "--echo-queries --set ON_ERROR_STOP=on --no-psqlrc --dbname=template1"

Definition at line 394 of file pg_upgrade.h.

◆ fopen_priv

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

Definition at line 419 of file pg_upgrade.h.

◆ GET_MAJOR_VERSION

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

Definition at line 27 of file pg_upgrade.h.

◆ GLOBALS_DUMP_FILE

#define GLOBALS_DUMP_FILE   "pg_upgrade_dump_globals.sql"

Definition at line 30 of file pg_upgrade.h.

◆ INTERNAL_LOG_FILE

#define INTERNAL_LOG_FILE   "pg_upgrade_internal.log"

Definition at line 46 of file pg_upgrade.h.

◆ JSONB_FORMAT_CHANGE_CAT_VER

#define JSONB_FORMAT_CHANGE_CAT_VER   201409291

Definition at line 126 of file pg_upgrade.h.

◆ LARGE_OBJECT_SIZE_PG_CONTROL_VER

#define LARGE_OBJECT_SIZE_PG_CONTROL_VER   942

Definition at line 121 of file pg_upgrade.h.

◆ LOG_OUTPUTDIR

#define LOG_OUTPUTDIR   "log"

Definition at line 40 of file pg_upgrade.h.

◆ MAX_STRING

#define MAX_STRING   1024

Definition at line 22 of file pg_upgrade.h.

◆ MESSAGE_WIDTH

#define MESSAGE_WIDTH   62

Definition at line 25 of file pg_upgrade.h.

◆ MULTIXACT_FORMATCHANGE_CAT_VER

#define MULTIXACT_FORMATCHANGE_CAT_VER   201301231

Definition at line 115 of file pg_upgrade.h.

◆ PATH_QUOTE

#define PATH_QUOTE   '\''

Definition at line 83 of file pg_upgrade.h.

◆ PATH_SEPARATOR

#define PATH_SEPARATOR   '/'

Definition at line 82 of file pg_upgrade.h.

◆ pg_mv_file

#define pg_mv_file   rename

Definition at line 81 of file pg_upgrade.h.

◆ QUERY_ALLOC

#define QUERY_ALLOC   8192

Definition at line 23 of file pg_upgrade.h.

◆ RM_CMD

#define RM_CMD   "rm -f"

Definition at line 84 of file pg_upgrade.h.

◆ RMDIR_CMD

#define RMDIR_CMD   "rm -rf"

Definition at line 85 of file pg_upgrade.h.

◆ SCRIPT_EXT

#define SCRIPT_EXT   "sh"

Definition at line 87 of file pg_upgrade.h.

◆ SCRIPT_PREFIX

#define SCRIPT_PREFIX   "./"

Definition at line 86 of file pg_upgrade.h.

◆ SERVER_LOG_FILE

#define SERVER_LOG_FILE   "pg_upgrade_server.log"

Definition at line 44 of file pg_upgrade.h.

◆ SERVER_START_LOG_FILE

#define SERVER_START_LOG_FILE   SERVER_LOG_FILE

Definition at line 67 of file pg_upgrade.h.

◆ SERVER_STOP_LOG_FILE

#define SERVER_STOP_LOG_FILE   SERVER_LOG_FILE

Definition at line 68 of file pg_upgrade.h.

◆ UTILITY_LOG_FILE

#define UTILITY_LOG_FILE   "pg_upgrade_utility.log"

Definition at line 45 of file pg_upgrade.h.

◆ VISIBILITY_MAP_FROZEN_BIT_CAT_VER

#define VISIBILITY_MAP_FROZEN_BIT_CAT_VER   201603011

Definition at line 107 of file pg_upgrade.h.

Typedef Documentation

◆ DataTypesUsageVersionCheck

typedef bool(* DataTypesUsageVersionCheck) (ClusterInfo *cluster)

Definition at line 355 of file pg_upgrade.h.

◆ UpgradeTask

typedef struct UpgradeTask UpgradeTask

Definition at line 503 of file pg_upgrade.h.

◆ UpgradeTaskProcessCB

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

Definition at line 500 of file pg_upgrade.h.

Enumeration Type Documentation

◆ eLogType

enum eLogType
Enumerator
PG_VERBOSE 
PG_STATUS 
PG_REPORT_NONL 
PG_REPORT 
PG_WARNING 
PG_FATAL 

Definition at line 264 of file pg_upgrade.h.

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

◆ transferMode

Enumerator
TRANSFER_MODE_CLONE 
TRANSFER_MODE_COPY 
TRANSFER_MODE_COPY_FILE_RANGE 
TRANSFER_MODE_LINK 

Definition at line 253 of file pg_upgrade.h.

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

Function Documentation

◆ adjust_data_dir()

void adjust_data_dir ( ClusterInfo cluster)

Definition at line 404 of file option.c.

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

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

◆ check_and_dump_old_cluster()

void check_and_dump_old_cluster ( void  )

Definition at line 586 of file check.c.

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

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

Referenced by main().

◆ check_cluster_compatibility()

void check_cluster_compatibility ( void  )

Definition at line 846 of file check.c.

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

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

Referenced by main().

◆ check_cluster_versions()

void check_cluster_versions ( void  )

Definition at line 803 of file check.c.

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

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

Referenced by main().

◆ check_control_data()

void check_control_data ( ControlData oldctrl,
ControlData newctrl 
)

Definition at line 655 of file controldata.c.

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

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

Referenced by check_cluster_compatibility().

◆ check_copy_file_range()

void check_copy_file_range ( void  )

Definition at line 400 of file file.c.

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

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

Referenced by check_new_cluster().

◆ check_file_clone()

void check_file_clone ( void  )

Definition at line 360 of file file.c.

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

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

Referenced by check_new_cluster().

◆ check_hard_link()

void check_hard_link ( void  )

Definition at line 437 of file file.c.

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

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

Referenced by check_new_cluster().

◆ check_loadable_libraries()

void check_loadable_libraries ( void  )

Definition at line 165 of file function.c.

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

References _, LogOpts::basedir, check_ok(), conn, connectToServer(), DbInfo::db_name, ClusterInfo::dbarr, LibraryInfo::dbnum, DbInfoArr::dbs, fopen_priv, fprintf, OSInfo::libraries, library_name_compare(), log_opts, MAXPGPATH, LibraryInfo::name, new_cluster, OSInfo::num_libraries, old_cluster, os_info, pg_fatal, pg_log(), PG_REPORT, PGRES_COMMAND_OK, PQclear(), PQerrorMessage(), PQescapeStringConn(), PQexec(), PQfinish(), PQresultStatus(), prep_status(), qsort, res, and snprintf.

Referenced by check_new_cluster().

◆ check_new_cluster()

void check_new_cluster ( void  )

Definition at line 693 of file check.c.

694{
696
698
700
701 switch (user_opts.transfer_mode)
702 {
705 break;
707 break;
710 break;
713 break;
714 }
715
717
719
721
723
725}
static void check_new_cluster_logical_replication_slots(void)
Definition: check.c:1750
static void check_new_cluster_subscription_configuration(void)
Definition: check.c:1823
static void check_new_cluster_is_empty(void)
Definition: check.c:860
static void check_for_new_tablespace_dir(void)
Definition: check.c:892
void check_file_clone(void)
Definition: file.c:360
void check_hard_link(void)
Definition: file.c:437
void check_copy_file_range(void)
Definition: file.c:400
void check_loadable_libraries(void)
Definition: function.c:165
transferMode transfer_mode
Definition: pg_upgrade.h:326

References check_copy_file_range(), check_file_clone(), check_for_new_tablespace_dir(), check_for_prepared_transactions(), check_hard_link(), check_is_install_user(), check_loadable_libraries(), check_new_cluster_is_empty(), check_new_cluster_logical_replication_slots(), check_new_cluster_subscription_configuration(), get_db_rel_and_slot_infos(), new_cluster, UserOpts::transfer_mode, TRANSFER_MODE_CLONE, TRANSFER_MODE_COPY, TRANSFER_MODE_COPY_FILE_RANGE, TRANSFER_MODE_LINK, and user_opts.

Referenced by main().

◆ check_ok()

void check_ok ( void  )

Definition at line 284 of file util.c.

285{
286 /* all seems well */
288}
static void void report_status(eLogType type, const char *fmt,...)
Definition: util.c:32

References PG_REPORT, and report_status().

◆ check_pghost_envvar()

void check_pghost_envvar ( void  )

Definition at line 369 of file server.c.

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

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

Referenced by setup().

◆ cleanup_output_dirs()

void cleanup_output_dirs ( void  )

Definition at line 63 of file util.c.

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

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

Referenced by main(), and report_clusters_compatible().

◆ cloneFile()

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

Definition at line 39 of file file.c.

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

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

Referenced by transfer_relfile().

◆ cluster_conn_opts()

PGresult char * cluster_conn_opts ( ClusterInfo cluster)

Definition at line 92 of file server.c.

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

References appendPQExpBuffer(), appendPQExpBufferChar(), appendPQExpBufferStr(), appendShellString(), buf, cluster(), createPQExpBuffer(), os_info, resetPQExpBuffer(), and OSInfo::user.

Referenced by create_new_objects(), generate_old_dump(), prepare_new_cluster(), and prepare_new_globals().

◆ connectToServer()

PGconn * connectToServer ( ClusterInfo cluster,
const char *  db_name 
)

Definition at line 28 of file server.c.

29{
30 PGconn *conn = get_db_conn(cluster, db_name);
31
32 if (conn == NULL || PQstatus(conn) != CONNECTION_OK)
33 {
35
36 if (conn)
38
39 printf(_("Failure, exiting\n"));
40 exit(1);
41 }
42
44
45 return conn;
46}
#define ALWAYS_SECURE_SEARCH_PATH_SQL
Definition: connect.h:25
ConnStatusType PQstatus(const PGconn *conn)
Definition: fe-connect.c:7205
@ CONNECTION_OK
Definition: libpq-fe.h:81
exit(1)
#define printf(...)
Definition: port.h:244
static PGconn * get_db_conn(ClusterInfo *cluster, const char *db_name)
Definition: server.c:57
PGresult * executeQueryOrDie(PGconn *conn, const char *fmt,...)
Definition: server.c:122

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

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

◆ copyFile()

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

Definition at line 82 of file file.c.

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

References _dosmaperr(), close, COPY_BUF_SIZE, PG_BINARY, pg_fatal, pg_file_create_mode, pg_free(), pg_malloc(), read, and write.

Referenced by transfer_relfile().

◆ copyFileByRange()

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

Definition at line 151 of file file.c.

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

References close, PG_BINARY, pg_fatal, and pg_file_create_mode.

Referenced by transfer_relfile().

◆ count_old_cluster_logical_slots()

int count_old_cluster_logical_slots ( void  )

Definition at line 742 of file info.c.

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

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

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

◆ create_script_for_old_cluster_deletion()

void create_script_for_old_cluster_deletion ( char **  deletion_script_file_name)

Definition at line 921 of file check.c.

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

References canonicalize_path(), check_ok(), DbInfo::db_oid, ClusterInfo::dbarr, DbInfoArr::dbs, fix_path_separator(), fopen_priv, fprintf, MAXPGPATH, DbInfoArr::ndbs, new_cluster, OSInfo::num_old_tablespaces, old_cluster, OSInfo::old_tablespaces, os_info, path_is_prefix_of_path(), PATH_QUOTE, PATH_SEPARATOR, pfree(), pg_fatal, pg_free(), pg_log(), pg_strdup(), PG_WARNING, ClusterInfo::pgdata, prep_status(), psprintf(), RMDIR_CMD, S_IRWXU, SCRIPT_EXT, SCRIPT_PREFIX, strlcpy(), and ClusterInfo::tablespace_suffix.

Referenced by main().

◆ disable_old_cluster()

void disable_old_cluster ( void  )

Definition at line 712 of file controldata.c.

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

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

Referenced by main().

◆ end_progress_output()

void end_progress_output ( void  )

Definition at line 43 of file util.c.

44{
45 /*
46 * For output to a tty, erase prior contents of progress line. When either
47 * tty or verbose, indent so that report_status() output will align
48 * nicely.
49 */
50 if (log_opts.isatty)
51 {
52 printf("\r");
54 }
55 else if (log_opts.verbose)
57}
#define MESSAGE_WIDTH
Definition: pg_upgrade.h:25
bool isatty
Definition: pg_upgrade.h:314
bool verbose
Definition: pg_upgrade.h:307

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

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

◆ exec_prog()

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

◆ executeQueryOrDie()

◆ gen_db_file_maps()

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

Definition at line 45 of file info.c.

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

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

Referenced by transfer_all_new_dbs().

◆ generate_old_dump()

void generate_old_dump ( void  )

Definition at line 16 of file dump.c.

17{
18 int dbnum;
19
20 prep_status("Creating dump of global objects");
21
22 /* run new pg_dumpall binary for globals */
23 exec_prog(UTILITY_LOG_FILE, NULL, true, true,
24 "\"%s/pg_dumpall\" %s --globals-only --quote-all-identifiers "
25 "--binary-upgrade %s --no-sync -f \"%s/%s\"",
27 log_opts.verbose ? "--verbose" : "",
30 check_ok();
31
32 prep_status_progress("Creating dump of database schemas");
33
34 /* create per-db dump files */
35 for (dbnum = 0; dbnum < old_cluster.dbarr.ndbs; dbnum++)
36 {
37 char sql_file_name[MAXPGPATH],
38 log_file_name[MAXPGPATH];
39 DbInfo *old_db = &old_cluster.dbarr.dbs[dbnum];
41 escaped_connstr;
42
44 appendPQExpBufferStr(&connstr, "dbname=");
46 initPQExpBuffer(&escaped_connstr);
47 appendShellString(&escaped_connstr, connstr.data);
49
50 pg_log(PG_STATUS, "%s", old_db->db_name);
51 snprintf(sql_file_name, sizeof(sql_file_name), DB_DUMP_FILE_MASK, old_db->db_oid);
52 snprintf(log_file_name, sizeof(log_file_name), DB_DUMP_LOG_FILE_MASK, old_db->db_oid);
53
54 parallel_exec_prog(log_file_name, NULL,
55 "\"%s/pg_dump\" %s --schema-only --quote-all-identifiers "
56 "--binary-upgrade --format=custom %s --no-sync --file=\"%s/%s\" %s",
58 log_opts.verbose ? "--verbose" : "",
60 sql_file_name, escaped_connstr.data);
61
62 termPQExpBuffer(&escaped_connstr);
63 }
64
65 /* reap all children */
66 while (reap_child(true) == true)
67 ;
68
70 check_ok();
71}
bool exec_prog(const char *log_filename, const char *opt_log_file, bool report_error, bool exit_on_error, const char *fmt,...)
Definition: exec.c:85
bool reap_child(bool wait_for_child)
Definition: parallel.c:278
void parallel_exec_prog(const char *log_file, const char *opt_log_file, const char *fmt,...)
Definition: parallel.c:62
static char * connstr
Definition: pg_dumpall.c:88
PGresult char * cluster_conn_opts(ClusterInfo *cluster)
Definition: server.c:92
#define GLOBALS_DUMP_FILE
Definition: pg_upgrade.h:30
#define DB_DUMP_LOG_FILE_MASK
Definition: pg_upgrade.h:43
#define UTILITY_LOG_FILE
Definition: pg_upgrade.h:45
void void prep_status_progress(const char *fmt,...) pg_attribute_printf(1
void end_progress_output(void)
Definition: util.c:43
#define DB_DUMP_FILE_MASK
Definition: pg_upgrade.h:31
void initPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:90
void termPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:129
void appendConnStrVal(PQExpBuffer buf, const char *str)
Definition: string_utils.c:545
char * bindir
Definition: pg_upgrade.h:288
char * dumpdir
Definition: pg_upgrade.h:312

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

Referenced by check_and_dump_old_cluster().

◆ get_control_data()

void get_control_data ( ClusterInfo cluster)

Definition at line 36 of file controldata.c.

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

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

Referenced by check_cluster_compatibility().

◆ get_db_rel_and_slot_infos()

void get_db_rel_and_slot_infos ( ClusterInfo cluster)

Definition at line 280 of file info.c.

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

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

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

◆ get_loadable_libraries()

void get_loadable_libraries ( void  )

Definition at line 79 of file function.c.

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

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

Referenced by check_and_dump_old_cluster().

◆ get_major_server_version()

uint32 get_major_server_version ( ClusterInfo cluster)

Definition at line 159 of file server.c.

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

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

Referenced by check_data_dir().

◆ get_sock_dir()

void get_sock_dir ( ClusterInfo cluster)

Definition at line 473 of file option.c.

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

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

Referenced by main().

◆ get_subscription_count()

void get_subscription_count ( ClusterInfo cluster)

Definition at line 758 of file info.c.

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

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

Referenced by check_and_dump_old_cluster().

◆ get_user_info()

int get_user_info ( char **  user_name_p)

Definition at line 323 of file util.c.

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

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

Referenced by parseCommandLine().

◆ init_tablespaces()

void init_tablespaces ( void  )

Definition at line 19 of file tablespace.c.

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

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

Referenced by check_and_dump_old_cluster().

◆ issue_warnings_and_set_wal_level()

void issue_warnings_and_set_wal_level ( void  )

Definition at line 748 of file check.c.

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

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

Referenced by main().

◆ jsonb_9_4_check_applicable()

bool jsonb_9_4_check_applicable ( ClusterInfo cluster)

Definition at line 21 of file version.c.

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

References cluster(), GET_MAJOR_VERSION, and JSONB_FORMAT_CHANGE_CAT_VER.

◆ linkFile()

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

Definition at line 190 of file file.c.

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

References link(), and pg_fatal.

Referenced by transfer_relfile().

◆ old_9_6_invalidate_hash_indexes()

void old_9_6_invalidate_hash_indexes ( ClusterInfo cluster,
bool  check_mode 
)

Definition at line 37 of file version.c.

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

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

Referenced by check_and_dump_old_cluster(), and issue_warnings_and_set_wal_level().

◆ output_check_banner()

void output_check_banner ( void  )

Definition at line 568 of file check.c.

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

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

Referenced by main().

◆ output_completion_banner()

void output_completion_banner ( char *  deletion_script_file_name)

Definition at line 769 of file check.c.

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

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

Referenced by main().

◆ parallel_exec_prog()

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

◆ parallel_transfer_all_new_dbs()

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

Definition at line 172 of file parallel.c.

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

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

Referenced by transfer_all_new_tablespaces().

◆ parseCommandLine()

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

Definition at line 39 of file option.c.

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

References _, ClusterInfo::bindir, canonicalize_path(), UserOpts::check, check_required_directory(), DEF_PGUPORT, UserOpts::do_sync, exit(), FIX_DEFAULT_READ_ONLY, fprintf, free, get_progname(), get_user_info(), getopt_long(), LogOpts::isatty, UserOpts::jobs, log_opts, MAXPGPATH, new_cluster, no_argument, old_cluster, optarg, optind, os_info, parse_sync_method(), path_is_prefix_of_path(), pfree(), pg_fatal, pg_free(), pg_log(), PG_REPORT, pg_strdup(), ClusterInfo::pgdata, ClusterInfo::pgopts, ClusterInfo::port, OSInfo::progname, psprintf(), required_argument, LogOpts::retain, setenv, UserOpts::socketdir, generate_unaccent_rules::stdout, strlcpy(), UserOpts::sync_method, UserOpts::transfer_mode, TRANSFER_MODE_CLONE, TRANSFER_MODE_COPY, TRANSFER_MODE_COPY_FILE_RANGE, TRANSFER_MODE_LINK, usage(), OSInfo::user, user_opts, OSInfo::user_specified, and LogOpts::verbose.

Referenced by main().

◆ pg_attribute_noreturn()

void void void pg_attribute_noreturn ( )

◆ pg_fatal()

void void void pg_fatal ( const char *  fmt,
  ... 
)

◆ pg_log()

◆ pid_lock_file_exists()

bool pid_lock_file_exists ( const char *  datadir)

Definition at line 233 of file exec.c.

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

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

Referenced by setup().

◆ prep_status()

◆ prep_status_progress()

void void prep_status_progress ( const char *  fmt,
  ... 
)

◆ quote_identifier()

char * quote_identifier ( const char *  s)

Definition at line 12940 of file ruleutils.c.

12941{
12942 /*
12943 * Can avoid quoting if ident starts with a lowercase letter or underscore
12944 * and contains only lowercase letters, digits, and underscores, *and* is
12945 * not any SQL keyword. Otherwise, supply quotes.
12946 */
12947 int nquotes = 0;
12948 bool safe;
12949 const char *ptr;
12950 char *result;
12951 char *optr;
12952
12953 /*
12954 * would like to use <ctype.h> macros here, but they might yield unwanted
12955 * locale-specific results...
12956 */
12957 safe = ((ident[0] >= 'a' && ident[0] <= 'z') || ident[0] == '_');
12958
12959 for (ptr = ident; *ptr; ptr++)
12960 {
12961 char ch = *ptr;
12962
12963 if ((ch >= 'a' && ch <= 'z') ||
12964 (ch >= '0' && ch <= '9') ||
12965 (ch == '_'))
12966 {
12967 /* okay */
12968 }
12969 else
12970 {
12971 safe = false;
12972 if (ch == '"')
12973 nquotes++;
12974 }
12975 }
12976
12978 safe = false;
12979
12980 if (safe)
12981 {
12982 /*
12983 * Check for keyword. We quote keywords except for unreserved ones.
12984 * (In some cases we could avoid quoting a col_name or type_func_name
12985 * keyword, but it seems much harder than it's worth to tell that.)
12986 *
12987 * Note: ScanKeywordLookup() does case-insensitive comparison, but
12988 * that's fine, since we already know we have all-lower-case.
12989 */
12990 int kwnum = ScanKeywordLookup(ident, &ScanKeywords);
12991
12992 if (kwnum >= 0 && ScanKeywordCategories[kwnum] != UNRESERVED_KEYWORD)
12993 safe = false;
12994 }
12995
12996 if (safe)
12997 return ident; /* no change needed */
12998
12999 result = (char *) palloc(strlen(ident) + nquotes + 2 + 1);
13000
13001 optr = result;
13002 *optr++ = '"';
13003 for (ptr = ident; *ptr; ptr++)
13004 {
13005 char ch = *ptr;
13006
13007 if (ch == '"')
13008 *optr++ = '"';
13009 *optr++ = ch;
13010 }
13011 *optr++ = '"';
13012 *optr = '\0';
13013
13014 return result;
13015}
const uint8 ScanKeywordCategories[SCANKEYWORDS_NUM_KEYWORDS]
Definition: keywords.c:29
#define ident
Definition: indent_codes.h:47
PGDLLIMPORT const ScanKeywordList ScanKeywords
#define UNRESERVED_KEYWORD
Definition: keywords.h:20
int ScanKeywordLookup(const char *str, const ScanKeywordList *keywords)
Definition: kwlookup.c:38
void * palloc(Size size)
Definition: mcxt.c:1317
bool quote_all_identifiers
Definition: ruleutils.c:339

◆ reap_child()

bool reap_child ( bool  wait_for_child)

Definition at line 278 of file parallel.c.

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

References UserOpts::jobs, parallel_jobs, pg_fatal, res, and user_opts.

Referenced by create_new_objects(), generate_old_dump(), parallel_exec_prog(), parallel_transfer_all_new_dbs(), and transfer_all_new_tablespaces().

◆ report_clusters_compatible()

void report_clusters_compatible ( void  )

Definition at line 729 of file check.c.

730{
731 if (user_opts.check)
732 {
733 pg_log(PG_REPORT, "\n*Clusters are compatible*");
734 /* stops new cluster */
735 stop_postmaster(false);
736
738 exit(0);
739 }
740
741 pg_log(PG_REPORT, "\n"
742 "If pg_upgrade fails after this point, you must re-initdb the\n"
743 "new cluster before continuing.");
744}
void cleanup_output_dirs(void)
Definition: util.c:63

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

Referenced by main().

◆ report_extension_updates()

void report_extension_updates ( ClusterInfo cluster)

Definition at line 179 of file version.c.

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

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

Referenced by issue_warnings_and_set_wal_level().

◆ report_status()

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

◆ rewriteVisibilityMap()

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

Definition at line 216 of file file.c.

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

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

Referenced by transfer_relfile().

◆ start_postmaster()

bool start_postmaster ( ClusterInfo cluster,
bool  report_and_exit_on_error 
)

Definition at line 198 of file server.c.

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

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

◆ stop_postmaster()

void stop_postmaster ( bool  in_atexit)

Definition at line 342 of file server.c.

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

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

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

◆ str2uint()

void void unsigned int str2uint ( const char *  str)

Definition at line 352 of file util.c.

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

References str.

Referenced by get_control_data().

◆ transfer_all_new_dbs()

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

Definition at line 87 of file relfilenumber.c.

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

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

Referenced by parallel_transfer_all_new_dbs().

◆ transfer_all_new_tablespaces()

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

Definition at line 27 of file relfilenumber.c.

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

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

Referenced by main().

◆ upgrade_task_add_step()

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

Definition at line 151 of file task.c.

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

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

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

◆ upgrade_task_create()

UpgradeTask * upgrade_task_create ( void  )

Definition at line 117 of file task.c.

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

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

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

◆ upgrade_task_free()

◆ upgrade_task_run()

void upgrade_task_run ( const UpgradeTask task,
const ClusterInfo cluster 
)

Definition at line 420 of file task.c.

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

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

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

◆ verify_directories()

bool void verify_directories ( void  )

Definition at line 263 of file exec.c.

264{
265#ifndef WIN32
266 if (access(".", R_OK | W_OK | X_OK) != 0)
267#else
268 if (win32_check_directory_write_permissions() != 0)
269#endif
270 pg_fatal("You must have read and write access in the current directory.");
271
272 check_bin_dir(&old_cluster, false);
276}
static void check_bin_dir(ClusterInfo *cluster, bool check_versions)
Definition: exec.c:383
static void check_data_dir(ClusterInfo *cluster)
Definition: exec.c:341
short access
Definition: preproc-type.c:36

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

Referenced by setup().

Variable Documentation

◆ log_opts

◆ new_cluster

ClusterInfo new_cluster

Definition at line 363 of file pg_upgrade.h.

◆ old_cluster

◆ os_info

◆ output_files

char* output_files[]
extern

Definition at line 71 of file pg_upgrade.c.

Referenced by make_outputdirs().

◆ user_opts