]> granicus.if.org Git - postgresql/blob - src/bin/pg_controldata/pg_controldata.c
Complain if too many options are passed to pg_controldata or pg_resetxlog.
[postgresql] / src / bin / pg_controldata / pg_controldata.c
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 <unistd.h>
22 #include <time.h>
23 #include <sys/stat.h>
24 #include <fcntl.h>
25
26 #include "access/xlog.h"
27 #include "access/xlog_internal.h"
28 #include "catalog/pg_control.h"
29
30
31 static void
32 usage(const char *progname)
33 {
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"));
43 }
44
45
46 static const char *
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 *
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_ARCHIVE:
77                         return "archive";
78                 case WAL_LEVEL_HOT_STANDBY:
79                         return "hot_standby";
80                 case WAL_LEVEL_LOGICAL:
81                         return "logical";
82         }
83         return _("unrecognized wal_level");
84 }
85
86
87 int
88 main(int argc, char *argv[])
89 {
90         ControlFileData ControlFile;
91         int                     fd;
92         char            ControlFilePath[MAXPGPATH];
93         char       *DataDir = NULL;
94         pg_crc32        crc;
95         time_t          time_tmp;
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;
101         XLogSegNo       segno;
102         char            xlogfilename[MAXFNAMELEN];
103         int                     c;
104
105         set_pglocale_pgservice(argv[0], PG_TEXTDOMAIN("pg_controldata"));
106
107         progname = get_progname(argv[0]);
108
109         if (argc > 1)
110         {
111                 if (strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-?") == 0)
112                 {
113                         usage(progname);
114                         exit(0);
115                 }
116                 if (strcmp(argv[1], "--version") == 0 || strcmp(argv[1], "-V") == 0)
117                 {
118                         puts("pg_controldata (PostgreSQL) " PG_VERSION);
119                         exit(0);
120                 }
121         }
122
123         while ((c = getopt(argc, argv, "D:")) != -1)
124         {
125                 switch (c)
126                 {
127                         case 'D':
128                                 DataDir = optarg;
129                                 break;
130
131                         default:
132                                 fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
133                                 exit(1);
134                 }
135         }
136
137         if (DataDir == NULL)
138         {
139                 if (optind < argc)
140                         DataDir = argv[optind++];
141                 else
142                         DataDir = getenv("PGDATA");
143         }
144
145         /* Complain if any arguments remain */
146         if (optind < argc)
147         {
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"),
151                                 progname);
152                 exit(1);
153         }
154
155         if (DataDir == NULL)
156         {
157                 fprintf(stderr, _("%s: no data directory specified\n"), progname);
158                 fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
159                 exit(1);
160         }
161
162         snprintf(ControlFilePath, MAXPGPATH, "%s/global/pg_control", DataDir);
163
164         if ((fd = open(ControlFilePath, O_RDONLY | PG_BINARY, 0)) == -1)
165         {
166                 fprintf(stderr, _("%s: could not open file \"%s\" for reading: %s\n"),
167                                 progname, ControlFilePath, strerror(errno));
168                 exit(2);
169         }
170
171         if (read(fd, &ControlFile, sizeof(ControlFileData)) != sizeof(ControlFileData))
172         {
173                 fprintf(stderr, _("%s: could not read file \"%s\": %s\n"),
174                                 progname, ControlFilePath, strerror(errno));
175                 exit(2);
176         }
177         close(fd);
178
179         /* Check the CRC. */
180         INIT_CRC32(crc);
181         COMP_CRC32(crc,
182                            (char *) &ControlFile,
183                            offsetof(ControlFileData, crc));
184         FIN_CRC32(crc);
185
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"));
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         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));
206
207         /*
208          * Calculate name of the WAL file containing the latest checkpoint's REDO
209          * start point.
210          */
211         XLByteToSeg(ControlFile.checkPointCopy.redo, segno);
212         XLogFileName(xlogfilename, ControlFile.checkPointCopy.ThisTimeLineID, segno);
213
214         /*
215          * Format system_identifier separately to keep platform-dependent format
216          * code out of the translatable message string.
217          */
218         snprintf(sysident_str, sizeof(sysident_str), UINT64_FORMAT,
219                          ControlFile.system_identifier);
220
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"),
231                    sysident_str);
232         printf(_("Database cluster state:               %s\n"),
233                    dbState(ControlFile.state));
234         printf(_("pg_control last modified:             %s\n"),
235                    pgctime_str);
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"),
246                    xlogfilename);
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"),
273                    ckpttime_str);
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"),
306                    ControlFile.blcksz);
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);
329         return 0;
330 }