LCOV - code coverage report
Current view: top level - src/bin/pg_controldata - pg_controldata.c (source / functions) Coverage Total Hit
Test: Code coverage Lines: 0.0 % 164 0
Test Date: 2026-01-26 10:56:24 Functions: 0.0 % 4 0
Legend: Lines:     hit not hit

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

Generated by: LCOV version 2.3.2-1