pg_controldata.c 8.6 KB
Newer Older
T
Tom Lane 已提交
1 2
/*
 * pg_controldata
3 4 5 6 7 8
 *
 * reads the data from $PGDATA/global/pg_control
 *
 * copyright (c) Oliver Elphick <olly@lfix.co.uk>, 2001;
 * licence: BSD
 *
9
 * $PostgreSQL: pgsql/src/bin/pg_controldata/pg_controldata.c,v 1.50 2010/06/03 03:20:00 rhaas Exp $
T
Tom Lane 已提交
10
 */
11 12 13 14 15 16 17 18

/*
 * We have to use postgres.h not postgres_fe.h here, because there's so much
 * backend-only stuff in the XLOG include files we need.  But we need a
 * frontend-ish environment otherwise.	Hence this ugly hack.
 */
#define FRONTEND 1

19
#include "postgres.h"
20 21 22 23 24 25

#include <unistd.h>
#include <time.h>
#include <sys/stat.h>
#include <fcntl.h>

26
#include "access/xlog.h"
T
Tom Lane 已提交
27
#include "catalog/pg_control.h"
28

29 30 31 32

static void
usage(const char *progname)
{
33
	printf(_("%s displays control information of a PostgreSQL database cluster.\n\n"), progname);
34
	printf
B
Bruce Momjian 已提交
35 36 37
		(
		 _(
		   "Usage:\n"
38
		   "  %s [OPTION] [DATADIR]\n\n"
B
Bruce Momjian 已提交
39 40 41 42 43 44
		   "Options:\n"
		   "  --help         show this help, then exit\n"
		   "  --version      output version information, then exit\n"
		   ),
		 progname
		);
45 46
	printf(_("\nIf no data directory (DATADIR) is specified, "
			 "the environment variable PGDATA\nis used.\n\n"));
47 48 49
	printf(_("Report bugs to <pgsql-bugs@postgresql.org>.\n"));
}

50

T
Tom Lane 已提交
51 52
static const char *
dbState(DBState state)
53
{
T
Tom Lane 已提交
54 55
	switch (state)
	{
56
		case DB_STARTUP:
57
			return _("starting up");
T
Tom Lane 已提交
58
		case DB_SHUTDOWNED:
59
			return _("shut down");
60 61
		case DB_SHUTDOWNED_IN_RECOVERY:
			return _("shut down in recovery");
T
Tom Lane 已提交
62
		case DB_SHUTDOWNING:
63
			return _("shutting down");
64 65 66 67
		case DB_IN_CRASH_RECOVERY:
			return _("in crash recovery");
		case DB_IN_ARCHIVE_RECOVERY:
			return _("in archive recovery");
T
Tom Lane 已提交
68
		case DB_IN_PRODUCTION:
69
			return _("in production");
T
Tom Lane 已提交
70
	}
71
	return _("unrecognized status code");
T
Tom Lane 已提交
72
}
73

74 75 76 77 78 79 80 81 82 83 84 85 86 87 88
static const char *
wal_level_str(WalLevel wal_level)
{
	switch (wal_level)
	{
		case WAL_LEVEL_MINIMAL:
			return "minimal";
		case WAL_LEVEL_ARCHIVE:
			return "archive";
		case WAL_LEVEL_HOT_STANDBY:
			return "hot_standby";
	}
	return _("unrecognized wal_level");
}

89

T
Tom Lane 已提交
90
int
91
main(int argc, char *argv[])
92 93
{
	ControlFileData ControlFile;
B
Bruce Momjian 已提交
94 95 96
	int			fd;
	char		ControlFilePath[MAXPGPATH];
	char	   *DataDir;
97
	pg_crc32	crc;
98
	time_t		time_tmp;
99 100
	char		pgctime_str[128];
	char		ckpttime_str[128];
101
	char		sysident_str[32];
102
	const char *strftime_fmt = "%c";
103
	const char *progname;
104

105
	set_pglocale_pgservice(argv[0], PG_TEXTDOMAIN("pg_controldata"));
106

107
	progname = get_progname(argv[0]);
108 109 110 111 112 113 114 115 116 117 118 119 120 121

	if (argc > 1)
	{
		if (strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-?") == 0)
		{
			usage(progname);
			exit(0);
		}
		if (strcmp(argv[1], "--version") == 0 || strcmp(argv[1], "-V") == 0)
		{
			puts("pg_controldata (PostgreSQL) " PG_VERSION);
			exit(0);
		}
	}
122

123 124 125 126
	if (argc > 1)
		DataDir = argv[1];
	else
		DataDir = getenv("PGDATA");
B
Bruce Momjian 已提交
127 128
	if (DataDir == NULL)
	{
129
		fprintf(stderr, _("%s: no data directory specified\n"), progname);
130
		fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
131 132 133 134 135
		exit(1);
	}

	snprintf(ControlFilePath, MAXPGPATH, "%s/global/pg_control", DataDir);

136
	if ((fd = open(ControlFilePath, O_RDONLY | PG_BINARY, 0)) == -1)
T
Tom Lane 已提交
137
	{
138
		fprintf(stderr, _("%s: could not open file \"%s\" for reading: %s\n"),
139
				progname, ControlFilePath, strerror(errno));
140 141 142
		exit(2);
	}

T
Tom Lane 已提交
143 144
	if (read(fd, &ControlFile, sizeof(ControlFileData)) != sizeof(ControlFileData))
	{
145
		fprintf(stderr, _("%s: could not read file \"%s\": %s\n"),
146
				progname, ControlFilePath, strerror(errno));
T
Tom Lane 已提交
147 148 149 150 151
		exit(2);
	}
	close(fd);

	/* Check the CRC. */
152 153 154 155 156
	INIT_CRC32(crc);
	COMP_CRC32(crc,
			   (char *) &ControlFile,
			   offsetof(ControlFileData, crc));
	FIN_CRC32(crc);
T
Tom Lane 已提交
157

158
	if (!EQ_CRC32(crc, ControlFile.crc))
159 160
		printf(_("WARNING: Calculated CRC checksum does not match value stored in file.\n"
				 "Either the file is corrupt, or it has a different layout than this program\n"
B
Bruce Momjian 已提交
161
				 "is expecting.  The results below are untrustworthy.\n\n"));
T
Tom Lane 已提交
162

163
	/*
164
	 * This slightly-chintzy coding will work as long as the control file
165 166
	 * timestamps are within the range of time_t; that should be the case in
	 * all foreseeable circumstances, so we don't bother importing the
167 168
	 * backend's timezone library into pg_controldata.
	 *
B
Bruce Momjian 已提交
169 170
	 * Use variable for format to suppress overly-anal-retentive gcc warning
	 * about %c
171
	 */
172
	time_tmp = (time_t) ControlFile.time;
173
	strftime(pgctime_str, sizeof(pgctime_str), strftime_fmt,
174 175
			 localtime(&time_tmp));
	time_tmp = (time_t) ControlFile.checkPointCopy.time;
176
	strftime(ckpttime_str, sizeof(ckpttime_str), strftime_fmt,
177
			 localtime(&time_tmp));
B
Bruce Momjian 已提交
178

179
	/*
B
Bruce Momjian 已提交
180 181
	 * Format system_identifier separately to keep platform-dependent format
	 * code out of the translatable message string.
182 183 184
	 */
	snprintf(sysident_str, sizeof(sysident_str), UINT64_FORMAT,
			 ControlFile.system_identifier);
T
Tom Lane 已提交
185

186 187
	printf(_("pg_control version number:            %u\n"),
		   ControlFile.pg_control_version);
188 189 190 191 192
	if (ControlFile.pg_control_version % 65536 == 0 && ControlFile.pg_control_version / 65536 != 0)
		printf(_("WARNING: possible byte ordering mismatch\n"
				 "The byte ordering used to store the pg_control file might not match the one\n"
				 "used by this program.  In that case the results below would be incorrect, and\n"
				 "the PostgreSQL installation would be incompatible with this data directory.\n"));
193 194 195 196 197 198 199 200
	printf(_("Catalog version number:               %u\n"),
		   ControlFile.catalog_version_no);
	printf(_("Database system identifier:           %s\n"),
		   sysident_str);
	printf(_("Database cluster state:               %s\n"),
		   dbState(ControlFile.state));
	printf(_("pg_control last modified:             %s\n"),
		   pgctime_str);
201
	printf(_("Latest checkpoint location:           %X/%X\n"),
202 203
		   ControlFile.checkPoint.xlogid,
		   ControlFile.checkPoint.xrecoff);
204
	printf(_("Prior checkpoint location:            %X/%X\n"),
205 206
		   ControlFile.prevCheckPoint.xlogid,
		   ControlFile.prevCheckPoint.xrecoff);
207
	printf(_("Latest checkpoint's REDO location:    %X/%X\n"),
208 209 210 211
		   ControlFile.checkPointCopy.redo.xlogid,
		   ControlFile.checkPointCopy.redo.xrecoff);
	printf(_("Latest checkpoint's TimeLineID:       %u\n"),
		   ControlFile.checkPointCopy.ThisTimeLineID);
212 213
	printf(_("Latest checkpoint's NextXID:          %u/%u\n"),
		   ControlFile.checkPointCopy.nextXidEpoch,
214 215 216 217 218 219 220
		   ControlFile.checkPointCopy.nextXid);
	printf(_("Latest checkpoint's NextOID:          %u\n"),
		   ControlFile.checkPointCopy.nextOid);
	printf(_("Latest checkpoint's NextMultiXactId:  %u\n"),
		   ControlFile.checkPointCopy.nextMulti);
	printf(_("Latest checkpoint's NextMultiOffset:  %u\n"),
		   ControlFile.checkPointCopy.nextMultiOffset);
221 222 223 224
	printf(_("Latest checkpoint's oldestXID:        %u\n"),
		   ControlFile.checkPointCopy.oldestXid);
	printf(_("Latest checkpoint's oldestXID's DB:   %u\n"),
		   ControlFile.checkPointCopy.oldestXidDB);
225
	printf(_("Latest checkpoint's oldestActiveXID:  %u\n"),
226
		   ControlFile.checkPointCopy.oldestActiveXid);
227 228 229 230 231
	printf(_("Time of latest checkpoint:            %s\n"),
		   ckpttime_str);
	printf(_("Minimum recovery ending location:     %X/%X\n"),
		   ControlFile.minRecoveryPoint.xlogid,
		   ControlFile.minRecoveryPoint.xrecoff);
232 233 234
	printf(_("Backup start location:                %X/%X\n"),
		   ControlFile.backupStartPoint.xlogid,
		   ControlFile.backupStartPoint.xrecoff);
235
	printf(_("Current wal_level setting:            %s\n"),
236
		   wal_level_str(ControlFile.wal_level));
237
	printf(_("Current max_connections setting:      %d\n"),
238
		   ControlFile.MaxConnections);
239
	printf(_("Current max_prepared_xacts setting:   %d\n"),
240
		   ControlFile.max_prepared_xacts);
241
	printf(_("Current max_locks_per_xact setting:   %d\n"),
242
		   ControlFile.max_locks_per_xact);
243 244
	printf(_("Maximum data alignment:               %u\n"),
		   ControlFile.maxAlign);
245
	/* we don't print floatFormat since can't say much useful about it */
246 247 248 249 250 251 252 253 254 255 256 257
	printf(_("Database block size:                  %u\n"),
		   ControlFile.blcksz);
	printf(_("Blocks per segment of large relation: %u\n"),
		   ControlFile.relseg_size);
	printf(_("WAL block size:                       %u\n"),
		   ControlFile.xlog_blcksz);
	printf(_("Bytes per WAL segment:                %u\n"),
		   ControlFile.xlog_seg_size);
	printf(_("Maximum length of identifiers:        %u\n"),
		   ControlFile.nameDataLen);
	printf(_("Maximum columns in an index:          %u\n"),
		   ControlFile.indexMaxKeys);
258 259
	printf(_("Maximum size of a TOAST chunk:        %u\n"),
		   ControlFile.toast_max_chunk_size);
260
	printf(_("Date/time type storage:               %s\n"),
261
		   (ControlFile.enableIntTimes ? _("64-bit integers") : _("floating-point numbers")));
262 263 264 265
	printf(_("Float4 argument passing:              %s\n"),
		   (ControlFile.float4ByVal ? _("by value") : _("by reference")));
	printf(_("Float8 argument passing:              %s\n"),
		   (ControlFile.float8ByVal ? _("by value") : _("by reference")));
266
	return 0;
267
}