LCOV - code coverage report
Current view: top level - src/bin/pg_controldata - pg_controldata.c (source / functions) Hit Total Coverage
Test: PostgreSQL 12beta1 Lines: 119 131 90.8 %
Date: 2019-06-16 14:06:46 Functions: 4 4 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * pg_controldata
       3             :  *
       4             :  * reads the data from $PGDATA/global/pg_control
       5             :  *
       6             :  * copyright (c) Oliver Elphick <olly@lfix.co.uk>, 2001;
       7             :  * licence: BSD
       8             :  *
       9             :  * src/bin/pg_controldata/pg_controldata.c
      10             :  */
      11             : 
      12             : /*
      13             :  * We have to use postgres.h not postgres_fe.h here, because there's so much
      14             :  * backend-only stuff in the XLOG include files we need.  But we need a
      15             :  * frontend-ish environment otherwise.  Hence this ugly hack.
      16             :  */
      17             : #define FRONTEND 1
      18             : 
      19             : #include "postgres.h"
      20             : 
      21             : #include <time.h>
      22             : 
      23             : #include "access/transam.h"
      24             : #include "access/xlog.h"
      25             : #include "access/xlog_internal.h"
      26             : #include "catalog/pg_control.h"
      27             : #include "common/controldata_utils.h"
      28             : #include "common/logging.h"
      29             : #include "pg_getopt.h"
      30             : #include "getopt_long.h"
      31             : 
      32             : 
      33             : static void
      34           2 : usage(const char *progname)
      35             : {
      36           2 :     printf(_("%s displays control information of a PostgreSQL database cluster.\n\n"), progname);
      37           2 :     printf(_("Usage:\n"));
      38           2 :     printf(_("  %s [OPTION] [DATADIR]\n"), progname);
      39           2 :     printf(_("\nOptions:\n"));
      40           2 :     printf(_(" [-D, --pgdata=]DATADIR  data directory\n"));
      41           2 :     printf(_("  -V, --version          output version information, then exit\n"));
      42           2 :     printf(_("  -?, --help             show this help, then exit\n"));
      43           2 :     printf(_("\nIf no data directory (DATADIR) is specified, "
      44             :              "the environment variable PGDATA\nis used.\n\n"));
      45           2 :     printf(_("Report bugs to <pgsql-bugs@lists.postgresql.org>.\n"));
      46           2 : }
      47             : 
      48             : 
      49             : static const char *
      50          20 : dbState(DBState state)
      51             : {
      52          20 :     switch (state)
      53             :     {
      54             :         case DB_STARTUP:
      55           2 :             return _("starting up");
      56             :         case DB_SHUTDOWNED:
      57          16 :             return _("shut down");
      58             :         case DB_SHUTDOWNED_IN_RECOVERY:
      59           2 :             return _("shut down in recovery");
      60             :         case DB_SHUTDOWNING:
      61           0 :             return _("shutting down");
      62             :         case DB_IN_CRASH_RECOVERY:
      63           0 :             return _("in crash recovery");
      64             :         case DB_IN_ARCHIVE_RECOVERY:
      65           0 :             return _("in archive recovery");
      66             :         case DB_IN_PRODUCTION:
      67           0 :             return _("in production");
      68             :     }
      69           0 :     return _("unrecognized status code");
      70             : }
      71             : 
      72             : static const char *
      73          20 : wal_level_str(WalLevel wal_level)
      74             : {
      75          20 :     switch (wal_level)
      76             :     {
      77             :         case WAL_LEVEL_MINIMAL:
      78           2 :             return "minimal";
      79             :         case WAL_LEVEL_REPLICA:
      80          18 :             return "replica";
      81             :         case WAL_LEVEL_LOGICAL:
      82           0 :             return "logical";
      83             :     }
      84           0 :     return _("unrecognized wal_level");
      85             : }
      86             : 
      87             : 
      88             : int
      89          30 : main(int argc, char *argv[])
      90             : {
      91             :     static struct option long_options[] = {
      92             :         {"pgdata", required_argument, NULL, 'D'},
      93             :         {NULL, 0, NULL, 0}
      94             :     };
      95             : 
      96             :     ControlFileData *ControlFile;
      97             :     bool        crc_ok;
      98          30 :     char       *DataDir = NULL;
      99             :     time_t      time_tmp;
     100             :     char        pgctime_str[128];
     101             :     char        ckpttime_str[128];
     102             :     char        sysident_str[32];
     103             :     char        mock_auth_nonce_str[MOCK_AUTH_NONCE_LEN * 2 + 1];
     104          30 :     const char *strftime_fmt = "%c";
     105             :     const char *progname;
     106             :     char        xlogfilename[MAXFNAMELEN];
     107             :     int         c;
     108             :     int         i;
     109             :     int         WalSegSz;
     110             : 
     111          30 :     pg_logging_init(argv[0]);
     112          30 :     set_pglocale_pgservice(argv[0], PG_TEXTDOMAIN("pg_controldata"));
     113          30 :     progname = get_progname(argv[0]);
     114             : 
     115          30 :     if (argc > 1)
     116             :     {
     117          28 :         if (strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-?") == 0)
     118             :         {
     119           2 :             usage(progname);
     120           2 :             exit(0);
     121             :         }
     122          26 :         if (strcmp(argv[1], "--version") == 0 || strcmp(argv[1], "-V") == 0)
     123             :         {
     124           2 :             puts("pg_controldata (PostgreSQL) " PG_VERSION);
     125           2 :             exit(0);
     126             :         }
     127             :     }
     128             : 
     129          52 :     while ((c = getopt_long(argc, argv, "D:", long_options, NULL)) != -1)
     130             :     {
     131           2 :         switch (c)
     132             :         {
     133             :             case 'D':
     134           0 :                 DataDir = optarg;
     135           0 :                 break;
     136             : 
     137             :             default:
     138           2 :                 fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
     139           2 :                 exit(1);
     140             :         }
     141             :     }
     142             : 
     143          24 :     if (DataDir == NULL)
     144             :     {
     145          24 :         if (optind < argc)
     146          22 :             DataDir = argv[optind++];
     147             :         else
     148           2 :             DataDir = getenv("PGDATA");
     149             :     }
     150             : 
     151             :     /* Complain if any arguments remain */
     152          24 :     if (optind < argc)
     153             :     {
     154           0 :         pg_log_error("too many command-line arguments (first is \"%s\")",
     155             :                      argv[optind]);
     156           0 :         fprintf(stderr, _("Try \"%s --help\" for more information.\n"),
     157             :                 progname);
     158           0 :         exit(1);
     159             :     }
     160             : 
     161          24 :     if (DataDir == NULL)
     162             :     {
     163           2 :         pg_log_error("no data directory specified");
     164           2 :         fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
     165           2 :         exit(1);
     166             :     }
     167             : 
     168             :     /* get a copy of the control file */
     169          22 :     ControlFile = get_controlfile(DataDir, &crc_ok);
     170          20 :     if (!crc_ok)
     171           2 :         printf(_("WARNING: Calculated CRC checksum does not match value stored in file.\n"
     172             :                  "Either the file is corrupt, or it has a different layout than this program\n"
     173             :                  "is expecting.  The results below are untrustworthy.\n\n"));
     174             : 
     175             :     /* set wal segment size */
     176          20 :     WalSegSz = ControlFile->xlog_seg_size;
     177             : 
     178          20 :     if (!IsValidWalSegSize(WalSegSz))
     179             :     {
     180           2 :         printf(_("WARNING: invalid WAL segment size\n"));
     181           2 :         printf(ngettext("The WAL segment size stored in the file, %d byte, is not a power of two\n"
     182             :                         "between 1 MB and 1 GB.  The file is corrupt and the results below are\n"
     183             :                         "untrustworthy.\n\n",
     184             :                         "The WAL segment size stored in the file, %d bytes, is not a power of two\n"
     185             :                         "between 1 MB and 1 GB.  The file is corrupt and the results below are\n"
     186             :                         "untrustworthy.\n\n",
     187             :                         WalSegSz),
     188             :                WalSegSz);
     189             :     }
     190             : 
     191             :     /*
     192             :      * This slightly-chintzy coding will work as long as the control file
     193             :      * timestamps are within the range of time_t; that should be the case in
     194             :      * all foreseeable circumstances, so we don't bother importing the
     195             :      * backend's timezone library into pg_controldata.
     196             :      *
     197             :      * Use variable for format to suppress overly-anal-retentive gcc warning
     198             :      * about %c
     199             :      */
     200          20 :     time_tmp = (time_t) ControlFile->time;
     201          20 :     strftime(pgctime_str, sizeof(pgctime_str), strftime_fmt,
     202          20 :              localtime(&time_tmp));
     203          20 :     time_tmp = (time_t) ControlFile->checkPointCopy.time;
     204          20 :     strftime(ckpttime_str, sizeof(ckpttime_str), strftime_fmt,
     205          20 :              localtime(&time_tmp));
     206             : 
     207             :     /*
     208             :      * Calculate name of the WAL file containing the latest checkpoint's REDO
     209             :      * start point.
     210             :      *
     211             :      * A corrupted control file could report a WAL segment size of 0, and to
     212             :      * guard against division by zero, we need to treat that specially.
     213             :      */
     214          20 :     if (WalSegSz != 0)
     215             :     {
     216             :         XLogSegNo   segno;
     217             : 
     218          18 :         XLByteToSeg(ControlFile->checkPointCopy.redo, segno, WalSegSz);
     219          18 :         XLogFileName(xlogfilename, ControlFile->checkPointCopy.ThisTimeLineID,
     220             :                      segno, WalSegSz);
     221             :     }
     222             :     else
     223           2 :         strcpy(xlogfilename, _("???"));
     224             : 
     225             :     /*
     226             :      * Format system_identifier and mock_authentication_nonce separately to
     227             :      * keep platform-dependent format code out of the translatable message
     228             :      * string.
     229             :      */
     230          20 :     snprintf(sysident_str, sizeof(sysident_str), UINT64_FORMAT,
     231             :              ControlFile->system_identifier);
     232         660 :     for (i = 0; i < MOCK_AUTH_NONCE_LEN; i++)
     233         640 :         snprintf(&mock_auth_nonce_str[i * 2], 3, "%02x",
     234         640 :                  (unsigned char) ControlFile->mock_authentication_nonce[i]);
     235             : 
     236          20 :     printf(_("pg_control version number:            %u\n"),
     237             :            ControlFile->pg_control_version);
     238          20 :     printf(_("Catalog version number:               %u\n"),
     239             :            ControlFile->catalog_version_no);
     240          20 :     printf(_("Database system identifier:           %s\n"),
     241             :            sysident_str);
     242          20 :     printf(_("Database cluster state:               %s\n"),
     243             :            dbState(ControlFile->state));
     244          20 :     printf(_("pg_control last modified:             %s\n"),
     245             :            pgctime_str);
     246          20 :     printf(_("Latest checkpoint location:           %X/%X\n"),
     247             :            (uint32) (ControlFile->checkPoint >> 32),
     248             :            (uint32) ControlFile->checkPoint);
     249          20 :     printf(_("Latest checkpoint's REDO location:    %X/%X\n"),
     250             :            (uint32) (ControlFile->checkPointCopy.redo >> 32),
     251             :            (uint32) ControlFile->checkPointCopy.redo);
     252          20 :     printf(_("Latest checkpoint's REDO WAL file:    %s\n"),
     253             :            xlogfilename);
     254          20 :     printf(_("Latest checkpoint's TimeLineID:       %u\n"),
     255             :            ControlFile->checkPointCopy.ThisTimeLineID);
     256          20 :     printf(_("Latest checkpoint's PrevTimeLineID:   %u\n"),
     257             :            ControlFile->checkPointCopy.PrevTimeLineID);
     258          20 :     printf(_("Latest checkpoint's full_page_writes: %s\n"),
     259             :            ControlFile->checkPointCopy.fullPageWrites ? _("on") : _("off"));
     260          20 :     printf(_("Latest checkpoint's NextXID:          %u:%u\n"),
     261             :            EpochFromFullTransactionId(ControlFile->checkPointCopy.nextFullXid),
     262             :            XidFromFullTransactionId(ControlFile->checkPointCopy.nextFullXid));
     263          20 :     printf(_("Latest checkpoint's NextOID:          %u\n"),
     264             :            ControlFile->checkPointCopy.nextOid);
     265          20 :     printf(_("Latest checkpoint's NextMultiXactId:  %u\n"),
     266             :            ControlFile->checkPointCopy.nextMulti);
     267          20 :     printf(_("Latest checkpoint's NextMultiOffset:  %u\n"),
     268             :            ControlFile->checkPointCopy.nextMultiOffset);
     269          20 :     printf(_("Latest checkpoint's oldestXID:        %u\n"),
     270             :            ControlFile->checkPointCopy.oldestXid);
     271          20 :     printf(_("Latest checkpoint's oldestXID's DB:   %u\n"),
     272             :            ControlFile->checkPointCopy.oldestXidDB);
     273          20 :     printf(_("Latest checkpoint's oldestActiveXID:  %u\n"),
     274             :            ControlFile->checkPointCopy.oldestActiveXid);
     275          20 :     printf(_("Latest checkpoint's oldestMultiXid:   %u\n"),
     276             :            ControlFile->checkPointCopy.oldestMulti);
     277          20 :     printf(_("Latest checkpoint's oldestMulti's DB: %u\n"),
     278             :            ControlFile->checkPointCopy.oldestMultiDB);
     279          20 :     printf(_("Latest checkpoint's oldestCommitTsXid:%u\n"),
     280             :            ControlFile->checkPointCopy.oldestCommitTsXid);
     281          20 :     printf(_("Latest checkpoint's newestCommitTsXid:%u\n"),
     282             :            ControlFile->checkPointCopy.newestCommitTsXid);
     283          20 :     printf(_("Time of latest checkpoint:            %s\n"),
     284             :            ckpttime_str);
     285          20 :     printf(_("Fake LSN counter for unlogged rels:   %X/%X\n"),
     286             :            (uint32) (ControlFile->unloggedLSN >> 32),
     287             :            (uint32) ControlFile->unloggedLSN);
     288          20 :     printf(_("Minimum recovery ending location:     %X/%X\n"),
     289             :            (uint32) (ControlFile->minRecoveryPoint >> 32),
     290             :            (uint32) ControlFile->minRecoveryPoint);
     291          20 :     printf(_("Min recovery ending loc's timeline:   %u\n"),
     292             :            ControlFile->minRecoveryPointTLI);
     293          20 :     printf(_("Backup start location:                %X/%X\n"),
     294             :            (uint32) (ControlFile->backupStartPoint >> 32),
     295             :            (uint32) ControlFile->backupStartPoint);
     296          20 :     printf(_("Backup end location:                  %X/%X\n"),
     297             :            (uint32) (ControlFile->backupEndPoint >> 32),
     298             :            (uint32) ControlFile->backupEndPoint);
     299          20 :     printf(_("End-of-backup record required:        %s\n"),
     300             :            ControlFile->backupEndRequired ? _("yes") : _("no"));
     301          20 :     printf(_("wal_level setting:                    %s\n"),
     302             :            wal_level_str(ControlFile->wal_level));
     303          20 :     printf(_("wal_log_hints setting:                %s\n"),
     304             :            ControlFile->wal_log_hints ? _("on") : _("off"));
     305          20 :     printf(_("max_connections setting:              %d\n"),
     306             :            ControlFile->MaxConnections);
     307          20 :     printf(_("max_worker_processes setting:         %d\n"),
     308             :            ControlFile->max_worker_processes);
     309          20 :     printf(_("max_wal_senders setting:              %d\n"),
     310             :            ControlFile->max_wal_senders);
     311          20 :     printf(_("max_prepared_xacts setting:           %d\n"),
     312             :            ControlFile->max_prepared_xacts);
     313          20 :     printf(_("max_locks_per_xact setting:           %d\n"),
     314             :            ControlFile->max_locks_per_xact);
     315          20 :     printf(_("track_commit_timestamp setting:       %s\n"),
     316             :            ControlFile->track_commit_timestamp ? _("on") : _("off"));
     317          20 :     printf(_("Maximum data alignment:               %u\n"),
     318             :            ControlFile->maxAlign);
     319             :     /* we don't print floatFormat since can't say much useful about it */
     320          20 :     printf(_("Database block size:                  %u\n"),
     321             :            ControlFile->blcksz);
     322          20 :     printf(_("Blocks per segment of large relation: %u\n"),
     323             :            ControlFile->relseg_size);
     324          20 :     printf(_("WAL block size:                       %u\n"),
     325             :            ControlFile->xlog_blcksz);
     326          20 :     printf(_("Bytes per WAL segment:                %u\n"),
     327             :            ControlFile->xlog_seg_size);
     328          20 :     printf(_("Maximum length of identifiers:        %u\n"),
     329             :            ControlFile->nameDataLen);
     330          20 :     printf(_("Maximum columns in an index:          %u\n"),
     331             :            ControlFile->indexMaxKeys);
     332          20 :     printf(_("Maximum size of a TOAST chunk:        %u\n"),
     333             :            ControlFile->toast_max_chunk_size);
     334          20 :     printf(_("Size of a large-object chunk:         %u\n"),
     335             :            ControlFile->loblksize);
     336             :     /* This is no longer configurable, but users may still expect to see it: */
     337          20 :     printf(_("Date/time type storage:               %s\n"),
     338             :            _("64-bit integers"));
     339          20 :     printf(_("Float4 argument passing:              %s\n"),
     340             :            (ControlFile->float4ByVal ? _("by value") : _("by reference")));
     341          20 :     printf(_("Float8 argument passing:              %s\n"),
     342             :            (ControlFile->float8ByVal ? _("by value") : _("by reference")));
     343          20 :     printf(_("Data page checksum version:           %u\n"),
     344             :            ControlFile->data_checksum_version);
     345          20 :     printf(_("Mock authentication nonce:            %s\n"),
     346             :            mock_auth_nonce_str);
     347          20 :     return 0;
     348             : }

Generated by: LCOV version 1.13