00001
00002
00003
00004
00005
00006
00007
00008 #include <unistd.h>
00009 #include <assert.h>
00010 #include <sys/stat.h>
00011 #include <sys/time.h>
00012
00013 #include "libpq-fe.h"
00014
00015
00016 #define DEF_PGUPORT 50432
00017
00018
00019 #define USER_NAME_SIZE 128
00020
00021 #define MAX_STRING 1024
00022 #define LINE_ALLOC 4096
00023 #define QUERY_ALLOC 8192
00024
00025 #define MIGRATOR_API_VERSION 1
00026
00027 #define MESSAGE_WIDTH 60
00028
00029 #define GET_MAJOR_VERSION(v) ((v) / 100)
00030
00031
00032 #define GLOBALS_DUMP_FILE "pg_upgrade_dump_globals.sql"
00033 #define DB_DUMP_FILE_MASK "pg_upgrade_dump_%u.custom"
00034
00035 #define DB_DUMP_LOG_FILE_MASK "pg_upgrade_dump_%u.log"
00036 #define SERVER_LOG_FILE "pg_upgrade_server.log"
00037 #define UTILITY_LOG_FILE "pg_upgrade_utility.log"
00038 #define INTERNAL_LOG_FILE "pg_upgrade_internal.log"
00039
00040 extern char *output_files[];
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058 #ifndef WIN32
00059 #define SERVER_START_LOG_FILE SERVER_LOG_FILE
00060 #define SERVER_STOP_LOG_FILE SERVER_LOG_FILE
00061 #else
00062 #define SERVER_START_LOG_FILE "pg_upgrade_server_start.log"
00063
00064
00065
00066
00067
00068 #define SERVER_STOP_LOG_FILE UTILITY_LOG_FILE
00069 #endif
00070
00071
00072 #ifndef WIN32
00073 #define pg_copy_file copy_file
00074 #define pg_mv_file rename
00075 #define pg_link_file link
00076 #define PATH_SEPARATOR '/'
00077 #define RM_CMD "rm -f"
00078 #define RMDIR_CMD "rm -rf"
00079 #define SCRIPT_EXT "sh"
00080 #define ECHO_QUOTE "'"
00081 #define ECHO_BLANK ""
00082 #else
00083 #define pg_copy_file CopyFile
00084 #define pg_mv_file pgrename
00085 #define pg_link_file win32_pghardlink
00086 #define sleep(x) Sleep(x * 1000)
00087 #define PATH_SEPARATOR '\\'
00088 #define RM_CMD "DEL /q"
00089 #define RMDIR_CMD "RMDIR /s/q"
00090 #define SCRIPT_EXT "bat"
00091 #define EXE_EXT ".exe"
00092 #define ECHO_QUOTE ""
00093 #define ECHO_BLANK "."
00094 #endif
00095
00096 #define CLUSTER_NAME(cluster) ((cluster) == &old_cluster ? "old" : \
00097 (cluster) == &new_cluster ? "new" : "none")
00098
00099 #define atooid(x) ((Oid) strtoul((x), NULL, 10))
00100
00101
00102 #define TABLE_SPACE_SUBDIRS_CAT_VER 201001111
00103
00104 #define BINARY_UPGRADE_SERVER_FLAG_CAT_VER 201104251
00105
00106
00107
00108
00109 #define VISIBILITY_MAP_CRASHSAFE_CAT_VER 201107031
00110
00111
00112
00113
00114
00115
00116
00117 #define MULTIXACT_FORMATCHANGE_CAT_VER 201301231
00118
00119
00120
00121
00122 typedef struct
00123 {
00124
00125 char *nspname;
00126 char *relname;
00127 Oid reloid;
00128 Oid relfilenode;
00129
00130 char tablespace[MAXPGPATH];
00131 } RelInfo;
00132
00133 typedef struct
00134 {
00135 RelInfo *rels;
00136 int nrels;
00137 } RelInfoArr;
00138
00139
00140
00141
00142 typedef struct
00143 {
00144 char old_tablespace[MAXPGPATH];
00145 char new_tablespace[MAXPGPATH];
00146 char old_tablespace_suffix[MAXPGPATH];
00147 char new_tablespace_suffix[MAXPGPATH];
00148 Oid old_db_oid;
00149 Oid new_db_oid;
00150
00151
00152
00153
00154
00155 Oid old_relfilenode;
00156 Oid new_relfilenode;
00157
00158 char *nspname;
00159 char *relname;
00160 } FileNameMap;
00161
00162
00163
00164
00165 typedef struct
00166 {
00167 Oid db_oid;
00168 char *db_name;
00169 char db_tblspace[MAXPGPATH];
00170 RelInfoArr rel_arr;
00171 } DbInfo;
00172
00173 typedef struct
00174 {
00175 DbInfo *dbs;
00176 int ndbs;
00177 } DbInfoArr;
00178
00179
00180
00181
00182
00183
00184 typedef struct
00185 {
00186 uint32 ctrl_ver;
00187 uint32 cat_ver;
00188 char nextxlogfile[25];
00189 uint32 chkpnt_tli;
00190 uint32 chkpnt_nxtxid;
00191 uint32 chkpnt_nxtoid;
00192 uint32 chkpnt_nxtmulti;
00193 uint32 chkpnt_nxtmxoff;
00194 uint32 chkpnt_oldstMulti;
00195 uint32 align;
00196 uint32 blocksz;
00197 uint32 largesz;
00198 uint32 walsz;
00199 uint32 walseg;
00200 uint32 ident;
00201 uint32 index;
00202 uint32 toast;
00203 bool date_is_int;
00204 bool float8_pass_by_value;
00205 bool data_checksum_version;
00206 char *lc_collate;
00207 char *lc_ctype;
00208 char *encoding;
00209 } ControlData;
00210
00211
00212
00213
00214 typedef enum
00215 {
00216 TRANSFER_MODE_COPY,
00217 TRANSFER_MODE_LINK
00218 } transferMode;
00219
00220
00221
00222
00223 typedef enum
00224 {
00225 PG_VERBOSE,
00226 PG_STATUS,
00227 PG_REPORT,
00228 PG_WARNING,
00229 PG_FATAL
00230 } eLogType;
00231
00232
00233 typedef long pgpid_t;
00234
00235
00236
00237
00238
00239
00240
00241 typedef struct
00242 {
00243 ControlData controldata;
00244 DbInfoArr dbarr;
00245 char *pgdata;
00246 char *pgconfig;
00247
00248 char *bindir;
00249 char *pgopts;
00250
00251 char *sockdir;
00252 unsigned short port;
00253 uint32 major_version;
00254 char major_version_str[64];
00255 uint32 bin_version;
00256 Oid pg_database_oid;
00257 Oid install_role_oid;
00258 Oid role_count;
00259 char *tablespace_suffix;
00260 } ClusterInfo;
00261
00262
00263
00264
00265
00266 typedef struct
00267 {
00268 FILE *internal;
00269 bool verbose;
00270 bool retain;
00271 } LogOpts;
00272
00273
00274
00275
00276
00277 typedef struct
00278 {
00279 bool check;
00280
00281 transferMode transfer_mode;
00282 int jobs;
00283 } UserOpts;
00284
00285
00286
00287
00288
00289 typedef struct
00290 {
00291 const char *progname;
00292 char *exec_path;
00293 char *user;
00294 char **old_tablespaces;
00295 int num_old_tablespaces;
00296 char **libraries;
00297 int num_libraries;
00298 ClusterInfo *running_cluster;
00299 } OSInfo;
00300
00301
00302
00303
00304
00305 extern LogOpts log_opts;
00306 extern UserOpts user_opts;
00307 extern ClusterInfo old_cluster,
00308 new_cluster;
00309 extern OSInfo os_info;
00310
00311
00312
00313
00314 void output_check_banner(bool live_check);
00315 void check_and_dump_old_cluster(bool live_check,
00316 char **sequence_script_file_name);
00317 void check_new_cluster(void);
00318 void report_clusters_compatible(void);
00319 void issue_warnings(char *sequence_script_file_name);
00320 void output_completion_banner(char *analyze_script_file_name,
00321 char *deletion_script_file_name);
00322 void check_cluster_versions(void);
00323 void check_cluster_compatibility(bool live_check);
00324 void create_script_for_old_cluster_deletion(char **deletion_script_file_name);
00325 void create_script_for_cluster_analyze(char **analyze_script_file_name);
00326
00327
00328
00329
00330 void get_control_data(ClusterInfo *cluster, bool live_check);
00331 void check_control_data(ControlData *oldctrl, ControlData *newctrl);
00332 void disable_old_cluster(void);
00333
00334
00335
00336
00337 void generate_old_dump(void);
00338
00339
00340
00341
00342 #define EXEC_PSQL_ARGS "--echo-queries --set ON_ERROR_STOP=on --no-psqlrc --dbname=template1"
00343 bool
00344 exec_prog(const char *log_file, const char *opt_log_file,
00345 bool throw_error, const char *fmt,...)
00346 __attribute__((format(PG_PRINTF_ATTRIBUTE, 4, 5)));
00347 void verify_directories(void);
00348 bool pid_lock_file_exists(const char *datadir);
00349
00350
00351
00352
00353 #ifdef PAGE_CONVERSION
00354 typedef const char *(*pluginStartup) (uint16 migratorVersion,
00355 uint16 *pluginVersion, uint16 newPageVersion,
00356 uint16 oldPageVersion, void **pluginData);
00357 typedef const char *(*pluginConvertFile) (void *pluginData,
00358 const char *dstName, const char *srcName);
00359 typedef const char *(*pluginConvertPage) (void *pluginData,
00360 const char *dstPage, const char *srcPage);
00361 typedef const char *(*pluginShutdown) (void *pluginData);
00362
00363 typedef struct
00364 {
00365 uint16 oldPageVersion;
00366 uint16 newPageVersion;
00367 uint16 pluginVersion;
00368 void *pluginData;
00369 pluginStartup startup;
00370 pluginConvertFile convertFile;
00371
00372 pluginConvertPage convertPage;
00373
00374 pluginShutdown shutdown;
00375 } pageCnvCtx;
00376
00377 const pageCnvCtx *setupPageConverter(void);
00378 #else
00379
00380 typedef void *pageCnvCtx;
00381 #endif
00382
00383 const char *copyAndUpdateFile(pageCnvCtx *pageConverter, const char *src,
00384 const char *dst, bool force);
00385 const char *linkAndUpdateFile(pageCnvCtx *pageConverter, const char *src,
00386 const char *dst);
00387
00388 void check_hard_link(void);
00389 FILE *fopen_priv(const char *path, const char *mode);
00390
00391
00392
00393 void install_support_functions_in_new_db(const char *db_name);
00394 void uninstall_support_functions_from_new_cluster(void);
00395 void get_loadable_libraries(void);
00396 void check_loadable_libraries(void);
00397
00398
00399
00400 FileNameMap *gen_db_file_maps(DbInfo *old_db,
00401 DbInfo *new_db, int *nmaps, const char *old_pgdata,
00402 const char *new_pgdata);
00403 void get_db_and_rel_infos(ClusterInfo *cluster);
00404 void print_maps(FileNameMap *maps, int n,
00405 const char *db_name);
00406
00407
00408
00409 void parseCommandLine(int argc, char *argv[]);
00410 void adjust_data_dir(ClusterInfo *cluster);
00411 void get_sock_dir(ClusterInfo *cluster, bool live_check);
00412
00413
00414
00415 void get_pg_database_relfilenode(ClusterInfo *cluster);
00416 void transfer_all_new_tablespaces(DbInfoArr *old_db_arr,
00417 DbInfoArr *new_db_arr, char *old_pgdata, char *new_pgdata);
00418 void transfer_all_new_dbs(DbInfoArr *old_db_arr,
00419 DbInfoArr *new_db_arr, char *old_pgdata, char *new_pgdata,
00420 char *old_tablespace);
00421
00422
00423
00424 void init_tablespaces(void);
00425
00426
00427
00428
00429 PGconn *connectToServer(ClusterInfo *cluster, const char *db_name);
00430 PGresult *
00431 executeQueryOrDie(PGconn *conn, const char *fmt,...)
00432 __attribute__((format(PG_PRINTF_ATTRIBUTE, 2, 3)));
00433
00434 char *cluster_conn_opts(ClusterInfo *cluster);
00435
00436 bool start_postmaster(ClusterInfo *cluster, bool throw_error);
00437 void stop_postmaster(bool fast);
00438 uint32 get_major_server_version(ClusterInfo *cluster);
00439 void check_pghost_envvar(void);
00440
00441
00442
00443
00444 char *quote_identifier(const char *s);
00445 int get_user_info(char **user_name);
00446 void check_ok(void);
00447 void
00448 report_status(eLogType type, const char *fmt,...)
00449 __attribute__((format(PG_PRINTF_ATTRIBUTE, 2, 3)));
00450 void
00451 pg_log(eLogType type, char *fmt,...)
00452 __attribute__((format(PG_PRINTF_ATTRIBUTE, 2, 3)));
00453 void end_progress_output(void);
00454 void
00455 prep_status(const char *fmt,...)
00456 __attribute__((format(PG_PRINTF_ATTRIBUTE, 1, 2)));
00457 void check_ok(void);
00458 const char *getErrorText(int errNum);
00459 unsigned int str2uint(const char *str);
00460 void pg_putenv(const char *var, const char *val);
00461
00462
00463
00464
00465 void new_9_0_populate_pg_largeobject_metadata(ClusterInfo *cluster,
00466 bool check_mode);
00467
00468
00469
00470 void old_8_3_check_for_name_data_type_usage(ClusterInfo *cluster);
00471 void old_8_3_check_for_tsquery_usage(ClusterInfo *cluster);
00472 void old_8_3_check_ltree_usage(ClusterInfo *cluster);
00473 void old_8_3_rebuild_tsvector_tables(ClusterInfo *cluster, bool check_mode);
00474 void old_8_3_invalidate_hash_gin_indexes(ClusterInfo *cluster, bool check_mode);
00475 void old_8_3_invalidate_bpchar_pattern_ops_indexes(ClusterInfo *cluster,
00476 bool check_mode);
00477 char *old_8_3_create_sequence_script(ClusterInfo *cluster);
00478
00479
00480 void parallel_exec_prog(const char *log_file, const char *opt_log_file,
00481 const char *fmt,...)
00482 __attribute__((format(PG_PRINTF_ATTRIBUTE, 3, 4)));
00483 void parallel_transfer_all_new_dbs(DbInfoArr *old_db_arr, DbInfoArr *new_db_arr,
00484 char *old_pgdata, char *new_pgdata,
00485 char *old_tablespace);
00486 bool reap_child(bool wait_for_child);
00487