Header And Logo

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

controldata.c

Go to the documentation of this file.
00001 /*
00002  *  controldata.c
00003  *
00004  *  controldata functions
00005  *
00006  *  Copyright (c) 2010-2013, PostgreSQL Global Development Group
00007  *  contrib/pg_upgrade/controldata.c
00008  */
00009 
00010 #include "postgres_fe.h"
00011 
00012 #include "pg_upgrade.h"
00013 
00014 #include <ctype.h>
00015 
00016 /*
00017  * get_control_data()
00018  *
00019  * gets pg_control information in "ctrl". Assumes that bindir and
00020  * datadir are valid absolute paths to postgresql bin and pgdata
00021  * directories respectively *and* pg_resetxlog is version compatible
00022  * with datadir. The main purpose of this function is to get pg_control
00023  * data in a version independent manner.
00024  *
00025  * The approach taken here is to invoke pg_resetxlog with -n option
00026  * and then pipe its output. With little string parsing we get the
00027  * pg_control data.  pg_resetxlog cannot be run while the server is running
00028  * so we use pg_controldata;  pg_controldata doesn't provide all the fields
00029  * we need to actually perform the upgrade, but it provides enough for
00030  * check mode.  We do not implement pg_resetxlog -n because it is hard to
00031  * return valid xid data for a running server.
00032  */
00033 void
00034 get_control_data(ClusterInfo *cluster, bool live_check)
00035 {
00036     char        cmd[MAXPGPATH];
00037     char        bufin[MAX_STRING];
00038     FILE       *output;
00039     char       *p;
00040     bool        got_xid = false;
00041     bool        got_oid = false;
00042     bool        got_nextxlogfile = false;
00043     bool        got_multi = false;
00044     bool        got_mxoff = false;
00045     bool        got_oldestmulti = false;
00046     bool        got_log_id = false;
00047     bool        got_log_seg = false;
00048     bool        got_tli = false;
00049     bool        got_align = false;
00050     bool        got_blocksz = false;
00051     bool        got_largesz = false;
00052     bool        got_walsz = false;
00053     bool        got_walseg = false;
00054     bool        got_ident = false;
00055     bool        got_index = false;
00056     bool        got_toast = false;
00057     bool        got_date_is_int = false;
00058     bool        got_float8_pass_by_value = false;
00059     bool        got_data_checksum_version = false;
00060     char       *lc_collate = NULL;
00061     char       *lc_ctype = NULL;
00062     char       *lc_monetary = NULL;
00063     char       *lc_numeric = NULL;
00064     char       *lc_time = NULL;
00065     char       *lang = NULL;
00066     char       *language = NULL;
00067     char       *lc_all = NULL;
00068     char       *lc_messages = NULL;
00069     uint32      logid = 0;
00070     uint32      segno = 0;
00071     uint32      tli = 0;
00072 
00073 
00074     /*
00075      * Because we test the pg_resetxlog output as strings, it has to be in
00076      * English.  Copied from pg_regress.c.
00077      */
00078     if (getenv("LC_COLLATE"))
00079         lc_collate = pg_strdup(getenv("LC_COLLATE"));
00080     if (getenv("LC_CTYPE"))
00081         lc_ctype = pg_strdup(getenv("LC_CTYPE"));
00082     if (getenv("LC_MONETARY"))
00083         lc_monetary = pg_strdup(getenv("LC_MONETARY"));
00084     if (getenv("LC_NUMERIC"))
00085         lc_numeric = pg_strdup(getenv("LC_NUMERIC"));
00086     if (getenv("LC_TIME"))
00087         lc_time = pg_strdup(getenv("LC_TIME"));
00088     if (getenv("LANG"))
00089         lang = pg_strdup(getenv("LANG"));
00090     if (getenv("LANGUAGE"))
00091         language = pg_strdup(getenv("LANGUAGE"));
00092     if (getenv("LC_ALL"))
00093         lc_all = pg_strdup(getenv("LC_ALL"));
00094     if (getenv("LC_MESSAGES"))
00095         lc_messages = pg_strdup(getenv("LC_MESSAGES"));
00096 
00097     pg_putenv("LC_COLLATE", NULL);
00098     pg_putenv("LC_CTYPE", NULL);
00099     pg_putenv("LC_MONETARY", NULL);
00100     pg_putenv("LC_NUMERIC", NULL);
00101     pg_putenv("LC_TIME", NULL);
00102     pg_putenv("LANG",
00103 #ifndef WIN32
00104               NULL);
00105 #else
00106     /* On Windows the default locale cannot be English, so force it */
00107               "en");
00108 #endif
00109     pg_putenv("LANGUAGE", NULL);
00110     pg_putenv("LC_ALL", NULL);
00111     pg_putenv("LC_MESSAGES", "C");
00112 
00113     snprintf(cmd, sizeof(cmd), SYSTEMQUOTE "\"%s/%s \"%s\"" SYSTEMQUOTE,
00114              cluster->bindir,
00115              live_check ? "pg_controldata\"" : "pg_resetxlog\" -n",
00116              cluster->pgdata);
00117     fflush(stdout);
00118     fflush(stderr);
00119 
00120     if ((output = popen(cmd, "r")) == NULL)
00121         pg_log(PG_FATAL, "Could not get control data using %s: %s\n",
00122                cmd, getErrorText(errno));
00123 
00124     /* Only pre-8.4 has these so if they are not set below we will check later */
00125     cluster->controldata.lc_collate = NULL;
00126     cluster->controldata.lc_ctype = NULL;
00127 
00128     /* Only in <= 8.3 */
00129     if (GET_MAJOR_VERSION(cluster->major_version) <= 803)
00130     {
00131         cluster->controldata.float8_pass_by_value = false;
00132         got_float8_pass_by_value = true;
00133     }
00134 
00135     /* Only in <= 9.2 */
00136     if (GET_MAJOR_VERSION(cluster->major_version) <= 902)
00137     {
00138         cluster->controldata.data_checksum_version = 0;
00139         got_data_checksum_version = true;
00140     }
00141 
00142     /* we have the result of cmd in "output". so parse it line by line now */
00143     while (fgets(bufin, sizeof(bufin), output))
00144     {
00145         pg_log(PG_VERBOSE, "%s", bufin);
00146 
00147 #ifdef WIN32
00148 
00149         /*
00150          * Due to an installer bug, LANG=C doesn't work for PG 8.3.3, but does
00151          * work 8.2.6 and 8.3.7, so check for non-ASCII output and suggest a
00152          * minor upgrade.
00153          */
00154         if (GET_MAJOR_VERSION(cluster->major_version) <= 803)
00155         {
00156             for (p = bufin; *p; p++)
00157                 if (!isascii(*p))
00158                     pg_log(PG_FATAL,
00159                            "The 8.3 cluster's pg_controldata is incapable of outputting ASCII, even\n"
00160                            "with LANG=C.  You must upgrade this cluster to a newer version of PostgreSQL\n"
00161                            "8.3 to fix this bug.  PostgreSQL 8.3.7 and later are known to work properly.\n");
00162         }
00163 #endif
00164 
00165         if ((p = strstr(bufin, "pg_control version number:")) != NULL)
00166         {
00167             p = strchr(p, ':');
00168 
00169             if (p == NULL || strlen(p) <= 1)
00170                 pg_log(PG_FATAL, "%d: pg_resetxlog problem\n", __LINE__);
00171 
00172             p++;                /* removing ':' char */
00173             cluster->controldata.ctrl_ver = str2uint(p);
00174         }
00175         else if ((p = strstr(bufin, "Catalog version number:")) != NULL)
00176         {
00177             p = strchr(p, ':');
00178 
00179             if (p == NULL || strlen(p) <= 1)
00180                 pg_log(PG_FATAL, "%d: controldata retrieval problem\n", __LINE__);
00181 
00182             p++;                /* removing ':' char */
00183             cluster->controldata.cat_ver = str2uint(p);
00184         }
00185         else if ((p = strstr(bufin, "First log segment after reset:")) != NULL)
00186         {
00187             /* Skip the colon and any whitespace after it */
00188             p = strchr(p, ':');
00189             if (p == NULL || strlen(p) <= 1)
00190                 pg_log(PG_FATAL, "%d: controldata retrieval problem\n", __LINE__);
00191             p = strpbrk(p, "01234567890ABCDEF");
00192             if (p == NULL || strlen(p) <= 1)
00193                 pg_log(PG_FATAL, "%d: controldata retrieval problem\n", __LINE__);
00194 
00195             /* Make sure it looks like a valid WAL file name */
00196             if (strspn(p, "0123456789ABCDEF") != 24)
00197                 pg_log(PG_FATAL, "%d: controldata retrieval problem\n", __LINE__);
00198 
00199             strlcpy(cluster->controldata.nextxlogfile, p, 25);
00200             got_nextxlogfile = true;
00201         }
00202         else if ((p = strstr(bufin, "First log file ID after reset:")) != NULL)
00203         {
00204             p = strchr(p, ':');
00205 
00206             if (p == NULL || strlen(p) <= 1)
00207                 pg_log(PG_FATAL, "%d: controldata retrieval problem\n", __LINE__);
00208 
00209             p++;                /* removing ':' char */
00210             logid = str2uint(p);
00211             got_log_id = true;
00212         }
00213         else if ((p = strstr(bufin, "First log file segment after reset:")) != NULL)
00214         {
00215             p = strchr(p, ':');
00216 
00217             if (p == NULL || strlen(p) <= 1)
00218                 pg_log(PG_FATAL, "%d: controldata retrieval problem\n", __LINE__);
00219 
00220             p++;                /* removing ':' char */
00221             segno = str2uint(p);
00222             got_log_seg = true;
00223         }
00224         else if ((p = strstr(bufin, "Latest checkpoint's TimeLineID:")) != NULL)
00225         {
00226             p = strchr(p, ':');
00227 
00228             if (p == NULL || strlen(p) <= 1)
00229                 pg_log(PG_FATAL, "%d: controldata retrieval problem\n", __LINE__);
00230 
00231             p++;                /* removing ':' char */
00232             cluster->controldata.chkpnt_tli = str2uint(p);
00233             got_tli = true;
00234         }
00235         else if ((p = strstr(bufin, "Latest checkpoint's NextXID:")) != NULL)
00236         {
00237             char       *op = strchr(p, '/');
00238 
00239             if (op == NULL)
00240                 op = strchr(p, ':');
00241 
00242             if (op == NULL || strlen(op) <= 1)
00243                 pg_log(PG_FATAL, "%d: controldata retrieval problem\n", __LINE__);
00244 
00245             op++;               /* removing ':' char */
00246             cluster->controldata.chkpnt_nxtxid = str2uint(op);
00247             got_xid = true;
00248         }
00249         else if ((p = strstr(bufin, "Latest checkpoint's NextOID:")) != NULL)
00250         {
00251             p = strchr(p, ':');
00252 
00253             if (p == NULL || strlen(p) <= 1)
00254                 pg_log(PG_FATAL, "%d: controldata retrieval problem\n", __LINE__);
00255 
00256             p++;                /* removing ':' char */
00257             cluster->controldata.chkpnt_nxtoid = str2uint(p);
00258             got_oid = true;
00259         }
00260         else if ((p = strstr(bufin, "Latest checkpoint's NextMultiXactId:")) != NULL)
00261         {
00262             p = strchr(p, ':');
00263 
00264             if (p == NULL || strlen(p) <= 1)
00265                 pg_log(PG_FATAL, "%d: controldata retrieval problem\n", __LINE__);
00266 
00267             p++;                /* removing ':' char */
00268             cluster->controldata.chkpnt_nxtmulti = str2uint(p);
00269             got_multi = true;
00270         }
00271         else if ((p = strstr(bufin, "Latest checkpoint's oldestMultiXid:")) != NULL)
00272         {
00273             p = strchr(p, ':');
00274 
00275             if (p == NULL || strlen(p) <= 1)
00276                 pg_log(PG_FATAL, "%d: controldata retrieval problem\n", __LINE__);
00277 
00278             p++;                /* removing ':' char */
00279             cluster->controldata.chkpnt_oldstMulti = str2uint(p);
00280             got_oldestmulti = true;
00281         }
00282         else if ((p = strstr(bufin, "Latest checkpoint's NextMultiOffset:")) != NULL)
00283         {
00284             p = strchr(p, ':');
00285 
00286             if (p == NULL || strlen(p) <= 1)
00287                 pg_log(PG_FATAL, "%d: controldata retrieval problem\n", __LINE__);
00288 
00289             p++;                /* removing ':' char */
00290             cluster->controldata.chkpnt_nxtmxoff = str2uint(p);
00291             got_mxoff = true;
00292         }
00293         else if ((p = strstr(bufin, "Maximum data alignment:")) != NULL)
00294         {
00295             p = strchr(p, ':');
00296 
00297             if (p == NULL || strlen(p) <= 1)
00298                 pg_log(PG_FATAL, "%d: controldata retrieval problem\n", __LINE__);
00299 
00300             p++;                /* removing ':' char */
00301             cluster->controldata.align = str2uint(p);
00302             got_align = true;
00303         }
00304         else if ((p = strstr(bufin, "Database block size:")) != NULL)
00305         {
00306             p = strchr(p, ':');
00307 
00308             if (p == NULL || strlen(p) <= 1)
00309                 pg_log(PG_FATAL, "%d: controldata retrieval problem\n", __LINE__);
00310 
00311             p++;                /* removing ':' char */
00312             cluster->controldata.blocksz = str2uint(p);
00313             got_blocksz = true;
00314         }
00315         else if ((p = strstr(bufin, "Blocks per segment of large relation:")) != NULL)
00316         {
00317             p = strchr(p, ':');
00318 
00319             if (p == NULL || strlen(p) <= 1)
00320                 pg_log(PG_FATAL, "%d: controldata retrieval problem\n", __LINE__);
00321 
00322             p++;                /* removing ':' char */
00323             cluster->controldata.largesz = str2uint(p);
00324             got_largesz = true;
00325         }
00326         else if ((p = strstr(bufin, "WAL block size:")) != NULL)
00327         {
00328             p = strchr(p, ':');
00329 
00330             if (p == NULL || strlen(p) <= 1)
00331                 pg_log(PG_FATAL, "%d: controldata retrieval problem\n", __LINE__);
00332 
00333             p++;                /* removing ':' char */
00334             cluster->controldata.walsz = str2uint(p);
00335             got_walsz = true;
00336         }
00337         else if ((p = strstr(bufin, "Bytes per WAL segment:")) != NULL)
00338         {
00339             p = strchr(p, ':');
00340 
00341             if (p == NULL || strlen(p) <= 1)
00342                 pg_log(PG_FATAL, "%d: controldata retrieval problem\n", __LINE__);
00343 
00344             p++;                /* removing ':' char */
00345             cluster->controldata.walseg = str2uint(p);
00346             got_walseg = true;
00347         }
00348         else if ((p = strstr(bufin, "Maximum length of identifiers:")) != NULL)
00349         {
00350             p = strchr(p, ':');
00351 
00352             if (p == NULL || strlen(p) <= 1)
00353                 pg_log(PG_FATAL, "%d: controldata retrieval problem\n", __LINE__);
00354 
00355             p++;                /* removing ':' char */
00356             cluster->controldata.ident = str2uint(p);
00357             got_ident = true;
00358         }
00359         else if ((p = strstr(bufin, "Maximum columns in an index:")) != NULL)
00360         {
00361             p = strchr(p, ':');
00362 
00363             if (p == NULL || strlen(p) <= 1)
00364                 pg_log(PG_FATAL, "%d: controldata retrieval problem\n", __LINE__);
00365 
00366             p++;                /* removing ':' char */
00367             cluster->controldata.index = str2uint(p);
00368             got_index = true;
00369         }
00370         else if ((p = strstr(bufin, "Maximum size of a TOAST chunk:")) != NULL)
00371         {
00372             p = strchr(p, ':');
00373 
00374             if (p == NULL || strlen(p) <= 1)
00375                 pg_log(PG_FATAL, "%d: controldata retrieval problem\n", __LINE__);
00376 
00377             p++;                /* removing ':' char */
00378             cluster->controldata.toast = str2uint(p);
00379             got_toast = true;
00380         }
00381         else if ((p = strstr(bufin, "Date/time type storage:")) != NULL)
00382         {
00383             p = strchr(p, ':');
00384 
00385             if (p == NULL || strlen(p) <= 1)
00386                 pg_log(PG_FATAL, "%d: controldata retrieval problem\n", __LINE__);
00387 
00388             p++;                /* removing ':' char */
00389             cluster->controldata.date_is_int = strstr(p, "64-bit integers") != NULL;
00390             got_date_is_int = true;
00391         }
00392         else if ((p = strstr(bufin, "Float8 argument passing:")) != NULL)
00393         {
00394             p = strchr(p, ':');
00395 
00396             if (p == NULL || strlen(p) <= 1)
00397                 pg_log(PG_FATAL, "%d: controldata retrieval problem\n", __LINE__);
00398 
00399             p++;                /* removing ':' char */
00400             /* used later for contrib check */
00401             cluster->controldata.float8_pass_by_value = strstr(p, "by value") != NULL;
00402             got_float8_pass_by_value = true;
00403         }
00404         else if ((p = strstr(bufin, "checksum")) != NULL)
00405         {
00406             p = strchr(p, ':');
00407 
00408             if (p == NULL || strlen(p) <= 1)
00409                 pg_log(PG_FATAL, "%d: controldata retrieval problem\n", __LINE__);
00410 
00411             p++;                /* removing ':' char */
00412             /* used later for contrib check */
00413             cluster->controldata.data_checksum_version = str2uint(p);
00414             got_data_checksum_version = true;
00415         }
00416         /* In pre-8.4 only */
00417         else if ((p = strstr(bufin, "LC_COLLATE:")) != NULL)
00418         {
00419             p = strchr(p, ':');
00420 
00421             if (p == NULL || strlen(p) <= 1)
00422                 pg_log(PG_FATAL, "%d: controldata retrieval problem\n", __LINE__);
00423 
00424             p++;                /* removing ':' char */
00425             /* skip leading spaces and remove trailing newline */
00426             p += strspn(p, " ");
00427             if (strlen(p) > 0 && *(p + strlen(p) - 1) == '\n')
00428                 *(p + strlen(p) - 1) = '\0';
00429             cluster->controldata.lc_collate = pg_strdup(p);
00430         }
00431         /* In pre-8.4 only */
00432         else if ((p = strstr(bufin, "LC_CTYPE:")) != NULL)
00433         {
00434             p = strchr(p, ':');
00435 
00436             if (p == NULL || strlen(p) <= 1)
00437                 pg_log(PG_FATAL, "%d: controldata retrieval problem\n", __LINE__);
00438 
00439             p++;                /* removing ':' char */
00440             /* skip leading spaces and remove trailing newline */
00441             p += strspn(p, " ");
00442             if (strlen(p) > 0 && *(p + strlen(p) - 1) == '\n')
00443                 *(p + strlen(p) - 1) = '\0';
00444             cluster->controldata.lc_ctype = pg_strdup(p);
00445         }
00446     }
00447 
00448     if (output)
00449         pclose(output);
00450 
00451     /*
00452      * Restore environment variables
00453      */
00454     pg_putenv("LC_COLLATE", lc_collate);
00455     pg_putenv("LC_CTYPE", lc_ctype);
00456     pg_putenv("LC_MONETARY", lc_monetary);
00457     pg_putenv("LC_NUMERIC", lc_numeric);
00458     pg_putenv("LC_TIME", lc_time);
00459     pg_putenv("LANG", lang);
00460     pg_putenv("LANGUAGE", language);
00461     pg_putenv("LC_ALL", lc_all);
00462     pg_putenv("LC_MESSAGES", lc_messages);
00463 
00464     pg_free(lc_collate);
00465     pg_free(lc_ctype);
00466     pg_free(lc_monetary);
00467     pg_free(lc_numeric);
00468     pg_free(lc_time);
00469     pg_free(lang);
00470     pg_free(language);
00471     pg_free(lc_all);
00472     pg_free(lc_messages);
00473 
00474     /*
00475      * Before 9.3, pg_resetxlog reported the xlogid and segno of the first
00476      * log file after reset as separate lines. Starting with 9.3, it reports
00477      * the WAL file name. If the old cluster is older than 9.3, we construct
00478      * the WAL file name from the xlogid and segno.
00479      */
00480     if (GET_MAJOR_VERSION(cluster->major_version) <= 902)
00481     {
00482         if (got_log_id && got_log_seg)
00483         {
00484             snprintf(cluster->controldata.nextxlogfile, 25, "%08X%08X%08X",
00485                      tli, logid, segno);
00486             got_nextxlogfile = true;
00487         }
00488     }
00489 
00490     /* verify that we got all the mandatory pg_control data */
00491     if (!got_xid || !got_oid ||
00492         !got_multi || !got_mxoff ||
00493         (!got_oldestmulti &&
00494          cluster->controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER) ||
00495         (!live_check && !got_nextxlogfile) ||
00496         !got_tli ||
00497         !got_align || !got_blocksz || !got_largesz || !got_walsz ||
00498         !got_walseg || !got_ident || !got_index || !got_toast ||
00499         !got_date_is_int || !got_float8_pass_by_value || !got_data_checksum_version)
00500     {
00501         pg_log(PG_REPORT,
00502             "The %s cluster lacks some required control information:\n",
00503             CLUSTER_NAME(cluster));
00504 
00505         if (!got_xid)
00506             pg_log(PG_REPORT, "  checkpoint next XID\n");
00507 
00508         if (!got_oid)
00509             pg_log(PG_REPORT, "  latest checkpoint next OID\n");
00510 
00511         if (!got_multi)
00512             pg_log(PG_REPORT, "  latest checkpoint next MultiXactId\n");
00513 
00514         if (!got_mxoff)
00515             pg_log(PG_REPORT, "  latest checkpoint next MultiXactOffset\n");
00516 
00517         if (!got_oldestmulti &&
00518             cluster->controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER)
00519             pg_log(PG_REPORT, "  latest checkpoint oldest MultiXactId\n");
00520 
00521         if (!live_check && !got_nextxlogfile)
00522             pg_log(PG_REPORT, "  first WAL segment after reset\n");
00523 
00524         if (!got_tli)
00525             pg_log(PG_REPORT, "  latest checkpoint timeline ID\n");
00526 
00527         if (!got_align)
00528             pg_log(PG_REPORT, "  maximum alignment\n");
00529 
00530         if (!got_blocksz)
00531             pg_log(PG_REPORT, "  block size\n");
00532 
00533         if (!got_largesz)
00534             pg_log(PG_REPORT, "  large relation segment size\n");
00535 
00536         if (!got_walsz)
00537             pg_log(PG_REPORT, "  WAL block size\n");
00538 
00539         if (!got_walseg)
00540             pg_log(PG_REPORT, "  WAL segment size\n");
00541 
00542         if (!got_ident)
00543             pg_log(PG_REPORT, "  maximum identifier length\n");
00544 
00545         if (!got_index)
00546             pg_log(PG_REPORT, "  maximum number of indexed columns\n");
00547 
00548         if (!got_toast)
00549             pg_log(PG_REPORT, "  maximum TOAST chunk size\n");
00550 
00551         if (!got_date_is_int)
00552             pg_log(PG_REPORT, "  dates/times are integers?\n");
00553 
00554         /* value added in Postgres 8.4 */
00555         if (!got_float8_pass_by_value)
00556             pg_log(PG_REPORT, "  float8 argument passing method\n");
00557 
00558         /* value added in Postgres 9.3 */
00559         if (!got_data_checksum_version)
00560             pg_log(PG_REPORT, "  data checksum version\n");
00561 
00562         pg_log(PG_FATAL,
00563                "Cannot continue without required control information, terminating\n");
00564     }
00565 }
00566 
00567 
00568 /*
00569  * check_control_data()
00570  *
00571  * check to make sure the control data settings are compatible
00572  */
00573 void
00574 check_control_data(ControlData *oldctrl,
00575                    ControlData *newctrl)
00576 {
00577     if (oldctrl->align == 0 || oldctrl->align != newctrl->align)
00578         pg_log(PG_FATAL,
00579                "old and new pg_controldata alignments are invalid or do not match\n"
00580                "Likely one cluster is a 32-bit install, the other 64-bit\n");
00581 
00582     if (oldctrl->blocksz == 0 || oldctrl->blocksz != newctrl->blocksz)
00583         pg_log(PG_FATAL,
00584                "old and new pg_controldata block sizes are invalid or do not match\n");
00585 
00586     if (oldctrl->largesz == 0 || oldctrl->largesz != newctrl->largesz)
00587         pg_log(PG_FATAL,
00588                "old and new pg_controldata maximum relation segement sizes are invalid or do not match\n");
00589 
00590     if (oldctrl->walsz == 0 || oldctrl->walsz != newctrl->walsz)
00591         pg_log(PG_FATAL,
00592                "old and new pg_controldata WAL block sizes are invalid or do not match\n");
00593 
00594     if (oldctrl->walseg == 0 || oldctrl->walseg != newctrl->walseg)
00595         pg_log(PG_FATAL,
00596                "old and new pg_controldata WAL segment sizes are invalid or do not match\n");
00597 
00598     if (oldctrl->ident == 0 || oldctrl->ident != newctrl->ident)
00599         pg_log(PG_FATAL,
00600                "old and new pg_controldata maximum identifier lengths are invalid or do not match\n");
00601 
00602     if (oldctrl->index == 0 || oldctrl->index != newctrl->index)
00603         pg_log(PG_FATAL,
00604                "old and new pg_controldata maximum indexed columns are invalid or do not match\n");
00605 
00606     if (oldctrl->toast == 0 || oldctrl->toast != newctrl->toast)
00607         pg_log(PG_FATAL,
00608                "old and new pg_controldata maximum TOAST chunk sizes are invalid or do not match\n");
00609 
00610     if (oldctrl->date_is_int != newctrl->date_is_int)
00611     {
00612         pg_log(PG_WARNING,
00613                "\nOld and new pg_controldata date/time storage types do not match.\n");
00614 
00615         /*
00616          * This is a common 8.3 -> 8.4 upgrade problem, so we are more verbose
00617          */
00618         pg_log(PG_FATAL,
00619             "You will need to rebuild the new server with configure option\n"
00620                "--disable-integer-datetimes or get server binaries built with those\n"
00621                "options.\n");
00622     }
00623 
00624     /* We might eventually allow upgrades from checksum to no-checksum clusters. */
00625     if (oldctrl->data_checksum_version != newctrl->data_checksum_version)
00626     {
00627         pg_log(PG_FATAL,
00628                "old and new pg_controldata checksum versions are invalid or do not match\n");
00629     }
00630 }
00631 
00632 
00633 void
00634 disable_old_cluster(void)
00635 {
00636     char        old_path[MAXPGPATH],
00637                 new_path[MAXPGPATH];
00638 
00639     /* rename pg_control so old server cannot be accidentally started */
00640     prep_status("Adding \".old\" suffix to old global/pg_control");
00641 
00642     snprintf(old_path, sizeof(old_path), "%s/global/pg_control", old_cluster.pgdata);
00643     snprintf(new_path, sizeof(new_path), "%s/global/pg_control.old", old_cluster.pgdata);
00644     if (pg_mv_file(old_path, new_path) != 0)
00645         pg_log(PG_FATAL, "Unable to rename %s to %s.\n", old_path, new_path);
00646     check_ok();
00647 
00648     pg_log(PG_REPORT, "\n"
00649            "If you want to start the old cluster, you will need to remove\n"
00650            "the \".old\" suffix from %s/global/pg_control.old.\n"
00651          "Because \"link\" mode was used, the old cluster cannot be safely\n"
00652     "started once the new cluster has been started.\n\n", old_cluster.pgdata);
00653 }