pg_controldata.c 6 KB
Newer Older
Tom Lane's avatar
Tom Lane committed
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.15 2004/05/12 13:38:43 momjian Exp $
Tom Lane's avatar
Tom Lane committed
10 11
 */
#include "postgres.h"
12 13 14 15 16

#include <unistd.h>
#include <time.h>
#include <sys/stat.h>
#include <fcntl.h>
17 18
#include <locale.h>
#include <errno.h>
19

Tom Lane's avatar
Tom Lane committed
20
#include "catalog/pg_control.h"
21

22 23 24 25 26 27
#define _(x) gettext((x))


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

45

Tom Lane's avatar
Tom Lane committed
46 47
static const char *
dbState(DBState state)
48
{
Tom Lane's avatar
Tom Lane committed
49 50
	switch (state)
	{
51
		case DB_STARTUP:
52
			return _("starting up");
Tom Lane's avatar
Tom Lane committed
53
		case DB_SHUTDOWNED:
54
			return _("shut down");
Tom Lane's avatar
Tom Lane committed
55
		case DB_SHUTDOWNING:
56
			return _("shutting down");
Tom Lane's avatar
Tom Lane committed
57
		case DB_IN_RECOVERY:
58
			return _("in recovery");
Tom Lane's avatar
Tom Lane committed
59
		case DB_IN_PRODUCTION:
60
			return _("in production");
Tom Lane's avatar
Tom Lane committed
61
	}
62
	return _("unrecognized status code");
Tom Lane's avatar
Tom Lane committed
63
}
64 65


Tom Lane's avatar
Tom Lane committed
66
int
67
main(int argc, char *argv[])
68 69
{
	ControlFileData ControlFile;
70 71 72 73
	int			fd;
	char		ControlFilePath[MAXPGPATH];
	char	   *DataDir;
	crc64		crc;
74 75
	char		pgctime_str[128];
	char		ckpttime_str[128];
76
	char		sysident_str[32];
77
	char	   *strftime_fmt = "%c";
78
	const char *progname;
79 80 81 82 83 84 85

	setlocale(LC_ALL, "");
#ifdef ENABLE_NLS
	bindtextdomain("pg_controldata", LOCALEDIR);
	textdomain("pg_controldata");
#endif

86
	progname = get_progname(argv[0]);
87 88 89 90 91 92 93 94 95 96 97 98 99 100

	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);
		}
	}
101

102 103 104 105
	if (argc > 1)
		DataDir = argv[1];
	else
		DataDir = getenv("PGDATA");
106 107
	if (DataDir == NULL)
	{
108
		fprintf(stderr, _("%s: no data directory specified\n"), progname);
109
		fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
110 111 112 113 114
		exit(1);
	}

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

Tom Lane's avatar
Tom Lane committed
115 116
	if ((fd = open(ControlFilePath, O_RDONLY)) == -1)
	{
117
		fprintf(stderr, _("%s: could not open file \"%s\" for reading: %s\n"),
118
				progname, ControlFilePath, strerror(errno));
119 120 121
		exit(2);
	}

Tom Lane's avatar
Tom Lane committed
122 123
	if (read(fd, &ControlFile, sizeof(ControlFileData)) != sizeof(ControlFileData))
	{
124
		fprintf(stderr, _("%s: could not read file \"%s\": %s\n"),
125
				progname, ControlFilePath, strerror(errno));
Tom Lane's avatar
Tom Lane committed
126 127 128 129 130 131
		exit(2);
	}
	close(fd);

	/* Check the CRC. */
	INIT_CRC64(crc);
132 133
	COMP_CRC64(crc,
			   (char *) &ControlFile + sizeof(crc64),
Tom Lane's avatar
Tom Lane committed
134 135 136 137
			   sizeof(ControlFileData) - sizeof(crc64));
	FIN_CRC64(crc);

	if (!EQ_CRC64(crc, ControlFile.crc))
138 139
		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"
Bruce Momjian's avatar
Bruce Momjian committed
140
			 "is expecting.  The results below are untrustworthy.\n\n"));
Tom Lane's avatar
Tom Lane committed
141

142
	/*
Bruce Momjian's avatar
Bruce Momjian committed
143 144
	 * Use variable for format to suppress overly-anal-retentive gcc
	 * warning about %c
145 146
	 */
	strftime(pgctime_str, sizeof(pgctime_str), strftime_fmt,
Tom Lane's avatar
Tom Lane committed
147
			 localtime(&(ControlFile.time)));
148
	strftime(ckpttime_str, sizeof(ckpttime_str), strftime_fmt,
Tom Lane's avatar
Tom Lane committed
149
			 localtime(&(ControlFile.checkPointCopy.time)));
150 151 152 153 154 155
	/*
	 * Format system_identifier separately to keep platform-dependent format
	 * code out of the translatable message string.
	 */
	snprintf(sysident_str, sizeof(sysident_str), UINT64_FORMAT,
			 ControlFile.system_identifier);
Tom Lane's avatar
Tom Lane committed
156

157 158
	printf(_("pg_control version number:            %u\n"), ControlFile.pg_control_version);
	printf(_("Catalog version number:               %u\n"), ControlFile.catalog_version_no);
159
	printf(_("Database system identifier:           %s\n"), sysident_str);
160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177
	printf(_("Database cluster state:               %s\n"), dbState(ControlFile.state));
	printf(_("pg_control last modified:             %s\n"), pgctime_str);
	printf(_("Current log file ID:                  %u\n"), ControlFile.logId);
	printf(_("Next log file segment:                %u\n"), ControlFile.logSeg);
	printf(_("Latest checkpoint location:           %X/%X\n"),
		   ControlFile.checkPoint.xlogid, ControlFile.checkPoint.xrecoff);
	printf(_("Prior checkpoint location:            %X/%X\n"),
		   ControlFile.prevCheckPoint.xlogid, ControlFile.prevCheckPoint.xrecoff);
	printf(_("Latest checkpoint's REDO location:    %X/%X\n"),
		   ControlFile.checkPointCopy.redo.xlogid, ControlFile.checkPointCopy.redo.xrecoff);
	printf(_("Latest checkpoint's UNDO location:    %X/%X\n"),
		   ControlFile.checkPointCopy.undo.xlogid, ControlFile.checkPointCopy.undo.xrecoff);
	printf(_("Latest checkpoint's StartUpID:        %u\n"), ControlFile.checkPointCopy.ThisStartUpID);
	printf(_("Latest checkpoint's NextXID:          %u\n"), ControlFile.checkPointCopy.nextXid);
	printf(_("Latest checkpoint's NextOID:          %u\n"), ControlFile.checkPointCopy.nextOid);
	printf(_("Time of latest checkpoint:            %s\n"), ckpttime_str);
	printf(_("Database block size:                  %u\n"), ControlFile.blcksz);
	printf(_("Blocks per segment of large relation: %u\n"), ControlFile.relseg_size);
178
	printf(_("Bytes per WAL segment:                %u\n"), ControlFile.xlog_seg_size);
179 180 181
	printf(_("Maximum length of identifiers:        %u\n"), ControlFile.nameDataLen);
	printf(_("Maximum number of function arguments: %u\n"), ControlFile.funcMaxArgs);
	printf(_("Date/time type storage:               %s\n"),
182
		   (ControlFile.enableIntTimes ? _("64-bit integers") : _("floating-point numbers")));
183 184 185 186 187
	printf(_("Maximum length of locale name:        %u\n"), ControlFile.localeBuflen);
	printf(_("LC_COLLATE:                           %s\n"), ControlFile.lc_collate);
	printf(_("LC_CTYPE:                             %s\n"), ControlFile.lc_ctype);

	return 0;
188
}