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/xlog.h"
24 #include "access/xlog_internal.h"
25 #include "catalog/pg_control.h"
26 #include "common/controldata_utils.h"
27 #include "pg_getopt.h"
28
29
30 static void
usage(const char * progname)31 usage(const char *progname)
32 {
33 printf(_("%s displays control information of a PostgreSQL database cluster.\n\n"), progname);
34 printf(_("Usage:\n"));
35 printf(_(" %s [OPTION] [DATADIR]\n"), progname);
36 printf(_("\nOptions:\n"));
37 printf(_(" [-D] DATADIR data directory\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"));
43 }
44
45
46 static const char *
dbState(DBState state)47 dbState(DBState state)
48 {
49 switch (state)
50 {
51 case DB_STARTUP:
52 return _("starting up");
53 case DB_SHUTDOWNED:
54 return _("shut down");
55 case DB_SHUTDOWNED_IN_RECOVERY:
56 return _("shut down in recovery");
57 case DB_SHUTDOWNING:
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");
65 }
66 return _("unrecognized status code");
67 }
68
69 static const char *
wal_level_str(WalLevel wal_level)70 wal_level_str(WalLevel wal_level)
71 {
72 switch (wal_level)
73 {
74 case WAL_LEVEL_MINIMAL:
75 return "minimal";
76 case WAL_LEVEL_REPLICA:
77 return "replica";
78 case WAL_LEVEL_LOGICAL:
79 return "logical";
80 }
81 return _("unrecognized wal_level");
82 }
83
84
85 int
main(int argc,char * argv[])86 main(int argc, char *argv[])
87 {
88 ControlFileData *ControlFile;
89 char *DataDir = NULL;
90 time_t time_tmp;
91 char pgctime_str[128];
92 char ckpttime_str[128];
93 char sysident_str[32];
94 const char *strftime_fmt = "%c";
95 const char *progname;
96 XLogSegNo segno;
97 char xlogfilename[MAXFNAMELEN];
98 int c;
99
100 set_pglocale_pgservice(argv[0], PG_TEXTDOMAIN("pg_controldata"));
101
102 progname = get_progname(argv[0]);
103
104 if (argc > 1)
105 {
106 if (strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-?") == 0)
107 {
108 usage(progname);
109 exit(0);
110 }
111 if (strcmp(argv[1], "--version") == 0 || strcmp(argv[1], "-V") == 0)
112 {
113 puts("pg_controldata (PostgreSQL) " PG_VERSION);
114 exit(0);
115 }
116 }
117
118 while ((c = getopt(argc, argv, "D:")) != -1)
119 {
120 switch (c)
121 {
122 case 'D':
123 DataDir = optarg;
124 break;
125
126 default:
127 fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
128 exit(1);
129 }
130 }
131
132 if (DataDir == NULL)
133 {
134 if (optind < argc)
135 DataDir = argv[optind++];
136 else
137 DataDir = getenv("PGDATA");
138 }
139
140 /* Complain if any arguments remain */
141 if (optind < argc)
142 {
143 fprintf(stderr, _("%s: too many command-line arguments (first is \"%s\")\n"),
144 progname, argv[optind]);
145 fprintf(stderr, _("Try \"%s --help\" for more information.\n"),
146 progname);
147 exit(1);
148 }
149
150 if (DataDir == NULL)
151 {
152 fprintf(stderr, _("%s: no data directory specified\n"), progname);
153 fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
154 exit(1);
155 }
156
157 /* get a copy of the control file */
158 ControlFile = get_controlfile(DataDir, progname);
159
160 /*
161 * This slightly-chintzy coding will work as long as the control file
162 * timestamps are within the range of time_t; that should be the case in
163 * all foreseeable circumstances, so we don't bother importing the
164 * backend's timezone library into pg_controldata.
165 *
166 * Use variable for format to suppress overly-anal-retentive gcc warning
167 * about %c
168 */
169 time_tmp = (time_t) ControlFile->time;
170 strftime(pgctime_str, sizeof(pgctime_str), strftime_fmt,
171 localtime(&time_tmp));
172 time_tmp = (time_t) ControlFile->checkPointCopy.time;
173 strftime(ckpttime_str, sizeof(ckpttime_str), strftime_fmt,
174 localtime(&time_tmp));
175
176 /*
177 * Calculate name of the WAL file containing the latest checkpoint's REDO
178 * start point.
179 */
180 XLByteToSeg(ControlFile->checkPointCopy.redo, segno);
181 XLogFileName(xlogfilename, ControlFile->checkPointCopy.ThisTimeLineID, segno);
182
183 /*
184 * Format system_identifier separately to keep platform-dependent format
185 * code out of the translatable message string.
186 */
187 snprintf(sysident_str, sizeof(sysident_str), UINT64_FORMAT,
188 ControlFile->system_identifier);
189
190 printf(_("pg_control version number: %u\n"),
191 ControlFile->pg_control_version);
192 printf(_("Catalog version number: %u\n"),
193 ControlFile->catalog_version_no);
194 printf(_("Database system identifier: %s\n"),
195 sysident_str);
196 printf(_("Database cluster state: %s\n"),
197 dbState(ControlFile->state));
198 printf(_("pg_control last modified: %s\n"),
199 pgctime_str);
200 printf(_("Latest checkpoint location: %X/%X\n"),
201 (uint32) (ControlFile->checkPoint >> 32),
202 (uint32) ControlFile->checkPoint);
203 printf(_("Prior checkpoint location: %X/%X\n"),
204 (uint32) (ControlFile->prevCheckPoint >> 32),
205 (uint32) ControlFile->prevCheckPoint);
206 printf(_("Latest checkpoint's REDO location: %X/%X\n"),
207 (uint32) (ControlFile->checkPointCopy.redo >> 32),
208 (uint32) ControlFile->checkPointCopy.redo);
209 printf(_("Latest checkpoint's REDO WAL file: %s\n"),
210 xlogfilename);
211 printf(_("Latest checkpoint's TimeLineID: %u\n"),
212 ControlFile->checkPointCopy.ThisTimeLineID);
213 printf(_("Latest checkpoint's PrevTimeLineID: %u\n"),
214 ControlFile->checkPointCopy.PrevTimeLineID);
215 printf(_("Latest checkpoint's full_page_writes: %s\n"),
216 ControlFile->checkPointCopy.fullPageWrites ? _("on") : _("off"));
217 printf(_("Latest checkpoint's NextXID: %u:%u\n"),
218 ControlFile->checkPointCopy.nextXidEpoch,
219 ControlFile->checkPointCopy.nextXid);
220 printf(_("Latest checkpoint's NextOID: %u\n"),
221 ControlFile->checkPointCopy.nextOid);
222 printf(_("Latest checkpoint's NextMultiXactId: %u\n"),
223 ControlFile->checkPointCopy.nextMulti);
224 printf(_("Latest checkpoint's NextMultiOffset: %u\n"),
225 ControlFile->checkPointCopy.nextMultiOffset);
226 printf(_("Latest checkpoint's oldestXID: %u\n"),
227 ControlFile->checkPointCopy.oldestXid);
228 printf(_("Latest checkpoint's oldestXID's DB: %u\n"),
229 ControlFile->checkPointCopy.oldestXidDB);
230 printf(_("Latest checkpoint's oldestActiveXID: %u\n"),
231 ControlFile->checkPointCopy.oldestActiveXid);
232 printf(_("Latest checkpoint's oldestMultiXid: %u\n"),
233 ControlFile->checkPointCopy.oldestMulti);
234 printf(_("Latest checkpoint's oldestMulti's DB: %u\n"),
235 ControlFile->checkPointCopy.oldestMultiDB);
236 printf(_("Latest checkpoint's oldestCommitTsXid:%u\n"),
237 ControlFile->checkPointCopy.oldestCommitTsXid);
238 printf(_("Latest checkpoint's newestCommitTsXid:%u\n"),
239 ControlFile->checkPointCopy.newestCommitTsXid);
240 printf(_("Time of latest checkpoint: %s\n"),
241 ckpttime_str);
242 printf(_("Fake LSN counter for unlogged rels: %X/%X\n"),
243 (uint32) (ControlFile->unloggedLSN >> 32),
244 (uint32) ControlFile->unloggedLSN);
245 printf(_("Minimum recovery ending location: %X/%X\n"),
246 (uint32) (ControlFile->minRecoveryPoint >> 32),
247 (uint32) ControlFile->minRecoveryPoint);
248 printf(_("Min recovery ending loc's timeline: %u\n"),
249 ControlFile->minRecoveryPointTLI);
250 printf(_("Backup start location: %X/%X\n"),
251 (uint32) (ControlFile->backupStartPoint >> 32),
252 (uint32) ControlFile->backupStartPoint);
253 printf(_("Backup end location: %X/%X\n"),
254 (uint32) (ControlFile->backupEndPoint >> 32),
255 (uint32) ControlFile->backupEndPoint);
256 printf(_("End-of-backup record required: %s\n"),
257 ControlFile->backupEndRequired ? _("yes") : _("no"));
258 printf(_("wal_level setting: %s\n"),
259 wal_level_str(ControlFile->wal_level));
260 printf(_("wal_log_hints setting: %s\n"),
261 ControlFile->wal_log_hints ? _("on") : _("off"));
262 printf(_("max_connections setting: %d\n"),
263 ControlFile->MaxConnections);
264 printf(_("max_worker_processes setting: %d\n"),
265 ControlFile->max_worker_processes);
266 printf(_("max_prepared_xacts setting: %d\n"),
267 ControlFile->max_prepared_xacts);
268 printf(_("max_locks_per_xact setting: %d\n"),
269 ControlFile->max_locks_per_xact);
270 printf(_("track_commit_timestamp setting: %s\n"),
271 ControlFile->track_commit_timestamp ? _("on") : _("off"));
272 printf(_("Maximum data alignment: %u\n"),
273 ControlFile->maxAlign);
274 /* we don't print floatFormat since can't say much useful about it */
275 printf(_("Database block size: %u\n"),
276 ControlFile->blcksz);
277 printf(_("Blocks per segment of large relation: %u\n"),
278 ControlFile->relseg_size);
279 printf(_("WAL block size: %u\n"),
280 ControlFile->xlog_blcksz);
281 printf(_("Bytes per WAL segment: %u\n"),
282 ControlFile->xlog_seg_size);
283 printf(_("Maximum length of identifiers: %u\n"),
284 ControlFile->nameDataLen);
285 printf(_("Maximum columns in an index: %u\n"),
286 ControlFile->indexMaxKeys);
287 printf(_("Maximum size of a TOAST chunk: %u\n"),
288 ControlFile->toast_max_chunk_size);
289 printf(_("Size of a large-object chunk: %u\n"),
290 ControlFile->loblksize);
291 printf(_("Date/time type storage: %s\n"),
292 (ControlFile->enableIntTimes ? _("64-bit integers") : _("floating-point numbers")));
293 printf(_("Float4 argument passing: %s\n"),
294 (ControlFile->float4ByVal ? _("by value") : _("by reference")));
295 printf(_("Float8 argument passing: %s\n"),
296 (ControlFile->float8ByVal ? _("by value") : _("by reference")));
297 printf(_("Data page checksum version: %u\n"),
298 ControlFile->data_checksum_version);
299 return 0;
300 }
301