4 * reads the data from $PGDATA/global/pg_control
6 * copyright (c) Oliver Elphick <olly@lfix.co.uk>, 2001;
9 * src/bin/pg_controldata/pg_controldata.c
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.
26 #include "access/xlog.h"
27 #include "access/xlog_internal.h"
28 #include "catalog/pg_control.h"
32 usage(const char *progname)
34 printf(_("%s displays control information of a PostgreSQL database cluster.\n\n"), progname);
35 printf(_("Usage:\n"));
36 printf(_(" %s [OPTION] [[-D] DATADIR]\n"), progname);
37 printf(_("\nOptions:\n"));
38 printf(_(" -V, --version output version information, then exit\n"));
39 printf(_(" -?, --help show this help, then exit\n"));
40 printf(_("\nIf no data directory (DATADIR) is specified, "
41 "the environment variable PGDATA\nis used.\n\n"));
42 printf(_("Report bugs to <pgsql-bugs@postgresql.org>.\n"));
47 dbState(DBState state)
52 return _("starting up");
54 return _("shut down");
55 case DB_SHUTDOWNED_IN_RECOVERY:
56 return _("shut down in recovery");
58 return _("shutting down");
59 case DB_IN_CRASH_RECOVERY:
60 return _("in crash recovery");
61 case DB_IN_ARCHIVE_RECOVERY:
62 return _("in archive recovery");
63 case DB_IN_PRODUCTION:
64 return _("in production");
66 return _("unrecognized status code");
70 wal_level_str(WalLevel wal_level)
74 case WAL_LEVEL_MINIMAL:
76 case WAL_LEVEL_ARCHIVE:
78 case WAL_LEVEL_HOT_STANDBY:
80 case WAL_LEVEL_LOGICAL:
83 return _("unrecognized wal_level");
88 main(int argc, char *argv[])
90 ControlFileData ControlFile;
92 char ControlFilePath[MAXPGPATH];
96 char pgctime_str[128];
97 char ckpttime_str[128];
98 char sysident_str[32];
99 const char *strftime_fmt = "%c";
100 const char *progname;
102 char xlogfilename[MAXFNAMELEN];
105 set_pglocale_pgservice(argv[0], PG_TEXTDOMAIN("pg_controldata"));
107 progname = get_progname(argv[0]);
111 if (strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-?") == 0)
116 if (strcmp(argv[1], "--version") == 0 || strcmp(argv[1], "-V") == 0)
118 puts("pg_controldata (PostgreSQL) " PG_VERSION);
123 while ((c = getopt(argc, argv, "D:")) != -1)
132 fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
140 DataDir = argv[optind++];
142 DataDir = getenv("PGDATA");
145 /* Complain if any arguments remain */
148 fprintf(stderr, _("%s: too many command-line arguments (first is \"%s\")\n"),
149 progname, argv[optind]);
150 fprintf(stderr, _("Try \"%s --help\" for more information.\n"),
157 fprintf(stderr, _("%s: no data directory specified\n"), progname);
158 fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
162 snprintf(ControlFilePath, MAXPGPATH, "%s/global/pg_control", DataDir);
164 if ((fd = open(ControlFilePath, O_RDONLY | PG_BINARY, 0)) == -1)
166 fprintf(stderr, _("%s: could not open file \"%s\" for reading: %s\n"),
167 progname, ControlFilePath, strerror(errno));
171 if (read(fd, &ControlFile, sizeof(ControlFileData)) != sizeof(ControlFileData))
173 fprintf(stderr, _("%s: could not read file \"%s\": %s\n"),
174 progname, ControlFilePath, strerror(errno));
182 (char *) &ControlFile,
183 offsetof(ControlFileData, crc));
186 if (!EQ_CRC32(crc, ControlFile.crc))
187 printf(_("WARNING: Calculated CRC checksum does not match value stored in file.\n"
188 "Either the file is corrupt, or it has a different layout than this program\n"
189 "is expecting. The results below are untrustworthy.\n\n"));
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.
197 * Use variable for format to suppress overly-anal-retentive gcc warning
200 time_tmp = (time_t) ControlFile.time;
201 strftime(pgctime_str, sizeof(pgctime_str), strftime_fmt,
202 localtime(&time_tmp));
203 time_tmp = (time_t) ControlFile.checkPointCopy.time;
204 strftime(ckpttime_str, sizeof(ckpttime_str), strftime_fmt,
205 localtime(&time_tmp));
208 * Calculate name of the WAL file containing the latest checkpoint's REDO
211 XLByteToSeg(ControlFile.checkPointCopy.redo, segno);
212 XLogFileName(xlogfilename, ControlFile.checkPointCopy.ThisTimeLineID, segno);
215 * Format system_identifier separately to keep platform-dependent format
216 * code out of the translatable message string.
218 snprintf(sysident_str, sizeof(sysident_str), UINT64_FORMAT,
219 ControlFile.system_identifier);
221 printf(_("pg_control version number: %u\n"),
222 ControlFile.pg_control_version);
223 if (ControlFile.pg_control_version % 65536 == 0 && ControlFile.pg_control_version / 65536 != 0)
224 printf(_("WARNING: possible byte ordering mismatch\n"
225 "The byte ordering used to store the pg_control file might not match the one\n"
226 "used by this program. In that case the results below would be incorrect, and\n"
227 "the PostgreSQL installation would be incompatible with this data directory.\n"));
228 printf(_("Catalog version number: %u\n"),
229 ControlFile.catalog_version_no);
230 printf(_("Database system identifier: %s\n"),
232 printf(_("Database cluster state: %s\n"),
233 dbState(ControlFile.state));
234 printf(_("pg_control last modified: %s\n"),
236 printf(_("Latest checkpoint location: %X/%X\n"),
237 (uint32) (ControlFile.checkPoint >> 32),
238 (uint32) ControlFile.checkPoint);
239 printf(_("Prior checkpoint location: %X/%X\n"),
240 (uint32) (ControlFile.prevCheckPoint >> 32),
241 (uint32) ControlFile.prevCheckPoint);
242 printf(_("Latest checkpoint's REDO location: %X/%X\n"),
243 (uint32) (ControlFile.checkPointCopy.redo >> 32),
244 (uint32) ControlFile.checkPointCopy.redo);
245 printf(_("Latest checkpoint's REDO WAL file: %s\n"),
247 printf(_("Latest checkpoint's TimeLineID: %u\n"),
248 ControlFile.checkPointCopy.ThisTimeLineID);
249 printf(_("Latest checkpoint's PrevTimeLineID: %u\n"),
250 ControlFile.checkPointCopy.PrevTimeLineID);
251 printf(_("Latest checkpoint's full_page_writes: %s\n"),
252 ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off"));
253 printf(_("Latest checkpoint's NextXID: %u/%u\n"),
254 ControlFile.checkPointCopy.nextXidEpoch,
255 ControlFile.checkPointCopy.nextXid);
256 printf(_("Latest checkpoint's NextOID: %u\n"),
257 ControlFile.checkPointCopy.nextOid);
258 printf(_("Latest checkpoint's NextMultiXactId: %u\n"),
259 ControlFile.checkPointCopy.nextMulti);
260 printf(_("Latest checkpoint's NextMultiOffset: %u\n"),
261 ControlFile.checkPointCopy.nextMultiOffset);
262 printf(_("Latest checkpoint's oldestXID: %u\n"),
263 ControlFile.checkPointCopy.oldestXid);
264 printf(_("Latest checkpoint's oldestXID's DB: %u\n"),
265 ControlFile.checkPointCopy.oldestXidDB);
266 printf(_("Latest checkpoint's oldestActiveXID: %u\n"),
267 ControlFile.checkPointCopy.oldestActiveXid);
268 printf(_("Latest checkpoint's oldestMultiXid: %u\n"),
269 ControlFile.checkPointCopy.oldestMulti);
270 printf(_("Latest checkpoint's oldestMulti's DB: %u\n"),
271 ControlFile.checkPointCopy.oldestMultiDB);
272 printf(_("Time of latest checkpoint: %s\n"),
274 printf(_("Fake LSN counter for unlogged rels: %X/%X\n"),
275 (uint32) (ControlFile.unloggedLSN >> 32),
276 (uint32) ControlFile.unloggedLSN);
277 printf(_("Minimum recovery ending location: %X/%X\n"),
278 (uint32) (ControlFile.minRecoveryPoint >> 32),
279 (uint32) ControlFile.minRecoveryPoint);
280 printf(_("Min recovery ending loc's timeline: %u\n"),
281 ControlFile.minRecoveryPointTLI);
282 printf(_("Backup start location: %X/%X\n"),
283 (uint32) (ControlFile.backupStartPoint >> 32),
284 (uint32) ControlFile.backupStartPoint);
285 printf(_("Backup end location: %X/%X\n"),
286 (uint32) (ControlFile.backupEndPoint >> 32),
287 (uint32) ControlFile.backupEndPoint);
288 printf(_("End-of-backup record required: %s\n"),
289 ControlFile.backupEndRequired ? _("yes") : _("no"));
290 printf(_("Current wal_level setting: %s\n"),
291 wal_level_str(ControlFile.wal_level));
292 printf(_("Current wal_log_hints setting: %s\n"),
293 ControlFile.wal_log_hints ? _("on") : _("off"));
294 printf(_("Current max_connections setting: %d\n"),
295 ControlFile.MaxConnections);
296 printf(_("Current max_worker_processes setting: %d\n"),
297 ControlFile.max_worker_processes);
298 printf(_("Current max_prepared_xacts setting: %d\n"),
299 ControlFile.max_prepared_xacts);
300 printf(_("Current max_locks_per_xact setting: %d\n"),
301 ControlFile.max_locks_per_xact);
302 printf(_("Maximum data alignment: %u\n"),
303 ControlFile.maxAlign);
304 /* we don't print floatFormat since can't say much useful about it */
305 printf(_("Database block size: %u\n"),
307 printf(_("Blocks per segment of large relation: %u\n"),
308 ControlFile.relseg_size);
309 printf(_("WAL block size: %u\n"),
310 ControlFile.xlog_blcksz);
311 printf(_("Bytes per WAL segment: %u\n"),
312 ControlFile.xlog_seg_size);
313 printf(_("Maximum length of identifiers: %u\n"),
314 ControlFile.nameDataLen);
315 printf(_("Maximum columns in an index: %u\n"),
316 ControlFile.indexMaxKeys);
317 printf(_("Maximum size of a TOAST chunk: %u\n"),
318 ControlFile.toast_max_chunk_size);
319 printf(_("Size of a large-object chunk: %u\n"),
320 ControlFile.loblksize);
321 printf(_("Date/time type storage: %s\n"),
322 (ControlFile.enableIntTimes ? _("64-bit integers") : _("floating-point numbers")));
323 printf(_("Float4 argument passing: %s\n"),
324 (ControlFile.float4ByVal ? _("by value") : _("by reference")));
325 printf(_("Float8 argument passing: %s\n"),
326 (ControlFile.float8ByVal ? _("by value") : _("by reference")));
327 printf(_("Data page checksum version: %u\n"),
328 ControlFile.data_checksum_version);