Header And Logo

PostgreSQL
| The world's most advanced open source database.

pg_upgrade.h

Go to the documentation of this file.
00001 /*
00002  *  pg_upgrade.h
00003  *
00004  *  Copyright (c) 2010-2013, PostgreSQL Global Development Group
00005  *  contrib/pg_upgrade/pg_upgrade.h
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 /* Use port in the private/dynamic port number range */
00016 #define DEF_PGUPORT         50432
00017 
00018 /* Allocate for null byte */
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 /* contains both global db information and CREATE DATABASE commands */
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  * WIN32 files do not accept writes from multiple processes
00044  *
00045  * On Win32, we can't send both pg_upgrade output and command output to the
00046  * same file because we get the error: "The process cannot access the file
00047  * because it is being used by another process." so send the pg_ctl
00048  * command-line output to a new file, rather than into the server log file.
00049  * Ideally we could use UTILITY_LOG_FILE for this, but some Windows platforms
00050  * keep the pg_ctl output file open by the running postmaster, even after
00051  * pg_ctl exits.
00052  *
00053  * We could use the Windows pgwin32_open() flags to allow shared file
00054  * writes but is unclear how all other tools would use those flags, so
00055  * we just avoid it and log a little differently on Windows;  we adjust
00056  * the error message appropriately.
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  *  "pg_ctl start" keeps SERVER_START_LOG_FILE and SERVER_LOG_FILE open
00065  *  while the server is running, so we use UTILITY_LOG_FILE for "pg_ctl
00066  *  stop".
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 /* OID system catalog preservation added during PG 9.0 development */
00102 #define TABLE_SPACE_SUBDIRS_CAT_VER 201001111
00103 /* postmaster/postgres -b (binary_upgrade) flag added during PG 9.1 development */
00104 #define BINARY_UPGRADE_SERVER_FLAG_CAT_VER 201104251
00105 /*
00106  *  Visibility map changed with this 9.2 commit,
00107  *  8f9fe6edce358f7904e0db119416b4d1080a83aa; pick later catalog version.
00108  */
00109 #define VISIBILITY_MAP_CRASHSAFE_CAT_VER 201107031
00110 
00111 /*
00112  * pg_multixact format changed in 9.3 commit 0ac5ad5134f2769ccbaefec73844f85,
00113  * ("Improve concurrency of foreign key locking") which also updated catalog
00114  * version to this value.  pg_upgrade behavior depends on whether old and new
00115  * server versions are both newer than this, or only the new one is.
00116  */
00117 #define MULTIXACT_FORMATCHANGE_CAT_VER 201301231
00118 
00119 /*
00120  * Each relation is represented by a relinfo structure.
00121  */
00122 typedef struct
00123 {
00124     /* Can't use NAMEDATALEN;  not guaranteed to fit on client */
00125     char        *nspname;       /* namespace name */
00126     char        *relname;       /* relation name */
00127     Oid         reloid;         /* relation oid */
00128     Oid         relfilenode;    /* relation relfile node */
00129     /* relation tablespace path, or "" for the cluster default */
00130     char        tablespace[MAXPGPATH];
00131 } RelInfo;
00132 
00133 typedef struct
00134 {
00135     RelInfo    *rels;
00136     int         nrels;
00137 } RelInfoArr;
00138 
00139 /*
00140  * The following structure represents a relation mapping.
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      * old/new relfilenodes might differ for pg_largeobject(_metadata) indexes
00153      * due to VACUUM FULL or REINDEX.  Other relfilenodes are preserved.
00154      */
00155     Oid         old_relfilenode;
00156     Oid         new_relfilenode;
00157     /* the rest are used only for logging and error reporting */
00158     char        *nspname;       /* namespaces */
00159     char        *relname;
00160 } FileNameMap;
00161 
00162 /*
00163  * Structure to store database information
00164  */
00165 typedef struct
00166 {
00167     Oid         db_oid;         /* oid of the database */
00168     char        *db_name;       /* database name */
00169     char        db_tblspace[MAXPGPATH]; /* database default tablespace path */
00170     RelInfoArr  rel_arr;        /* array of all user relinfos */
00171 } DbInfo;
00172 
00173 typedef struct
00174 {
00175     DbInfo     *dbs;            /* array of db infos */
00176     int         ndbs;           /* number of db infos */
00177 } DbInfoArr;
00178 
00179 /*
00180  * The following structure is used to hold pg_control information.
00181  * Rather than using the backend's control structure we use our own
00182  * structure to avoid pg_control version issues between releases.
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  * Enumeration to denote link modes
00213  */
00214 typedef enum
00215 {
00216     TRANSFER_MODE_COPY,
00217     TRANSFER_MODE_LINK
00218 } transferMode;
00219 
00220 /*
00221  * Enumeration to denote pg_log modes
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  * cluster
00238  *
00239  *  information about each cluster
00240  */
00241 typedef struct
00242 {
00243     ControlData controldata;    /* pg_control information */
00244     DbInfoArr   dbarr;          /* dbinfos array */
00245     char       *pgdata;         /* pathname for cluster's $PGDATA directory */
00246     char       *pgconfig;       /* pathname for cluster's config file
00247                                  * directory */
00248     char       *bindir;         /* pathname for cluster's executable directory */
00249     char       *pgopts;         /* options to pass to the server, like pg_ctl
00250                                  * -o */
00251     char       *sockdir;        /* directory for Unix Domain socket, if any */
00252     unsigned short port;        /* port number where postmaster is waiting */
00253     uint32      major_version;  /* PG_VERSION of cluster */
00254     char        major_version_str[64];  /* string PG_VERSION of cluster */
00255     uint32      bin_version;    /* version returned from pg_ctl */
00256     Oid         pg_database_oid;    /* OID of pg_database relation */
00257     Oid         install_role_oid;   /* OID of connected role */
00258     Oid         role_count;         /* number of roles defined in the cluster */
00259     char       *tablespace_suffix;      /* directory specification */
00260 } ClusterInfo;
00261 
00262 
00263 /*
00264  *  LogOpts
00265 */
00266 typedef struct
00267 {
00268     FILE       *internal;       /* internal log FILE */
00269     bool        verbose;        /* TRUE -> be verbose in messages */
00270     bool        retain;         /* retain log files on success */
00271 } LogOpts;
00272 
00273 
00274 /*
00275  *  UserOpts
00276 */
00277 typedef struct
00278 {
00279     bool        check;          /* TRUE -> ask user for permission to make
00280                                  * changes */
00281     transferMode transfer_mode; /* copy files or link them? */
00282     int         jobs;
00283 } UserOpts;
00284 
00285 
00286 /*
00287  * OSInfo
00288  */
00289 typedef struct
00290 {
00291     const char *progname;       /* complete pathname for this program */
00292     char       *exec_path;      /* full path to my executable */
00293     char       *user;           /* username for clusters */
00294     char      **old_tablespaces;    /* tablespaces */
00295     int         num_old_tablespaces;
00296     char      **libraries;      /* loadable libraries */
00297     int         num_libraries;
00298     ClusterInfo *running_cluster;
00299 } OSInfo;
00300 
00301 
00302 /*
00303  * Global variables
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 /* check.c */
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 /* controldata.c */
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 /* dump.c */
00336 
00337 void        generate_old_dump(void);
00338 
00339 
00340 /* exec.c */
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 /* file.c */
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; /* Page layout version of the old cluster       */
00366     uint16      newPageVersion; /* Page layout version of the new cluster       */
00367     uint16      pluginVersion;  /* API version of converter plugin */
00368     void       *pluginData;     /* Plugin data (set by plugin) */
00369     pluginStartup startup;      /* Pointer to plugin's startup function */
00370     pluginConvertFile convertFile;      /* Pointer to plugin's file converter
00371                                          * function */
00372     pluginConvertPage convertPage;      /* Pointer to plugin's page converter
00373                                          * function */
00374     pluginShutdown shutdown;    /* Pointer to plugin's shutdown function */
00375 } pageCnvCtx;
00376 
00377 const pageCnvCtx *setupPageConverter(void);
00378 #else
00379 /* dummy */
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 /* function.c */
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 /* info.c */
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 /* option.c */
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 /* relfilenode.c */
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 /* tablespace.c */
00423 
00424 void        init_tablespaces(void);
00425 
00426 
00427 /* server.c */
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 /* util.c */
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 /* version.c */
00464 
00465 void new_9_0_populate_pg_largeobject_metadata(ClusterInfo *cluster,
00466                                          bool check_mode);
00467 
00468 /* version_old_8_3.c */
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 /* parallel.c */
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