Header And Logo

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

pg_controldata.c

Go to the documentation of this file.
00001 /*
00002  * pg_controldata
00003  *
00004  * reads the data from $PGDATA/global/pg_control
00005  *
00006  * copyright (c) Oliver Elphick <[email protected]>, 2001;
00007  * licence: BSD
00008  *
00009  * src/bin/pg_controldata/pg_controldata.c
00010  */
00011 
00012 /*
00013  * We have to use postgres.h not postgres_fe.h here, because there's so much
00014  * backend-only stuff in the XLOG include files we need.  But we need a
00015  * frontend-ish environment otherwise.  Hence this ugly hack.
00016  */
00017 #define FRONTEND 1
00018 
00019 #include "postgres.h"
00020 
00021 #include <unistd.h>
00022 #include <time.h>
00023 #include <sys/stat.h>
00024 #include <fcntl.h>
00025 
00026 #include "access/xlog.h"
00027 #include "access/xlog_internal.h"
00028 #include "catalog/pg_control.h"
00029 
00030 
00031 static void
00032 usage(const char *progname)
00033 {
00034     printf(_("%s displays control information of a PostgreSQL database cluster.\n\n"), progname);
00035     printf(_("Usage:\n"));
00036     printf(_("  %s [OPTION] [DATADIR]\n"), progname);
00037     printf(_("\nOptions:\n"));
00038     printf(_("  -V, --version  output version information, then exit\n"));
00039     printf(_("  -?, --help     show this help, then exit\n"));
00040     printf(_("\nIf no data directory (DATADIR) is specified, "
00041              "the environment variable PGDATA\nis used.\n\n"));
00042     printf(_("Report bugs to <[email protected]>.\n"));
00043 }
00044 
00045 
00046 static const char *
00047 dbState(DBState state)
00048 {
00049     switch (state)
00050     {
00051         case DB_STARTUP:
00052             return _("starting up");
00053         case DB_SHUTDOWNED:
00054             return _("shut down");
00055         case DB_SHUTDOWNED_IN_RECOVERY:
00056             return _("shut down in recovery");
00057         case DB_SHUTDOWNING:
00058             return _("shutting down");
00059         case DB_IN_CRASH_RECOVERY:
00060             return _("in crash recovery");
00061         case DB_IN_ARCHIVE_RECOVERY:
00062             return _("in archive recovery");
00063         case DB_IN_PRODUCTION:
00064             return _("in production");
00065     }
00066     return _("unrecognized status code");
00067 }
00068 
00069 static const char *
00070 wal_level_str(WalLevel wal_level)
00071 {
00072     switch (wal_level)
00073     {
00074         case WAL_LEVEL_MINIMAL:
00075             return "minimal";
00076         case WAL_LEVEL_ARCHIVE:
00077             return "archive";
00078         case WAL_LEVEL_HOT_STANDBY:
00079             return "hot_standby";
00080     }
00081     return _("unrecognized wal_level");
00082 }
00083 
00084 
00085 int
00086 main(int argc, char *argv[])
00087 {
00088     ControlFileData ControlFile;
00089     int         fd;
00090     char        ControlFilePath[MAXPGPATH];
00091     char       *DataDir;
00092     pg_crc32    crc;
00093     time_t      time_tmp;
00094     char        pgctime_str[128];
00095     char        ckpttime_str[128];
00096     char        sysident_str[32];
00097     const char *strftime_fmt = "%c";
00098     const char *progname;
00099     XLogSegNo   segno;
00100     char        xlogfilename[MAXFNAMELEN];
00101 
00102     set_pglocale_pgservice(argv[0], PG_TEXTDOMAIN("pg_controldata"));
00103 
00104     progname = get_progname(argv[0]);
00105 
00106     if (argc > 1)
00107     {
00108         if (strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-?") == 0)
00109         {
00110             usage(progname);
00111             exit(0);
00112         }
00113         if (strcmp(argv[1], "--version") == 0 || strcmp(argv[1], "-V") == 0)
00114         {
00115             puts("pg_controldata (PostgreSQL) " PG_VERSION);
00116             exit(0);
00117         }
00118     }
00119 
00120     if (argc > 1)
00121         DataDir = argv[1];
00122     else
00123         DataDir = getenv("PGDATA");
00124     if (DataDir == NULL)
00125     {
00126         fprintf(stderr, _("%s: no data directory specified\n"), progname);
00127         fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
00128         exit(1);
00129     }
00130 
00131     snprintf(ControlFilePath, MAXPGPATH, "%s/global/pg_control", DataDir);
00132 
00133     if ((fd = open(ControlFilePath, O_RDONLY | PG_BINARY, 0)) == -1)
00134     {
00135         fprintf(stderr, _("%s: could not open file \"%s\" for reading: %s\n"),
00136                 progname, ControlFilePath, strerror(errno));
00137         exit(2);
00138     }
00139 
00140     if (read(fd, &ControlFile, sizeof(ControlFileData)) != sizeof(ControlFileData))
00141     {
00142         fprintf(stderr, _("%s: could not read file \"%s\": %s\n"),
00143                 progname, ControlFilePath, strerror(errno));
00144         exit(2);
00145     }
00146     close(fd);
00147 
00148     /* Check the CRC. */
00149     INIT_CRC32(crc);
00150     COMP_CRC32(crc,
00151                (char *) &ControlFile,
00152                offsetof(ControlFileData, crc));
00153     FIN_CRC32(crc);
00154 
00155     if (!EQ_CRC32(crc, ControlFile.crc))
00156         printf(_("WARNING: Calculated CRC checksum does not match value stored in file.\n"
00157                  "Either the file is corrupt, or it has a different layout than this program\n"
00158                  "is expecting.  The results below are untrustworthy.\n\n"));
00159 
00160     /*
00161      * This slightly-chintzy coding will work as long as the control file
00162      * timestamps are within the range of time_t; that should be the case in
00163      * all foreseeable circumstances, so we don't bother importing the
00164      * backend's timezone library into pg_controldata.
00165      *
00166      * Use variable for format to suppress overly-anal-retentive gcc warning
00167      * about %c
00168      */
00169     time_tmp = (time_t) ControlFile.time;
00170     strftime(pgctime_str, sizeof(pgctime_str), strftime_fmt,
00171              localtime(&time_tmp));
00172     time_tmp = (time_t) ControlFile.checkPointCopy.time;
00173     strftime(ckpttime_str, sizeof(ckpttime_str), strftime_fmt,
00174              localtime(&time_tmp));
00175 
00176     /*
00177      * Calculate name of the WAL file containing the latest checkpoint's REDO
00178      * start point.
00179      */
00180     XLByteToSeg(ControlFile.checkPointCopy.redo, segno);
00181     XLogFileName(xlogfilename, ControlFile.checkPointCopy.ThisTimeLineID, segno);
00182 
00183     /*
00184      * Format system_identifier separately to keep platform-dependent format
00185      * code out of the translatable message string.
00186      */
00187     snprintf(sysident_str, sizeof(sysident_str), UINT64_FORMAT,
00188              ControlFile.system_identifier);
00189 
00190     printf(_("pg_control version number:            %u\n"),
00191            ControlFile.pg_control_version);
00192     if (ControlFile.pg_control_version % 65536 == 0 && ControlFile.pg_control_version / 65536 != 0)
00193         printf(_("WARNING: possible byte ordering mismatch\n"
00194                  "The byte ordering used to store the pg_control file might not match the one\n"
00195                  "used by this program.  In that case the results below would be incorrect, and\n"
00196                  "the PostgreSQL installation would be incompatible with this data directory.\n"));
00197     printf(_("Catalog version number:               %u\n"),
00198            ControlFile.catalog_version_no);
00199     printf(_("Database system identifier:           %s\n"),
00200            sysident_str);
00201     printf(_("Database cluster state:               %s\n"),
00202            dbState(ControlFile.state));
00203     printf(_("pg_control last modified:             %s\n"),
00204            pgctime_str);
00205     printf(_("Latest checkpoint location:           %X/%X\n"),
00206            (uint32) (ControlFile.checkPoint >> 32),
00207            (uint32) ControlFile.checkPoint);
00208     printf(_("Prior checkpoint location:            %X/%X\n"),
00209            (uint32) (ControlFile.prevCheckPoint >> 32),
00210            (uint32) ControlFile.prevCheckPoint);
00211     printf(_("Latest checkpoint's REDO location:    %X/%X\n"),
00212            (uint32) (ControlFile.checkPointCopy.redo >> 32),
00213            (uint32) ControlFile.checkPointCopy.redo);
00214     printf(_("Latest checkpoint's REDO WAL file:    %s\n"),
00215            xlogfilename);
00216     printf(_("Latest checkpoint's TimeLineID:       %u\n"),
00217            ControlFile.checkPointCopy.ThisTimeLineID);
00218     printf(_("Latest checkpoint's PrevTimeLineID:   %u\n"),
00219            ControlFile.checkPointCopy.PrevTimeLineID);
00220     printf(_("Latest checkpoint's full_page_writes: %s\n"),
00221            ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off"));
00222     printf(_("Latest checkpoint's NextXID:          %u/%u\n"),
00223            ControlFile.checkPointCopy.nextXidEpoch,
00224            ControlFile.checkPointCopy.nextXid);
00225     printf(_("Latest checkpoint's NextOID:          %u\n"),
00226            ControlFile.checkPointCopy.nextOid);
00227     printf(_("Latest checkpoint's NextMultiXactId:  %u\n"),
00228            ControlFile.checkPointCopy.nextMulti);
00229     printf(_("Latest checkpoint's NextMultiOffset:  %u\n"),
00230            ControlFile.checkPointCopy.nextMultiOffset);
00231     printf(_("Latest checkpoint's oldestXID:        %u\n"),
00232            ControlFile.checkPointCopy.oldestXid);
00233     printf(_("Latest checkpoint's oldestXID's DB:   %u\n"),
00234            ControlFile.checkPointCopy.oldestXidDB);
00235     printf(_("Latest checkpoint's oldestActiveXID:  %u\n"),
00236            ControlFile.checkPointCopy.oldestActiveXid);
00237     printf(_("Latest checkpoint's oldestMultiXid:   %u\n"),
00238            ControlFile.checkPointCopy.oldestMulti);
00239     printf(_("Latest checkpoint's oldestMulti's DB: %u\n"),
00240            ControlFile.checkPointCopy.oldestMultiDB);
00241     printf(_("Time of latest checkpoint:            %s\n"),
00242            ckpttime_str);
00243     printf(_("Fake LSN counter for unlogged rels:   %X/%X\n"),
00244            (uint32) (ControlFile.unloggedLSN >> 32),
00245            (uint32) ControlFile.unloggedLSN);
00246     printf(_("Minimum recovery ending location:     %X/%X\n"),
00247            (uint32) (ControlFile.minRecoveryPoint >> 32),
00248            (uint32) ControlFile.minRecoveryPoint);
00249     printf(_("Min recovery ending loc's timeline:   %u\n"),
00250            ControlFile.minRecoveryPointTLI);
00251     printf(_("Backup start location:                %X/%X\n"),
00252            (uint32) (ControlFile.backupStartPoint >> 32),
00253            (uint32) ControlFile.backupStartPoint);
00254     printf(_("Backup end location:                  %X/%X\n"),
00255            (uint32) (ControlFile.backupEndPoint >> 32),
00256            (uint32) ControlFile.backupEndPoint);
00257     printf(_("End-of-backup record required:        %s\n"),
00258            ControlFile.backupEndRequired ? _("yes") : _("no"));
00259     printf(_("Current wal_level setting:            %s\n"),
00260            wal_level_str(ControlFile.wal_level));
00261     printf(_("Current max_connections setting:      %d\n"),
00262            ControlFile.MaxConnections);
00263     printf(_("Current max_prepared_xacts setting:   %d\n"),
00264            ControlFile.max_prepared_xacts);
00265     printf(_("Current max_locks_per_xact setting:   %d\n"),
00266            ControlFile.max_locks_per_xact);
00267     printf(_("Maximum data alignment:               %u\n"),
00268            ControlFile.maxAlign);
00269     /* we don't print floatFormat since can't say much useful about it */
00270     printf(_("Database block size:                  %u\n"),
00271            ControlFile.blcksz);
00272     printf(_("Blocks per segment of large relation: %u\n"),
00273            ControlFile.relseg_size);
00274     printf(_("WAL block size:                       %u\n"),
00275            ControlFile.xlog_blcksz);
00276     printf(_("Bytes per WAL segment:                %u\n"),
00277            ControlFile.xlog_seg_size);
00278     printf(_("Maximum length of identifiers:        %u\n"),
00279            ControlFile.nameDataLen);
00280     printf(_("Maximum columns in an index:          %u\n"),
00281            ControlFile.indexMaxKeys);
00282     printf(_("Maximum size of a TOAST chunk:        %u\n"),
00283            ControlFile.toast_max_chunk_size);
00284     printf(_("Date/time type storage:               %s\n"),
00285            (ControlFile.enableIntTimes ? _("64-bit integers") : _("floating-point numbers")));
00286     printf(_("Float4 argument passing:              %s\n"),
00287            (ControlFile.float4ByVal ? _("by value") : _("by reference")));
00288     printf(_("Float8 argument passing:              %s\n"),
00289            (ControlFile.float8ByVal ? _("by value") : _("by reference")));
00290     printf(_("Data page checksum version:           %u\n"),
00291            ControlFile.data_checksum_version);
00292     return 0;
00293 }