Age Owner TLA 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 : * 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
7536 peter_e 33 CBC 1 : usage(const char *progname)
34 : {
7200 35 1 : printf(_("%s displays control information of a PostgreSQL database cluster.\n\n"), progname);
3947 36 1 : printf(_("Usage:\n"));
2762 37 1 : printf(_(" %s [OPTION] [DATADIR]\n"), progname);
3947 38 1 : printf(_("\nOptions:\n"));
1788 39 1 : printf(_(" [-D, --pgdata=]DATADIR data directory\n"));
40 1 : printf(_(" -V, --version output version information, then exit\n"));
41 1 : printf(_(" -?, --help show this help, then exit\n"));
6772 neilc 42 1 : printf(_("\nIf no data directory (DATADIR) is specified, "
43 : "the environment variable PGDATA\nis used.\n\n"));
1136 peter 44 1 : printf(_("Report bugs to <%s>.\n"), PACKAGE_BUGREPORT);
45 1 : printf(_("%s home page: <%s>\n"), PACKAGE_NAME, PACKAGE_URL);
7536 peter_e 46 1 : }
47 :
48 :
49 : static const char *
8062 tgl 50 14 : dbState(DBState state)
51 : {
52 14 : switch (state)
53 : {
7836 bruce 54 1 : case DB_STARTUP:
7524 peter_e 55 1 : return _("starting up");
8062 tgl 56 11 : case DB_SHUTDOWNED:
7524 peter_e 57 11 : return _("shut down");
4693 rhaas 58 2 : case DB_SHUTDOWNED_IN_RECOVERY:
59 2 : return _("shut down in recovery");
8062 tgl 60 UBC 0 : case DB_SHUTDOWNING:
7524 peter_e 61 0 : return _("shutting down");
6089 tgl 62 0 : case DB_IN_CRASH_RECOVERY:
63 0 : return _("in crash recovery");
64 0 : case DB_IN_ARCHIVE_RECOVERY:
65 0 : return _("in archive recovery");
8062 66 0 : case DB_IN_PRODUCTION:
7524 peter_e 67 0 : return _("in production");
68 : }
7536 69 0 : return _("unrecognized status code");
70 : }
71 :
72 : static const char *
4729 heikki.linnakangas 73 CBC 14 : wal_level_str(WalLevel wal_level)
74 : {
75 14 : switch (wal_level)
76 : {
77 4 : case WAL_LEVEL_MINIMAL:
78 4 : return "minimal";
2596 peter_e 79 10 : case WAL_LEVEL_REPLICA:
80 10 : return "replica";
3407 rhaas 81 UBC 0 : case WAL_LEVEL_LOGICAL:
82 0 : return "logical";
83 : }
4729 heikki.linnakangas 84 0 : return _("unrecognized wal_level");
85 : }
86 :
87 :
88 : int
7885 peter_e 89 CBC 23 : 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;
3089 heikki.linnakangas 98 23 : char *DataDir = NULL;
99 : time_t time_tmp;
100 : char pgctime_str[128];
101 : char ckpttime_str[128];
102 : char mock_auth_nonce_str[MOCK_AUTH_NONCE_LEN * 2 + 1];
5866 neilc 103 23 : const char *strftime_fmt = "%c";
104 : const char *progname;
105 : char xlogfilename[MAXFNAMELEN];
106 : int c;
107 : int i;
108 : int WalSegSz;
109 :
1469 peter 110 23 : pg_logging_init(argv[0]);
5232 peter_e 111 23 : set_pglocale_pgservice(argv[0], PG_TEXTDOMAIN("pg_controldata"));
7310 bruce 112 23 : progname = get_progname(argv[0]);
113 :
7536 peter_e 114 23 : if (argc > 1)
115 : {
116 22 : if (strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-?") == 0)
117 : {
118 1 : usage(progname);
119 1 : exit(0);
120 : }
121 21 : if (strcmp(argv[1], "--version") == 0 || strcmp(argv[1], "-V") == 0)
122 : {
123 5 : puts("pg_controldata (PostgreSQL) " PG_VERSION);
124 5 : exit(0);
125 : }
126 : }
127 :
1842 128 17 : while ((c = getopt_long(argc, argv, "D:", long_options, NULL)) != -1)
129 : {
3089 heikki.linnakangas 130 1 : switch (c)
131 : {
3089 heikki.linnakangas 132 UBC 0 : case 'D':
133 0 : DataDir = optarg;
134 0 : break;
135 :
3089 heikki.linnakangas 136 CBC 1 : default:
137 : /* getopt_long already emitted a complaint */
366 tgl 138 1 : pg_log_error_hint("Try \"%s --help\" for more information.", progname);
3089 heikki.linnakangas 139 1 : exit(1);
140 : }
141 : }
142 :
143 16 : if (DataDir == NULL)
144 : {
145 16 : if (optind < argc)
146 15 : DataDir = argv[optind++];
147 : else
148 1 : DataDir = getenv("PGDATA");
149 : }
150 :
151 : /* Complain if any arguments remain */
152 16 : if (optind < argc)
153 : {
1469 peter 154 UBC 0 : pg_log_error("too many command-line arguments (first is \"%s\")",
155 : argv[optind]);
366 tgl 156 0 : pg_log_error_hint("Try \"%s --help\" for more information.", progname);
3089 heikki.linnakangas 157 0 : exit(1);
158 : }
159 :
8053 bruce 160 CBC 16 : if (DataDir == NULL)
161 : {
1469 peter 162 1 : pg_log_error("no data directory specified");
366 tgl 163 1 : pg_log_error_hint("Try \"%s --help\" for more information.", progname);
8080 bruce 164 1 : exit(1);
165 : }
166 :
167 : /* get a copy of the control file */
1469 peter 168 15 : ControlFile = get_controlfile(DataDir, &crc_ok);
2384 peter_e 169 14 : if (!crc_ok)
2448 170 1 : printf(_("WARNING: Calculated CRC checksum does not match value stored in file.\n"
171 : "Either the file is corrupt, or it has a different layout than this program\n"
172 : "is expecting. The results below are untrustworthy.\n\n"));
173 :
174 : /* set wal segment size */
2028 andres 175 14 : WalSegSz = ControlFile->xlog_seg_size;
176 :
177 14 : if (!IsValidWalSegSize(WalSegSz))
178 : {
1788 peter_e 179 1 : printf(_("WARNING: invalid WAL segment size\n"));
180 1 : printf(ngettext("The WAL segment size stored in the file, %d byte, is not a power of two\n"
181 : "between 1 MB and 1 GB. The file is corrupt and the results below are\n"
182 : "untrustworthy.\n\n",
183 : "The WAL segment size stored in the file, %d bytes, is not a power of two\n"
184 : "between 1 MB and 1 GB. The file is corrupt and the results below are\n"
185 : "untrustworthy.\n\n",
186 : WalSegSz),
187 : WalSegSz);
188 : }
189 :
190 : /*
191 : * This slightly-chintzy coding will work as long as the control file
192 : * timestamps are within the range of time_t; that should be the case in
193 : * all foreseeable circumstances, so we don't bother importing the
194 : * backend's timezone library into pg_controldata.
195 : *
196 : * Use variable for format to suppress overly-anal-retentive gcc warning
197 : * about %c
198 : */
2591 mail 199 14 : time_tmp = (time_t) ControlFile->time;
7539 tgl 200 14 : strftime(pgctime_str, sizeof(pgctime_str), strftime_fmt,
5530 201 14 : localtime(&time_tmp));
2591 mail 202 14 : time_tmp = (time_t) ControlFile->checkPointCopy.time;
7539 tgl 203 14 : strftime(ckpttime_str, sizeof(ckpttime_str), strftime_fmt,
5530 204 14 : localtime(&time_tmp));
205 :
206 : /*
207 : * Calculate name of the WAL file containing the latest checkpoint's REDO
208 : * start point.
209 : *
210 : * A corrupted control file could report a WAL segment size of 0, and to
211 : * guard against division by zero, we need to treat that specially.
212 : */
1845 peter_e 213 14 : if (WalSegSz != 0)
214 : {
215 : XLogSegNo segno;
216 :
217 13 : XLByteToSeg(ControlFile->checkPointCopy.redo, segno, WalSegSz);
218 13 : XLogFileName(xlogfilename, ControlFile->checkPointCopy.ThisTimeLineID,
219 : segno, WalSegSz);
220 : }
221 : else
222 1 : strcpy(xlogfilename, _("???"));
223 :
2224 heikki.linnakangas 224 462 : for (i = 0; i < MOCK_AUTH_NONCE_LEN; i++)
225 448 : snprintf(&mock_auth_nonce_str[i * 2], 3, "%02x",
226 448 : (unsigned char) ControlFile->mock_authentication_nonce[i]);
227 :
6089 tgl 228 14 : printf(_("pg_control version number: %u\n"),
229 : ControlFile->pg_control_version);
230 14 : printf(_("Catalog version number: %u\n"),
231 : ControlFile->catalog_version_no);
1403 peter 232 14 : printf(_("Database system identifier: %llu\n"),
233 : (unsigned long long) ControlFile->system_identifier);
6089 tgl 234 14 : printf(_("Database cluster state: %s\n"),
235 : dbState(ControlFile->state));
236 14 : printf(_("pg_control last modified: %s\n"),
237 : pgctime_str);
7536 peter_e 238 14 : printf(_("Latest checkpoint location: %X/%X\n"),
239 : LSN_FORMAT_ARGS(ControlFile->checkPoint));
240 14 : printf(_("Latest checkpoint's REDO location: %X/%X\n"),
241 : LSN_FORMAT_ARGS(ControlFile->checkPointCopy.redo));
3921 heikki.linnakangas 242 14 : printf(_("Latest checkpoint's REDO WAL file: %s\n"),
243 : xlogfilename);
6089 tgl 244 14 : printf(_("Latest checkpoint's TimeLineID: %u\n"),
245 : ControlFile->checkPointCopy.ThisTimeLineID);
3709 heikki.linnakangas 246 14 : printf(_("Latest checkpoint's PrevTimeLineID: %u\n"),
247 : ControlFile->checkPointCopy.PrevTimeLineID);
4092 simon 248 14 : printf(_("Latest checkpoint's full_page_writes: %s\n"),
249 : ControlFile->checkPointCopy.fullPageWrites ? _("on") : _("off"));
2613 mail 250 14 : printf(_("Latest checkpoint's NextXID: %u:%u\n"),
251 : EpochFromFullTransactionId(ControlFile->checkPointCopy.nextXid),
252 : XidFromFullTransactionId(ControlFile->checkPointCopy.nextXid));
6089 tgl 253 14 : printf(_("Latest checkpoint's NextOID: %u\n"),
254 : ControlFile->checkPointCopy.nextOid);
255 14 : printf(_("Latest checkpoint's NextMultiXactId: %u\n"),
256 : ControlFile->checkPointCopy.nextMulti);
257 14 : printf(_("Latest checkpoint's NextMultiOffset: %u\n"),
258 : ControlFile->checkPointCopy.nextMultiOffset);
4969 259 14 : printf(_("Latest checkpoint's oldestXID: %u\n"),
260 : ControlFile->checkPointCopy.oldestXid);
261 14 : printf(_("Latest checkpoint's oldestXID's DB: %u\n"),
262 : ControlFile->checkPointCopy.oldestXidDB);
4843 heikki.linnakangas 263 14 : printf(_("Latest checkpoint's oldestActiveXID: %u\n"),
264 : ControlFile->checkPointCopy.oldestActiveXid);
3727 alvherre 265 14 : printf(_("Latest checkpoint's oldestMultiXid: %u\n"),
266 : ControlFile->checkPointCopy.oldestMulti);
3728 267 14 : printf(_("Latest checkpoint's oldestMulti's DB: %u\n"),
268 : ControlFile->checkPointCopy.oldestMultiDB);
2659 mail 269 14 : printf(_("Latest checkpoint's oldestCommitTsXid:%u\n"),
270 : ControlFile->checkPointCopy.oldestCommitTsXid);
271 14 : printf(_("Latest checkpoint's newestCommitTsXid:%u\n"),
272 : ControlFile->checkPointCopy.newestCommitTsXid);
6089 tgl 273 14 : printf(_("Time of latest checkpoint: %s\n"),
274 : ckpttime_str);
3709 heikki.linnakangas 275 14 : printf(_("Fake LSN counter for unlogged rels: %X/%X\n"),
276 : LSN_FORMAT_ARGS(ControlFile->unloggedLSN));
3676 peter_e 277 14 : printf(_("Minimum recovery ending location: %X/%X\n"),
278 : LSN_FORMAT_ARGS(ControlFile->minRecoveryPoint));
3778 heikki.linnakangas 279 14 : printf(_("Min recovery ending loc's timeline: %u\n"),
280 : ControlFile->minRecoveryPointTLI);
4843 281 14 : printf(_("Backup start location: %X/%X\n"),
282 : LSN_FORMAT_ARGS(ControlFile->backupStartPoint));
4092 simon 283 14 : printf(_("Backup end location: %X/%X\n"),
284 : LSN_FORMAT_ARGS(ControlFile->backupEndPoint));
4253 heikki.linnakangas 285 14 : printf(_("End-of-backup record required: %s\n"),
286 : ControlFile->backupEndRequired ? _("yes") : _("no"));
2784 mail 287 14 : printf(_("wal_level setting: %s\n"),
288 : wal_level_str(ControlFile->wal_level));
289 14 : printf(_("wal_log_hints setting: %s\n"),
290 : ControlFile->wal_log_hints ? _("on") : _("off"));
291 14 : printf(_("max_connections setting: %d\n"),
292 : ControlFile->MaxConnections);
293 14 : printf(_("max_worker_processes setting: %d\n"),
294 : ControlFile->max_worker_processes);
1517 michael 295 14 : printf(_("max_wal_senders setting: %d\n"),
296 : ControlFile->max_wal_senders);
2784 mail 297 14 : printf(_("max_prepared_xacts setting: %d\n"),
298 : ControlFile->max_prepared_xacts);
299 14 : printf(_("max_locks_per_xact setting: %d\n"),
300 : ControlFile->max_locks_per_xact);
301 14 : printf(_("track_commit_timestamp setting: %s\n"),
302 : ControlFile->track_commit_timestamp ? _("on") : _("off"));
6089 tgl 303 14 : printf(_("Maximum data alignment: %u\n"),
304 : ControlFile->maxAlign);
305 : /* we don't print floatFormat since can't say much useful about it */
306 14 : printf(_("Database block size: %u\n"),
307 : ControlFile->blcksz);
308 14 : printf(_("Blocks per segment of large relation: %u\n"),
309 : ControlFile->relseg_size);
310 14 : printf(_("WAL block size: %u\n"),
311 : ControlFile->xlog_blcksz);
312 14 : printf(_("Bytes per WAL segment: %u\n"),
313 : ControlFile->xlog_seg_size);
314 14 : printf(_("Maximum length of identifiers: %u\n"),
315 : ControlFile->nameDataLen);
316 14 : printf(_("Maximum columns in an index: %u\n"),
317 : ControlFile->indexMaxKeys);
5850 318 14 : printf(_("Maximum size of a TOAST chunk: %u\n"),
319 : ControlFile->toast_max_chunk_size);
3230 320 14 : printf(_("Size of a large-object chunk: %u\n"),
321 : ControlFile->loblksize);
322 : /* This is no longer configurable, but users may still expect to see it: */
7536 peter_e 323 14 : printf(_("Date/time type storage: %s\n"),
324 : _("64-bit integers"));
5466 tgl 325 14 : printf(_("Float8 argument passing: %s\n"),
326 : (ControlFile->float8ByVal ? _("by value") : _("by reference")));
3631 simon 327 14 : printf(_("Data page checksum version: %u\n"),
328 : ControlFile->data_checksum_version);
2224 heikki.linnakangas 329 14 : printf(_("Mock authentication nonce: %s\n"),
330 : mock_auth_nonce_str);
7536 peter_e 331 14 : return 0;
332 : }
|